1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2013 ADVANSEE 4 * Beno��t Th��baudeau <benoit.thebaudeau@advansee.com> 5 * 6 * Based on Dirk Behme's 7 * https://github.com/dirkbehme/u-boot-imx6/blob/28b17e9/drivers/misc/imx_otp.c, 8 * which is based on Freescale's 9 * https://source.codeaurora.org/external/imx/uboot-imx/tree/drivers/misc/imx_otp.c?id=9aa74e6, 10 * which is: 11 * Copyright (C) 2011 Freescale Semiconductor, Inc. 12 */ 13 14#include <common.h> 15#include <fuse.h> 16#include <linux/delay.h> 17#include <linux/errno.h> 18#include <asm/io.h> 19#include <asm/arch/clock.h> 20#include <asm/arch/imx-regs.h> 21#include <asm/mach-imx/sys_proto.h> 22 23#define BO_CTRL_WR_UNLOCK 16 24#define BM_CTRL_WR_UNLOCK 0xffff0000 25#define BV_CTRL_WR_UNLOCK_KEY 0x3e77 26#define BM_CTRL_ERROR 0x00000200 27#define BM_CTRL_BUSY 0x00000100 28#define BO_CTRL_ADDR 0 29#ifdef CONFIG_MX7 30#define BM_CTRL_ADDR 0x0000000f 31#define BM_CTRL_RELOAD 0x00000400 32#elif defined(CONFIG_MX7ULP) 33#define BM_CTRL_ADDR 0x000000FF 34#define BM_CTRL_RELOAD 0x00000400 35#define BM_OUT_STATUS_DED 0x00000400 36#define BM_OUT_STATUS_LOCKED 0x00000800 37#define BM_OUT_STATUS_PROGFAIL 0x00001000 38#elif defined(CONFIG_IMX8M) 39#ifdef CONFIG_IMX8MP 40#undef BM_CTRL_ADDR 41#undef BM_CTRL_ERROR 42#undef BM_CTRL_BUSY 43#define BM_CTRL_ADDR 0x000001ff 44#define BM_CTRL_ERROR 0x00000400 45#define BM_CTRL_BUSY 0x00000200 46#else 47#define BM_CTRL_ADDR 0x000000ff 48#endif 49#else 50#define BM_CTRL_ADDR 0x0000007f 51#endif 52 53#ifdef CONFIG_MX7 54#define BO_TIMING_FSOURCE 12 55#define BM_TIMING_FSOURCE 0x0007f000 56#define BV_TIMING_FSOURCE_NS 1001 57#define BO_TIMING_PROG 0 58#define BM_TIMING_PROG 0x00000fff 59#define BV_TIMING_PROG_US 10 60#else 61#define BO_TIMING_STROBE_READ 16 62#define BM_TIMING_STROBE_READ 0x003f0000 63#define BV_TIMING_STROBE_READ_NS 37 64#define BO_TIMING_RELAX 12 65#define BM_TIMING_RELAX 0x0000f000 66#define BV_TIMING_RELAX_NS 17 67#define BO_TIMING_STROBE_PROG 0 68#define BM_TIMING_STROBE_PROG 0x00000fff 69#define BV_TIMING_STROBE_PROG_US 10 70#endif 71 72#define BM_READ_CTRL_READ_FUSE 0x00000001 73 74#define BF(value, field) (((value) << BO_##field) & BM_##field) 75 76#define WRITE_POSTAMBLE_US 2 77 78#if defined(CONFIG_MX6) || defined(CONFIG_VF610) 79#define FUSE_BANK_SIZE 0x80 80#ifdef CONFIG_MX6SL 81#define FUSE_BANKS 8 82#elif defined(CONFIG_MX6ULL) || defined(CONFIG_MX6SLL) 83#define FUSE_BANKS 9 84#else 85#define FUSE_BANKS 16 86#endif 87#elif defined CONFIG_MX7 88#define FUSE_BANK_SIZE 0x40 89#define FUSE_BANKS 16 90#elif defined(CONFIG_MX7ULP) 91#define FUSE_BANK_SIZE 0x80 92#define FUSE_BANKS 31 93#elif defined(CONFIG_IMX8M) 94#define FUSE_BANK_SIZE 0x40 95#ifdef CONFIG_IMX8MP 96#define FUSE_BANKS 96 97#else 98#define FUSE_BANKS 64 99#endif 100#else 101#error "Unsupported architecture\n" 102#endif 103 104#if defined(CONFIG_MX6) 105 106/* 107 * There is a hole in shadow registers address map of size 0x100 108 * between bank 5 and bank 6 on iMX6QP, iMX6DQ, iMX6SDL, iMX6SX, 109 * iMX6UL, i.MX6ULL and i.MX6SLL. 110 * Bank 5 ends at 0x6F0 and Bank 6 starts at 0x800. When reading the fuses, 111 * we should account for this hole in address space. 112 * 113 * Similar hole exists between bank 14 and bank 15 of size 114 * 0x80 on iMX6QP, iMX6DQ, iMX6SDL and iMX6SX. 115 * Note: iMX6SL has only 0-7 banks and there is no hole. 116 * Note: iMX6UL doesn't have this one. 117 * 118 * This function is to covert user input to physical bank index. 119 * Only needed when read fuse, because we use register offset, so 120 * need to calculate real register offset. 121 * When write, no need to consider hole, always use the bank/word 122 * index from fuse map. 123 */ 124u32 fuse_bank_physical(int index) 125{ 126 u32 phy_index; 127 128 if (is_mx6sl() || is_mx7ulp()) { 129 phy_index = index; 130 } else if (is_mx6ul() || is_mx6ull() || is_mx6sll()) { 131 if ((is_mx6ull() || is_mx6sll()) && index == 8) 132 index = 7; 133 134 if (index >= 6) 135 phy_index = fuse_bank_physical(5) + (index - 6) + 3; 136 else 137 phy_index = index; 138 } else { 139 if (index >= 15) 140 phy_index = fuse_bank_physical(14) + (index - 15) + 2; 141 else if (index >= 6) 142 phy_index = fuse_bank_physical(5) + (index - 6) + 3; 143 else 144 phy_index = index; 145 } 146 return phy_index; 147} 148 149u32 fuse_word_physical(u32 bank, u32 word_index) 150{ 151 if (is_mx6ull() || is_mx6sll()) { 152 if (bank == 8) 153 word_index = word_index + 4; 154 } 155 156 return word_index; 157} 158#else 159u32 fuse_bank_physical(int index) 160{ 161 return index; 162} 163 164u32 fuse_word_physical(u32 bank, u32 word_index) 165{ 166 return word_index; 167} 168 169#endif 170 171static void wait_busy(struct ocotp_regs *regs, unsigned int delay_us) 172{ 173 while (readl(®s->ctrl) & BM_CTRL_BUSY) 174 udelay(delay_us); 175} 176 177static void clear_error(struct ocotp_regs *regs) 178{ 179 writel(BM_CTRL_ERROR, ®s->ctrl_clr); 180} 181 182static int prepare_access(struct ocotp_regs **regs, u32 bank, u32 word, 183 int assert, const char *caller) 184{ 185 *regs = (struct ocotp_regs *)OCOTP_BASE_ADDR; 186 187 if (bank >= FUSE_BANKS || 188 word >= ARRAY_SIZE((*regs)->bank[0].fuse_regs) >> 2 || 189 !assert) { 190 printf("mxc_ocotp %s(): Invalid argument\n", caller); 191 return -EINVAL; 192 } 193 194 if (is_mx6ull() || is_mx6sll()) { 195 if ((bank == 7 || bank == 8) && 196 word >= ARRAY_SIZE((*regs)->bank[0].fuse_regs) >> 3) { 197 printf("mxc_ocotp %s(): Invalid argument\n", caller); 198 return -EINVAL; 199 } 200 } 201 202 enable_ocotp_clk(1); 203 204 wait_busy(*regs, 1); 205 clear_error(*regs); 206 207 return 0; 208} 209 210static int finish_access(struct ocotp_regs *regs, const char *caller) 211{ 212 u32 err; 213 214 err = !!(readl(®s->ctrl) & BM_CTRL_ERROR); 215 clear_error(regs); 216 217#ifdef CONFIG_MX7ULP 218 /* Need to power down the OTP memory */ 219 writel(1, ®s->pdn); 220#endif 221 if (err) { 222 printf("mxc_ocotp %s(): Access protect error\n", caller); 223 return -EIO; 224 } 225 226 return 0; 227} 228 229static int prepare_read(struct ocotp_regs **regs, u32 bank, u32 word, u32 *val, 230 const char *caller) 231{ 232 return prepare_access(regs, bank, word, val != NULL, caller); 233} 234 235int fuse_read(u32 bank, u32 word, u32 *val) 236{ 237 struct ocotp_regs *regs; 238 int ret; 239 u32 phy_bank; 240 u32 phy_word; 241 242 ret = prepare_read(®s, bank, word, val, __func__); 243 if (ret) 244 return ret; 245 246 phy_bank = fuse_bank_physical(bank); 247 phy_word = fuse_word_physical(bank, word); 248 249 *val = readl(®s->bank[phy_bank].fuse_regs[phy_word << 2]); 250 251#ifdef CONFIG_MX7ULP 252 if (readl(®s->out_status) & BM_OUT_STATUS_DED) { 253 writel(BM_OUT_STATUS_DED, ®s->out_status_clr); 254 printf("mxc_ocotp %s(): fuse read wrong\n", __func__); 255 return -EIO; 256 } 257#endif 258 return finish_access(regs, __func__); 259} 260 261#ifdef CONFIG_MX7 262static void set_timing(struct ocotp_regs *regs) 263{ 264 u32 ipg_clk; 265 u32 fsource, prog; 266 u32 timing; 267 268 ipg_clk = mxc_get_clock(MXC_IPG_CLK); 269 270 fsource = DIV_ROUND_UP((ipg_clk / 1000) * BV_TIMING_FSOURCE_NS, 271 + 1000000) + 1; 272 prog = DIV_ROUND_CLOSEST(ipg_clk * BV_TIMING_PROG_US, 1000000) + 1; 273 274 timing = BF(fsource, TIMING_FSOURCE) | BF(prog, TIMING_PROG); 275 276 clrsetbits_le32(®s->timing, BM_TIMING_FSOURCE | BM_TIMING_PROG, 277 timing); 278} 279#elif defined(CONFIG_MX7ULP) 280static void set_timing(struct ocotp_regs *regs) 281{ 282 /* No timing set for MX7ULP */ 283} 284 285#else 286static void set_timing(struct ocotp_regs *regs) 287{ 288 u32 ipg_clk; 289 u32 relax, strobe_read, strobe_prog; 290 u32 timing; 291 292 ipg_clk = mxc_get_clock(MXC_IPG_CLK); 293 294 relax = DIV_ROUND_UP(ipg_clk * BV_TIMING_RELAX_NS, 1000000000) - 1; 295 strobe_read = DIV_ROUND_UP(ipg_clk * BV_TIMING_STROBE_READ_NS, 296 1000000000) + 2 * (relax + 1) - 1; 297 strobe_prog = DIV_ROUND_CLOSEST(ipg_clk * BV_TIMING_STROBE_PROG_US, 298 1000000) + 2 * (relax + 1) - 1; 299 300 timing = BF(strobe_read, TIMING_STROBE_READ) | 301 BF(relax, TIMING_RELAX) | 302 BF(strobe_prog, TIMING_STROBE_PROG); 303 304 clrsetbits_le32(®s->timing, BM_TIMING_STROBE_READ | BM_TIMING_RELAX | 305 BM_TIMING_STROBE_PROG, timing); 306} 307#endif 308 309static void setup_direct_access(struct ocotp_regs *regs, u32 bank, u32 word, 310 int write) 311{ 312 u32 wr_unlock = write ? BV_CTRL_WR_UNLOCK_KEY : 0; 313#ifdef CONFIG_MX7 314 u32 addr = bank; 315#elif defined CONFIG_IMX8M 316 u32 addr = bank << 2 | word; 317#else 318 u32 addr; 319 /* Bank 7 and Bank 8 only supports 4 words each for i.MX6ULL */ 320 if ((is_mx6ull() || is_mx6sll()) && (bank > 7)) { 321 bank = bank - 1; 322 word += 4; 323 } 324 addr = bank << 3 | word; 325#endif 326 327 set_timing(regs); 328 clrsetbits_le32(®s->ctrl, BM_CTRL_WR_UNLOCK | BM_CTRL_ADDR, 329 BF(wr_unlock, CTRL_WR_UNLOCK) | 330 BF(addr, CTRL_ADDR)); 331} 332 333int fuse_sense(u32 bank, u32 word, u32 *val) 334{ 335 struct ocotp_regs *regs; 336 int ret; 337 338 if (is_imx8mq() && (soc_rev() >= CHIP_REV_2_1)) { 339 printf("mxc_ocotp %s(): fuse sense is disabled\n", __func__); 340 return -EPERM; 341 } 342 343 ret = prepare_read(®s, bank, word, val, __func__); 344 if (ret) 345 return ret; 346 347 setup_direct_access(regs, bank, word, false); 348 writel(BM_READ_CTRL_READ_FUSE, ®s->read_ctrl); 349 wait_busy(regs, 1); 350#ifdef CONFIG_MX7 351 *val = readl((®s->read_fuse_data0) + (word << 2)); 352#else 353 *val = readl(®s->read_fuse_data); 354#endif 355 356#ifdef CONFIG_MX7ULP 357 if (readl(®s->out_status) & BM_OUT_STATUS_DED) { 358 writel(BM_OUT_STATUS_DED, ®s->out_status_clr); 359 printf("mxc_ocotp %s(): fuse read wrong\n", __func__); 360 return -EIO; 361 } 362#endif 363 364 return finish_access(regs, __func__); 365} 366 367static int prepare_write(struct ocotp_regs **regs, u32 bank, u32 word, 368 const char *caller) 369{ 370#ifdef CONFIG_MX7ULP 371 u32 val; 372 int ret; 373 374 /* Only bank 0 and 1 are redundancy mode, others are ECC mode */ 375 if (bank != 0 && bank != 1) { 376 if ((soc_rev() < CHIP_REV_2_0) || 377 ((soc_rev() >= CHIP_REV_2_0) && 378 bank != 9 && bank != 10 && bank != 28)) { 379 ret = fuse_sense(bank, word, &val); 380 if (ret) 381 return ret; 382 383 if (val != 0) { 384 printf("mxc_ocotp: The word has been programmed, no more write\n"); 385 return -EPERM; 386 } 387 } 388 } 389#endif 390 391 return prepare_access(regs, bank, word, true, caller); 392} 393 394int fuse_prog(u32 bank, u32 word, u32 val) 395{ 396 struct ocotp_regs *regs; 397 int ret; 398 399 ret = prepare_write(®s, bank, word, __func__); 400 if (ret) 401 return ret; 402 403 setup_direct_access(regs, bank, word, true); 404#ifdef CONFIG_MX7 405 switch (word) { 406 case 0: 407 writel(0, ®s->data1); 408 writel(0, ®s->data2); 409 writel(0, ®s->data3); 410 writel(val, ®s->data0); 411 break; 412 case 1: 413 writel(val, ®s->data1); 414 writel(0, ®s->data2); 415 writel(0, ®s->data3); 416 writel(0, ®s->data0); 417 break; 418 case 2: 419 writel(0, ®s->data1); 420 writel(val, ®s->data2); 421 writel(0, ®s->data3); 422 writel(0, ®s->data0); 423 break; 424 case 3: 425 writel(0, ®s->data1); 426 writel(0, ®s->data2); 427 writel(val, ®s->data3); 428 writel(0, ®s->data0); 429 break; 430 } 431 wait_busy(regs, BV_TIMING_PROG_US); 432#else 433 writel(val, ®s->data); 434 wait_busy(regs, BV_TIMING_STROBE_PROG_US); 435#endif 436 udelay(WRITE_POSTAMBLE_US); 437 438#ifdef CONFIG_MX7ULP 439 if (readl(®s->out_status) & (BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED)) { 440 writel((BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED), ®s->out_status_clr); 441 printf("mxc_ocotp %s(): fuse write is failed\n", __func__); 442 return -EIO; 443 } 444#endif 445 446 return finish_access(regs, __func__); 447} 448 449int fuse_override(u32 bank, u32 word, u32 val) 450{ 451 struct ocotp_regs *regs; 452 int ret; 453 u32 phy_bank; 454 u32 phy_word; 455 456 ret = prepare_write(®s, bank, word, __func__); 457 if (ret) 458 return ret; 459 460 phy_bank = fuse_bank_physical(bank); 461 phy_word = fuse_word_physical(bank, word); 462 463 writel(val, ®s->bank[phy_bank].fuse_regs[phy_word << 2]); 464 465#ifdef CONFIG_MX7ULP 466 if (readl(®s->out_status) & (BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED)) { 467 writel((BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED), ®s->out_status_clr); 468 printf("mxc_ocotp %s(): fuse write is failed\n", __func__); 469 return -EIO; 470 } 471#endif 472 473 return finish_access(regs, __func__); 474} 475