diff options
| author | Niko Mauno <[email protected]> | 2026-02-04 15:17:37 +0200 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-02-18 16:35:07 -0600 |
| commit | f97642853cd379ef69d00bca6c3928bce226dc5e (patch) | |
| tree | 9559d78fe713e8519527dd54683fb32908b75e49 /drivers/bootcount/bootcount_dm_i2c.c | |
| parent | 05b56599b5b13a504d8ed66db27a4446f8b9acc5 (diff) | |
bootcount: dm_i2c: Support also single word mode
In addition to pre-existing half-word (2 byte) mode, add support for
the driver to work also in single word (4 byte) mode by adding
'size = <0x4>;' in the device tree node.
Signed-off-by: Niko Mauno <[email protected]>
Diffstat (limited to 'drivers/bootcount/bootcount_dm_i2c.c')
| -rw-r--r-- | drivers/bootcount/bootcount_dm_i2c.c | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/drivers/bootcount/bootcount_dm_i2c.c b/drivers/bootcount/bootcount_dm_i2c.c index e27034cbeb0..07359ecfa6c 100644 --- a/drivers/bootcount/bootcount_dm_i2c.c +++ b/drivers/bootcount/bootcount_dm_i2c.c @@ -15,6 +15,7 @@ struct bootcount_i2c_priv { struct udevice *bcdev; unsigned int offset; + unsigned int size; }; static int bootcount_i2c_set(struct udevice *dev, const u32 val) @@ -22,13 +23,22 @@ static int bootcount_i2c_set(struct udevice *dev, const u32 val) int ret; struct bootcount_i2c_priv *priv = dev_get_priv(dev); - ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC); - if (ret < 0) - goto err_exit; - - ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff); - if (ret < 0) - goto err_exit; + if (priv->size == 4) { + u32 bc = (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK) + | (val & BOOTCOUNT_COUNT_MASK); + + ret = dm_i2c_write(priv->bcdev, priv->offset, (uint8_t *)&bc, sizeof(bc)); + if (ret < 0) + goto err_exit; + } else { + ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC); + if (ret < 0) + goto err_exit; + + ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff); + if (ret < 0) + goto err_exit; + } return 0; @@ -42,21 +52,39 @@ static int bootcount_i2c_get(struct udevice *dev, u32 *val) int ret; struct bootcount_i2c_priv *priv = dev_get_priv(dev); - ret = dm_i2c_reg_read(priv->bcdev, priv->offset); - if (ret < 0) - goto err_exit; - - if ((ret & 0xff) != BC_MAGIC) { - log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__); - *val = 0; - return bootcount_i2c_set(dev, 0); + if (priv->size == 4) { + u32 bc; + + ret = dm_i2c_read(priv->bcdev, priv->offset, (uint8_t *)&bc, sizeof(bc)); + if (ret < 0) + goto err_exit; + + if ((bc & BOOTCOUNT_MAGIC_MASK) != + (CONFIG_SYS_BOOTCOUNT_MAGIC & BOOTCOUNT_MAGIC_MASK)) { + log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__); + *val = 0; + return bootcount_i2c_set(dev, 0); + } + + *val = (bc & BOOTCOUNT_COUNT_MASK); + } else { + ret = dm_i2c_reg_read(priv->bcdev, priv->offset); + if (ret < 0) + goto err_exit; + + if ((ret & 0xff) != BC_MAGIC) { + log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__); + *val = 0; + return bootcount_i2c_set(dev, 0); + } + + ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1); + if (ret < 0) + goto err_exit; + + *val = ret; } - ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1); - if (ret < 0) - goto err_exit; - - *val = ret; return 0; err_exit: @@ -73,6 +101,12 @@ static int bootcount_i2c_probe(struct udevice *dev) if (ret) goto exit; + priv->size = dev_read_u32_default(dev, "size", 2); + if (priv->size != 2 && priv->size != 4) { + ret = -EINVAL; + goto exit; + } + ret = i2c_get_chip_by_phandle(dev, "i2cbcdev", &priv->bcdev); exit: |
