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
enable_otp_clk(int clk)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
restore_otp_clk(int clk,uint32_t reg)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
check_sbpi_done_int(uint32_t otp_base)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
otp_select(uint32_t addr)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
rk_otp_ecc_enable(uint32_t otp_base,bool enable)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
rk_otp_sbpi_read(uint32_t addr,uint16_t * read_data,bool is_need_ecc)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
rk_otp_read(uint32_t byte_addr,uint32_t byte_len,uint16_t * buf,bool is_need_ecc)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
rk_otp_ns_ecc_flag(uint32_t addr)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