[U-Boot] [PATCH 1/5] i2c: omap24xx: Convert to DM

Heiko Schocher hs at denx.de
Mon Jan 18 06:49:54 CET 2016


Hello Christophe,

Am 17.01.2016 um 12:09 schrieb Christophe Ricard:
> 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(-)

Looks good to me, Thanks!

Acked-by: Heiko Schocher <hs at denx.de>

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 <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
>

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


More information about the U-Boot mailing list