summaryrefslogtreecommitdiff
path: root/drivers/i2c/mvtwsi.c
diff options
context:
space:
mode:
authormario.six@gdsys.cc <mario.six@gdsys.cc>2016-07-21 11:57:10 +0200
committerHeiko Schocher <hs@denx.de>2016-07-26 10:20:13 +0200
commit14a6ff2c4f22010e5d67f25508f09e3b53a1f1c4 (patch)
treea7c787ce86307304796e715c2db8d07275bcfa8d /drivers/i2c/mvtwsi.c
parentf8a10ed1fd9986362a39f2b18d89429dfdb078cb (diff)
i2c: mvtwsi: Add compatibility to DM
This patch adds the necessary functions and Kconfig entry to make the MVTWSI I2C driver compatible with the driver model. A possible device tree entry might look like this: i2c@11100 { compatible = "marvell,mv64xxx-i2c"; reg = <0x11000 0x20>; clock-frequency = <100000>; u-boot,i2c-slave-addr = <0x0>; }; Signed-off-by: Mario Six <mario.six@gdsys.cc> Reviewed-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'drivers/i2c/mvtwsi.c')
-rw-r--r--drivers/i2c/mvtwsi.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 3325c4bd46..f694527ec6 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -12,12 +12,18 @@
#include <i2c.h>
#include <asm/errno.h>
#include <asm/io.h>
+#ifdef CONFIG_DM_I2C
+#include <dm.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
/*
* Include a file that will provide CONFIG_I2C_MVTWSI_BASE*, and possibly other
* settings
*/
+#ifndef CONFIG_DM_I2C
#if defined(CONFIG_ORION5X)
#include <asm/arch/orion5x.h>
#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU))
@@ -27,6 +33,7 @@
#else
#error Driver mvtwsi not supported by SoC or board
#endif
+#endif /* CONFIG_DM_I2C */
/*
* TWSI register structure
@@ -61,6 +68,19 @@ struct mvtwsi_registers {
#endif
+#ifdef CONFIG_DM_I2C
+struct mvtwsi_i2c_dev {
+ /* TWSI Register base for the device */
+ struct mvtwsi_registers *base;
+ /* Number of the device (determined from cell-index property) */
+ int index;
+ /* The I2C slave address for the device */
+ u8 slaveadd;
+ /* The configured I2C speed in Hz */
+ uint speed;
+};
+#endif /* CONFIG_DM_I2C */
+
/*
* enum mvtwsi_ctrl_register_fields - Bit masks for flags in the control
* register
@@ -134,6 +154,7 @@ enum mvtwsi_ack_flags {
MVTWSI_READ_ACK = 1,
};
+#ifndef CONFIG_DM_I2C
/*
* MVTWSI controller base
*/
@@ -172,6 +193,7 @@ static struct mvtwsi_registers *twsi_get_base(struct i2c_adapter *adap)
return NULL;
}
+#endif
/*
* enum mvtwsi_error_class - types of I2C errors
@@ -358,7 +380,7 @@ static uint __twsi_i2c_set_bus_speed(struct mvtwsi_registers *twsi,
}
static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed,
- int slaveadd)
+ int slaveadd)
{
/* Reset controller */
twsi_reset(twsi);
@@ -472,6 +494,7 @@ static int __twsi_i2c_write(struct mvtwsi_registers *twsi, uchar chip,
return status != 0 ? status : stop_status;
}
+#ifndef CONFIG_DM_I2C
static void twsi_i2c_init(struct i2c_adapter *adap, int speed,
int slaveadd)
{
@@ -561,3 +584,89 @@ U_BOOT_I2C_ADAP_COMPLETE(twsi5, twsi_i2c_init, twsi_i2c_probe,
CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 5)
#endif
+#else /* CONFIG_DM_I2C */
+
+static int mvtwsi_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
+ u32 chip_flags)
+{
+ struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+ return __twsi_i2c_probe_chip(dev->base, chip_addr);
+}
+
+static int mvtwsi_i2c_set_bus_speed(struct udevice *bus, uint speed)
+{
+ struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+ return __twsi_i2c_set_bus_speed(dev->base, speed);
+}
+
+static int mvtwsi_i2c_ofdata_to_platdata(struct udevice *bus)
+{
+ struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+
+ dev->base = dev_get_addr_ptr(bus);
+
+ if (!dev->base)
+ return -ENOMEM;
+
+ dev->index = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+ "cell-index", -1);
+ dev->slaveadd = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+ "u-boot,i2c-slave-addr", 0x0);
+ dev->speed = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+ "clock-frequency", 100000);
+ return 0;
+}
+
+static int mvtwsi_i2c_probe(struct udevice *bus)
+{
+ struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+ __twsi_i2c_init(dev->base, dev->speed, dev->slaveadd);
+ return 0;
+}
+
+static int mvtwsi_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+ struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
+ struct i2c_msg *dmsg, *omsg, dummy;
+
+ memset(&dummy, 0, sizeof(struct i2c_msg));
+
+ /* We expect either two messages (one with an offset and one with the
+ * actual data) or one message (just data or offset/data combined) */
+ if (nmsgs > 2 || nmsgs == 0) {
+ debug("%s: Only one or two messages are supported.", __func__);
+ return -1;
+ }
+
+ omsg = nmsgs == 1 ? &dummy : msg;
+ dmsg = nmsgs == 1 ? msg : msg + 1;
+
+ if (dmsg->flags & I2C_M_RD)
+ return __twsi_i2c_read(dev->base, dmsg->addr, omsg->buf,
+ omsg->len, dmsg->buf, dmsg->len);
+ else
+ return __twsi_i2c_write(dev->base, dmsg->addr, omsg->buf,
+ omsg->len, dmsg->buf, dmsg->len);
+}
+
+static const struct dm_i2c_ops mvtwsi_i2c_ops = {
+ .xfer = mvtwsi_i2c_xfer,
+ .probe_chip = mvtwsi_i2c_probe_chip,
+ .set_bus_speed = mvtwsi_i2c_set_bus_speed,
+};
+
+static const struct udevice_id mvtwsi_i2c_ids[] = {
+ { .compatible = "marvell,mv64xxx-i2c", },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(i2c_mvtwsi) = {
+ .name = "i2c_mvtwsi",
+ .id = UCLASS_I2C,
+ .of_match = mvtwsi_i2c_ids,
+ .probe = mvtwsi_i2c_probe,
+ .ofdata_to_platdata = mvtwsi_i2c_ofdata_to_platdata,
+ .priv_auto_alloc_size = sizeof(struct mvtwsi_i2c_dev),
+ .ops = &mvtwsi_i2c_ops,
+};
+#endif /* CONFIG_DM_I2C */