Lines Matching +full:imx6sx +full:- +full:ocotp

1 // SPDX-License-Identifier: GPL-2.0-only
3 * i.MX6 OCOTP fusebox driver
9 * Based on the barebox ocotp driver,
14 * Copyright (C) 2010-2013 Freescale Semiconductor, Inc
21 #include <linux/nvmem-provider.h>
107 void __iomem *base = priv->base; in imx_ocotp_wait_for_busy()
109 bm_ctrl_busy = priv->params->ctrl.bm_busy; in imx_ocotp_wait_for_busy()
110 bm_ctrl_error = priv->params->ctrl.bm_error; in imx_ocotp_wait_for_busy()
114 for (count = 10000; count >= 0; count--) { in imx_ocotp_wait_for_busy()
124 * - A write is performed to a shadow register during a shadow in imx_ocotp_wait_for_busy()
128 * - A write is performed to a shadow register which has been in imx_ocotp_wait_for_busy()
130 * - A read is performed to from a shadow register which has in imx_ocotp_wait_for_busy()
132 * - A program is performed to a fuse word which has been locked in imx_ocotp_wait_for_busy()
133 * - A read is performed to from a fuse word which has been read in imx_ocotp_wait_for_busy()
137 return -EPERM; in imx_ocotp_wait_for_busy()
138 return -ETIMEDOUT; in imx_ocotp_wait_for_busy()
147 void __iomem *base = priv->base; in imx_ocotp_clr_err_if_set()
149 bm_ctrl_error = priv->params->ctrl.bm_error; in imx_ocotp_clr_err_if_set()
171 if (count > (priv->params->nregs - index)) in imx_ocotp_read()
172 count = priv->params->nregs - index; in imx_ocotp_read()
176 return -ENOMEM; in imx_ocotp_read()
182 ret = clk_prepare_enable(priv->clk); in imx_ocotp_read()
185 dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); in imx_ocotp_read()
192 dev_err(priv->dev, "timeout during read setup\n"); in imx_ocotp_read()
197 *(u32 *)buf = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 + in imx_ocotp_read()
216 clk_disable_unprepare(priv->clk); in imx_ocotp_read()
239 * timings given in u-boot we can say: in imx_ocotp_set_imx6_timing()
241 * - Minimum STROBE_PROG time is 10 microseconds. Intuitively 10 in imx_ocotp_set_imx6_timing()
245 * - Minimum STROBE_READ i.e. the time to wait post OTP fuse burn before in imx_ocotp_set_imx6_timing()
248 * - Minimum RELAX timing is 17 nanoseconds. This final RELAX minimum in imx_ocotp_set_imx6_timing()
255 * value will mess up a re-load of the shadow registers post OTP in imx_ocotp_set_imx6_timing()
258 clk_rate = clk_get_rate(priv->clk); in imx_ocotp_set_imx6_timing()
260 relax = DIV_ROUND_UP(clk_rate * TIMING_RELAX_NS, 1000000000) - 1; in imx_ocotp_set_imx6_timing()
263 strobe_read += 2 * (relax + 1) - 1; in imx_ocotp_set_imx6_timing()
266 strobe_prog += 2 * (relax + 1) - 1; in imx_ocotp_set_imx6_timing()
268 timing = readl(priv->base + IMX_OCOTP_ADDR_TIMING) & 0x0FC00000; in imx_ocotp_set_imx6_timing()
273 writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); in imx_ocotp_set_imx6_timing()
285 clk_rate = clk_get_rate(priv->clk); in imx_ocotp_set_imx7_timing()
294 writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); in imx_ocotp_set_imx7_timing()
309 if ((bytes != priv->config->word_size) || in imx_ocotp_write()
310 (offset % priv->config->word_size)) in imx_ocotp_write()
311 return -EINVAL; in imx_ocotp_write()
315 ret = clk_prepare_enable(priv->clk); in imx_ocotp_write()
318 dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); in imx_ocotp_write()
323 priv->params->set_timing(priv); in imx_ocotp_write()
333 dev_err(priv->dev, "timeout during timing setup\n"); in imx_ocotp_write()
344 if (priv->params->bank_address_words != 0) { in imx_ocotp_write()
350 offset = offset / priv->config->word_size; in imx_ocotp_write()
351 waddr = offset / priv->params->bank_address_words; in imx_ocotp_write()
352 word = offset & (priv->params->bank_address_words - 1); in imx_ocotp_write()
355 * Non-banked i.MX6 mode. in imx_ocotp_write()
362 ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL); in imx_ocotp_write()
363 ctrl &= ~priv->params->ctrl.bm_addr; in imx_ocotp_write()
364 ctrl |= waddr & priv->params->ctrl.bm_addr; in imx_ocotp_write()
367 writel(ctrl, priv->base + IMX_OCOTP_ADDR_CTRL); in imx_ocotp_write()
372 * protect programming same OTP bit twice, before program OCOTP will in imx_ocotp_write()
375 * a 32-bit word in the OTP per the address in HW_OCOTP_CTRL[ADDR]. Bit in imx_ocotp_write()
391 if (priv->params->bank_address_words != 0) { in imx_ocotp_write()
395 writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
396 writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
397 writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
398 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
401 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
402 writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
403 writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
404 writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
407 writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
408 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
409 writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
410 writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
413 writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
414 writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
415 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
416 writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
420 /* Non-banked i.MX6 mode */ in imx_ocotp_write()
421 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
433 if (ret == -EPERM) { in imx_ocotp_write()
434 dev_err(priv->dev, "failed write to locked region"); in imx_ocotp_write()
437 dev_err(priv->dev, "timeout during data write\n"); in imx_ocotp_write()
451 writel(priv->params->ctrl.bm_rel_shadows, in imx_ocotp_write()
452 priv->base + IMX_OCOTP_ADDR_CTRL_SET); in imx_ocotp_write()
454 priv->params->ctrl.bm_rel_shadows); in imx_ocotp_write()
456 dev_err(priv->dev, "timeout during shadow register reload\n"); in imx_ocotp_write()
459 clk_disable_unprepare(priv->clk); in imx_ocotp_write()
465 .name = "imx-ocotp",
557 { .compatible = "fsl,imx6q-ocotp", .data = &imx6q_params },
558 { .compatible = "fsl,imx6sl-ocotp", .data = &imx6sl_params },
559 { .compatible = "fsl,imx6sx-ocotp", .data = &imx6sx_params },
560 { .compatible = "fsl,imx6ul-ocotp", .data = &imx6ul_params },
561 { .compatible = "fsl,imx6ull-ocotp", .data = &imx6ull_params },
562 { .compatible = "fsl,imx7d-ocotp", .data = &imx7d_params },
563 { .compatible = "fsl,imx6sll-ocotp", .data = &imx6sll_params },
564 { .compatible = "fsl,imx7ulp-ocotp", .data = &imx7ulp_params },
565 { .compatible = "fsl,imx8mq-ocotp", .data = &imx8mq_params },
566 { .compatible = "fsl,imx8mm-ocotp", .data = &imx8mm_params },
567 { .compatible = "fsl,imx8mn-ocotp", .data = &imx8mn_params },
568 { .compatible = "fsl,imx8mp-ocotp", .data = &imx8mp_params },
575 struct device *dev = &pdev->dev; in imx_ocotp_probe()
581 return -ENOMEM; in imx_ocotp_probe()
583 priv->dev = dev; in imx_ocotp_probe()
585 priv->base = devm_platform_ioremap_resource(pdev, 0); in imx_ocotp_probe()
586 if (IS_ERR(priv->base)) in imx_ocotp_probe()
587 return PTR_ERR(priv->base); in imx_ocotp_probe()
589 priv->clk = devm_clk_get(dev, NULL); in imx_ocotp_probe()
590 if (IS_ERR(priv->clk)) in imx_ocotp_probe()
591 return PTR_ERR(priv->clk); in imx_ocotp_probe()
593 priv->params = of_device_get_match_data(&pdev->dev); in imx_ocotp_probe()
594 imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; in imx_ocotp_probe()
597 priv->config = &imx_ocotp_nvmem_config; in imx_ocotp_probe()
599 clk_prepare_enable(priv->clk); in imx_ocotp_probe()
601 clk_disable_unprepare(priv->clk); in imx_ocotp_probe()
618 MODULE_DESCRIPTION("i.MX6/i.MX7 OCOTP fuse box driver");