12bbcccf5SMarek Vasut /*
22bbcccf5SMarek Vasut * Freescale i.MX28 OCOTP Driver
32bbcccf5SMarek Vasut *
42bbcccf5SMarek Vasut * Copyright (C) 2014 Marek Vasut <marex@denx.de>
52bbcccf5SMarek Vasut *
62bbcccf5SMarek Vasut * SPDX-License-Identifier: GPL-2.0+
72bbcccf5SMarek Vasut *
82bbcccf5SMarek Vasut * Note: The i.MX23/i.MX28 OCOTP block is a predecessor to the OCOTP block
92bbcccf5SMarek Vasut * used in i.MX6 . While these blocks are very similar at the first
102bbcccf5SMarek Vasut * glance, by digging deeper, one will notice differences (like the
112bbcccf5SMarek Vasut * tight dependence on MXS power block, some completely new registers
122bbcccf5SMarek Vasut * etc.) which would make common driver an ifdef nightmare :-(
132bbcccf5SMarek Vasut */
142bbcccf5SMarek Vasut
152bbcccf5SMarek Vasut #include <common.h>
162bbcccf5SMarek Vasut #include <fuse.h>
17*1221ce45SMasahiro Yamada #include <linux/errno.h>
182bbcccf5SMarek Vasut #include <asm/io.h>
192bbcccf5SMarek Vasut #include <asm/arch/clock.h>
202bbcccf5SMarek Vasut #include <asm/arch/imx-regs.h>
212bbcccf5SMarek Vasut #include <asm/arch/sys_proto.h>
222bbcccf5SMarek Vasut
232bbcccf5SMarek Vasut #define MXS_OCOTP_TIMEOUT 100000
242bbcccf5SMarek Vasut
252bbcccf5SMarek Vasut static struct mxs_ocotp_regs *ocotp_regs =
262bbcccf5SMarek Vasut (struct mxs_ocotp_regs *)MXS_OCOTP_BASE;
272bbcccf5SMarek Vasut static struct mxs_power_regs *power_regs =
282bbcccf5SMarek Vasut (struct mxs_power_regs *)MXS_POWER_BASE;
292bbcccf5SMarek Vasut static struct mxs_clkctrl_regs *clkctrl_regs =
302bbcccf5SMarek Vasut (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
312bbcccf5SMarek Vasut
mxs_ocotp_wait_busy_clear(void)322bbcccf5SMarek Vasut static int mxs_ocotp_wait_busy_clear(void)
332bbcccf5SMarek Vasut {
342bbcccf5SMarek Vasut uint32_t reg;
352bbcccf5SMarek Vasut int timeout = MXS_OCOTP_TIMEOUT;
362bbcccf5SMarek Vasut
372bbcccf5SMarek Vasut while (--timeout) {
382bbcccf5SMarek Vasut reg = readl(&ocotp_regs->hw_ocotp_ctrl);
392bbcccf5SMarek Vasut if (!(reg & OCOTP_CTRL_BUSY))
402bbcccf5SMarek Vasut break;
412bbcccf5SMarek Vasut udelay(10);
422bbcccf5SMarek Vasut }
432bbcccf5SMarek Vasut
442bbcccf5SMarek Vasut if (!timeout)
452bbcccf5SMarek Vasut return -EINVAL;
462bbcccf5SMarek Vasut
472bbcccf5SMarek Vasut /* Wait a little as per FSL datasheet's 'write postamble' section. */
482bbcccf5SMarek Vasut udelay(10);
492bbcccf5SMarek Vasut
502bbcccf5SMarek Vasut return 0;
512bbcccf5SMarek Vasut }
522bbcccf5SMarek Vasut
mxs_ocotp_clear_error(void)532bbcccf5SMarek Vasut static void mxs_ocotp_clear_error(void)
542bbcccf5SMarek Vasut {
552bbcccf5SMarek Vasut writel(OCOTP_CTRL_ERROR, &ocotp_regs->hw_ocotp_ctrl_clr);
562bbcccf5SMarek Vasut }
572bbcccf5SMarek Vasut
mxs_ocotp_read_bank_open(bool open)582bbcccf5SMarek Vasut static int mxs_ocotp_read_bank_open(bool open)
592bbcccf5SMarek Vasut {
602bbcccf5SMarek Vasut int ret = 0;
612bbcccf5SMarek Vasut
622bbcccf5SMarek Vasut if (open) {
632bbcccf5SMarek Vasut writel(OCOTP_CTRL_RD_BANK_OPEN,
642bbcccf5SMarek Vasut &ocotp_regs->hw_ocotp_ctrl_set);
652bbcccf5SMarek Vasut
662bbcccf5SMarek Vasut /*
672bbcccf5SMarek Vasut * Wait before polling the BUSY bit, since the BUSY bit might
682bbcccf5SMarek Vasut * be asserted only after a few HCLK cycles and if we were to
692bbcccf5SMarek Vasut * poll immediatelly, we could miss the busy bit.
702bbcccf5SMarek Vasut */
712bbcccf5SMarek Vasut udelay(10);
722bbcccf5SMarek Vasut ret = mxs_ocotp_wait_busy_clear();
732bbcccf5SMarek Vasut } else {
742bbcccf5SMarek Vasut writel(OCOTP_CTRL_RD_BANK_OPEN,
752bbcccf5SMarek Vasut &ocotp_regs->hw_ocotp_ctrl_clr);
762bbcccf5SMarek Vasut }
772bbcccf5SMarek Vasut
782bbcccf5SMarek Vasut return ret;
792bbcccf5SMarek Vasut }
802bbcccf5SMarek Vasut
mxs_ocotp_scale_vddio(bool enter,uint32_t * val)812bbcccf5SMarek Vasut static void mxs_ocotp_scale_vddio(bool enter, uint32_t *val)
822bbcccf5SMarek Vasut {
832bbcccf5SMarek Vasut uint32_t scale_val;
842bbcccf5SMarek Vasut
852bbcccf5SMarek Vasut if (enter) {
862bbcccf5SMarek Vasut /*
872bbcccf5SMarek Vasut * Enter the fuse programming VDDIO voltage setup. We start
882bbcccf5SMarek Vasut * scaling the voltage from it's current value down to 2.8V
892bbcccf5SMarek Vasut * which is the one and only correct voltage for programming
902bbcccf5SMarek Vasut * the OCOTP fuses (according to datasheet).
912bbcccf5SMarek Vasut */
922bbcccf5SMarek Vasut scale_val = readl(&power_regs->hw_power_vddioctrl);
932bbcccf5SMarek Vasut scale_val &= POWER_VDDIOCTRL_TRG_MASK;
942bbcccf5SMarek Vasut
952bbcccf5SMarek Vasut /* Return the original voltage. */
962bbcccf5SMarek Vasut *val = scale_val;
972bbcccf5SMarek Vasut
982bbcccf5SMarek Vasut /*
992bbcccf5SMarek Vasut * Start scaling VDDIO down to 0x2, which is 2.8V . Actually,
1002bbcccf5SMarek Vasut * the value 0x0 should be 2.8V, but that's not the case on
1012bbcccf5SMarek Vasut * most designs due to load etc., so we play safe. Undervolt
1022bbcccf5SMarek Vasut * can actually cause incorrect programming of the fuses and
1032bbcccf5SMarek Vasut * or reboots of the board.
1042bbcccf5SMarek Vasut */
1052bbcccf5SMarek Vasut while (scale_val > 2) {
1062bbcccf5SMarek Vasut clrsetbits_le32(&power_regs->hw_power_vddioctrl,
1072bbcccf5SMarek Vasut POWER_VDDIOCTRL_TRG_MASK, --scale_val);
1082bbcccf5SMarek Vasut udelay(500);
1092bbcccf5SMarek Vasut }
1102bbcccf5SMarek Vasut } else {
1112bbcccf5SMarek Vasut /* Start scaling VDDIO up to original value . */
1122bbcccf5SMarek Vasut for (scale_val = 2; scale_val <= *val; scale_val++) {
1132bbcccf5SMarek Vasut clrsetbits_le32(&power_regs->hw_power_vddioctrl,
1142bbcccf5SMarek Vasut POWER_VDDIOCTRL_TRG_MASK, scale_val);
1152bbcccf5SMarek Vasut udelay(500);
1162bbcccf5SMarek Vasut }
1172bbcccf5SMarek Vasut }
1182bbcccf5SMarek Vasut
1192bbcccf5SMarek Vasut mdelay(10);
1202bbcccf5SMarek Vasut }
1212bbcccf5SMarek Vasut
mxs_ocotp_wait_hclk_ready(void)1222bbcccf5SMarek Vasut static int mxs_ocotp_wait_hclk_ready(void)
1232bbcccf5SMarek Vasut {
1242bbcccf5SMarek Vasut uint32_t reg, timeout = MXS_OCOTP_TIMEOUT;
1252bbcccf5SMarek Vasut
1262bbcccf5SMarek Vasut while (--timeout) {
1272bbcccf5SMarek Vasut reg = readl(&clkctrl_regs->hw_clkctrl_hbus);
1282bbcccf5SMarek Vasut if (!(reg & CLKCTRL_HBUS_ASM_BUSY))
1292bbcccf5SMarek Vasut break;
1302bbcccf5SMarek Vasut }
1312bbcccf5SMarek Vasut
1322bbcccf5SMarek Vasut if (!timeout)
1332bbcccf5SMarek Vasut return -EINVAL;
1342bbcccf5SMarek Vasut
1352bbcccf5SMarek Vasut return 0;
1362bbcccf5SMarek Vasut }
1372bbcccf5SMarek Vasut
mxs_ocotp_scale_hclk(bool enter,uint32_t * val)1382bbcccf5SMarek Vasut static int mxs_ocotp_scale_hclk(bool enter, uint32_t *val)
1392bbcccf5SMarek Vasut {
1402bbcccf5SMarek Vasut uint32_t scale_val;
1412bbcccf5SMarek Vasut int ret;
1422bbcccf5SMarek Vasut
1432bbcccf5SMarek Vasut ret = mxs_ocotp_wait_hclk_ready();
1442bbcccf5SMarek Vasut if (ret)
1452bbcccf5SMarek Vasut return ret;
1462bbcccf5SMarek Vasut
1472bbcccf5SMarek Vasut /* Set CPU bypass */
1482bbcccf5SMarek Vasut writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
1492bbcccf5SMarek Vasut &clkctrl_regs->hw_clkctrl_clkseq_set);
1502bbcccf5SMarek Vasut
1512bbcccf5SMarek Vasut if (enter) {
1522bbcccf5SMarek Vasut /* Return the original HCLK clock speed. */
1532bbcccf5SMarek Vasut *val = readl(&clkctrl_regs->hw_clkctrl_hbus);
1542bbcccf5SMarek Vasut *val &= CLKCTRL_HBUS_DIV_MASK;
155d4b8b5d4SChris Smith *val >>= CLKCTRL_HBUS_DIV_OFFSET;
1562bbcccf5SMarek Vasut
1572bbcccf5SMarek Vasut /* Scale the HCLK to 454/19 = 23.9 MHz . */
1582bbcccf5SMarek Vasut scale_val = (~19) << CLKCTRL_HBUS_DIV_OFFSET;
1592bbcccf5SMarek Vasut scale_val &= CLKCTRL_HBUS_DIV_MASK;
1602bbcccf5SMarek Vasut } else {
1612bbcccf5SMarek Vasut /* Scale the HCLK back to original frequency. */
1622bbcccf5SMarek Vasut scale_val = (~(*val)) << CLKCTRL_HBUS_DIV_OFFSET;
1632bbcccf5SMarek Vasut scale_val &= CLKCTRL_HBUS_DIV_MASK;
1642bbcccf5SMarek Vasut }
1652bbcccf5SMarek Vasut
1662bbcccf5SMarek Vasut writel(CLKCTRL_HBUS_DIV_MASK,
1672bbcccf5SMarek Vasut &clkctrl_regs->hw_clkctrl_hbus_set);
1682bbcccf5SMarek Vasut writel(scale_val,
1692bbcccf5SMarek Vasut &clkctrl_regs->hw_clkctrl_hbus_clr);
1702bbcccf5SMarek Vasut
1712bbcccf5SMarek Vasut mdelay(10);
1722bbcccf5SMarek Vasut
1732bbcccf5SMarek Vasut ret = mxs_ocotp_wait_hclk_ready();
1742bbcccf5SMarek Vasut if (ret)
1752bbcccf5SMarek Vasut return ret;
1762bbcccf5SMarek Vasut
1772bbcccf5SMarek Vasut /* Disable CPU bypass */
1782bbcccf5SMarek Vasut writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
1792bbcccf5SMarek Vasut &clkctrl_regs->hw_clkctrl_clkseq_clr);
1802bbcccf5SMarek Vasut
1812bbcccf5SMarek Vasut mdelay(10);
1822bbcccf5SMarek Vasut
1832bbcccf5SMarek Vasut return 0;
1842bbcccf5SMarek Vasut }
1852bbcccf5SMarek Vasut
mxs_ocotp_write_fuse(uint32_t addr,uint32_t mask)1862bbcccf5SMarek Vasut static int mxs_ocotp_write_fuse(uint32_t addr, uint32_t mask)
1872bbcccf5SMarek Vasut {
1882bbcccf5SMarek Vasut uint32_t hclk_val, vddio_val;
1892bbcccf5SMarek Vasut int ret;
1902bbcccf5SMarek Vasut
1913d99fcbcSHector Palacios mxs_ocotp_clear_error();
1923d99fcbcSHector Palacios
1932bbcccf5SMarek Vasut /* Make sure the banks are closed for reading. */
1942bbcccf5SMarek Vasut ret = mxs_ocotp_read_bank_open(0);
1952bbcccf5SMarek Vasut if (ret) {
1962bbcccf5SMarek Vasut puts("Failed closing banks for reading!\n");
1972bbcccf5SMarek Vasut return ret;
1982bbcccf5SMarek Vasut }
1992bbcccf5SMarek Vasut
2002bbcccf5SMarek Vasut ret = mxs_ocotp_scale_hclk(1, &hclk_val);
2012bbcccf5SMarek Vasut if (ret) {
2022bbcccf5SMarek Vasut puts("Failed scaling down the HCLK!\n");
2032bbcccf5SMarek Vasut return ret;
2042bbcccf5SMarek Vasut }
2052bbcccf5SMarek Vasut mxs_ocotp_scale_vddio(1, &vddio_val);
2062bbcccf5SMarek Vasut
2072bbcccf5SMarek Vasut ret = mxs_ocotp_wait_busy_clear();
2082bbcccf5SMarek Vasut if (ret) {
2092bbcccf5SMarek Vasut puts("Failed waiting for ready state!\n");
2102bbcccf5SMarek Vasut goto fail;
2112bbcccf5SMarek Vasut }
2122bbcccf5SMarek Vasut
2132bbcccf5SMarek Vasut /* Program the fuse address */
2142bbcccf5SMarek Vasut writel(addr | OCOTP_CTRL_WR_UNLOCK_KEY, &ocotp_regs->hw_ocotp_ctrl);
2152bbcccf5SMarek Vasut
2162bbcccf5SMarek Vasut /* Program the data. */
2172bbcccf5SMarek Vasut writel(mask, &ocotp_regs->hw_ocotp_data);
2182bbcccf5SMarek Vasut
2192bbcccf5SMarek Vasut udelay(10);
2202bbcccf5SMarek Vasut
2212bbcccf5SMarek Vasut ret = mxs_ocotp_wait_busy_clear();
2222bbcccf5SMarek Vasut if (ret) {
2232bbcccf5SMarek Vasut puts("Failed waiting for ready state!\n");
2242bbcccf5SMarek Vasut goto fail;
2252bbcccf5SMarek Vasut }
2262bbcccf5SMarek Vasut
227ad5dd7aeSHector Palacios /* Check for errors */
228ad5dd7aeSHector Palacios if (readl(&ocotp_regs->hw_ocotp_ctrl) & OCOTP_CTRL_ERROR) {
229ad5dd7aeSHector Palacios puts("Failed writing fuses!\n");
230ad5dd7aeSHector Palacios ret = -EPERM;
231ad5dd7aeSHector Palacios goto fail;
232ad5dd7aeSHector Palacios }
233ad5dd7aeSHector Palacios
2342bbcccf5SMarek Vasut fail:
2352bbcccf5SMarek Vasut mxs_ocotp_scale_vddio(0, &vddio_val);
236d8d160e4SHector Palacios if (mxs_ocotp_scale_hclk(0, &hclk_val))
2372bbcccf5SMarek Vasut puts("Failed scaling up the HCLK!\n");
2382bbcccf5SMarek Vasut
2392bbcccf5SMarek Vasut return ret;
2402bbcccf5SMarek Vasut }
2412bbcccf5SMarek Vasut
mxs_ocotp_read_fuse(uint32_t reg,uint32_t * val)2422bbcccf5SMarek Vasut static int mxs_ocotp_read_fuse(uint32_t reg, uint32_t *val)
2432bbcccf5SMarek Vasut {
2442bbcccf5SMarek Vasut int ret;
2452bbcccf5SMarek Vasut
2462bbcccf5SMarek Vasut /* Register offset from CUST0 */
2472bbcccf5SMarek Vasut reg = ((uint32_t)&ocotp_regs->hw_ocotp_cust0) + (reg << 4);
2482bbcccf5SMarek Vasut
2492bbcccf5SMarek Vasut ret = mxs_ocotp_wait_busy_clear();
2502bbcccf5SMarek Vasut if (ret) {
2512bbcccf5SMarek Vasut puts("Failed waiting for ready state!\n");
2522bbcccf5SMarek Vasut return ret;
2532bbcccf5SMarek Vasut }
2542bbcccf5SMarek Vasut
2552bbcccf5SMarek Vasut mxs_ocotp_clear_error();
2562bbcccf5SMarek Vasut
2572bbcccf5SMarek Vasut ret = mxs_ocotp_read_bank_open(1);
2582bbcccf5SMarek Vasut if (ret) {
2592bbcccf5SMarek Vasut puts("Failed opening banks for reading!\n");
2602bbcccf5SMarek Vasut return ret;
2612bbcccf5SMarek Vasut }
2622bbcccf5SMarek Vasut
2632bbcccf5SMarek Vasut *val = readl(reg);
2642bbcccf5SMarek Vasut
2652bbcccf5SMarek Vasut ret = mxs_ocotp_read_bank_open(0);
2662bbcccf5SMarek Vasut if (ret) {
2672bbcccf5SMarek Vasut puts("Failed closing banks for reading!\n");
2682bbcccf5SMarek Vasut return ret;
2692bbcccf5SMarek Vasut }
2702bbcccf5SMarek Vasut
2712bbcccf5SMarek Vasut return ret;
2722bbcccf5SMarek Vasut }
2732bbcccf5SMarek Vasut
mxs_ocotp_valid(u32 bank,u32 word)2742bbcccf5SMarek Vasut static int mxs_ocotp_valid(u32 bank, u32 word)
2752bbcccf5SMarek Vasut {
2762bbcccf5SMarek Vasut if (bank > 4)
2772bbcccf5SMarek Vasut return -EINVAL;
2782bbcccf5SMarek Vasut if (word > 7)
2792bbcccf5SMarek Vasut return -EINVAL;
2802bbcccf5SMarek Vasut return 0;
2812bbcccf5SMarek Vasut }
2822bbcccf5SMarek Vasut
2832bbcccf5SMarek Vasut /*
2842bbcccf5SMarek Vasut * The 'fuse' command API
2852bbcccf5SMarek Vasut */
fuse_read(u32 bank,u32 word,u32 * val)2862bbcccf5SMarek Vasut int fuse_read(u32 bank, u32 word, u32 *val)
2872bbcccf5SMarek Vasut {
2882bbcccf5SMarek Vasut int ret;
2892bbcccf5SMarek Vasut
2902bbcccf5SMarek Vasut ret = mxs_ocotp_valid(bank, word);
2912bbcccf5SMarek Vasut if (ret)
2922bbcccf5SMarek Vasut return ret;
2932bbcccf5SMarek Vasut
2942bbcccf5SMarek Vasut return mxs_ocotp_read_fuse((bank << 3) | word, val);
2952bbcccf5SMarek Vasut }
2962bbcccf5SMarek Vasut
fuse_prog(u32 bank,u32 word,u32 val)2972bbcccf5SMarek Vasut int fuse_prog(u32 bank, u32 word, u32 val)
2982bbcccf5SMarek Vasut {
2992bbcccf5SMarek Vasut int ret;
3002bbcccf5SMarek Vasut
3012bbcccf5SMarek Vasut ret = mxs_ocotp_valid(bank, word);
3022bbcccf5SMarek Vasut if (ret)
3032bbcccf5SMarek Vasut return ret;
3042bbcccf5SMarek Vasut
3052bbcccf5SMarek Vasut return mxs_ocotp_write_fuse((bank << 3) | word, val);
3062bbcccf5SMarek Vasut }
3072bbcccf5SMarek Vasut
fuse_sense(u32 bank,u32 word,u32 * val)3082bbcccf5SMarek Vasut int fuse_sense(u32 bank, u32 word, u32 *val)
3092bbcccf5SMarek Vasut {
3102bbcccf5SMarek Vasut /* We do not support sensing :-( */
3112bbcccf5SMarek Vasut return -EINVAL;
3122bbcccf5SMarek Vasut }
3132bbcccf5SMarek Vasut
fuse_override(u32 bank,u32 word,u32 val)3142bbcccf5SMarek Vasut int fuse_override(u32 bank, u32 word, u32 val)
3152bbcccf5SMarek Vasut {
3162bbcccf5SMarek Vasut /* We do not support overriding :-( */
3172bbcccf5SMarek Vasut return -EINVAL;
3182bbcccf5SMarek Vasut }
319