rockchip-otp.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Rockchip OTP Driver
  4. *
  5. * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
  6. * Author: Finley Xiao <finley.xiao@rock-chips.com>
  7. */
  8. #include <linux/clk.h>
  9. #include <linux/delay.h>
  10. #include <linux/device.h>
  11. #include <linux/io.h>
  12. #include <linux/iopoll.h>
  13. #include <linux/module.h>
  14. #include <linux/nvmem-provider.h>
  15. #include <linux/reset.h>
  16. #include <linux/slab.h>
  17. #include <linux/of.h>
  18. #include <linux/of_platform.h>
  19. #include <linux/platform_device.h>
  20. /* OTP Register Offsets */
  21. #define OTPC_SBPI_CTRL 0x0020
  22. #define OTPC_SBPI_CMD_VALID_PRE 0x0024
  23. #define OTPC_SBPI_CS_VALID_PRE 0x0028
  24. #define OTPC_SBPI_STATUS 0x002C
  25. #define OTPC_USER_CTRL 0x0100
  26. #define OTPC_USER_ADDR 0x0104
  27. #define OTPC_USER_ENABLE 0x0108
  28. #define OTPC_USER_Q 0x0124
  29. #define OTPC_INT_STATUS 0x0304
  30. #define OTPC_SBPI_CMD0_OFFSET 0x1000
  31. #define OTPC_SBPI_CMD1_OFFSET 0x1004
  32. /* OTP Register bits and masks */
  33. #define OTPC_USER_ADDR_MASK GENMASK(31, 16)
  34. #define OTPC_USE_USER BIT(0)
  35. #define OTPC_USE_USER_MASK GENMASK(16, 16)
  36. #define OTPC_USER_FSM_ENABLE BIT(0)
  37. #define OTPC_USER_FSM_ENABLE_MASK GENMASK(16, 16)
  38. #define OTPC_SBPI_DONE BIT(1)
  39. #define OTPC_USER_DONE BIT(2)
  40. #define SBPI_DAP_ADDR 0x02
  41. #define SBPI_DAP_ADDR_SHIFT 8
  42. #define SBPI_DAP_ADDR_MASK GENMASK(31, 24)
  43. #define SBPI_CMD_VALID_MASK GENMASK(31, 16)
  44. #define SBPI_DAP_CMD_WRF 0xC0
  45. #define SBPI_DAP_REG_ECC 0x3A
  46. #define SBPI_ECC_ENABLE 0x00
  47. #define SBPI_ECC_DISABLE 0x09
  48. #define SBPI_ENABLE BIT(0)
  49. #define SBPI_ENABLE_MASK GENMASK(16, 16)
  50. #define OTPC_TIMEOUT 10000
  51. struct rockchip_otp {
  52. struct device *dev;
  53. void __iomem *base;
  54. struct clk_bulk_data *clks;
  55. int num_clks;
  56. struct reset_control *rst;
  57. };
  58. /* list of required clocks */
  59. static const char * const rockchip_otp_clocks[] = {
  60. "otp", "apb_pclk", "phy",
  61. };
  62. struct rockchip_data {
  63. int size;
  64. };
  65. static int rockchip_otp_reset(struct rockchip_otp *otp)
  66. {
  67. int ret;
  68. ret = reset_control_assert(otp->rst);
  69. if (ret) {
  70. dev_err(otp->dev, "failed to assert otp phy %d\n", ret);
  71. return ret;
  72. }
  73. udelay(2);
  74. ret = reset_control_deassert(otp->rst);
  75. if (ret) {
  76. dev_err(otp->dev, "failed to deassert otp phy %d\n", ret);
  77. return ret;
  78. }
  79. return 0;
  80. }
  81. static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
  82. {
  83. u32 status = 0;
  84. int ret;
  85. ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status,
  86. (status & flag), 1, OTPC_TIMEOUT);
  87. if (ret)
  88. return ret;
  89. /* clean int status */
  90. writel(flag, otp->base + OTPC_INT_STATUS);
  91. return 0;
  92. }
  93. static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
  94. {
  95. int ret = 0;
  96. writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
  97. otp->base + OTPC_SBPI_CTRL);
  98. writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
  99. writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
  100. otp->base + OTPC_SBPI_CMD0_OFFSET);
  101. if (enable)
  102. writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
  103. else
  104. writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
  105. writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
  106. ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
  107. if (ret < 0)
  108. dev_err(otp->dev, "timeout during ecc_enable\n");
  109. return ret;
  110. }
  111. static int rockchip_otp_read(void *context, unsigned int offset,
  112. void *val, size_t bytes)
  113. {
  114. struct rockchip_otp *otp = context;
  115. u8 *buf = val;
  116. int ret = 0;
  117. ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
  118. if (ret < 0) {
  119. dev_err(otp->dev, "failed to prepare/enable clks\n");
  120. return ret;
  121. }
  122. ret = rockchip_otp_reset(otp);
  123. if (ret) {
  124. dev_err(otp->dev, "failed to reset otp phy\n");
  125. goto disable_clks;
  126. }
  127. ret = rockchip_otp_ecc_enable(otp, false);
  128. if (ret < 0) {
  129. dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
  130. goto disable_clks;
  131. }
  132. writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
  133. udelay(5);
  134. while (bytes--) {
  135. writel(offset++ | OTPC_USER_ADDR_MASK,
  136. otp->base + OTPC_USER_ADDR);
  137. writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
  138. otp->base + OTPC_USER_ENABLE);
  139. ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
  140. if (ret < 0) {
  141. dev_err(otp->dev, "timeout during read setup\n");
  142. goto read_end;
  143. }
  144. *buf++ = readb(otp->base + OTPC_USER_Q);
  145. }
  146. read_end:
  147. writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
  148. disable_clks:
  149. clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
  150. return ret;
  151. }
  152. static struct nvmem_config otp_config = {
  153. .name = "rockchip-otp",
  154. .owner = THIS_MODULE,
  155. .read_only = true,
  156. .stride = 1,
  157. .word_size = 1,
  158. .reg_read = rockchip_otp_read,
  159. };
  160. static const struct rockchip_data px30_data = {
  161. .size = 0x40,
  162. };
  163. static const struct of_device_id rockchip_otp_match[] = {
  164. {
  165. .compatible = "rockchip,px30-otp",
  166. .data = (void *)&px30_data,
  167. },
  168. {
  169. .compatible = "rockchip,rk3308-otp",
  170. .data = (void *)&px30_data,
  171. },
  172. { /* sentinel */ },
  173. };
  174. MODULE_DEVICE_TABLE(of, rockchip_otp_match);
  175. static int rockchip_otp_probe(struct platform_device *pdev)
  176. {
  177. struct device *dev = &pdev->dev;
  178. struct rockchip_otp *otp;
  179. const struct rockchip_data *data;
  180. struct nvmem_device *nvmem;
  181. int ret, i;
  182. data = of_device_get_match_data(dev);
  183. if (!data) {
  184. dev_err(dev, "failed to get match data\n");
  185. return -EINVAL;
  186. }
  187. otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
  188. GFP_KERNEL);
  189. if (!otp)
  190. return -ENOMEM;
  191. otp->dev = dev;
  192. otp->base = devm_platform_ioremap_resource(pdev, 0);
  193. if (IS_ERR(otp->base))
  194. return PTR_ERR(otp->base);
  195. otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
  196. otp->clks = devm_kcalloc(dev, otp->num_clks,
  197. sizeof(*otp->clks), GFP_KERNEL);
  198. if (!otp->clks)
  199. return -ENOMEM;
  200. for (i = 0; i < otp->num_clks; ++i)
  201. otp->clks[i].id = rockchip_otp_clocks[i];
  202. ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
  203. if (ret)
  204. return ret;
  205. otp->rst = devm_reset_control_get(dev, "phy");
  206. if (IS_ERR(otp->rst))
  207. return PTR_ERR(otp->rst);
  208. otp_config.size = data->size;
  209. otp_config.priv = otp;
  210. otp_config.dev = dev;
  211. nvmem = devm_nvmem_register(dev, &otp_config);
  212. return PTR_ERR_OR_ZERO(nvmem);
  213. }
  214. static struct platform_driver rockchip_otp_driver = {
  215. .probe = rockchip_otp_probe,
  216. .driver = {
  217. .name = "rockchip-otp",
  218. .of_match_table = rockchip_otp_match,
  219. },
  220. };
  221. module_platform_driver(rockchip_otp_driver);
  222. MODULE_DESCRIPTION("Rockchip OTP driver");
  223. MODULE_LICENSE("GPL v2");