[PATCH 2/2] nvmem: imx-ocotp: allow reads with arbitrary size and offset

From: Jose Diaz de Grenu
Date: Tue Jul 23 2019 - 11:33:07 EST


Currently the driver only allows to read 32 aligned 32-bit chunks. This
is inconvenient when defining nvmem-cells, as they are rarely a multiple
of 32 bits in size, and that makes the nvmem-consumer hardcode offsets and
masks to extract the real value.

Remove the limitation but keep reading in 32-bit chunks from the hardware
to ensure there is no change in the behaviour.

Signed-off-by: Jose Diaz de Grenu <Jose.DiazdeGrenu@xxxxxxxx>
---
drivers/nvmem/imx-ocotp.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index dc86d863563a..9590eeab85d8 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -121,16 +121,8 @@ static int imx_ocotp_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct ocotp_priv *priv = context;
- unsigned int count;
- u32 *buf = val;
+ u8 *buf = val;
int i, ret;
- u32 index;
-
- index = offset >> 2;
- count = bytes >> 2;
-
- if (count > (priv->params->nregs - index))
- count = priv->params->nregs - index;

mutex_lock(&ocotp_mutex);

@@ -147,9 +139,9 @@ static int imx_ocotp_read(void *context, unsigned int offset,
goto read_end;
}

- for (i = index; i < (index + count); i++) {
- *buf++ = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 +
- i * IMX_OCOTP_OFFSET_PER_WORD);
+ for (i = offset; i < (bytes + offset); i++) {
+ u32 word_val = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 +
+ (i >> 2) * IMX_OCOTP_OFFSET_PER_WORD);

/* 47.3.1.2
* For "read locked" registers 0xBADABADA will be returned and
@@ -157,9 +149,14 @@ static int imx_ocotp_read(void *context, unsigned int offset,
* software before any new write, read or reload access can be
* issued
*/
- if (*(buf - 1) == IMX_OCOTP_READ_LOCKED_VAL)
+ if (word_val == IMX_OCOTP_READ_LOCKED_VAL)
imx_ocotp_clr_err_if_set(priv->base);
+
+ word_val >>= (i % 4) * 8;
+
+ *buf++ = (u8) (word_val & 0xFF);
}
+
ret = 0;

read_end:
@@ -415,8 +412,8 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val,
static struct nvmem_config imx_ocotp_nvmem_config = {
.name = "imx-ocotp",
.read_only = false,
- .word_size = 4,
- .stride = 4,
+ .word_size = 1,
+ .stride = 1,
.reg_read = imx_ocotp_read,
.reg_write = imx_ocotp_write,
};