xref: /rk3399_ARM-atf/plat/rockchip/rk3568/drivers/otp/otp.c (revision 4e1ccc60ea47b889e704c7d7f0301ad986e40893)
1*4e1ccc60SShengfei Xu /*
2*4e1ccc60SShengfei Xu  * Copyright (c) 2024-2025, Rockchip Electronics Co., Ltd. All rights reserved..
3*4e1ccc60SShengfei Xu  *
4*4e1ccc60SShengfei Xu  * SPDX-License-Identifier: BSD-3-Clause
5*4e1ccc60SShengfei Xu  */
6*4e1ccc60SShengfei Xu 
7*4e1ccc60SShengfei Xu #include <common/debug.h>
8*4e1ccc60SShengfei Xu #include <drivers/delay_timer.h>
9*4e1ccc60SShengfei Xu 
10*4e1ccc60SShengfei Xu #include "otp.h"
11*4e1ccc60SShengfei Xu #include <plat_private.h>
12*4e1ccc60SShengfei Xu #include <platform_def.h>
13*4e1ccc60SShengfei Xu #include <rk3568_clk.h>
14*4e1ccc60SShengfei Xu #include <rk3568_def.h>
15*4e1ccc60SShengfei Xu #include <soc.h>
16*4e1ccc60SShengfei Xu 
17*4e1ccc60SShengfei Xu /* default SBPI_READ mode */
18*4e1ccc60SShengfei Xu #define OTP_USER_READ		0
19*4e1ccc60SShengfei Xu #define USEC_PER_SEC		1000000
20*4e1ccc60SShengfei Xu 
21*4e1ccc60SShengfei Xu enum clk_type {
22*4e1ccc60SShengfei Xu 	PCLK_PHY = 0,
23*4e1ccc60SShengfei Xu 	PCLK_NS,
24*4e1ccc60SShengfei Xu 	PCLK_S,
25*4e1ccc60SShengfei Xu 	CLK_NS_USER,
26*4e1ccc60SShengfei Xu 	CLK_NS_SBPI,
27*4e1ccc60SShengfei Xu 	CLK_S_USER,
28*4e1ccc60SShengfei Xu 	CLK_S_SBPI
29*4e1ccc60SShengfei Xu };
30*4e1ccc60SShengfei Xu 
31*4e1ccc60SShengfei Xu static uint8_t otp_ns_ecc_flag[OTP_NS_BYTE_SIZE / 2];
32*4e1ccc60SShengfei Xu 
33*4e1ccc60SShengfei Xu static uint32_t enable_otp_clk(int clk)
34*4e1ccc60SShengfei Xu {
35*4e1ccc60SShengfei Xu 	uint32_t reg = 0;
36*4e1ccc60SShengfei Xu 
37*4e1ccc60SShengfei Xu 	switch (clk) {
38*4e1ccc60SShengfei Xu 	case CLK_NS_USER:
39*4e1ccc60SShengfei Xu 		reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(26));
40*4e1ccc60SShengfei Xu 		if (reg & CLK_NS_OTP_USER_EN)
41*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26),
42*4e1ccc60SShengfei Xu 				      CLK_NS_OTP_USER_EN << WRITE_MASK);
43*4e1ccc60SShengfei Xu 
44*4e1ccc60SShengfei Xu 		break;
45*4e1ccc60SShengfei Xu 	case CLK_NS_SBPI:
46*4e1ccc60SShengfei Xu 		reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(26));
47*4e1ccc60SShengfei Xu 		if (reg & CLK_NS_OTP_SBPI_EN)
48*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26),
49*4e1ccc60SShengfei Xu 				      CLK_NS_OTP_SBPI_EN << WRITE_MASK);
50*4e1ccc60SShengfei Xu 
51*4e1ccc60SShengfei Xu 		break;
52*4e1ccc60SShengfei Xu 	case PCLK_NS:
53*4e1ccc60SShengfei Xu 		reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(26));
54*4e1ccc60SShengfei Xu 		if (reg & PCLK_NS_OTP_EN)
55*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26),
56*4e1ccc60SShengfei Xu 				      PCLK_NS_OTP_EN << WRITE_MASK);
57*4e1ccc60SShengfei Xu 
58*4e1ccc60SShengfei Xu 		break;
59*4e1ccc60SShengfei Xu 	case PCLK_PHY:
60*4e1ccc60SShengfei Xu 		reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(34));
61*4e1ccc60SShengfei Xu 		if (reg & PCLK_PHY_OTP_EN)
62*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(34),
63*4e1ccc60SShengfei Xu 				      PCLK_PHY_OTP_EN << WRITE_MASK);
64*4e1ccc60SShengfei Xu 
65*4e1ccc60SShengfei Xu 		break;
66*4e1ccc60SShengfei Xu 	case CLK_S_USER:
67*4e1ccc60SShengfei Xu 		reg = mmio_read_32(SCRU_BASE + SCRU_GATE_CON01);
68*4e1ccc60SShengfei Xu 		if (reg & CLK_S_OTP_USER_EN)
69*4e1ccc60SShengfei Xu 			mmio_write_32(SCRU_BASE + SCRU_GATE_CON01,
70*4e1ccc60SShengfei Xu 				      CLK_S_OTP_USER_EN << WRITE_MASK);
71*4e1ccc60SShengfei Xu 
72*4e1ccc60SShengfei Xu 		break;
73*4e1ccc60SShengfei Xu 	case CLK_S_SBPI:
74*4e1ccc60SShengfei Xu 		reg = mmio_read_32(SCRU_BASE + SCRU_GATE_CON01);
75*4e1ccc60SShengfei Xu 		if (reg & CLK_S_OTP_SBPI_EN)
76*4e1ccc60SShengfei Xu 			mmio_write_32(SCRU_BASE + SCRU_GATE_CON01,
77*4e1ccc60SShengfei Xu 				      CLK_S_OTP_SBPI_EN << WRITE_MASK);
78*4e1ccc60SShengfei Xu 
79*4e1ccc60SShengfei Xu 		break;
80*4e1ccc60SShengfei Xu 	case PCLK_S:
81*4e1ccc60SShengfei Xu 		reg = mmio_read_32(SCRU_BASE + SCRU_GATE_CON01);
82*4e1ccc60SShengfei Xu 		if (reg & PCLK_S_OTP_EN)
83*4e1ccc60SShengfei Xu 			mmio_write_32(SCRU_BASE + SCRU_GATE_CON01,
84*4e1ccc60SShengfei Xu 				      PCLK_S_OTP_EN << WRITE_MASK);
85*4e1ccc60SShengfei Xu 
86*4e1ccc60SShengfei Xu 		break;
87*4e1ccc60SShengfei Xu 	default:
88*4e1ccc60SShengfei Xu 		break;
89*4e1ccc60SShengfei Xu 	}
90*4e1ccc60SShengfei Xu 
91*4e1ccc60SShengfei Xu 	return reg;
92*4e1ccc60SShengfei Xu }
93*4e1ccc60SShengfei Xu 
94*4e1ccc60SShengfei Xu static void restore_otp_clk(int clk, uint32_t reg)
95*4e1ccc60SShengfei Xu {
96*4e1ccc60SShengfei Xu 	switch (clk) {
97*4e1ccc60SShengfei Xu 	case CLK_NS_USER:
98*4e1ccc60SShengfei Xu 		if (reg & CLK_NS_OTP_USER_EN)
99*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26),
100*4e1ccc60SShengfei Xu 				      (CLK_NS_OTP_USER_EN << WRITE_MASK) | reg);
101*4e1ccc60SShengfei Xu 		break;
102*4e1ccc60SShengfei Xu 	case CLK_NS_SBPI:
103*4e1ccc60SShengfei Xu 		if (reg & CLK_NS_OTP_SBPI_EN)
104*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26),
105*4e1ccc60SShengfei Xu 				      (CLK_NS_OTP_SBPI_EN << WRITE_MASK) | reg);
106*4e1ccc60SShengfei Xu 		break;
107*4e1ccc60SShengfei Xu 	case PCLK_NS:
108*4e1ccc60SShengfei Xu 		if (reg & PCLK_NS_OTP_EN)
109*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26),
110*4e1ccc60SShengfei Xu 				      (PCLK_NS_OTP_EN << WRITE_MASK) | reg);
111*4e1ccc60SShengfei Xu 		break;
112*4e1ccc60SShengfei Xu 	case PCLK_PHY:
113*4e1ccc60SShengfei Xu 		if (reg & PCLK_PHY_OTP_EN)
114*4e1ccc60SShengfei Xu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(34),
115*4e1ccc60SShengfei Xu 				      (PCLK_PHY_OTP_EN << WRITE_MASK) | reg);
116*4e1ccc60SShengfei Xu 		break;
117*4e1ccc60SShengfei Xu 	case CLK_S_USER:
118*4e1ccc60SShengfei Xu 		if (reg & CLK_S_OTP_USER_EN)
119*4e1ccc60SShengfei Xu 			mmio_write_32(SCRU_BASE + SCRU_GATE_CON01,
120*4e1ccc60SShengfei Xu 				      (CLK_S_OTP_USER_EN << WRITE_MASK) | reg);
121*4e1ccc60SShengfei Xu 		break;
122*4e1ccc60SShengfei Xu 	case CLK_S_SBPI:
123*4e1ccc60SShengfei Xu 		if (reg & CLK_S_OTP_SBPI_EN)
124*4e1ccc60SShengfei Xu 			mmio_write_32(SCRU_BASE + SCRU_GATE_CON01,
125*4e1ccc60SShengfei Xu 				      (CLK_S_OTP_SBPI_EN << WRITE_MASK) | reg);
126*4e1ccc60SShengfei Xu 		break;
127*4e1ccc60SShengfei Xu 	case PCLK_S:
128*4e1ccc60SShengfei Xu 		if (reg & PCLK_S_OTP_EN)
129*4e1ccc60SShengfei Xu 			mmio_write_32(SCRU_BASE + SCRU_GATE_CON01,
130*4e1ccc60SShengfei Xu 				      (PCLK_S_OTP_EN << WRITE_MASK) | reg);
131*4e1ccc60SShengfei Xu 		break;
132*4e1ccc60SShengfei Xu 	default:
133*4e1ccc60SShengfei Xu 		return;
134*4e1ccc60SShengfei Xu 	}
135*4e1ccc60SShengfei Xu }
136*4e1ccc60SShengfei Xu 
137*4e1ccc60SShengfei Xu static int check_sbpi_done_int(uint32_t otp_base)
138*4e1ccc60SShengfei Xu {
139*4e1ccc60SShengfei Xu 	/* wait max 10ms */
140*4e1ccc60SShengfei Xu 	uint32_t timeout = 10000;
141*4e1ccc60SShengfei Xu 
142*4e1ccc60SShengfei Xu 	while (1) {
143*4e1ccc60SShengfei Xu 		/* check sbpi DONE INT */
144*4e1ccc60SShengfei Xu 		if (((mmio_read_32(otp_base + REG_OTPC_INT_STATUS) >> 1) & 0x01) == 0x01) {
145*4e1ccc60SShengfei Xu 			mmio_write_32(otp_base + REG_OTPC_INT_STATUS,
146*4e1ccc60SShengfei Xu 				      0xffff0002); /* clear sbpi DONE INT */
147*4e1ccc60SShengfei Xu 			break;
148*4e1ccc60SShengfei Xu 		}
149*4e1ccc60SShengfei Xu 
150*4e1ccc60SShengfei Xu 		if (timeout == 0) {
151*4e1ccc60SShengfei Xu 			WARN("---OTP---Check sbpi int done TIMEOUT");
152*4e1ccc60SShengfei Xu 			return -1;
153*4e1ccc60SShengfei Xu 		}
154*4e1ccc60SShengfei Xu 
155*4e1ccc60SShengfei Xu 		timeout--;
156*4e1ccc60SShengfei Xu 		udelay(1);
157*4e1ccc60SShengfei Xu 	}
158*4e1ccc60SShengfei Xu 
159*4e1ccc60SShengfei Xu 	return 0;
160*4e1ccc60SShengfei Xu }
161*4e1ccc60SShengfei Xu 
162*4e1ccc60SShengfei Xu static uint32_t otp_select(uint32_t addr)
163*4e1ccc60SShengfei Xu {
164*4e1ccc60SShengfei Xu 	uint32_t otp_base = 0;
165*4e1ccc60SShengfei Xu 
166*4e1ccc60SShengfei Xu 	if (addr < 0x1c0) {  /* 0-447 otp0 S */
167*4e1ccc60SShengfei Xu 		otp_base = OTP_S_BASE;
168*4e1ccc60SShengfei Xu 		mmio_write_32(SGRF_BASE + SGRF_SOC_CON2,
169*4e1ccc60SShengfei Xu 			      (SGRF_CON_OTP_SECURE << WRITE_MASK) |
170*4e1ccc60SShengfei Xu 			       SGRF_CON_OTP_SECURE); /* secure */
171*4e1ccc60SShengfei Xu 	} else if (addr >= 0x1c0 && addr < 0x200) { /* 448-511 otp0 NS */
172*4e1ccc60SShengfei Xu 		otp_base = OTP_NS_BASE;
173*4e1ccc60SShengfei Xu 		mmio_write_32(SGRF_BASE + SGRF_SOC_CON2,
174*4e1ccc60SShengfei Xu 			      SGRF_CON_OTP_SECURE << WRITE_MASK); /* non secure */
175*4e1ccc60SShengfei Xu 	}
176*4e1ccc60SShengfei Xu 
177*4e1ccc60SShengfei Xu 	return otp_base;
178*4e1ccc60SShengfei Xu }
179*4e1ccc60SShengfei Xu 
180*4e1ccc60SShengfei Xu static int rk_otp_ecc_enable(uint32_t otp_base, bool enable)
181*4e1ccc60SShengfei Xu {
182*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
183*4e1ccc60SShengfei Xu 		      BITS_WITH_WMASK(0x2, 0xffu, SBPI_DEV_ID_SHIFT)); /* device id */
184*4e1ccc60SShengfei Xu 	/* a value define number of sbpi valid command */
185*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, SBPI_VAILI_COMMAND(1));
186*4e1ccc60SShengfei Xu 	/* SBPI_CMD will be programmable from offset 0x1000 to 0x2000,
187*4e1ccc60SShengfei Xu 	 * which is 4kBAnd there are 1024 registers totally, which are
188*4e1ccc60SShengfei Xu 	 * correspond to a sertain command.The address of these registers
189*4e1ccc60SShengfei Xu 	 * are: 0x10000x1004...0x1ffc
190*4e1ccc60SShengfei Xu 	 */
191*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(0), 0xfa); /* sbpi cmd */
192*4e1ccc60SShengfei Xu 
193*4e1ccc60SShengfei Xu 	if (enable)
194*4e1ccc60SShengfei Xu 		mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(1),
195*4e1ccc60SShengfei Xu 			      0x00); /* sbpi cmd enable ecc*/
196*4e1ccc60SShengfei Xu 	else
197*4e1ccc60SShengfei Xu 		mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(1),
198*4e1ccc60SShengfei Xu 			      0x09); /* sbpi cmd disable ecc*/
199*4e1ccc60SShengfei Xu 
200*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
201*4e1ccc60SShengfei Xu 		      (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE); /* sbpi enable */
202*4e1ccc60SShengfei Xu 
203*4e1ccc60SShengfei Xu 	if (check_sbpi_done_int(otp_base))
204*4e1ccc60SShengfei Xu 		return -1;
205*4e1ccc60SShengfei Xu 
206*4e1ccc60SShengfei Xu 	return 0;
207*4e1ccc60SShengfei Xu }
208*4e1ccc60SShengfei Xu 
209*4e1ccc60SShengfei Xu static int rk_otp_sbpi_read(uint32_t addr, uint16_t *read_data, bool is_need_ecc)
210*4e1ccc60SShengfei Xu {
211*4e1ccc60SShengfei Xu 	uint32_t otp_base = 0;
212*4e1ccc60SShengfei Xu 	uint32_t otp_qp;
213*4e1ccc60SShengfei Xu 
214*4e1ccc60SShengfei Xu 	otp_base = otp_select(addr);
215*4e1ccc60SShengfei Xu 
216*4e1ccc60SShengfei Xu 	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(28),
217*4e1ccc60SShengfei Xu 		      (OTP_PHY_SRSTN << WRITE_MASK) | OTP_PHY_SRSTN); /* reset otp phy */
218*4e1ccc60SShengfei Xu 	udelay(2);
219*4e1ccc60SShengfei Xu 	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(28),
220*4e1ccc60SShengfei Xu 		      OTP_PHY_SRSTN << WRITE_MASK);
221*4e1ccc60SShengfei Xu 	udelay(1);
222*4e1ccc60SShengfei Xu 
223*4e1ccc60SShengfei Xu 	mmio_write_32(SGRF_BASE + SGRF_SOC_CON2,
224*4e1ccc60SShengfei Xu 		      (SGRF_CON_OTP_CKE << WRITE_MASK) | SGRF_CON_OTP_CKE); /* CKE = 1 */
225*4e1ccc60SShengfei Xu 	udelay(2);
226*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_USER_CTRL, USER_DCTRL << WRITE_MASK);
227*4e1ccc60SShengfei Xu 	udelay(2);
228*4e1ccc60SShengfei Xu 
229*4e1ccc60SShengfei Xu 	rk_otp_ecc_enable(otp_base, is_need_ecc);
230*4e1ccc60SShengfei Xu 
231*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
232*4e1ccc60SShengfei Xu 		      (SBPI_CS_AUTO << WRITE_MASK) | SBPI_CS_AUTO); /* cs auto */
233*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CS_VALID_PRE,
234*4e1ccc60SShengfei Xu 		      0xffff0000); /* cs valid number */
235*4e1ccc60SShengfei Xu 
236*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
237*4e1ccc60SShengfei Xu 		      BITS_WITH_WMASK(0x2, 0xffu, SBPI_DEV_ID_SHIFT)); /* device id */
238*4e1ccc60SShengfei Xu 	/* a value define number of sbpi valid command */
239*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, SBPI_VAILI_COMMAND(2));
240*4e1ccc60SShengfei Xu 	/* SBPI_CMD will be programmable from offset 0x1000 to 0x2000,
241*4e1ccc60SShengfei Xu 	 * which is 4kBAnd there are 1024 registers totally, which are
242*4e1ccc60SShengfei Xu 	 * correspond to a sertain command.The address of these registers
243*4e1ccc60SShengfei Xu 	 * are: 0x10000x1004...0x1ffc
244*4e1ccc60SShengfei Xu 	 */
245*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(0), 0xfc); /* sbpi cmd */
246*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(1), addr & 0xff); /* sbpi cmd 3c addr */
247*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(2),
248*4e1ccc60SShengfei Xu 		      (addr >> 8) & 0xff); /* sbpi cmd 3d addr */
249*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
250*4e1ccc60SShengfei Xu 		      (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE); /* sbpi enable */
251*4e1ccc60SShengfei Xu 
252*4e1ccc60SShengfei Xu 	if (check_sbpi_done_int(otp_base))
253*4e1ccc60SShengfei Xu 		return -1;
254*4e1ccc60SShengfei Xu 
255*4e1ccc60SShengfei Xu 	/* a value define number of sbpi valid command */
256*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, SBPI_VAILI_COMMAND(7));
257*4e1ccc60SShengfei Xu 	/* SBPI_CMD will be programmable from offset 0x1000 to 0x2000,
258*4e1ccc60SShengfei Xu 	 * which is 4kBAnd there are 1024 registers totally, which are
259*4e1ccc60SShengfei Xu 	 * correspond to a sertain command.The address of these registers
260*4e1ccc60SShengfei Xu 	 * are: 0x10000x1004...0x1ffc
261*4e1ccc60SShengfei Xu 	 */
262*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(0), 0x00);
263*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(1), 0x00);
264*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(2), 0x40);
265*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(3), 0x40);
266*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(4), 0x00);
267*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(5), 0x02);
268*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(6), 0x80);
269*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(7), 0x81);
270*4e1ccc60SShengfei Xu 	/* sbpi enable */
271*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
272*4e1ccc60SShengfei Xu 		      (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE);
273*4e1ccc60SShengfei Xu 
274*4e1ccc60SShengfei Xu 	if (check_sbpi_done_int(otp_base))
275*4e1ccc60SShengfei Xu 		return -1;
276*4e1ccc60SShengfei Xu 
277*4e1ccc60SShengfei Xu 	if (is_need_ecc) {
278*4e1ccc60SShengfei Xu 		otp_qp = mmio_read_32(otp_base + REG_OTPC_USER_QP);
279*4e1ccc60SShengfei Xu 		VERBOSE("otp_addr:0x%x, otp_qp:0x%x\n", addr, otp_qp);
280*4e1ccc60SShengfei Xu 		if (((otp_qp & 0xc0) == 0xc0) || (otp_qp & 0x20)) {
281*4e1ccc60SShengfei Xu 			otp_ns_ecc_flag[addr - OTP_S_BYTE_SIZE / 2] = 1;
282*4e1ccc60SShengfei Xu 			ERROR("ecc otp_addr:0x%x, otp_qp failed 0x%x\n", addr, otp_qp);
283*4e1ccc60SShengfei Xu 		}
284*4e1ccc60SShengfei Xu 	}
285*4e1ccc60SShengfei Xu 
286*4e1ccc60SShengfei Xu 	*read_data =
287*4e1ccc60SShengfei Xu 		(uint16_t)mmio_read_32(otp_base + REG_OTPC_SBPI_READ_DATA_BASE + 0x20);
288*4e1ccc60SShengfei Xu 	*read_data +=
289*4e1ccc60SShengfei Xu 		(uint16_t)(mmio_read_32(otp_base + REG_OTPC_SBPI_READ_DATA_BASE + 0x24) << 8);
290*4e1ccc60SShengfei Xu 	 /* a value define number of sbpi valid command */
291*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, SBPI_VAILI_COMMAND(1));
292*4e1ccc60SShengfei Xu 	/* SBPI_CMD will be programmable from offset 0x1000 to 0x2000,
293*4e1ccc60SShengfei Xu 	 * which is 4kBAnd there are 1024 registers totally, which are
294*4e1ccc60SShengfei Xu 	 * correspond to a sertain command.The address of these registers
295*4e1ccc60SShengfei Xu 	 * are: 0x10000x1004...0x1ffc
296*4e1ccc60SShengfei Xu 	 */
297*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(0), 0xa0);
298*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_OFFSET(1), 0x0);
299*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL,
300*4e1ccc60SShengfei Xu 		      (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE);
301*4e1ccc60SShengfei Xu 
302*4e1ccc60SShengfei Xu 	if (check_sbpi_done_int(otp_base))
303*4e1ccc60SShengfei Xu 		return -1;
304*4e1ccc60SShengfei Xu 
305*4e1ccc60SShengfei Xu 	mmio_write_32(otp_base + REG_OTPC_INT_STATUS, 0xffff0003); /* clear sbpi INT */
306*4e1ccc60SShengfei Xu 
307*4e1ccc60SShengfei Xu 	mmio_write_32(SGRF_BASE + SGRF_SOC_CON2,
308*4e1ccc60SShengfei Xu 		      SGRF_CON_OTP_SECURE << WRITE_MASK); /* non secure */
309*4e1ccc60SShengfei Xu 
310*4e1ccc60SShengfei Xu 	return 0;
311*4e1ccc60SShengfei Xu }
312*4e1ccc60SShengfei Xu 
313*4e1ccc60SShengfei Xu int rk_otp_read(uint32_t byte_addr, uint32_t byte_len, uint16_t *buf, bool is_need_ecc)
314*4e1ccc60SShengfei Xu {
315*4e1ccc60SShengfei Xu 	int ret = 0;
316*4e1ccc60SShengfei Xu 	uint32_t i = 0;
317*4e1ccc60SShengfei Xu 	uint32_t clk_ns_user = 0, clk_ns_sbpi = 0, pclk_ns = 0, pclk_phy = 0;
318*4e1ccc60SShengfei Xu 	uint32_t clk_s_user = 0, clk_s_sbpi = 0, pclk_s = 0;
319*4e1ccc60SShengfei Xu 	uint32_t addr, length;
320*4e1ccc60SShengfei Xu 
321*4e1ccc60SShengfei Xu 	/*
322*4e1ccc60SShengfei Xu 	 * RK3568 platform OTP R&W by halfword
323*4e1ccc60SShengfei Xu 	 * Address and Length must be an integral multiple of 2
324*4e1ccc60SShengfei Xu 	 */
325*4e1ccc60SShengfei Xu 	if ((byte_addr % 2) != 0 || (byte_len % 2) != 0) {
326*4e1ccc60SShengfei Xu 		ERROR("byte addr and byte length must be even numbers!");
327*4e1ccc60SShengfei Xu 		return -1;
328*4e1ccc60SShengfei Xu 	}
329*4e1ccc60SShengfei Xu 
330*4e1ccc60SShengfei Xu 	addr = byte_addr / 2;
331*4e1ccc60SShengfei Xu 	length = byte_len / 2;
332*4e1ccc60SShengfei Xu 
333*4e1ccc60SShengfei Xu 	if (addr >= OTP_MAX_SIZE || length <= 0 || length > OTP_MAX_SIZE || !buf)
334*4e1ccc60SShengfei Xu 		return -1;
335*4e1ccc60SShengfei Xu 
336*4e1ccc60SShengfei Xu 	if ((addr + length) > OTP_MAX_SIZE)
337*4e1ccc60SShengfei Xu 		return -1;
338*4e1ccc60SShengfei Xu 
339*4e1ccc60SShengfei Xu 	if (addr < OTP_S_SIZE && (addr + length) > OTP_S_SIZE) {
340*4e1ccc60SShengfei Xu 		ERROR("Both read secure and non secure otp are not supported!");
341*4e1ccc60SShengfei Xu 		return -1;
342*4e1ccc60SShengfei Xu 	}
343*4e1ccc60SShengfei Xu 
344*4e1ccc60SShengfei Xu 	/* enable otp clk if clk is disabled */
345*4e1ccc60SShengfei Xu 	pclk_phy = enable_otp_clk(PCLK_PHY);
346*4e1ccc60SShengfei Xu 	if (addr < 0x1C0) {  /* 0-447 otp0 S */
347*4e1ccc60SShengfei Xu 		pclk_s = enable_otp_clk(PCLK_S);
348*4e1ccc60SShengfei Xu 		clk_s_sbpi = enable_otp_clk(CLK_S_SBPI);
349*4e1ccc60SShengfei Xu 		clk_s_user = enable_otp_clk(CLK_S_USER);
350*4e1ccc60SShengfei Xu 	} else if (addr >= 0x1C0 && addr < 0x200) { /* 448-511 otp0 NS */
351*4e1ccc60SShengfei Xu 		pclk_ns = enable_otp_clk(PCLK_NS);
352*4e1ccc60SShengfei Xu 		clk_ns_sbpi = enable_otp_clk(CLK_NS_SBPI);
353*4e1ccc60SShengfei Xu 		clk_ns_user = enable_otp_clk(CLK_NS_USER);
354*4e1ccc60SShengfei Xu 	}
355*4e1ccc60SShengfei Xu 
356*4e1ccc60SShengfei Xu 	for (i = 0; i < length; i++) {
357*4e1ccc60SShengfei Xu 
358*4e1ccc60SShengfei Xu 		ret = rk_otp_sbpi_read(addr + i, buf + i, is_need_ecc);
359*4e1ccc60SShengfei Xu 		if (ret) {
360*4e1ccc60SShengfei Xu 			ERROR("---OTP---sbpi read otp failed! addr: 0x%x", addr + i);
361*4e1ccc60SShengfei Xu 			goto out;
362*4e1ccc60SShengfei Xu 		}
363*4e1ccc60SShengfei Xu 	}
364*4e1ccc60SShengfei Xu 
365*4e1ccc60SShengfei Xu out:
366*4e1ccc60SShengfei Xu 	/* restore otp clk state */
367*4e1ccc60SShengfei Xu 	restore_otp_clk(PCLK_PHY, pclk_phy);
368*4e1ccc60SShengfei Xu 	if (addr < 0x1C0) {  /* 0-447 otp0 S */
369*4e1ccc60SShengfei Xu 		restore_otp_clk(PCLK_S, pclk_s);
370*4e1ccc60SShengfei Xu 		restore_otp_clk(CLK_S_SBPI, clk_s_sbpi);
371*4e1ccc60SShengfei Xu 		restore_otp_clk(CLK_S_USER, clk_s_user);
372*4e1ccc60SShengfei Xu 	} else if (addr >= 0x1C0 && addr < 0x200) { /* 448-511 otp0 NS */
373*4e1ccc60SShengfei Xu 		restore_otp_clk(PCLK_NS, pclk_ns);
374*4e1ccc60SShengfei Xu 		restore_otp_clk(CLK_NS_SBPI, clk_ns_sbpi);
375*4e1ccc60SShengfei Xu 		restore_otp_clk(CLK_NS_USER, clk_ns_user);
376*4e1ccc60SShengfei Xu 	}
377*4e1ccc60SShengfei Xu 
378*4e1ccc60SShengfei Xu 	return ret;
379*4e1ccc60SShengfei Xu }
380*4e1ccc60SShengfei Xu 
381*4e1ccc60SShengfei Xu int rk_otp_ns_ecc_flag(uint32_t addr)
382*4e1ccc60SShengfei Xu {
383*4e1ccc60SShengfei Xu 	if (addr >= OTP_NS_BYTE_SIZE)
384*4e1ccc60SShengfei Xu 		return 0;
385*4e1ccc60SShengfei Xu 
386*4e1ccc60SShengfei Xu 	return otp_ns_ecc_flag[addr / 2];
387*4e1ccc60SShengfei Xu }
388