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 
9 #include <linux/clk.h>
10 #include <linux/delay.h>
11 #include <linux/device.h>
12 #include <linux/io.h>
13 #include <linux/iopoll.h>
14 #include <linux/module.h>
15 #include <linux/nvmem-provider.h>
16 #include <linux/reset.h>
17 #include <linux/slab.h>
18 #include <linux/of.h>
19 #include <linux/of_platform.h>
20 #include <linux/platform_device.h>
21 
22 /* OTP Register Offsets */
23 #define OTPC_SBPI_CTRL 0x0020
24 #define OTPC_SBPI_CMD_VALID_PRE 0x0024
25 #define OTPC_SBPI_CS_VALID_PRE 0x0028
26 #define OTPC_SBPI_STATUS 0x002C
27 #define OTPC_USER_CTRL 0x0100
28 #define OTPC_USER_ADDR 0x0104
29 #define OTPC_USER_ENABLE 0x0108
30 #define OTPC_USER_Q 0x0124
31 #define OTPC_INT_STATUS 0x0304
32 #define OTPC_SBPI_CMD0_OFFSET 0x1000
33 #define OTPC_SBPI_CMD1_OFFSET 0x1004
34 
35 /* OTP Register bits and masks */
36 #define OTPC_USER_ADDR_MASK GENMASK(31, 16)
37 #define OTPC_USE_USER BIT(0)
38 #define OTPC_USE_USER_MASK GENMASK(16, 16)
39 #define OTPC_USER_FSM_ENABLE BIT(0)
40 #define OTPC_USER_FSM_ENABLE_MASK GENMASK(16, 16)
41 #define OTPC_SBPI_DONE BIT(1)
42 #define OTPC_USER_DONE BIT(2)
43 
44 #define SBPI_DAP_ADDR 0x02
45 #define SBPI_DAP_ADDR_SHIFT 8
46 #define SBPI_DAP_ADDR_MASK GENMASK(31, 24)
47 #define SBPI_CMD_VALID_MASK GENMASK(31, 16)
48 #define SBPI_DAP_CMD_WRF 0xC0
49 #define SBPI_DAP_REG_ECC 0x3A
50 #define SBPI_ECC_ENABLE 0x00
51 #define SBPI_ECC_DISABLE 0x09
52 #define SBPI_ENABLE BIT(0)
53 #define SBPI_ENABLE_MASK GENMASK(16, 16)
54 
55 #define OTPC_TIMEOUT 10000
56 
57 #define UDELAY_TWO 2
58 #define UDELAY_FIVE 5
59 
60 struct rockchip_otp {
61     struct device *dev;
62     void __iomem *base;
63     struct clk_bulk_data *clks;
64     int num_clks;
65     struct reset_control *rst;
66 };
67 
68 /* list of required clocks */
69 static const char *const rockchip_otp_clocks[] = {
70     "otp",
71     "apb_pclk",
72     "phy",
73 };
74 
75 struct rockchip_data {
76     int size;
77 };
78 
rockchip_otp_reset(struct rockchip_otp *otp)79 static int rockchip_otp_reset(struct rockchip_otp *otp)
80 {
81     int ret;
82 
83     ret = reset_control_assert(otp->rst);
84     if (ret) {
85         dev_err(otp->dev, "failed to assert otp phy %d\n", ret);
86         return ret;
87     }
88 
89     udelay(UDELAY_TWO);
90 
91     ret = reset_control_deassert(otp->rst);
92     if (ret) {
93         dev_err(otp->dev, "failed to deassert otp phy %d\n", ret);
94         return ret;
95     }
96 
97     return 0;
98 }
99 
rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)100 static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
101 {
102     u32 status = 0;
103     int ret;
104 
105     ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status, (status & flag), 1, OTPC_TIMEOUT);
106     if (ret) {
107         return ret;
108     }
109 
110     /* clean int status */
111     writel(flag, otp->base + OTPC_INT_STATUS);
112 
113     return 0;
114 }
115 
rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)116 static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
117 {
118     int ret = 0;
119 
120     writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT), otp->base + OTPC_SBPI_CTRL);
121 
122     writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
123     writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC, otp->base + OTPC_SBPI_CMD0_OFFSET);
124     if (enable) {
125         writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
126     } else {
127         writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
128     }
129 
130     writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
131 
132     ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
133     if (ret < 0) {
134         dev_err(otp->dev, "timeout during ecc_enable\n");
135     }
136 
137     return ret;
138 }
139 
rockchip_otp_read(void *context, unsigned int offset, void *val, size_t bytes)140 static int rockchip_otp_read(void *context, unsigned int offset, void *val, size_t bytes)
141 {
142     struct rockchip_otp *otp = context;
143     u8 *buf = val;
144     int ret = 0;
145 
146     ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
147     if (ret < 0) {
148         dev_err(otp->dev, "failed to prepare/enable clks\n");
149         return ret;
150     }
151 
152     ret = rockchip_otp_reset(otp);
153     if (ret) {
154         dev_err(otp->dev, "failed to reset otp phy\n");
155         goto disable_clks;
156     }
157 
158     ret = rockchip_otp_ecc_enable(otp, false);
159     if (ret < 0) {
160         dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
161         goto disable_clks;
162     }
163 
164     writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
165     udelay(UDELAY_FIVE);
166     while (bytes--) {
167         writel(offset++ | OTPC_USER_ADDR_MASK, otp->base + OTPC_USER_ADDR);
168         writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, otp->base + OTPC_USER_ENABLE);
169         ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
170         if (ret < 0) {
171             dev_err(otp->dev, "timeout during read setup\n");
172             goto read_end;
173         }
174         *buf++ = readb(otp->base + OTPC_USER_Q);
175     }
176 
177 read_end:
178     writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
179 disable_clks:
180     clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
181 
182     return ret;
183 }
184 
185 static struct nvmem_config otp_config = {
186     .name = "rockchip-otp",
187     .owner = THIS_MODULE,
188     .read_only = true,
189     .stride = 1,
190     .word_size = 1,
191     .reg_read = rockchip_otp_read,
192 };
193 
194 static const struct rockchip_data px30_data = {
195     .size = 0x40,
196 };
197 
198 static const struct of_device_id rockchip_otp_match[] = {
199     {
200         .compatible = "rockchip,px30-otp",
201         .data = (void *)&px30_data,
202     },
203     {
204         .compatible = "rockchip,rk3308-otp",
205         .data = (void *)&px30_data,
206     },
207     {},
208 };
209 MODULE_DEVICE_TABLE(of, rockchip_otp_match);
210 
rockchip_otp_probe(struct platform_device *pdev)211 static int rockchip_otp_probe(struct platform_device *pdev)
212 {
213     struct device *dev = &pdev->dev;
214     struct rockchip_otp *otp;
215     const struct rockchip_data *data;
216     struct nvmem_device *nvmem;
217     int ret, i;
218 
219     data = of_device_get_match_data(dev);
220     if (!data) {
221         dev_err(dev, "failed to get match data\n");
222         return -EINVAL;
223     }
224 
225     otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp), GFP_KERNEL);
226     if (!otp) {
227         return -ENOMEM;
228     }
229 
230     otp->dev = dev;
231     otp->base = devm_platform_ioremap_resource(pdev, 0);
232     if (IS_ERR(otp->base)) {
233         return PTR_ERR(otp->base);
234     }
235 
236     otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
237     otp->clks = devm_kcalloc(dev, otp->num_clks, sizeof(*otp->clks), GFP_KERNEL);
238     if (!otp->clks) {
239         return -ENOMEM;
240     }
241 
242     for (i = 0; i < otp->num_clks; ++i) {
243         otp->clks[i].id = rockchip_otp_clocks[i];
244     }
245 
246     ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
247     if (ret) {
248         return ret;
249     }
250 
251     otp->rst = devm_reset_control_get(dev, "phy");
252     if (IS_ERR(otp->rst)) {
253         return PTR_ERR(otp->rst);
254     }
255 
256     otp_config.size = data->size;
257     otp_config.priv = otp;
258     otp_config.dev = dev;
259     nvmem = devm_nvmem_register(dev, &otp_config);
260 
261     return PTR_ERR_OR_ZERO(nvmem);
262 }
263 
264 static struct platform_driver rockchip_otp_driver = {
265     .probe = rockchip_otp_probe,
266     .driver =
267         {
268             .name = "rockchip-otp",
269             .of_match_table = rockchip_otp_match,
270         },
271 };
272 
rockchip_otp_init(void)273 static int __init rockchip_otp_init(void)
274 {
275     int ret;
276 
277     ret = platform_driver_register(&rockchip_otp_driver);
278     if (ret) {
279         pr_err("failed to register otp driver\n");
280         return ret;
281     }
282 
283     return 0;
284 }
285 
rockchip_otp_exit(void)286 static void __exit rockchip_otp_exit(void)
287 {
288     return platform_driver_unregister(&rockchip_otp_driver);
289 }
290 
291 subsys_initcall(rockchip_otp_init);
292 module_exit(rockchip_otp_exit);
293 
294 MODULE_DESCRIPTION("Rockchip OTP driver");
295 MODULE_LICENSE("GPL v2");
296