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