This Patch introduce the new i2c_core file, which holds the I2C core functions, for the rework of the multibus/ multiadapter support. Also adds changes in i2c.h for the new I2C multibus/multiadapter support. This new support can be activated with the CONFIG_SYS_I2C define.
Signed-off-by: Heiko Schocher <h...@denx.de> Signed-off-by: Simon Glass <s...@chromium.org> Cc: Mike Frysinger <vap...@gentoo.org> --- - changes against Simons patches: - gd->cur_i2c_adap now used as "struct i2c_bus_hose *" - get rid of "i2c_cur_bus" add comments from Mike Frysinger: - renamed cur_adap to cur_i2c_adap - use uintx_t types --- arch/arm/include/asm/global_data.h | 3 + arch/avr32/include/asm/global_data.h | 3 + arch/blackfin/include/asm/global_data.h | 4 +- arch/m68k/include/asm/global_data.h | 3 + arch/microblaze/include/asm/global_data.h | 3 + arch/mips/include/asm/global_data.h | 3 + arch/nds32/include/asm/global_data.h | 3 + arch/nios2/include/asm/global_data.h | 3 + arch/powerpc/include/asm/global_data.h | 3 + arch/sh/include/asm/global_data.h | 3 + arch/sparc/include/asm/global_data.h | 3 + arch/x86/include/asm/global_data.h | 3 + drivers/i2c/Makefile | 1 + drivers/i2c/i2c_core.c | 363 +++++++++++++++++++++++++++++ include/i2c.h | 196 +++++++++++++++- 15 files changed, 588 insertions(+), 9 deletions(-) create mode 100644 drivers/i2c/i2c_core.c diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index f8088fe..bc97520 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -82,6 +82,9 @@ typedef struct global_data { unsigned long post_log_res; /* success of POST test */ unsigned long post_init_f_time; /* When post_init_f started */ #endif +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h index 7878bb1..e7da6e4 100644 --- a/arch/avr32/include/asm/global_data.h +++ b/arch/avr32/include/asm/global_data.h @@ -48,6 +48,9 @@ typedef struct global_data { #endif void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h index 290a9e7..f08f493 100644 --- a/arch/blackfin/include/asm/global_data.h +++ b/arch/blackfin/include/asm/global_data.h @@ -54,9 +54,11 @@ typedef struct global_data { unsigned long post_log_res; /* success of POST test */ unsigned long post_init_f_time; /* When post_init_f started */ #endif - void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h index cd55b83..e976bbf 100644 --- a/arch/m68k/include/asm/global_data.h +++ b/arch/m68k/include/asm/global_data.h @@ -66,6 +66,9 @@ typedef struct global_data { #endif void **jt; /* Standalone app jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h index de3b8db..eb5ded5 100644 --- a/arch/microblaze/include/asm/global_data.h +++ b/arch/microblaze/include/asm/global_data.h @@ -46,6 +46,9 @@ typedef struct global_data { unsigned long fb_base; /* base address of frame buffer */ void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h index 6e2cdc7..ad23587 100644 --- a/arch/mips/include/asm/global_data.h +++ b/arch/mips/include/asm/global_data.h @@ -59,6 +59,9 @@ typedef struct global_data { unsigned long env_valid; /* Checksum of Environment valid? */ void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h index 94bd4c2..bac218e 100644 --- a/arch/nds32/include/asm/global_data.h +++ b/arch/nds32/include/asm/global_data.h @@ -63,6 +63,9 @@ typedef struct global_data { void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h index 3b0d9e6..e4c36dc 100644 --- a/arch/nios2/include/asm/global_data.h +++ b/arch/nios2/include/asm/global_data.h @@ -42,6 +42,9 @@ typedef struct global_data { #endif void **jt; /* Standalone app jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h index 5a5877f..f063be9 100644 --- a/arch/powerpc/include/asm/global_data.h +++ b/arch/powerpc/include/asm/global_data.h @@ -182,6 +182,9 @@ typedef struct global_data { #endif void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h index 6e534ad..1929352 100644 --- a/arch/sh/include/asm/global_data.h +++ b/arch/sh/include/asm/global_data.h @@ -42,6 +42,9 @@ typedef struct global_data unsigned long env_valid; /* Checksum of Environment valid */ void **jt; /* Standalone app jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h index 93d3cc0..71432aa 100644 --- a/arch/sparc/include/asm/global_data.h +++ b/arch/sparc/include/asm/global_data.h @@ -74,6 +74,9 @@ typedef struct global_data { #endif void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; #include <asm-generic/global_data_flags.h> diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 6d29c0b..88e9d6c 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -57,6 +57,9 @@ typedef struct global_data { unsigned long reset_status; /* reset status register at boot */ void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_SYS_I2C) + void *cur_i2c_bus; /* current used i2c bus */ +#endif } gd_t; static inline gd_t *get_fs_gd_ptr(void) diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 5dbdbe3..6373306 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -46,6 +46,7 @@ COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o COBJS-$(CONFIG_SH_I2C) += sh_i2c.o COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o +COBJS-$(CONFIG_SYS_I2C) += i2c_core.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c new file mode 100644 index 0000000..cdb6a06 --- /dev/null +++ b/drivers/i2c/i2c_core.c @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2009 Sergey Kubushyn <k...@koi8.net> + * + * Multibus/multiadapter I2C core functions (wrappers) + */ +#include <common.h> +#include <i2c.h> + +struct i2c_adapter *i2c_adap[CONFIG_SYS_NUM_I2C_ADAPTERS] = + CONFIG_SYS_I2C_ADAPTERS; + +struct i2c_bus_hose i2c_bus[CONFIG_SYS_NUM_I2C_BUSSES] = + CONFIG_SYS_I2C_BUSSES; + +DECLARE_GLOBAL_DATA_PTR; + +void i2c_reloc_fixup(void) +{ +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + int i; + unsigned long addr; + + for (i = 0; i < CONFIG_SYS_NUM_I2C_ADAPTERS; i++) { + /* Adapter itself */ + addr = (unsigned long)i2c_adap[i]; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i] = (struct i2c_adapter *)addr; + /* i2c_init() */ + addr = (unsigned long)i2c_adap[i]->init; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i]->init = (void (*)(int, int))addr; + /* i2c_probe() */ + addr = (unsigned long)i2c_adap[i]->probe; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i]->probe = (int (*)(uint8_t))addr; + /* i2c_read() */ + addr = (unsigned long)i2c_adap[i]->read; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i]->read = (int (*)(uint8_t, uint, int, uint8_t *, + int))addr; + /* i2c_write() */ + addr = (unsigned long)i2c_adap[i]->write; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i]->write = (int (*)(uint8_t, uint, int, uint8_t *, + int))addr; + /* i2c_set_bus_speed() */ + addr = (unsigned long)i2c_adap[i]->set_bus_speed; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i]->set_bus_speed = (uint (*)(uint))addr; + /* name */ + addr = (unsigned long)i2c_adap[i]->name; + if (addr != 0) + addr += gd->reloc_off; + + i2c_adap[i]->name = (char *)addr; + } + gd->cur_i2c_bus += gd->reloc_off; +#else + /* + * we need this here to set after relocation gd->cur_i2c_bus + * to the new relocated value. + */ + gd->cur_i2c_bus = NULL; + i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM); +#endif +} + +#ifndef CONFIG_SYS_I2C_DIRECT_BUS +/* + * i2c_mux_set() + * ------------- + * + * This turns on the given channel on I2C multiplexer chip connected to + * a given I2C adapter directly or via other multiplexers. In the latter + * case the entire multiplexer chain must be initialized first starting + * with the one connected directly to the adapter. When disabling a chain + * muxes must be programmed in reverse order, starting with the one + * farthest from the adapter. + * + * mux_id is the multiplexer chip type from defined in i2c.h. So far only + * NXP (Philips) PCA954x multiplexers are supported. Switches are NOT + * supported (anybody uses them?) + */ + +static int i2c_mux_set(struct i2c_adapter *adap, int mux_id, int chip, + int channel) +{ + uint8_t buf; + + /* channel < 0 - turn off the mux */ + if (channel < 0) { + buf = 0; + return adap->write(chip, 0, 0, &buf, 1); + } + + switch (mux_id) { + case I2C_MUX_PCA9540_ID: + case I2C_MUX_PCA9542_ID: + if (channel > 1) + return -1; + buf = (uint8_t)((channel & 0x01) | (1 << 2)); + break; + case I2C_MUX_PCA9544_ID: + if (channel > 3) + return -1; + buf = (uint8_t)((channel & 0x03) | (1 << 2)); + break; + case I2C_MUX_PCA9547_ID: + if (channel > 7) + return -1; + buf = (uint8_t)((channel & 0x07) | (1 << 3)); + break; + default: + return -1; + } + + return adap->write(chip, 0, 0, &buf, 1); +} +#endif + +/* + * i2c_init_bus(): + * --------------- + * + * Initializes one bus. Will initialize the parent adapter. No current bus + * changes, no mux (if any) setup. + */ +static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr) +{ + if (bus_no >= CONFIG_SYS_NUM_I2C_BUSSES) + return; + + I2C_ADAP->init(speed, slaveaddr); + + if (gd->flags & GD_FLG_RELOC) { + I2C_ADAP->init_done = 1; + I2C_ADAP->speed = speed; + I2C_ADAP->slaveaddr = slaveaddr; + } +} + +/* + * i2c_init_all(): + * + * not longer needed, will deleted. Actual init the SPD_BUS + * for compatibility. + * i2c_adap[] must be initialized beforehead with function pointers and + * data, including speed and slaveaddr. + */ +void i2c_init_all(void) +{ + i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM); + return; +} + +/* + * i2c_get_bus_num(): + * ------------------ + * + * Returns index of currently active I2C bus. Zero-based. + */ +unsigned int i2c_get_bus_num(void) +{ + int i = 0; + + if (gd->cur_i2c_bus == NULL) + return CONFIG_SYS_SPD_BUS_NUM; + + while (i < CONFIG_SYS_NUM_I2C_BUSSES) { + if (I2C_BUS == &i2c_bus[i]) + return i; + i++; + } + + return CONFIG_SYS_SPD_BUS_NUM; +} + +/* + * i2c_set_bus_num(): + * ------------------ + * + * Change the active I2C bus. Subsequent read/write calls will + * go to this one. Sets all of the muxes in a proper condition + * if that bus is behind muxes. + * If previously selected bus is behind the muxes turns off all the + * muxes along the path to that bus. + * + * bus - bus index, zero based + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_set_bus_num(unsigned int bus) +{ +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + int i; + uint8_t buf; +#endif + + if (bus >= CONFIG_SYS_NUM_I2C_BUSSES) + return -1; + + if (gd->cur_i2c_bus == NULL) + gd->cur_i2c_bus = &i2c_bus[bus]; + else if ((&i2c_bus[bus] == I2C_BUS) && + (I2C_ADAP->init_done > 0)) + return 0; +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + else { + /* Disconnect current bus (turn off muxes if any) */ + if ((I2C_BUS->next_hop[0].chip != 0) && + (I2C_ADAP->init_done != 0)) { + i = CONFIG_SYS_I2C_MAX_HOPS; + do { + uint8_t chip; + + chip = I2C_BUS->next_hop[--i].chip; + if (chip == 0) + continue; + + I2C_ADAP->write(chip, 0, 0, &buf, 1); + } while (i > 0); + } + } +#endif + + gd->cur_i2c_bus = &i2c_bus[bus]; + if (I2C_ADAP->init_done == 0) + i2c_init_bus(bus, I2C_ADAP->speed, I2C_ADAP->slaveaddr); + +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + /* Connect requested bus if behind muxes */ + if (I2C_BUS->next_hop[0].chip != 0) { + + /* Set all muxes along the path to that bus */ + for (i = 0; i < CONFIG_SYS_I2C_MAX_HOPS; i++) { + int ret; + + if (I2C_BUS->next_hop[i].chip == 0) + break; + + ret = i2c_mux_set(I2C_ADAP, + I2C_BUS->next_hop[i].mux.id, + I2C_BUS->next_hop[i].chip, + I2C_BUS->next_hop[i].channel); + if (ret != 0) { + printf("%s: could not set mux: id: %d "\ + "chip: %x channel: %d\n", __func__, + I2C_BUS->next_hop[i].mux.id, + I2C_BUS->next_hop[i].chip, + I2C_BUS->next_hop[i].channel); + } + } + } +#endif + + return 0; +} + +/* + * Probe the given I2C chip address. Returns 0 if a chip responded, + * not 0 on failure. + */ +int i2c_probe(uint8_t chip) +{ + return I2C_ADAP->probe(chip); +} + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_read(uint8_t chip, unsigned int addr, int alen, + uint8_t *buffer, int len) +{ + return I2C_ADAP->read(chip, addr, alen, buffer, len); +} + +int i2c_write(uint8_t chip, unsigned int addr, int alen, + uint8_t *buffer, int len) +{ + return I2C_ADAP->write(chip, addr, alen, buffer, len); +} + +unsigned int i2c_set_bus_speed(unsigned int speed) +{ + unsigned int ret; + + if (I2C_ADAP->set_bus_speed == NULL) + return 0; + ret = I2C_ADAP->set_bus_speed(speed); + if (gd->flags & GD_FLG_RELOC) + I2C_ADAP->speed = ret; + + return ret; +} + +unsigned int i2c_get_bus_speed(void) +{ + struct i2c_adapter *cur = I2C_ADAP; + return cur->speed; +} + +uint8_t i2c_reg_read(uint8_t addr, uint8_t reg) +{ + uint8_t buf; + +#ifdef CONFIG_8xx + /* MPC8xx needs this. Maybe one day we can get rid of it. */ + /* maybe it is now the time for it ... */ + i2c_set_bus_num(i2c_get_bus_num()); +#endif + i2c_read(addr, reg, 1, &buf, 1); + +#ifdef DEBUG + printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", + __func__, i2c_get_bus_num(), addr, reg, buf); +#endif + + return buf; +} + +void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val) +{ +#ifdef CONFIG_8xx + /* MPC8xx needs this. Maybe one day we can get rid of it. */ + /* maybe it is now the time for it ... */ + i2c_set_bus_num(i2c_get_bus_num()); +#endif + +#ifdef DEBUG + printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", + __func__, i2c_get_bus_num(), addr, reg, val); +#endif + + i2c_write(addr, reg, 1, &val, 1); +} + +void __i2c_init(int speed, int slaveaddr) +{ + i2c_init_bus(i2c_get_bus_num(), speed, slaveaddr); +} +void i2c_init(int speed, int slaveaddr) + __attribute__((weak, alias("__i2c_init"))); diff --git a/include/i2c.h b/include/i2c.h index 16f099d..44a05cd 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -1,4 +1,8 @@ /* + * Copyright (C) 2009 Sergey Kubushyn <k...@koi8.net> + * Copyright (C) 2009 Heiko Schocher <h...@denx.de> + * Changes for multibus/multiadapter I2C support. + * * (C) Copyright 2001 * Gerald Van Baren, Custom IDEAS, vanba...@cideas.com. * @@ -46,16 +50,25 @@ */ #define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */ -#ifdef CONFIG_I2C_MULTI_BUS -#define MAX_I2C_BUS 2 -#define I2C_MULTI_BUS 1 -#else -#define MAX_I2C_BUS 1 -#define I2C_MULTI_BUS 0 +#ifndef CONFIG_SYS_NUM_I2C_ADAPTERS +#define CONFIG_SYS_NUM_I2C_ADAPTERS 1 #endif -#if !defined(CONFIG_SYS_MAX_I2C_BUS) -#define CONFIG_SYS_MAX_I2C_BUS MAX_I2C_BUS +#if !defined(CONFIG_SYS_I2C_MAX_HOPS) +#define CONFIG_SYS_I2C_DIRECT_BUS 1 +#define CONFIG_SYS_I2C_MAX_HOPS 1 +#if !defined(CONFIG_SYS_NUM_I2C_BUSSES) +#define CONFIG_SYS_NUM_I2C_BUSSES CONFIG_SYS_NUM_I2C_ADAPTERS +#define CONFIG_SYS_I2C_BUSSES { {0, {I2C_NULL_HOP} } } +#endif +#else +#undef CONFIG_SYS_I2C_DIRECT_BUS +#ifndef CONFIG_SYS_NUM_I2C_BUSSES +#define CONFIG_SYS_NUM_I2C_BUSSES 1 +#endif +#ifndef CONFIG_SYS_I2C_BUSSES +#define CONFIG_SYS_I2C_BUSSES { {0, {I2C_NULL_HOP} } } +#endif #endif /* define the I2C bus number for RTC and DTT if not already done */ @@ -69,6 +82,59 @@ #define CONFIG_SYS_SPD_BUS_NUM 0 #endif +struct i2c_adapter { + void (*init)(int speed, int slaveaddr); + int (*probe)(uint8_t chip); + int (*read)(uint8_t chip, uint addr, int alen, + uint8_t *buffer, int len); + int (*write)(uint8_t chip, uint addr, int alen, + uint8_t *buffer, int len); + uint (*set_bus_speed)(uint speed); + + int speed; + int slaveaddr; + int init_done; + int hwadapnr; + char *name; +}; + +struct i2c_mux { + int id; + char name[16]; +}; + +struct i2c_next_hop { + struct i2c_mux mux; + uint8_t chip; + uint8_t channel; +}; + +struct i2c_bus_hose { + int adapter; + struct i2c_next_hop next_hop[CONFIG_SYS_I2C_MAX_HOPS]; +}; + +#define I2C_NULL_HOP {{-1, ""}, 0, 0} + +extern struct i2c_bus_hose i2c_bus[]; +extern struct i2c_adapter *i2c_adap[]; + +#define I2C_ADAP_NR(bus) i2c_adap[i2c_bus[bus].adapter] +#define I2C_BUS ((struct i2c_bus_hose *)gd->cur_i2c_bus) +#define I2C_ADAP i2c_adap[I2C_BUS->adapter] +#define I2C_ADAP_HWNR (I2C_ADAP->hwadapnr) + +#ifndef CONFIG_SYS_I2C_DIRECT_BUS +#define I2C_MUX_PCA9540_ID 1 +#define I2C_MUX_PCA9540 {I2C_MUX_PCA9540_ID, "PCA9540B"} +#define I2C_MUX_PCA9542_ID 2 +#define I2C_MUX_PCA9542 {I2C_MUX_PCA9542_ID, "PCA9542A"} +#define I2C_MUX_PCA9544_ID 3 +#define I2C_MUX_PCA9544 {I2C_MUX_PCA9544_ID, "PCA9544A"} +#define I2C_MUX_PCA9547_ID 4 +#define I2C_MUX_PCA9547 {I2C_MUX_PCA9547_ID, "PCA9547A"} +#endif + #ifndef I2C_SOFT_DECLARATIONS # if defined(CONFIG_MPC8260) # define I2C_SOFT_DECLARATIONS volatile ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, I2C_PORT); @@ -134,6 +200,104 @@ int i2x_mux_select_mux(int bus); int i2c_mux_ident_muxstring_f (uchar *buf); #endif +#ifdef CONFIG_SYS_I2C +/* + * Initialization, must be called once on start up, may be called + * repeatedly to change the speed and slave addresses. + */ +void i2c_init(unsigned int speed, int slaveaddr); +#ifdef CONFIG_SYS_I2C_INIT_BOARD +void i2c_init_board(void); +#endif + +/* + * i2c_get_bus_num: + * + * Returns index of currently active I2C bus. Zero-based. + */ +unsigned int i2c_get_bus_num(void); + +/* + * 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(unsigned int bus); + +/* + * i2c_init_all(): + * + * Initializes all I2C adapters in the system. All i2c_adap structures must + * be initialized beforehead with function pointers and data, including + * speed and slaveaddr. Returns 0 on success, non-0 on failure. + */ +void i2c_init_all(void); + +/* + * Probe the given I2C chip address. Returns 0 if a chip responded, + * not 0 on failure. + */ +int i2c_probe(uint8_t chip); + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_read(uint8_t chip, unsigned int addr, int alen, + uint8_t *buffer, int len); + +int i2c_write(uint8_t chip, unsigned int addr, int alen, + uint8_t *buffer, int len); + +/* + * Utility routines to read/write registers. + */ +uint8_t i2c_reg_read(uint8_t addr, uint8_t reg); + +void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val); + +/* + * i2c_set_bus_speed: + * + * Change the speed of the active I2C bus + * + * speed - bus speed in Hz + * + * Returns: new bus speed + * + */ +unsigned int i2c_set_bus_speed(unsigned int speed); + +/* + * i2c_get_bus_speed: + * + * Returns speed of currently active I2C bus in Hz + */ + +unsigned int i2c_get_bus_speed(void); + +/* + * i2c_reloc_fixup: + * + * Adjusts I2C pointers after U-Boot is relocated to DRAM + */ +void i2c_reloc_fixup(void); +#else + /* * Probe the given I2C chip address. Returns 0 if a chip responded, * not 0 on failure. @@ -235,6 +399,22 @@ int i2c_set_bus_speed(unsigned int); */ unsigned int i2c_get_bus_speed(void); +#endif /* CONFIG_SYS_I2C */ + +/* + * only for backwardcompatibility, should go away if we switched + * completely to new multibus support. + */ +#if (CONFIG_SYS_NUM_I2C_BUSSES > 1) || defined(CONFIG_I2C_MULTI_BUS) +# if !defined(CONFIG_SYS_MAX_I2C_BUS) +# define CONFIG_SYS_MAX_I2C_BUS 2 +# endif +# define I2C_MULTI_BUS 0 +#else +# define CONFIG_SYS_MAX_I2C_BUS 1 +# define I2C_MULTI_BUS 0 +#endif + /* NOTE: These two functions MUST be always_inline to avoid code growth! */ static inline unsigned int I2C_GET_BUS(void) __attribute__((always_inline)); -- 1.7.7.6 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot