diff --git a/drivers/eeprom/eeprom_mb85rcxx.c b/drivers/eeprom/eeprom_mb85rcxx.c index 23b9a60fed4..7d63f845ddd 100644 --- a/drivers/eeprom/eeprom_mb85rcxx.c +++ b/drivers/eeprom/eeprom_mb85rcxx.c @@ -20,6 +20,7 @@ struct mb85rcxx_config { struct i2c_dt_spec i2c; struct gpio_dt_spec wp_gpio; size_t size; + size_t pagesize; uint8_t addr_width; bool readonly; }; @@ -43,16 +44,31 @@ static uint16_t mb85rcxx_translate_address(const struct device *dev, off_t offse { const struct mb85rcxx_config *cfg = dev->config; + off_t page_offset = offset % cfg->pagesize; + if (cfg->addr_width > 8) { - sys_put_be16(offset, addr); + sys_put_be16(page_offset, addr); addr[0] &= BIT_MASK(cfg->addr_width - 8); } else { - addr[0] = offset & BIT_MASK(cfg->addr_width); + addr[0] = page_offset & BIT_MASK(cfg->addr_width); } return cfg->i2c.addr + (offset >> cfg->addr_width); } +static size_t mb85rcxx_remaining_len_in_page(const struct device *dev, off_t offset, size_t len) +{ + const struct mb85rcxx_config *cfg = dev->config; + off_t page_offset = offset % cfg->pagesize; + size_t rem = cfg->pagesize - page_offset; + + if (rem > len) { + rem = len; + } + + return rem; +} + static int mb85rcxx_init(const struct device *dev) { const struct mb85rcxx_config *cfg = dev->config; @@ -87,6 +103,7 @@ static int mb85rcxx_read(const struct device *dev, off_t offset, void *buf, size struct mb85rcxx_data *data = dev->data; uint8_t addr[2]; uint16_t i2c_addr; + size_t len_in_page; int ret; if (offset + len > cfg->size) { @@ -94,16 +111,27 @@ static int mb85rcxx_read(const struct device *dev, off_t offset, void *buf, size return -EINVAL; } - i2c_addr = mb85rcxx_translate_address(dev, offset, addr); - k_mutex_lock(&data->lock, K_FOREVER); - ret = i2c_write_read(cfg->i2c.bus, i2c_addr, addr, DIV_ROUND_UP(cfg->addr_width, 8), buf, - len); - if (ret < 0) { - LOG_ERR("failed to read FRAM (err %d)", ret); + + while (len) { + i2c_addr = mb85rcxx_translate_address(dev, offset, addr); + len_in_page = mb85rcxx_remaining_len_in_page(dev, offset, len); + + ret = i2c_write_read(cfg->i2c.bus, i2c_addr, addr, DIV_ROUND_UP(cfg->addr_width, 8), + buf, len_in_page); + if (ret < 0) { + LOG_ERR("failed to read FRAM (err %d)", ret); + k_mutex_unlock(&data->lock); + return ret; + } + + len -= len_in_page; + *(char *)&buf += len_in_page; + offset += len_in_page; } + k_mutex_unlock(&data->lock); - return ret; + return 0; } static int mb85rcxx_i2c_write(const struct device *dev, uint16_t i2c_addr, uint8_t *addr, @@ -129,6 +157,7 @@ static int mb85rcxx_write(const struct device *dev, off_t offset, const void *bu struct mb85rcxx_data *data = dev->data; uint8_t addr[2]; uint16_t i2c_addr; + size_t len_in_page; int ret; if (cfg->readonly) { @@ -147,10 +176,24 @@ static int mb85rcxx_write(const struct device *dev, off_t offset, const void *bu return ret; } - i2c_addr = mb85rcxx_translate_address(dev, offset, addr); - k_mutex_lock(&data->lock, K_FOREVER); - ret = mb85rcxx_i2c_write(dev, i2c_addr, addr, buf, len); + + while (len) { + i2c_addr = mb85rcxx_translate_address(dev, offset, addr); + len_in_page = mb85rcxx_remaining_len_in_page(dev, offset, len); + + ret = mb85rcxx_i2c_write(dev, i2c_addr, addr, buf, len); + if (ret < 0) { + LOG_ERR("failed to write to FRAM (err %d)", ret); + k_mutex_unlock(&data->lock); + return ret; + } + + len -= len_in_page; + *(char *)&buf += len_in_page; + offset += len_in_page; + } + k_mutex_unlock(&data->lock); mb85rcxx_write_protect_set(dev, 1); return ret; @@ -177,6 +220,9 @@ static const struct eeprom_driver_api mb85rcxx_driver_api = { IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, wp_gpios), \ (.wp_gpio = GPIO_DT_SPEC_INST_GET(inst, wp_gpios),)) \ .size = DT_INST_PROP(inst, size), \ + .pagesize = \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pagesize), \ + (DT_INST_PROP(inst, pagesize)), (DT_INST_PROP(inst, size))), \ .addr_width = DT_INST_PROP(inst, address_width), \ .readonly = DT_INST_PROP(inst, read_only)}; \ \ diff --git a/dts/bindings/mtd/fujitsu,mb85rcxx.yaml b/dts/bindings/mtd/fujitsu,mb85rcxx.yaml index 14d8ce45f45..21de9dcfbcc 100644 --- a/dts/bindings/mtd/fujitsu,mb85rcxx.yaml +++ b/dts/bindings/mtd/fujitsu,mb85rcxx.yaml @@ -12,6 +12,12 @@ properties: required: true description: Total FRAM size in bytes. + pagesize: + type: int + description: | + Size of the single FRAM module in bytes. + If not provided it is assumed to be the same as total size. + address-width: type: int required: true diff --git a/tests/drivers/build_all/eeprom/app.overlay b/tests/drivers/build_all/eeprom/app.overlay index 6575656db0c..117dd417b59 100644 --- a/tests/drivers/build_all/eeprom/app.overlay +++ b/tests/drivers/build_all/eeprom/app.overlay @@ -46,6 +46,7 @@ compatible = "fujitsu,mb85rcxx"; reg = <0x1>; size = <131072>; + pagesize = <131072>; address-width = <16>; wp-gpios = <&test_gpio 0 0>; /* read-only; */