From ff52ac20c1603317f601af73076179da06b3a909 Mon Sep 17 00:00:00 2001 From: Mulin Chao Date: Thu, 4 Feb 2016 10:30:38 +0800 Subject: common: Fix sleep mask for multi-port lock. This change use a simple counter to to prevent ec enter sleep if there's any i2c port active. Once there's no i2c port active, we enable sleep bit of i2c in i2c_lock() func. Please note FW disables interrupt during changing counter to prevent preemptive conditions. Modified sources: 1. common/i2c.c: Fix sleep mask for multi-port lock. BUG=crbug.com/537759 TEST=make buildall -j; test on wheatley when CONFIG_LOW_POWER_S0 is deifned. BRANCH=none Change-Id: I17c226108fee0e5d656fa157808179898f9a8dbf Signed-off-by: Mulin Chao Reviewed-on: https://chromium-review.googlesource.com/325256 Reviewed-by: Randall Spangler --- common/i2c.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index 6e8bf10c4e..c06df9d784 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -33,6 +33,7 @@ #endif static struct mutex port_mutex[I2C_CONTROLLER_COUNT]; +static uint32_t i2c_port_active_count; int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) @@ -57,18 +58,27 @@ void i2c_lock(int port, int lock) ASSERT(port != -1); #endif if (lock) { - /* - * Don't allow deep sleep when I2C port is locked - * TODO(crbug.com/537759): Fix sleep mask for multi-port lock. - */ + mutex_lock(port_mutex + port); + + /* Disable interrupt during changing counter for preemption. */ + interrupt_disable(); + + i2c_port_active_count++; + /* Ec cannot enter sleep if there's any i2c port active. */ disable_sleep(SLEEP_MASK_I2C_MASTER); - mutex_lock(port_mutex + port); + interrupt_enable(); } else { - mutex_unlock(port_mutex + port); + interrupt_disable(); + + i2c_port_active_count--; + /* Once there is no i2c port active, enable sleep bit of i2c. */ + if (!i2c_port_active_count) + enable_sleep(SLEEP_MASK_I2C_MASTER); - /* Allow deep sleep again after I2C port is unlocked */ - enable_sleep(SLEEP_MASK_I2C_MASTER); + interrupt_enable(); + + mutex_unlock(port_mutex + port); } } -- cgit v1.2.1