diff options
author | Peng Fan <peng.fan@nxp.com> | 2017-08-18 11:19:08 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 22bbc876f7be91f5c9cd221c06826d02846a1cbd (patch) | |
tree | 1c8a2fa166b0598ffcb4752d7e568501b294e9cc /drivers/nvmem | |
parent | 69aa134f82b8b07dc126b7de66970d3d177b848e (diff) |
MLK-16204-4: nvmem: imx-ocotp: add i.mx8mq support and fix read
Add i.MX8MQ support and Fix read.
When offset is not 4 bytes aligned, directly shift righty by 2 bits
will cause reading out wrong data. Since imx ocotp only supports
4 bytes reading once, we need handle offset is not 4 bytes aligned
and enlarge the bytes to 4 bytes aligned. After finished reading,
copy the needed data from buffer to caller and free buffer.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'drivers/nvmem')
-rw-r--r-- | drivers/nvmem/Kconfig | 2 | ||||
-rw-r--r-- | drivers/nvmem/imx-ocotp.c | 30 |
2 files changed, 25 insertions, 7 deletions
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 29601e0b3e42..f165be7f65cf 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -15,7 +15,7 @@ if NVMEM config NVMEM_IMX_OCOTP tristate "i.MX6 On-Chip OTP Controller support" - depends on SOC_IMX6 || COMPILE_TEST + depends on SOC_IMX6 || ARCH_MXC_ARM64 || COMPILE_TEST depends on HAS_IOMEM help This is a driver for the On-Chip OTP Controller (OCOTP) available on diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index 8e7b120696fa..d5c02174149d 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c @@ -3,6 +3,8 @@ * * Copyright (c) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de> * + * Copyright 2017 NXP + * * Based on the barebox ocotp driver, * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>, * Orex Computed Radiography @@ -37,26 +39,40 @@ static int imx_ocotp_read(void *context, unsigned int offset, { struct ocotp_priv *priv = context; unsigned int count; - u32 *buf = val; + u8 *buf, *p; int i, ret; - u32 index; + u32 index, num_bytes; index = offset >> 2; - count = bytes >> 2; + num_bytes = round_up((offset % 4) + bytes, 4); + count = num_bytes >> 2; if (count > (priv->nregs - index)) count = priv->nregs - index; + p = kzalloc(num_bytes, GFP_KERNEL); + if (!p) + return -ENOMEM; + buf = p; + ret = clk_prepare_enable(priv->clk); if (ret < 0) { dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); + kfree(p); return ret; } - for (i = index; i < (index + count); i++) - *buf++ = readl(priv->base + 0x400 + i * 0x10); + for (i = index; i < (index + count); i++) { + *(u32 *)buf = readl(priv->base + 0x400 + i * 0x10); + buf += 4; + } clk_disable_unprepare(priv->clk); + index = offset % 4; + memcpy(val, &p[index], bytes); + + kfree(p); + return 0; } @@ -64,7 +80,7 @@ static struct nvmem_config imx_ocotp_nvmem_config = { .name = "imx-ocotp", .read_only = true, .word_size = 4, - .stride = 4, + .stride = 1, .owner = THIS_MODULE, .reg_read = imx_ocotp_read, }; @@ -73,6 +89,7 @@ static const struct of_device_id imx_ocotp_dt_ids[] = { { .compatible = "fsl,imx6q-ocotp", (void *)128 }, { .compatible = "fsl,imx6sl-ocotp", (void *)64 }, { .compatible = "fsl,imx6sx-ocotp", (void *)128 }, + { .compatible = "fsl,imx8mq-ocotp", (void *)256 }, { }, }; MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); @@ -100,6 +117,7 @@ static int imx_ocotp_probe(struct platform_device *pdev) of_id = of_match_device(imx_ocotp_dt_ids, dev); priv->nregs = (unsigned long)of_id->data; + priv->dev = dev; imx_ocotp_nvmem_config.size = 4 * priv->nregs; imx_ocotp_nvmem_config.dev = dev; imx_ocotp_nvmem_config.priv = priv; |