1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <asm/arch/cpu.h> 8 #include <asm/io.h> 9 #include <command.h> 10 #include <dm.h> 11 #include <linux/bitops.h> 12 #include <linux/delay.h> 13 #include <linux/iopoll.h> 14 #include <misc.h> 15 #include <rockchip-otp.h> 16 17 struct otp_data { 18 int (*init)(struct udevice *dev); 19 int (*read)(struct udevice *dev, int offset, void *buf, int size); 20 }; 21 22 static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp, 23 u32 flag) 24 { 25 int delay = OTPC_TIMEOUT; 26 27 while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) { 28 udelay(1); 29 delay--; 30 if (delay <= 0) { 31 printf("%s: wait init status timeout\n", __func__); 32 return -ETIMEDOUT; 33 } 34 } 35 36 /* clean int status */ 37 writel(flag, otp->base + OTPC_INT_STATUS); 38 39 return 0; 40 } 41 42 static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp, 43 bool enable) 44 { 45 int ret = 0; 46 47 writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT), 48 otp->base + OTPC_SBPI_CTRL); 49 50 writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE); 51 writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC, 52 otp->base + OTPC_SBPI_CMD0_OFFSET); 53 if (enable) 54 writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET); 55 else 56 writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET); 57 58 writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); 59 60 ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); 61 if (ret < 0) 62 printf("%s timeout during ecc_enable\n", __func__); 63 64 return ret; 65 } 66 67 static int rockchip_px30_otp_read(struct udevice *dev, int offset, 68 void *buf, int size) 69 { 70 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 71 u8 *buffer = buf; 72 int ret = 0; 73 74 ret = rockchip_otp_ecc_enable(otp, false); 75 if (ret < 0) { 76 printf("%s rockchip_otp_ecc_enable err\n", __func__); 77 return ret; 78 } 79 80 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 81 udelay(5); 82 while (size--) { 83 writel(offset++ | OTPC_USER_ADDR_MASK, 84 otp->base + OTPC_USER_ADDR); 85 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, 86 otp->base + OTPC_USER_ENABLE); 87 ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); 88 if (ret < 0) { 89 printf("%s timeout during read setup\n", __func__); 90 goto read_end; 91 } 92 *buffer++ = readb(otp->base + OTPC_USER_Q); 93 } 94 95 read_end: 96 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 97 98 return ret; 99 } 100 101 static int rk3308bs_otp_wait_status(struct rockchip_otp_platdata *otp, u32 flag) 102 { 103 int delay = OTPC_TIMEOUT; 104 105 while (!(readl(otp->base + OTPC_IRQ_ST) & flag)) { 106 udelay(1); 107 delay--; 108 if (delay <= 0) { 109 printf("%s: wait init status timeout\n", __func__); 110 return -ETIMEDOUT; 111 } 112 } 113 114 /* clean int status */ 115 writel(flag, otp->base + OTPC_IRQ_ST); 116 117 return 0; 118 } 119 120 static int rk3308bs_otp_active(struct rockchip_otp_platdata *otp) 121 { 122 int ret = 0; 123 u32 mode; 124 125 mode = readl(otp->base + OTPC_MODE_CTRL); 126 127 switch (mode) { 128 case OTPC_DEEP_STANDBY: 129 writel(OTPC_STANDBY, otp->base + OTPC_MODE_CTRL); 130 ret = rk3308bs_otp_wait_status(otp, OTPC_DP2STB_IRQ_ST); 131 if (ret < 0) { 132 dev_err(otp->dev, "timeout during wait dp2stb\n"); 133 return ret; 134 } 135 case OTPC_STANDBY: 136 writel(OTPC_ACTIVE, otp->base + OTPC_MODE_CTRL); 137 ret = rk3308bs_otp_wait_status(otp, OTPC_STB2ACT_IRQ_ST); 138 if (ret < 0) { 139 dev_err(otp->dev, "timeout during wait stb2act\n"); 140 return ret; 141 } 142 break; 143 default: 144 break; 145 } 146 147 return ret; 148 } 149 150 static int rk3308bs_otp_standby(struct rockchip_otp_platdata *otp) 151 { 152 int ret = 0; 153 u32 mode; 154 155 mode = readl(otp->base + OTPC_MODE_CTRL); 156 157 switch (mode) { 158 case OTPC_ACTIVE: 159 writel(OTPC_STANDBY, otp->base + OTPC_MODE_CTRL); 160 ret = rk3308bs_otp_wait_status(otp, OTPC_ACT2STB_IRQ_ST); 161 if (ret < 0) { 162 dev_err(otp->dev, "timeout during wait act2stb\n"); 163 return ret; 164 } 165 case OTPC_STANDBY: 166 writel(OTPC_DEEP_STANDBY, otp->base + OTPC_MODE_CTRL); 167 ret = rk3308bs_otp_wait_status(otp, OTPC_STB2DP_IRQ_ST); 168 if (ret < 0) { 169 dev_err(otp->dev, "timeout during wait stb2dp\n"); 170 return ret; 171 } 172 break; 173 default: 174 break; 175 } 176 177 return ret; 178 } 179 180 static int rockchip_rk3308bs_otp_read(struct udevice *dev, int offset, 181 void *buf, int size) 182 { 183 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 184 unsigned int addr_start, addr_end, addr_offset, addr_len; 185 u32 out_value; 186 u8 *buffer; 187 int ret = 0, i = 0; 188 189 if (offset > RK3308BS_MAX_BYTES - 1) 190 return -ENOMEM; 191 if (offset + size > RK3308BS_MAX_BYTES) 192 size = RK3308BS_MAX_BYTES - offset; 193 194 ret = rk3308bs_otp_active(otp); 195 if (ret) 196 goto out; 197 198 addr_start = rounddown(offset, RK3308BS_NBYTES) / RK3308BS_NBYTES; 199 addr_end = roundup(offset + size, RK3308BS_NBYTES) / RK3308BS_NBYTES; 200 addr_offset = offset % RK3308BS_NBYTES; 201 addr_len = addr_end - addr_start; 202 203 buffer = calloc(1, sizeof(*buffer) * addr_len * RK3308BS_NBYTES); 204 if (!buffer) { 205 ret = -ENOMEM; 206 goto read_end; 207 } 208 209 while (addr_len--) { 210 writel(OTPC_TRANS_NUM, otp->base + OTPC_REPR_RD_TRANS_NUM); 211 writel(addr_start++, otp->base + OTPC_ACCESS_ADDR); 212 writel(OTPC_READ_ACCESS, otp->base + OTPC_MODE_CTRL); 213 ret = rk3308bs_otp_wait_status(otp, OTPC_RDM_IRQ_ST); 214 if (ret < 0) { 215 printf("timeout during wait rd\n"); 216 goto read_end; 217 } 218 out_value = readl(otp->base + OTPC_RD_DATA); 219 memcpy(&buffer[i], &out_value, RK3308BS_NBYTES); 220 i += RK3308BS_NBYTES; 221 } 222 memcpy(buf, buffer + addr_offset, size); 223 224 read_end: 225 kfree(buffer); 226 rk3308bs_otp_standby(otp); 227 out: 228 return ret; 229 } 230 231 static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, void *buf, 232 int size) 233 { 234 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 235 unsigned int addr_start, addr_end, addr_offset, addr_len; 236 u32 out_value; 237 u8 *buffer; 238 int ret = 0, i = 0; 239 240 addr_start = rounddown(offset, RK3568_NBYTES) / RK3568_NBYTES; 241 addr_end = roundup(offset + size, RK3568_NBYTES) / RK3568_NBYTES; 242 addr_offset = offset % RK3568_NBYTES; 243 addr_len = addr_end - addr_start; 244 245 buffer = calloc(1, sizeof(*buffer) * addr_len * RK3568_NBYTES); 246 if (!buffer) 247 return -ENOMEM; 248 249 ret = rockchip_otp_ecc_enable(otp, false); 250 if (ret < 0) { 251 printf("%s rockchip_otp_ecc_enable err\n", __func__); 252 return ret; 253 } 254 255 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 256 udelay(5); 257 while (addr_len--) { 258 writel(addr_start++ | OTPC_USER_ADDR_MASK, 259 otp->base + OTPC_USER_ADDR); 260 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, 261 otp->base + OTPC_USER_ENABLE); 262 ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); 263 if (ret < 0) { 264 printf("%s timeout during read setup\n", __func__); 265 goto read_end; 266 } 267 out_value = readl(otp->base + OTPC_USER_Q); 268 memcpy(&buffer[i], &out_value, RK3568_NBYTES); 269 i += RK3568_NBYTES; 270 } 271 272 memcpy(buf, buffer + addr_offset, size); 273 274 read_end: 275 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 276 277 kfree(buffer); 278 279 return ret; 280 } 281 282 static int rockchip_rk3588_otp_read(struct udevice *dev, int offset, void *buf, 283 int size) 284 { 285 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 286 unsigned int addr_start, addr_end, addr_offset, addr_len; 287 int ret = 0, i = 0; 288 u32 out_value, st = 0; 289 u8 *buffer; 290 291 if (offset > RK3588_MAX_BYTES - 1) 292 return -ENOMEM; 293 if (offset + size > RK3588_MAX_BYTES) 294 size = RK3588_MAX_BYTES - offset; 295 296 addr_start = rounddown(offset, RK3588_NBYTES) / RK3588_NBYTES; 297 addr_end = roundup(offset + size, RK3588_NBYTES) / RK3588_NBYTES; 298 addr_offset = offset % RK3588_NBYTES; 299 addr_len = addr_end - addr_start; 300 addr_start += RK3588_NO_SECURE_OFFSET; 301 302 buffer = calloc(1, sizeof(*buffer) * addr_len * RK3588_NBYTES); 303 if (!buffer) 304 return -ENOMEM; 305 306 while (addr_len--) { 307 writel((addr_start << RK3588_ADDR_SHIFT) | 308 (RK3588_BURST_NUM << RK3588_BURST_SHIFT), 309 otp->base + RK3588_OTPC_AUTO_CTRL); 310 writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); 311 ret = readl_poll_timeout(otp->base + RK3588_OTPC_INT_ST, st, 312 st & RK3588_RD_DONE, OTPC_TIMEOUT); 313 if (ret < 0) { 314 printf("%s timeout during read setup\n", __func__); 315 goto read_end; 316 } 317 writel(RK3588_RD_DONE, otp->base + RK3588_OTPC_INT_ST); 318 319 out_value = readl(otp->base + RK3588_OTPC_DOUT0); 320 memcpy(&buffer[i], &out_value, RK3588_NBYTES); 321 i += RK3588_NBYTES; 322 addr_start++; 323 } 324 325 memcpy(buf, buffer + addr_offset, size); 326 327 read_end: 328 kfree(buffer); 329 330 return ret; 331 } 332 333 static int rockchip_rv1126_otp_init(struct udevice *dev) 334 { 335 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 336 u32 status = 0; 337 int ret; 338 339 writel(0x0, otp->base + RV1126_OTP_NVM_CEB); 340 ret = readl_poll_timeout(otp->base + RV1126_OTP_NVM_ST, status, 341 status & 0x1, OTPC_TIMEOUT); 342 if (ret < 0) { 343 printf("%s timeout during set ceb\n", __func__); 344 return ret; 345 } 346 347 writel(0x1, otp->base + RV1126_OTP_NVM_RSTB); 348 ret = readl_poll_timeout(otp->base + RV1126_OTP_NVM_ST, status, 349 status & 0x4, OTPC_TIMEOUT); 350 if (ret < 0) { 351 printf("%s timeout during set rstb\n", __func__); 352 return ret; 353 } 354 355 return 0; 356 } 357 358 static int rockchip_rv1126_otp_read(struct udevice *dev, int offset, void *buf, 359 int size) 360 { 361 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 362 u32 status = 0; 363 u8 *buffer = buf; 364 int ret = 0; 365 366 while (size--) { 367 writel(offset++, otp->base + RV1126_OTP_NVM_RADDR); 368 writel(0x1, otp->base + RV1126_OTP_NVM_RSTART); 369 ret = readl_poll_timeout(otp->base + RV1126_OTP_READ_ST, 370 status, status == 0, OTPC_TIMEOUT); 371 if (ret < 0) { 372 printf("%s timeout during read setup\n", __func__); 373 return ret; 374 } 375 376 *buffer++ = readb(otp->base + RV1126_OTP_NVM_RDATA); 377 } 378 379 return 0; 380 } 381 382 static int rockchip_otp_read(struct udevice *dev, int offset, 383 void *buf, int size) 384 { 385 struct otp_data *data; 386 387 data = (struct otp_data *)dev_get_driver_data(dev); 388 if (!data) 389 return -ENOSYS; 390 391 if (soc_is_rk3308bs() || soc_is_px30s()) 392 return rockchip_rk3308bs_otp_read(dev, offset, buf, size); 393 394 return data->read(dev, offset, buf, size); 395 } 396 397 static const struct misc_ops rockchip_otp_ops = { 398 .read = rockchip_otp_read, 399 }; 400 401 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev) 402 { 403 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 404 405 otp->base = dev_read_addr_ptr(dev); 406 407 return 0; 408 } 409 410 static int rockchip_otp_probe(struct udevice *dev) 411 { 412 struct otp_data *data; 413 414 data = (struct otp_data *)dev_get_driver_data(dev); 415 if (!data) 416 return -EINVAL; 417 418 if (data->init) 419 return data->init(dev); 420 421 return 0; 422 } 423 424 static const struct otp_data px30_data = { 425 .read = rockchip_px30_otp_read, 426 }; 427 428 static const struct otp_data rk3308bs_data = { 429 .read = rockchip_rk3308bs_otp_read, 430 }; 431 432 static const struct otp_data rk3568_data = { 433 .read = rockchip_rk3568_otp_read, 434 }; 435 436 static const struct otp_data rk3588_data = { 437 .read = rockchip_rk3588_otp_read, 438 }; 439 440 static const struct otp_data rv1126_data = { 441 .init = rockchip_rv1126_otp_init, 442 .read = rockchip_rv1126_otp_read, 443 }; 444 445 static const struct udevice_id rockchip_otp_ids[] = { 446 { 447 .compatible = "rockchip,px30-otp", 448 .data = (ulong)&px30_data, 449 }, 450 { 451 .compatible = "rockchip,px30s-otp", 452 .data = (ulong)&rk3308bs_data, 453 }, 454 { 455 .compatible = "rockchip,rk3308-otp", 456 .data = (ulong)&px30_data, 457 }, 458 { 459 .compatible = "rockchip,rk3308bs-otp", 460 .data = (ulong)&rk3308bs_data, 461 }, 462 { 463 .compatible = "rockchip,rk3528-otp", 464 .data = (ulong)&rk3568_data, 465 }, 466 { 467 .compatible = "rockchip,rk3562-otp", 468 .data = (ulong)&rk3568_data, 469 }, 470 { 471 .compatible = "rockchip,rk3568-otp", 472 .data = (ulong)&rk3568_data, 473 }, 474 { 475 .compatible = "rockchip,rk3588-otp", 476 .data = (ulong)&rk3588_data, 477 }, 478 { 479 .compatible = "rockchip,rv1106-otp", 480 .data = (ulong)&rk3568_data, 481 }, 482 { 483 .compatible = "rockchip,rv1126-otp", 484 .data = (ulong)&rv1126_data, 485 }, 486 {} 487 }; 488 489 U_BOOT_DRIVER(rockchip_otp) = { 490 .name = "rockchip_otp", 491 .id = UCLASS_MISC, 492 .of_match = rockchip_otp_ids, 493 .ops = &rockchip_otp_ops, 494 .ofdata_to_platdata = rockchip_otp_ofdata_to_platdata, 495 .platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata), 496 .probe = rockchip_otp_probe, 497 }; 498