diff options
author | Nico Huber <nico.huber@secunet.com> | 2017-11-01 13:15:33 +0100 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2019-09-30 11:50:16 +0000 |
commit | 9734af669768203349485bd76a4ad3c79c8bdc73 (patch) | |
tree | 7395ab22c71f5e5a7b6f12b8e71aa449ba47cf2e | |
parent | 9529530766ed6f1ed17c2af11d51deca9a2092d6 (diff) | |
download | coreboot-9734af669768203349485bd76a4ad3c79c8bdc73.tar.xz |
device/i2c_bus: Add i2c_dev_read_at16()
i2c_dev_read_at16() sends a 16-bit offset to the I2C chip (for larger
EEPROM parts), then reads bytes up to a given length into a buffer.
Change-Id: I7516f3e5d9aca362c2b340aa5627d91510c09412
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/29478
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
-rw-r--r-- | src/device/i2c_bus.c | 37 | ||||
-rw-r--r-- | src/include/device/i2c_bus.h | 8 |
2 files changed, 45 insertions, 0 deletions
diff --git a/src/device/i2c_bus.c b/src/device/i2c_bus.c index 30bb80ca98..93634d223b 100644 --- a/src/device/i2c_bus.c +++ b/src/device/i2c_bus.c @@ -16,6 +16,7 @@ #include <console/console.h> #include <device/smbus.h> #include <device/i2c_bus.h> +#include <commonlib/endian.h> struct bus *i2c_link(struct device *const dev) { @@ -159,3 +160,39 @@ int i2c_dev_writeb_at(struct device *const dev, return -1; } } + +int i2c_dev_read_at16(struct device *const dev, + uint8_t *const buf, const size_t len, uint16_t off) +{ + struct device *const busdev = i2c_busdev(dev); + if (!busdev) + return -1; + + if (busdev->ops->ops_i2c_bus) { + const struct i2c_msg msg[] = { + { + .flags = 0, + .slave = dev->path.i2c.device, + .buf = (uint8_t *)&off, + .len = sizeof(off), + }, + { + .flags = I2C_M_RD, + .slave = dev->path.i2c.device, + .buf = buf, + .len = len, + }, + }; + + write_be16(&off, off); + const int ret = busdev->ops->ops_i2c_bus->transfer( + busdev, msg, ARRAY_SIZE(msg)); + if (ret) + return ret; + else + return len; + } else { + printk(BIOS_ERR, "%s Missing ops_i2c_bus->transfer", dev_path(busdev)); + return -1; + } +} diff --git a/src/include/device/i2c_bus.h b/src/include/device/i2c_bus.h index 6aa4f9ba9d..5302d20228 100644 --- a/src/include/device/i2c_bus.h +++ b/src/include/device/i2c_bus.h @@ -89,4 +89,12 @@ int i2c_dev_readb_at(struct device *, uint8_t off); */ int i2c_dev_writeb_at(struct device *, uint8_t off, uint8_t val); +/* + * Sends the 16-bit register offset `off` and reads `len` bytes into `buf`. + * + * Returns the number of bytes read on success, negative `enum cb_err` + * value on error. + */ +int i2c_dev_read_at16(struct device *, uint8_t *buf, size_t len, uint16_t off); + #endif /* _DEVICE_I2C_BUS_H_ */ |