From 3f4358da8d42e407a3fb583b7b3ea7033090e0cd Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 21 Apr 2016 08:19:40 +0200 Subject: [PATCH] i2c: designware_i2c: Prepare for DM driver conversion This patch prepares the designware I2C driver for the DM conversion. This is mainly done by removing struct i2c_adapter from the functions that shall be used by the DM driver version as well. Signed-off-by: Stefan Roese Reviewed-by: Simon Glass Reviewed-by: Bin Meng Cc: Marek Vasut Cc: Heiko Schocher --- drivers/i2c/designware_i2c.c | 471 ++++++++++++++++++----------------- 1 file changed, 239 insertions(+), 232 deletions(-) diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index 035bf23dfc..2adc36e3b7 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -10,30 +10,6 @@ #include #include "designware_i2c.h" -static struct i2c_regs *i2c_get_base(struct i2c_adapter *adap) -{ - switch (adap->hwadapnr) { -#if CONFIG_SYS_I2C_BUS_MAX >= 4 - case 3: - return (struct i2c_regs *)CONFIG_SYS_I2C_BASE3; -#endif -#if CONFIG_SYS_I2C_BUS_MAX >= 3 - case 2: - return (struct i2c_regs *)CONFIG_SYS_I2C_BASE2; -#endif -#if CONFIG_SYS_I2C_BUS_MAX >= 2 - case 1: - return (struct i2c_regs *)CONFIG_SYS_I2C_BASE1; -#endif - case 0: - return (struct i2c_regs *)CONFIG_SYS_I2C_BASE; - default: - printf("Wrong I2C-adapter number %d\n", adap->hwadapnr); - } - - return NULL; -} - static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable) { u32 ena = enable ? IC_ENABLE_0B : 0; @@ -61,10 +37,9 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable) * * Set the i2c speed. */ -static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap, - unsigned int speed) +static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base, + unsigned int speed) { - struct i2c_regs *i2c_base = i2c_get_base(adap); unsigned int cntl; unsigned int hcnt, lcnt; int i2c_spd; @@ -113,11 +88,243 @@ static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap, /* Enable back i2c now speed set */ dw_i2c_enable(i2c_base, true); - adap->speed = speed; + return 0; +} + +/* + * i2c_setaddress - Sets the target slave address + * @i2c_addr: target i2c address + * + * Sets the target slave address. + */ +static void i2c_setaddress(struct i2c_regs *i2c_base, unsigned int i2c_addr) +{ + /* Disable i2c */ + dw_i2c_enable(i2c_base, false); + + writel(i2c_addr, &i2c_base->ic_tar); + + /* Enable i2c */ + dw_i2c_enable(i2c_base, true); +} + +/* + * i2c_flush_rxfifo - Flushes the i2c RX FIFO + * + * Flushes the i2c RX FIFO + */ +static void i2c_flush_rxfifo(struct i2c_regs *i2c_base) +{ + while (readl(&i2c_base->ic_status) & IC_STATUS_RFNE) + readl(&i2c_base->ic_cmd_data); +} + +/* + * i2c_wait_for_bb - Waits for bus busy + * + * Waits for bus busy + */ +static int i2c_wait_for_bb(struct i2c_regs *i2c_base) +{ + unsigned long start_time_bb = get_timer(0); + + while ((readl(&i2c_base->ic_status) & IC_STATUS_MA) || + !(readl(&i2c_base->ic_status) & IC_STATUS_TFE)) { + + /* Evaluate timeout */ + if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB)) + return 1; + } return 0; } +static int i2c_xfer_init(struct i2c_regs *i2c_base, uchar chip, uint addr, + int alen) +{ + if (i2c_wait_for_bb(i2c_base)) + return 1; + + i2c_setaddress(i2c_base, chip); + while (alen) { + alen--; + /* high byte address going out first */ + writel((addr >> (alen * 8)) & 0xff, + &i2c_base->ic_cmd_data); + } + return 0; +} + +static int i2c_xfer_finish(struct i2c_regs *i2c_base) +{ + ulong start_stop_det = get_timer(0); + + while (1) { + if ((readl(&i2c_base->ic_raw_intr_stat) & IC_STOP_DET)) { + readl(&i2c_base->ic_clr_stop_det); + break; + } else if (get_timer(start_stop_det) > I2C_STOPDET_TO) { + break; + } + } + + if (i2c_wait_for_bb(i2c_base)) { + printf("Timed out waiting for bus\n"); + return 1; + } + + i2c_flush_rxfifo(i2c_base); + + return 0; +} + +/* + * i2c_read - Read from i2c memory + * @chip: target i2c address + * @addr: address to read from + * @alen: + * @buffer: buffer for read data + * @len: no of bytes to be read + * + * Read from i2c memory. + */ +static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr, + int alen, u8 *buffer, int len) +{ + unsigned long start_time_rx; + +#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. + */ + dev |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); + addr &= ~(CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW << (alen * 8)); + + debug("%s: fix addr_overflow: dev %02x addr %02x\n", __func__, dev, + addr); +#endif + + if (i2c_xfer_init(i2c_base, dev, addr, alen)) + return 1; + + start_time_rx = get_timer(0); + while (len) { + if (len == 1) + writel(IC_CMD | IC_STOP, &i2c_base->ic_cmd_data); + else + writel(IC_CMD, &i2c_base->ic_cmd_data); + + if (readl(&i2c_base->ic_status) & IC_STATUS_RFNE) { + *buffer++ = (uchar)readl(&i2c_base->ic_cmd_data); + len--; + start_time_rx = get_timer(0); + + } else if (get_timer(start_time_rx) > I2C_BYTE_TO) { + return 1; + } + } + + return i2c_xfer_finish(i2c_base); +} + +/* + * i2c_write - Write to i2c memory + * @chip: target i2c address + * @addr: address to read from + * @alen: + * @buffer: buffer for read data + * @len: no of bytes to be read + * + * Write to i2c memory. + */ +static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr, + int alen, u8 *buffer, int len) +{ + int nb = len; + unsigned long start_time_tx; + +#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. + */ + dev |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); + addr &= ~(CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW << (alen * 8)); + + debug("%s: fix addr_overflow: dev %02x addr %02x\n", __func__, dev, + addr); +#endif + + if (i2c_xfer_init(i2c_base, dev, addr, alen)) + return 1; + + start_time_tx = get_timer(0); + while (len) { + if (readl(&i2c_base->ic_status) & IC_STATUS_TFNF) { + if (--len == 0) { + writel(*buffer | IC_STOP, + &i2c_base->ic_cmd_data); + } else { + writel(*buffer, &i2c_base->ic_cmd_data); + } + buffer++; + start_time_tx = get_timer(0); + + } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) { + printf("Timed out. i2c write Failed\n"); + return 1; + } + } + + return i2c_xfer_finish(i2c_base); +} + +static struct i2c_regs *i2c_get_base(struct i2c_adapter *adap) +{ + switch (adap->hwadapnr) { +#if CONFIG_SYS_I2C_BUS_MAX >= 4 + case 3: + return (struct i2c_regs *)CONFIG_SYS_I2C_BASE3; +#endif +#if CONFIG_SYS_I2C_BUS_MAX >= 3 + case 2: + return (struct i2c_regs *)CONFIG_SYS_I2C_BASE2; +#endif +#if CONFIG_SYS_I2C_BUS_MAX >= 2 + case 1: + return (struct i2c_regs *)CONFIG_SYS_I2C_BASE1; +#endif + case 0: + return (struct i2c_regs *)CONFIG_SYS_I2C_BASE; + default: + printf("Wrong I2C-adapter number %d\n", adap->hwadapnr); + } + + return NULL; +} + +static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int speed) +{ + adap->speed = speed; + return __dw_i2c_set_bus_speed(i2c_get_base(adap), speed); +} + /* * i2c_init - Init function * @speed: required i2c speed @@ -144,217 +351,16 @@ static void dw_i2c_init(struct i2c_adapter *adap, int speed, dw_i2c_enable(i2c_base, true); } -/* - * i2c_setaddress - Sets the target slave address - * @i2c_addr: target i2c address - * - * Sets the target slave address. - */ -static void i2c_setaddress(struct i2c_adapter *adap, unsigned int i2c_addr) -{ - struct i2c_regs *i2c_base = i2c_get_base(adap); - - /* Disable i2c */ - dw_i2c_enable(i2c_base, false); - - writel(i2c_addr, &i2c_base->ic_tar); - - /* Enable i2c */ - dw_i2c_enable(i2c_base, true); -} - -/* - * i2c_flush_rxfifo - Flushes the i2c RX FIFO - * - * Flushes the i2c RX FIFO - */ -static void i2c_flush_rxfifo(struct i2c_adapter *adap) -{ - struct i2c_regs *i2c_base = i2c_get_base(adap); - - while (readl(&i2c_base->ic_status) & IC_STATUS_RFNE) - readl(&i2c_base->ic_cmd_data); -} - -/* - * i2c_wait_for_bb - Waits for bus busy - * - * Waits for bus busy - */ -static int i2c_wait_for_bb(struct i2c_adapter *adap) -{ - struct i2c_regs *i2c_base = i2c_get_base(adap); - unsigned long start_time_bb = get_timer(0); - - while ((readl(&i2c_base->ic_status) & IC_STATUS_MA) || - !(readl(&i2c_base->ic_status) & IC_STATUS_TFE)) { - - /* Evaluate timeout */ - if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB)) - return 1; - } - - return 0; -} - -static int i2c_xfer_init(struct i2c_adapter *adap, uchar chip, uint addr, - int alen) -{ - struct i2c_regs *i2c_base = i2c_get_base(adap); - - if (i2c_wait_for_bb(adap)) - return 1; - - i2c_setaddress(adap, chip); - while (alen) { - alen--; - /* high byte address going out first */ - writel((addr >> (alen * 8)) & 0xff, - &i2c_base->ic_cmd_data); - } - return 0; -} - -static int i2c_xfer_finish(struct i2c_adapter *adap) -{ - struct i2c_regs *i2c_base = i2c_get_base(adap); - ulong start_stop_det = get_timer(0); - - while (1) { - if ((readl(&i2c_base->ic_raw_intr_stat) & IC_STOP_DET)) { - readl(&i2c_base->ic_clr_stop_det); - break; - } else if (get_timer(start_stop_det) > I2C_STOPDET_TO) { - break; - } - } - - if (i2c_wait_for_bb(adap)) { - printf("Timed out waiting for bus\n"); - return 1; - } - - i2c_flush_rxfifo(adap); - - return 0; -} - -/* - * i2c_read - Read from i2c memory - * @chip: target i2c address - * @addr: address to read from - * @alen: - * @buffer: buffer for read data - * @len: no of bytes to be read - * - * Read from i2c memory. - */ static int dw_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *buffer, int len) { - struct i2c_regs *i2c_base = i2c_get_base(adap); - unsigned long start_time_rx; - -#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. - */ - dev |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); - addr &= ~(CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW << (alen * 8)); - - debug("%s: fix addr_overflow: dev %02x addr %02x\n", __func__, dev, - addr); -#endif - - if (i2c_xfer_init(adap, dev, addr, alen)) - return 1; - - start_time_rx = get_timer(0); - while (len) { - if (len == 1) - writel(IC_CMD | IC_STOP, &i2c_base->ic_cmd_data); - else - writel(IC_CMD, &i2c_base->ic_cmd_data); - - if (readl(&i2c_base->ic_status) & IC_STATUS_RFNE) { - *buffer++ = (uchar)readl(&i2c_base->ic_cmd_data); - len--; - start_time_rx = get_timer(0); - - } else if (get_timer(start_time_rx) > I2C_BYTE_TO) { - return 1; - } - } - - return i2c_xfer_finish(adap); + return __dw_i2c_read(i2c_get_base(adap), dev, addr, alen, buffer, len); } -/* - * i2c_write - Write to i2c memory - * @chip: target i2c address - * @addr: address to read from - * @alen: - * @buffer: buffer for read data - * @len: no of bytes to be read - * - * Write to i2c memory. - */ static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, int alen, u8 *buffer, int len) { - struct i2c_regs *i2c_base = i2c_get_base(adap); - int nb = len; - unsigned long start_time_tx; - -#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. - */ - dev |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); - addr &= ~(CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW << (alen * 8)); - - debug("%s: fix addr_overflow: dev %02x addr %02x\n", __func__, dev, - addr); -#endif - - if (i2c_xfer_init(adap, dev, addr, alen)) - return 1; - - start_time_tx = get_timer(0); - while (len) { - if (readl(&i2c_base->ic_status) & IC_STATUS_TFNF) { - if (--len == 0) { - writel(*buffer | IC_STOP, - &i2c_base->ic_cmd_data); - } else { - writel(*buffer, &i2c_base->ic_cmd_data); - } - buffer++; - start_time_tx = get_timer(0); - - } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) { - printf("Timed out. i2c write Failed\n"); - return 1; - } - } - - return i2c_xfer_finish(adap); + return __dw_i2c_write(i2c_get_base(adap), dev, addr, alen, buffer, len); } /* @@ -362,13 +368,14 @@ static int dw_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, */ static int dw_i2c_probe(struct i2c_adapter *adap, u8 dev) { + struct i2c_regs *i2c_base = i2c_get_base(adap); u32 tmp; int ret; /* * Try to read the first location of the chip. */ - ret = dw_i2c_read(adap, dev, 0, 1, (uchar *)&tmp, 1); + ret = __dw_i2c_read(i2c_base, dev, 0, 1, (uchar *)&tmp, 1); if (ret) dw_i2c_init(adap, adap->speed, adap->slaveaddr);