1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4 */
5
6 #include <asm/io.h>
7 #include <command.h>
8 #include <display_options.h>
9 #include <dm.h>
10 #include <linux/bitops.h>
11 #include <linux/delay.h>
12 #include <linux/iopoll.h>
13 #include <malloc.h>
14 #include <misc.h>
15
16 /* OTP Register Offsets */
17 #define OTPC_SBPI_CTRL 0x0020
18 #define OTPC_SBPI_CMD_VALID_PRE 0x0024
19 #define OTPC_SBPI_CS_VALID_PRE 0x0028
20 #define OTPC_SBPI_STATUS 0x002C
21 #define OTPC_USER_CTRL 0x0100
22 #define OTPC_USER_ADDR 0x0104
23 #define OTPC_USER_ENABLE 0x0108
24 #define OTPC_USER_QP 0x0120
25 #define OTPC_USER_Q 0x0124
26 #define OTPC_INT_STATUS 0x0304
27 #define OTPC_SBPI_CMD0_OFFSET 0x1000
28 #define OTPC_SBPI_CMD1_OFFSET 0x1004
29
30 /* OTP Register bits and masks */
31 #define OTPC_USER_ADDR_MASK GENMASK(31, 16)
32 #define OTPC_USE_USER BIT(0)
33 #define OTPC_USE_USER_MASK GENMASK(16, 16)
34 #define OTPC_USER_FSM_ENABLE BIT(0)
35 #define OTPC_USER_FSM_ENABLE_MASK GENMASK(16, 16)
36 #define OTPC_SBPI_DONE BIT(1)
37 #define OTPC_USER_DONE BIT(2)
38
39 #define SBPI_DAP_ADDR 0x02
40 #define SBPI_DAP_ADDR_SHIFT 8
41 #define SBPI_DAP_ADDR_MASK GENMASK(31, 24)
42 #define SBPI_CMD_VALID_MASK GENMASK(31, 16)
43 #define SBPI_DAP_CMD_WRF 0xC0
44 #define SBPI_DAP_REG_ECC 0x3A
45 #define SBPI_ECC_ENABLE 0x00
46 #define SBPI_ECC_DISABLE 0x09
47 #define SBPI_ENABLE BIT(0)
48 #define SBPI_ENABLE_MASK GENMASK(16, 16)
49
50 #define OTPC_TIMEOUT 10000
51
52 #define RK3588_OTPC_AUTO_CTRL 0x0004
53 #define RK3588_ADDR_SHIFT 16
54 #define RK3588_ADDR(n) ((n) << RK3588_ADDR_SHIFT)
55 #define RK3588_BURST_SHIFT 8
56 #define RK3588_BURST(n) ((n) << RK3588_BURST_SHIFT)
57 #define RK3588_OTPC_AUTO_EN 0x0008
58 #define RK3588_AUTO_EN BIT(0)
59 #define RK3588_OTPC_DOUT0 0x0020
60 #define RK3588_OTPC_INT_ST 0x0084
61 #define RK3588_RD_DONE BIT(1)
62
63 #define RV1126_OTP_NVM_CEB 0x00
64 #define RV1126_OTP_NVM_RSTB 0x04
65 #define RV1126_OTP_NVM_ST 0x18
66 #define RV1126_OTP_NVM_RADDR 0x1C
67 #define RV1126_OTP_NVM_RSTART 0x20
68 #define RV1126_OTP_NVM_RDATA 0x24
69 #define RV1126_OTP_READ_ST 0x30
70
71 struct rockchip_otp_plat {
72 void __iomem *base;
73 };
74
75 struct rockchip_otp_data {
76 int (*init)(struct udevice *dev);
77 int (*read)(struct udevice *dev, int offset, void *buf, int size);
78 int offset;
79 int size;
80 int block_size;
81 };
82
83 #if defined(DEBUG)
dump_otp(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])84 static int dump_otp(struct cmd_tbl *cmdtp, int flag,
85 int argc, char *const argv[])
86 {
87 struct udevice *dev;
88 u8 data[4];
89 int ret, i;
90
91 ret = uclass_get_device_by_driver(UCLASS_MISC,
92 DM_DRIVER_GET(rockchip_otp), &dev);
93 if (ret) {
94 printf("%s: no misc-device found\n", __func__);
95 return 0;
96 }
97
98 for (i = 0; true; i += sizeof(data)) {
99 ret = misc_read(dev, i, &data, sizeof(data));
100 if (ret <= 0)
101 return 0;
102
103 print_buffer(i, data, 1, sizeof(data), sizeof(data));
104 }
105
106 return 0;
107 }
108
109 U_BOOT_CMD(
110 dump_otp, 1, 1, dump_otp,
111 "Dump the content of the otp",
112 ""
113 );
114 #endif
115
rockchip_otp_poll_timeout(struct rockchip_otp_plat * otp,u32 flag,u32 reg)116 static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp,
117 u32 flag, u32 reg)
118 {
119 u32 status;
120 int ret;
121
122 ret = readl_poll_sleep_timeout(otp->base + reg, status,
123 (status & flag), 1, OTPC_TIMEOUT);
124 if (ret)
125 return ret;
126
127 /* Clear int flag */
128 writel(flag, otp->base + reg);
129
130 return 0;
131 }
132
rockchip_otp_ecc_enable(struct rockchip_otp_plat * otp,bool enable)133 static int rockchip_otp_ecc_enable(struct rockchip_otp_plat *otp, bool enable)
134 {
135 writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
136 otp->base + OTPC_SBPI_CTRL);
137
138 writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
139 writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
140 otp->base + OTPC_SBPI_CMD0_OFFSET);
141
142 if (enable)
143 writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
144 else
145 writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
146
147 writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
148
149 return rockchip_otp_poll_timeout(otp, OTPC_SBPI_DONE, OTPC_INT_STATUS);
150 }
151
rockchip_px30_otp_read(struct udevice * dev,int offset,void * buf,int size)152 static int rockchip_px30_otp_read(struct udevice *dev, int offset,
153 void *buf, int size)
154 {
155 struct rockchip_otp_plat *otp = dev_get_plat(dev);
156 u8 *buffer = buf;
157 int ret;
158
159 ret = rockchip_otp_ecc_enable(otp, false);
160 if (ret)
161 return ret;
162
163 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
164 udelay(5);
165
166 while (size--) {
167 writel(offset++ | OTPC_USER_ADDR_MASK,
168 otp->base + OTPC_USER_ADDR);
169 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
170 otp->base + OTPC_USER_ENABLE);
171
172 ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE,
173 OTPC_INT_STATUS);
174 if (ret)
175 goto read_end;
176
177 *buffer++ = (u8)(readl(otp->base + OTPC_USER_Q) & 0xFF);
178 }
179
180 read_end:
181 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
182
183 return ret;
184 }
185
rockchip_rk3568_otp_read(struct udevice * dev,int offset,void * buf,int size)186 static int rockchip_rk3568_otp_read(struct udevice *dev, int offset,
187 void *buf, int size)
188 {
189 struct rockchip_otp_plat *otp = dev_get_plat(dev);
190 u16 *buffer = buf;
191 int ret;
192
193 ret = rockchip_otp_ecc_enable(otp, false);
194 if (ret)
195 return ret;
196
197 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
198 udelay(5);
199
200 while (size--) {
201 writel(offset++ | OTPC_USER_ADDR_MASK,
202 otp->base + OTPC_USER_ADDR);
203 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
204 otp->base + OTPC_USER_ENABLE);
205
206 ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE,
207 OTPC_INT_STATUS);
208 if (ret)
209 goto read_end;
210
211 *buffer++ = (u16)(readl(otp->base + OTPC_USER_Q) & 0xFFFF);
212 }
213
214 read_end:
215 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
216
217 return ret;
218 }
219
rockchip_rk3588_otp_read(struct udevice * dev,int offset,void * buf,int size)220 static int rockchip_rk3588_otp_read(struct udevice *dev, int offset,
221 void *buf, int size)
222 {
223 struct rockchip_otp_plat *otp = dev_get_plat(dev);
224 u32 *buffer = buf;
225 int ret;
226
227 while (size--) {
228 writel(RK3588_ADDR(offset++) | RK3588_BURST(1),
229 otp->base + RK3588_OTPC_AUTO_CTRL);
230 writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
231
232 ret = rockchip_otp_poll_timeout(otp, RK3588_RD_DONE,
233 RK3588_OTPC_INT_ST);
234 if (ret)
235 return ret;
236
237 *buffer++ = readl(otp->base + RK3588_OTPC_DOUT0);
238 }
239
240 return 0;
241 }
242
rockchip_rv1126_otp_init(struct udevice * dev)243 static int rockchip_rv1126_otp_init(struct udevice *dev)
244 {
245 struct rockchip_otp_plat *otp = dev_get_plat(dev);
246 int ret;
247
248 writel(0x0, otp->base + RV1126_OTP_NVM_CEB);
249 ret = rockchip_otp_poll_timeout(otp, 0x1, RV1126_OTP_NVM_ST);
250
251 if (ret)
252 return ret;
253
254 writel(0x1, otp->base + RV1126_OTP_NVM_RSTB);
255 ret = rockchip_otp_poll_timeout(otp, 0x4, RV1126_OTP_NVM_ST);
256
257 if (ret)
258 return ret;
259
260 return 0;
261 }
262
rockchip_rv1126_otp_read(struct udevice * dev,int offset,void * buf,int size)263 static int rockchip_rv1126_otp_read(struct udevice *dev, int offset, void *buf,
264 int size)
265 {
266 struct rockchip_otp_plat *otp = dev_get_plat(dev);
267 u32 status = 0;
268 u8 *buffer = buf;
269 int ret = 0;
270
271 while (size--) {
272 writel(offset++, otp->base + RV1126_OTP_NVM_RADDR);
273 writel(0x1, otp->base + RV1126_OTP_NVM_RSTART);
274 ret = readl_poll_timeout(otp->base + RV1126_OTP_READ_ST,
275 status, !status, OTPC_TIMEOUT);
276 if (ret)
277 return ret;
278
279 *buffer++ = (u8)(readl(otp->base + RV1126_OTP_NVM_RDATA) & 0xFF);
280 }
281
282 return 0;
283 }
284
rockchip_otp_read(struct udevice * dev,int offset,void * buf,int size)285 static int rockchip_otp_read(struct udevice *dev, int offset,
286 void *buf, int size)
287 {
288 const struct rockchip_otp_data *data =
289 (void *)dev_get_driver_data(dev);
290 u32 block_start, block_end, block_offset, blocks;
291 u8 *buffer;
292 int ret;
293
294 if (offset < 0 || !buf || size <= 0 || offset + size > data->size)
295 return -EINVAL;
296
297 if (!data->read)
298 return -ENOSYS;
299
300 offset += data->offset;
301
302 if (data->block_size <= 1) {
303 ret = data->read(dev, offset, buf, size);
304 goto done;
305 }
306
307 block_start = offset / data->block_size;
308 block_offset = offset % data->block_size;
309 block_end = DIV_ROUND_UP(offset + size, data->block_size);
310 blocks = block_end - block_start;
311
312 buffer = calloc(blocks, data->block_size);
313 if (!buffer)
314 return -ENOMEM;
315
316 ret = data->read(dev, block_start, buffer, blocks);
317 if (!ret)
318 memcpy(buf, buffer + block_offset, size);
319
320 free(buffer);
321
322 done:
323 return ret < 0 ? ret : size;
324 }
325
326 static const struct misc_ops rockchip_otp_ops = {
327 .read = rockchip_otp_read,
328 };
329
rockchip_otp_of_to_plat(struct udevice * dev)330 static int rockchip_otp_of_to_plat(struct udevice *dev)
331 {
332 struct rockchip_otp_plat *plat = dev_get_plat(dev);
333
334 plat->base = dev_read_addr_ptr(dev);
335
336 return 0;
337 }
338
rockchip_otp_probe(struct udevice * dev)339 static int rockchip_otp_probe(struct udevice *dev)
340 {
341 struct rockchip_otp_data *data;
342
343 data = (struct rockchip_otp_data *)dev_get_driver_data(dev);
344 if (!data)
345 return -EINVAL;
346
347 if (data->init)
348 return data->init(dev);
349
350 return 0;
351 }
352
353 static const struct rockchip_otp_data px30_data = {
354 .read = rockchip_px30_otp_read,
355 .size = 0x40,
356 };
357
358 static const struct rockchip_otp_data rk3568_data = {
359 .read = rockchip_rk3568_otp_read,
360 .size = 0x80,
361 .block_size = 2,
362 };
363
364 static const struct rockchip_otp_data rk3576_data = {
365 .read = rockchip_rk3588_otp_read,
366 .offset = 0x700,
367 .size = 0x100,
368 .block_size = 4,
369 };
370
371 static const struct rockchip_otp_data rk3588_data = {
372 .read = rockchip_rk3588_otp_read,
373 .offset = 0xC00,
374 .size = 0x400,
375 .block_size = 4,
376 };
377
378 static const struct rockchip_otp_data rv1126_data = {
379 .init = rockchip_rv1126_otp_init,
380 .read = rockchip_rv1126_otp_read,
381 .size = 0x40,
382 };
383
384 static const struct udevice_id rockchip_otp_ids[] = {
385 {
386 .compatible = "rockchip,px30-otp",
387 .data = (ulong)&px30_data,
388 },
389 {
390 .compatible = "rockchip,rk3308-otp",
391 .data = (ulong)&px30_data,
392 },
393 {
394 .compatible = "rockchip,rk3528-otp",
395 .data = (ulong)&rk3568_data,
396 },
397 {
398 .compatible = "rockchip,rk3568-otp",
399 .data = (ulong)&rk3568_data,
400 },
401 {
402 .compatible = "rockchip,rk3576-otp",
403 .data = (ulong)&rk3576_data,
404 },
405 {
406 .compatible = "rockchip,rk3588-otp",
407 .data = (ulong)&rk3588_data,
408 },
409 {
410 .compatible = "rockchip,rv1126-otp",
411 .data = (ulong)&rv1126_data,
412 },
413 {}
414 };
415
416 U_BOOT_DRIVER(rockchip_otp) = {
417 .name = "rockchip_otp",
418 .id = UCLASS_MISC,
419 .of_match = rockchip_otp_ids,
420 .of_to_plat = rockchip_otp_of_to_plat,
421 .plat_auto = sizeof(struct rockchip_otp_plat),
422 .ops = &rockchip_otp_ops,
423 .probe = rockchip_otp_probe,
424 };
425