xref: /rk3399_rockchip-uboot/drivers/misc/rockchip-efuse.c (revision 2b4182c1edaf1bfb2e4b0fb60381ba7dbb2e6a60)
1 /*
2  * eFuse driver for Rockchip devices
3  *
4  * Copyright 2017, Theobroma Systems Design und Consulting GmbH
5  * Written by Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
6  *
7  * SPDX-License-Identifier:	GPL-2.0+
8  */
9 
10 #include <common.h>
11 #include <asm/io.h>
12 #include <command.h>
13 #include <display_options.h>
14 #include <dm.h>
15 #include <linux/bitops.h>
16 #include <linux/delay.h>
17 #include <misc.h>
18 
19 #define T_CSB_P_S		0
20 #define T_PGENB_P_S		0
21 #define T_LOAD_P_S		0
22 #define T_ADDR_P_S		0
23 #define T_STROBE_P_S		(0 + 110) /* 1.1us */
24 #define T_CSB_P_L		(0 + 110 + 1000 + 20) /* 200ns */
25 #define T_PGENB_P_L		(0 + 110 + 1000 + 20)
26 #define T_LOAD_P_L		(0 + 110 + 1000 + 20)
27 #define T_ADDR_P_L		(0 + 110 + 1000 + 20)
28 #define T_STROBE_P_L		(0 + 110 + 1000) /* 10us */
29 #define T_CSB_R_S		0
30 #define T_PGENB_R_S		0
31 #define T_LOAD_R_S		0
32 #define T_ADDR_R_S		2
33 #define T_STROBE_R_S		(2 + 3)
34 #define T_CSB_R_L		(2 + 3 + 3 + 3)
35 #define T_PGENB_R_L		(2 + 3 + 3 + 3)
36 #define T_LOAD_R_L		(2 + 3 + 3 + 3)
37 #define T_ADDR_R_L		(2 + 3 + 3 + 2)
38 #define T_STROBE_R_L		(2 + 3 + 3)
39 
40 #define T_CSB_P			0x28
41 #define T_PGENB_P		0x2c
42 #define T_LOAD_P		0x30
43 #define T_ADDR_P		0x34
44 #define T_STROBE_P		0x38
45 #define T_CSB_R			0x3c
46 #define T_PGENB_R		0x40
47 #define T_LOAD_R		0x44
48 #define T_ADDR_R		0x48
49 #define T_STROBE_R		0x4c
50 
51 #define RK1808_USER_MODE	BIT(0)
52 #define RK1808_INT_FINISH	BIT(0)
53 #define RK1808_AUTO_ENB		BIT(0)
54 #define RK1808_AUTO_RD		BIT(1)
55 #define RK1808_A_SHIFT		16
56 #define RK1808_A_MASK		0x3ff
57 #define RK1808_NBYTES		4
58 
59 #define RK3399_A_SHIFT          16
60 #define RK3399_A_MASK           0x3ff
61 #define RK3399_NFUSES           32
62 #define RK3399_BYTES_PER_FUSE   4
63 #define RK3399_STROBSFTSEL      BIT(9)
64 #define RK3399_RSB              BIT(7)
65 #define RK3399_PD               BIT(5)
66 #define RK3399_PGENB            BIT(3)
67 #define RK3399_LOAD             BIT(2)
68 #define RK3399_STROBE           BIT(1)
69 #define RK3399_CSB              BIT(0)
70 
71 #define RK3288_A_SHIFT          6
72 #define RK3288_A_MASK           0x3ff
73 #define RK3288_NFUSES           32
74 #define RK3288_BYTES_PER_FUSE   1
75 #define RK3288_PGENB            BIT(3)
76 #define RK3288_LOAD             BIT(2)
77 #define RK3288_STROBE           BIT(1)
78 #define RK3288_CSB              BIT(0)
79 
80 #define RK3328_INT_STATUS	0x0018
81 #define RK3328_DOUT		0x0020
82 #define RK3328_AUTO_CTRL	0x0024
83 #define RK3328_INT_FINISH	BIT(0)
84 #define RK3328_AUTO_ENB		BIT(0)
85 #define RK3328_AUTO_RD		BIT(1)
86 
87 typedef int (*EFUSE_READ)(struct udevice *dev, int offset, void *buf, int size);
88 
89 struct rockchip_efuse_regs {
90 	u32 ctrl;      /* 0x00  efuse control register */
91 	u32 dout;      /* 0x04  efuse data out register */
92 	u32 rf;        /* 0x08  efuse redundancy bit used register */
93 	u32 _rsvd0;
94 	u32 jtag_pass; /* 0x10  JTAG password */
95 	u32 strobe_finish_ctrl;
96 		       /* 0x14	efuse strobe finish control register */
97 	u32 int_status;/* 0x18 */
98 	u32 reserved;  /* 0x1c */
99 	u32 dout2;     /* 0x20 */
100 	u32 auto_ctrl; /* 0x24 */
101 };
102 
103 struct rockchip_efuse_platdata {
104 	void __iomem *base;
105 	struct clk *clk;
106 };
107 
108 static void rk1808_efuse_timing_init(void __iomem *base)
109 {
110 	static bool init;
111 
112 	if (init)
113 		return;
114 
115 	/* enable auto mode */
116 	writel(readl(base) & (~RK1808_USER_MODE), base);
117 
118 	/* setup efuse timing */
119 	writel((T_CSB_P_S << 16) | T_CSB_P_L, base + T_CSB_P);
120 	writel((T_PGENB_P_S << 16) | T_PGENB_P_L, base + T_PGENB_P);
121 	writel((T_LOAD_P_S << 16) | T_LOAD_P_L, base + T_LOAD_P);
122 	writel((T_ADDR_P_S << 16) | T_ADDR_P_L, base + T_ADDR_P);
123 	writel((T_STROBE_P_S << 16) | T_STROBE_P_L, base + T_STROBE_P);
124 	writel((T_CSB_R_S << 16) | T_CSB_R_L, base + T_CSB_R);
125 	writel((T_PGENB_R_S << 16) | T_PGENB_R_L, base + T_PGENB_R);
126 	writel((T_LOAD_R_S << 16) | T_LOAD_R_L, base + T_LOAD_R);
127 	writel((T_ADDR_R_S << 16) | T_ADDR_R_L, base + T_ADDR_R);
128 	writel((T_STROBE_R_S << 16) | T_STROBE_R_L, base + T_STROBE_R);
129 
130 	init = true;
131 }
132 
133 static int rockchip_rk1808_efuse_read(struct udevice *dev, int offset,
134 				      void *buf, int size)
135 {
136 	struct rockchip_efuse_platdata *plat = dev_get_platdata(dev);
137 	struct rockchip_efuse_regs *efuse =
138 		(struct rockchip_efuse_regs *)plat->base;
139 	unsigned int addr_start, addr_end, addr_offset, addr_len;
140 	u32 out_value, status;
141 	u8 *buffer;
142 	int ret = 0, i = 0;
143 
144 	rk1808_efuse_timing_init(plat->base);
145 
146 	addr_start = rounddown(offset, RK1808_NBYTES) / RK1808_NBYTES;
147 	addr_end = roundup(offset + size, RK1808_NBYTES) / RK1808_NBYTES;
148 	addr_offset = offset % RK1808_NBYTES;
149 	addr_len = addr_end - addr_start;
150 
151 	buffer = calloc(1, sizeof(*buffer) * addr_len * RK1808_NBYTES);
152 	if (!buffer)
153 		return -ENOMEM;
154 
155 	while (addr_len--) {
156 		writel(RK1808_AUTO_RD | RK1808_AUTO_ENB |
157 		       ((addr_start++ & RK1808_A_MASK) << RK1808_A_SHIFT),
158 		       &efuse->auto_ctrl);
159 		udelay(2);
160 		status = readl(&efuse->int_status);
161 		if (!(status & RK1808_INT_FINISH)) {
162 			ret = -EIO;
163 			goto err;
164 		}
165 		out_value = readl(&efuse->dout2);
166 		writel(RK1808_INT_FINISH, &efuse->int_status);
167 
168 		memcpy(&buffer[i], &out_value, RK1808_NBYTES);
169 		i += RK1808_NBYTES;
170 	}
171 	memcpy(buf, buffer + addr_offset, size);
172 err:
173 	kfree(buffer);
174 
175 	return ret;
176 }
177 
178 static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset,
179 				      void *buf, int size)
180 {
181 	struct rockchip_efuse_platdata *plat = dev_get_platdata(dev);
182 	struct rockchip_efuse_regs *efuse =
183 		(struct rockchip_efuse_regs *)plat->base;
184 
185 	unsigned int addr_start, addr_end, addr_offset;
186 	u32 out_value;
187 	u8  bytes[RK3399_NFUSES * RK3399_BYTES_PER_FUSE];
188 	int i = 0;
189 	u32 addr;
190 
191 	addr_start = offset / RK3399_BYTES_PER_FUSE;
192 	addr_offset = offset % RK3399_BYTES_PER_FUSE;
193 	addr_end = DIV_ROUND_UP(offset + size, RK3399_BYTES_PER_FUSE);
194 
195 	/* cap to the size of the efuse block */
196 	if (addr_end > RK3399_NFUSES)
197 		addr_end = RK3399_NFUSES;
198 
199 	writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB,
200 	       &efuse->ctrl);
201 	udelay(1);
202 	for (addr = addr_start; addr < addr_end; addr++) {
203 		setbits_le32(&efuse->ctrl,
204 			     RK3399_STROBE | (addr << RK3399_A_SHIFT));
205 		udelay(1);
206 		out_value = readl(&efuse->dout);
207 		clrbits_le32(&efuse->ctrl, RK3399_STROBE);
208 		udelay(1);
209 
210 		memcpy(&bytes[i], &out_value, RK3399_BYTES_PER_FUSE);
211 		i += RK3399_BYTES_PER_FUSE;
212 	}
213 
214 	/* Switch to standby mode */
215 	writel(RK3399_PD | RK3399_CSB, &efuse->ctrl);
216 
217 	memcpy(buf, bytes + addr_offset, size);
218 
219 	return 0;
220 }
221 
222 static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset,
223 				      void *buf, int size)
224 {
225 	struct rockchip_efuse_platdata *plat = dev_get_platdata(dev);
226 	struct rockchip_efuse_regs *efuse =
227 		(struct rockchip_efuse_regs *)plat->base;
228 	u8 *buffer = buf;
229 	int max_size = RK3288_NFUSES * RK3288_BYTES_PER_FUSE;
230 
231 	if (size > (max_size - offset))
232 		size = max_size - offset;
233 
234 	/* Switch to read mode */
235 	writel(RK3288_LOAD | RK3288_PGENB, &efuse->ctrl);
236 	udelay(1);
237 
238 	while (size--) {
239 		writel(readl(&efuse->ctrl) &
240 				(~(RK3288_A_MASK << RK3288_A_SHIFT)),
241 				&efuse->ctrl);
242 		/* set addr */
243 		writel(readl(&efuse->ctrl) |
244 				((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
245 				&efuse->ctrl);
246 		udelay(1);
247 		/* strobe low to high */
248 		writel(readl(&efuse->ctrl) |
249 				RK3288_STROBE, &efuse->ctrl);
250 		ndelay(60);
251 		/* read data */
252 		*buffer++ = readl(&efuse->dout);
253 		/* reset strobe to low */
254 		writel(readl(&efuse->ctrl) &
255 				(~RK3288_STROBE), &efuse->ctrl);
256 		udelay(1);
257 	}
258 
259 	/* Switch to standby mode */
260 	writel(RK3288_PGENB | RK3288_CSB, &efuse->ctrl);
261 
262 	return 0;
263 }
264 
265 static int rockchip_rk3328_efuse_read(struct udevice *dev, int offset,
266 				      void *buf, int size)
267 {
268 	struct rockchip_efuse_platdata *plat = dev_get_platdata(dev);
269 	struct rockchip_efuse_regs *efuse =
270 		(struct rockchip_efuse_regs *)plat->base;
271 	unsigned int addr_start, addr_end, addr_offset, addr_len;
272 	u32 out_value, status;
273 	u8 *buffer;
274 	int ret = 0, i = 0, j = 0;
275 
276 	/* Max non-secure Byte */
277 	if (size > 32)
278 		size = 32;
279 
280 	/* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */
281 	offset += 96;
282 	addr_start = rounddown(offset, RK3399_BYTES_PER_FUSE) /
283 						RK3399_BYTES_PER_FUSE;
284 	addr_end = roundup(offset + size, RK3399_BYTES_PER_FUSE) /
285 						RK3399_BYTES_PER_FUSE;
286 	addr_offset = offset % RK3399_BYTES_PER_FUSE;
287 	addr_len = addr_end - addr_start;
288 
289 	buffer = calloc(1, sizeof(*buffer) * addr_len * RK3399_BYTES_PER_FUSE);
290 	if (!buffer)
291 		return -ENOMEM;
292 
293 	for (j = 0; j < addr_len; j++) {
294 		writel(RK3328_AUTO_RD | RK3328_AUTO_ENB |
295 		       ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT),
296 		         &efuse->auto_ctrl);
297 		udelay(5);
298 		status = readl(&efuse->int_status);
299 		if (!(status & RK3328_INT_FINISH)) {
300 			ret = -EIO;
301 			goto err;
302 		}
303 		out_value = readl(&efuse->dout2);
304 		writel(RK3328_INT_FINISH, &efuse->int_status);
305 
306 		memcpy(&buffer[i], &out_value, RK3399_BYTES_PER_FUSE);
307 		i += RK3399_BYTES_PER_FUSE;
308 	}
309 	memcpy(buf, buffer + addr_offset, size);
310 err:
311 	free(buffer);
312 
313 	return ret;
314 }
315 
316 static int rockchip_efuse_read(struct udevice *dev, int offset,
317 			       void *buf, int size)
318 {
319 	EFUSE_READ efuse_read = NULL;
320 
321 	efuse_read = (EFUSE_READ)dev_get_driver_data(dev);
322 	if (!efuse_read)
323 		return -ENOSYS;
324 
325 	return (*efuse_read)(dev, offset, buf, size);
326 }
327 
328 static const struct misc_ops rockchip_efuse_ops = {
329 	.read = rockchip_efuse_read,
330 };
331 
332 static int rockchip_efuse_ofdata_to_platdata(struct udevice *dev)
333 {
334 	struct rockchip_efuse_platdata *plat = dev_get_platdata(dev);
335 
336 	plat->base = dev_read_addr_ptr(dev);
337 	return 0;
338 }
339 
340 static const struct udevice_id rockchip_efuse_ids[] = {
341 	{
342 		.compatible = "rockchip,rk1808-efuse",
343 		.data = (ulong)&rockchip_rk1808_efuse_read,
344 	},
345 	{
346 		.compatible = "rockchip,rockchip-efuse",
347 		.data = (ulong)&rockchip_rk3288_efuse_read,
348 	},
349 	{
350 		.compatible = "rockchip,rk3066a-efuse",
351 		.data = (ulong)&rockchip_rk3288_efuse_read,
352 	},
353 	{
354 		.compatible = "rockchip,rk3188-efuse",
355 		.data = (ulong)&rockchip_rk3288_efuse_read,
356 	},
357 	{
358 		.compatible = "rockchip,rk322x-efuse",
359 		.data = (ulong)&rockchip_rk3288_efuse_read,
360 	},
361 	{
362 		.compatible = "rockchip,rk3328-efuse",
363 		.data = (ulong)&rockchip_rk3328_efuse_read,
364 	},
365 	{
366 		.compatible = "rockchip,rk3399-efuse",
367 		.data = (ulong)&rockchip_rk3399_efuse_read,
368 	},
369 	{}
370 };
371 
372 U_BOOT_DRIVER(rockchip_efuse) = {
373 	.name = "rockchip_efuse",
374 	.id = UCLASS_MISC,
375 	.of_match = rockchip_efuse_ids,
376 	.ofdata_to_platdata = rockchip_efuse_ofdata_to_platdata,
377 	.platdata_auto_alloc_size = sizeof(struct rockchip_efuse_platdata),
378 	.ops = &rockchip_efuse_ops,
379 };
380