1
0
Fork 0

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 <hs@denx.de>
Signed-off-by: Simon Glass <sjg@chromium.org>
utp
Simon Glass 2014-12-10 08:55:57 -07:00
parent a6c7b46181
commit b0e6ef4640
30 changed files with 210 additions and 374 deletions

View File

@ -6,6 +6,7 @@
*/
#include <common.h>
#include <i2c.h>
#include <tps6586x.h>
#include <asm/io.h>
#include <asm/arch/tegra.h>
@ -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);

View File

@ -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";

View File

@ -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";

View File

@ -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_ */

View File

@ -6,6 +6,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/gp_padctrl.h>
#include <asm/arch/gpio.h>
@ -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);
}
/*

View File

@ -6,6 +6,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/gp_padctrl.h>
#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);
}
}

View File

@ -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");

View File

@ -15,6 +15,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/gp_padctrl.h>
#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);

View File

@ -6,6 +6,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/io.h>
#include <asm/arch/tegra.h>
#include <asm/arch/clock.h>
@ -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);
}

View File

@ -6,7 +6,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/arch/gp_padctrl.h>
#include <asm/arch/pinmux.h>
#include <asm/gpio.h>
@ -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;
}

View File

@ -7,6 +7,8 @@
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <i2c.h>
#include <asm/io.h>
@ -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;
u8 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, &reg, 1, false);
if (rc) {
debug("Error probing 0x%x.\n", chip);
return 1;
}
return 0;
/* Shift 7-bit address over for lower-level i2c functions */
rc = tegra_i2c_write_data(i2c_bus, chip_addr << 1, &reg, sizeof(reg),
false);
return rc;
}
static int i2c_addr_ok(const uint addr, const int alen)
static int tegra_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
int nmsgs)
{
/* We support 7 or 10 bit addresses, so one or two bytes each */
return alen == 1 || alen == 2;
}
struct i2c_bus *i2c_bus = dev_get_priv(bus);
int ret;
/* Read bytes */
static int tegra_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
int alen, uchar *buffer, int len)
{
struct i2c_bus *bus;
uint offset;
int i;
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_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;
}
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;
struct udevice *bus;
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;
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 -ENODEV;
}
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,
};
static int tegra_i2c_child_pre_probe(struct udevice *dev)
{
struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
if (dev->of_offset == -1)
return 0;
return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
i2c_chip);
}
static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
{
return 0;
}
int tegra_i2c_get_dvc_bus_num(void)
{
int i;
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 },
{ }
};
for (i = 0; i < TEGRA_I2C_NUM_CONTROLLERS; i++) {
struct i2c_bus *bus = &i2c_controllers[i];
if (bus->inited && bus->is_dvc)
return i;
}
return -1;
}
/*
* 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
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,
};

View File

@ -10,9 +10,7 @@
#include <asm/io.h>
#include <i2c.h>
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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */