[U-Boot] [RFC] i2c, ppc4xx_i2c: switch to new multibus/multiadapter support

Dirk Eibach
2013-04-24T11:43:45Z

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Cc: Heiko Schocher <hs@denx.de>
Cc: Stefan Roese <sr@denx.de>
---
drivers/i2c/Makefile | 2 +-
drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++-----------------------
2 files changed, 97 insertions(+), 98 deletions(-)

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 564d061..0298e3e 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -36,7 +36,6 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
COBJS-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
-COBJS-$(CONFIG_PPC4XX_I2C) += ppc4xx_i2c.o
COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o
COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o
COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
@@ -45,6 +44,7 @@ COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
COBJS-$(CONFIG_SYS_I2C) += i2c_core.o
COBJS-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
+COBJS-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o
COBJS-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
COBJS-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o

diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c
index 53fedd5..c924874 100644
--- a/drivers/i2c/ppc4xx_i2c.c
+++ b/drivers/i2c/ppc4xx_i2c.c
@@ -32,27 +32,29 @@
#include <i2c.h>
#include <asm/io.h>

-#ifdef CONFIG_HARD_I2C
-
DECLARE_GLOBAL_DATA_PTR;

-#if defined(CONFIG_I2C_MULTI_BUS)
-/*
- * Initialize the bus pointer to whatever one the SPD EEPROM is on.
- * Default is bus 0. This is necessary because the DDR initialization
- * runs from ROM, and we can't switch buses because we can't modify
- * the global variables.
- */
-#ifndef CONFIG_SYS_SPD_BUS_NUM
-#define CONFIG_SYS_SPD_BUS_NUM 0
+static inline struct ppc4xx_i2c *ppc4xx_get_i2c(int hwadapnr)
+{
+ unsigned long base;
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ base = CONFIG_SYS_PERIPHERAL_BASE + 0x00000700 + (hwadapnr * 0x100);
+#elif defined(CONFIG_440) || defined(CONFIG_405EX)
+/* all remaining 440 variants */
+ base = CONFIG_SYS_PERIPHERAL_BASE + 0x00000400 + (hwadapnr * 0x100);
+#else
+/* all 405 variants */
+ base = 0xEF600500 + (hwadapnr * 0x100);
#endif
-static unsigned int i2c_bus_num __attribute__ ((section (".data"))) =
- CONFIG_SYS_SPD_BUS_NUM;
-#endif /* CONFIG_I2C_MULTI_BUS */
+ return (struct ppc4xx_i2c *)base;
+}

-static void _i2c_bus_reset(void)
+static void _i2c_bus_reset(struct i2c_adapter *adap)
{
- struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;
+ struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr);
int i;
u8 dc;

@@ -91,11 +93,10 @@ static void _i2c_bus_reset(void)
out_8(&i2c->xtcntlss, 0);
}

-void i2c_init(int speed, int slaveaddr)
+static void ppc4xx_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
{
- struct ppc4xx_i2c *i2c;
+ struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr);
int val, divisor;
- int bus;

#ifdef CONFIG_SYS_I2C_INIT_BOARD
/*
@@ -106,67 +107,57 @@ void i2c_init(int speed, int slaveaddr)
i2c_init_board();
#endif

- for (bus = 0; bus < CONFIG_SYS_MAX_I2C_BUS; bus++) {
- I2C_SET_BUS(bus);
-
- /* Set i2c pointer after calling I2C_SET_BUS() */
- i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;
-
- /* Handle possible failed I2C state */
- /* FIXME: put this into i2c_init_board()? */
- _i2c_bus_reset();
+ /* Handle possible failed I2C state */
+ /* FIXME: put this into i2c_init_board()? */
+ _i2c_bus_reset(adap);

- /* clear lo master address */
- out_8(&i2c->lmadr, 0);
+ /* clear lo master address */
+ out_8(&i2c->lmadr, 0);

- /* clear hi master address */
- out_8(&i2c->hmadr, 0);
-
- /* clear lo slave address */
- out_8(&i2c->lsadr, 0);
+ /* clear hi master address */
+ out_8(&i2c->hmadr, 0);

- /* clear hi slave address */
- out_8(&i2c->hsadr, 0);
+ /* clear lo slave address */
+ out_8(&i2c->lsadr, 0);

- /* Clock divide Register */
- /* set divisor according to freq_opb */
- divisor = (get_OPB_freq() - 1) / 10000000;
- if (divisor == 0)
- divisor = 1;
- out_8(&i2c->clkdiv, divisor);
+ /* clear hi slave address */
+ out_8(&i2c->hsadr, 0);

- /* no interrupts */
- out_8(&i2c->intrmsk, 0);
+ /* Clock divide Register */
+ /* set divisor according to freq_opb */
+ divisor = (get_OPB_freq() - 1) / 10000000;
+ if (divisor == 0)
+ divisor = 1;
+ out_8(&i2c->clkdiv, divisor);

- /* clear transfer count */
- out_8(&i2c->xfrcnt, 0);
+ /* no interrupts */
+ out_8(&i2c->intrmsk, 0);

- /* clear extended control & stat */
- /* write 1 in SRC SRS SWC SWS to clear these fields */
- out_8(&i2c->xtcntlss, 0xF0);
+ /* clear transfer count */
+ out_8(&i2c->xfrcnt, 0);

