summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2016-11-09 08:14:12 -0800
committerSascha Hauer <s.hauer@pengutronix.de>2017-01-11 08:07:00 +0100
commit278a35ffcb4bc2486a869380da462e8a4d291020 (patch)
tree5e8f3746c29af4ff42af0e58064077233fc474c8 /arch
parenta44efbc983b79aee95af6192c12ccc22e32b05ff (diff)
downloadbarebox-278a35ffcb4bc2486a869380da462e8a4d291020.tar.gz
i.MX: ocotp: Account for shadow memory gaps
Shadow memory does not have a true 1:1 mapping to fuse address space. All i.MX6 devices, with exception of i.MX6SL have a 0x100 byte gap between banks 5 and 6 (or addresses 0x2f and 0x30), so we need to account for that when reading data from shadow memory. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/ocotp.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 9c6b971..f39e1fa 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -74,6 +74,7 @@
struct imx_ocotp_data {
int num_regs;
+ u32 (*addr_to_offset)(u32 addr);
};
struct ocotp_priv {
@@ -85,6 +86,7 @@ struct ocotp_priv {
int sense_enable;
char ethaddr[6];
struct regmap_config map_config;
+ const struct imx_ocotp_data *data;
};
static struct ocotp_priv *imx_ocotp;
@@ -195,7 +197,8 @@ static int imx_ocotp_reg_read(void *ctx, unsigned int reg, unsigned int *val)
if (ret)
return ret;
} else {
- *(u32 *)val = readl(priv->base + 0x400 + index * 0x10);
+ *(u32 *)val = readl(priv->base +
+ priv->data->addr_to_offset(index));
}
return 0;
@@ -275,7 +278,8 @@ static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val)
if (ret < 0)
return ret;
} else {
- writel(val, priv->base + 0x400 + index * 0x10);
+ writel(val, priv->base +
+ priv->data->addr_to_offset(index));
}
if (priv->permanent_write_enable)
@@ -437,7 +441,7 @@ static int imx_ocotp_probe(struct device_d *dev)
void __iomem *base;
struct ocotp_priv *priv;
int ret = 0;
- struct imx_ocotp_data *data;
+ const struct imx_ocotp_data *data;
ret = dev_get_drvdata(dev, (const void **)&data);
if (ret)
@@ -452,6 +456,7 @@ static int imx_ocotp_probe(struct device_d *dev)
priv = xzalloc(sizeof(*priv));
+ priv->data = data;
priv->base = base;
priv->clk = clk_get(dev, NULL);
if (IS_ERR(priv->clk))
@@ -490,12 +495,35 @@ static int imx_ocotp_probe(struct device_d *dev)
return 0;
}
+static u32 imx6sl_addr_to_offset(u32 addr)
+{
+ return 0x400 + addr * 0x10;
+}
+
+static u32 imx6q_addr_to_offset(u32 addr)
+{
+ u32 addendum = 0;
+
+ if (addr > 0x2F) {
+ /*
+ * If we are reading past Bank 5, take into account a
+ * 0x100 bytes wide gap between Bank 5 and Bank 6
+ */
+ addendum += 0x100;
+ }
+
+
+ return imx6sl_addr_to_offset(addr) + addendum;
+}
+
static struct imx_ocotp_data imx6q_ocotp_data = {
.num_regs = 512,
+ .addr_to_offset = imx6q_addr_to_offset,
};
static struct imx_ocotp_data imx6sl_ocotp_data = {
.num_regs = 256,
+ .addr_to_offset = imx6sl_addr_to_offset,
};
static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {