[U-Boot] [PATCH 1/5] i2c: omap24xx: Convert to DM
Christophe Ricard
christophe.ricard at gmail.com
Sun Jan 17 12:09:48 CET 2016
Convert omap24xx_i2c driver to DM
Signed-off-by: Christophe Ricard <christophe-h.ricard at st.com>
---
drivers/i2c/Kconfig | 8 ++
drivers/i2c/omap24xx_i2c.c | 280 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 277 insertions(+), 11 deletions(-)
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 14adda2..3498af1 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -58,6 +58,14 @@ config DM_I2C_GPIO
bindings are supported.
Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
+config SYS_I2C_OMAP24XX
+ bool "Texas Instrument OMAP I2C driver"
+ depends on DM_I2C
+ help
+ Enable support for the I2C interface on the Texas Instruments
+ OMAP1/2 family of processors. Like OMAP1510/1610/1710/5912 and OMAP242x.
+ For details see http://www.ti.com/omap.
+
config SYS_I2C_ROCKCHIP
bool "Rockchip I2C driver"
depends on DM_I2C
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 79a5c94..f3a4d96 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -36,13 +36,18 @@
* Copyright (c) 2014 Hannes Schmelzer <oe5hpm at oevsv.at>, B&R
* - Added support for set_speed
*
+ * Copyright (c) 2016 Christophe Ricard <christophe.ricard at gmail.com>
+ * - Added support for DM_I2C
+ *
*/
#include <common.h>
#include <i2c.h>
+#include <dm.h>
#include <asm/arch/i2c.h>
#include <asm/io.h>
+#include <asm/errno.h>
#include "omap24xx_i2c.h"
@@ -53,10 +58,26 @@ DECLARE_GLOBAL_DATA_PTR;
/* Absolutely safe for status update at 100 kHz I2C: */
#define I2C_WAIT 200
+#ifdef CONFIG_DM_I2C
+struct omap24_i2c_bus {
+ int bus_num;
+ int waitdelay;
+ unsigned clock_frequency;
+ struct i2c *i2c_base;
+};
+#endif
+
+#ifdef CONFIG_SYS_I2C
static int wait_for_bb(struct i2c_adapter *adap);
static struct i2c *omap24_get_base(struct i2c_adapter *adap);
static u16 wait_for_event(struct i2c_adapter *adap);
static void flush_fifo(struct i2c_adapter *adap);
+#else
+static int wait_for_bb(struct udevice *dev);
+static u16 wait_for_event(struct udevice *dev);
+static void flush_fifo(struct udevice *dev);
+#endif
+
static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
{
unsigned int sampleclk, prescaler;
@@ -90,13 +111,27 @@ static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
}
return -1;
}
+
+#ifdef CONFIG_SYS_I2C
static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
+#else
+static int omap24_i2c_setspeed(struct udevice *adap, unsigned int speed)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
int psc, fsscll = 0, fssclh = 0;
int hsscll = 0, hssclh = 0;
u32 scll = 0, sclh = 0;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
if (speed >= OMAP_I2C_HIGH_SPEED) {
/* High speed */
psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
@@ -142,8 +177,14 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
}
}
+#ifdef CONFIG_SYS_I2C
adap->speed = speed;
adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
+#else
+ i2c_bus->clock_frequency = speed;
+ i2c_bus->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
+#endif
+
writew(0, &i2c_base->con);
writew(psc, &i2c_base->psc);
writew(scll, &i2c_base->scll);
@@ -154,13 +195,26 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
return 0;
}
+#ifdef CONFIG_SYS_I2C
static void omap24_i2c_deblock(struct i2c_adapter *adap)
+#else
+static int omap24_i2c_deblock(struct udevice *adap)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
int i;
u16 systest;
u16 orgsystest;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
/* set test mode ST_EN = 1 */
orgsystest = readw(&i2c_base->systest);
systest = orgsystest;
@@ -198,14 +252,31 @@ static void omap24_i2c_deblock(struct i2c_adapter *adap)
/* restore original mode */
writew(orgsystest, &i2c_base->systest);
+
+#ifdef CONFIG_DM_I2C
+ return 0;
+#endif
}
+#ifdef CONFIG_SYS_I2C
static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+#else
+static void omap24_i2c_init(struct udevice *adap, int speed, int slaveadd)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
int timeout = I2C_TIMEOUT;
int deblock = 1;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
retry:
if (readw(&i2c_base->con) & I2C_CON_EN) {
writew(0, &i2c_base->con);
@@ -253,11 +324,24 @@ retry:
}
}
+#ifdef CONFIG_SYS_I2C
static void flush_fifo(struct i2c_adapter *adap)
+#else
+static void flush_fifo(struct udevice *adap)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
u16 stat;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
/*
* note: if you try and read data when its not there or ready
* you get a bus error
@@ -277,12 +361,25 @@ static void flush_fifo(struct i2c_adapter *adap)
* i2c_probe: Use write access. Allows to identify addresses that are
* write-only (like the config register of dual-port EEPROMs)
*/
+#ifdef CONFIG_SYS_I2C
static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
+#else
+static int omap24_i2c_probe(struct udevice *adap, uint chip, uint chip_flags)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
u16 status;
int res = 1; /* default = fail */
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
if (chip == readw(&i2c_base->oa))
return res;
@@ -305,17 +402,26 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
* silent exit is desired upon unconfigured bus, remove the
* following 'if' section:
*/
- if (status == I2C_STAT_XRDY)
+ if (status == I2C_STAT_XRDY) {
+#ifdef CONFIG_SYS_I2C
printf("i2c_probe: pads on bus %d probably not configured (status=0x%x)\n",
adap->hwadapnr, status);
-
+#else
+ printf("i2c_probe: pads on bus %d probably not configured (status=0x%x)\n",
+ i2c_bus->bus_num, status);
+#endif
+ }
goto pr_exit;
}
/* Check for ACK (!NAK) */
if (!(status & I2C_STAT_NACK)) {
res = 0; /* Device found */
+#ifdef CONFIG_SYS_I2C
udelay(adap->waitdelay);/* Required by AM335X in SPL */
+#else
+ udelay(i2c_bus->waitdelay);
+#endif
/* Abort transfer (force idle state) */
writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
udelay(1000);
@@ -341,13 +447,27 @@ pr_exit:
* or that do not need a register address at all (such as some clock
* distributors).
*/
+#ifdef CONFIG_SYS_I2C
static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *buffer, int len)
+#else
+static int omap24_i2c_read(struct udevice *adap, uchar chip, uint addr,
+ int alen, uchar *buffer, int len)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
int i2c_error = 0;
u16 status;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
if (alen < 0) {
puts("I2C read: addr len < 0\n");
return 1;
@@ -397,8 +517,13 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
/* Try to identify bus that is not padconf'd for I2C */
if (status == I2C_STAT_XRDY) {
i2c_error = 2;
+#ifdef CONFIG_SYS_I2C
printf("i2c_read (addr phase): pads on bus %d probably not configured (status=0x%x)\n",
adap->hwadapnr, status);
+#else
+ printf("i2c_read (addr phase): pads on bus %d probably not configured (status=0x%x)\n",
+ i2c_bus->bus_num, status);
+#endif
goto rd_exit;
}
if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -441,8 +566,13 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
*/
if (status == I2C_STAT_XRDY) {
i2c_error = 2;
+#ifdef CONFIG_SYS_I2C
printf("i2c_read (data phase): pads on bus %d probably not configured (status=0x%x)\n",
adap->hwadapnr, status);
+#else
+ printf("i2c_read (data phase): pads on bus %d probably not configured (status=0x%x)\n",
+ i2c_bus->bus_num, status);
+#endif
goto rd_exit;
}
if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -466,15 +596,29 @@ rd_exit:
}
/* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */
+#ifdef CONFIG_SYS_I2C
static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *buffer, int len)
+#else
+static int omap24_i2c_write(struct udevice *adap, uchar chip, uint addr,
+ int alen, uchar *buffer, int len)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
int i;
u16 status;
int i2c_error = 0;
int timeout = I2C_TIMEOUT;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
if (alen < 0) {
puts("I2C write: addr len < 0\n");
return 1;
@@ -519,8 +663,13 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
/* Try to identify bus that is not padconf'd for I2C */
if (status == I2C_STAT_XRDY) {
i2c_error = 2;
+#ifdef CONFIG_SYS_I2C
printf("i2c_write: pads on bus %d probably not configured (status=0x%x)\n",
adap->hwadapnr, status);
+#else
+ printf("i2c_write: pads on bus %d probably not configured (status=0x%x)\n",
+ i2c_bus->bus_num, status);
+#endif
goto wr_exit;
}
if (status == 0 || (status & I2C_STAT_NACK)) {
@@ -579,12 +728,25 @@ wr_exit:
* Wait for the bus to be free by checking the Bus Busy (BB)
* bit to become clear
*/
+#ifdef CONFIG_SYS_I2C
static int wait_for_bb(struct i2c_adapter *adap)
+#else
+static int wait_for_bb(struct udevice *adap)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
int timeout = I2C_TIMEOUT;
u16 stat;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
@@ -594,7 +756,11 @@ static int wait_for_bb(struct i2c_adapter *adap)
I2C_STAT_BB) && timeout--) {
#endif
writew(stat, &i2c_base->stat);
+#ifdef CONFIG_SYS_I2C
udelay(adap->waitdelay);
+#else
+ udelay(i2c_bus->waitdelay);
+#endif
}
if (timeout <= 0) {
@@ -610,14 +776,31 @@ static int wait_for_bb(struct i2c_adapter *adap)
* Wait for the I2C controller to complete current action
* and update status
*/
+#ifdef CONFIG_SYS_I2C
static u16 wait_for_event(struct i2c_adapter *adap)
+#else
+static u16 wait_for_event(struct udevice *adap)
+#endif
{
- struct i2c *i2c_base = omap24_get_base(adap);
+ struct i2c *i2c_base;
u16 status;
int timeout = I2C_TIMEOUT;
+#ifdef CONFIG_SYS_I2C
+ i2c_base = omap24_get_base(adap);
+#else
+ struct omap24_i2c_bus *i2c_bus;
+
+ i2c_bus = dev_get_priv(adap);
+ i2c_base = i2c_bus->i2c_base;
+#endif
+
do {
+#ifdef CONFIG_SYS_I2C
udelay(adap->waitdelay);
+#else
+ udelay(i2c_bus->waitdelay);
+#endif
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
status = readw(&i2c_base->stat);
#else
@@ -636,8 +819,13 @@ static u16 wait_for_event(struct i2c_adapter *adap)
* If status is still 0 here, probably the bus pads have
* not been configured for I2C, and/or pull-ups are missing.
*/
+#ifdef CONFIG_SYS_I2C
printf("Check if pads/pull-ups of bus %d are properly configured\n",
adap->hwadapnr);
+#else
+ printf("Check if pads/pull-ups of bus %d are properly configured\n",
+ i2c_bus->bus_num);
+#endif
writew(0xFFFF, &i2c_base->stat);
status = 0;
}
@@ -645,6 +833,7 @@ static u16 wait_for_event(struct i2c_adapter *adap)
return status;
}
+#ifdef CONFIG_SYS_I2C
static struct i2c *omap24_get_base(struct i2c_adapter *adap)
{
switch (adap->hwadapnr) {
@@ -735,3 +924,72 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_4, omap24_i2c_init, omap24_i2c_probe,
#endif
#endif
#endif
+#endif
+
+#ifdef CONFIG_DM_I2C
+static int omap24_i2c_xfer(struct udevice *adap, struct i2c_msg *msg,
+ int nmsgs)
+{
+ int ret;
+
+ for (; nmsgs > 0; nmsgs--, msg++) {
+ if (msg->flags & I2C_M_RD) {
+ ret = omap24_i2c_read(adap, msg->addr, 0, 0, msg->buf,
+ msg->len);
+ } else {
+ ret = omap24_i2c_write(adap, msg->addr, 0, 0, msg->buf,
+ msg->len);
+ }
+
+ if (ret)
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int omap24_i2c_ofdata_to_platdata(struct udevice *adap)
+{
+ const void *blob = gd->fdt_blob;
+ struct omap24_i2c_bus *i2c_bus = dev_get_priv(adap);
+ int node;
+
+ node = adap->of_offset;
+
+ i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
+ "clock-frequency", 100000);
+ i2c_bus->i2c_base = (struct i2c *)dev_get_addr(adap);
+ i2c_bus->waitdelay = (10000000 / i2c_bus->clock_frequency) * 2; /* wait for 20 clkperiods */
+
+ i2c_bus->bus_num = adap->seq;
+
+ omap24_i2c_init(adap, i2c_bus->clock_frequency, 1);
+
+ return 0;
+}
+
+static const struct dm_i2c_ops omap24_i2c_ops = {
+ .xfer = omap24_i2c_xfer,
+ .probe_chip = omap24_i2c_probe,
+ .set_bus_speed = omap24_i2c_setspeed,
+ .deblock = omap24_i2c_deblock,
+};
+
+static const struct udevice_id omap24_i2c_ids[] = {
+ { .compatible = "ti,omap3-i2c" },
+ { .compatible = "ti,omap4-i2c" },
+ { .compatible = "ti,omap2430-i2c" },
+ { .compatible = "ti,omap2420-i2c" },
+ { }
+};
+
+U_BOOT_DRIVER(omap_i2c) = {
+ .name = "omap_i2c",
+ .id = UCLASS_I2C,
+ .of_match = omap24_i2c_ids,
+ .ofdata_to_platdata = omap24_i2c_ofdata_to_platdata,
+ .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+ .priv_auto_alloc_size = sizeof(struct omap24_i2c_bus),
+ .ops = &omap24_i2c_ops,
+};
+#endif
--
2.5.0
More information about the U-Boot
mailing list