diff options
author | Julius Werner <jwerner@chromium.org> | 2014-05-05 18:03:46 -0700 |
---|---|---|
committer | Marc Jones <marc.jones@se-eng.com> | 2014-12-30 22:07:42 +0100 |
commit | 37d7ac8b5ba12d4618b8a91f35d444fe9572beb4 (patch) | |
tree | 8d395e92cb35d27ad6ad3c2c129c07878317faae /src/include/device | |
parent | b4bd53a3cba45b2cbf86b8b020bb8a678e583f97 (diff) |
i2c: Add software_i2c driver for I2C debugging and emulation
This patch adds I2C emulation in software through raw toggling of the
SDA/SCL lines. Platforms need to provide bindings to toggle their
respective I2C busses for this to work (e.g. by pinmuxing them as GPIOs,
currently only enabled for Tegra).
This is mostly useful as a debugging feature, to drive unusual states on
a bus and closely monitor the device output without the need of a bus
analyzer. It provides a few functions to "wedge" an I2C bus by aborting
a transaction at certain points, which can be used to test if a system
can correctly recover from an ill-timed reboot. However, it can also
dynamically replace the existing I2C transfer functions and drive
some/all I2C transfers on the system, which might be useful if a driver
for the actual I2C controller hardware is not (yet) available.
Based on original code by Doug Anderson <dianders@chromium.org> and
Hung-ying Tyan <tyanh@chromium.org> for the ChromeOS embedded
controller project.
BRANCH=None
BUG=chrome-os-partner:28323
TEST=Spread tegra_software_i2c_init()/tegra_software_i2c_disable()
through the code and see that everything still works.
Original-Change-Id: I9ee7ccbd1efb38206669a35d0c3318af16f8be63
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/198791
Original-Reviewed-by: Doug Anderson <dianders@chromium.org>
Original-Reviewed-by: Tom Warren <twarren@nvidia.com>
Original-Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
(cherry picked from commit 8f71503dbbd74c5298e90e2163b67d4efe3e89db)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: Id6c5f75bb5baaabd62b6b1fc26c2c71d9f1ce682
Reviewed-on: http://review.coreboot.org/7947
Tested-by: build bot (Jenkins)
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Diffstat (limited to 'src/include/device')
-rw-r--r-- | src/include/device/i2c.h | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/src/include/device/i2c.h b/src/include/device/i2c.h index da9d1bcb3c..c1f2a2103a 100644 --- a/src/include/device/i2c.h +++ b/src/include/device/i2c.h @@ -31,7 +31,39 @@ struct i2c_seg int len; }; -int i2c_transfer(unsigned bus, struct i2c_seg *segments, int count); +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count); + +#define SOFTWARE_I2C_MAX_BUS 10 /* increase as necessary */ + +struct software_i2c_ops { + void (*set_sda)(unsigned bus, int high); + void (*set_scl)(unsigned bus, int high); + int (*get_sda)(unsigned bus); + int (*get_scl)(unsigned bus); +}; + +extern struct software_i2c_ops *software_i2c[]; + +int software_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count); +void software_i2c_wedge_ack(unsigned bus, u8 chip); +void software_i2c_wedge_read(unsigned bus, u8 chip, u8 reg, int bit_count); +void software_i2c_wedge_write(unsigned bus, u8 chip, u8 reg, int bit_count); + +/* + * software_i2c is supposed to be a debug feature. It's usually not compiled in, + * but when it is it can be dynamically enabled at runtime for certain busses. + * Need this ugly stub to arbitrate since I2C device drivers hardcode + * 'i2c_transfer()' as their entry point. + */ +static inline int i2c_transfer(unsigned bus, struct i2c_seg *segments, + int count) +{ + if (CONFIG_SOFTWARE_I2C) + if (bus < SOFTWARE_I2C_MAX_BUS && software_i2c[bus]) + return software_i2c_transfer(bus, segments, count); + + return platform_i2c_transfer(bus, segments, count); +} /* * Read a raw chunk of data in one segment and one frame. |