xref: /rk3399_rockchip-uboot/drivers/misc/rockchip-otp.c (revision 2ba7147f8008e675b31a0a5c13b8366431ea09ae)
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/io.h>
8 #include <command.h>
9 #include <dm.h>
10 #include <linux/bitops.h>
11 #include <linux/delay.h>
12 #include <misc.h>
13 
14 /* OTP Register Offsets */
15 #define OTPC_SBPI_CTRL			0x0020
16 #define OTPC_SBPI_CMD_VALID_PRE		0x0024
17 #define OTPC_SBPI_CS_VALID_PRE		0x0028
18 #define OTPC_SBPI_STATUS		0x002C
19 #define OTPC_USER_CTRL			0x0100
20 #define OTPC_USER_ADDR			0x0104
21 #define OTPC_USER_ENABLE		0x0108
22 #define OTPC_USER_Q			0x0124
23 #define OTPC_INT_STATUS			0x0304
24 #define OTPC_SBPI_CMD0_OFFSET		0x1000
25 #define OTPC_SBPI_CMD1_OFFSET		0x1004
26 
27 /* OTP Register bits and masks */
28 #define OTPC_USER_ADDR_MASK		GENMASK(31, 16)
29 #define OTPC_USE_USER			BIT(0)
30 #define OTPC_USE_USER_MASK		GENMASK(16, 16)
31 #define OTPC_USER_FSM_ENABLE		BIT(0)
32 #define OTPC_USER_FSM_ENABLE_MASK	GENMASK(16, 16)
33 #define OTPC_SBPI_DONE			BIT(1)
34 #define OTPC_USER_DONE			BIT(2)
35 
36 #define SBPI_DAP_ADDR			0x02
37 #define SBPI_DAP_ADDR_SHIFT		8
38 #define SBPI_DAP_ADDR_MASK		GENMASK(31, 24)
39 #define SBPI_CMD_VALID_MASK		GENMASK(31, 16)
40 #define SBPI_DAP_CMD_WRF		0xC0
41 #define SBPI_DAP_REG_ECC		0x3A
42 #define SBPI_ECC_ENABLE			0x00
43 #define SBPI_ECC_DISABLE		0x09
44 #define SBPI_ENABLE			BIT(0)
45 #define SBPI_ENABLE_MASK		GENMASK(16, 16)
46 
47 #define OTPC_TIMEOUT			10000
48 
49 typedef int (*OTP_READ)(struct udevice *dev, int offset, void *buf, int size);
50 
51 struct rockchip_otp_platdata {
52 	void __iomem *base;
53 };
54 
55 #if defined(DEBUG)
56 static int dump_otps(cmd_tbl_t *cmdtp, int flag,
57 		     int argc, char * const argv[])
58 {
59 	struct udevice *dev;
60 	u8 otps[64] = {0};
61 	int ret;
62 
63 	/* retrieve the device */
64 	ret = uclass_get_device_by_driver(UCLASS_MISC,
65 					  DM_GET_DRIVER(rockchip_otp), &dev);
66 	if (ret) {
67 		printf("%s: no misc-device found\n", __func__);
68 		return 0;
69 	}
70 
71 	ret = misc_read(dev, 0, &otps, sizeof(otps));
72 	if (ret) {
73 		printf("%s: misc_read failed\n", __func__);
74 		return 0;
75 	}
76 
77 	printf("otp-contents:\n");
78 	print_buffer(0, otps, 1, 64, 16);
79 
80 	return 0;
81 }
82 
83 U_BOOT_CMD(
84 	rockchip_dump_otps, 1, 1, dump_otps,
85 	"Dump the content of the otps",
86 	""
87 );
88 #endif
89 
90 static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp,
91 				    u32 flag)
92 {
93 	int delay = OTPC_TIMEOUT;
94 
95 	while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) {
96 		udelay(1);
97 		delay--;
98 		if (delay <= 0) {
99 			printf("%s: wait init status timeout\n", __func__);
100 			return -ETIMEDOUT;
101 		}
102 	}
103 
104 	/* clean int status */
105 	writel(flag, otp->base + OTPC_INT_STATUS);
106 
107 	return 0;
108 }
109 
110 static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp,
111 				   bool enable)
112 {
113 	int ret = 0;
114 
115 	writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
116 	       otp->base + OTPC_SBPI_CTRL);
117 
118 	writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
119 	writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
120 	       otp->base + OTPC_SBPI_CMD0_OFFSET);
121 	if (enable)
122 		writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
123 	else
124 		writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
125 
126 	writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
127 
128 	ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
129 	if (ret < 0)
130 		printf("%s timeout during ecc_enable\n", __func__);
131 
132 	return ret;
133 }
134 
135 static int rockchip_px30_otp_read(struct udevice *dev, int offset,
136 				  void *buf, int size)
137 {
138 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
139 	u8 *buffer = buf;
140 	int ret = 0;
141 
142 	ret = rockchip_otp_ecc_enable(otp, false);
143 	if (ret < 0) {
144 		printf("%s rockchip_otp_ecc_enable err\n", __func__);
145 		return ret;
146 	}
147 
148 	writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
149 	udelay(5);
150 	while (size--) {
151 		writel(offset++ | OTPC_USER_ADDR_MASK,
152 		       otp->base + OTPC_USER_ADDR);
153 		writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
154 		       otp->base + OTPC_USER_ENABLE);
155 		ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
156 		if (ret < 0) {
157 			printf("%s timeout during read setup\n", __func__);
158 			goto read_end;
159 		}
160 		*buffer++ = readb(otp->base + OTPC_USER_Q);
161 	}
162 
163 read_end:
164 	writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
165 
166 	return ret;
167 }
168 
169 static int rockchip_otp_read(struct udevice *dev, int offset,
170 			     void *buf, int size)
171 {
172 	OTP_READ otp_read = NULL;
173 
174 	otp_read = (OTP_READ)dev_get_driver_data(dev);
175 	if (!otp_read)
176 		return -ENOSYS;
177 
178 	return (*otp_read)(dev, offset, buf, size);
179 }
180 
181 static const struct misc_ops rockchip_otp_ops = {
182 	.read = rockchip_otp_read,
183 };
184 
185 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev)
186 {
187 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
188 
189 	otp->base = dev_read_addr_ptr(dev);
190 
191 	return 0;
192 }
193 
194 static const struct udevice_id rockchip_otp_ids[] = {
195 	{
196 		.compatible = "rockchip,px30-otp",
197 		.data = (ulong)&rockchip_px30_otp_read,
198 	},
199 	{
200 		.compatible = "rockchip,rk3308-otp",
201 		.data = (ulong)&rockchip_px30_otp_read,
202 	},
203 	{}
204 };
205 
206 U_BOOT_DRIVER(rockchip_otp) = {
207 	.name = "rockchip_otp",
208 	.id = UCLASS_MISC,
209 	.of_match = rockchip_otp_ids,
210 	.ops = &rockchip_otp_ops,
211 	.ofdata_to_platdata = rockchip_otp_ofdata_to_platdata,
212 	.platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata),
213 };
214