X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fi2c%2Fomap24xx_i2c.c;h=0759585c9e1a39322fab2cc25b8d2be8d0e7a7c6;hb=2e668af5531815dc6a6190cf6490b866da71ffaa;hp=79a5c94f1cd045094557fca6b564464b64084c96;hpb=656ae05273419c344c11466de72476455793d6b6;p=u-boot diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 79a5c94f1c..0759585c9e 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -39,6 +39,7 @@ */ #include +#include #include #include @@ -46,53 +47,158 @@ #include "omap24xx_i2c.h" -DECLARE_GLOBAL_DATA_PTR; - #define I2C_TIMEOUT 1000 /* Absolutely safe for status update at 100 kHz I2C: */ #define I2C_WAIT 200 -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); +struct omap_i2c { + struct udevice *clk; + struct i2c *regs; + unsigned int speed; + int waitdelay; + int clk_id; +}; + static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) { - unsigned int sampleclk, prescaler; - int fsscll, fssclh; + unsigned long internal_clk = 0, fclk; + unsigned int prescaler; - speed <<= 1; - prescaler = 0; /* - * some divisors may cause a precission loss, but shouldn't - * be a big thing, because i2c_clk is then allready very slow. + * This method is only called for Standard and Fast Mode speeds + * + * For some TI SoCs it is explicitly written in TRM (e,g, SPRUHZ6G, + * page 5685, Table 24-7) + * that the internal I2C clock (after prescaler) should be between + * 7-12 MHz (at least for Fast Mode (FS)). + * + * Such approach is used in v4.9 Linux kernel in: + * ./drivers/i2c/busses/i2c-omap.c (omap_i2c_init function). */ - while (prescaler <= 0xFF) { - sampleclk = I2C_IP_CLK / (prescaler+1); - fsscll = sampleclk / speed; - fssclh = fsscll; - fsscll -= I2C_FASTSPEED_SCLL_TRIM; - fssclh -= I2C_FASTSPEED_SCLH_TRIM; - - if (((fsscll > 0) && (fssclh > 0)) && - ((fsscll <= (255-I2C_FASTSPEED_SCLL_TRIM)) && - (fssclh <= (255-I2C_FASTSPEED_SCLH_TRIM)))) { - if (pscl) - *pscl = fsscll; - if (psch) - *psch = fssclh; - - return prescaler; - } - prescaler++; + speed /= 1000; /* convert speed to kHz */ + + if (speed > 100) + internal_clk = 9600; + else + internal_clk = 4000; + + fclk = I2C_IP_CLK / 1000; + prescaler = fclk / internal_clk; + prescaler = prescaler - 1; + + if (speed > 100) { + unsigned long scl; + + /* Fast mode */ + scl = internal_clk / speed; + *pscl = scl - (scl / 3) - I2C_FASTSPEED_SCLL_TRIM; + *psch = (scl / 3) - I2C_FASTSPEED_SCLH_TRIM; + } else { + /* Standard mode */ + *pscl = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLL_TRIM; + *psch = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLH_TRIM; } - return -1; + + debug("%s: speed [kHz]: %d psc: 0x%x sscl: 0x%x ssch: 0x%x\n", + __func__, speed, prescaler, *pscl, *psch); + + if (*pscl <= 0 || *psch <= 0 || prescaler <= 0) + return -EINVAL; + + return prescaler; } -static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) + +/* + * Wait for the bus to be free by checking the Bus Busy (BB) + * bit to become clear + */ +static int wait_for_bb(struct i2c *i2c_base, int waitdelay) +{ + int timeout = I2C_TIMEOUT; + u16 stat; + + writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/ +#if defined(CONFIG_OMAP34XX) + while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) { +#else + /* Read RAW status */ + while ((stat = readw(&i2c_base->irqstatus_raw) & + I2C_STAT_BB) && timeout--) { +#endif + writew(stat, &i2c_base->stat); + udelay(waitdelay); + } + + if (timeout <= 0) { + printf("Timed out in wait_for_bb: status=%04x\n", + stat); + return 1; + } + writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ + return 0; +} + +/* + * Wait for the I2C controller to complete current action + * and update status + */ +static u16 wait_for_event(struct i2c *i2c_base, int waitdelay) +{ + u16 status; + int timeout = I2C_TIMEOUT; + + do { + udelay(waitdelay); +#if defined(CONFIG_OMAP34XX) + status = readw(&i2c_base->stat); +#else + /* Read RAW status */ + status = readw(&i2c_base->irqstatus_raw); +#endif + } while (!(status & + (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | + I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | + I2C_STAT_AL)) && timeout--); + + if (timeout <= 0) { + printf("Timed out in wait_for_event: status=%04x\n", + status); + /* + * If status is still 0 here, probably the bus pads have + * not been configured for I2C, and/or pull-ups are missing. + */ + printf("Check if pads/pull-ups of bus are properly configured\n"); + writew(0xFFFF, &i2c_base->stat); + status = 0; + } + + return status; +} + +static void flush_fifo(struct i2c *i2c_base) +{ + u16 stat; + + /* + * note: if you try and read data when its not there or ready + * you get a bus error + */ + while (1) { + stat = readw(&i2c_base->stat); + if (stat == I2C_STAT_RRDY) { + readb(&i2c_base->data); + writew(I2C_STAT_RRDY, &i2c_base->stat); + udelay(1000); + } else + break; + } +} + +static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed, + int *waitdelay) { - struct i2c *i2c_base = omap24_get_base(adap); int psc, fsscll = 0, fssclh = 0; int hsscll = 0, hssclh = 0; u32 scll = 0, sclh = 0; @@ -142,8 +248,7 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) } } - adap->speed = speed; - adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */ + *waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */ writew(0, &i2c_base->con); writew(psc, &i2c_base->psc); writew(scll, &i2c_base->scll); @@ -154,9 +259,8 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) return 0; } -static void omap24_i2c_deblock(struct i2c_adapter *adap) +static void omap24_i2c_deblock(struct i2c *i2c_base) { - struct i2c *i2c_base = omap24_get_base(adap); int i; u16 systest; u16 orgsystest; @@ -200,9 +304,9 @@ static void omap24_i2c_deblock(struct i2c_adapter *adap) writew(orgsystest, &i2c_base->systest); } -static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +static void __omap24_i2c_init(struct i2c *i2c_base, int speed, int slaveadd, + int *waitdelay) { - struct i2c *i2c_base = omap24_get_base(adap); int timeout = I2C_TIMEOUT; int deblock = 1; @@ -224,7 +328,7 @@ retry: udelay(1000); } - if (0 != omap24_i2c_setspeed(adap, speed)) { + if (0 != __omap24_i2c_setspeed(i2c_base, speed, waitdelay)) { printf("ERROR: failed to setup I2C bus-speed!\n"); return; } @@ -232,7 +336,7 @@ retry: /* own address */ writew(slaveadd, &i2c_base->oa); -#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) +#if defined(CONFIG_OMAP34XX) /* * Have to enable interrupts for OMAP2/3, these IPs don't have * an 'irqstatus_raw' register and we shall have to poll 'stat' @@ -241,45 +345,24 @@ retry: I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie); #endif udelay(1000); - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); /* Handle possible failed I2C state */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, *waitdelay)) if (deblock == 1) { - omap24_i2c_deblock(adap); + omap24_i2c_deblock(i2c_base); deblock = 0; goto retry; } } -static void flush_fifo(struct i2c_adapter *adap) -{ - struct i2c *i2c_base = omap24_get_base(adap); - u16 stat; - - /* - * note: if you try and read data when its not there or ready - * you get a bus error - */ - while (1) { - stat = readw(&i2c_base->stat); - if (stat == I2C_STAT_RRDY) { - readb(&i2c_base->data); - writew(I2C_STAT_RRDY, &i2c_base->stat); - udelay(1000); - } else - break; - } -} - /* * i2c_probe: Use write access. Allows to identify addresses that are * write-only (like the config register of dual-port EEPROMs) */ -static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) +static int __omap24_i2c_probe(struct i2c *i2c_base, int waitdelay, uchar chip) { - struct i2c *i2c_base = omap24_get_base(adap); u16 status; int res = 1; /* default = fail */ @@ -287,7 +370,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) return res; /* Wait until bus is free */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, waitdelay)) return res; /* No data transfer, slave addr only */ @@ -296,7 +379,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP, &i2c_base->con); - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) { /* @@ -306,8 +389,8 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) * following 'if' section: */ if (status == I2C_STAT_XRDY) - printf("i2c_probe: pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_probe: pads on bus probably not configured (status=0x%x)\n", + status); goto pr_exit; } @@ -315,7 +398,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) /* Check for ACK (!NAK) */ if (!(status & I2C_STAT_NACK)) { res = 0; /* Device found */ - udelay(adap->waitdelay);/* Required by AM335X in SPL */ + udelay(waitdelay);/* Required by AM335X in SPL */ /* Abort transfer (force idle state) */ writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */ udelay(1000); @@ -323,7 +406,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) I2C_CON_STP, &i2c_base->con); /* STP */ } pr_exit: - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); return res; } @@ -341,10 +424,9 @@ pr_exit: * or that do not need a register address at all (such as some clock * distributors). */ -static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buffer, int len) +static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, + uint addr, int alen, uchar *buffer, int len) { - struct i2c *i2c_base = omap24_get_base(adap); int i2c_error = 0; u16 status; @@ -371,8 +453,25 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, return 1; } +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + /* Wait until bus not busy */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, waitdelay)) return 1; /* Zero, one or two bytes reg address (offset) */ @@ -393,12 +492,12 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, #endif /* Send register offset */ while (1) { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); /* Try to identify bus that is not padconf'd for I2C */ if (status == I2C_STAT_XRDY) { i2c_error = 2; - printf("i2c_read (addr phase): pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_read (addr phase): pads on bus probably not configured (status=0x%x)\n", + status); goto rd_exit; } if (status == 0 || (status & I2C_STAT_NACK)) { @@ -433,7 +532,7 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, /* Receive data */ while (1) { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); /* * Try to identify bus that is not padconf'd for I2C. This * state could be left over from previous transactions if @@ -441,8 +540,8 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, */ if (status == I2C_STAT_XRDY) { i2c_error = 2; - printf("i2c_read (data phase): pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_read (data phase): pads on bus probably not configured (status=0x%x)\n", + status); goto rd_exit; } if (status == 0 || (status & I2C_STAT_NACK)) { @@ -460,16 +559,15 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, } rd_exit: - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); return i2c_error; } /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */ -static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buffer, int len) +static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, + uint addr, int alen, uchar *buffer, int len) { - struct i2c *i2c_base = omap24_get_base(adap); int i; u16 status; int i2c_error = 0; @@ -501,8 +599,25 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, return 1; } +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + /* Wait until bus not busy */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, waitdelay)) return 1; /* Start address phase - will write regoffset + len bytes data */ @@ -515,12 +630,12 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, while (alen) { /* Must write reg offset (one or two bytes) */ - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); /* Try to identify bus that is not padconf'd for I2C */ if (status == I2C_STAT_XRDY) { i2c_error = 2; - printf("i2c_write: pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_write: pads on bus probably not configured (status=0x%x)\n", + status); goto wr_exit; } if (status == 0 || (status & I2C_STAT_NACK)) { @@ -542,7 +657,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, } /* Address phase is over, now write data */ for (i = 0; i < len; i++) { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); if (status == 0 || (status & I2C_STAT_NACK)) { i2c_error = 1; printf("i2c_write: error waiting for data ACK (status=0x%x)\n", @@ -564,87 +679,22 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, * transferred on the bus. */ do { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); } while (!(status & I2C_STAT_ARDY) && timeout--); if (timeout <= 0) printf("i2c_write: timed out writig last byte!\n"); wr_exit: - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); return i2c_error; } +#ifndef CONFIG_DM_I2C /* - * Wait for the bus to be free by checking the Bus Busy (BB) - * bit to become clear + * The legacy I2C functions. These need to get removed once + * all users of this driver are converted to DM. */ -static int wait_for_bb(struct i2c_adapter *adap) -{ - struct i2c *i2c_base = omap24_get_base(adap); - int timeout = I2C_TIMEOUT; - u16 stat; - - 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--) { -#else - /* Read RAW status */ - while ((stat = readw(&i2c_base->irqstatus_raw) & - I2C_STAT_BB) && timeout--) { -#endif - writew(stat, &i2c_base->stat); - udelay(adap->waitdelay); - } - - if (timeout <= 0) { - printf("Timed out in wait_for_bb: status=%04x\n", - stat); - return 1; - } - writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ - return 0; -} - -/* - * Wait for the I2C controller to complete current action - * and update status - */ -static u16 wait_for_event(struct i2c_adapter *adap) -{ - struct i2c *i2c_base = omap24_get_base(adap); - u16 status; - int timeout = I2C_TIMEOUT; - - do { - udelay(adap->waitdelay); -#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) - status = readw(&i2c_base->stat); -#else - /* Read RAW status */ - status = readw(&i2c_base->irqstatus_raw); -#endif - } while (!(status & - (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | - I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | - I2C_STAT_AL)) && timeout--); - - if (timeout <= 0) { - printf("Timed out in wait_for_event: status=%04x\n", - status); - /* - * If status is still 0 here, probably the bus pads have - * not been configured for I2C, and/or pull-ups are missing. - */ - printf("Check if pads/pull-ups of bus %d are properly configured\n", - adap->hwadapnr); - writew(0xFFFF, &i2c_base->stat); - status = 0; - } - - return status; -} - static struct i2c *omap24_get_base(struct i2c_adapter *adap) { switch (adap->hwadapnr) { @@ -654,15 +704,15 @@ static struct i2c *omap24_get_base(struct i2c_adapter *adap) case 1: return (struct i2c *)I2C_BASE2; break; -#if (I2C_BUS_MAX > 2) +#if (CONFIG_SYS_I2C_BUS_MAX > 2) case 2: return (struct i2c *)I2C_BASE3; break; -#if (I2C_BUS_MAX > 3) +#if (CONFIG_SYS_I2C_BUS_MAX > 3) case 3: return (struct i2c *)I2C_BASE4; break; -#if (I2C_BUS_MAX > 4) +#if (CONFIG_SYS_I2C_BUS_MAX > 4) case 4: return (struct i2c *)I2C_BASE5; break; @@ -676,6 +726,56 @@ static struct i2c *omap24_get_base(struct i2c_adapter *adap) return NULL; } + +static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_read(i2c_base, adap->waitdelay, chip, addr, + alen, buffer, len); +} + + +static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_write(i2c_base, adap->waitdelay, chip, addr, + alen, buffer, len); +} + +static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) +{ + struct i2c *i2c_base = omap24_get_base(adap); + int ret; + + ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay); + if (ret) { + pr_err("%s: set i2c speed failed\n", __func__); + return ret; + } + + adap->speed = speed; + + return 0; +} + +static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_init(i2c_base, speed, slaveadd, &adap->waitdelay); +} + +static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_probe(i2c_base, adap->waitdelay, chip); +} + #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1) #define CONFIG_SYS_OMAP24_I2C_SPEED1 CONFIG_SYS_OMAP24_I2C_SPEED #endif @@ -693,7 +793,7 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_1, omap24_i2c_init, omap24_i2c_probe, CONFIG_SYS_OMAP24_I2C_SPEED1, CONFIG_SYS_OMAP24_I2C_SLAVE1, 1) -#if (I2C_BUS_MAX > 2) +#if (CONFIG_SYS_I2C_BUS_MAX > 2) #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED2) #define CONFIG_SYS_OMAP24_I2C_SPEED2 CONFIG_SYS_OMAP24_I2C_SPEED #endif @@ -706,7 +806,7 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_2, omap24_i2c_init, omap24_i2c_probe, CONFIG_SYS_OMAP24_I2C_SPEED2, CONFIG_SYS_OMAP24_I2C_SLAVE2, 2) -#if (I2C_BUS_MAX > 3) +#if (CONFIG_SYS_I2C_BUS_MAX > 3) #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED3) #define CONFIG_SYS_OMAP24_I2C_SPEED3 CONFIG_SYS_OMAP24_I2C_SPEED #endif @@ -719,7 +819,7 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_3, omap24_i2c_init, omap24_i2c_probe, CONFIG_SYS_OMAP24_I2C_SPEED3, CONFIG_SYS_OMAP24_I2C_SLAVE3, 3) -#if (I2C_BUS_MAX > 4) +#if (CONFIG_SYS_I2C_BUS_MAX > 4) #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED4) #define CONFIG_SYS_OMAP24_I2C_SPEED4 CONFIG_SYS_OMAP24_I2C_SPEED #endif @@ -735,3 +835,93 @@ U_BOOT_I2C_ADAP_COMPLETE(omap24_4, omap24_i2c_init, omap24_i2c_probe, #endif #endif #endif + +#else /* CONFIG_DM_I2C */ + +static int omap_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + struct omap_i2c *priv = dev_get_priv(bus); + int ret; + + debug("i2c_xfer: %d messages\n", nmsgs); + for (; nmsgs > 0; nmsgs--, msg++) { + debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); + if (msg->flags & I2C_M_RD) { + ret = __omap24_i2c_read(priv->regs, priv->waitdelay, + msg->addr, 0, 0, msg->buf, + msg->len); + } else { + ret = __omap24_i2c_write(priv->regs, priv->waitdelay, + msg->addr, 0, 0, msg->buf, + msg->len); + } + if (ret) { + debug("i2c_write: error sending\n"); + return -EREMOTEIO; + } + } + + return 0; +} + +static int omap_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) +{ + struct omap_i2c *priv = dev_get_priv(bus); + + priv->speed = speed; + + return __omap24_i2c_setspeed(priv->regs, speed, &priv->waitdelay); +} + +static int omap_i2c_probe_chip(struct udevice *bus, uint chip_addr, + uint chip_flags) +{ + struct omap_i2c *priv = dev_get_priv(bus); + + return __omap24_i2c_probe(priv->regs, priv->waitdelay, chip_addr); +} + +static int omap_i2c_probe(struct udevice *bus) +{ + struct omap_i2c *priv = dev_get_priv(bus); + + __omap24_i2c_init(priv->regs, priv->speed, 0, &priv->waitdelay); + + return 0; +} + +static int omap_i2c_ofdata_to_platdata(struct udevice *bus) +{ + struct omap_i2c *priv = dev_get_priv(bus); + + priv->regs = map_physmem(devfdt_get_addr(bus), sizeof(void *), + MAP_NOCACHE); + priv->speed = CONFIG_SYS_OMAP24_I2C_SPEED; + + return 0; +} + +static const struct dm_i2c_ops omap_i2c_ops = { + .xfer = omap_i2c_xfer, + .probe_chip = omap_i2c_probe_chip, + .set_bus_speed = omap_i2c_set_bus_speed, +}; + +static const struct udevice_id omap_i2c_ids[] = { + { .compatible = "ti,omap3-i2c" }, + { .compatible = "ti,omap4-i2c" }, + { } +}; + +U_BOOT_DRIVER(i2c_omap) = { + .name = "i2c_omap", + .id = UCLASS_I2C, + .of_match = omap_i2c_ids, + .ofdata_to_platdata = omap_i2c_ofdata_to_platdata, + .probe = omap_i2c_probe, + .priv_auto_alloc_size = sizeof(struct omap_i2c), + .ops = &omap_i2c_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#endif /* CONFIG_DM_I2C */