xref: /rk3399_rockchip-uboot/drivers/misc/rockchip-otp.c (revision 2b4182c1edaf1bfb2e4b0fb60381ba7dbb2e6a60)
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 static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp,
56 				    u32 flag)
57 {
58 	int delay = OTPC_TIMEOUT;
59 
60 	while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) {
61 		udelay(1);
62 		delay--;
63 		if (delay <= 0) {
64 			printf("%s: wait init status timeout\n", __func__);
65 			return -ETIMEDOUT;
66 		}
67 	}
68 
69 	/* clean int status */
70 	writel(flag, otp->base + OTPC_INT_STATUS);
71 
72 	return 0;
73 }
74 
75 static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp,
76 				   bool enable)
77 {
78 	int ret = 0;
79 
80 	writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
81 	       otp->base + OTPC_SBPI_CTRL);
82 
83 	writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
84 	writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
85 	       otp->base + OTPC_SBPI_CMD0_OFFSET);
86 	if (enable)
87 		writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
88 	else
89 		writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
90 
91 	writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
92 
93 	ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
94 	if (ret < 0)
95 		printf("%s timeout during ecc_enable\n", __func__);
96 
97 	return ret;
98 }
99 
100 static int rockchip_px30_otp_read(struct udevice *dev, int offset,
101 				  void *buf, int size)
102 {
103 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
104 	u8 *buffer = buf;
105 	int ret = 0;
106 
107 	ret = rockchip_otp_ecc_enable(otp, false);
108 	if (ret < 0) {
109 		printf("%s rockchip_otp_ecc_enable err\n", __func__);
110 		return ret;
111 	}
112 
113 	writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
114 	udelay(5);
115 	while (size--) {
116 		writel(offset++ | OTPC_USER_ADDR_MASK,
117 		       otp->base + OTPC_USER_ADDR);
118 		writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
119 		       otp->base + OTPC_USER_ENABLE);
120 		ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
121 		if (ret < 0) {
122 			printf("%s timeout during read setup\n", __func__);
123 			goto read_end;
124 		}
125 		*buffer++ = readb(otp->base + OTPC_USER_Q);
126 	}
127 
128 read_end:
129 	writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
130 
131 	return ret;
132 }
133 
134 static int rockchip_otp_read(struct udevice *dev, int offset,
135 			     void *buf, int size)
136 {
137 	OTP_READ otp_read = NULL;
138 
139 	otp_read = (OTP_READ)dev_get_driver_data(dev);
140 	if (!otp_read)
141 		return -ENOSYS;
142 
143 	return (*otp_read)(dev, offset, buf, size);
144 }
145 
146 static const struct misc_ops rockchip_otp_ops = {
147 	.read = rockchip_otp_read,
148 };
149 
150 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev)
151 {
152 	struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
153 
154 	otp->base = dev_read_addr_ptr(dev);
155 
156 	return 0;
157 }
158 
159 static const struct udevice_id rockchip_otp_ids[] = {
160 	{
161 		.compatible = "rockchip,px30-otp",
162 		.data = (ulong)&rockchip_px30_otp_read,
163 	},
164 	{
165 		.compatible = "rockchip,rk3308-otp",
166 		.data = (ulong)&rockchip_px30_otp_read,
167 	},
168 	{}
169 };
170 
171 U_BOOT_DRIVER(rockchip_otp) = {
172 	.name = "rockchip_otp",
173 	.id = UCLASS_MISC,
174 	.of_match = rockchip_otp_ids,
175 	.ops = &rockchip_otp_ops,
176 	.ofdata_to_platdata = rockchip_otp_ofdata_to_platdata,
177 	.platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata),
178 };
179