summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/snow/board.c71
-rw-r--r--chip/stm32/i2c.c8
2 files changed, 71 insertions, 8 deletions
diff --git a/board/snow/board.c b/board/snow/board.c
index 4c9e30bd4b..4231ee4b2a 100644
--- a/board/snow/board.c
+++ b/board/snow/board.c
@@ -5,12 +5,15 @@
/* Snow board-specific configuration */
#include "board.h"
+#include "chipset.h"
#include "common.h"
+#include "console.h"
#include "dma.h"
#include "gpio.h"
#include "i2c.h"
#include "registers.h"
#include "spi.h"
+#include "timer.h"
#include "util.h"
#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH)
@@ -170,3 +173,71 @@ void board_interrupt_host(int active)
/* interrupt host by using active low EC_INT signal */
gpio_set_level(GPIO_EC_INT, !active);
}
+
+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 = 50 * 1000,
+};
+
+#ifdef CONFIG_ARBITRATE_I2C
+#define GPIO_AP_CLAIM GPIO_SPI1_NSS
+#define GPIO_EC_CLAIM GPIO_SPI1_MISO
+
+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_ON)) {
+ gpio_set_level(GPIO_EC_CLAIM, 0);
+ 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 */
+ 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);
+
+ 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);
+ }
+}
+#endif
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c
index e4840e786e..ec3be2ace7 100644
--- a/chip/stm32/i2c.c
+++ b/chip/stm32/i2c.c
@@ -424,10 +424,6 @@ static int i2c_master_transmit(int port, int slave_addr, uint8_t *data,
{
int rv, i;
- /* if the AP is ON, don't play with the connection */
- if ((port == I2C_PORT_SLAVE) && chipset_in_state(CHIPSET_STATE_ON))
- return EC_ERROR_BUSY;
-
disable_ack(port);
rv = master_start(port, slave_addr);
if (rv)
@@ -471,10 +467,6 @@ static int i2c_master_receive(int port, int slave_addr, uint8_t *data,
*/
int rv, i;
- /* if the AP is ON, don't play with the connection */
- if ((port == I2C_PORT_SLAVE) && chipset_in_state(CHIPSET_STATE_ON))
- return EC_ERROR_BUSY;
-
if (data == NULL || size < 1)
return EC_ERROR_INVAL;