From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/5] i2c: omap24xx: Convert to DM
Date: Mon, 18 Jan 2016 06:49:54 +0100 [thread overview]
Message-ID: <569C7D02.4000802@denx.de> (raw)
In-Reply-To: <1453028992-14220-2-git-send-email-christophe-h.ricard@st.com>
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@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@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@oevsv.at>, B&R
> * - Added support for set_speed
> *
> + * Copyright (c) 2016 Christophe Ricard <christophe.ricard@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
next prev parent reply other threads:[~2016-01-18 5:49 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-17 11:09 [U-Boot] [PATCH 0/5] Convert omap24xx-i2c driver to Driver Model Christophe Ricard
2016-01-17 11:09 ` [U-Boot] [PATCH 1/5] i2c: omap24xx: Convert to DM Christophe Ricard
2016-01-18 5:49 ` Heiko Schocher [this message]
2016-01-21 2:46 ` Simon Glass
2016-01-17 11:09 ` [U-Boot] [PATCH 2/5] i2c: omap24xx: Fix waitdelay value for I2C HS Christophe Ricard
2016-01-18 5:59 ` Heiko Schocher
2016-01-17 11:09 ` [U-Boot] [PATCH 3/5] i2c: omap24xx: Remove unused I2C_WAIT macro Christophe Ricard
2016-01-18 6:00 ` Heiko Schocher
2016-01-17 11:09 ` [U-Boot] [PATCH 4/5] i2c: omap24xx: Fix high speed trimming calculation Christophe Ricard
2016-01-18 6:02 ` Heiko Schocher
2016-01-17 11:09 ` [U-Boot] [PATCH 5/5] i2c: omap24xx: Convert fully to DM_I2C Christophe Ricard
2016-01-18 6:04 ` Heiko Schocher
2016-01-18 21:22 ` Christophe Ricard
2016-01-20 4:50 ` Heiko Schocher
2016-12-05 12:19 ` [U-Boot] [PATCH 0/5] Convert omap24xx-i2c driver to Driver Model Heiko Schocher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=569C7D02.4000802@denx.de \
--to=hs@denx.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.