Message ID | 1341489592-24243-6-git-send-email-rajeshwari.s@samsung.com |
---|---|
State | New |
Headers | show |
Hi, On Thu, Jul 5, 2012 at 12:59 PM, Rajeshwari Shinde <rajeshwari.s@samsung.com> wrote: > This patch modifies the S3C I2C driver to suppport EXYNOS5. > The cahnges made to driver are as follows: > - I2C base address is passed as a parameter to many > functions to avoid multiple #ifdef > - Channel initialisation is moved to a commom funation > as it is required by i2c_init. > - Hardcoding for I2CCON_ACKGEN removed. > - Replaced printf with debug. > - Checkpatch issues resolved. > - Pinmux setting will be done in board/samsung/smdk5250/smdk5250.c > to avoid repeated setting of gpio lines, as it have multi bus support. > > Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com> > Signed-off-by: Doug Anderson <dianders@chromium.org> > Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com> > Acked-by: Simon Glass <sjg@chromium.org> > --- One more comment on this if not too late. I wonder if the g_current_bus variable could exist for all variants, but always be zero, so you can get rid of some of the #ifdef EXYNOS5 stuff? It seems like it might be a harmless change? Regards, Simon > Changes in V2: > - Removed #define for I2C cahnnels from hearder file except for I2C0. > - Incorporated review comments from Simon Glass. > Changes in V3: > - Incorporated review comments from Joonyoung Shim. > - Reduced the number of #ifdef by modifying get_i2c_base function. > - Removed duplicate code. > Changes in V4: > - Resolved build error for s3c2410. > Changes in V5: > - Pinmux setting will be done in board/samsung/smdk5250/smdk5250.c > to avoid repeated setting of gpio lines, as it have multi bus support. > - I2C bus offset calulation done based on EXYNOS_I2C_SPACING > - Peripharal related code removed. > drivers/i2c/s3c24x0_i2c.c | 193 +++++++++++++++++++++++++++----------------- > 1 files changed, 118 insertions(+), 75 deletions(-) > > diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c > index ba6f39b..bbd2ef8 100644 > --- a/drivers/i2c/s3c24x0_i2c.c > +++ b/drivers/i2c/s3c24x0_i2c.c > @@ -27,10 +27,15 @@ > */ > > #include <common.h> > +#ifdef CONFIG_EXYNOS5 > +#include <asm/arch/clk.h> > +#include <asm/arch/cpu.h> > +#else > #include <asm/arch/s3c24x0_cpu.h> > - > +#endif > #include <asm/io.h> > #include <i2c.h> > +#include "s3c24x0_i2c.h" > > #ifdef CONFIG_HARD_I2C > > @@ -45,6 +50,7 @@ > > #define I2CSTAT_BSY 0x20 /* Busy bit */ > #define I2CSTAT_NACK 0x01 /* Nack bit */ > +#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ > #define I2CCON_IRPND 0x10 /* Interrupt pending bit */ > #define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ > #define I2C_MODE_MR 0x80 /* Master Receive Mode */ > @@ -53,6 +59,10 @@ > > #define I2C_TIMEOUT 1 /* 1 second */ > > + > +#ifdef CONFIG_EXYNOS5 > +static unsigned int g_current_bus; /* Stores Current I2C Bus */ > +#else > static int GetI2CSDA(void) > { > struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); > @@ -77,16 +87,17 @@ static void SetI2CSCL(int x) > struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); > > #ifdef CONFIG_S3C2410 > - writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat); > + writel((readl(&gpio->gpedat) & ~0x4000) | > + (x & 1) << 14, &gpio->gpedat); > #endif > #ifdef CONFIG_S3C2400 > writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat); > #endif > } > +#endif > > -static int WaitForXfer(void) > +static int WaitForXfer(struct s3c24x0_i2c *i2c) > { > - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); > int i; > > i = I2C_TIMEOUT * 10000; > @@ -98,35 +109,77 @@ static int WaitForXfer(void) > return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT; > } > > -static int IsACK(void) > +static int IsACK(struct s3c24x0_i2c *i2c) > { > - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); > - > return !(readl(&i2c->iicstat) & I2CSTAT_NACK); > } > > -static void ReadWriteByte(void) > +static void ReadWriteByte(struct s3c24x0_i2c *i2c) > { > - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); > - > writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); > } > > +static struct s3c24x0_i2c *get_base_i2c(void) > +{ > +#ifdef CONFIG_EXYNOS5 > + struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c() > + + (EXYNOS_I2C_SPACING > + * g_current_bus)); > + return i2c; > +#else > + return s3c24x0_get_base_i2c(); > +#endif > +} > + > +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) > +{ > + ulong freq, pres = 16, div; > +#ifdef CONFIG_EXYNOS5 > + freq = get_i2c_clk(); > +#else > + freq = get_PCLK(); > +#endif > + /* calculate prescaler and divisor values */ > + if ((freq / pres / (16 + 1)) > speed) > + /* set prescaler to 512 */ > + pres = 512; > + > + div = 0; > + while ((freq / pres / (div + 1)) > speed) > + div++; > + > + /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ > + writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); > + > + /* init to SLAVE REVEIVE and set slaveaddr */ > + writel(0, &i2c->iicstat); > + writel(slaveadd, &i2c->iicadd); > + /* program Master Transmit (and implicit STOP) */ > + writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); > +} > + > void i2c_init(int speed, int slaveadd) > { > - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); > + struct s3c24x0_i2c *i2c = get_base_i2c(); > +#ifndef CONFIG_EXYNOS5 > struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); > - ulong freq, pres = 16, div; > +#endif > int i; > > - /* wait for some time to give previous transfer a chance to finish */ > +#ifdef CONFIG_EXYNOS5 > + /* By default i2c channel 0 is the current bus */ > + g_current_bus = 0; > > + i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); > +#endif > + /* wait for some time to give previous transfer a chance to finish */ > i = I2C_TIMEOUT * 1000; > while ((readl(&i2c->iicstat) && I2CSTAT_BSY) && (i > 0)) { > udelay(1000); > i--; > } > > +#ifndef CONFIG_EXYNOS5 > if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) { > #ifdef CONFIG_S3C2410 > ulong old_gpecon = readl(&gpio->gpecon); > @@ -171,26 +224,8 @@ void i2c_init(int speed, int slaveadd) > #endif > } > > - /* calculate prescaler and divisor values */ > - freq = get_PCLK(); > - if ((freq / pres / (16 + 1)) > speed) > - /* set prescaler to 512 */ > - pres = 512; > - > - div = 0; > - while ((freq / pres / (div + 1)) > speed) > - div++; > - > - /* set prescaler, divisor according to freq, also set > - * ACKGEN, IRQ */ > - writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); > - > - /* init to SLAVE REVEIVE and set slaveaddr */ > - writel(0, &i2c->iicstat); > - writel(slaveadd, &i2c->iicadd); > - /* program Master Transmit (and implicit STOP) */ > - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); > - > + i2c_ch_init(i2c, speed, slaveadd); > +#endif /* #ifndef CONFIG_EXYNOS5 */ > } > > /* > @@ -200,19 +235,19 @@ void i2c_init(int speed, int slaveadd) > * by the char, we could make it larger if needed. If it is > * 0 we skip the address write cycle. > */ > -static > -int i2c_transfer(unsigned char cmd_type, > - unsigned char chip, > - unsigned char addr[], > - unsigned char addr_len, > - unsigned char data[], unsigned short data_len) > +static int i2c_transfer(struct s3c24x0_i2c *i2c, > + unsigned char cmd_type, > + unsigned char chip, > + unsigned char addr[], > + unsigned char addr_len, > + unsigned char data[], > + unsigned short data_len) > { > - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); > int i, result; > > if (data == 0 || data_len == 0) { > /*Don't support data transfer of no length or to address 0 */ > - printf("i2c_transfer: bad call\n"); > + debug("i2c_transfer: bad call\n"); > return I2C_NOK; > } > > @@ -226,7 +261,7 @@ int i2c_transfer(unsigned char cmd_type, > if (readl(&i2c->iicstat) & I2CSTAT_BSY) > return I2C_NOK_TOUT; > > - writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon); > + writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); > result = I2C_OK; > > switch (cmd_type) { > @@ -238,16 +273,16 @@ int i2c_transfer(unsigned char cmd_type, > &i2c->iicstat); > i = 0; > while ((i < addr_len) && (result == I2C_OK)) { > - result = WaitForXfer(); > + result = WaitForXfer(i2c); > writel(addr[i], &i2c->iicds); > - ReadWriteByte(); > + ReadWriteByte(i2c); > i++; > } > i = 0; > while ((i < data_len) && (result == I2C_OK)) { > - result = WaitForXfer(); > + result = WaitForXfer(i2c); > writel(data[i], &i2c->iicds); > - ReadWriteByte(); > + ReadWriteByte(i2c); > i++; > } > } else { > @@ -257,19 +292,19 @@ int i2c_transfer(unsigned char cmd_type, > &i2c->iicstat); > i = 0; > while ((i < data_len) && (result = I2C_OK)) { > - result = WaitForXfer(); > + result = WaitForXfer(i2c); > writel(data[i], &i2c->iicds); > - ReadWriteByte(); > + ReadWriteByte(i2c); > i++; > } > } > > if (result == I2C_OK) > - result = WaitForXfer(); > + result = WaitForXfer(i2c); > > /* send STOP */ > writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); > - ReadWriteByte(); > + ReadWriteByte(i2c); > break; > > case I2C_READ: > @@ -279,13 +314,13 @@ int i2c_transfer(unsigned char cmd_type, > /* send START */ > writel(readl(&i2c->iicstat) | I2C_START_STOP, > &i2c->iicstat); > - result = WaitForXfer(); > - if (IsACK()) { > + result = WaitForXfer(i2c); > + if (IsACK(i2c)) { > i = 0; > while ((i < addr_len) && (result == I2C_OK)) { > writel(addr[i], &i2c->iicds); > - ReadWriteByte(); > - result = WaitForXfer(); > + ReadWriteByte(i2c); > + result = WaitForXfer(i2c); > i++; > } > > @@ -293,16 +328,17 @@ int i2c_transfer(unsigned char cmd_type, > /* resend START */ > writel(I2C_MODE_MR | I2C_TXRX_ENA | > I2C_START_STOP, &i2c->iicstat); > - ReadWriteByte(); > - result = WaitForXfer(); > + ReadWriteByte(i2c); > + result = WaitForXfer(i2c); > i = 0; > while ((i < data_len) && (result == I2C_OK)) { > /* disable ACK for final READ */ > if (i == data_len - 1) > writel(readl(&i2c->iiccon) > - & ~0x80, &i2c->iiccon); > - ReadWriteByte(); > - result = WaitForXfer(); > + & ~I2CCON_ACKGEN, > + &i2c->iiccon); > + ReadWriteByte(i2c); > + result = WaitForXfer(i2c); > data[i] = readl(&i2c->iicds); > i++; > } > @@ -316,17 +352,18 @@ int i2c_transfer(unsigned char cmd_type, > /* send START */ > writel(readl(&i2c->iicstat) | I2C_START_STOP, > &i2c->iicstat); > - result = WaitForXfer(); > + result = WaitForXfer(i2c); > > - if (IsACK()) { > + if (IsACK(i2c)) { > i = 0; > while ((i < data_len) && (result == I2C_OK)) { > /* disable ACK for final READ */ > if (i == data_len - 1) > writel(readl(&i2c->iiccon) & > - ~0x80, &i2c->iiccon); > - ReadWriteByte(); > - result = WaitForXfer(); > + ~I2CCON_ACKGEN, > + &i2c->iiccon); > + ReadWriteByte(i2c); > + result = WaitForXfer(i2c); > data[i] = readl(&i2c->iicds); > i++; > } > @@ -337,22 +374,24 @@ int i2c_transfer(unsigned char cmd_type, > > /* send STOP */ > writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); > - ReadWriteByte(); > + ReadWriteByte(i2c); > break; > > default: > - printf("i2c_transfer: bad call\n"); > + debug("i2c_transfer: bad call\n"); > result = I2C_NOK; > break; > } > > - return (result); > + return result; > } > > int i2c_probe(uchar chip) > { > + struct s3c24x0_i2c *i2c; > uchar buf[1]; > > + i2c = get_base_i2c(); > buf[0] = 0; > > /* > @@ -360,16 +399,17 @@ int i2c_probe(uchar chip) > * address was <ACK>ed (i.e. there was a chip at that address which > * drove the data line low). > */ > - return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK; > + return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK; > } > > int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) > { > + struct s3c24x0_i2c *i2c; > uchar xaddr[4]; > int ret; > > if (alen > 4) { > - printf("I2C read: addr len %d not supported\n", alen); > + debug("I2C read: addr len %d not supported\n", alen); > return 1; > } > > @@ -396,10 +436,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) > chip |= ((addr >> (alen * 8)) & > CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); > #endif > - if ((ret = > - i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen, > - buffer, len)) != 0) { > - printf("I2c read: failed %d\n", ret); > + i2c = get_base_i2c(); > + ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen, > + buffer, len); > + if (ret != 0) { > + debug("I2c read: failed %d\n", ret); > return 1; > } > return 0; > @@ -407,10 +448,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) > > int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) > { > + struct s3c24x0_i2c *i2c; > uchar xaddr[4]; > > if (alen > 4) { > - printf("I2C write: addr len %d not supported\n", alen); > + debug("I2C write: addr len %d not supported\n", alen); > return 1; > } > > @@ -436,8 +478,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) > chip |= ((addr >> (alen * 8)) & > CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); > #endif > + i2c = get_base_i2c(); > return (i2c_transfer > - (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, > + (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, > len) != 0); > } > #endif /* CONFIG_HARD_I2C */ > -- > 1.7.4.4 >
Hi Simon Glass, Thank you for comments. On Thu, Jul 19, 2012 at 1:36 AM, Simon Glass <sjg@chromium.org> wrote: > Hi, > > On Thu, Jul 5, 2012 at 12:59 PM, Rajeshwari Shinde > <rajeshwari.s@samsung.com> wrote: >> This patch modifies the S3C I2C driver to suppport EXYNOS5. >> The cahnges made to driver are as follows: >> - I2C base address is passed as a parameter to many >> functions to avoid multiple #ifdef >> - Channel initialisation is moved to a commom funation >> as it is required by i2c_init. >> - Hardcoding for I2CCON_ACKGEN removed. >> - Replaced printf with debug. >> - Checkpatch issues resolved. >> - Pinmux setting will be done in board/samsung/smdk5250/smdk5250.c >> to avoid repeated setting of gpio lines, as it have multi bus support. >> >> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com> >> Signed-off-by: Doug Anderson <dianders@chromium.org> >> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com> >> Acked-by: Simon Glass <sjg@chromium.org> >> --- > > One more comment on this if not too late. I wonder if the > g_current_bus variable could exist for all variants, but always be > zero, so you can get rid of some of the #ifdef EXYNOS5 stuff? It seems > like it might be a harmless change? > -- Will do this change. > Regards, > Simon > >> Changes in V2: >> - Removed #define for I2C cahnnels from hearder file except for I2C0. >> - Incorporated review comments from Simon Glass. >> Changes in V3: >> - Incorporated review comments from Joonyoung Shim. >> - Reduced the number of #ifdef by modifying get_i2c_base function. >> - Removed duplicate code. >> Changes in V4: >> - Resolved build error for s3c2410. >> Changes in V5: >> - Pinmux setting will be done in board/samsung/smdk5250/smdk5250.c >> to avoid repeated setting of gpio lines, as it have multi bus support. >> - I2C bus offset calulation done based on EXYNOS_I2C_SPACING >> - Peripharal related code removed. >> drivers/i2c/s3c24x0_i2c.c | 193 +++++++++++++++++++++++++++----------------- >> 1 files changed, 118 insertions(+), 75 deletions(-) >> >> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c >> index ba6f39b..bbd2ef8 100644 >> --- a/drivers/i2c/s3c24x0_i2c.c >> +++ b/drivers/i2c/s3c24x0_i2c.c >> @@ -27,10 +27,15 @@ >> */ >> >> #include <common.h> >> +#ifdef CONFIG_EXYNOS5 >> +#include <asm/arch/clk.h> >> +#include <asm/arch/cpu.h> >> +#else >> #include <asm/arch/s3c24x0_cpu.h> >> - >> +#endif >> #include <asm/io.h> >> #include <i2c.h> >> +#include "s3c24x0_i2c.h" >> >> #ifdef CONFIG_HARD_I2C >> >> @@ -45,6 +50,7 @@ >> >> #define I2CSTAT_BSY 0x20 /* Busy bit */ >> #define I2CSTAT_NACK 0x01 /* Nack bit */ >> +#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ >> #define I2CCON_IRPND 0x10 /* Interrupt pending bit */ >> #define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ >> #define I2C_MODE_MR 0x80 /* Master Receive Mode */ >> @@ -53,6 +59,10 @@ >> >> #define I2C_TIMEOUT 1 /* 1 second */ >> >> + >> +#ifdef CONFIG_EXYNOS5 >> +static unsigned int g_current_bus; /* Stores Current I2C Bus */ >> +#else >> static int GetI2CSDA(void) >> { >> struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); >> @@ -77,16 +87,17 @@ static void SetI2CSCL(int x) >> struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); >> >> #ifdef CONFIG_S3C2410 >> - writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat); >> + writel((readl(&gpio->gpedat) & ~0x4000) | >> + (x & 1) << 14, &gpio->gpedat); >> #endif >> #ifdef CONFIG_S3C2400 >> writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat); >> #endif >> } >> +#endif >> >> -static int WaitForXfer(void) >> +static int WaitForXfer(struct s3c24x0_i2c *i2c) >> { >> - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); >> int i; >> >> i = I2C_TIMEOUT * 10000; >> @@ -98,35 +109,77 @@ static int WaitForXfer(void) >> return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT; >> } >> >> -static int IsACK(void) >> +static int IsACK(struct s3c24x0_i2c *i2c) >> { >> - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); >> - >> return !(readl(&i2c->iicstat) & I2CSTAT_NACK); >> } >> >> -static void ReadWriteByte(void) >> +static void ReadWriteByte(struct s3c24x0_i2c *i2c) >> { >> - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); >> - >> writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); >> } >> >> +static struct s3c24x0_i2c *get_base_i2c(void) >> +{ >> +#ifdef CONFIG_EXYNOS5 >> + struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c() >> + + (EXYNOS_I2C_SPACING >> + * g_current_bus)); >> + return i2c; >> +#else >> + return s3c24x0_get_base_i2c(); >> +#endif >> +} >> + >> +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) >> +{ >> + ulong freq, pres = 16, div; >> +#ifdef CONFIG_EXYNOS5 >> + freq = get_i2c_clk(); >> +#else >> + freq = get_PCLK(); >> +#endif >> + /* calculate prescaler and divisor values */ >> + if ((freq / pres / (16 + 1)) > speed) >> + /* set prescaler to 512 */ >> + pres = 512; >> + >> + div = 0; >> + while ((freq / pres / (div + 1)) > speed) >> + div++; >> + >> + /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ >> + writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); >> + >> + /* init to SLAVE REVEIVE and set slaveaddr */ >> + writel(0, &i2c->iicstat); >> + writel(slaveadd, &i2c->iicadd); >> + /* program Master Transmit (and implicit STOP) */ >> + writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); >> +} >> + >> void i2c_init(int speed, int slaveadd) >> { >> - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); >> + struct s3c24x0_i2c *i2c = get_base_i2c(); >> +#ifndef CONFIG_EXYNOS5 >> struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); >> - ulong freq, pres = 16, div; >> +#endif >> int i; >> >> - /* wait for some time to give previous transfer a chance to finish */ >> +#ifdef CONFIG_EXYNOS5 >> + /* By default i2c channel 0 is the current bus */ >> + g_current_bus = 0; >> >> + i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); >> +#endif >> + /* wait for some time to give previous transfer a chance to finish */ >> i = I2C_TIMEOUT * 1000; >> while ((readl(&i2c->iicstat) && I2CSTAT_BSY) && (i > 0)) { >> udelay(1000); >> i--; >> } >> >> +#ifndef CONFIG_EXYNOS5 >> if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) { >> #ifdef CONFIG_S3C2410 >> ulong old_gpecon = readl(&gpio->gpecon); >> @@ -171,26 +224,8 @@ void i2c_init(int speed, int slaveadd) >> #endif >> } >> >> - /* calculate prescaler and divisor values */ >> - freq = get_PCLK(); >> - if ((freq / pres / (16 + 1)) > speed) >> - /* set prescaler to 512 */ >> - pres = 512; >> - >> - div = 0; >> - while ((freq / pres / (div + 1)) > speed) >> - div++; >> - >> - /* set prescaler, divisor according to freq, also set >> - * ACKGEN, IRQ */ >> - writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); >> - >> - /* init to SLAVE REVEIVE and set slaveaddr */ >> - writel(0, &i2c->iicstat); >> - writel(slaveadd, &i2c->iicadd); >> - /* program Master Transmit (and implicit STOP) */ >> - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); >> - >> + i2c_ch_init(i2c, speed, slaveadd); >> +#endif /* #ifndef CONFIG_EXYNOS5 */ >> } >> >> /* >> @@ -200,19 +235,19 @@ void i2c_init(int speed, int slaveadd) >> * by the char, we could make it larger if needed. If it is >> * 0 we skip the address write cycle. >> */ >> -static >> -int i2c_transfer(unsigned char cmd_type, >> - unsigned char chip, >> - unsigned char addr[], >> - unsigned char addr_len, >> - unsigned char data[], unsigned short data_len) >> +static int i2c_transfer(struct s3c24x0_i2c *i2c, >> + unsigned char cmd_type, >> + unsigned char chip, >> + unsigned char addr[], >> + unsigned char addr_len, >> + unsigned char data[], >> + unsigned short data_len) >> { >> - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); >> int i, result; >> >> if (data == 0 || data_len == 0) { >> /*Don't support data transfer of no length or to address 0 */ >> - printf("i2c_transfer: bad call\n"); >> + debug("i2c_transfer: bad call\n"); >> return I2C_NOK; >> } >> >> @@ -226,7 +261,7 @@ int i2c_transfer(unsigned char cmd_type, >> if (readl(&i2c->iicstat) & I2CSTAT_BSY) >> return I2C_NOK_TOUT; >> >> - writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon); >> + writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); >> result = I2C_OK; >> >> switch (cmd_type) { >> @@ -238,16 +273,16 @@ int i2c_transfer(unsigned char cmd_type, >> &i2c->iicstat); >> i = 0; >> while ((i < addr_len) && (result == I2C_OK)) { >> - result = WaitForXfer(); >> + result = WaitForXfer(i2c); >> writel(addr[i], &i2c->iicds); >> - ReadWriteByte(); >> + ReadWriteByte(i2c); >> i++; >> } >> i = 0; >> while ((i < data_len) && (result == I2C_OK)) { >> - result = WaitForXfer(); >> + result = WaitForXfer(i2c); >> writel(data[i], &i2c->iicds); >> - ReadWriteByte(); >> + ReadWriteByte(i2c); >> i++; >> } >> } else { >> @@ -257,19 +292,19 @@ int i2c_transfer(unsigned char cmd_type, >> &i2c->iicstat); >> i = 0; >> while ((i < data_len) && (result = I2C_OK)) { >> - result = WaitForXfer(); >> + result = WaitForXfer(i2c); >> writel(data[i], &i2c->iicds); >> - ReadWriteByte(); >> + ReadWriteByte(i2c); >> i++; >> } >> } >> >> if (result == I2C_OK) >> - result = WaitForXfer(); >> + result = WaitForXfer(i2c); >> >> /* send STOP */ >> writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); >> - ReadWriteByte(); >> + ReadWriteByte(i2c); >> break; >> >> case I2C_READ: >> @@ -279,13 +314,13 @@ int i2c_transfer(unsigned char cmd_type, >> /* send START */ >> writel(readl(&i2c->iicstat) | I2C_START_STOP, >> &i2c->iicstat); >> - result = WaitForXfer(); >> - if (IsACK()) { >> + result = WaitForXfer(i2c); >> + if (IsACK(i2c)) { >> i = 0; >> while ((i < addr_len) && (result == I2C_OK)) { >> writel(addr[i], &i2c->iicds); >> - ReadWriteByte(); >> - result = WaitForXfer(); >> + ReadWriteByte(i2c); >> + result = WaitForXfer(i2c); >> i++; >> } >> >> @@ -293,16 +328,17 @@ int i2c_transfer(unsigned char cmd_type, >> /* resend START */ >> writel(I2C_MODE_MR | I2C_TXRX_ENA | >> I2C_START_STOP, &i2c->iicstat); >> - ReadWriteByte(); >> - result = WaitForXfer(); >> + ReadWriteByte(i2c); >> + result = WaitForXfer(i2c); >> i = 0; >> while ((i < data_len) && (result == I2C_OK)) { >> /* disable ACK for final READ */ >> if (i == data_len - 1) >> writel(readl(&i2c->iiccon) >> - & ~0x80, &i2c->iiccon); >> - ReadWriteByte(); >> - result = WaitForXfer(); >> + & ~I2CCON_ACKGEN, >> + &i2c->iiccon); >> + ReadWriteByte(i2c); >> + result = WaitForXfer(i2c); >> data[i] = readl(&i2c->iicds); >> i++; >> } >> @@ -316,17 +352,18 @@ int i2c_transfer(unsigned char cmd_type, >> /* send START */ >> writel(readl(&i2c->iicstat) | I2C_START_STOP, >> &i2c->iicstat); >> - result = WaitForXfer(); >> + result = WaitForXfer(i2c); >> >> - if (IsACK()) { >> + if (IsACK(i2c)) { >> i = 0; >> while ((i < data_len) && (result == I2C_OK)) { >> /* disable ACK for final READ */ >> if (i == data_len - 1) >> writel(readl(&i2c->iiccon) & >> - ~0x80, &i2c->iiccon); >> - ReadWriteByte(); >> - result = WaitForXfer(); >> + ~I2CCON_ACKGEN, >> + &i2c->iiccon); >> + ReadWriteByte(i2c); >> + result = WaitForXfer(i2c); >> data[i] = readl(&i2c->iicds); >> i++; >> } >> @@ -337,22 +374,24 @@ int i2c_transfer(unsigned char cmd_type, >> >> /* send STOP */ >> writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); >> - ReadWriteByte(); >> + ReadWriteByte(i2c); >> break; >> >> default: >> - printf("i2c_transfer: bad call\n"); >> + debug("i2c_transfer: bad call\n"); >> result = I2C_NOK; >> break; >> } >> >> - return (result); >> + return result; >> } >> >> int i2c_probe(uchar chip) >> { >> + struct s3c24x0_i2c *i2c; >> uchar buf[1]; >> >> + i2c = get_base_i2c(); >> buf[0] = 0; >> >> /* >> @@ -360,16 +399,17 @@ int i2c_probe(uchar chip) >> * address was <ACK>ed (i.e. there was a chip at that address which >> * drove the data line low). >> */ >> - return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK; >> + return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK; >> } >> >> int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) >> { >> + struct s3c24x0_i2c *i2c; >> uchar xaddr[4]; >> int ret; >> >> if (alen > 4) { >> - printf("I2C read: addr len %d not supported\n", alen); >> + debug("I2C read: addr len %d not supported\n", alen); >> return 1; >> } >> >> @@ -396,10 +436,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) >> chip |= ((addr >> (alen * 8)) & >> CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); >> #endif >> - if ((ret = >> - i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen, >> - buffer, len)) != 0) { >> - printf("I2c read: failed %d\n", ret); >> + i2c = get_base_i2c(); >> + ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen, >> + buffer, len); >> + if (ret != 0) { >> + debug("I2c read: failed %d\n", ret); >> return 1; >> } >> return 0; >> @@ -407,10 +448,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) >> >> int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) >> { >> + struct s3c24x0_i2c *i2c; >> uchar xaddr[4]; >> >> if (alen > 4) { >> - printf("I2C write: addr len %d not supported\n", alen); >> + debug("I2C write: addr len %d not supported\n", alen); >> return 1; >> } >> >> @@ -436,8 +478,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) >> chip |= ((addr >> (alen * 8)) & >> CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); >> #endif >> + i2c = get_base_i2c(); >> return (i2c_transfer >> - (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, >> + (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, >> len) != 0); >> } >> #endif /* CONFIG_HARD_I2C */ >> -- >> 1.7.4.4 >> > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot Regards, Rajeshwari Shinde.
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index ba6f39b..bbd2ef8 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -27,10 +27,15 @@ */ #include <common.h> +#ifdef CONFIG_EXYNOS5 +#include <asm/arch/clk.h> +#include <asm/arch/cpu.h> +#else #include <asm/arch/s3c24x0_cpu.h> - +#endif #include <asm/io.h> #include <i2c.h> +#include "s3c24x0_i2c.h" #ifdef CONFIG_HARD_I2C @@ -45,6 +50,7 @@ #define I2CSTAT_BSY 0x20 /* Busy bit */ #define I2CSTAT_NACK 0x01 /* Nack bit */ +#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ #define I2CCON_IRPND 0x10 /* Interrupt pending bit */ #define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ #define I2C_MODE_MR 0x80 /* Master Receive Mode */ @@ -53,6 +59,10 @@ #define I2C_TIMEOUT 1 /* 1 second */ + +#ifdef CONFIG_EXYNOS5 +static unsigned int g_current_bus; /* Stores Current I2C Bus */ +#else static int GetI2CSDA(void) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); @@ -77,16 +87,17 @@ static void SetI2CSCL(int x) struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); #ifdef CONFIG_S3C2410 - writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat); + writel((readl(&gpio->gpedat) & ~0x4000) | + (x & 1) << 14, &gpio->gpedat); #endif #ifdef CONFIG_S3C2400 writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat); #endif } +#endif -static int WaitForXfer(void) +static int WaitForXfer(struct s3c24x0_i2c *i2c) { - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); int i; i = I2C_TIMEOUT * 10000; @@ -98,35 +109,77 @@ static int WaitForXfer(void) return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT; } -static int IsACK(void) +static int IsACK(struct s3c24x0_i2c *i2c) { - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); - return !(readl(&i2c->iicstat) & I2CSTAT_NACK); } -static void ReadWriteByte(void) +static void ReadWriteByte(struct s3c24x0_i2c *i2c) { - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); - writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); } +static struct s3c24x0_i2c *get_base_i2c(void) +{ +#ifdef CONFIG_EXYNOS5 + struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c() + + (EXYNOS_I2C_SPACING + * g_current_bus)); + return i2c; +#else + return s3c24x0_get_base_i2c(); +#endif +} + +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) +{ + ulong freq, pres = 16, div; +#ifdef CONFIG_EXYNOS5 + freq = get_i2c_clk(); +#else + freq = get_PCLK(); +#endif + /* calculate prescaler and divisor values */ + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; + + div = 0; + while ((freq / pres / (div + 1)) > speed) + div++; + + /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ + writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); + + /* init to SLAVE REVEIVE and set slaveaddr */ + writel(0, &i2c->iicstat); + writel(slaveadd, &i2c->iicadd); + /* program Master Transmit (and implicit STOP) */ + writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); +} + void i2c_init(int speed, int slaveadd) { - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); + struct s3c24x0_i2c *i2c = get_base_i2c(); +#ifndef CONFIG_EXYNOS5 struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); - ulong freq, pres = 16, div; +#endif int i; - /* wait for some time to give previous transfer a chance to finish */ +#ifdef CONFIG_EXYNOS5 + /* By default i2c channel 0 is the current bus */ + g_current_bus = 0; + i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif + /* wait for some time to give previous transfer a chance to finish */ i = I2C_TIMEOUT * 1000; while ((readl(&i2c->iicstat) && I2CSTAT_BSY) && (i > 0)) { udelay(1000); i--; } +#ifndef CONFIG_EXYNOS5 if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) { #ifdef CONFIG_S3C2410 ulong old_gpecon = readl(&gpio->gpecon); @@ -171,26 +224,8 @@ void i2c_init(int speed, int slaveadd) #endif } - /* calculate prescaler and divisor values */ - freq = get_PCLK(); - if ((freq / pres / (16 + 1)) > speed) - /* set prescaler to 512 */ - pres = 512; - - div = 0; - while ((freq / pres / (div + 1)) > speed) - div++; - - /* set prescaler, divisor according to freq, also set - * ACKGEN, IRQ */ - writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); - - /* init to SLAVE REVEIVE and set slaveaddr */ - writel(0, &i2c->iicstat); - writel(slaveadd, &i2c->iicadd); - /* program Master Transmit (and implicit STOP) */ - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); - + i2c_ch_init(i2c, speed, slaveadd); +#endif /* #ifndef CONFIG_EXYNOS5 */ } /* @@ -200,19 +235,19 @@ void i2c_init(int speed, int slaveadd) * by the char, we could make it larger if needed. If it is * 0 we skip the address write cycle. */ -static -int i2c_transfer(unsigned char cmd_type, - unsigned char chip, - unsigned char addr[], - unsigned char addr_len, - unsigned char data[], unsigned short data_len) +static int i2c_transfer(struct s3c24x0_i2c *i2c, + unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], + unsigned short data_len) { - struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c(); int i, result; if (data == 0 || data_len == 0) { /*Don't support data transfer of no length or to address 0 */ - printf("i2c_transfer: bad call\n"); + debug("i2c_transfer: bad call\n"); return I2C_NOK; } @@ -226,7 +261,7 @@ int i2c_transfer(unsigned char cmd_type, if (readl(&i2c->iicstat) & I2CSTAT_BSY) return I2C_NOK_TOUT; - writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon); + writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); result = I2C_OK; switch (cmd_type) { @@ -238,16 +273,16 @@ int i2c_transfer(unsigned char cmd_type, &i2c->iicstat); i = 0; while ((i < addr_len) && (result == I2C_OK)) { - result = WaitForXfer(); + result = WaitForXfer(i2c); writel(addr[i], &i2c->iicds); - ReadWriteByte(); + ReadWriteByte(i2c); i++; } i = 0; while ((i < data_len) && (result == I2C_OK)) { - result = WaitForXfer(); + result = WaitForXfer(i2c); writel(data[i], &i2c->iicds); - ReadWriteByte(); + ReadWriteByte(i2c); i++; } } else { @@ -257,19 +292,19 @@ int i2c_transfer(unsigned char cmd_type, &i2c->iicstat); i = 0; while ((i < data_len) && (result = I2C_OK)) { - result = WaitForXfer(); + result = WaitForXfer(i2c); writel(data[i], &i2c->iicds); - ReadWriteByte(); + ReadWriteByte(i2c); i++; } } if (result == I2C_OK) - result = WaitForXfer(); + result = WaitForXfer(i2c); /* send STOP */ writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); - ReadWriteByte(); + ReadWriteByte(i2c); break; case I2C_READ: @@ -279,13 +314,13 @@ int i2c_transfer(unsigned char cmd_type, /* send START */ writel(readl(&i2c->iicstat) | I2C_START_STOP, &i2c->iicstat); - result = WaitForXfer(); - if (IsACK()) { + result = WaitForXfer(i2c); + if (IsACK(i2c)) { i = 0; while ((i < addr_len) && (result == I2C_OK)) { writel(addr[i], &i2c->iicds); - ReadWriteByte(); - result = WaitForXfer(); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); i++; } @@ -293,16 +328,17 @@ int i2c_transfer(unsigned char cmd_type, /* resend START */ writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP, &i2c->iicstat); - ReadWriteByte(); - result = WaitForXfer(); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); i = 0; while ((i < data_len) && (result == I2C_OK)) { /* disable ACK for final READ */ if (i == data_len - 1) writel(readl(&i2c->iiccon) - & ~0x80, &i2c->iiccon); - ReadWriteByte(); - result = WaitForXfer(); + & ~I2CCON_ACKGEN, + &i2c->iiccon); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); data[i] = readl(&i2c->iicds); i++; } @@ -316,17 +352,18 @@ int i2c_transfer(unsigned char cmd_type, /* send START */ writel(readl(&i2c->iicstat) | I2C_START_STOP, &i2c->iicstat); - result = WaitForXfer(); + result = WaitForXfer(i2c); - if (IsACK()) { + if (IsACK(i2c)) { i = 0; while ((i < data_len) && (result == I2C_OK)) { /* disable ACK for final READ */ if (i == data_len - 1) writel(readl(&i2c->iiccon) & - ~0x80, &i2c->iiccon); - ReadWriteByte(); - result = WaitForXfer(); + ~I2CCON_ACKGEN, + &i2c->iiccon); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); data[i] = readl(&i2c->iicds); i++; } @@ -337,22 +374,24 @@ int i2c_transfer(unsigned char cmd_type, /* send STOP */ writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); - ReadWriteByte(); + ReadWriteByte(i2c); break; default: - printf("i2c_transfer: bad call\n"); + debug("i2c_transfer: bad call\n"); result = I2C_NOK; break; } - return (result); + return result; } int i2c_probe(uchar chip) { + struct s3c24x0_i2c *i2c; uchar buf[1]; + i2c = get_base_i2c(); buf[0] = 0; /* @@ -360,16 +399,17 @@ int i2c_probe(uchar chip) * address was <ACK>ed (i.e. there was a chip at that address which * drove the data line low). */ - return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK; + return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK; } int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) { + struct s3c24x0_i2c *i2c; uchar xaddr[4]; int ret; if (alen > 4) { - printf("I2C read: addr len %d not supported\n", alen); + debug("I2C read: addr len %d not supported\n", alen); return 1; } @@ -396,10 +436,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); #endif - if ((ret = - i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen, - buffer, len)) != 0) { - printf("I2c read: failed %d\n", ret); + i2c = get_base_i2c(); + ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen, + buffer, len); + if (ret != 0) { + debug("I2c read: failed %d\n", ret); return 1; } return 0; @@ -407,10 +448,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) { + struct s3c24x0_i2c *i2c; uchar xaddr[4]; if (alen > 4) { - printf("I2C write: addr len %d not supported\n", alen); + debug("I2C write: addr len %d not supported\n", alen); return 1; } @@ -436,8 +478,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); #endif + i2c = get_base_i2c(); return (i2c_transfer - (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, + (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, len) != 0); } #endif /* CONFIG_HARD_I2C */