X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fi2c%2Fsoft_i2c.c;h=69b5f42205f427255344ad55913896d426774464;hb=127cec1889c7a9bb3c3eab521779b08657043a9a;hp=23db2ee8ff4375be62c0800ca87edfa39bee601c;hpb=4d75e0aa9caca64d4a1d55d95cd1ca5f30d9fc56;p=u-boot diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c index 23db2ee8ff..69b5f42205 100644 --- a/drivers/i2c/soft_i2c.c +++ b/drivers/i2c/soft_i2c.c @@ -28,10 +28,15 @@ #include #ifdef CONFIG_MPC8260 /* only valid for MPC8260 */ #include +#include #endif -#ifdef CONFIG_AT91RM9200 /* need this for the at91rm9200 */ +#if defined(CONFIG_AT91FAMILY) #include #include +#include +#ifdef CONFIG_AT91_LEGACY +#include +#endif #endif #ifdef CONFIG_IXP425 /* only valid for IXP425 */ #include @@ -39,22 +44,75 @@ #ifdef CONFIG_LPC2292 #include #endif +#if defined(CONFIG_MPC852T) || defined(CONFIG_MPC866) +#include +#endif #include +#if defined(CONFIG_SOFT_I2C_GPIO_SCL) +# include + +# ifndef I2C_GPIO_SYNC +# define I2C_GPIO_SYNC +# endif + +# ifndef I2C_INIT +# define I2C_INIT \ + do { \ + gpio_request(CONFIG_SOFT_I2C_GPIO_SCL, "soft_i2c"); \ + gpio_request(CONFIG_SOFT_I2C_GPIO_SDA, "soft_i2c"); \ + } while (0) +# endif + +# ifndef I2C_ACTIVE +# define I2C_ACTIVE do { } while (0) +# endif + +# ifndef I2C_TRISTATE +# define I2C_TRISTATE do { } while (0) +# endif + +# ifndef I2C_READ +# define I2C_READ gpio_get_value(CONFIG_SOFT_I2C_GPIO_SDA) +# endif + +# ifndef I2C_SDA +# define I2C_SDA(bit) \ + do { \ + if (bit) \ + gpio_direction_input(CONFIG_SOFT_I2C_GPIO_SDA); \ + else \ + gpio_direction_output(CONFIG_SOFT_I2C_GPIO_SDA, 0); \ + I2C_GPIO_SYNC; \ + } while (0) +# endif + +# ifndef I2C_SCL +# define I2C_SCL(bit) \ + do { \ + gpio_direction_output(CONFIG_SOFT_I2C_GPIO_SCL, bit); \ + I2C_GPIO_SYNC; \ + } while (0) +# endif + +# ifndef I2C_DELAY +# define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */ +# endif + +#endif + /* #define DEBUG_I2C */ #ifdef DEBUG_I2C DECLARE_GLOBAL_DATA_PTR; #endif - /*----------------------------------------------------------------------- * Definitions */ #define RETRIES 0 - #define I2C_ACK 0 /* PD_SDA level to ack a byte */ #define I2C_NOACK 1 /* PD_SDA level to noack a byte */ @@ -68,17 +126,23 @@ DECLARE_GLOBAL_DATA_PTR; #define PRINTD(fmt,args...) #endif +#if defined(CONFIG_I2C_MULTI_BUS) +static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = 0; +#endif /* CONFIG_I2C_MULTI_BUS */ + /*----------------------------------------------------------------------- * Local functions */ +#if !defined(CONFIG_SYS_I2C_INIT_BOARD) static void send_reset (void); +#endif static void send_start (void); static void send_stop (void); static void send_ack (int); static int write_byte (uchar byte); static uchar read_byte (int); - +#if !defined(CONFIG_SYS_I2C_INIT_BOARD) /*----------------------------------------------------------------------- * Send a reset sequence consisting of 9 clocks with the data signal high * to clock any confused device back into an idle state. Also send a @@ -86,12 +150,7 @@ static uchar read_byte (int); */ static void send_reset(void) { -#ifdef CONFIG_MPC8260 - volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); -#endif -#ifdef CONFIG_8xx - volatile immap_t *immr = (immap_t *)CFG_IMMR; -#endif + I2C_SOFT_DECLARATIONS /* intentional without ';' */ int j; I2C_SCL(1); @@ -111,18 +170,14 @@ static void send_reset(void) send_stop(); I2C_TRISTATE; } +#endif /*----------------------------------------------------------------------- * START: High -> Low on SDA while SCL is High */ static void send_start(void) { -#ifdef CONFIG_MPC8260 - volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); -#endif -#ifdef CONFIG_8xx - volatile immap_t *immr = (immap_t *)CFG_IMMR; -#endif + I2C_SOFT_DECLARATIONS /* intentional without ';' */ I2C_DELAY; I2C_SDA(1); @@ -139,12 +194,7 @@ static void send_start(void) */ static void send_stop(void) { -#ifdef CONFIG_MPC8260 - volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); -#endif -#ifdef CONFIG_8xx - volatile immap_t *immr = (immap_t *)CFG_IMMR; -#endif + I2C_SOFT_DECLARATIONS /* intentional without ';' */ I2C_SCL(0); I2C_DELAY; @@ -158,18 +208,12 @@ static void send_stop(void) I2C_TRISTATE; } - /*----------------------------------------------------------------------- * ack should be I2C_ACK or I2C_NOACK */ static void send_ack(int ack) { -#ifdef CONFIG_MPC8260 - volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); -#endif -#ifdef CONFIG_8xx - volatile immap_t *immr = (immap_t *)CFG_IMMR; -#endif + I2C_SOFT_DECLARATIONS /* intentional without ';' */ I2C_SCL(0); I2C_DELAY; @@ -183,18 +227,12 @@ static void send_ack(int ack) I2C_DELAY; } - /*----------------------------------------------------------------------- * Send 8 bits and look for an acknowledgement. */ static int write_byte(uchar data) { -#ifdef CONFIG_MPC8260 - volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); -#endif -#ifdef CONFIG_8xx - volatile immap_t *immr = (immap_t *)CFG_IMMR; -#endif + I2C_SOFT_DECLARATIONS /* intentional without ';' */ int j; int nack; @@ -230,6 +268,37 @@ static int write_byte(uchar data) return(nack); /* not a nack is an ack */ } +#if defined(CONFIG_I2C_MULTI_BUS) +/* + * Functions for multiple I2C bus handling + */ +unsigned int i2c_get_bus_num(void) +{ + return i2c_bus_num; +} + +int i2c_set_bus_num(unsigned int bus) +{ +#if defined(CONFIG_I2C_MUX) + if (bus < CONFIG_SYS_MAX_I2C_BUS) { + i2c_bus_num = bus; + } else { + int ret; + + ret = i2x_mux_select_mux(bus); + if (ret == 0) + i2c_bus_num = bus; + else + return ret; + } +#else + if (bus >= CONFIG_SYS_MAX_I2C_BUS) + return -1; + i2c_bus_num = bus; +#endif + return 0; +} +#endif /*----------------------------------------------------------------------- * if ack == I2C_ACK, ACK the byte so can continue reading, else @@ -237,12 +306,7 @@ static int write_byte(uchar data) */ static uchar read_byte(int ack) { -#ifdef CONFIG_MPC8260 - volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); -#endif -#ifdef CONFIG_8xx - volatile immap_t *immr = (immap_t *)CFG_IMMR; -#endif + I2C_SOFT_DECLARATIONS /* intentional without ';' */ int data; int j; @@ -275,6 +339,12 @@ static uchar read_byte(int ack) */ void i2c_init (int speed, int slaveaddr) { +#if defined(CONFIG_SYS_I2C_INIT_BOARD) + /* call board specific i2c bus reset routine before accessing the */ + /* environment, which might be in a chip on that bus. For details */ + /* about this problem see doc/I2C_Edge_Conditions. */ + i2c_init_board(); +#else /* * WARNING: Do NOT save speed in a static variable: if the * I2C routines are called before RAM is initialized (to read @@ -282,6 +352,7 @@ void i2c_init (int speed, int slaveaddr) * system will crash. */ send_reset (); +#endif } /*----------------------------------------------------------------------- @@ -313,7 +384,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) PRINTD("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n", chip, addr, alen, buffer, len); -#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW +#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 @@ -325,7 +396,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) * still be one byte because the extra address bits are * hidden in the chip address. */ - chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); + chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); PRINTD("i2c_read: fix addr_overflow: chip %02X addr %02X\n", chip, addr); @@ -352,8 +423,18 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) } shift -= 8; } - send_stop(); /* reportedly some chips need a full stop */ + + /* Some I2C chips need a stop/start sequence here, + * other chips don't work with a full stop and need + * only a start. Default behaviour is to send the + * stop/start sequence. + */ +#ifdef CONFIG_SOFT_I2C_READ_REPEATED_START send_start(); +#else + send_stop(); + send_start(); +#endif } /* * Send the chip address again, this time for a read cycle. @@ -401,23 +482,3 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) send_stop(); return(failures); } - -/*----------------------------------------------------------------------- - * Read a register - */ -uchar i2c_reg_read(uchar i2c_addr, uchar reg) -{ - uchar buf; - - i2c_read(i2c_addr, reg, 1, &buf, 1); - - return(buf); -} - -/*----------------------------------------------------------------------- - * Write a register - */ -void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) -{ - i2c_write(i2c_addr, reg, 1, &val, 1); -}