xref: /rk3399_rockchip-uboot/drivers/misc/rockchip-otp.c (revision 5a94b26492fd3ad20c580976e18e101b67d14e6e)
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 
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 
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 
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 
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 
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 
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 
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 
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, false);
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 
282 static int rockchip_rv1126_otp_init(struct udevice *dev)
283 {
284 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
285 	u32 status = 0;
286 	int ret;
287 
288 	writel(0x0, otp->base + RV1126_OTP_NVM_CEB);
289 	ret = readl_poll_timeout(otp->base + RV1126_OTP_NVM_ST, status,
290 				 status & 0x1, OTPC_TIMEOUT);
291 	if (ret < 0) {
292 		printf("%s timeout during set ceb\n", __func__);
293 		return ret;
294 	}
295 
296 	writel(0x1, otp->base + RV1126_OTP_NVM_RSTB);
297 	ret = readl_poll_timeout(otp->base + RV1126_OTP_NVM_ST, status,
298 				 status & 0x4, OTPC_TIMEOUT);
299 	if (ret < 0) {
300 		printf("%s timeout during set rstb\n", __func__);
301 		return ret;
302 	}
303 
304 	return 0;
305 }
306 
307 static int rockchip_rv1126_otp_read(struct udevice *dev, int offset, void *buf,
308 				    int size)
309 {
310 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
311 	u32 status = 0;
312 	u8 *buffer = buf;
313 	int ret = 0;
314 
315 	while (size--) {
316 		writel(offset++, otp->base + RV1126_OTP_NVM_RADDR);
317 		writel(0x1, otp->base + RV1126_OTP_NVM_RSTART);
318 		ret = readl_poll_timeout(otp->base + RV1126_OTP_READ_ST,
319 					 status, status == 0, OTPC_TIMEOUT);
320 		if (ret < 0) {
321 			printf("%s timeout during read setup\n", __func__);
322 			return ret;
323 		}
324 
325 		*buffer++ = readb(otp->base + RV1126_OTP_NVM_RDATA);
326 	}
327 
328 	return 0;
329 }
330 
331 static int rockchip_otp_read(struct udevice *dev, int offset,
332 			     void *buf, int size)
333 {
334 	struct otp_data *data;
335 
336 	data = (struct otp_data *)dev_get_driver_data(dev);
337 	if (!data)
338 		return -ENOSYS;
339 
340 	if (soc_is_rk3308bs())
341 		return rockchip_rk3308bs_otp_read(dev, offset, buf, size);
342 
343 	return data->read(dev, offset, buf, size);
344 }
345 
346 static const struct misc_ops rockchip_otp_ops = {
347 	.read = rockchip_otp_read,
348 };
349 
350 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev)
351 {
352 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
353 
354 	otp->base = dev_read_addr_ptr(dev);
355 
356 	return 0;
357 }
358 
359 static int rockchip_otp_probe(struct udevice *dev)
360 {
361 	struct otp_data *data;
362 
363 	data = (struct otp_data *)dev_get_driver_data(dev);
364 	if (!data)
365 		return -EINVAL;
366 
367 	if (data->init)
368 		return data->init(dev);
369 
370 	return 0;
371 }
372 
373 static const struct otp_data px30_data = {
374 	.read = rockchip_px30_otp_read,
375 };
376 
377 static const struct otp_data rk3308bs_data = {
378 	.read = rockchip_rk3308bs_otp_read,
379 };
380 
381 static const struct otp_data rk3568_data = {
382 	.read = rockchip_rk3568_otp_read,
383 };
384 
385 static const struct otp_data rv1126_data = {
386 	.init = rockchip_rv1126_otp_init,
387 	.read = rockchip_rv1126_otp_read,
388 };
389 
390 static const struct udevice_id rockchip_otp_ids[] = {
391 	{
392 		.compatible = "rockchip,px30-otp",
393 		.data = (ulong)&px30_data,
394 	},
395 	{
396 		.compatible = "rockchip,rk3308-otp",
397 		.data = (ulong)&px30_data,
398 	},
399 	{
400 		.compatible = "rockchip,rk3308bs-otp",
401 		.data = (ulong)&rk3308bs_data,
402 	},
403 	{
404 		.compatible = "rockchip,rk3568-otp",
405 		.data = (ulong)&rk3568_data,
406 	},
407 	{
408 		.compatible = "rockchip,rv1126-otp",
409 		.data = (ulong)&rv1126_data,
410 	},
411 	{}
412 };
413 
414 U_BOOT_DRIVER(rockchip_otp) = {
415 	.name = "rockchip_otp",
416 	.id = UCLASS_MISC,
417 	.of_match = rockchip_otp_ids,
418 	.ops = &rockchip_otp_ops,
419 	.ofdata_to_platdata = rockchip_otp_ofdata_to_platdata,
420 	.platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata),
421 	.probe = rockchip_otp_probe,
422 };
423