From 031ed2fa748ccfc746bd0e0073f8690c84a0d7b6 Mon Sep 17 00:00:00 2001 From: Vipin KUMAR Date: Sun, 26 Feb 2012 23:13:29 +0000 Subject: i2c: Add support for designware i2c controller Earlier, a driver exists in the u-boot source for designware i2c interface. That driver was specific to spear platforms. This patch implements the i2c controller as a generic driver which can be used by multiple platforms The driver files are now renamed to designware_i2c.c and designware_i2c.h and these are moved into drivers/i2c folder for reusability by other platforms Signed-off-by: Vipin Kumar Signed-off-by: Amit Virdi diff --git a/arch/arm/include/asm/arch-spear/spr_i2c.h b/arch/arm/include/asm/arch-spear/spr_i2c.h deleted file mode 100644 index 7521ebc..0000000 --- a/arch/arm/include/asm/arch-spear/spr_i2c.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * (C) Copyright 2009 - * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __SPR_I2C_H_ -#define __SPR_I2C_H_ - -struct i2c_regs { - u32 ic_con; - u32 ic_tar; - u32 ic_sar; - u32 ic_hs_maddr; - u32 ic_cmd_data; - u32 ic_ss_scl_hcnt; - u32 ic_ss_scl_lcnt; - u32 ic_fs_scl_hcnt; - u32 ic_fs_scl_lcnt; - u32 ic_hs_scl_hcnt; - u32 ic_hs_scl_lcnt; - u32 ic_intr_stat; - u32 ic_intr_mask; - u32 ic_raw_intr_stat; - u32 ic_rx_tl; - u32 ic_tx_tl; - u32 ic_clr_intr; - u32 ic_clr_rx_under; - u32 ic_clr_rx_over; - u32 ic_clr_tx_over; - u32 ic_clr_rd_req; - u32 ic_clr_tx_abrt; - u32 ic_clr_rx_done; - u32 ic_clr_activity; - u32 ic_clr_stop_det; - u32 ic_clr_start_det; - u32 ic_clr_gen_call; - u32 ic_enable; - u32 ic_status; - u32 ic_txflr; - u32 ix_rxflr; - u32 reserved_1; - u32 ic_tx_abrt_source; -}; - -#define IC_CLK 166 -#define NANO_TO_MICRO 1000 - -/* High and low times in different speed modes (in ns) */ -#define MIN_SS_SCL_HIGHTIME 4000 -#define MIN_SS_SCL_LOWTIME 5000 -#define MIN_FS_SCL_HIGHTIME 800 -#define MIN_FS_SCL_LOWTIME 1700 -#define MIN_HS_SCL_HIGHTIME 60 -#define MIN_HS_SCL_LOWTIME 160 - -/* Worst case timeout for 1 byte is kept as 2ms */ -#define I2C_BYTE_TO (CONFIG_SYS_HZ/500) -#define I2C_STOPDET_TO (CONFIG_SYS_HZ/500) -#define I2C_BYTE_TO_BB (I2C_BYTE_TO * 16) - -/* i2c control register definitions */ -#define IC_CON_SD 0x0040 -#define IC_CON_RE 0x0020 -#define IC_CON_10BITADDRMASTER 0x0010 -#define IC_CON_10BITADDR_SLAVE 0x0008 -#define IC_CON_SPD_MSK 0x0006 -#define IC_CON_SPD_SS 0x0002 -#define IC_CON_SPD_FS 0x0004 -#define IC_CON_SPD_HS 0x0006 -#define IC_CON_MM 0x0001 - -/* i2c target address register definitions */ -#define TAR_ADDR 0x0050 - -/* i2c slave address register definitions */ -#define IC_SLAVE_ADDR 0x0002 - -/* i2c data buffer and command register definitions */ -#define IC_CMD 0x0100 - -/* i2c interrupt status register definitions */ -#define IC_GEN_CALL 0x0800 -#define IC_START_DET 0x0400 -#define IC_STOP_DET 0x0200 -#define IC_ACTIVITY 0x0100 -#define IC_RX_DONE 0x0080 -#define IC_TX_ABRT 0x0040 -#define IC_RD_REQ 0x0020 -#define IC_TX_EMPTY 0x0010 -#define IC_TX_OVER 0x0008 -#define IC_RX_FULL 0x0004 -#define IC_RX_OVER 0x0002 -#define IC_RX_UNDER 0x0001 - -/* fifo threshold register definitions */ -#define IC_TL0 0x00 -#define IC_TL1 0x01 -#define IC_TL2 0x02 -#define IC_TL3 0x03 -#define IC_TL4 0x04 -#define IC_TL5 0x05 -#define IC_TL6 0x06 -#define IC_TL7 0x07 -#define IC_RX_TL IC_TL0 -#define IC_TX_TL IC_TL0 - -/* i2c enable register definitions */ -#define IC_ENABLE_0B 0x0001 - -/* i2c status register definitions */ -#define IC_STATUS_SA 0x0040 -#define IC_STATUS_MA 0x0020 -#define IC_STATUS_RFF 0x0010 -#define IC_STATUS_RFNE 0x0008 -#define IC_STATUS_TFE 0x0004 -#define IC_STATUS_TFNF 0x0002 -#define IC_STATUS_ACT 0x0001 - -/* Speed Selection */ -#define IC_SPEED_MODE_STANDARD 1 -#define IC_SPEED_MODE_FAST 2 -#define IC_SPEED_MODE_MAX 3 - -#define I2C_MAX_SPEED 3400000 -#define I2C_FAST_SPEED 400000 -#define I2C_STANDARD_SPEED 100000 - -#endif /* __SPR_I2C_H_ */ diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 42913f7..5dbdbe3 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libi2c.o COBJS-$(CONFIG_BFIN_TWI_I2C) += bfin-twi_i2c.o COBJS-$(CONFIG_DRIVER_DAVINCI_I2C) += davinci_i2c.o +COBJS-$(CONFIG_DW_I2C) += designware_i2c.o COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o COBJS-$(CONFIG_I2C_MV) += mv_i2c.o @@ -40,7 +41,6 @@ COBJS-$(CONFIG_PPC4XX_I2C) += ppc4xx_i2c.o COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o -COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o COBJS-$(CONFIG_TEGRA_I2C) += tegra_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c new file mode 100644 index 0000000..d352146 --- /dev/null +++ b/drivers/i2c/designware_i2c.c @@ -0,0 +1,331 @@ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include "designware_i2c.h" + +static struct i2c_regs *const i2c_regs_p = + (struct i2c_regs *)CONFIG_SYS_I2C_BASE; + +/* + * set_speed - Set the i2c speed mode (standard, high, fast) + * @i2c_spd: required i2c speed mode + * + * Set the i2c speed mode (standard, high, fast) + */ +static void set_speed(int i2c_spd) +{ + unsigned int cntl; + unsigned int hcnt, lcnt; + unsigned int high, low; + + cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK)); + + switch (i2c_spd) { + case IC_SPEED_MODE_MAX: + cntl |= IC_CON_SPD_HS; + high = MIN_HS_SCL_HIGHTIME; + low = MIN_HS_SCL_LOWTIME; + break; + + case IC_SPEED_MODE_STANDARD: + cntl |= IC_CON_SPD_SS; + high = MIN_SS_SCL_HIGHTIME; + low = MIN_SS_SCL_LOWTIME; + break; + + case IC_SPEED_MODE_FAST: + default: + cntl |= IC_CON_SPD_FS; + high = MIN_FS_SCL_HIGHTIME; + low = MIN_FS_SCL_LOWTIME; + break; + } + + writel(cntl, &i2c_regs_p->ic_con); + + hcnt = (IC_CLK * high) / NANO_TO_MICRO; + writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt); + + lcnt = (IC_CLK * low) / NANO_TO_MICRO; + writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt); +} + +/* + * i2c_set_bus_speed - Set the i2c speed + * @speed: required i2c speed + * + * Set the i2c speed. + */ +void i2c_set_bus_speed(int speed) +{ + if (speed >= I2C_MAX_SPEED) + set_speed(IC_SPEED_MODE_MAX); + else if (speed >= I2C_FAST_SPEED) + set_speed(IC_SPEED_MODE_FAST); + else + set_speed(IC_SPEED_MODE_STANDARD); +} + +/* + * i2c_get_bus_speed - Gets the i2c speed + * + * Gets the i2c speed. + */ +int i2c_get_bus_speed(void) +{ + u32 cntl; + + cntl = (readl(&i2c_regs_p->ic_con) & IC_CON_SPD_MSK); + + if (cntl == IC_CON_SPD_HS) + return I2C_MAX_SPEED; + else if (cntl == IC_CON_SPD_FS) + return I2C_FAST_SPEED; + else if (cntl == IC_CON_SPD_SS) + return I2C_STANDARD_SPEED; + + return 0; +} + +/* + * i2c_init - Init function + * @speed: required i2c speed + * @slaveadd: slave address for the device + * + * Initialization function. + */ +void i2c_init(int speed, int slaveadd) +{ + unsigned int enbl; + + /* Disable i2c */ + enbl = readl(&i2c_regs_p->ic_enable); + enbl &= ~IC_ENABLE_0B; + writel(enbl, &i2c_regs_p->ic_enable); + + writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_regs_p->ic_con); + writel(IC_RX_TL, &i2c_regs_p->ic_rx_tl); + writel(IC_TX_TL, &i2c_regs_p->ic_tx_tl); + i2c_set_bus_speed(speed); + writel(IC_STOP_DET, &i2c_regs_p->ic_intr_mask); + writel(slaveadd, &i2c_regs_p->ic_sar); + + /* Enable i2c */ + enbl = readl(&i2c_regs_p->ic_enable); + enbl |= IC_ENABLE_0B; + writel(enbl, &i2c_regs_p->ic_enable); +} + +/* + * i2c_setaddress - Sets the target slave address + * @i2c_addr: target i2c address + * + * Sets the target slave address. + */ +static void i2c_setaddress(unsigned int i2c_addr) +{ + writel(i2c_addr, &i2c_regs_p->ic_tar); +} + +/* + * i2c_flush_rxfifo - Flushes the i2c RX FIFO + * + * Flushes the i2c RX FIFO + */ +static void i2c_flush_rxfifo(void) +{ + while (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) + readl(&i2c_regs_p->ic_cmd_data); +} + +/* + * i2c_wait_for_bb - Waits for bus busy + * + * Waits for bus busy + */ +static int i2c_wait_for_bb(void) +{ + unsigned long start_time_bb = get_timer(0); + + while ((readl(&i2c_regs_p->ic_status) & IC_STATUS_MA) || + !(readl(&i2c_regs_p->ic_status) & IC_STATUS_TFE)) { + + /* Evaluate timeout */ + if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB)) + return 1; + } + + return 0; +} + +/* check parameters for i2c_read and i2c_write */ +static int check_params(uint addr, int alen, uchar *buffer, int len) +{ + if (buffer == NULL) { + printf("Buffer is invalid\n"); + return 1; + } + + if (alen > 1) { + printf("addr len %d not supported\n", alen); + return 1; + } + + if (addr + len > 256) { + printf("address out of range\n"); + return 1; + } + + return 0; +} + +static int i2c_xfer_init(uchar chip, uint addr) +{ + if (i2c_wait_for_bb()) { + printf("Timed out waiting for bus\n"); + return 1; + } + + i2c_setaddress(chip); + writel(addr, &i2c_regs_p->ic_cmd_data); + + return 0; +} + +static int i2c_xfer_finish(void) +{ + ulong start_stop_det = get_timer(0); + + while (1) { + if ((readl(&i2c_regs_p->ic_raw_intr_stat) & IC_STOP_DET)) { + readl(&i2c_regs_p->ic_clr_stop_det); + break; + } else if (get_timer(start_stop_det) > I2C_STOPDET_TO) { + break; + } + } + + if (i2c_wait_for_bb()) { + printf("Timed out waiting for bus\n"); + return 1; + } + + i2c_flush_rxfifo(); + + /* Wait for read/write operation to complete on actual memory */ + udelay(10000); + + 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. + */ +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + unsigned long start_time_rx; + + if (check_params(addr, alen, buffer, len)) + return 1; + + if (i2c_xfer_init(chip, addr)) + return 1; + + start_time_rx = get_timer(0); + while (len) { + writel(IC_CMD, &i2c_regs_p->ic_cmd_data); + + if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) { + *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data); + len--; + start_time_rx = get_timer(0); + + } else if (get_timer(start_time_rx) > I2C_BYTE_TO) { + printf("Timed out. i2c read Failed\n"); + return 1; + } + } + + return i2c_xfer_finish(); +} + +/* + * 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. + */ +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + int nb = len; + unsigned long start_time_tx; + + if (check_params(addr, alen, buffer, len)) + return 1; + + if (i2c_xfer_init(chip, addr)) + return 1; + + start_time_tx = get_timer(0); + while (len) { + if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) { + writel(*buffer, &i2c_regs_p->ic_cmd_data); + buffer++; + len--; + 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_probe - Probe the i2c chip + */ +int i2c_probe(uchar chip) +{ + u32 tmp; + + /* + * Try to read the first location of the chip. + */ + return i2c_read(chip, 0, 1, (uchar *)&tmp, 1); +} diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h new file mode 100644 index 0000000..03b520e --- /dev/null +++ b/drivers/i2c/designware_i2c.h @@ -0,0 +1,146 @@ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __DW_I2C_H_ +#define __DW_I2C_H_ + +struct i2c_regs { + u32 ic_con; + u32 ic_tar; + u32 ic_sar; + u32 ic_hs_maddr; + u32 ic_cmd_data; + u32 ic_ss_scl_hcnt; + u32 ic_ss_scl_lcnt; + u32 ic_fs_scl_hcnt; + u32 ic_fs_scl_lcnt; + u32 ic_hs_scl_hcnt; + u32 ic_hs_scl_lcnt; + u32 ic_intr_stat; + u32 ic_intr_mask; + u32 ic_raw_intr_stat; + u32 ic_rx_tl; + u32 ic_tx_tl; + u32 ic_clr_intr; + u32 ic_clr_rx_under; + u32 ic_clr_rx_over; + u32 ic_clr_tx_over; + u32 ic_clr_rd_req; + u32 ic_clr_tx_abrt; + u32 ic_clr_rx_done; + u32 ic_clr_activity; + u32 ic_clr_stop_det; + u32 ic_clr_start_det; + u32 ic_clr_gen_call; + u32 ic_enable; + u32 ic_status; + u32 ic_txflr; + u32 ix_rxflr; + u32 reserved_1; + u32 ic_tx_abrt_source; +}; + +#define IC_CLK 166 +#define NANO_TO_MICRO 1000 + +/* High and low times in different speed modes (in ns) */ +#define MIN_SS_SCL_HIGHTIME 4000 +#define MIN_SS_SCL_LOWTIME 5000 +#define MIN_FS_SCL_HIGHTIME 800 +#define MIN_FS_SCL_LOWTIME 1700 +#define MIN_HS_SCL_HIGHTIME 60 +#define MIN_HS_SCL_LOWTIME 160 + +/* Worst case timeout for 1 byte is kept as 2ms */ +#define I2C_BYTE_TO (CONFIG_SYS_HZ/500) +#define I2C_STOPDET_TO (CONFIG_SYS_HZ/500) +#define I2C_BYTE_TO_BB (I2C_BYTE_TO * 16) + +/* i2c control register definitions */ +#define IC_CON_SD 0x0040 +#define IC_CON_RE 0x0020 +#define IC_CON_10BITADDRMASTER 0x0010 +#define IC_CON_10BITADDR_SLAVE 0x0008 +#define IC_CON_SPD_MSK 0x0006 +#define IC_CON_SPD_SS 0x0002 +#define IC_CON_SPD_FS 0x0004 +#define IC_CON_SPD_HS 0x0006 +#define IC_CON_MM 0x0001 + +/* i2c target address register definitions */ +#define TAR_ADDR 0x0050 + +/* i2c slave address register definitions */ +#define IC_SLAVE_ADDR 0x0002 + +/* i2c data buffer and command register definitions */ +#define IC_CMD 0x0100 + +/* i2c interrupt status register definitions */ +#define IC_GEN_CALL 0x0800 +#define IC_START_DET 0x0400 +#define IC_STOP_DET 0x0200 +#define IC_ACTIVITY 0x0100 +#define IC_RX_DONE 0x0080 +#define IC_TX_ABRT 0x0040 +#define IC_RD_REQ 0x0020 +#define IC_TX_EMPTY 0x0010 +#define IC_TX_OVER 0x0008 +#define IC_RX_FULL 0x0004 +#define IC_RX_OVER 0x0002 +#define IC_RX_UNDER 0x0001 + +/* fifo threshold register definitions */ +#define IC_TL0 0x00 +#define IC_TL1 0x01 +#define IC_TL2 0x02 +#define IC_TL3 0x03 +#define IC_TL4 0x04 +#define IC_TL5 0x05 +#define IC_TL6 0x06 +#define IC_TL7 0x07 +#define IC_RX_TL IC_TL0 +#define IC_TX_TL IC_TL0 + +/* i2c enable register definitions */ +#define IC_ENABLE_0B 0x0001 + +/* i2c status register definitions */ +#define IC_STATUS_SA 0x0040 +#define IC_STATUS_MA 0x0020 +#define IC_STATUS_RFF 0x0010 +#define IC_STATUS_RFNE 0x0008 +#define IC_STATUS_TFE 0x0004 +#define IC_STATUS_TFNF 0x0002 +#define IC_STATUS_ACT 0x0001 + +/* Speed Selection */ +#define IC_SPEED_MODE_STANDARD 1 +#define IC_SPEED_MODE_FAST 2 +#define IC_SPEED_MODE_MAX 3 + +#define I2C_MAX_SPEED 3400000 +#define I2C_FAST_SPEED 400000 +#define I2C_STANDARD_SPEED 100000 + +#endif /* __DW_I2C_H_ */ diff --git a/drivers/i2c/spr_i2c.c b/drivers/i2c/spr_i2c.c deleted file mode 100644 index eabfe84..0000000 --- a/drivers/i2c/spr_i2c.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * (C) Copyright 2009 - * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include - -static struct i2c_regs *const i2c_regs_p = - (struct i2c_regs *)CONFIG_SYS_I2C_BASE; - -/* - * set_speed - Set the i2c speed mode (standard, high, fast) - * @i2c_spd: required i2c speed mode - * - * Set the i2c speed mode (standard, high, fast) - */ -static void set_speed(int i2c_spd) -{ - unsigned int cntl; - unsigned int hcnt, lcnt; - unsigned int high, low; - - cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK)); - - switch (i2c_spd) { - case IC_SPEED_MODE_MAX: - cntl |= IC_CON_SPD_HS; - high = MIN_HS_SCL_HIGHTIME; - low = MIN_HS_SCL_LOWTIME; - break; - - case IC_SPEED_MODE_STANDARD: - cntl |= IC_CON_SPD_SS; - high = MIN_SS_SCL_HIGHTIME; - low = MIN_SS_SCL_LOWTIME; - break; - - case IC_SPEED_MODE_FAST: - default: - cntl |= IC_CON_SPD_FS; - high = MIN_FS_SCL_HIGHTIME; - low = MIN_FS_SCL_LOWTIME; - break; - } - - writel(cntl, &i2c_regs_p->ic_con); - - hcnt = (IC_CLK * high) / NANO_TO_MICRO; - writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt); - - lcnt = (IC_CLK * low) / NANO_TO_MICRO; - writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt); -} - -/* - * i2c_set_bus_speed - Set the i2c speed - * @speed: required i2c speed - * - * Set the i2c speed. - */ -void i2c_set_bus_speed(int speed) -{ - if (speed >= I2C_MAX_SPEED) - set_speed(IC_SPEED_MODE_MAX); - else if (speed >= I2C_FAST_SPEED) - set_speed(IC_SPEED_MODE_FAST); - else - set_speed(IC_SPEED_MODE_STANDARD); -} - -/* - * i2c_get_bus_speed - Gets the i2c speed - * - * Gets the i2c speed. - */ -int i2c_get_bus_speed(void) -{ - u32 cntl; - - cntl = (readl(&i2c_regs_p->ic_con) & IC_CON_SPD_MSK); - - if (cntl == IC_CON_SPD_HS) - return I2C_MAX_SPEED; - else if (cntl == IC_CON_SPD_FS) - return I2C_FAST_SPEED; - else if (cntl == IC_CON_SPD_SS) - return I2C_STANDARD_SPEED; - - return 0; -} - -/* - * i2c_init - Init function - * @speed: required i2c speed - * @slaveadd: slave address for the spear device - * - * Initialization function. - */ -void i2c_init(int speed, int slaveadd) -{ - unsigned int enbl; - - /* Disable i2c */ - enbl = readl(&i2c_regs_p->ic_enable); - enbl &= ~IC_ENABLE_0B; - writel(enbl, &i2c_regs_p->ic_enable); - - writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_regs_p->ic_con); - writel(IC_RX_TL, &i2c_regs_p->ic_rx_tl); - writel(IC_TX_TL, &i2c_regs_p->ic_tx_tl); - i2c_set_bus_speed(speed); - writel(IC_STOP_DET, &i2c_regs_p->ic_intr_mask); - writel(slaveadd, &i2c_regs_p->ic_sar); - - /* Enable i2c */ - enbl = readl(&i2c_regs_p->ic_enable); - enbl |= IC_ENABLE_0B; - writel(enbl, &i2c_regs_p->ic_enable); -} - -/* - * i2c_setaddress - Sets the target slave address - * @i2c_addr: target i2c address - * - * Sets the target slave address. - */ -static void i2c_setaddress(unsigned int i2c_addr) -{ - writel(i2c_addr, &i2c_regs_p->ic_tar); -} - -/* - * i2c_flush_rxfifo - Flushes the i2c RX FIFO - * - * Flushes the i2c RX FIFO - */ -static void i2c_flush_rxfifo(void) -{ - while (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) - readl(&i2c_regs_p->ic_cmd_data); -} - -/* - * i2c_wait_for_bb - Waits for bus busy - * - * Waits for bus busy - */ -static int i2c_wait_for_bb(void) -{ - unsigned long start_time_bb = get_timer(0); - - while ((readl(&i2c_regs_p->ic_status) & IC_STATUS_MA) || - !(readl(&i2c_regs_p->ic_status) & IC_STATUS_TFE)) { - - /* Evaluate timeout */ - if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB)) - return 1; - } - - return 0; -} - -/* check parameters for i2c_read and i2c_write */ -static int check_params(uint addr, int alen, uchar *buffer, int len) -{ - if (buffer == NULL) { - printf("Buffer is invalid\n"); - return 1; - } - - if (alen > 1) { - printf("addr len %d not supported\n", alen); - return 1; - } - - if (addr + len > 256) { - printf("address out of range\n"); - return 1; - } - - return 0; -} - -static int i2c_xfer_init(uchar chip, uint addr) -{ - if (i2c_wait_for_bb()) { - printf("Timed out waiting for bus\n"); - return 1; - } - - i2c_setaddress(chip); - writel(addr, &i2c_regs_p->ic_cmd_data); - - return 0; -} - -static int i2c_xfer_finish(void) -{ - ulong start_stop_det = get_timer(0); - - while (1) { - if ((readl(&i2c_regs_p->ic_raw_intr_stat) & IC_STOP_DET)) { - readl(&i2c_regs_p->ic_clr_stop_det); - break; - } else if (get_timer(start_stop_det) > I2C_STOPDET_TO) { - break; - } - } - - if (i2c_wait_for_bb()) { - printf("Timed out waiting for bus\n"); - return 1; - } - - i2c_flush_rxfifo(); - - /* Wait for read/write operation to complete on actual memory */ - udelay(10000); - - 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. - */ -int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) -{ - unsigned long start_time_rx; - - if (check_params(addr, alen, buffer, len)) - return 1; - - if (i2c_xfer_init(chip, addr)) - return 1; - - start_time_rx = get_timer(0); - while (len) { - writel(IC_CMD, &i2c_regs_p->ic_cmd_data); - - if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) { - *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data); - len--; - start_time_rx = get_timer(0); - - } else if (get_timer(start_time_rx) > I2C_BYTE_TO) { - printf("Timed out. i2c read Failed\n"); - return 1; - } - } - - return i2c_xfer_finish(); -} - -/* - * 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. - */ -int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) -{ - int nb = len; - unsigned long start_time_tx; - - if (check_params(addr, alen, buffer, len)) - return 1; - - if (i2c_xfer_init(chip, addr)) - return 1; - - start_time_tx = get_timer(0); - while (len) { - if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) { - writel(*buffer, &i2c_regs_p->ic_cmd_data); - buffer++; - len--; - 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_probe - Probe the i2c chip - */ -int i2c_probe(uchar chip) -{ - u32 tmp; - - /* - * Try to read the first location of the chip. - */ - return i2c_read(chip, 0, 1, (uchar *)&tmp, 1); -} diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h index 5fef8cc..a791815 100644 --- a/include/configs/spear-common.h +++ b/include/configs/spear-common.h @@ -41,7 +41,7 @@ /* I2C driver configuration */ #define CONFIG_HARD_I2C -#define CONFIG_SPEAR_I2C +#define CONFIG_DW_I2C #define CONFIG_SYS_I2C_SPEED 400000 #define CONFIG_SYS_I2C_SLAVE 0x02 -- cgit v0.10.2