Add support for multiple I2C buses

Hello,

Attached is a patch providing support for multiple I2C buses at the
command level.  The second part of the patch includes an implementation
for the MPC834x CPU and MPC8349EMDS board.

/*** Note: This patch replaces ticket DNX#2006083042000018 ***/

Signed-off-by: Ben Warren <bwarren@qstreams.com>

Overview:

1. Include new 'i2c' command (based on USB implementation) using
CONFIG_I2C_CMD_TREE.

2. Allow multiple buses by defining CONFIG_I2C_MULTI_BUS.  Note that
the commands to change bus number and speed are only available under the
new 'i2c' command mentioned in the first bullet.

3. The option CFG_I2C_NOPROBES has been expanded to work in multi-bus
systems.  When CONFIG_I2C_MULTI_BUS is used, this option takes the form
of an array of bus-device pairs.  Otherwise, it is an array of uchar.

CHANGELOG:
        Added new 'i2c' master command for all I2C interaction.  This is
conditionally compiled with CONFIG_I2C_CMD_TREE.  New commands added for
setting I2C bus speed as well as changing the active bus if the board
has more than one (conditionally compiled with
CONFIG_I2C_MULTI_BUS).  Updated NOPROBE logic to handle multiple buses.
Updated README.

regards,
Ben
master
Ben Warren 18 years ago committed by Kim Phillips
parent bed85caf87
commit bb99ad6d82
  1. 42
      README
  2. 159
      common/cmd_i2c.c
  3. 45
      include/i2c.h

