summaryrefslogtreecommitdiff
path: root/common/i2c_wedge.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/i2c_wedge.c')
-rw-r--r--common/i2c_wedge.c341
1 files changed, 0 insertions, 341 deletions
diff --git a/common/i2c_wedge.c b/common/i2c_wedge.c
deleted file mode 100644
index 48bcac090c..0000000000
--- a/common/i2c_wedge.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Copyright 2013 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Define CONFIG_CMD_I2CWEDGE and I2C_PORT_HOST to enable the 'i2cwedge'
- * console command to allow us to bang the bus into a wedged state. For
- * example, include the following lines in board/pit/board.h to enable it on
- * pit:
- *
- * #define CONFIG_CMD_I2CWEDGE
- * #define I2C_PORT_HOST I2C_PORT_CONTROLLER
- *
- */
-
-#include "console.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "system.h"
-#include "timer.h"
-#include "util.h"
-
-/*
- * The implementation is based on Wikipedia.
- */
-
-int i2c_bang_started;
-
-static void i2c_bang_delay(void)
-{
- udelay(5);
-}
-
-static void i2c_bang_start_cond(void)
-{
- /* Restart if needed */
- if (i2c_bang_started) {
- /* set SDA to 1 */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /* Repeated start setup time, minimum 4.7us */
- i2c_bang_delay();
- }
-
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- if (i2c_raw_get_sda(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): arbitration_lost */
-
- /* SCL is high, set SDA from 1 to 0. */
- i2c_raw_set_sda(I2C_PORT_HOST, 0);
- i2c_bang_delay();
- i2c_raw_set_scl(I2C_PORT_HOST, 0);
- i2c_bang_started = 1;
-
- ccputs("BITBANG: send start\n");
-}
-
-static void i2c_bang_stop_cond(void)
-{
- /* set SDA to 0 */
- i2c_raw_set_sda(I2C_PORT_HOST, 0);
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /* Stop bit setup time, minimum 4us */
- i2c_bang_delay();
-
- /* SCL is high, set SDA from 0 to 1 */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- if (i2c_raw_get_sda(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): arbitration_lost */
-
- i2c_bang_delay();
-
- i2c_bang_started = 0;
- ccputs("BITBANG: send stop\n");
-}
-
-static void i2c_bang_out_bit(int bit)
-{
- if (bit)
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- else
- i2c_raw_set_sda(I2C_PORT_HOST, 0);
-
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /*
- * SCL is high, now data is valid
- * If SDA is high, check that nobody else is driving SDA
- */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- if (bit && i2c_raw_get_sda(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): arbitration_lost */
-
- i2c_bang_delay();
- i2c_raw_set_scl(I2C_PORT_HOST, 0);
-}
-
-static int i2c_bang_in_bit(void)
-{
- int bit;
-
- /* Let the peripheral drive data */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /* SCL is high, now data is valid */
- bit = i2c_raw_get_sda(I2C_PORT_HOST);
- i2c_bang_delay();
- i2c_raw_set_scl(I2C_PORT_HOST, 0);
-
- return bit;
-}
-
-/* Write a byte to I2C bus. Return 0 if ack by the peripheral. */
-static int i2c_bang_out_byte(int send_start, int send_stop, unsigned char byte)
-{
- unsigned bit;
- int nack;
- int tmp = byte;
-
- if (send_start)
- i2c_bang_start_cond();
-
- for (bit = 0; bit < 8; bit++) {
- i2c_bang_out_bit((byte & 0x80) != 0);
- byte <<= 1;
- }
-
- nack = i2c_bang_in_bit();
-
- ccprintf(" write byte: %d ack/nack=%d\n", tmp, nack);
-
- if (send_stop)
- i2c_bang_stop_cond();
-
- return nack;
-}
-
-static unsigned char i2c_bang_in_byte(int ack, int send_stop)
-{
- unsigned char byte = 0;
- int i;
- for (i = 0; i < 8; ++i)
- byte = (byte << 1) | i2c_bang_in_bit();
- i2c_bang_out_bit(ack != 0);
- if (send_stop)
- i2c_bang_stop_cond();
- return byte;
-}
-
-static void i2c_bang_init(void)
-{
- i2c_bang_started = 0;
-
- i2c_raw_mode(I2C_PORT_HOST, 1);
-}
-
-static void i2c_bang_xfer(int addr, int reg)
-{
- int byte;
-
- i2c_bang_init();
-
- /* State a write command to 'addr' */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr);
- /* Write 'reg' */
- i2c_bang_out_byte(0 /*start*/, 0 /*stop*/, reg);
-
- /* Start a read command */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr | 1);
-
- /* Read two bytes */
- byte = i2c_bang_in_byte(0, 0); /* ack and no stop */
- ccprintf(" read byte: %d\n", byte);
- byte = i2c_bang_in_byte(1, 1); /* nack and stop */
- ccprintf(" read byte: %d\n", byte);
-}
-
-static void i2c_bang_wedge_write(int addr, int byte, int bit_count,
- int reboot)
-{
- int i;
-
- i2c_bang_init();
-
- /* State a write command to 'addr' */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr);
- /* Send a few bits and stop */
- for (i = 0; i < bit_count; ++i) {
- i2c_bang_out_bit((byte & 0x80) != 0);
- byte <<= 1;
- }
- ccprintf(" wedged write after %d bits\n", bit_count);
-
- if (reboot)
- system_reset(0);
-}
-
-static void i2c_bang_wedge_read(int addr, int reg, int bit_count,
- int reboot)
-{
- int i;
-
- i2c_bang_init();
-
- /* State a write command to 'addr' */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr);
- /* Write 'reg' */
- i2c_bang_out_byte(0 /*start*/, 0 /*stop*/, reg);
-
- /* Start a read command */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr | 1);
-
- /* Read bit_count bits and stop */
- for (i = 0; i < bit_count; ++i)
- i2c_bang_in_bit();
-
- ccprintf(" wedged read after %d bits\n", bit_count);
-
- if (reboot)
- system_reset(0);
-}
-
-#define WEDGE_WRITE 1
-#define WEDGE_READ 2
-#define WEDGE_REBOOT 4
-
-static int command_i2c_wedge(int argc, char **argv)
-{
- int addr, reg, wedge_flag = 0, wedge_bit_count = -1;
- char *e;
- enum gpio_signal tmp;
-
- /* Verify that the I2C_PORT_HOST has SDA and SCL pins defined. */
- if (get_sda_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS ||
- get_scl_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS) {
- ccprintf("Cannot wedge bus because no SCL and SDA pins are"
- "defined for this port. Check i2c_ports[].\n");
- return EC_SUCCESS;
- }
-
- if (argc < 3) {
- ccputs("Usage: i2cwedge addr out_byte "
- "[wedge_flag [wedge_bit_count]]\n");
- ccputs(" wedge_flag - (1: wedge out; 2: wedge in;"
- " 5: wedge out+reboot; 6: wedge in+reboot)]\n");
- ccputs(" wedge_bit_count - 0 to 8\n");
- return EC_ERROR_UNKNOWN;
- }
-
- addr = strtoi(argv[1], &e, 0);
- if (*e) {
- ccprintf("Invalid addr %s\n", argv[1]);
- return EC_ERROR_INVAL;
- }
- reg = strtoi(argv[2], &e, 0);
- if (*e) {
- ccprintf("Invalid out_byte %s\n", argv[2]);
- return EC_ERROR_INVAL;
- }
- if (argc > 3) {
- wedge_flag = strtoi(argv[3], &e, 0);
- if (*e) {
- ccprintf("Invalid wedge_flag %s\n", argv[3]);
- return EC_ERROR_INVAL;
- }
- }
- if (argc > 4) {
- wedge_bit_count = strtoi(argv[4], &e, 0);
- if (*e || wedge_bit_count < 0 || wedge_bit_count > 8) {
- ccprintf("Invalid wedge_bit_count %s.\n", argv[4]);
- return EC_ERROR_INVAL;
- }
- }
-
- i2c_lock(I2C_PORT_HOST, 1);
-
- if (wedge_flag & WEDGE_WRITE) {
- if (wedge_bit_count < 0)
- wedge_bit_count = 8;
- i2c_bang_wedge_write(addr, reg, wedge_bit_count,
- (wedge_flag & WEDGE_REBOOT));
- } else if (wedge_flag & WEDGE_READ) {
- if (wedge_bit_count < 0)
- wedge_bit_count = 2;
- i2c_bang_wedge_read(addr, reg, wedge_bit_count,
- (wedge_flag & WEDGE_REBOOT));
- } else {
- i2c_bang_xfer(addr, reg);
- }
-
- /* Put it back into normal mode */
- i2c_raw_mode(I2C_PORT_HOST, 0);
-
- i2c_lock(I2C_PORT_HOST, 0);
-
- if (wedge_flag & (WEDGE_WRITE | WEDGE_READ))
- ccprintf("I2C bus %d is now wedged. Enjoy.\n", I2C_PORT_HOST);
- else
- ccprintf("Bit bang xfer complete.\n");
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(i2cwedge, command_i2c_wedge,
- "i2cwedge addr out_byte "
- "[wedge_flag [wedge_bit_count]]",
- "Wedge host I2C bus");
-
-static int command_i2c_unwedge(int argc, char **argv)
-{
- i2c_unwedge(I2C_PORT_HOST);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(i2cunwedge, command_i2c_unwedge,
- "",
- "Unwedge host I2C bus");
-