diff options
author | Denis Brockus <dbrockus@chromium.org> | 2019-12-08 13:13:09 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-12-15 16:15:16 +0000 |
commit | 349bceadd7c30c1a01f78f62d68da0b9b79af346 (patch) | |
tree | d1342cd1c9e977f8a8bd7228829850aa149e9655 /common | |
parent | 96ff4b86f9b6ceac2232c41527103f3d7bd825f3 (diff) | |
download | chrome-ec-349bceadd7c30c1a01f78f62d68da0b9b79af346.tar.gz |
i2c: add generic read/modify/write operations
i2c_update is used to set or clear a mask
i2c_field_update is used to clear out a field before the set
BUG=none
BRANCH=none
TEST=make buildall -j
Change-Id: I7f8f93f4894fb9635092931a93961d328eacfeb9
Signed-off-by: Denis Brockus <dbrockus@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1956437
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Commit-Queue: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2584544
Reviewed-by: Zhuohao Lee <zhuohao@chromium.org>
Tested-by: David Huang <david.huang@quanta.corp-partner.google.com>
Auto-Submit: David Huang <david.huang@quanta.corp-partner.google.com>
Diffstat (limited to 'common')
-rw-r--r-- | common/i2c_master.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/common/i2c_master.c b/common/i2c_master.c index f6d5b2fdc5..1aa4dc7bc7 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -306,6 +306,92 @@ int i2c_write8(int port, int slave_addr, int offset, int data) return i2c_xfer(port, slave_addr, buf, 2, 0, 0); } +int i2c_update8(const int port, + const uint16_t slave_addr_flags, + const int offset, + const uint8_t mask, + const enum mask_update_action action) +{ + int rv; + int val, oldval; + + rv = i2c_read8(port, slave_addr_flags, offset, &oldval); + if (rv) + return rv; + + val = (action == MASK_SET) ? oldval | mask + : oldval & ~mask; + + if (val != oldval) + return i2c_write8(port, slave_addr_flags, offset, val); + + return EC_SUCCESS; +} + +int i2c_update16(const int port, + const uint16_t slave_addr_flags, + const int offset, + const uint16_t mask, + const enum mask_update_action action) +{ + int rv; + int val, oldval; + + rv = i2c_read16(port, slave_addr_flags, offset, &oldval); + if (rv) + return rv; + + val = (action == MASK_SET) ? oldval | mask + : oldval & ~mask; + + if (val != oldval) + return i2c_write16(port, slave_addr_flags, offset, val); + + return EC_SUCCESS; +} + +int i2c_field_update8(const int port, + const uint16_t slave_addr_flags, + const int offset, + const uint8_t field_mask, + const uint8_t set_value) +{ + int rv; + int val, oldval; + + rv = i2c_read8(port, slave_addr_flags, offset, &oldval); + if (rv) + return rv; + + val = (oldval & (~field_mask)) | set_value; + + if (val != oldval) + return i2c_write8(port, slave_addr_flags, offset, val); + + return EC_SUCCESS; +} + +int i2c_field_update16(const int port, + const uint16_t slave_addr_flags, + const int offset, + const uint16_t field_mask, + const uint16_t set_value) +{ + int rv; + int val, oldval; + + rv = i2c_read16(port, slave_addr_flags, offset, &oldval); + if (rv) + return rv; + + val = (oldval & (~field_mask)) | set_value; + + if (val != oldval) + return i2c_write16(port, slave_addr_flags, offset, val); + + return EC_SUCCESS; +} + int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, int len) { |