- /* Mode Control Register
- Flush Slave/Master data buffer */
- out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
+ /* clear extended control & stat */
+ /* write 1 in SRC SRS SWC SWS to clear these fields */
+ out_8(&i2c->xtcntlss, 0xF0);

- val = in_8(&i2c->mdcntl);
+ /* Mode Control Register
+ Flush Slave/Master data buffer */
+ out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);

- /* Ignore General Call, slave transfers are ignored,
- * disable interrupts, exit unknown bus state, enable hold
- * SCL 100kHz normaly or FastMode for 400kHz and above
- */
+ val = in_8(&i2c->mdcntl);

- val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL;
- if (speed >= 400000)
- val |= IIC_MDCNTL_FSM;
- out_8(&i2c->mdcntl, val);
+ /* Ignore General Call, slave transfers are ignored,
+ * disable interrupts, exit unknown bus state, enable hold
+ * SCL 100kHz normaly or FastMode for 400kHz and above
+ */

- /* clear control reg */
- out_8(&i2c->cntl, 0x00);
- }
+ val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL;
+ if (speed >= 400000)
+ val |= IIC_MDCNTL_FSM;
+ out_8(&i2c->mdcntl, val);

- /* set to SPD bus as default bus upon powerup */
- I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM);
+ /* clear control reg */
+ out_8(&i2c->cntl, 0x00);
}

/*
@@ -194,14 +185,15 @@ void i2c_init(int speed, int slaveaddr)
*
* It does not check XFRCNT.
*/
-static int i2c_transfer(unsigned char cmd_type,
+static int _i2c_transfer(struct i2c_adapter *adap,
+ unsigned char cmd_type,
unsigned char chip,
unsigned char addr[],
unsigned char addr_len,
unsigned char data[],
unsigned short data_len)
{
- struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;
+ struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr);
u8 *ptr;
int reading;
int tran, cnt;
@@ -345,7 +337,7 @@ static int i2c_transfer(unsigned char cmd_type,
return result;
}

-int i2c_probe(uchar chip)
+static int ppc4xx_i2c_probe(struct i2c_adapter *adap, uchar chip)
{
uchar buf[1];

@@ -356,11 +348,11 @@ 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(1, chip << 1, 0, 0, buf, 1) != 0);
+ return (_i2c_transfer(adap, 1, chip << 1, 0, 0, buf, 1) != 0);
}

-static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer,
- int len, int read)
+static int ppc4xx_i2c_transfer(struct i2c_adapter *adap, uchar chip, uint addr,
+ int alen, uchar *buffer, int len, int read)
{
uchar xaddr[4];
int ret;
@@ -394,43 +386,50 @@ static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer,
chip |= ((addr >> (alen * 8)) &
CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
#endif
- if ((ret = i2c_transfer(read, chip << 1, &xaddr[4 - alen], alen,
- buffer, len)) != 0) {
+ ret = _i2c_transfer(adap, read, chip << 1, &xaddr[4 - alen], alen,
+ buffer, len);
+ if (ret) {
printf("I2C %s: failed %d\n", read ? "read" : "write", ret);
-
return 1;
}

return 0;
}

-int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)
+static int ppc4xx_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
+ int alen, uchar *buffer, int len)
{
- return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 1);
+ return ppc4xx_i2c_transfer(adap, chip, addr, alen, buffer, len, 1);
}

-int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len)
+static int ppc4xx_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
+ int alen, uchar *buffer, int len)
{
- return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 0);
+ return ppc4xx_i2c_transfer(adap, chip, addr, alen, buffer, len, 0);
}

-#if defined(CONFIG_I2C_MULTI_BUS)
-/*
- * Functions for multiple I2C bus handling
- */
-unsigned int i2c_get_bus_num(void)
+static unsigned int ppc4xx_i2c_set_bus_speed(struct i2c_adapter *adap,
+ unsigned int speed)
{
- return i2c_bus_num;
-}
-
-int i2c_set_bus_num(unsigned int bus)
-{
- if (bus >= CONFIG_SYS_MAX_I2C_BUS)
+ if (speed != adap->speed)
return -1;
-
- i2c_bus_num = bus;
-
- return 0;
+ return speed;
}
-#endif /* CONFIG_I2C_MULTI_BUS */
-#endif /* CONFIG_HARD_I2C */
+
+/*
+ * Register ppc4xx i2c adapters
+ */
+#ifdef CONFIG_SYS_I2C_PPC4XX_CH0
+U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_0, ppc4xx_i2c_init, ppc4xx_i2c_probe,
+ ppc4xx_i2c_read, ppc4xx_i2c_write,
+ ppc4xx_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_PPC4XX_SPEED_0,
+ CONFIG_SYS_I2C_PPC4XX_SLAVE_0, 0)
+#endif
+#ifdef CONFIG_SYS_I2C_PPC4XX_CH1
+U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_1, ppc4xx_i2c_init, ppc4xx_i2c_probe,
+ ppc4xx_i2c_read, ppc4xx_i2c_write,
+ ppc4xx_i2c_set_bus_speed,
+ CONFIG_SYS_I2C_PPC4XX_SPEED_1,
+ CONFIG_SYS_I2C_PPC4XX_SLAVE_1, 1)
+#endif
--
1.7.2.5