From 14a6ff2c4f22010e5d67f25508f09e3b53a1f1c4 Mon Sep 17 00:00:00 2001 From: "mario.six@gdsys.cc" Date: Thu, 21 Jul 2016 11:57:10 +0200 Subject: [PATCH] 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 Reviewed-by: Stefan Roese --- drivers/i2c/Kconfig | 7 +++ drivers/i2c/mvtwsi.c | 111 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 6e22bbadff..b3e84052eb 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -154,6 +154,13 @@ config SYS_I2C_UNIPHIER_F Support for UniPhier FIFO-builtin I2C controller driver. This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs. +config SYS_I2C_MVTWSI + bool "Marvell I2C driver" + depends on DM_I2C + help + Support for Marvell I2C controllers as used on the orion5x and + kirkwood SoC families. + source "drivers/i2c/muxes/Kconfig" endmenu 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 #include #include +#ifdef CONFIG_DM_I2C +#include +#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 #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 */ -- 2.25.1