@ -1207,7 +1207,12 @@ The following options need to be configured:
clock chips. See common/cmd_i2c.c for a description of the
command line interface.
CONFIG_HARD_I2C selects the CPM hardware driver for I2C.
CONFIG_I2C_CMD_TREE is a recommended option that places
all I2C commands under a single 'i2c' root command. The
older 'imm', 'imd', 'iprobe' etc. commands are considered
deprecated and may disappear in the future.
CONFIG_HARD_I2C selects a hardware I2C controller.
CONFIG_SOFT_I2C configures u-boot to use a software (aka
bit-banging) driver instead of CPM or similar hardware
@ -1312,6 +1317,31 @@ The following options need to be configured:
in u-boot bd_info structure based on u-boot environment
variable "i2cfast". (see also i2cfast)
CONFIG_I2C_MULTI_BUS
This option allows the use of multiple I2C buses, each of which
must have a controller. At any point in time, only one bus is
active. To switch to a different bus, use the 'i2c dev' command.
Note that bus numbering is zero-based.
CFG_I2C_NOPROBES
This option specifies a list of I2C devices that will be skipped
when the 'i2c probe' command is issued (or 'iprobe' using the legacy
command). If CONFIG_I2C_MULTI_BUS is set, specify a list of bus-device
pairs. Otherwise, specify a 1D array of device addresses
e.g.
#undef CONFIG_I2C_MULTI_BUS
#define CFG_I2C_NOPROBES {0x50,0x68}
will skip addresses 0x50 and 0x68 on a board with one I2C bus
#define CONFIG_I2C_MULTI_BUS
#define CFG_I2C_MULTI_NOPROBES {{0,0x50},{0,0x68},{1,0x54}}
will skip addresses 0x50 and 0x68 on bus 0 and address 0x54 on bus 1
- SPI Support: CONFIG_SPI
Enables SPI driver (so far only tested with
@ -2209,6 +2239,16 @@ Low Level (hardware related) configuration options:
CFG_POCMR2_MASK_ATTRIB: (MPC826x only)
Overrides the default PCI memory map in cpu/mpc8260/pci.c if set.
- CONFIG_SPD_EEPROM
Get DDR timing information from an I2C EEPROM. Common with pluggable
memory modules such as SODIMMs
SPD_EEPROM_ADDRESS
I2C address of the SPD EEPROM
- CFG_SPD_BUS_NUM
If SPD EEPROM is on an I2C bus other than the first one, specify here.
Note that the value must resolve to something your driver can deal with.
- CONFIG_ETHER_ON_FEC[12]
Define to enable FEC[12] on a 8xx series processor.

@ -101,8 +101,31 @@ static uchar i2c_mm_last_chip;
static uint i2c_mm_last_addr;
static uint i2c_mm_last_alen;
/* If only one I2C bus is present, the list of devices to ignore when
* the probe command is issued is represented by a 1D array of addresses.
* When multiple buses are present, the list is an array of bus-address
* pairs. The following macros take care of this */
#if defined(CFG_I2C_NOPROBES)
#if defined(CONFIG_I2C_MULTI_BUS)
static struct
{
uchar bus;
uchar addr;
} i2c_no_probes[] = CFG_I2C_NOPROBES;
#define GET_BUS_NUM i2c_get_bus_num()
#define COMPARE_BUS(b,i) (i2c_no_probes[(i)].bus == (b))
#define COMPARE_ADDR(a,i) (i2c_no_probes[(i)].addr == (a))
#define NO_PROBE_ADDR(i) i2c_no_probes[(i)].addr
#else /* single bus */
static uchar i2c_no_probes[] = CFG_I2C_NOPROBES;
#define GET_BUS_NUM 0
#define COMPARE_BUS(b,i) ((b) == 0) /* Make compiler happy */
#define COMPARE_ADDR(a,i) (i2c_no_probes[(i)] == (a))
#define NO_PROBE_ADDR(i) i2c_no_probes[(i)]
#endif /* CONFIG_MULTI_BUS */
#define NUM_ELEMENTS_NOPROBE (sizeof(i2c_no_probes)/sizeof(i2c_no_probes[0]))
#endif
static int
@ -538,14 +561,17 @@ int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
int j;
#if defined(CFG_I2C_NOPROBES)
int k, skip;
#endif
uchar bus = GET_BUS_NUM;
#endif /* NOPROBES */
puts ("Valid chip addresses:");
for(j = 0; j < 128; j++) {
#if defined(CFG_I2C_NOPROBES)
skip = 0;
for (k = 0; k < sizeof(i2c_no_probes); k++){
if (j == i2c_no_probes[k]){
for(k=0; k < NUM_ELEMENTS_NOPROBE; k++)
{
if(COMPARE_BUS(bus, k) && COMPARE_ADDR(j, k))
{
skip = 1;
break;
}
@ -561,8 +587,11 @@ int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
#if defined(CFG_I2C_NOPROBES)
puts ("Excluded chip addresses:");
for( k = 0; k < sizeof(i2c_no_probes); k++ )
printf(" %02X", i2c_no_probes[k] );
for(k=0; k < NUM_ELEMENTS_NOPROBE; k++)
{
if(COMPARE_BUS(bus,k))
printf(" %02X", NO_PROBE_ADDR(k));
}
putc ('\n');
#endif
@ -873,6 +902,104 @@ int do_sdram ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
}
#endif /* CFG_CMD_SDRAM */
#if defined(CONFIG_I2C_CMD_TREE)
#if defined(CONFIG_I2C_MULTI_BUS)
int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int bus_idx, ret=0;
if (argc == 1) /* querying current setting */
{
printf("Current bus is %d\n", i2c_get_bus_num());
}
else
{
bus_idx = simple_strtoul(argv[1], NULL, 10);
printf("Setting bus to %d\n", bus_idx);
ret = i2c_set_bus_num(bus_idx);
if(ret)
{
printf("Failure changing bus number (%d)\n", ret);
}
}
return ret;
}
#endif /* CONFIG_I2C_MULTI_BUS */
int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int speed, ret=0;
if (argc == 1) /* querying current speed */
{
printf("Current bus speed=%d\n", i2c_get_bus_speed());
}
else
{
speed = simple_strtoul(argv[1], NULL, 10);
printf("Setting bus speed to %d Hz\n", speed);
ret = i2c_set_bus_speed(speed);
if(ret)
{
printf("Failure changing bus speed (%d)\n", ret);
}
}
return ret;
}
int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
#if defined(CONFIG_I2C_MULTI_BUS)
if(!strncmp(argv[1], "de", 2))
{
return do_i2c_bus_num(cmdtp, flag, --argc, ++argv);
}
#endif /* CONFIG_I2C_MULTI_BUS */
if(!strncmp(argv[1], "sp", 2))
{
return do_i2c_bus_speed(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "md", 2))
{
return do_i2c_md(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "mm", 2))
{
return do_i2c_mm(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "mw", 2))
{
return do_i2c_mw(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "nm", 2))
{
return do_i2c_nm(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "cr", 2))
{
return do_i2c_crc(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "pr", 2))
{
return do_i2c_probe(cmdtp, flag, --argc, ++argv);
}
if(!strncmp(argv[1], "lo", 2))
{
return do_i2c_loop(cmdtp, flag, --argc, ++argv);
}
#if (CONFIG_COMMANDS & CFG_CMD_SDRAM)
if(!strncmp(argv[1], "sd", 2))
{
return do_sdram(cmdtp, flag, --argc, ++argv);
}
#endif /* CFG_CMD_SDRAM */
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
}
return 0;
}
#endif /* CONFIG_I2C_CMD_TREE */
/***************************************************/
@ -930,4 +1057,26 @@ U_BOOT_CMD(
" (valid chip values 50..57)\n"
);
#endif
#if defined(CONFIG_I2C_CMD_TREE)
U_BOOT_CMD(
i2c, 6, 1, do_i2c,
"i2c - I2C sub-system\n",
#if defined(CONFIG_I2C_MULTI_BUS)
"dev [dev] - show or set current I2C bus\n"
#endif /* CONFIG_I2C_MULTI_BUS */
"i2c speed [speed] - show or set I2C bus speed\n"
"i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n"
"i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n"
"i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)\n"
"i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n"
"i2c crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n"
"i2c probe - show devices on the I2C bus\n"
"i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device\n"
#if (CONFIG_COMMANDS & CFG_CMD_SDRAM)
"i2c sdram chip - print SDRAM configuration information\n"
#endif /* CFG_CMD_SDRAM */
);
#endif /* CONFIG_I2C_CMD_TREE */
#endif /* CFG_CMD_I2C */

@ -82,4 +82,49 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len);
uchar i2c_reg_read (uchar chip, uchar reg);
void i2c_reg_write(uchar chip, uchar reg, uchar val);
/*
* Functions for setting the current I2C bus and its speed
*/
/*
* i2c_set_bus_num:
*
* Change the active I2C bus. Subsequent read/write calls will
* go to this one.
*
* bus - bus index, zero based
*
* Returns: 0 on success, not 0 on failure
*
*/
int i2c_set_bus_num(uchar bus);
/*
* i2c_get_bus_num:
*
* Returns index of currently active I2C bus. Zero-based.
*/
uchar i2c_get_bus_num(void);
/*
* i2c_set_bus_speed:
*
* Change the speed of the active I2C bus
*
* speed - bus speed in Hz
*
* Returns: 0 on success, not 0 on failure
*
*/
int i2c_set_bus_speed(int);
/*
* i2c_get_bus_speed:
*
* Returns speed of currently active I2C bus in Hz
*/
int i2c_get_bus_speed(void);
#endif /* _I2C_H_ */

Loading…
Cancel
Save