rockchip-otp.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
  4. */
  5. #include <common.h>
  6. #include <asm/io.h>
  7. #include <command.h>
  8. #include <dm.h>
  9. #include <linux/bitops.h>
  10. #include <linux/delay.h>
  11. #include <misc.h>
  12. /* OTP Register Offsets */
  13. #define OTPC_SBPI_CTRL 0x0020
  14. #define OTPC_SBPI_CMD_VALID_PRE 0x0024
  15. #define OTPC_SBPI_CS_VALID_PRE 0x0028
  16. #define OTPC_SBPI_STATUS 0x002C
  17. #define OTPC_USER_CTRL 0x0100
  18. #define OTPC_USER_ADDR 0x0104
  19. #define OTPC_USER_ENABLE 0x0108
  20. #define OTPC_USER_QP 0x0120
  21. #define OTPC_USER_Q 0x0124
  22. #define OTPC_INT_STATUS 0x0304
  23. #define OTPC_SBPI_CMD0_OFFSET 0x1000
  24. #define OTPC_SBPI_CMD1_OFFSET 0x1004
  25. /* OTP Register bits and masks */
  26. #define OTPC_USER_ADDR_MASK GENMASK(31, 16)
  27. #define OTPC_USE_USER BIT(0)
  28. #define OTPC_USE_USER_MASK GENMASK(16, 16)
  29. #define OTPC_USER_FSM_ENABLE BIT(0)
  30. #define OTPC_USER_FSM_ENABLE_MASK GENMASK(16, 16)
  31. #define OTPC_SBPI_DONE BIT(1)
  32. #define OTPC_USER_DONE BIT(2)
  33. #define SBPI_DAP_ADDR 0x02
  34. #define SBPI_DAP_ADDR_SHIFT 8
  35. #define SBPI_DAP_ADDR_MASK GENMASK(31, 24)
  36. #define SBPI_CMD_VALID_MASK GENMASK(31, 16)
  37. #define SBPI_DAP_CMD_WRF 0xC0
  38. #define SBPI_DAP_REG_ECC 0x3A
  39. #define SBPI_ECC_ENABLE 0x00
  40. #define SBPI_ECC_DISABLE 0x09
  41. #define SBPI_ENABLE BIT(0)
  42. #define SBPI_ENABLE_MASK GENMASK(16, 16)
  43. #define OTPC_TIMEOUT 10000
  44. struct rockchip_otp_plat {
  45. void __iomem *base;
  46. unsigned long secure_conf_base;
  47. unsigned long otp_mask_base;
  48. };
  49. static int rockchip_otp_wait_status(struct rockchip_otp_plat *otp,
  50. u32 flag)
  51. {
  52. int delay = OTPC_TIMEOUT;
  53. while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) {
  54. udelay(1);
  55. delay--;
  56. if (delay <= 0) {
  57. printf("%s: wait init status timeout\n", __func__);
  58. return -ETIMEDOUT;
  59. }
  60. }
  61. /* clean int status */
  62. writel(flag, otp->base + OTPC_INT_STATUS);
  63. return 0;
  64. }
  65. static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp,
  66. bool enable)
  67. {
  68. int ret = 0;
  69. writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
  70. otp->base + OTPC_SBPI_CTRL);
  71. writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
  72. writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
  73. otp->base + OTPC_SBPI_CMD0_OFFSET);
  74. if (enable)
  75. writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
  76. else
  77. writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
  78. writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
  79. ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
  80. if (ret < 0)
  81. printf("%s timeout during ecc_enable\n", __func__);
  82. return ret;
  83. }
  84. static int rockchip_px30_otp_read(struct udevice *dev, int offset,
  85. void *buf, int size)
  86. {
  87. struct rockchip_otp_plat *otp = dev_get_plat(dev);
  88. u8 *buffer = buf;
  89. int ret = 0;
  90. ret = rockchip_otp_ecc_enable(otp, false);
  91. if (ret < 0) {
  92. printf("%s rockchip_otp_ecc_enable err\n", __func__);
  93. return ret;
  94. }
  95. writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
  96. udelay(5);
  97. while (size--) {
  98. writel(offset++ | OTPC_USER_ADDR_MASK,
  99. otp->base + OTPC_USER_ADDR);
  100. writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
  101. otp->base + OTPC_USER_ENABLE);
  102. ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
  103. if (ret < 0) {
  104. printf("%s timeout during read setup\n", __func__);
  105. goto read_end;
  106. }
  107. *buffer++ = readb(otp->base + OTPC_USER_Q);
  108. }
  109. read_end:
  110. writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
  111. return ret;
  112. }
  113. static int rockchip_otp_read(struct udevice *dev, int offset,
  114. void *buf, int size)
  115. {
  116. return rockchip_px30_otp_read(dev, offset, buf, size);
  117. }
  118. static const struct misc_ops rockchip_otp_ops = {
  119. .read = rockchip_otp_read,
  120. };
  121. static int rockchip_otp_of_to_plat(struct udevice *dev)
  122. {
  123. struct rockchip_otp_plat *otp = dev_get_plat(dev);
  124. otp->base = dev_read_addr_ptr(dev);
  125. return 0;
  126. }
  127. static const struct udevice_id rockchip_otp_ids[] = {
  128. {
  129. .compatible = "rockchip,px30-otp",
  130. .data = (ulong)&rockchip_px30_otp_read,
  131. },
  132. {
  133. .compatible = "rockchip,rk3308-otp",
  134. .data = (ulong)&rockchip_px30_otp_read,
  135. },
  136. {}
  137. };
  138. U_BOOT_DRIVER(rockchip_otp) = {
  139. .name = "rockchip_otp",
  140. .id = UCLASS_MISC,
  141. .of_match = rockchip_otp_ids,
  142. .ops = &rockchip_otp_ops,
  143. .of_to_plat = rockchip_otp_of_to_plat,
  144. .plat_auto = sizeof(struct rockchip_otp_plat),
  145. };