summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-03-19 13:40:59 -0700
committerChromeBot <chrome-bot@google.com>2013-03-20 15:23:29 -0700
commit34e17d4c05ccc4ad48b0a717aebcf278c97f1a79 (patch)
tree6afb325abc859c8e99ea9b5d7ced633557a0bde4
parent19920f1f74f07e00160f4bb817d756f2af024744 (diff)
downloadchrome-ec-34e17d4c05ccc4ad48b0a717aebcf278c97f1a79.tar.gz
Move I2C arbitration to its own file
It's only board-specific in that we've only needed it on snow so far. But by that logic, x86_power would be board specific because we've only needed it on link. No functionality change, just moving code between files and renaming the interface to indicate it's not board-specific. BUG=chrome-os-partner:18343 BRANCH=none TEST=build daisy,snow,spring Change-Id: I35debdaa71829d55a2fbc5d3c62b2aaf6e467633 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/45879
-rw-r--r--board/snow/board.c96
-rw-r--r--board/snow/board.h2
-rw-r--r--chip/stm32/i2c.c27
-rw-r--r--common/build.mk1
-rw-r--r--common/i2c_arbitration.c104
-rw-r--r--include/i2c.h30
-rw-r--r--include/i2c_arbitration.h44
7 files changed, 157 insertions, 147 deletions
diff --git a/board/snow/board.c b/board/snow/board.c
index 3964f15f3a..2f5900340b 100644
--- a/board/snow/board.c
+++ b/board/snow/board.c
@@ -229,34 +229,6 @@ void board_power_led_config(enum powerled_config config)
}
}
-enum {
- /* Time between requesting bus and deciding that we have it */
- BUS_SLEW_DELAY_US = 10,
-
- /* Time between retrying to see if the AP has released the bus */
- BUS_WAIT_RETRY_US = 3000,
-
- /* Time to wait until the bus becomes free */
- BUS_WAIT_FREE_US = 100 * 1000,
-};
-
-/*
- * This reflects the desired value of GPIO_EC_CLAIM to ensure that the
- * GPIO is driven correctly when re-enabled before AP power on.
- */
-static char i2c_claimed_by_ec;
-
-static void board_pre_init_hook(void)
-{
-#ifdef CONFIG_ARBITRATE_I2C
- gpio_set_flags(GPIO_AP_CLAIM, GPIO_PULL_UP);
- gpio_set_level(GPIO_EC_CLAIM, i2c_claimed_by_ec ? 0 : 1);
- gpio_set_flags(GPIO_EC_CLAIM, GPIO_OUTPUT);
- usleep(BUS_SLEW_DELAY_US);
-#endif
-}
-DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, board_pre_init_hook, HOOK_PRIO_DEFAULT);
-
static void board_startup_hook(void)
{
gpio_set_flags(GPIO_SUSPEND_L, INT_BOTH_PULL_UP);
@@ -267,77 +239,9 @@ static void board_shutdown_hook(void)
{
/* Disable pull-up on SUSPEND_L during shutdown to prevent leakage */
gpio_set_flags(GPIO_SUSPEND_L, INT_BOTH_FLOATING);
-
-#ifdef CONFIG_ARBITRATE_I2C
- gpio_set_flags(GPIO_AP_CLAIM, GPIO_INPUT);
- gpio_set_flags(GPIO_EC_CLAIM, GPIO_INPUT);
-#endif
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_shutdown_hook, HOOK_PRIO_DEFAULT);
-#ifdef CONFIG_ARBITRATE_I2C
-
-int board_i2c_claim(int port)
-{
- timestamp_t start;
-
- if (port != I2C_PORT_HOST)
- return EC_SUCCESS;
-
- /* If AP is off, we have the bus */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
- i2c_claimed_by_ec = 1;
- return EC_SUCCESS;
- }
-
- /* Start a round of trying to claim the bus */
- start = get_time();
- do {
- timestamp_t start_retry;
- int waiting = 0;
-
- /* Indicate that we want to claim the bus */
- gpio_set_level(GPIO_EC_CLAIM, 0);
- usleep(BUS_SLEW_DELAY_US);
-
- /* Wait for the AP to release it */
- start_retry = get_time();
- while (time_since32(start_retry) < BUS_WAIT_RETRY_US) {
- if (gpio_get_level(GPIO_AP_CLAIM)) {
- /* We got it, so return */
- i2c_claimed_by_ec = 1;
- return EC_SUCCESS;
- }
-
- if (!waiting)
- waiting = 1;
- }
-
- /* It didn't release, so give up, wait, and try again */
- gpio_set_level(GPIO_EC_CLAIM, 1);
-
- usleep(BUS_WAIT_RETRY_US);
- } while (time_since32(start) < BUS_WAIT_FREE_US);
-
- gpio_set_level(GPIO_EC_CLAIM, 1);
- usleep(BUS_SLEW_DELAY_US);
- i2c_claimed_by_ec = 0;
-
- panic_puts("Unable to access I2C bus (arbitration timeout)\n");
- return EC_ERROR_BUSY;
-}
-
-void board_i2c_release(int port)
-{
- if (port == I2C_PORT_HOST) {
- /* Release our claim */
- gpio_set_level(GPIO_EC_CLAIM, 1);
- usleep(BUS_SLEW_DELAY_US);
- i2c_claimed_by_ec = 0;
- }
-}
-#endif /* CONFIG_ARBITRATE_I2C */
-
/*
* Force the pmic to reset completely. This forces an entire system reset,
* and therefore should never return
diff --git a/board/snow/board.h b/board/snow/board.h
index 89e77e4f0c..5f2bb4c5c9 100644
--- a/board/snow/board.h
+++ b/board/snow/board.h
@@ -24,6 +24,7 @@
#define CONFIG_CONFIGURE_BOARD_LATE
#define CONFIG_HOST_COMMAND_STATUS
#define CONFIG_I2C
+#define CONFIG_I2C_ARBITRATION
#undef CONFIG_TASK_PROFILING
#define CONFIG_WATCHDOG_HELP
@@ -50,7 +51,6 @@
#define I2C_PORT_BATTERY I2C_PORT_HOST
#define I2C_PORT_CHARGER I2C_PORT_HOST
#define I2C_PORT_SLAVE 1
-#define CONFIG_ARBITRATE_I2C I2C_PORT_HOST
#define GPIO_AP_CLAIM GPIO_SPI1_NSS /* AP claims bus */
#define GPIO_EC_CLAIM GPIO_SPI1_MISO /* EC claims bus */
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c
index e2f1a9fbd8..a682883c89 100644
--- a/chip/stm32/i2c.c
+++ b/chip/stm32/i2c.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 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.
*/
@@ -12,6 +12,7 @@
#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
+#include "i2c_arbitration.h"
#include "registers.h"
#include "task.h"
#include "timer.h"
@@ -123,22 +124,6 @@ static inline void disable_ack(int port)
STM32_I2C_CR1(port) &= ~(1 << 10);
}
-int __board_i2c_claim(int port)
-{
- return 0;
-}
-
-int board_i2c_claim(int port)
- __attribute__((weak, alias("__board_i2c_claim")));
-
-
-void __board_i2c_release(int port)
-{
-}
-
-void board_i2c_release(int port)
- __attribute__((weak, alias("__board_i2c_release")));
-
static void i2c_init_port(unsigned int port);
static int i2c_write_raw_slave(int port, void *buf, int len)
@@ -464,9 +449,9 @@ static void i2c_init_port(unsigned int port)
if (!(STM32_RCC_APB1ENR & (1 << i2c_clock_bit[port]))) {
/* Only unwedge the bus if the clock is off */
- if (board_i2c_claim(port) == EC_SUCCESS) {
+ if (i2c_claim(port) == EC_SUCCESS) {
unwedge_i2c_bus(port);
- board_i2c_release(port);
+ i2c_release(port);
}
/* enable I2C2 clock */
@@ -848,7 +833,7 @@ static int i2c_xfer(int port, int slave_addr, uint8_t *out, int out_bytes,
disable_sleep(SLEEP_MASK_I2C);
mutex_lock(&i2c_mutex);
- if (board_i2c_claim(port)) {
+ if (i2c_claim(port)) {
rv = EC_ERROR_BUSY;
goto err_claim;
}
@@ -863,7 +848,7 @@ static int i2c_xfer(int port, int slave_addr, uint8_t *out, int out_bytes,
enable_i2c_interrupt(port);
- board_i2c_release(port);
+ i2c_release(port);
err_claim:
mutex_unlock(&i2c_mutex);
diff --git a/common/build.mk b/common/build.mk
index 7fb75d3a39..a490cf9479 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -19,6 +19,7 @@ common-$(CONFIG_EOPTION)+=eoption.o
common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o
common-$(CONFIG_FLASH)+=flash_common.o fmap.o
common-$(CONFIG_I2C)+=i2c_commands.o
+common-$(CONFIG_I2C_ARBITRATION)+=i2c_arbitration.o
common-$(CONFIG_IR357x)+=ir357x.o
common-$(CONFIG_KEYBOARD_TEST)+=keyboard_test.o
common-$(CONFIG_LP5562)+=lp5562.o
diff --git a/common/i2c_arbitration.c b/common/i2c_arbitration.c
new file mode 100644
index 0000000000..70b4b81dcd
--- /dev/null
+++ b/common/i2c_arbitration.c
@@ -0,0 +1,104 @@
+/* Copyright (c) 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.
+ */
+/* I2C arbitration using a pair of GPIO lines */
+
+#include "chipset.h"
+#include "common.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "timer.h"
+#include "util.h"
+
+/* Time between requesting bus and deciding that we have it */
+#define BUS_SLEW_DELAY_US 10
+
+/* Time between retrying to see if the AP has released the bus */
+#define BUS_WAIT_RETRY_US 3000
+
+/* Time to wait until the bus becomes free */
+#define BUS_WAIT_FREE_US (100 * 1000)
+
+/*
+ * This reflects the desired value of GPIO_EC_CLAIM to ensure that the
+ * GPIO is driven correctly when re-enabled before AP power on.
+ */
+static char i2c_claimed_by_ec;
+
+int i2c_claim(int port)
+{
+ timestamp_t start;
+
+ if (port != I2C_PORT_HOST)
+ return EC_SUCCESS;
+
+ /* If AP is off, we have the bus */
+ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
+ i2c_claimed_by_ec = 1;
+ return EC_SUCCESS;
+ }
+
+ /* Start a round of trying to claim the bus */
+ start = get_time();
+ do {
+ timestamp_t start_retry;
+ int waiting = 0;
+
+ /* Indicate that we want to claim the bus */
+ gpio_set_level(GPIO_EC_CLAIM, 0);
+ usleep(BUS_SLEW_DELAY_US);
+
+ /* Wait for the AP to release it */
+ start_retry = get_time();
+ while (time_since32(start_retry) < BUS_WAIT_RETRY_US) {
+ if (gpio_get_level(GPIO_AP_CLAIM)) {
+ /* We got it, so return */
+ i2c_claimed_by_ec = 1;
+ return EC_SUCCESS;
+ }
+
+ if (!waiting)
+ waiting = 1;
+ }
+
+ /* It didn't release, so give up, wait, and try again */
+ gpio_set_level(GPIO_EC_CLAIM, 1);
+
+ usleep(BUS_WAIT_RETRY_US);
+ } while (time_since32(start) < BUS_WAIT_FREE_US);
+
+ gpio_set_level(GPIO_EC_CLAIM, 1);
+ usleep(BUS_SLEW_DELAY_US);
+ i2c_claimed_by_ec = 0;
+
+ panic_puts("Unable to access I2C bus (arbitration timeout)\n");
+ return EC_ERROR_BUSY;
+}
+
+void i2c_release(int port)
+{
+ if (port == I2C_PORT_HOST) {
+ /* Release our claim */
+ gpio_set_level(GPIO_EC_CLAIM, 1);
+ usleep(BUS_SLEW_DELAY_US);
+ i2c_claimed_by_ec = 0;
+ }
+}
+
+static void i2c_pre_init_hook(void)
+{
+ gpio_set_flags(GPIO_AP_CLAIM, GPIO_PULL_UP);
+ gpio_set_level(GPIO_EC_CLAIM, i2c_claimed_by_ec ? 0 : 1);
+ gpio_set_flags(GPIO_EC_CLAIM, GPIO_OUTPUT);
+ usleep(BUS_SLEW_DELAY_US);
+}
+DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, i2c_pre_init_hook, HOOK_PRIO_DEFAULT);
+
+static void i2c_shutdown_hook(void)
+{
+ gpio_set_flags(GPIO_AP_CLAIM, GPIO_INPUT);
+ gpio_set_flags(GPIO_EC_CLAIM, GPIO_INPUT);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, i2c_shutdown_hook, HOOK_PRIO_DEFAULT);
diff --git a/include/i2c.h b/include/i2c.h
index dbf933e102..d14008a2d0 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 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.
*/
@@ -48,32 +48,4 @@ int i2c_write8(int port, int slave_addr, int offset, int data);
int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data,
int len);
-/**
- * Claim an I2C port for use in master mode
- *
- * If this function succeed, then you must later call board_i2c_release()
- * to release the claim.
- *
- * This function may optionally be implemented by a board file. If provided
- * then it should check the port number and arbitrate as needed.
- *
- * This function will not be called to claim an already-claimed port.
- *
- * @param port Port to claim (0 for first, 1 for second, etc.)
- * @return 0 if claimed successfully, -1 if it is in use
- */
-int board_i2c_claim(int port);
-
-/**
- * Release an I2C port (after previously being claimed)
- *
- * This function may optionally be implemented by a board file. If provided
- * then it should check the port number and arbitrate as needed.
- *
- * This function will not be called to release an already-released port.
- *
- * @param port Port to claim (0 for first, 1 for second, etc.)
- */
-void board_i2c_release(int port);
-
#endif /* __CROS_EC_I2C_H */
diff --git a/include/i2c_arbitration.h b/include/i2c_arbitration.h
new file mode 100644
index 0000000000..cf4d39d247
--- /dev/null
+++ b/include/i2c_arbitration.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 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.
+ */
+
+/* I2C arbitration for Chrome EC */
+
+#ifndef __CROS_EC_I2C_ARBITRATION_H
+#define __CROS_EC_I2C_ARBITRATION_H
+
+#include "common.h"
+
+#ifdef CONFIG_I2C_ARBITRATION
+
+/**
+ * Claim an I2C port for use in master mode.
+ *
+ * If this function succeeds, you must later call i2c_release() to release the
+ * claim.
+ *
+ * This function must not be called to claim an already-claimed port.
+ *
+ * @param port Port to claim (0 for first, 1 for second, etc.)
+ * @return 0 if claimed successfully, -1 if it is in use
+ */
+int i2c_claim(int port);
+
+/**
+ * Release an I2C port (after previously being claimed)
+ *
+ * This function must not be called to release an already-released port.
+ *
+ * @param port Port to claim (0 for first, 1 for second, etc.)
+ */
+void i2c_release(int port);
+
+#else
+
+static inline int i2c_claim(int port) { return EC_SUCCESS; }
+static inline void i2c_release(int port) {}
+
+#endif
+
+#endif /* __CROS_EC_I2C_ARBITRATION_H */