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