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