diff options
author | wdenk <wdenk> | 2003-10-08 22:33:00 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2003-10-08 22:33:00 +0000 |
commit | fc3e2165efda62670d447617a7d44c5666178ea4 (patch) | |
tree | a1ab5ba88bafe1fbb0e539f81016cead9cab81c0 /drivers/s3c24x0_i2c.c | |
parent | ef1464cc01cf9dcab52396283bf597e609caa450 (diff) | |
download | u-boot-imx-fc3e2165efda62670d447617a7d44c5666178ea4.zip u-boot-imx-fc3e2165efda62670d447617a7d44c5666178ea4.tar.gz u-boot-imx-fc3e2165efda62670d447617a7d44c5666178ea4.tar.bz2 |
* Patch by Sangmoon Kim, 23 Sep 2003:
fix pll_pci_to_mem_multiplier table for MPC8245
* Patch by Anders Larsen, 22 Sep 2003:
enable timed autoboot on PXA
* Patch by David Müller, 22 Sep 2003:
- add $(CFLAGS) to "-print-libgcc-filename" so compiler driver
returns correct libgcc file path
- "latency" reduction of busy-loop waiting to improve "U-Boot" boot
time on s3c24x0 systems
* Patch by Jon Diekema, 19 Sep 2003:
- Add CFG_FAULT_ECHO_LINK_DOWN option to echo the inverted Ethernet
link state to the fault LED.
- In NetLoop, make the Fault LED reflect the link status. The link
status gets updated on entry, and on timeouts.
Diffstat (limited to 'drivers/s3c24x0_i2c.c')
-rw-r--r-- | drivers/s3c24x0_i2c.c | 530 |
1 files changed, 264 insertions, 266 deletions
diff --git a/drivers/s3c24x0_i2c.c b/drivers/s3c24x0_i2c.c index 2c27cb5..ef56cd1 100644 --- a/drivers/s3c24x0_i2c.c +++ b/drivers/s3c24x0_i2c.c @@ -91,359 +91,357 @@ static void SetI2CSCL(int x) } -static int WaitForXfer(void) +static int WaitForXfer (void) { - S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C(); - int i, status; + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + int i, status; - i = I2C_TIMEOUT * 1000; - status = i2c->IICCON; - while ((i > 0) && !(status & I2CCON_IRPND)) { - udelay(1000); + i = I2C_TIMEOUT * 10000; status = i2c->IICCON; - i--; - } + while ((i > 0) && !(status & I2CCON_IRPND)) { + udelay (100); + status = i2c->IICCON; + i--; + } - return(status & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT; + return (status & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT; } -static int IsACK(void) +static int IsACK (void) { - S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C(); + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); - return(!(i2c->IICSTAT & I2CSTAT_NACK)); + return (!(i2c->IICSTAT & I2CSTAT_NACK)); } -static void ReadWriteByte(void) +static void ReadWriteByte (void) { - S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C(); + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); - i2c->IICCON &= ~I2CCON_IRPND; + i2c->IICCON &= ~I2CCON_IRPND; } void i2c_init (int speed, int slaveadd) { - S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C(); - S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); - ulong freq, pres = 16, div; - int i, status; + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + S3C24X0_GPIO *const gpio = S3C24X0_GetBase_GPIO (); + ulong freq, pres = 16, div; + int i, status; - /* wait for some time to give previous transfer a chance to finish */ + /* wait for some time to give previous transfer a chance to finish */ - i = I2C_TIMEOUT * 1000; - status = i2c->IICSTAT; - while ((i > 0) && (status & I2CSTAT_BSY)) { - udelay(1000); + i = I2C_TIMEOUT * 1000; status = i2c->IICSTAT; - i--; - } + while ((i > 0) && (status & I2CSTAT_BSY)) { + udelay (1000); + status = i2c->IICSTAT; + i--; + } - if ((status & I2CSTAT_BSY) || GetI2CSDA() == 0) { + if ((status & I2CSTAT_BSY) || GetI2CSDA () == 0) { #ifdef CONFIG_S3C2410 - ulong old_gpecon = gpio->GPECON; + ulong old_gpecon = gpio->GPECON; #endif #ifdef CONFIG_S3C2400 - ulong old_gpecon = gpio->PGCON; + ulong old_gpecon = gpio->PGCON; #endif - /* bus still busy probably by (most) previously interrupted transfer */ + /* bus still busy probably by (most) previously interrupted transfer */ #ifdef CONFIG_S3C2410 - /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */ - gpio->GPECON = (gpio->GPECON & ~0xF0000000) | 0x10000000; + /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */ + gpio->GPECON = (gpio->GPECON & ~0xF0000000) | 0x10000000; #endif #ifdef CONFIG_S3C2400 - /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */ - gpio->PGCON = (gpio->PGCON & ~0x00003c00) | 0x00000c00; + /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */ + gpio->PGCON = (gpio->PGCON & ~0x00003c00) | 0x00000c00; #endif - /* toggle I2CSCL until bus idle */ - SetI2CSCL(0); udelay(1000); - i = 10; - while ((i > 0) && (GetI2CSDA() != 1)) { - SetI2CSCL(1); udelay(1000); - SetI2CSCL(0); udelay(1000); - i--; - } - SetI2CSCL(1); udelay(1000); + /* toggle I2CSCL until bus idle */ + SetI2CSCL (0); + udelay (1000); + i = 10; + while ((i > 0) && (GetI2CSDA () != 1)) { + SetI2CSCL (1); + udelay (1000); + SetI2CSCL (0); + udelay (1000); + i--; + } + SetI2CSCL (1); + udelay (1000); - /* restore pin functions */ + /* restore pin functions */ #ifdef CONFIG_S3C2410 - gpio->GPECON = old_gpecon; + gpio->GPECON = old_gpecon; #endif #ifdef CONFIG_S3C2400 - gpio->PGCON = old_gpecon; + gpio->PGCON = old_gpecon; #endif - } + } - /* calculate prescaler and divisor values */ - freq = get_PCLK(); - if ((freq / pres / (16+1)) > speed) - /* set prescaler to 512 */ - pres = 512; + /* calculate prescaler and divisor values */ + freq = get_PCLK (); + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; - div = 0; - while ((freq / pres / (div+1)) > speed) - div++; + div = 0; + while ((freq / pres / (div + 1)) > speed) + div++; - /* set prescaler, divisor according to freq, also set - ACKGEN, IRQ */ - i2c->IICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0); + /* set prescaler, divisor according to freq, also set + * ACKGEN, IRQ */ + i2c->IICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0); - /* init to SLAVE REVEIVE and set slaveaddr */ - i2c->IICSTAT = 0; - i2c->IICADD = slaveadd; - /* program Master Transmit (and implicit STOP) */ - i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA; + /* init to SLAVE REVEIVE and set slaveaddr */ + i2c->IICSTAT = 0; + i2c->IICADD = slaveadd; + /* program Master Transmit (and implicit STOP) */ + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA; } /* - cmd_type is 0 for write 1 for read. - - addr_len can take any value from 0-255, it is only limited - by the char, we could make it larger if needed. If it is - 0 we skip the address write cycle. - -*/ + * cmd_type is 0 for write, 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + */ static -int i2c_transfer(unsigned char cmd_type, - unsigned char chip, - unsigned char addr[], - unsigned char addr_len, - unsigned char data[], - unsigned short data_len) +int i2c_transfer (unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], unsigned short data_len) { - S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C(); - int i, status, result; - - if (data == 0 || data_len == 0) { - /*Don't support data transfer of no length or to address 0*/ - printf( "i2c_transfer: bad call\n" ); - return I2C_NOK; - } - - /*CheckDelay(); */ - - /* Check I2C bus idle */ - i = I2C_TIMEOUT * 1000; - status = i2c->IICSTAT; - while ((i > 0) && (status & I2CSTAT_BSY)) { - udelay(1000); - status = i2c->IICSTAT; - i--; - } + S3C24X0_I2C *const i2c = S3C24X0_GetBase_I2C (); + int i, status, result; + if (data == 0 || data_len == 0) { + /*Don't support data transfer of no length or to address 0 */ + printf ("i2c_transfer: bad call\n"); + return I2C_NOK; + } - if (status & I2CSTAT_BSY) { - result = I2C_NOK_TOUT; - return(result); - } + /* Check I2C bus idle */ + i = I2C_TIMEOUT * 1000; + status = i2c->IICSTAT; + while ((i > 0) && (status & I2CSTAT_BSY)) { + udelay (1000); + status = i2c->IICSTAT; + i--; + } - i2c->IICCON |= 0x80; + if (status & I2CSTAT_BSY) + return I2C_NOK_TOUT; - result = I2C_OK; + i2c->IICCON |= 0x80; + result = I2C_OK; - switch (cmd_type) { + switch (cmd_type) { case I2C_WRITE: - if (addr && addr_len) { - i2c->IICDS = chip; - /* send START */ - i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP; - i = 0; - while ((i < addr_len) && (result == I2C_OK)) { - result = WaitForXfer(); - i2c->IICDS = addr[i]; - ReadWriteByte(); - i++; - } - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - result = WaitForXfer(); - i2c->IICDS = data[i]; - ReadWriteByte(); - i++; - } - } else { - i2c->IICDS = chip; - /* send START */ - i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP; - i = 0; - while ((i < data_len) && (result = I2C_OK)) { - result = WaitForXfer(); - i2c->IICDS = data[i]; - ReadWriteByte(); - i++; + if (addr && addr_len) { + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP; + i = 0; + while ((i < addr_len) && (result == I2C_OK)) { + result = WaitForXfer (); + i2c->IICDS = addr[i]; + ReadWriteByte (); + i++; + } + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + result = WaitForXfer (); + i2c->IICDS = data[i]; + ReadWriteByte (); + i++; + } + } else { + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP; + i = 0; + while ((i < data_len) && (result = I2C_OK)) { + result = WaitForXfer (); + i2c->IICDS = data[i]; + ReadWriteByte (); + i++; + } } - } - if (result == I2C_OK) - result = WaitForXfer(); + if (result == I2C_OK) + result = WaitForXfer (); - /* send STOP */ - i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; - ReadWriteByte(); - break; + /* send STOP */ + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; + ReadWriteByte (); + break; case I2C_READ: - if (addr && addr_len) { - i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA; - i2c->IICDS = chip; - /* send START */ - i2c->IICSTAT |= I2C_START_STOP; - result = WaitForXfer(); - if (IsACK()) { - i = 0; - while ((i < addr_len) && (result == I2C_OK)) { - i2c->IICDS = addr[i]; - ReadWriteByte(); - result = WaitForXfer(); - i++; - } - - i2c->IICDS = chip; - /* resend START */ - i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP; - ReadWriteByte(); - result = WaitForXfer(); - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - /* disable ACK for final READ */ - if (i == data_len - 1) - i2c->IICCON &= ~0x80; - ReadWriteByte(); - result = WaitForXfer(); - data[i] = i2c->IICDS; - i++; - } - } else { - result = I2C_NACK; - } + if (addr && addr_len) { + i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA; + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT |= I2C_START_STOP; + result = WaitForXfer (); + if (IsACK ()) { + i = 0; + while ((i < addr_len) && (result == I2C_OK)) { + i2c->IICDS = addr[i]; + ReadWriteByte (); + result = WaitForXfer (); + i++; + } + + i2c->IICDS = chip; + /* resend START */ + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA | + I2C_START_STOP; + ReadWriteByte (); + result = WaitForXfer (); + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) + i2c->IICCON &= ~0x80; + ReadWriteByte (); + result = WaitForXfer (); + data[i] = i2c->IICDS; + i++; + } + } else { + result = I2C_NACK; + } - } else { - i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; - i2c->IICDS = chip; - /* send START */ - i2c->IICSTAT |= I2C_START_STOP; - result = WaitForXfer(); - - if (IsACK()) { - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - /* disable ACK for final READ */ - if (i == data_len - 1) - i2c->IICCON &= ~0x80; - ReadWriteByte(); - result = WaitForXfer(); - data[i] = i2c->IICDS; - i++; - } } else { - result = I2C_NACK; + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; + i2c->IICDS = chip; + /* send START */ + i2c->IICSTAT |= I2C_START_STOP; + result = WaitForXfer (); + + if (IsACK ()) { + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) + i2c->IICCON &= ~0x80; + ReadWriteByte (); + result = WaitForXfer (); + data[i] = i2c->IICDS; + i++; + } + } else { + result = I2C_NACK; + } } - } - /* send STOP */ - i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; - ReadWriteByte(); - break; + /* send STOP */ + i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA; + ReadWriteByte (); + break; default: - printf( "i2c_transfer: bad call\n" ); - result = I2C_NOK; - break; - } + printf ("i2c_transfer: bad call\n"); + result = I2C_NOK; + break; + } - return (result); + return (result); } int i2c_probe (uchar chip) { - uchar buf[1]; + uchar buf[1]; - buf[0] = 0; + buf[0] = 0; - /* - * What is needed is to send the chip address and verify that the - * address was <ACK>ed (i.e. there was a chip at that address which - * drove the data line low). - */ - return(i2c_transfer (I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK); + /* + * What is needed is to send the chip address and verify that the + * address was <ACK>ed (i.e. there was a chip at that address which + * drove the data line low). + */ + return (i2c_transfer (I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK); } int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) { - uchar xaddr[4]; - int ret; + uchar xaddr[4]; + int ret; - if ( alen > 4 ) { - printf ("I2C read: addr len %d not supported\n", alen); - return 1; - } - - if ( alen > 0 ) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } + if (alen > 4) { + printf ("I2C read: addr len %d not supported\n", alen); + return 1; + } + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } #ifdef CFG_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. - */ - if( alen > 0 ) - chip |= ((addr >> (alen * 8)) & CFG_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. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); #endif - if( (ret = i2c_transfer(I2C_READ, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) { - printf( "I2c read: failed %d\n", ret); - return 1; - } - return 0; + if ((ret = + i2c_transfer (I2C_READ, chip << 1, &xaddr[4 - alen], alen, + buffer, len)) != 0) { + printf ("I2c read: failed %d\n", ret); + return 1; + } + return 0; } int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) { - uchar xaddr[4]; + uchar xaddr[4]; - if ( alen > 4 ) { - printf ("I2C write: addr len %d not supported\n", alen); - return 1; - } - - if ( alen > 0 ) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } + if (alen > 4) { + printf ("I2C write: addr len %d not supported\n", alen); + return 1; + } + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } #ifdef CFG_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. - */ - if( alen > 0 ) - chip |= ((addr >> (alen * 8)) & CFG_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. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); #endif - return (i2c_transfer(I2C_WRITE, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0); + return (i2c_transfer + (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer, + len) != 0); } - #endif /* CONFIG_HARD_I2C */ #endif /* CONFIG_DRIVER_S3C24X0_I2C */ |