From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heiko Schocher Date: Mon, 09 Feb 2009 13:21:50 +0100 Subject: [U-Boot] PATCH 3/8 Multi-adapter multi-bus I2C In-Reply-To: References: Message-ID: <49901FDE.8050405@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello ksi, ksi at koi8.net wrote: > Signed-off-by: Sergey Kubushyn > --- > diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c > index da6cec1..f0c1771 100644 > --- a/drivers/i2c/soft_i2c.c > +++ b/drivers/i2c/soft_i2c.c > @@ -1,4 +1,8 @@ > /* > + * Copyright (c) 2009 Sergey Kubushyn > + * > + * Changes for multibus/multiadapter I2C support. > + * > * (C) Copyright 2001, 2002 > * Wolfgang Denk, DENX Software Engineering, wd at denx.de. > * > @@ -72,375 +76,493 @@ 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); > +#ifndef I2C_INIT > +#define I2C_INIT do {} while(0) > #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 > - * at the end of the sequence for belts & suspenders. > - */ > -static void send_reset(void) > -{ > - I2C_SOFT_DECLARATIONS /* intentional without ';' */ > - int j; > - > - I2C_SCL(1); > - I2C_SDA(1); > -#ifdef I2C_INIT > - I2C_INIT; > +#ifndef I2C_INIT0 > +#define I2C_INIT0 do {} while(0) > #endif > - I2C_TRISTATE; > - for(j = 0; j < 9; j++) { > - I2C_SCL(0); > - I2C_DELAY; > - I2C_DELAY; > - I2C_SCL(1); > - I2C_DELAY; > - I2C_DELAY; > - } > - send_stop(); > - I2C_TRISTATE; > -} > +#ifndef I2C_INIT1 > +#define I2C_INIT1 do {} while(0) > +#endif > +#ifndef I2C_INIT2 > +#define I2C_INIT2 do {} while(0) > #endif > +#ifndef I2C_INIT3 > +#define I2C_INIT3 do {} while(0) > +#endif > + > > /*----------------------------------------------------------------------- > * START: High -> Low on SDA while SCL is High > */ > -static void send_start(void) > -{ > - I2C_SOFT_DECLARATIONS /* intentional without ';' */ > - > - I2C_DELAY; > - I2C_SDA(1); > - I2C_ACTIVE; > - I2C_DELAY; > - I2C_SCL(1); > - I2C_DELAY; > - I2C_SDA(0); > - I2C_DELAY; > +#define I2C_SOFT_SEND_START(n) \ > +static void send_start##n(void) \ > +{ \ > + I2C_SOFT_DECLARATIONS##n \ > + I2C_DELAY##n; \ > + I2C_SDA##n(1); \ > + I2C_ACTIVE##n; \ > + I2C_DELAY##n; \ > + I2C_SCL##n(1); \ > + I2C_DELAY##n; \ > + I2C_SDA##n(0); \ > + I2C_DELAY##n; \ > } > [...] > - PRINTD("i2c_read: fix addr_overflow: chip %02X addr %02X\n", > - chip, addr); > -#endif > +#define DO_EEAD_OVF chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); \ > Line too long. > + PRINTD("%s: fix addr_overflow: chip %02X addr %02X\n", \ > + __FUNCTION__, chip, addr); > > - /* > - * Do the addressing portion of a write cycle to set the > - * chip's address pointer. If the address length is zero, > - * don't do the normal write cycle to set the address pointer, > - * there is no address pointer in this chip. > [...] > +#if defined(I2C_SOFT_DECLARATIONS3) > +I2C_SOFT_SEND_START(3) > +I2C_SOFT_SEND_STOP(3) > +I2C_SOFT_SEND_ACK(3) > +#if !defined(CONFIG_SYS_I2C_INIT_BOARD) > +I2C_SOFT_SEND_RESET(3) > +#endif > +I2C_SOFT_WRITE_BYTE(3) > +I2C_SOFT_READ_BYTE(3) > +I2C_SOFT_INIT_ADAPTER(3) > +I2C_SOFT_PROBE(3) > +I2C_SOFT_READ(3) > +I2C_SOFT_WRITE(3) > +I2C_SOFT_GET_BUS_SPEED(3) > +I2C_SOFT_SET_BUS_SPEED(3) > +#endif > + > Hmm... are this lots of defines really necessary? Couldn't we add something like int hw_adapnr; /* hardware adapter number */ to the i2c_adap_t struct, and have an pointer (cur_i2c_adap?) to the current used i2c_adap_t? Then you have where you need it, your hw_adapnr and need not all of this defines. For example you need in the config for MPC8548CDS.h just this define: #define I2C_SDA(bit) (printf("HW adap: %d sda: %d", cur_i2c_adap->hw_adapnr, bit)) and not I2C_SDA(bit) and I2C_SDA1(bit) > +i2c_adap_t soft_i2c_adap[] = { > + { > +#if defined(I2C_SOFT_DECLARATIONS) > + .init = soft_i2c_init, > + .probe = soft_i2c_probe, > + .read = soft_i2c_read, > + .write = soft_i2c_write, > + .set_bus_speed = soft_i2c_set_bus_speed, > + .get_bus_speed = soft_i2c_get_bus_speed, > + .speed = CONFIG_SYS_SOFT_I2C_SPEED, > + .slaveaddr = CONFIG_SYS_SOFT_I2C_SLAVE, > + .init_done = 0, > + .name = "soft-i2c" > +#elif defined(I2C_SOFT_DECLARATIONS0) > + .init = soft_i2c_init0, > + .probe = soft_i2c_probe0, > + .read = soft_i2c_read0, > + .write = soft_i2c_write0, > + .set_bus_speed = soft_i2c_set_bus_speed0, > + .get_bus_speed = soft_i2c_get_bus_speed0, > + .speed = CONFIG_SYS_SOFT_I2C0_SPEED, > + .slaveaddr = CONFIG_SYS_SOFT_I2C0_SLAVE, > + .init_done = 0, > + .name = "soft-i2c#0" > +#endif > + }, > +#if defined(I2C_SOFT_DECLARATIONS1) > + { > + .init = soft_i2c_init1, > + .probe = soft_i2c_probe1, > + .read = soft_i2c_read1, > + .write = soft_i2c_write1, > + .set_bus_speed = soft_i2c_set_bus_speed1, > + .get_bus_speed = soft_i2c_get_bus_speed1, > + .speed = CONFIG_SYS_SOFT_I2C1_SPEED, > + .slaveaddr = CONFIG_SYS_SOFT_I2C1_SLAVE, > + .init_done = 0, > + .name = "soft-i2c#1" > + }, > +#endif > +#if defined(I2C_SOFT_DECLARATIONS2) > + { > + .init = soft_i2c_init2, > + .probe = soft_i2c_probe2, > + .read = soft_i2c_read2, > + .write = soft_i2c_write2, > + .set_bus_speed = soft_i2c_set_bus_speed2, > + .get_bus_speed = soft_i2c_get_bus_speed2, > + .speed = CONFIG_SYS_SOFT_I2C2_SPEED, > + .slaveaddr = CONFIG_SYS_SOFT_I2C2_SLAVE, > + .init_done = 0, > + .name = "soft-i2c#2" > + }, > +#endif > +#if defined(I2C_SOFT_DECLARATIONS3) > + { > + .init = soft_i2c_init3, > + .probe = soft_i2c_probe3, > + .read = soft_i2c_read3, > + .write = soft_i2c_write3, > + .set_bus_speed = soft_i2c_set_bus_speed3, > + .get_bus_speed = soft_i2c_get_bus_speed3, > + .speed = CONFIG_SYS_SOFT_I2C3_SPEED, > + .slaveaddr = CONFIG_SYS_SOFT_I2C3_SLAVE, > + .init_done = 0, > + .name = "soft-i2c#3" > + }, > +#endif > +}; > bye Heiko -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany