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