xref: /linux/drivers/nvmem/imx-ocotp.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
1acee2e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23edba6b4SPhilipp Zabel /*
33edba6b4SPhilipp Zabel  * i.MX6 OCOTP fusebox driver
43edba6b4SPhilipp Zabel  *
53edba6b4SPhilipp Zabel  * Copyright (c) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
63edba6b4SPhilipp Zabel  *
73311bf18SPeng Fan  * Copyright 2019 NXP
83311bf18SPeng Fan  *
93edba6b4SPhilipp Zabel  * Based on the barebox ocotp driver,
103edba6b4SPhilipp Zabel  * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>,
113edba6b4SPhilipp Zabel  *	Orex Computed Radiography
123edba6b4SPhilipp Zabel  *
130642bac7SRichard Leitner  * Write support based on the fsl_otp driver,
140642bac7SRichard Leitner  * Copyright (C) 2010-2013 Freescale Semiconductor, Inc
153edba6b4SPhilipp Zabel  */
163edba6b4SPhilipp Zabel 
17deb31970SPeng Fan #include <linux/clk.h>
183edba6b4SPhilipp Zabel #include <linux/device.h>
193edba6b4SPhilipp Zabel #include <linux/io.h>
203edba6b4SPhilipp Zabel #include <linux/module.h>
213edba6b4SPhilipp Zabel #include <linux/nvmem-provider.h>
223edba6b4SPhilipp Zabel #include <linux/of.h>
233edba6b4SPhilipp Zabel #include <linux/platform_device.h>
243edba6b4SPhilipp Zabel #include <linux/slab.h>
250642bac7SRichard Leitner #include <linux/delay.h>
263edba6b4SPhilipp Zabel 
279b66587eSRichard Leitner #define IMX_OCOTP_OFFSET_B0W0		0x400 /* Offset from base address of the
289b66587eSRichard Leitner 					       * OTP Bank0 Word0
299b66587eSRichard Leitner 					       */
309b66587eSRichard Leitner #define IMX_OCOTP_OFFSET_PER_WORD	0x10  /* Offset between the start addr
319b66587eSRichard Leitner 					       * of two consecutive OTP words.
329b66587eSRichard Leitner 					       */
330642bac7SRichard Leitner 
349b66587eSRichard Leitner #define IMX_OCOTP_ADDR_CTRL		0x0000
350642bac7SRichard Leitner #define IMX_OCOTP_ADDR_CTRL_SET		0x0004
369b66587eSRichard Leitner #define IMX_OCOTP_ADDR_CTRL_CLR		0x0008
370642bac7SRichard Leitner #define IMX_OCOTP_ADDR_TIMING		0x0010
38ffd9115fSBryan O'Donoghue #define IMX_OCOTP_ADDR_DATA0		0x0020
39ffd9115fSBryan O'Donoghue #define IMX_OCOTP_ADDR_DATA1		0x0030
40ffd9115fSBryan O'Donoghue #define IMX_OCOTP_ADDR_DATA2		0x0040
41ffd9115fSBryan O'Donoghue #define IMX_OCOTP_ADDR_DATA3		0x0050
429b66587eSRichard Leitner 
43c03bb448SBryan O'Donoghue #define IMX_OCOTP_BM_CTRL_ADDR		0x000000FF
440642bac7SRichard Leitner #define IMX_OCOTP_BM_CTRL_BUSY		0x00000100
459b66587eSRichard Leitner #define IMX_OCOTP_BM_CTRL_ERROR		0x00000200
460642bac7SRichard Leitner #define IMX_OCOTP_BM_CTRL_REL_SHADOWS	0x00000400
479b66587eSRichard Leitner 
48c3f4af8bSPeng Fan #define IMX_OCOTP_BM_CTRL_ADDR_8MP		0x000001FF
49c3f4af8bSPeng Fan #define IMX_OCOTP_BM_CTRL_BUSY_8MP		0x00000200
50c3f4af8bSPeng Fan #define IMX_OCOTP_BM_CTRL_ERROR_8MP		0x00000400
51c3f4af8bSPeng Fan #define IMX_OCOTP_BM_CTRL_REL_SHADOWS_8MP	0x00000800
52c3f4af8bSPeng Fan 
53226c5126SPeng Fan #define IMX_OCOTP_BM_CTRL_DEFAULT				\
54226c5126SPeng Fan 	{							\
55226c5126SPeng Fan 		.bm_addr = IMX_OCOTP_BM_CTRL_ADDR,		\
56226c5126SPeng Fan 		.bm_busy = IMX_OCOTP_BM_CTRL_BUSY,		\
57226c5126SPeng Fan 		.bm_error = IMX_OCOTP_BM_CTRL_ERROR,		\
58226c5126SPeng Fan 		.bm_rel_shadows = IMX_OCOTP_BM_CTRL_REL_SHADOWS,\
59226c5126SPeng Fan 	}
60226c5126SPeng Fan 
61c3f4af8bSPeng Fan #define IMX_OCOTP_BM_CTRL_8MP					\
62c3f4af8bSPeng Fan 	{							\
63c3f4af8bSPeng Fan 		.bm_addr = IMX_OCOTP_BM_CTRL_ADDR_8MP,		\
64c3f4af8bSPeng Fan 		.bm_busy = IMX_OCOTP_BM_CTRL_BUSY_8MP,		\
65c3f4af8bSPeng Fan 		.bm_error = IMX_OCOTP_BM_CTRL_ERROR_8MP,	\
66c3f4af8bSPeng Fan 		.bm_rel_shadows = IMX_OCOTP_BM_CTRL_REL_SHADOWS_8MP,\
67c3f4af8bSPeng Fan 	}
68c3f4af8bSPeng Fan 
69159dbaf5SBryan O'Donoghue #define TIMING_STROBE_PROG_US		10	/* Min time to blow a fuse */
70159dbaf5SBryan O'Donoghue #define TIMING_STROBE_READ_NS		37	/* Min time before read */
71159dbaf5SBryan O'Donoghue #define TIMING_RELAX_NS			17
72828ae7a4SBryan O'Donoghue #define DEF_FSOURCE			1001	/* > 1000 ns */
73828ae7a4SBryan O'Donoghue #define DEF_STROBE_PROG			10000	/* IPG clocks */
740642bac7SRichard Leitner #define IMX_OCOTP_WR_UNLOCK		0x3E770000
759b66587eSRichard Leitner #define IMX_OCOTP_READ_LOCKED_VAL	0xBADABADA
769b66587eSRichard Leitner 
770642bac7SRichard Leitner static DEFINE_MUTEX(ocotp_mutex);
780642bac7SRichard Leitner 
793edba6b4SPhilipp Zabel struct ocotp_priv {
803edba6b4SPhilipp Zabel 	struct device *dev;
81deb31970SPeng Fan 	struct clk *clk;
823edba6b4SPhilipp Zabel 	void __iomem *base;
83e20d2b29SBryan O'Donoghue 	const struct ocotp_params *params;
840642bac7SRichard Leitner 	struct nvmem_config *config;
853edba6b4SPhilipp Zabel };
863edba6b4SPhilipp Zabel 
87226c5126SPeng Fan struct ocotp_ctrl_reg {
88226c5126SPeng Fan 	u32 bm_addr;
89226c5126SPeng Fan 	u32 bm_busy;
90226c5126SPeng Fan 	u32 bm_error;
91226c5126SPeng Fan 	u32 bm_rel_shadows;
92226c5126SPeng Fan };
93226c5126SPeng Fan 
94828ae7a4SBryan O'Donoghue struct ocotp_params {
95828ae7a4SBryan O'Donoghue 	unsigned int nregs;
96828ae7a4SBryan O'Donoghue 	unsigned int bank_address_words;
97828ae7a4SBryan O'Donoghue 	void (*set_timing)(struct ocotp_priv *priv);
98226c5126SPeng Fan 	struct ocotp_ctrl_reg ctrl;
99828ae7a4SBryan O'Donoghue };
100828ae7a4SBryan O'Donoghue 
imx_ocotp_wait_for_busy(struct ocotp_priv * priv,u32 flags)101226c5126SPeng Fan static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
1020642bac7SRichard Leitner {
1030642bac7SRichard Leitner 	int count;
1040642bac7SRichard Leitner 	u32 c, mask;
105226c5126SPeng Fan 	u32 bm_ctrl_busy, bm_ctrl_error;
106226c5126SPeng Fan 	void __iomem *base = priv->base;
1070642bac7SRichard Leitner 
108226c5126SPeng Fan 	bm_ctrl_busy = priv->params->ctrl.bm_busy;
109226c5126SPeng Fan 	bm_ctrl_error = priv->params->ctrl.bm_error;
110226c5126SPeng Fan 
111226c5126SPeng Fan 	mask = bm_ctrl_busy | bm_ctrl_error | flags;
1120642bac7SRichard Leitner 
1130642bac7SRichard Leitner 	for (count = 10000; count >= 0; count--) {
1140642bac7SRichard Leitner 		c = readl(base + IMX_OCOTP_ADDR_CTRL);
1150642bac7SRichard Leitner 		if (!(c & mask))
1160642bac7SRichard Leitner 			break;
1170642bac7SRichard Leitner 		cpu_relax();
1180642bac7SRichard Leitner 	}
1190642bac7SRichard Leitner 
1200642bac7SRichard Leitner 	if (count < 0) {
1210642bac7SRichard Leitner 		/* HW_OCOTP_CTRL[ERROR] will be set under the following
1220642bac7SRichard Leitner 		 * conditions:
1230642bac7SRichard Leitner 		 * - A write is performed to a shadow register during a shadow
1240642bac7SRichard Leitner 		 *   reload (essentially, while HW_OCOTP_CTRL[RELOAD_SHADOWS] is
1250642bac7SRichard Leitner 		 *   set. In addition, the contents of the shadow register shall
1260642bac7SRichard Leitner 		 *   not be updated.
1270642bac7SRichard Leitner 		 * - A write is performed to a shadow register which has been
1280642bac7SRichard Leitner 		 *   locked.
1290642bac7SRichard Leitner 		 * - A read is performed to from a shadow register which has
1300642bac7SRichard Leitner 		 *   been read locked.
1310642bac7SRichard Leitner 		 * - A program is performed to a fuse word which has been locked
1320642bac7SRichard Leitner 		 * - A read is performed to from a fuse word which has been read
1330642bac7SRichard Leitner 		 *   locked.
1340642bac7SRichard Leitner 		 */
135226c5126SPeng Fan 		if (c & bm_ctrl_error)
1360642bac7SRichard Leitner 			return -EPERM;
1370642bac7SRichard Leitner 		return -ETIMEDOUT;
1380642bac7SRichard Leitner 	}
1390642bac7SRichard Leitner 
1400642bac7SRichard Leitner 	return 0;
1410642bac7SRichard Leitner }
1420642bac7SRichard Leitner 
imx_ocotp_clr_err_if_set(struct ocotp_priv * priv)143226c5126SPeng Fan static void imx_ocotp_clr_err_if_set(struct ocotp_priv *priv)
1449b66587eSRichard Leitner {
145226c5126SPeng Fan 	u32 c, bm_ctrl_error;
146226c5126SPeng Fan 	void __iomem *base = priv->base;
147226c5126SPeng Fan 
148226c5126SPeng Fan 	bm_ctrl_error = priv->params->ctrl.bm_error;
1499b66587eSRichard Leitner 
1509b66587eSRichard Leitner 	c = readl(base + IMX_OCOTP_ADDR_CTRL);
151226c5126SPeng Fan 	if (!(c & bm_ctrl_error))
1529b66587eSRichard Leitner 		return;
1539b66587eSRichard Leitner 
154226c5126SPeng Fan 	writel(bm_ctrl_error, base + IMX_OCOTP_ADDR_CTRL_CLR);
1559b66587eSRichard Leitner }
1569b66587eSRichard Leitner 
imx_ocotp_read(void * context,unsigned int offset,void * val,size_t bytes)15733e5e29cSSrinivas Kandagatla static int imx_ocotp_read(void *context, unsigned int offset,
15833e5e29cSSrinivas Kandagatla 			  void *val, size_t bytes)
1593edba6b4SPhilipp Zabel {
1603edba6b4SPhilipp Zabel 	struct ocotp_priv *priv = context;
1613edba6b4SPhilipp Zabel 	unsigned int count;
1623311bf18SPeng Fan 	u8 *buf, *p;
163deb31970SPeng Fan 	int i, ret;
1643311bf18SPeng Fan 	u32 index, num_bytes;
1653edba6b4SPhilipp Zabel 
1663edba6b4SPhilipp Zabel 	index = offset >> 2;
1673311bf18SPeng Fan 	num_bytes = round_up((offset % 4) + bytes, 4);
1683311bf18SPeng Fan 	count = num_bytes >> 2;
1693edba6b4SPhilipp Zabel 
170e20d2b29SBryan O'Donoghue 	if (count > (priv->params->nregs - index))
171e20d2b29SBryan O'Donoghue 		count = priv->params->nregs - index;
1723edba6b4SPhilipp Zabel 
1733311bf18SPeng Fan 	p = kzalloc(num_bytes, GFP_KERNEL);
1743311bf18SPeng Fan 	if (!p)
1753311bf18SPeng Fan 		return -ENOMEM;
1763311bf18SPeng Fan 
1770642bac7SRichard Leitner 	mutex_lock(&ocotp_mutex);
1780642bac7SRichard Leitner 
1793311bf18SPeng Fan 	buf = p;
1803311bf18SPeng Fan 
181deb31970SPeng Fan 	ret = clk_prepare_enable(priv->clk);
182deb31970SPeng Fan 	if (ret < 0) {
1830642bac7SRichard Leitner 		mutex_unlock(&ocotp_mutex);
184deb31970SPeng Fan 		dev_err(priv->dev, "failed to prepare/enable ocotp clk\n");
1853311bf18SPeng Fan 		kfree(p);
186deb31970SPeng Fan 		return ret;
187deb31970SPeng Fan 	}
1889b66587eSRichard Leitner 
189226c5126SPeng Fan 	ret = imx_ocotp_wait_for_busy(priv, 0);
1900642bac7SRichard Leitner 	if (ret < 0) {
1910642bac7SRichard Leitner 		dev_err(priv->dev, "timeout during read setup\n");
1920642bac7SRichard Leitner 		goto read_end;
1930642bac7SRichard Leitner 	}
1940642bac7SRichard Leitner 
1959b66587eSRichard Leitner 	for (i = index; i < (index + count); i++) {
1963311bf18SPeng Fan 		*(u32 *)buf = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 +
1979b66587eSRichard Leitner 			       i * IMX_OCOTP_OFFSET_PER_WORD);
1989b66587eSRichard Leitner 
1999b66587eSRichard Leitner 		/* 47.3.1.2
2009b66587eSRichard Leitner 		 * For "read locked" registers 0xBADABADA will be returned and
2019b66587eSRichard Leitner 		 * HW_OCOTP_CTRL[ERROR] will be set. It must be cleared by
2029b66587eSRichard Leitner 		 * software before any new write, read or reload access can be
2039b66587eSRichard Leitner 		 * issued
2049b66587eSRichard Leitner 		 */
2053311bf18SPeng Fan 		if (*((u32 *)buf) == IMX_OCOTP_READ_LOCKED_VAL)
206226c5126SPeng Fan 			imx_ocotp_clr_err_if_set(priv);
2073311bf18SPeng Fan 
2083311bf18SPeng Fan 		buf += 4;
2099b66587eSRichard Leitner 	}
2103edba6b4SPhilipp Zabel 
2113311bf18SPeng Fan 	index = offset % 4;
2123311bf18SPeng Fan 	memcpy(val, &p[index], bytes);
2133311bf18SPeng Fan 
2140642bac7SRichard Leitner read_end:
215deb31970SPeng Fan 	clk_disable_unprepare(priv->clk);
2160642bac7SRichard Leitner 	mutex_unlock(&ocotp_mutex);
2173311bf18SPeng Fan 
2183311bf18SPeng Fan 	kfree(p);
2193311bf18SPeng Fan 
2200642bac7SRichard Leitner 	return ret;
2210642bac7SRichard Leitner }
2220642bac7SRichard Leitner 
imx_ocotp_cell_pp(void * context,const char * id,int index,unsigned int offset,void * data,size_t bytes)2235d8e6e6cSMichael Walle static int imx_ocotp_cell_pp(void *context, const char *id, int index,
2245d8e6e6cSMichael Walle 			     unsigned int offset, void *data, size_t bytes)
225d0221a78SSrinivas Kandagatla {
226d0221a78SSrinivas Kandagatla 	u8 *buf = data;
227d0221a78SSrinivas Kandagatla 	int i;
228d0221a78SSrinivas Kandagatla 
2296c56a82dSMichael Walle 	/* Deal with some post processing of nvmem cell data */
2306c56a82dSMichael Walle 	if (id && !strcmp(id, "mac-address"))
231d0221a78SSrinivas Kandagatla 		for (i = 0; i < bytes / 2; i++)
232d0221a78SSrinivas Kandagatla 			swap(buf[i], buf[bytes - i - 1]);
233d0221a78SSrinivas Kandagatla 
234d0221a78SSrinivas Kandagatla 	return 0;
235d0221a78SSrinivas Kandagatla }
236d0221a78SSrinivas Kandagatla 
imx_ocotp_set_imx6_timing(struct ocotp_priv * priv)237b50cb68fSBryan O'Donoghue static void imx_ocotp_set_imx6_timing(struct ocotp_priv *priv)
2380642bac7SRichard Leitner {
23913d588baSAnson Huang 	unsigned long clk_rate;
2400642bac7SRichard Leitner 	unsigned long strobe_read, relax, strobe_prog;
24113d588baSAnson Huang 	u32 timing;
2420642bac7SRichard Leitner 
2430642bac7SRichard Leitner 	/* 47.3.1.3.1
2440642bac7SRichard Leitner 	 * Program HW_OCOTP_TIMING[STROBE_PROG] and HW_OCOTP_TIMING[RELAX]
2450642bac7SRichard Leitner 	 * fields with timing values to match the current frequency of the
2460642bac7SRichard Leitner 	 * ipg_clk. OTP writes will work at maximum bus frequencies as long
2470642bac7SRichard Leitner 	 * as the HW_OCOTP_TIMING parameters are set correctly.
248159dbaf5SBryan O'Donoghue 	 *
249159dbaf5SBryan O'Donoghue 	 * Note: there are minimum timings required to ensure an OTP fuse burns
250159dbaf5SBryan O'Donoghue 	 * correctly that are independent of the ipg_clk. Those values are not
251159dbaf5SBryan O'Donoghue 	 * formally documented anywhere however, working from the minimum
252159dbaf5SBryan O'Donoghue 	 * timings given in u-boot we can say:
253159dbaf5SBryan O'Donoghue 	 *
254159dbaf5SBryan O'Donoghue 	 * - Minimum STROBE_PROG time is 10 microseconds. Intuitively 10
255159dbaf5SBryan O'Donoghue 	 *   microseconds feels about right as representative of a minimum time
256159dbaf5SBryan O'Donoghue 	 *   to physically burn out a fuse.
257159dbaf5SBryan O'Donoghue 	 *
258159dbaf5SBryan O'Donoghue 	 * - Minimum STROBE_READ i.e. the time to wait post OTP fuse burn before
259159dbaf5SBryan O'Donoghue 	 *   performing another read is 37 nanoseconds
260159dbaf5SBryan O'Donoghue 	 *
261159dbaf5SBryan O'Donoghue 	 * - Minimum RELAX timing is 17 nanoseconds. This final RELAX minimum
262159dbaf5SBryan O'Donoghue 	 *   timing is not entirely clear the documentation says "This
263159dbaf5SBryan O'Donoghue 	 *   count value specifies the time to add to all default timing
264159dbaf5SBryan O'Donoghue 	 *   parameters other than the Tpgm and Trd. It is given in number
265159dbaf5SBryan O'Donoghue 	 *   of ipg_clk periods." where Tpgm and Trd refer to STROBE_PROG
266159dbaf5SBryan O'Donoghue 	 *   and STROBE_READ respectively. What the other timing parameters
267159dbaf5SBryan O'Donoghue 	 *   are though, is not specified. Experience shows a zero RELAX
268159dbaf5SBryan O'Donoghue 	 *   value will mess up a re-load of the shadow registers post OTP
269159dbaf5SBryan O'Donoghue 	 *   burn.
2700642bac7SRichard Leitner 	 */
2710642bac7SRichard Leitner 	clk_rate = clk_get_rate(priv->clk);
2720642bac7SRichard Leitner 
273159dbaf5SBryan O'Donoghue 	relax = DIV_ROUND_UP(clk_rate * TIMING_RELAX_NS, 1000000000) - 1;
274159dbaf5SBryan O'Donoghue 	strobe_read = DIV_ROUND_UP(clk_rate * TIMING_STROBE_READ_NS,
275159dbaf5SBryan O'Donoghue 				   1000000000);
276159dbaf5SBryan O'Donoghue 	strobe_read += 2 * (relax + 1) - 1;
277159dbaf5SBryan O'Donoghue 	strobe_prog = DIV_ROUND_CLOSEST(clk_rate * TIMING_STROBE_PROG_US,
278159dbaf5SBryan O'Donoghue 					1000000);
279159dbaf5SBryan O'Donoghue 	strobe_prog += 2 * (relax + 1) - 1;
2800642bac7SRichard Leitner 
2810493c479SBryan O'Donoghue 	timing = readl(priv->base + IMX_OCOTP_ADDR_TIMING) & 0x0FC00000;
2820493c479SBryan O'Donoghue 	timing |= strobe_prog & 0x00000FFF;
2830642bac7SRichard Leitner 	timing |= (relax       << 12) & 0x0000F000;
2840642bac7SRichard Leitner 	timing |= (strobe_read << 16) & 0x003F0000;
2850642bac7SRichard Leitner 
2860642bac7SRichard Leitner 	writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING);
287b50cb68fSBryan O'Donoghue }
288b50cb68fSBryan O'Donoghue 
imx_ocotp_set_imx7_timing(struct ocotp_priv * priv)289828ae7a4SBryan O'Donoghue static void imx_ocotp_set_imx7_timing(struct ocotp_priv *priv)
290828ae7a4SBryan O'Donoghue {
29113d588baSAnson Huang 	unsigned long clk_rate;
292828ae7a4SBryan O'Donoghue 	u64 fsource, strobe_prog;
29313d588baSAnson Huang 	u32 timing;
294828ae7a4SBryan O'Donoghue 
295828ae7a4SBryan O'Donoghue 	/* i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1
296828ae7a4SBryan O'Donoghue 	 * 6.4.3.3
297828ae7a4SBryan O'Donoghue 	 */
298828ae7a4SBryan O'Donoghue 	clk_rate = clk_get_rate(priv->clk);
299828ae7a4SBryan O'Donoghue 	fsource = DIV_ROUND_UP_ULL((u64)clk_rate * DEF_FSOURCE,
300828ae7a4SBryan O'Donoghue 				   NSEC_PER_SEC) + 1;
301828ae7a4SBryan O'Donoghue 	strobe_prog = DIV_ROUND_CLOSEST_ULL((u64)clk_rate * DEF_STROBE_PROG,
302828ae7a4SBryan O'Donoghue 					    NSEC_PER_SEC) + 1;
303828ae7a4SBryan O'Donoghue 
304828ae7a4SBryan O'Donoghue 	timing = strobe_prog & 0x00000FFF;
305828ae7a4SBryan O'Donoghue 	timing |= (fsource << 12) & 0x000FF000;
306828ae7a4SBryan O'Donoghue 
307828ae7a4SBryan O'Donoghue 	writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING);
308828ae7a4SBryan O'Donoghue }
309828ae7a4SBryan O'Donoghue 
imx_ocotp_write(void * context,unsigned int offset,void * val,size_t bytes)310b50cb68fSBryan O'Donoghue static int imx_ocotp_write(void *context, unsigned int offset, void *val,
311b50cb68fSBryan O'Donoghue 			   size_t bytes)
312b50cb68fSBryan O'Donoghue {
313b50cb68fSBryan O'Donoghue 	struct ocotp_priv *priv = context;
314b50cb68fSBryan O'Donoghue 	u32 *buf = val;
315b50cb68fSBryan O'Donoghue 	int ret;
316b50cb68fSBryan O'Donoghue 
317b50cb68fSBryan O'Donoghue 	u32 ctrl;
318b50cb68fSBryan O'Donoghue 	u8 waddr;
319b50cb68fSBryan O'Donoghue 	u8 word = 0;
320b50cb68fSBryan O'Donoghue 
321b50cb68fSBryan O'Donoghue 	/* allow only writing one complete OTP word at a time */
322b50cb68fSBryan O'Donoghue 	if ((bytes != priv->config->word_size) ||
323b50cb68fSBryan O'Donoghue 	    (offset % priv->config->word_size))
324b50cb68fSBryan O'Donoghue 		return -EINVAL;
325b50cb68fSBryan O'Donoghue 
326b50cb68fSBryan O'Donoghue 	mutex_lock(&ocotp_mutex);
327b50cb68fSBryan O'Donoghue 
328b50cb68fSBryan O'Donoghue 	ret = clk_prepare_enable(priv->clk);
329b50cb68fSBryan O'Donoghue 	if (ret < 0) {
330b50cb68fSBryan O'Donoghue 		mutex_unlock(&ocotp_mutex);
331b50cb68fSBryan O'Donoghue 		dev_err(priv->dev, "failed to prepare/enable ocotp clk\n");
332b50cb68fSBryan O'Donoghue 		return ret;
333b50cb68fSBryan O'Donoghue 	}
334b50cb68fSBryan O'Donoghue 
335b50cb68fSBryan O'Donoghue 	/* Setup the write timing values */
336828ae7a4SBryan O'Donoghue 	priv->params->set_timing(priv);
3370642bac7SRichard Leitner 
3380642bac7SRichard Leitner 	/* 47.3.1.3.2
3390642bac7SRichard Leitner 	 * Check that HW_OCOTP_CTRL[BUSY] and HW_OCOTP_CTRL[ERROR] are clear.
3400642bac7SRichard Leitner 	 * Overlapped accesses are not supported by the controller. Any pending
3410642bac7SRichard Leitner 	 * write or reload must be completed before a write access can be
3420642bac7SRichard Leitner 	 * requested.
3430642bac7SRichard Leitner 	 */
344226c5126SPeng Fan 	ret = imx_ocotp_wait_for_busy(priv, 0);
3450642bac7SRichard Leitner 	if (ret < 0) {
3460642bac7SRichard Leitner 		dev_err(priv->dev, "timeout during timing setup\n");
3470642bac7SRichard Leitner 		goto write_end;
3480642bac7SRichard Leitner 	}
3490642bac7SRichard Leitner 
3500642bac7SRichard Leitner 	/* 47.3.1.3.3
3510642bac7SRichard Leitner 	 * Write the requested address to HW_OCOTP_CTRL[ADDR] and program the
3520642bac7SRichard Leitner 	 * unlock code into HW_OCOTP_CTRL[WR_UNLOCK]. This must be programmed
3530642bac7SRichard Leitner 	 * for each write access. The lock code is documented in the register
3540642bac7SRichard Leitner 	 * description. Both the unlock code and address can be written in the
3550642bac7SRichard Leitner 	 * same operation.
3560642bac7SRichard Leitner 	 */
357ffd9115fSBryan O'Donoghue 	if (priv->params->bank_address_words != 0) {
358ffd9115fSBryan O'Donoghue 		/*
359ffd9115fSBryan O'Donoghue 		 * In banked/i.MX7 mode the OTP register bank goes into waddr
360ffd9115fSBryan O'Donoghue 		 * see i.MX 7Solo Applications Processor Reference Manual, Rev.
361ffd9115fSBryan O'Donoghue 		 * 0.1 section 6.4.3.1
362ffd9115fSBryan O'Donoghue 		 */
363ffd9115fSBryan O'Donoghue 		offset = offset / priv->config->word_size;
364ffd9115fSBryan O'Donoghue 		waddr = offset / priv->params->bank_address_words;
365ffd9115fSBryan O'Donoghue 		word  = offset & (priv->params->bank_address_words - 1);
366ffd9115fSBryan O'Donoghue 	} else {
367ffd9115fSBryan O'Donoghue 		/*
368ffd9115fSBryan O'Donoghue 		 * Non-banked i.MX6 mode.
369ffd9115fSBryan O'Donoghue 		 * OTP write/read address specifies one of 128 word address
370ffd9115fSBryan O'Donoghue 		 * locations
371ffd9115fSBryan O'Donoghue 		 */
3720642bac7SRichard Leitner 		waddr = offset / 4;
373ffd9115fSBryan O'Donoghue 	}
3740642bac7SRichard Leitner 
3750642bac7SRichard Leitner 	ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL);
376226c5126SPeng Fan 	ctrl &= ~priv->params->ctrl.bm_addr;
377226c5126SPeng Fan 	ctrl |= waddr & priv->params->ctrl.bm_addr;
3780642bac7SRichard Leitner 	ctrl |= IMX_OCOTP_WR_UNLOCK;
3790642bac7SRichard Leitner 
3800642bac7SRichard Leitner 	writel(ctrl, priv->base + IMX_OCOTP_ADDR_CTRL);
3810642bac7SRichard Leitner 
3820642bac7SRichard Leitner 	/* 47.3.1.3.4
3830642bac7SRichard Leitner 	 * Write the data to the HW_OCOTP_DATA register. This will automatically
3840642bac7SRichard Leitner 	 * set HW_OCOTP_CTRL[BUSY] and clear HW_OCOTP_CTRL[WR_UNLOCK]. To
3850642bac7SRichard Leitner 	 * protect programming same OTP bit twice, before program OCOTP will
3860642bac7SRichard Leitner 	 * automatically read fuse value in OTP and use read value to mask
3870642bac7SRichard Leitner 	 * program data. The controller will use masked program data to program
3880642bac7SRichard Leitner 	 * a 32-bit word in the OTP per the address in HW_OCOTP_CTRL[ADDR]. Bit
3890642bac7SRichard Leitner 	 * fields with 1's will result in that OTP bit being programmed. Bit
3900642bac7SRichard Leitner 	 * fields with 0's will be ignored. At the same time that the write is
3910642bac7SRichard Leitner 	 * accepted, the controller makes an internal copy of
3920642bac7SRichard Leitner 	 * HW_OCOTP_CTRL[ADDR] which cannot be updated until the next write
3930642bac7SRichard Leitner 	 * sequence is initiated. This copy guarantees that erroneous writes to
3940642bac7SRichard Leitner 	 * HW_OCOTP_CTRL[ADDR] will not affect an active write operation. It
3950642bac7SRichard Leitner 	 * should also be noted that during the programming HW_OCOTP_DATA will
3960642bac7SRichard Leitner 	 * shift right (with zero fill). This shifting is required to program
3970642bac7SRichard Leitner 	 * the OTP serially. During the write operation, HW_OCOTP_DATA cannot be
3980642bac7SRichard Leitner 	 * modified.
399ffd9115fSBryan O'Donoghue 	 * Note: on i.MX7 there are four data fields to write for banked write
400ffd9115fSBryan O'Donoghue 	 *       with the fuse blowing operation only taking place after data0
401ffd9115fSBryan O'Donoghue 	 *	 has been written. This is why data0 must always be the last
402ffd9115fSBryan O'Donoghue 	 *	 register written.
4030642bac7SRichard Leitner 	 */
404ffd9115fSBryan O'Donoghue 	if (priv->params->bank_address_words != 0) {
405ffd9115fSBryan O'Donoghue 		/* Banked/i.MX7 mode */
406ffd9115fSBryan O'Donoghue 		switch (word) {
407ffd9115fSBryan O'Donoghue 		case 0:
408ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA1);
409ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA2);
410ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA3);
411ffd9115fSBryan O'Donoghue 			writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0);
412ffd9115fSBryan O'Donoghue 			break;
413ffd9115fSBryan O'Donoghue 		case 1:
414ffd9115fSBryan O'Donoghue 			writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA1);
415ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA2);
416ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA3);
417ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA0);
418ffd9115fSBryan O'Donoghue 			break;
419ffd9115fSBryan O'Donoghue 		case 2:
420ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA1);
421ffd9115fSBryan O'Donoghue 			writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA2);
422ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA3);
423ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA0);
424ffd9115fSBryan O'Donoghue 			break;
425ffd9115fSBryan O'Donoghue 		case 3:
426ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA1);
427ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA2);
428ffd9115fSBryan O'Donoghue 			writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA3);
429ffd9115fSBryan O'Donoghue 			writel(0, priv->base + IMX_OCOTP_ADDR_DATA0);
430ffd9115fSBryan O'Donoghue 			break;
431ffd9115fSBryan O'Donoghue 		}
432ffd9115fSBryan O'Donoghue 	} else {
433ffd9115fSBryan O'Donoghue 		/* Non-banked i.MX6 mode */
434ffd9115fSBryan O'Donoghue 		writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0);
435ffd9115fSBryan O'Donoghue 	}
4360642bac7SRichard Leitner 
4370642bac7SRichard Leitner 	/* 47.4.1.4.5
4380642bac7SRichard Leitner 	 * Once complete, the controller will clear BUSY. A write request to a
4390642bac7SRichard Leitner 	 * protected or locked region will result in no OTP access and no
4400642bac7SRichard Leitner 	 * setting of HW_OCOTP_CTRL[BUSY]. In addition HW_OCOTP_CTRL[ERROR] will
4410642bac7SRichard Leitner 	 * be set. It must be cleared by software before any new write access
4420642bac7SRichard Leitner 	 * can be issued.
4430642bac7SRichard Leitner 	 */
444226c5126SPeng Fan 	ret = imx_ocotp_wait_for_busy(priv, 0);
4450642bac7SRichard Leitner 	if (ret < 0) {
4460642bac7SRichard Leitner 		if (ret == -EPERM) {
4470642bac7SRichard Leitner 			dev_err(priv->dev, "failed write to locked region");
448226c5126SPeng Fan 			imx_ocotp_clr_err_if_set(priv);
4490642bac7SRichard Leitner 		} else {
4500642bac7SRichard Leitner 			dev_err(priv->dev, "timeout during data write\n");
4510642bac7SRichard Leitner 		}
4520642bac7SRichard Leitner 		goto write_end;
4530642bac7SRichard Leitner 	}
4540642bac7SRichard Leitner 
4550642bac7SRichard Leitner 	/* 47.3.1.4
4560642bac7SRichard Leitner 	 * Write Postamble: Due to internal electrical characteristics of the
4570642bac7SRichard Leitner 	 * OTP during writes, all OTP operations following a write must be
4580642bac7SRichard Leitner 	 * separated by 2 us after the clearing of HW_OCOTP_CTRL_BUSY following
4590642bac7SRichard Leitner 	 * the write.
4600642bac7SRichard Leitner 	 */
4610642bac7SRichard Leitner 	udelay(2);
4620642bac7SRichard Leitner 
4630642bac7SRichard Leitner 	/* reload all shadow registers */
464226c5126SPeng Fan 	writel(priv->params->ctrl.bm_rel_shadows,
4650642bac7SRichard Leitner 	       priv->base + IMX_OCOTP_ADDR_CTRL_SET);
466226c5126SPeng Fan 	ret = imx_ocotp_wait_for_busy(priv,
467226c5126SPeng Fan 				      priv->params->ctrl.bm_rel_shadows);
4680e2abffdSAnson Huang 	if (ret < 0)
4690642bac7SRichard Leitner 		dev_err(priv->dev, "timeout during shadow register reload\n");
4700642bac7SRichard Leitner 
4710642bac7SRichard Leitner write_end:
4720642bac7SRichard Leitner 	clk_disable_unprepare(priv->clk);
4730642bac7SRichard Leitner 	mutex_unlock(&ocotp_mutex);
4740e2abffdSAnson Huang 	return ret < 0 ? ret : bytes;
4753edba6b4SPhilipp Zabel }
4763edba6b4SPhilipp Zabel 
4773edba6b4SPhilipp Zabel static struct nvmem_config imx_ocotp_nvmem_config = {
4783edba6b4SPhilipp Zabel 	.name = "imx-ocotp",
4790642bac7SRichard Leitner 	.read_only = false,
48033e5e29cSSrinivas Kandagatla 	.word_size = 4,
4813311bf18SPeng Fan 	.stride = 1,
48233e5e29cSSrinivas Kandagatla 	.reg_read = imx_ocotp_read,
4830642bac7SRichard Leitner 	.reg_write = imx_ocotp_write,
4843edba6b4SPhilipp Zabel };
4853edba6b4SPhilipp Zabel 
486e20d2b29SBryan O'Donoghue static const struct ocotp_params imx6q_params = {
487e20d2b29SBryan O'Donoghue 	.nregs = 128,
488ffd9115fSBryan O'Donoghue 	.bank_address_words = 0,
489828ae7a4SBryan O'Donoghue 	.set_timing = imx_ocotp_set_imx6_timing,
490226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
491e20d2b29SBryan O'Donoghue };
492e20d2b29SBryan O'Donoghue 
493e20d2b29SBryan O'Donoghue static const struct ocotp_params imx6sl_params = {
494e20d2b29SBryan O'Donoghue 	.nregs = 64,
495ffd9115fSBryan O'Donoghue 	.bank_address_words = 0,
496828ae7a4SBryan O'Donoghue 	.set_timing = imx_ocotp_set_imx6_timing,
497226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
498e20d2b29SBryan O'Donoghue };
499e20d2b29SBryan O'Donoghue 
5006da27821SAnson Huang static const struct ocotp_params imx6sll_params = {
501414a98abSPeng Fan 	.nregs = 80,
5026da27821SAnson Huang 	.bank_address_words = 0,
5036da27821SAnson Huang 	.set_timing = imx_ocotp_set_imx6_timing,
504226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
5056da27821SAnson Huang };
5066da27821SAnson Huang 
507e20d2b29SBryan O'Donoghue static const struct ocotp_params imx6sx_params = {
508e20d2b29SBryan O'Donoghue 	.nregs = 128,
509ffd9115fSBryan O'Donoghue 	.bank_address_words = 0,
510828ae7a4SBryan O'Donoghue 	.set_timing = imx_ocotp_set_imx6_timing,
511226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
512e20d2b29SBryan O'Donoghue };
513e20d2b29SBryan O'Donoghue 
514e20d2b29SBryan O'Donoghue static const struct ocotp_params imx6ul_params = {
5157d6e10f5SPeng Fan 	.nregs = 144,
516ffd9115fSBryan O'Donoghue 	.bank_address_words = 0,
517828ae7a4SBryan O'Donoghue 	.set_timing = imx_ocotp_set_imx6_timing,
518226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
519e20d2b29SBryan O'Donoghue };
520e20d2b29SBryan O'Donoghue 
521ffbc34bfSStefan Wahren static const struct ocotp_params imx6ull_params = {
5222382c1b0SPeng Fan 	.nregs = 80,
523ffbc34bfSStefan Wahren 	.bank_address_words = 0,
524ffbc34bfSStefan Wahren 	.set_timing = imx_ocotp_set_imx6_timing,
525226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
526ffbc34bfSStefan Wahren };
527ffbc34bfSStefan Wahren 
528e20d2b29SBryan O'Donoghue static const struct ocotp_params imx7d_params = {
529e20d2b29SBryan O'Donoghue 	.nregs = 64,
530ffd9115fSBryan O'Donoghue 	.bank_address_words = 4,
531828ae7a4SBryan O'Donoghue 	.set_timing = imx_ocotp_set_imx7_timing,
532226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
533e20d2b29SBryan O'Donoghue };
534e20d2b29SBryan O'Donoghue 
535c8b63ddcSAnson Huang static const struct ocotp_params imx7ulp_params = {
536c8b63ddcSAnson Huang 	.nregs = 256,
537c8b63ddcSAnson Huang 	.bank_address_words = 0,
538226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
539c8b63ddcSAnson Huang };
540c8b63ddcSAnson Huang 
54138e7b6efSLucas Stach static const struct ocotp_params imx8mq_params = {
54238e7b6efSLucas Stach 	.nregs = 256,
5435a1c1724SLeonard Crestez 	.bank_address_words = 0,
5445a1c1724SLeonard Crestez 	.set_timing = imx_ocotp_set_imx6_timing,
545226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
54638e7b6efSLucas Stach };
54738e7b6efSLucas Stach 
5484112c853SBryan O'Donoghue static const struct ocotp_params imx8mm_params = {
5494112c853SBryan O'Donoghue 	.nregs = 256,
5504112c853SBryan O'Donoghue 	.bank_address_words = 0,
5514112c853SBryan O'Donoghue 	.set_timing = imx_ocotp_set_imx6_timing,
552226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
5534112c853SBryan O'Donoghue };
5544112c853SBryan O'Donoghue 
555d93b5d4aSAnson Huang static const struct ocotp_params imx8mn_params = {
556d93b5d4aSAnson Huang 	.nregs = 256,
557d93b5d4aSAnson Huang 	.bank_address_words = 0,
558d93b5d4aSAnson Huang 	.set_timing = imx_ocotp_set_imx6_timing,
559226c5126SPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
560d93b5d4aSAnson Huang };
561d93b5d4aSAnson Huang 
562c3f4af8bSPeng Fan static const struct ocotp_params imx8mp_params = {
563c3f4af8bSPeng Fan 	.nregs = 384,
564c3f4af8bSPeng Fan 	.bank_address_words = 0,
565c3f4af8bSPeng Fan 	.set_timing = imx_ocotp_set_imx6_timing,
566c3f4af8bSPeng Fan 	.ctrl = IMX_OCOTP_BM_CTRL_8MP,
567c3f4af8bSPeng Fan };
568c3f4af8bSPeng Fan 
5693edba6b4SPhilipp Zabel static const struct of_device_id imx_ocotp_dt_ids[] = {
570e20d2b29SBryan O'Donoghue 	{ .compatible = "fsl,imx6q-ocotp",  .data = &imx6q_params },
571e20d2b29SBryan O'Donoghue 	{ .compatible = "fsl,imx6sl-ocotp", .data = &imx6sl_params },
572e20d2b29SBryan O'Donoghue 	{ .compatible = "fsl,imx6sx-ocotp", .data = &imx6sx_params },
573e20d2b29SBryan O'Donoghue 	{ .compatible = "fsl,imx6ul-ocotp", .data = &imx6ul_params },
574ffbc34bfSStefan Wahren 	{ .compatible = "fsl,imx6ull-ocotp", .data = &imx6ull_params },
575e20d2b29SBryan O'Donoghue 	{ .compatible = "fsl,imx7d-ocotp",  .data = &imx7d_params },
5766da27821SAnson Huang 	{ .compatible = "fsl,imx6sll-ocotp", .data = &imx6sll_params },
577c8b63ddcSAnson Huang 	{ .compatible = "fsl,imx7ulp-ocotp", .data = &imx7ulp_params },
57838e7b6efSLucas Stach 	{ .compatible = "fsl,imx8mq-ocotp", .data = &imx8mq_params },
5794112c853SBryan O'Donoghue 	{ .compatible = "fsl,imx8mm-ocotp", .data = &imx8mm_params },
580d93b5d4aSAnson Huang 	{ .compatible = "fsl,imx8mn-ocotp", .data = &imx8mn_params },
581c3f4af8bSPeng Fan 	{ .compatible = "fsl,imx8mp-ocotp", .data = &imx8mp_params },
5823edba6b4SPhilipp Zabel 	{ },
5833edba6b4SPhilipp Zabel };
5843edba6b4SPhilipp Zabel MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
5853edba6b4SPhilipp Zabel 
imx_ocotp_fixup_dt_cell_info(struct nvmem_device * nvmem,struct nvmem_cell_info * cell)586*1172460eSMiquel Raynal static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem,
5876c56a82dSMichael Walle 					 struct nvmem_cell_info *cell)
5886c56a82dSMichael Walle {
5896c56a82dSMichael Walle 	cell->read_post_process = imx_ocotp_cell_pp;
5906c56a82dSMichael Walle }
5916c56a82dSMichael Walle 
imx_ocotp_probe(struct platform_device * pdev)5923edba6b4SPhilipp Zabel static int imx_ocotp_probe(struct platform_device *pdev)
5933edba6b4SPhilipp Zabel {
5943edba6b4SPhilipp Zabel 	struct device *dev = &pdev->dev;
5953edba6b4SPhilipp Zabel 	struct ocotp_priv *priv;
5963edba6b4SPhilipp Zabel 	struct nvmem_device *nvmem;
5973edba6b4SPhilipp Zabel 
5983edba6b4SPhilipp Zabel 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
5993edba6b4SPhilipp Zabel 	if (!priv)
6003edba6b4SPhilipp Zabel 		return -ENOMEM;
6013edba6b4SPhilipp Zabel 
6024cefb74aSRichard Leitner 	priv->dev = dev;
6034cefb74aSRichard Leitner 
6043b26cd88SAnson Huang 	priv->base = devm_platform_ioremap_resource(pdev, 0);
6053edba6b4SPhilipp Zabel 	if (IS_ERR(priv->base))
6063edba6b4SPhilipp Zabel 		return PTR_ERR(priv->base);
6073edba6b4SPhilipp Zabel 
6084cefb74aSRichard Leitner 	priv->clk = devm_clk_get(dev, NULL);
609deb31970SPeng Fan 	if (IS_ERR(priv->clk))
610deb31970SPeng Fan 		return PTR_ERR(priv->clk);
611deb31970SPeng Fan 
612e20d2b29SBryan O'Donoghue 	priv->params = of_device_get_match_data(&pdev->dev);
6132cc3b37fSRafał Miłecki 	imx_ocotp_nvmem_config.add_legacy_fixed_of_cells = true;
614e20d2b29SBryan O'Donoghue 	imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
6153edba6b4SPhilipp Zabel 	imx_ocotp_nvmem_config.dev = dev;
61633e5e29cSSrinivas Kandagatla 	imx_ocotp_nvmem_config.priv = priv;
617*1172460eSMiquel Raynal 	imx_ocotp_nvmem_config.fixup_dt_cell_info = &imx_ocotp_fixup_dt_cell_info;
6186c56a82dSMichael Walle 
6190642bac7SRichard Leitner 	priv->config = &imx_ocotp_nvmem_config;
6200642bac7SRichard Leitner 
621226c5126SPeng Fan 	clk_prepare_enable(priv->clk);
622226c5126SPeng Fan 	imx_ocotp_clr_err_if_set(priv);
623226c5126SPeng Fan 	clk_disable_unprepare(priv->clk);
624226c5126SPeng Fan 
625226c5126SPeng Fan 	nvmem = devm_nvmem_register(dev, &imx_ocotp_nvmem_config);
6263edba6b4SPhilipp Zabel 
627a830274fSAndrey Smirnov 	return PTR_ERR_OR_ZERO(nvmem);
6283edba6b4SPhilipp Zabel }
6293edba6b4SPhilipp Zabel 
6303edba6b4SPhilipp Zabel static struct platform_driver imx_ocotp_driver = {
6313edba6b4SPhilipp Zabel 	.probe	= imx_ocotp_probe,
6323edba6b4SPhilipp Zabel 	.driver = {
6333edba6b4SPhilipp Zabel 		.name	= "imx_ocotp",
6343edba6b4SPhilipp Zabel 		.of_match_table = imx_ocotp_dt_ids,
6353edba6b4SPhilipp Zabel 	},
6363edba6b4SPhilipp Zabel };
6373edba6b4SPhilipp Zabel module_platform_driver(imx_ocotp_driver);
6383edba6b4SPhilipp Zabel 
6393edba6b4SPhilipp Zabel MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
640aef9a4deSBryan O'Donoghue MODULE_DESCRIPTION("i.MX6/i.MX7 OCOTP fuse box driver");
6413edba6b4SPhilipp Zabel MODULE_LICENSE("GPL v2");
642