2 * i.MX6 OCOTP fusebox driver
4 * Copyright (c) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
6 * Based on the barebox ocotp driver,
7 * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>,
8 * Orex Computed Radiography
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * http://www.opensource.org/licenses/gpl-license.html
15 * http://www.gnu.org/copyleft/gpl.html
18 #include <linux/clk.h>
19 #include <linux/device.h>
21 #include <linux/module.h>
22 #include <linux/nvmem-provider.h>
24 #include <linux/of_device.h>
25 #include <linux/platform_device.h>
26 #include <linux/slab.h>
35 static int imx_ocotp_read(void *context
, unsigned int offset
,
36 void *val
, size_t bytes
)
38 struct ocotp_priv
*priv
= context
;
47 if (count
> (priv
->nregs
- index
))
48 count
= priv
->nregs
- index
;
50 ret
= clk_prepare_enable(priv
->clk
);
52 dev_err(priv
->dev
, "failed to prepare/enable ocotp clk\n");
55 for (i
= index
; i
< (index
+ count
); i
++)
56 *buf
++ = readl(priv
->base
+ 0x400 + i
* 0x10);
58 clk_disable_unprepare(priv
->clk
);
63 static struct nvmem_config imx_ocotp_nvmem_config
= {
69 .reg_read
= imx_ocotp_read
,
72 static const struct of_device_id imx_ocotp_dt_ids
[] = {
73 { .compatible
= "fsl,imx6q-ocotp", (void *)128 },
74 { .compatible
= "fsl,imx6sl-ocotp", (void *)32 },
75 { .compatible
= "fsl,imx6sx-ocotp", (void *)128 },
78 MODULE_DEVICE_TABLE(of
, imx_ocotp_dt_ids
);
80 static int imx_ocotp_probe(struct platform_device
*pdev
)
82 const struct of_device_id
*of_id
;
83 struct device
*dev
= &pdev
->dev
;
85 struct ocotp_priv
*priv
;
86 struct nvmem_device
*nvmem
;
88 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
92 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
93 priv
->base
= devm_ioremap_resource(dev
, res
);
94 if (IS_ERR(priv
->base
))
95 return PTR_ERR(priv
->base
);
97 priv
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
98 if (IS_ERR(priv
->clk
))
99 return PTR_ERR(priv
->clk
);
101 of_id
= of_match_device(imx_ocotp_dt_ids
, dev
);
102 priv
->nregs
= (unsigned long)of_id
->data
;
103 imx_ocotp_nvmem_config
.size
= 4 * priv
->nregs
;
104 imx_ocotp_nvmem_config
.dev
= dev
;
105 imx_ocotp_nvmem_config
.priv
= priv
;
106 nvmem
= nvmem_register(&imx_ocotp_nvmem_config
);
108 return PTR_ERR(nvmem
);
110 platform_set_drvdata(pdev
, nvmem
);
115 static int imx_ocotp_remove(struct platform_device
*pdev
)
117 struct nvmem_device
*nvmem
= platform_get_drvdata(pdev
);
119 return nvmem_unregister(nvmem
);
122 static struct platform_driver imx_ocotp_driver
= {
123 .probe
= imx_ocotp_probe
,
124 .remove
= imx_ocotp_remove
,
127 .of_match_table
= imx_ocotp_dt_ids
,
130 module_platform_driver(imx_ocotp_driver
);
132 MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
133 MODULE_DESCRIPTION("i.MX6 OCOTP fuse box driver");
134 MODULE_LICENSE("GPL v2");