Lines Matching +full:e +full:- +full:fuse

1 // SPDX-License-Identifier: GPL-2.0-only
14 * Copyright (C) 2010-2013 Freescale Semiconductor, Inc
21 #include <linux/nvmem-provider.h>
69 #define TIMING_STROBE_PROG_US 10 /* Min time to blow a fuse */
106 void __iomem *base = priv->base; in imx_ocotp_wait_for_busy()
108 bm_ctrl_busy = priv->params->ctrl.bm_busy; in imx_ocotp_wait_for_busy()
109 bm_ctrl_error = priv->params->ctrl.bm_error; in imx_ocotp_wait_for_busy()
113 for (count = 10000; count >= 0; count--) { in imx_ocotp_wait_for_busy()
123 * - A write is performed to a shadow register during a shadow in imx_ocotp_wait_for_busy()
127 * - A write is performed to a shadow register which has been in imx_ocotp_wait_for_busy()
129 * - A read is performed to from a shadow register which has in imx_ocotp_wait_for_busy()
131 * - A program is performed to a fuse word which has been locked in imx_ocotp_wait_for_busy()
132 * - A read is performed to from a fuse word which has been read in imx_ocotp_wait_for_busy()
136 return -EPERM; in imx_ocotp_wait_for_busy()
137 return -ETIMEDOUT; in imx_ocotp_wait_for_busy()
146 void __iomem *base = priv->base; in imx_ocotp_clr_err_if_set()
148 bm_ctrl_error = priv->params->ctrl.bm_error; in imx_ocotp_clr_err_if_set()
170 if (count > (priv->params->nregs - index)) in imx_ocotp_read()
171 count = priv->params->nregs - index; in imx_ocotp_read()
175 return -ENOMEM; in imx_ocotp_read()
181 ret = clk_prepare_enable(priv->clk); in imx_ocotp_read()
184 dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); in imx_ocotp_read()
191 dev_err(priv->dev, "timeout during read setup\n"); in imx_ocotp_read()
196 *(u32 *)buf = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 + in imx_ocotp_read()
215 clk_disable_unprepare(priv->clk); in imx_ocotp_read()
230 if (id && !strcmp(id, "mac-address")) in imx_ocotp_cell_pp()
232 swap(buf[i], buf[bytes - i - 1]); in imx_ocotp_cell_pp()
249 * Note: there are minimum timings required to ensure an OTP fuse burns in imx_ocotp_set_imx6_timing()
252 * timings given in u-boot we can say: in imx_ocotp_set_imx6_timing()
254 * - Minimum STROBE_PROG time is 10 microseconds. Intuitively 10 in imx_ocotp_set_imx6_timing()
256 * to physically burn out a fuse. in imx_ocotp_set_imx6_timing()
258 * - Minimum STROBE_READ i.e. the time to wait post OTP fuse burn before in imx_ocotp_set_imx6_timing()
261 * - Minimum RELAX timing is 17 nanoseconds. This final RELAX minimum in imx_ocotp_set_imx6_timing()
268 * value will mess up a re-load of the shadow registers post OTP in imx_ocotp_set_imx6_timing()
271 clk_rate = clk_get_rate(priv->clk); in imx_ocotp_set_imx6_timing()
273 relax = DIV_ROUND_UP(clk_rate * TIMING_RELAX_NS, 1000000000) - 1; in imx_ocotp_set_imx6_timing()
276 strobe_read += 2 * (relax + 1) - 1; in imx_ocotp_set_imx6_timing()
279 strobe_prog += 2 * (relax + 1) - 1; in imx_ocotp_set_imx6_timing()
281 timing = readl(priv->base + IMX_OCOTP_ADDR_TIMING) & 0x0FC00000; in imx_ocotp_set_imx6_timing()
286 writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); in imx_ocotp_set_imx6_timing()
298 clk_rate = clk_get_rate(priv->clk); in imx_ocotp_set_imx7_timing()
307 writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); in imx_ocotp_set_imx7_timing()
322 if ((bytes != priv->config->word_size) || in imx_ocotp_write()
323 (offset % priv->config->word_size)) in imx_ocotp_write()
324 return -EINVAL; in imx_ocotp_write()
328 ret = clk_prepare_enable(priv->clk); in imx_ocotp_write()
331 dev_err(priv->dev, "failed to prepare/enable ocotp clk\n"); in imx_ocotp_write()
336 priv->params->set_timing(priv); in imx_ocotp_write()
346 dev_err(priv->dev, "timeout during timing setup\n"); in imx_ocotp_write()
357 if (priv->params->bank_address_words != 0) { in imx_ocotp_write()
363 offset = offset / priv->config->word_size; in imx_ocotp_write()
364 waddr = offset / priv->params->bank_address_words; in imx_ocotp_write()
365 word = offset & (priv->params->bank_address_words - 1); in imx_ocotp_write()
368 * Non-banked i.MX6 mode. in imx_ocotp_write()
375 ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL); in imx_ocotp_write()
376 ctrl &= ~priv->params->ctrl.bm_addr; in imx_ocotp_write()
377 ctrl |= waddr & priv->params->ctrl.bm_addr; in imx_ocotp_write()
380 writel(ctrl, priv->base + IMX_OCOTP_ADDR_CTRL); in imx_ocotp_write()
386 * automatically read fuse value in OTP and use read value to mask in imx_ocotp_write()
388 * a 32-bit word in the OTP per the address in HW_OCOTP_CTRL[ADDR]. Bit in imx_ocotp_write()
400 * with the fuse blowing operation only taking place after data0 in imx_ocotp_write()
404 if (priv->params->bank_address_words != 0) { in imx_ocotp_write()
408 writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
409 writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
410 writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
411 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
414 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
415 writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
416 writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
417 writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
420 writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
421 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
422 writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
423 writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
426 writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); in imx_ocotp_write()
427 writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); in imx_ocotp_write()
428 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA3); in imx_ocotp_write()
429 writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
433 /* Non-banked i.MX6 mode */ in imx_ocotp_write()
434 writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0); in imx_ocotp_write()
446 if (ret == -EPERM) { in imx_ocotp_write()
447 dev_err(priv->dev, "failed write to locked region"); in imx_ocotp_write()
450 dev_err(priv->dev, "timeout during data write\n"); in imx_ocotp_write()
464 writel(priv->params->ctrl.bm_rel_shadows, in imx_ocotp_write()
465 priv->base + IMX_OCOTP_ADDR_CTRL_SET); in imx_ocotp_write()
467 priv->params->ctrl.bm_rel_shadows); in imx_ocotp_write()
469 dev_err(priv->dev, "timeout during shadow register reload\n"); in imx_ocotp_write()
472 clk_disable_unprepare(priv->clk); in imx_ocotp_write()
478 .name = "imx-ocotp",
570 { .compatible = "fsl,imx6q-ocotp", .data = &imx6q_params },
571 { .compatible = "fsl,imx6sl-ocotp", .data = &imx6sl_params },
572 { .compatible = "fsl,imx6sx-ocotp", .data = &imx6sx_params },
573 { .compatible = "fsl,imx6ul-ocotp", .data = &imx6ul_params },
574 { .compatible = "fsl,imx6ull-ocotp", .data = &imx6ull_params },
575 { .compatible = "fsl,imx7d-ocotp", .data = &imx7d_params },
576 { .compatible = "fsl,imx6sll-ocotp", .data = &imx6sll_params },
577 { .compatible = "fsl,imx7ulp-ocotp", .data = &imx7ulp_params },
578 { .compatible = "fsl,imx8mq-ocotp", .data = &imx8mq_params },
579 { .compatible = "fsl,imx8mm-ocotp", .data = &imx8mm_params },
580 { .compatible = "fsl,imx8mn-ocotp", .data = &imx8mn_params },
581 { .compatible = "fsl,imx8mp-ocotp", .data = &imx8mp_params },
589 cell->read_post_process = imx_ocotp_cell_pp; in imx_ocotp_fixup_dt_cell_info()
594 struct device *dev = &pdev->dev; in imx_ocotp_probe()
600 return -ENOMEM; in imx_ocotp_probe()
602 priv->dev = dev; in imx_ocotp_probe()
604 priv->base = devm_platform_ioremap_resource(pdev, 0); in imx_ocotp_probe()
605 if (IS_ERR(priv->base)) in imx_ocotp_probe()
606 return PTR_ERR(priv->base); in imx_ocotp_probe()
608 priv->clk = devm_clk_get(dev, NULL); in imx_ocotp_probe()
609 if (IS_ERR(priv->clk)) in imx_ocotp_probe()
610 return PTR_ERR(priv->clk); in imx_ocotp_probe()
612 priv->params = of_device_get_match_data(&pdev->dev); in imx_ocotp_probe()
614 imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; in imx_ocotp_probe()
619 priv->config = &imx_ocotp_nvmem_config; in imx_ocotp_probe()
621 clk_prepare_enable(priv->clk); in imx_ocotp_probe()
623 clk_disable_unprepare(priv->clk); in imx_ocotp_probe()
640 MODULE_DESCRIPTION("i.MX6/i.MX7 OCOTP fuse box driver");