From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heiko Schocher Date: Mon, 18 Jan 2016 06:49:54 +0100 Subject: [U-Boot] [PATCH 1/5] i2c: omap24xx: Convert to DM In-Reply-To: <1453028992-14220-2-git-send-email-christophe-h.ricard@st.com> References: <1453028992-14220-1-git-send-email-christophe-h.ricard@st.com> <1453028992-14220-2-git-send-email-christophe-h.ricard@st.com> Message-ID: <569C7D02.4000802@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello Christophe, Am 17.01.2016 um 12:09 schrieb Christophe Ricard: > Convert omap24xx_i2c driver to DM > > Signed-off-by: Christophe Ricard > --- > > drivers/i2c/Kconfig | 8 ++ > drivers/i2c/omap24xx_i2c.c | 280 +++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 277 insertions(+), 11 deletions(-) Looks good to me, Thanks! Acked-by: Heiko Schocher bye, Heiko > > 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 , B&R > * - Added support for set_speed > * > + * Copyright (c) 2016 Christophe Ricard > + * - Added support for DM_I2C > + * > */ > > #include > #include > +#include > > #include > #include > +#include > > #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 > -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany