summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2011-06-10 14:52:27 -0700
committerSimon Glass <sjg@chromium.org>2011-08-29 10:39:28 -0700
commit6871b417c03452377b6c484a0be363484d7b835c (patch)
treead76f3c3a4da16649849dc9354b28977754ff85f /drivers
parent6ddb4c1015086c21059bbcc00fcca01c21823e9a (diff)
Add 16 bit register address support to the tegra2 i2c driver.
This change makes the tegra2 i2c driver's i2c_read and i2c_write functions actually use the alen parameter instead of assuming a value of 1. This code assumes the code handling the address is compiled little endian and that multibyte register addresses should be transmitted as big endian. BUG=chrome-os-partner:3580 TEST=Used the i2c u-boot command to read and write several registers on a chip that uses 16 bit addresses. Read and wrote several registers on several devices that use 8 bit addresses. Change-Id: I0c2291a9d8f023822a64393b82c596bb2b2e2ff4 Reviewed-on: http://gerrit.chromium.org/gerrit/2592 Reviewed-by: Gabe Black <gabeblack@chromium.org> Tested-by: Gabe Black <gabeblack@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/tegra2_i2c.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/drivers/i2c/tegra2_i2c.c b/drivers/i2c/tegra2_i2c.c
index 82c8d9aae3c..6f82131eb02 100644
--- a/drivers/i2c/tegra2_i2c.c
+++ b/drivers/i2c/tegra2_i2c.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Copyright (c) 2010-2011 NVIDIA Corporation
* NVIDIA Corporation <www.nvidia.com>
*
@@ -473,29 +474,47 @@ int i2c_probe(uchar chip)
return 0;
}
+static int i2c_addr_ok(const uint addr, const int alen)
+{
+ if (alen < 0 || alen > sizeof(addr))
+ return 0;
+ if (alen != sizeof(addr)) {
+ uint max_addr = (1 << (8 * alen)) - 1;
+ if (addr > max_addr)
+ return 0;
+ }
+ return 1;
+}
+
/* Read bytes */
int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
{
- int rc;
- uchar *ptr = buffer;
-
- debug("i2c_read: chip=0x%x, addr=0x%x, len=0x%x\n", chip, addr, len);
+ uint offset;
+ int i;
- while (len) {
- rc = i2c_write_data(chip, (uchar *)&addr, 1);
- if (rc) {
- debug("i2c_read: error sending (0x%x)\n", addr);
- return 1;
+ debug("i2c_read: chip=0x%x, addr=0x%x, len=0x%x\n",
+ chip, addr, len);
+ 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(chip, data, alen)) {
+ debug("i2c_read: error sending (0x%x)\n",
+ addr);
+ return 1;
+ }
}
-
- rc = i2c_read_data(chip, ptr, 1);
- if (rc) {
+ if (i2c_read_data(chip, buffer + offset, 1)) {
debug("i2c_read: error reading (0x%x)\n", addr);
return 1;
}
- ++addr;
- ++ptr;
- --len;
}
return 0;
@@ -504,23 +523,24 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
/* Write bytes */
int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
{
- int rc;
- uchar local_buffer[4];
- uchar *ptr = buffer;
-
- debug("i2c_write: chip=0x%x, addr=0x%x, len=0x%x\n", chip, addr, len);
+ uint offset;
+ int i;
- while (len) {
- local_buffer[0] = addr & 0xFF;
- local_buffer[1] = *ptr;
- rc = i2c_write_data(chip, local_buffer, 2);
- if (rc) {
+ debug("i2c_write: chip=0x%x, addr=0x%x, len=0x%x\n",
+ chip, addr, len);
+ 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(chip, data, alen + 1)) {
debug("i2c_write: error sending (0x%x)\n", addr);
return 1;
}
- ++addr;
- ++ptr;
- --len;
}
return 0;