From b0e6ef46405353270595ffa35c21f4334c541189 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 10 Dec 2014 08:55:57 -0700 Subject: [PATCH] dm: i2c: tegra: Convert to driver model This converts all Tegra boards over to use driver model for I2C. The driver is adjusted to use driver model and the following obsolete CONFIGs are removed: - CONFIG_SYS_I2C_INIT_BOARD - CONFIG_I2C_MULTI_BUS - CONFIG_SYS_MAX_I2C_BUS - CONFIG_SYS_I2C_SPEED - CONFIG_SYS_I2C This has been tested on: - trimslice (no I2C) - beaver - Jetson-TK1 It has not been tested on Tegra 114 as I don't have that board. Acked-by: Heiko Schocher Signed-off-by: Simon Glass --- arch/arm/cpu/tegra20-common/pmu.c | 21 +- arch/arm/dts/tegra124-jetson-tk1.dts | 1 - arch/arm/dts/tegra30-tec-ng.dts | 4 + arch/arm/include/asm/arch-tegra/tegra_i2c.h | 2 +- board/avionic-design/common/tamonten-ng.c | 12 +- board/nvidia/cardhu/cardhu.c | 13 +- board/nvidia/common/board.c | 4 - board/nvidia/dalmore/dalmore.c | 21 +- board/nvidia/whistler/whistler.c | 29 ++- board/toradex/apalis_t30/apalis_t30.c | 19 +- drivers/i2c/tegra_i2c.c | 366 +++++++++------------------- drivers/power/tps6586x.c | 27 +- include/configs/apalis_t30.h | 3 - include/configs/beaver.h | 3 - include/configs/cardhu.h | 5 - include/configs/colibri_t30.h | 3 - include/configs/dalmore.h | 5 - include/configs/jetson-tk1.h | 5 - include/configs/nyan-big.h | 5 - include/configs/seaboard.h | 3 - include/configs/tec-ng.h | 5 - include/configs/tegra-common.h | 1 + include/configs/tegra114-common.h | 3 - include/configs/tegra124-common.h | 3 - include/configs/tegra20-common.h | 3 - include/configs/tegra30-common.h | 3 - include/configs/trimslice.h | 3 - include/configs/venice2.h | 5 - include/configs/whistler.h | 3 - include/tps6586x.h | 4 +- 30 files changed, 210 insertions(+), 374 deletions(-) diff --git a/arch/arm/cpu/tegra20-common/pmu.c b/arch/arm/cpu/tegra20-common/pmu.c index c595f70..36a76a2 100644 --- a/arch/arm/cpu/tegra20-common/pmu.c +++ b/arch/arm/cpu/tegra20-common/pmu.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -23,9 +24,13 @@ #define VDD_TRANSITION_STEP 0x06 /* 150mv */ #define VDD_TRANSITION_RATE 0x06 /* 3.52mv/us */ +#define PMI_I2C_ADDRESS 0x34 /* chip requires this address */ + int pmu_set_nominal(void) { - int core, cpu, bus; + struct udevice *bus, *dev; + int core, cpu; + int ret; /* by default, the table has been filled with T25 settings */ switch (tegra_get_chip_sku()) { @@ -42,12 +47,18 @@ int pmu_set_nominal(void) return -1; } - bus = tegra_i2c_get_dvc_bus_num(); - if (bus == -1) { + ret = tegra_i2c_get_dvc_bus(&bus); + if (ret) { debug("%s: Cannot find DVC I2C bus\n", __func__); - return -1; + return ret; } - tps6586x_init(bus); + ret = i2c_get_chip(bus, PMI_I2C_ADDRESS, &dev); + if (ret) { + debug("%s: Cannot find DVC I2C chip\n", __func__); + return ret; + } + + tps6586x_init(dev); tps6586x_set_pwm_mode(TPS6586X_PWM_SM1); return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP, VDD_TRANSITION_RATE, VDD_RELATION); diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts index ffad116..f6fe9a0 100644 --- a/arch/arm/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/dts/tegra124-jetson-tk1.dts @@ -16,7 +16,6 @@ i2c2 = "/i2c@7000c400"; i2c3 = "/i2c@7000c500"; i2c4 = "/i2c@7000c700"; - i2c5 = "/i2c@7000d100"; sdhci0 = "/sdhci@700b0600"; sdhci1 = "/sdhci@700b0400"; spi0 = "/spi@7000d400"; diff --git a/arch/arm/dts/tegra30-tec-ng.dts b/arch/arm/dts/tegra30-tec-ng.dts index 8a69e81..e924acc 100644 --- a/arch/arm/dts/tegra30-tec-ng.dts +++ b/arch/arm/dts/tegra30-tec-ng.dts @@ -6,6 +6,10 @@ model = "Avionic Design Tamonten™ NG Evaluation Carrier"; compatible = "ad,tec-ng", "nvidia,tegra30"; + aliases { + i2c0 = "/i2c@7000c400"; + }; + /* GEN2 */ i2c@7000c400 { status = "okay"; diff --git a/arch/arm/include/asm/arch-tegra/tegra_i2c.h b/arch/arm/include/asm/arch-tegra/tegra_i2c.h index 7ca6907..eeeb247 100644 --- a/arch/arm/include/asm/arch-tegra/tegra_i2c.h +++ b/arch/arm/include/asm/arch-tegra/tegra_i2c.h @@ -167,6 +167,6 @@ struct i2c_ctlr { * * @return number of bus, or -1 if there is no DVC active */ -int tegra_i2c_get_dvc_bus_num(void); +int tegra_i2c_get_dvc_bus(struct udevice **busp); #endif /* _TEGRA_I2C_H_ */ diff --git a/board/avionic-design/common/tamonten-ng.c b/board/avionic-design/common/tamonten-ng.c index 5870b95..86a0844 100644 --- a/board/avionic-design/common/tamonten-ng.c +++ b/board/avionic-design/common/tamonten-ng.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -51,8 +52,15 @@ void gpio_early_init(void) void pmu_write(uchar reg, uchar data) { - i2c_set_bus_num(4); /* PMU is on bus 4 */ - i2c_write(PMU_I2C_ADDRESS, reg, 1, &data, 1); + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(4, PMU_I2C_ADDRESS, &dev); + if (ret) { + debug("%s: Cannot find PMIC I2C chip\n", __func__); + return; + } + i2c_write(dev, reg, &data, 1); } /* diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c index cc0e5e1..026f45c 100644 --- a/board/nvidia/cardhu/cardhu.c +++ b/board/nvidia/cardhu/cardhu.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include "pinmux-config-cardhu.h" @@ -37,17 +38,23 @@ void pinmux_init(void) */ void board_sdmmc_voltage_init(void) { + struct udevice *dev; uchar reg, data_buffer[1]; + int ret; int i; - i2c_set_bus_num(0); /* PMU is on bus 0 */ + ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev); + if (ret) { + debug("%s: Cannot find PMIC I2C chip\n", __func__); + return; + } /* TPS659110: LDO5_REG = 3.3v, ACTIVE to SDMMC1 */ data_buffer[0] = 0x65; reg = 0x32; for (i = 0; i < MAX_I2C_RETRY; ++i) { - if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + if (i2c_write(dev, reg, data_buffer, 1)) udelay(100); } @@ -56,7 +63,7 @@ void board_sdmmc_voltage_init(void) reg = 0x67; for (i = 0; i < MAX_I2C_RETRY; ++i) { - if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + if (i2c_write(dev, reg, data_buffer, 1)) udelay(100); } } diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 0e4a65a..4bdbf01 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -113,10 +113,6 @@ int board_init(void) power_det_init(); #ifdef CONFIG_SYS_I2C_TEGRA -#ifndef CONFIG_SYS_I2C_INIT_BOARD -#error "You must define CONFIG_SYS_I2C_INIT_BOARD to use i2c on Nvidia boards" -#endif - i2c_init_board(); # ifdef CONFIG_TEGRA_PMU if (pmu_set_nominal()) debug("Failed to select nominal voltages\n"); diff --git a/board/nvidia/dalmore/dalmore.c b/board/nvidia/dalmore/dalmore.c index f2d05af..2a73746 100644 --- a/board/nvidia/dalmore/dalmore.c +++ b/board/nvidia/dalmore/dalmore.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include "pinmux-config-dalmore.h" @@ -50,18 +51,21 @@ void pinmux_init(void) */ void board_sdmmc_voltage_init(void) { + struct udevice *dev; uchar reg, data_buffer[1]; int ret; - ret = i2c_set_bus_num(0);/* PMU is on bus 0 */ - if (ret) - printf("%s: i2c_set_bus_num returned %d\n", __func__, ret); + ret = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev); + if (ret) { + debug("%s: Cannot find PMIC I2C chip\n", __func__); + return; + } /* TPS65913: LDO9_VOLTAGE = 3.3V */ data_buffer[0] = 0x31; reg = 0x61; - ret = i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1); + ret = i2c_write(dev, reg, data_buffer, 1); if (ret) printf("%s: PMU i2c_write %02X<-%02X returned %d\n", __func__, reg, data_buffer[0], ret); @@ -70,7 +74,7 @@ void board_sdmmc_voltage_init(void) data_buffer[0] = 0x01; reg = 0x60; - ret = i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1); + ret = i2c_write(dev, reg, data_buffer, 1); if (ret) printf("%s: PMU i2c_write %02X<-%02X returned %d\n", __func__, reg, data_buffer[0], ret); @@ -79,7 +83,12 @@ void board_sdmmc_voltage_init(void) data_buffer[0] = 0x03; reg = 0x14; - ret = i2c_write(BAT_I2C_ADDRESS, reg, 1, data_buffer, 1); + ret = i2c_get_chip_for_busnum(0, BAT_I2C_ADDRESS, &dev); + if (ret) { + debug("%s: Cannot find charger I2C chip\n", __func__); + return; + } + ret = i2c_write(dev, reg, data_buffer, 1); if (ret) printf("%s: BAT i2c_write %02X<-%02X returned %d\n", __func__, reg, data_buffer[0], ret); diff --git a/board/nvidia/whistler/whistler.c b/board/nvidia/whistler/whistler.c index 3e9d3d9..3114b20 100644 --- a/board/nvidia/whistler/whistler.c +++ b/board/nvidia/whistler/whistler.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -21,23 +22,26 @@ */ void pin_mux_mmc(void) { + struct udevice *dev; uchar val; int ret; /* Turn on MAX8907B LDO12 to 2.8V for J40 power */ - ret = i2c_set_bus_num(0); - if (ret) - printf("i2c_set_bus_num failed: %d\n", ret); + ret = i2c_get_chip_for_busnum(0, 0x3c, &dev); + if (ret) { + printf("%s: Cannot find MAX8907B I2C chip\n", __func__); + return; + } val = 0x29; - ret = i2c_write(0x3c, 0x46, 1, &val, 1); + ret = i2c_write(dev, 0x46, &val, 1); if (ret) printf("i2c_write 0 0x3c 0x46 failed: %d\n", ret); val = 0x00; - ret = i2c_write(0x3c, 0x45, 1, &val, 1); + ret = i2c_write(dev, 0x45, &val, 1); if (ret) printf("i2c_write 0 0x3c 0x45 failed: %d\n", ret); val = 0x1f; - ret = i2c_write(0x3c, 0x44, 1, &val, 1); + ret = i2c_write(dev, 0x44, &val, 1); if (ret) printf("i2c_write 0 0x3c 0x44 failed: %d\n", ret); @@ -49,6 +53,7 @@ void pin_mux_mmc(void) /* this is a weak define that we are overriding */ void pin_mux_usb(void) { + struct udevice *dev; uchar val; int ret; @@ -59,15 +64,17 @@ void pin_mux_usb(void) */ /* Turn on TAC6416's GPIO 0+1 for USB1/3's VBUS */ - ret = i2c_set_bus_num(0); - if (ret) - printf("i2c_set_bus_num failed: %d\n", ret); + ret = i2c_get_chip_for_busnum(0, 0x20, &dev); + if (ret) { + printf("%s: Cannot find TAC6416 I2C chip\n", __func__); + return; + } val = 0x03; - ret = i2c_write(0x20, 2, 1, &val, 1); + ret = i2c_write(dev, 2, &val, 1); if (ret) printf("i2c_write 0 0x20 2 failed: %d\n", ret); val = 0xfc; - ret = i2c_write(0x20, 6, 1, &val, 1); + ret = i2c_write(dev, 6, &val, 1); if (ret) printf("i2c_write 0 0x20 6 failed: %d\n", ret); } diff --git a/board/toradex/apalis_t30/apalis_t30.c b/board/toradex/apalis_t30/apalis_t30.c index b9d694a..5d2c024 100644 --- a/board/toradex/apalis_t30/apalis_t30.c +++ b/board/toradex/apalis_t30/apalis_t30.c @@ -6,7 +6,7 @@ */ #include - +#include #include #include #include @@ -38,23 +38,20 @@ void pinmux_init(void) #ifdef CONFIG_PCI_TEGRA int tegra_pcie_board_init(void) { - unsigned int old_bus; + struct udevice *dev; u8 addr, data[1]; int err; - old_bus = i2c_get_bus_num(); - - err = i2c_set_bus_num(0); + err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev); if (err) { - debug("failed to set I2C bus\n"); + debug("%s: Cannot find PMIC I2C chip\n", __func__); return err; } - /* TPS659110: VDD2_OP_REG = 1.05V */ data[0] = 0x27; addr = 0x25; - err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1); + err = i2c_write(dev, addr, data, 1); if (err) { debug("failed to set VDD supply\n"); return err; @@ -64,7 +61,7 @@ int tegra_pcie_board_init(void) data[0] = 0x0D; addr = 0x24; - err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1); + err = i2c_write(dev, addr, data, 1); if (err) { debug("failed to enable VDD supply\n"); return err; @@ -74,14 +71,12 @@ int tegra_pcie_board_init(void) data[0] = 0x0D; addr = 0x35; - err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1); + err = i2c_write(dev, addr, data, 1); if (err) { debug("failed to set AVDD supply\n"); return err; } - i2c_set_bus_num(old_bus); - return 0; } diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c index 562211e..87290c3 100644 --- a/drivers/i2c/tegra_i2c.c +++ b/drivers/i2c/tegra_i2c.c @@ -7,6 +7,8 @@ */ #include +#include +#include #include #include #include @@ -19,6 +21,12 @@ DECLARE_GLOBAL_DATA_PTR; +enum i2c_type { + TYPE_114, + TYPE_STD, + TYPE_DVC, +}; + /* Information about i2c controller */ struct i2c_bus { int id; @@ -27,20 +35,17 @@ struct i2c_bus { int pinmux_config; struct i2c_control *control; struct i2c_ctlr *regs; - int is_dvc; /* DVC type, rather than I2C */ - int is_scs; /* single clock source (T114+) */ + enum i2c_type type; int inited; /* bus is inited */ }; -static struct i2c_bus i2c_controllers[TEGRA_I2C_NUM_CONTROLLERS]; - static void set_packet_mode(struct i2c_bus *i2c_bus) { u32 config; config = I2C_CNFG_NEW_MASTER_FSM_MASK | I2C_CNFG_PACKET_MODE_MASK; - if (i2c_bus->is_dvc) { + if (i2c_bus->type == TYPE_DVC) { struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs; writel(config, &dvc->cnfg); @@ -65,6 +70,9 @@ static void i2c_reset_controller(struct i2c_bus *i2c_bus) static void i2c_init_controller(struct i2c_bus *i2c_bus) { + if (!i2c_bus->speed) + return; + debug("%s: speed=%d\n", __func__, i2c_bus->speed); /* * Use PLLP - DP-04508-001_v06 datasheet indicates a divisor of 8 * here, in section 23.3.1, but in fact we seem to need a factor of @@ -73,7 +81,7 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus) clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH, i2c_bus->speed * 2 * 8); - if (i2c_bus->is_scs) { + if (i2c_bus->type == TYPE_114) { /* * T114 I2C went to a single clock source for standard/fast and * HS clock speeds. The new clock rate setting calculation is: @@ -98,7 +106,7 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus) i2c_reset_controller(i2c_bus); /* Configure I2C controller. */ - if (i2c_bus->is_dvc) { /* only for DVC I2C */ + if (i2c_bus->type == TYPE_DVC) { /* only for DVC I2C */ struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs; setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK); @@ -272,7 +280,7 @@ exit: return error; } -static int tegra_i2c_write_data(struct i2c_bus *bus, u32 addr, u8 *data, +static int tegra_i2c_write_data(struct i2c_bus *i2c_bus, u32 addr, u8 *data, u32 len, bool end_with_repeated_start) { int error; @@ -286,14 +294,14 @@ static int tegra_i2c_write_data(struct i2c_bus *bus, u32 addr, u8 *data, trans_info.num_bytes = len; trans_info.is_10bit_address = 0; - error = send_recv_packets(bus, &trans_info); + error = send_recv_packets(i2c_bus, &trans_info); if (error) debug("tegra_i2c_write_data: Error (%d) !!!\n", error); return error; } -static int tegra_i2c_read_data(struct i2c_bus *bus, u32 addr, u8 *data, +static int tegra_i2c_read_data(struct i2c_bus *i2c_bus, u32 addr, u8 *data, u32 len) { int error; @@ -305,52 +313,32 @@ static int tegra_i2c_read_data(struct i2c_bus *bus, u32 addr, u8 *data, trans_info.num_bytes = len; trans_info.is_10bit_address = 0; - error = send_recv_packets(bus, &trans_info); + error = send_recv_packets(i2c_bus, &trans_info); if (error) debug("tegra_i2c_read_data: Error (%d) !!!\n", error); return error; } -#ifndef CONFIG_OF_CONTROL -#error "Please enable device tree support to use this driver" -#endif - -/** - * Check that a bus number is valid and return a pointer to it - * - * @param bus_num Bus number to check / return - * @return pointer to bus, if valid, else NULL - */ -static struct i2c_bus *tegra_i2c_get_bus(struct i2c_adapter *adap) +static int tegra_i2c_set_bus_speed(struct udevice *dev, unsigned int speed) { - struct i2c_bus *bus; + struct i2c_bus *i2c_bus = dev_get_priv(dev); - bus = &i2c_controllers[adap->hwadapnr]; - if (!bus->inited) { - debug("%s: Bus %u not available\n", __func__, adap->hwadapnr); - return NULL; - } - - return bus; -} - -static unsigned int tegra_i2c_set_bus_speed(struct i2c_adapter *adap, - unsigned int speed) -{ - struct i2c_bus *bus; - - bus = tegra_i2c_get_bus(adap); - if (!bus) - return 0; - bus->speed = speed; - i2c_init_controller(bus); + i2c_bus->speed = speed; + i2c_init_controller(i2c_bus); return 0; } -static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus) +static int tegra_i2c_probe(struct udevice *dev) { + struct i2c_bus *i2c_bus = dev_get_priv(dev); + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + bool is_dvc; + + i2c_bus->id = dev->seq; + i2c_bus->type = dev_get_of_data(dev); i2c_bus->regs = (struct i2c_ctlr *)fdtdec_get_addr(blob, node, "reg"); /* @@ -358,7 +346,6 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus) * far no one needs anything other than the default. */ i2c_bus->pinmux_config = FUNCMUX_DEFAULT; - i2c_bus->speed = fdtdec_get_int(blob, node, "clock-frequency", 0); i2c_bus->periph_id = clock_decode_periph_id(blob, node); /* @@ -371,107 +358,25 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus) * i2c_bus->pinmux_config = FUNCMUX_I2C2_PTA; */ if (i2c_bus->periph_id == -1) - return -FDT_ERR_NOTFOUND; + return -EINVAL; - return 0; -} - -/* - * Process a list of nodes, adding them to our list of I2C ports. - * - * @param blob fdt blob - * @param node_list list of nodes to process (any <=0 are ignored) - * @param count number of nodes to process - * @param is_dvc 1 if these are DVC ports, 0 if standard I2C - * @param is_scs 1 if this HW uses a single clock source (T114+) - * @return 0 if ok, -1 on error - */ -static int process_nodes(const void *blob, int node_list[], int count, - int is_dvc, int is_scs) -{ - struct i2c_bus *i2c_bus; - int i; - - /* build the i2c_controllers[] for each controller */ - for (i = 0; i < count; i++) { - int node = node_list[i]; - - if (node <= 0) - continue; - - i2c_bus = &i2c_controllers[i]; - i2c_bus->id = i; - - if (i2c_get_config(blob, node, i2c_bus)) { - printf("i2c_init_board: failed to decode bus %d\n", i); - return -1; - } - - i2c_bus->is_scs = is_scs; - - i2c_bus->is_dvc = is_dvc; - if (is_dvc) { - i2c_bus->control = - &((struct dvc_ctlr *)i2c_bus->regs)->control; - } else { - i2c_bus->control = &i2c_bus->regs->control; - } - debug("%s: controller bus %d at %p, periph_id %d, speed %d: ", - is_dvc ? "dvc" : "i2c", i, i2c_bus->regs, - i2c_bus->periph_id, i2c_bus->speed); - i2c_init_controller(i2c_bus); - debug("ok\n"); - i2c_bus->inited = 1; - - /* Mark position as used */ - node_list[i] = -1; + is_dvc = dev_get_of_data(dev) == TYPE_DVC; + if (is_dvc) { + i2c_bus->control = + &((struct dvc_ctlr *)i2c_bus->regs)->control; + } else { + i2c_bus->control = &i2c_bus->regs->control; } + i2c_init_controller(i2c_bus); + debug("%s: controller bus %d at %p, periph_id %d, speed %d: ", + is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs, + i2c_bus->periph_id, i2c_bus->speed); return 0; } -/* Sadly there is no error return from this function */ -void i2c_init_board(void) -{ - int node_list[TEGRA_I2C_NUM_CONTROLLERS]; - const void *blob = gd->fdt_blob; - int count; - - /* First check for newer (T114+) I2C ports */ - count = fdtdec_find_aliases_for_id(blob, "i2c", - COMPAT_NVIDIA_TEGRA114_I2C, node_list, - TEGRA_I2C_NUM_CONTROLLERS); - if (process_nodes(blob, node_list, count, 0, 1)) - return; - - /* Now get the older (T20/T30) normal I2C ports */ - count = fdtdec_find_aliases_for_id(blob, "i2c", - COMPAT_NVIDIA_TEGRA20_I2C, node_list, - TEGRA_I2C_NUM_CONTROLLERS); - if (process_nodes(blob, node_list, count, 0, 0)) - return; - - /* Now look for dvc ports */ - count = fdtdec_add_aliases_for_id(blob, "i2c", - COMPAT_NVIDIA_TEGRA20_DVC, node_list, - TEGRA_I2C_NUM_CONTROLLERS); - if (process_nodes(blob, node_list, count, 1, 0)) - return; -} - -static void tegra_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) -{ - /* No i2c support prior to relocation */ - if (!(gd->flags & GD_FLG_RELOC)) - return; - - /* This will override the speed selected in the fdt for that port */ - debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr); - i2c_set_bus_speed(speed); -} - /* i2c write version without the register address */ -static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, +static int i2c_write_data(struct i2c_bus *i2c_bus, uchar chip, uchar *buffer, int len, bool end_with_repeated_start) { int rc; @@ -484,7 +389,7 @@ static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, debug("\n"); /* Shift 7-bit address over for lower-level i2c functions */ - rc = tegra_i2c_write_data(bus, chip << 1, buffer, len, + rc = tegra_i2c_write_data(i2c_bus, chip << 1, buffer, len, end_with_repeated_start); if (rc) debug("i2c_write_data(): rc=%d\n", rc); @@ -493,14 +398,14 @@ static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, } /* i2c read version without the register address */ -static int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer, - int len) +static int i2c_read_data(struct i2c_bus *i2c_bus, uchar chip, uchar *buffer, + int len) { int rc; debug("inside i2c_read_data():\n"); /* Shift 7-bit address over for lower-level i2c functions */ - rc = tegra_i2c_read_data(bus, chip << 1, buffer, len); + rc = tegra_i2c_read_data(i2c_bus, chip << 1, buffer, len); if (rc) { debug("i2c_read_data(): rc=%d\n", rc); return rc; @@ -516,132 +421,99 @@ static int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer, } /* Probe to see if a chip is present. */ -static int tegra_i2c_probe(struct i2c_adapter *adap, uchar chip) +static int tegra_i2c_probe_chip(struct udevice *bus, uint chip_addr, + uint chip_flags) { - struct i2c_bus *bus; + struct i2c_bus *i2c_bus = dev_get_priv(bus); int rc; - uchar reg; - - debug("i2c_probe: addr=0x%x\n", chip); - bus = tegra_i2c_get_bus(adap); - if (!bus) - return 1; - reg = 0; - rc = i2c_write_data(bus, chip, ®, 1, false); - if (rc) { - debug("Error probing 0x%x.\n", chip); - return 1; - } - return 0; -} + u8 reg; -static int i2c_addr_ok(const uint addr, const int alen) -{ - /* We support 7 or 10 bit addresses, so one or two bytes each */ - return alen == 1 || alen == 2; + /* Shift 7-bit address over for lower-level i2c functions */ + rc = tegra_i2c_write_data(i2c_bus, chip_addr << 1, ®, sizeof(reg), + false); + + return rc; } -/* Read bytes */ -static int tegra_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buffer, int len) +static int tegra_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, + int nmsgs) { - struct i2c_bus *bus; - uint offset; - int i; - - debug("i2c_read: chip=0x%x, addr=0x%x, alen=0x%x len=0x%x\n", - chip, addr, alen, len); - bus = tegra_i2c_get_bus(adap); - if (!bus) - return 1; - if (!i2c_addr_ok(addr, alen)) { - debug("i2c_read: Bad address %x.%d.\n", addr, alen); - return 1; - } - for (offset = 0; offset < len; offset++) { - if (alen) { - uchar data[alen]; - for (i = 0; i < alen; i++) { - data[alen - i - 1] = - (addr + offset) >> (8 * i); - } - if (i2c_write_data(bus, chip, data, alen, true)) { - debug("i2c_read: error sending (0x%x)\n", - addr); - return 1; - } + struct i2c_bus *i2c_bus = dev_get_priv(bus); + int ret; + + debug("i2c_xfer: %d messages\n", nmsgs); + for (; nmsgs > 0; nmsgs--, msg++) { + bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD); + + debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); + if (msg->flags & I2C_M_RD) { + ret = i2c_read_data(i2c_bus, msg->addr, msg->buf, + msg->len); + } else { + ret = i2c_write_data(i2c_bus, msg->addr, msg->buf, + msg->len, next_is_read); } - if (i2c_read_data(bus, chip, buffer + offset, 1)) { - debug("i2c_read: error reading (0x%x)\n", addr); - return 1; + if (ret) { + debug("i2c_write: error sending\n"); + return -EREMOTEIO; } } return 0; } -/* Write bytes */ -static int tegra_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buffer, int len) +int tegra_i2c_get_dvc_bus(struct udevice **busp) { - struct i2c_bus *bus; - uint offset; - int i; - - debug("i2c_write: chip=0x%x, addr=0x%x, alen=0x%x len=0x%x\n", - chip, addr, alen, len); - bus = tegra_i2c_get_bus(adap); - if (!bus) - return 1; - if (!i2c_addr_ok(addr, alen)) { - debug("i2c_write: Bad address %x.%d.\n", addr, alen); - return 1; - } - for (offset = 0; offset < len; offset++) { - uchar data[alen + 1]; - for (i = 0; i < alen; i++) - data[alen - i - 1] = (addr + offset) >> (8 * i); - data[alen] = buffer[offset]; - if (i2c_write_data(bus, chip, data, alen + 1, false)) { - debug("i2c_write: error sending (0x%x)\n", addr); - return 1; + struct udevice *bus; + + for (uclass_first_device(UCLASS_I2C, &bus); + bus; + uclass_next_device(&bus)) { + if (dev_get_of_data(bus) == TYPE_DVC) { + *busp = bus; + return 0; } } - return 0; + return -ENODEV; } -int tegra_i2c_get_dvc_bus_num(void) -{ - int i; +static const struct dm_i2c_ops tegra_i2c_ops = { + .xfer = tegra_i2c_xfer, + .probe_chip = tegra_i2c_probe_chip, + .set_bus_speed = tegra_i2c_set_bus_speed, +}; - for (i = 0; i < TEGRA_I2C_NUM_CONTROLLERS; i++) { - struct i2c_bus *bus = &i2c_controllers[i]; +static int tegra_i2c_child_pre_probe(struct udevice *dev) +{ + struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev); - if (bus->inited && bus->is_dvc) - return i; - } + if (dev->of_offset == -1) + return 0; + return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, + i2c_chip); +} - return -1; +static int tegra_i2c_ofdata_to_platdata(struct udevice *dev) +{ + return 0; } -/* - * Register soft i2c adapters - */ -U_BOOT_I2C_ADAP_COMPLETE(tegra0, tegra_i2c_init, tegra_i2c_probe, - tegra_i2c_read, tegra_i2c_write, - tegra_i2c_set_bus_speed, 100000, 0, 0) -U_BOOT_I2C_ADAP_COMPLETE(tegra1, tegra_i2c_init, tegra_i2c_probe, - tegra_i2c_read, tegra_i2c_write, - tegra_i2c_set_bus_speed, 100000, 0, 1) -U_BOOT_I2C_ADAP_COMPLETE(tegra2, tegra_i2c_init, tegra_i2c_probe, - tegra_i2c_read, tegra_i2c_write, - tegra_i2c_set_bus_speed, 100000, 0, 2) -U_BOOT_I2C_ADAP_COMPLETE(tegra3, tegra_i2c_init, tegra_i2c_probe, - tegra_i2c_read, tegra_i2c_write, - tegra_i2c_set_bus_speed, 100000, 0, 3) -#if TEGRA_I2C_NUM_CONTROLLERS > 4 -U_BOOT_I2C_ADAP_COMPLETE(tegra4, tegra_i2c_init, tegra_i2c_probe, - tegra_i2c_read, tegra_i2c_write, - tegra_i2c_set_bus_speed, 100000, 0, 4) -#endif +static const struct udevice_id tegra_i2c_ids[] = { + { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 }, + { .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD }, + { .compatible = "nvidia,tegra20-i2c-dvc", .data = TYPE_DVC }, + { } +}; + +U_BOOT_DRIVER(i2c_tegra) = { + .name = "i2c_tegra", + .id = UCLASS_I2C, + .of_match = tegra_i2c_ids, + .ofdata_to_platdata = tegra_i2c_ofdata_to_platdata, + .probe = tegra_i2c_probe, + .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip), + .child_pre_probe = tegra_i2c_child_pre_probe, + .priv_auto_alloc_size = sizeof(struct i2c_bus), + .ops = &tegra_i2c_ops, +}; diff --git a/drivers/power/tps6586x.c b/drivers/power/tps6586x.c index d29d969..29bab4c 100644 --- a/drivers/power/tps6586x.c +++ b/drivers/power/tps6586x.c @@ -10,9 +10,7 @@ #include #include -static int bus_num; /* I2C bus we are on */ -#define I2C_ADDRESS 0x34 /* chip requires this address */ -static char inited; /* 1 if we have been inited */ +static struct udevice *tps6586x_dev; enum { /* Registers that we access */ @@ -37,13 +35,9 @@ static int tps6586x_read(int reg) int i; uchar data; int retval = -1; - int old_bus_num; - - old_bus_num = i2c_get_bus_num(); - i2c_set_bus_num(bus_num); for (i = 0; i < MAX_I2C_RETRY; ++i) { - if (!i2c_read(I2C_ADDRESS, reg, 1, &data, 1)) { + if (!i2c_read(tps6586x_dev, reg, &data, 1)) { retval = (int)data; goto exit; } @@ -53,7 +47,6 @@ static int tps6586x_read(int reg) } exit: - i2c_set_bus_num(old_bus_num); debug("pmu_read %x=%x\n", reg, retval); if (retval < 0) debug("%s: failed to read register %#x: %d\n", __func__, reg, @@ -65,13 +58,9 @@ static int tps6586x_write(int reg, uchar *data, uint len) { int i; int retval = -1; - int old_bus_num; - - old_bus_num = i2c_get_bus_num(); - i2c_set_bus_num(bus_num); for (i = 0; i < MAX_I2C_RETRY; ++i) { - if (!i2c_write(I2C_ADDRESS, reg, 1, data, len)) { + if (!i2c_write(tps6586x_dev, reg, data, len)) { retval = 0; goto exit; } @@ -81,7 +70,6 @@ static int tps6586x_write(int reg, uchar *data, uint len) } exit: - i2c_set_bus_num(old_bus_num); debug("pmu_write %x=%x: ", reg, retval); for (i = 0; i < len; i++) debug("%x ", data[i]); @@ -163,7 +151,7 @@ int tps6586x_set_pwm_mode(int mask) uchar val; int ret; - assert(inited); + assert(tps6586x_dev); ret = tps6586x_read(PFM_MODE); if (ret != -1) { val = (uchar)ret; @@ -184,7 +172,7 @@ int tps6586x_adjust_sm0_sm1(int sm0_target, int sm1_target, int step, int rate, int sm0, sm1; int bad; - assert(inited); + assert(tps6586x_dev); /* get current voltage settings */ if (read_voltages(&sm0, &sm1)) { @@ -255,10 +243,9 @@ int tps6586x_adjust_sm0_sm1(int sm0_target, int sm1_target, int step, int rate, return bad ? -1 : 0; } -int tps6586x_init(int bus) +int tps6586x_init(struct udevice *dev) { - bus_num = bus; - inited = 1; + tps6586x_dev = dev; return 0; } diff --git a/include/configs/apalis_t30.h b/include/configs/apalis_t30.h index 3cde923..61809fc 100644 --- a/include/configs/apalis_t30.h +++ b/include/configs/apalis_t30.h @@ -26,10 +26,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/beaver.h b/include/configs/beaver.h index 164b2dd..5d765f3 100644 --- a/include/configs/beaver.h +++ b/include/configs/beaver.h @@ -40,10 +40,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h index 09129c7..758b7ad 100644 --- a/include/configs/cardhu.h +++ b/include/configs/cardhu.h @@ -43,12 +43,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_I2C_MULTI_BUS -#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/colibri_t30.h b/include/configs/colibri_t30.h index a582e25..ce6f23b 100644 --- a/include/configs/colibri_t30.h +++ b/include/configs/colibri_t30.h @@ -25,10 +25,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/dalmore.h b/include/configs/dalmore.h index ff7ec4a..0b04ee6 100644 --- a/include/configs/dalmore.h +++ b/include/configs/dalmore.h @@ -36,12 +36,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_I2C_MULTI_BUS -#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/jetson-tk1.h b/include/configs/jetson-tk1.h index d67c025..a7d7665 100644 --- a/include/configs/jetson-tk1.h +++ b/include/configs/jetson-tk1.h @@ -25,12 +25,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_I2C_MULTI_BUS -#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/nyan-big.h b/include/configs/nyan-big.h index a62bc4e..cf331ab 100644 --- a/include/configs/nyan-big.h +++ b/include/configs/nyan-big.h @@ -25,12 +25,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_I2C_MULTI_BUS -#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h index 04e4f82..5f77051 100644 --- a/include/configs/seaboard.h +++ b/include/configs/seaboard.h @@ -37,10 +37,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/tec-ng.h b/include/configs/tec-ng.h index 51f87da..e37b233 100644 --- a/include/configs/tec-ng.h +++ b/include/configs/tec-ng.h @@ -23,12 +23,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_I2C_MULTI_BUS -#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index d690045..0685328 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -26,6 +26,7 @@ #endif #define CONFIG_DM_SPI #define CONFIG_DM_SPI_FLASH +#define CONFIG_DM_I2C #define CONFIG_SYS_TIMER_RATE 1000000 #define CONFIG_SYS_TIMER_COUNTER NV_PA_TMRUS_BASE diff --git a/include/configs/tegra114-common.h b/include/configs/tegra114-common.h index 555c237..9eba5d5 100644 --- a/include/configs/tegra114-common.h +++ b/include/configs/tegra114-common.h @@ -76,9 +76,6 @@ #define CONFIG_SYS_SPL_MALLOC_START 0x80090000 #define CONFIG_SPL_STACK 0x800ffffc -/* Total I2C ports on Tegra114 */ -#define TEGRA_I2C_NUM_CONTROLLERS 5 - /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 diff --git a/include/configs/tegra124-common.h b/include/configs/tegra124-common.h index 61e5026..f2b3774 100644 --- a/include/configs/tegra124-common.h +++ b/include/configs/tegra124-common.h @@ -68,9 +68,6 @@ #define CONFIG_SYS_SPL_MALLOC_START 0x80090000 #define CONFIG_SPL_STACK 0x800ffffc -/* Total I2C ports on Tegra124 */ -#define TEGRA_I2C_NUM_CONTROLLERS 5 - /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 diff --git a/include/configs/tegra20-common.h b/include/configs/tegra20-common.h index 21bf977..6330281 100644 --- a/include/configs/tegra20-common.h +++ b/include/configs/tegra20-common.h @@ -97,9 +97,6 @@ #define CONFIG_EHCI_IS_TDI #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 -/* Total I2C ports on Tegra20 */ -#define TEGRA_I2C_NUM_CONTROLLERS 4 - #define CONFIG_SYS_NAND_SELF_INIT #define CONFIG_SYS_NAND_ONFI_DETECTION diff --git a/include/configs/tegra30-common.h b/include/configs/tegra30-common.h index 443c842..bfdbeb7 100644 --- a/include/configs/tegra30-common.h +++ b/include/configs/tegra30-common.h @@ -73,9 +73,6 @@ #define CONFIG_SYS_SPL_MALLOC_START 0x80090000 #define CONFIG_SPL_STACK 0x800ffffc -/* Total I2C ports on Tegra30 */ -#define TEGRA_I2C_NUM_CONTROLLERS 5 - /* For USB EHCI controller */ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_EHCI_TXFIFO_THRESH 0x10 diff --git a/include/configs/trimslice.h b/include/configs/trimslice.h index 7c00642..a254f86 100644 --- a/include/configs/trimslice.h +++ b/include/configs/trimslice.h @@ -34,10 +34,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/venice2.h b/include/configs/venice2.h index 6897aa8..8880de8 100644 --- a/include/configs/venice2.h +++ b/include/configs/venice2.h @@ -25,12 +25,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_I2C_MULTI_BUS -#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/configs/whistler.h b/include/configs/whistler.h index 10e70d2..e083cbd 100644 --- a/include/configs/whistler.h +++ b/include/configs/whistler.h @@ -26,10 +26,7 @@ /* I2C */ #define CONFIG_SYS_I2C_TEGRA -#define CONFIG_SYS_I2C_INIT_BOARD -#define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_SYS_I2C /* SD/MMC */ #define CONFIG_MMC diff --git a/include/tps6586x.h b/include/tps6586x.h index 78ce428..eefc95f 100644 --- a/include/tps6586x.h +++ b/include/tps6586x.h @@ -44,9 +44,9 @@ int tps6586x_adjust_sm0_sm1(int sm0_target, int sm1_target, int step, int rate, * Set up the TPS6586X I2C bus number. This will be used for all operations * on the device. This function must be called before using other functions. * - * @param bus I2C bus number containing the TPS6586X chip + * @param bus I2C bus containing the TPS6586X chip * @return 0 (always succeeds) */ -int tps6586x_init(int bus); +int tps6586x_init(struct udevice *bus); #endif /* _TPS6586X_H_ */