summaryrefslogtreecommitdiff
path: root/include/i2c.h
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-02-28 15:10:26 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-03-06 02:42:49 +0000
commit8a9817a5c7be54b6efc0e116ae607fb9955af247 (patch)
tree6afc3294ab5c27e46ba9211dcde516b4898e9f54 /include/i2c.h
parent362cf0864a46b8ae6a66093cceba6859c801b443 (diff)
downloadchrome-ec-8a9817a5c7be54b6efc0e116ae607fb9955af247.tar.gz
cleanup: Combined i2c unwedge code into one common function
Refactored the i2c unwedge code to place it in the common directory so that any EC chip can use it. Added to the STM32F and LM4 boards, code to automatically detect and unwedge the i2c bus at the start of an i2c transaction. Note that STM32L already had this ability. To enable unwedging of the i2c port though, the gpio pins for SDA and SCL must be defined in the i2c_ports[] array in the board.c file. This allows the i2c module to bit bang the unwedging for the given port. If SDA and SCL are not defined for the port, then the unwedge code will not run. BUG=chrome-os-partner:26315, chrome-os-partner:23802 BRANCH=none TEST=Manual testing on machines with different EC chips. Testing made extensive use of https://chromium-review.googlesource.com/66389 in order to force wedging of the i2c bus so that we can attempt to unwedge it. Note that you can easily test if the bus is wedged by running i2cscan. On pit and spring: On pit, after each of the following, I verified that the bus was automatically unwedged. On spring, the unwedge only runs at reboot, so, for the non-reboot wedge commands, I manually ran console command unwedge, and verified that the bus became unwedged. (1) Bit bang a transaction but only read part of the response. Command to wedge: i2cwedge 0x90 0 2 2 (2) Bit bang a transaction to do a "write" and stop while the other side is acking. Command to wedge: i2cwedge 0x90 0 1 (3) Same as (1) but do a reboot instead of returning and see that the unwedge works at init time w/ no cancelled transactions. Command to wedge: i2cwedge 0x90 0 6 2 (4) Same as (2) but do a reboot instead of returning and see that the unwedge works at init time w/ no cancelled transactions. Command to wedge: i2cwedge 0x90 0 5 On glimmer: Added code to call i2c_unwedge in accel_init(). Then tested unwedging the accelerometer with the following. One extra difficulty testing this with the accelerometer is that sometimes the bit you stop on is high, which means it won't be wedged at all, the next start transaction will reset the bus. So, sometimes running i2cwedge won't wedge the bus and sometimes it will depending on the acceleration data. (1) Big bang transaction to do a "read" of accelerometer and stop partway: i2cwedge 0x1c 0x0f 2 2 i2cscan to make sure bus is actually wedged i2cunwedge i2cscan to make sure bus is now unwedged. (2) Bit bang transaction to do a "read" and stop partway, then reboot: i2cwedge 0x1c 0x0f 6 2. i2cscan to verify that the bus is working after the reboot. Change-Id: Ie3328e843ffb40f5001c96626fea131c0f9ad9b1 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/188422 Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'include/i2c.h')
-rw-r--r--include/i2c.h79
1 files changed, 75 insertions, 4 deletions
diff --git a/include/i2c.h b/include/i2c.h
index 7d93eed7ef..ac572960df 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -15,9 +15,11 @@
/* Data structure to define I2C port configuration. */
struct i2c_port_t {
- const char *name; /* Port name */
- int port; /* Port */
- int kbps; /* Speed in kbps */
+ const char *name; /* Port name */
+ int port; /* Port */
+ int kbps; /* Speed in kbps */
+ enum gpio_signal scl; /* Port SCL GPIO line */
+ enum gpio_signal sda; /* Port SDA GPIO line */
};
extern const struct i2c_port_t i2c_ports[];
@@ -51,13 +53,73 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
#define I2C_LINE_IDLE (I2C_LINE_SCL_HIGH | I2C_LINE_SDA_HIGH)
/**
- * Return raw I/O line levels (I2C_LINE_*) for a port.
+ * Return raw I/O line levels (I2C_LINE_*) for a port when port is in alternate
+ * function mode.
*
* @param port Port to check
*/
int i2c_get_line_levels(int port);
/**
+ * Get GPIO pin for I2C SCL from the i2c port number
+ *
+ * @param port I2C port number
+ * @param sda Pointer to gpio signal to store the SCL gpio at
+ * @return EC_SUCCESS if a valid GPIO point is found, EC_ERROR_INVAL if not
+ */
+int get_scl_from_i2c_port(int port, enum gpio_signal *scl);
+
+/**
+ * Get GPIO pin for I2C SDA from the i2c port number
+ *
+ * @param port I2C port number
+ * @param sda Pointer to gpio signal to store the SDA gpio at
+ * @return EC_SUCCESS if a valid GPIO point is found, EC_ERROR_INVAL if not
+ */
+int get_sda_from_i2c_port(int port, enum gpio_signal *sda);
+
+/**
+ * Get the state of the SCL pin when port is not in alternate function mode.
+ *
+ * @param port I2C port of interest
+ * @return State of SCL pin
+ */
+int i2c_raw_get_scl(int port);
+
+/**
+ * Get the state of the SDA pin when port is not in alternate function mode.
+ *
+ * @param port I2C port of interest
+ * @return State of SDA pin
+ */
+int i2c_raw_get_sda(int port);
+
+/**
+ * Set the state of the SCL pin.
+ *
+ * @param port I2C port of interest
+ * @param level State to set SCL pin to
+ */
+void i2c_raw_set_scl(int port, int level);
+
+/**
+ * Set the state of the SDA pin.
+ *
+ * @param port I2C port of interest
+ * @param level State to set SDA pin to
+ */
+void i2c_raw_set_sda(int port, int level);
+
+/**
+ * Toggle the I2C pins into or out of raw / big-bang mode.
+ *
+ * @param port I2C port of interest
+ * @param enable Flag to enable raw mode or disable it
+ * @return EC_SUCCESS if successful
+ */
+int i2c_raw_mode(int port, int enable);
+
+/**
* Lock / unlock an I2C port.
* @param port Port to lock
* @param lock 1 to lock, 0 to unlock
@@ -80,6 +142,15 @@ int i2c_read8(int port, int slave_addr, int offset, int *data);
* the specified 8-bit <offset> in the slave's address space. */
int i2c_write8(int port, int slave_addr, int offset, int data);
+/**
+ * Attempt to unwedge an I2C bus.
+ *
+ * @param port I2C port
+ *
+ * @return EC_SUCCESS or EC_ERROR_UNKNOWN
+ */
+int i2c_unwedge(int port);
+
/* Read ascii string using smbus read block protocol.
* Read bytestream from <slaveaddr>:<offset> with format:
* [length_N] [byte_0] [byte_1] ... [byte_N-1]