1*525c44eeSSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause 2*525c44eeSSandeep Tripathy /* 3*525c44eeSSandeep Tripathy * Copyright 2019 Broadcom. 4*525c44eeSSandeep Tripathy */ 5*525c44eeSSandeep Tripathy 6*525c44eeSSandeep Tripathy #include <assert.h> 7*525c44eeSSandeep Tripathy #include <drivers/bcm_sotp.h> 8*525c44eeSSandeep Tripathy #include <initcall.h> 9*525c44eeSSandeep Tripathy #include <io.h> 10*525c44eeSSandeep Tripathy #include <kernel/delay.h> 11*525c44eeSSandeep Tripathy #include <mm/core_memprot.h> 12*525c44eeSSandeep Tripathy #include <platform_config.h> 13*525c44eeSSandeep Tripathy #include <util.h> 14*525c44eeSSandeep Tripathy 15*525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL 0x0 16*525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN BIT(15) 17*525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC BIT(9) 18*525c44eeSSandeep Tripathy #define SOTP_ADDR__OTP_ROW_ADDR_R 6 19*525c44eeSSandeep Tripathy 20*525c44eeSSandeep Tripathy #define SOTP_ADDR 0xc 21*525c44eeSSandeep Tripathy 22*525c44eeSSandeep Tripathy #define SOTP_CTRL_0 0x10 23*525c44eeSSandeep Tripathy #define SOTP_CTRL_0__START 1 24*525c44eeSSandeep Tripathy #define SOTP_READ 0 25*525c44eeSSandeep Tripathy 26*525c44eeSSandeep Tripathy #define SOTP_STAT_0 0x18 27*525c44eeSSandeep Tripathy #define SOTP_STATUS_0__FDONE BIT(3) 28*525c44eeSSandeep Tripathy 29*525c44eeSSandeep Tripathy #define SOTP_STATUS_1 0x1c 30*525c44eeSSandeep Tripathy #define SOTP_STATUS_1__CMD_DONE BIT(1) 31*525c44eeSSandeep Tripathy #define SOTP_STATUS_1__ECC_DET BIT(17) 32*525c44eeSSandeep Tripathy 33*525c44eeSSandeep Tripathy #define SOTP_RDDATA_0 0x20 34*525c44eeSSandeep Tripathy #define SOTP_RDDATA_1 0x24 35*525c44eeSSandeep Tripathy #define SOTP_ADDR_MASK 0x3ff 36*525c44eeSSandeep Tripathy 37*525c44eeSSandeep Tripathy #define SOTP_ECC_ERR_DETECT BIT64(63) 38*525c44eeSSandeep Tripathy 39*525c44eeSSandeep Tripathy #define SOTP_TIMEOUT_US 300 40*525c44eeSSandeep Tripathy 41*525c44eeSSandeep Tripathy static vaddr_t bcm_sotp_base; 42*525c44eeSSandeep Tripathy 43*525c44eeSSandeep Tripathy static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit) 44*525c44eeSSandeep Tripathy { 45*525c44eeSSandeep Tripathy uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US); 46*525c44eeSSandeep Tripathy 47*525c44eeSSandeep Tripathy while (!(io_read32(addr) & bit)) 48*525c44eeSSandeep Tripathy if (timeout_elapsed(timeout)) 49*525c44eeSSandeep Tripathy return TEE_ERROR_BUSY; 50*525c44eeSSandeep Tripathy return TEE_SUCCESS; 51*525c44eeSSandeep Tripathy } 52*525c44eeSSandeep Tripathy 53*525c44eeSSandeep Tripathy TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, uint32_t sotp_add_ecc, 54*525c44eeSSandeep Tripathy uint64_t *rdata) 55*525c44eeSSandeep Tripathy { 56*525c44eeSSandeep Tripathy uint64_t read_data = 0; 57*525c44eeSSandeep Tripathy uint32_t reg_val = 0; 58*525c44eeSSandeep Tripathy TEE_Result ret = TEE_SUCCESS; 59*525c44eeSSandeep Tripathy 60*525c44eeSSandeep Tripathy assert(bcm_sotp_base); 61*525c44eeSSandeep Tripathy /* Check for FDONE status */ 62*525c44eeSSandeep Tripathy ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), 63*525c44eeSSandeep Tripathy SOTP_STATUS_0__FDONE); 64*525c44eeSSandeep Tripathy if (ret) { 65*525c44eeSSandeep Tripathy EMSG("FDONE status done wait failed"); 66*525c44eeSSandeep Tripathy return ret; 67*525c44eeSSandeep Tripathy } 68*525c44eeSSandeep Tripathy 69*525c44eeSSandeep Tripathy /* Enable OTP access by CPU */ 70*525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 71*525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); 72*525c44eeSSandeep Tripathy 73*525c44eeSSandeep Tripathy if (sotp_add_ecc == 1) { 74*525c44eeSSandeep Tripathy io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 75*525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_DISABLE_ECC); 76*525c44eeSSandeep Tripathy } else { 77*525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 78*525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_DISABLE_ECC); 79*525c44eeSSandeep Tripathy } 80*525c44eeSSandeep Tripathy 81*525c44eeSSandeep Tripathy /* 10 bit row address */ 82*525c44eeSSandeep Tripathy reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R; 83*525c44eeSSandeep Tripathy io_write32((bcm_sotp_base + SOTP_ADDR), reg_val); 84*525c44eeSSandeep Tripathy reg_val = SOTP_READ; 85*525c44eeSSandeep Tripathy io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val); 86*525c44eeSSandeep Tripathy 87*525c44eeSSandeep Tripathy /* Start bit to tell SOTP to send command to the OTP controller */ 88*525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); 89*525c44eeSSandeep Tripathy 90*525c44eeSSandeep Tripathy /* Wait for SOTP command done to be set */ 91*525c44eeSSandeep Tripathy ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), 92*525c44eeSSandeep Tripathy SOTP_STATUS_1__CMD_DONE); 93*525c44eeSSandeep Tripathy if (ret) { 94*525c44eeSSandeep Tripathy EMSG("FDONE cmd done wait failed\n"); 95*525c44eeSSandeep Tripathy return ret; 96*525c44eeSSandeep Tripathy } 97*525c44eeSSandeep Tripathy 98*525c44eeSSandeep Tripathy DMSG("CMD Done\n"); 99*525c44eeSSandeep Tripathy 100*525c44eeSSandeep Tripathy /* Clr Start bit after command done */ 101*525c44eeSSandeep Tripathy io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); 102*525c44eeSSandeep Tripathy read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1); 103*525c44eeSSandeep Tripathy read_data = ((read_data & 0x1ff) << 32); 104*525c44eeSSandeep Tripathy read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0); 105*525c44eeSSandeep Tripathy 106*525c44eeSSandeep Tripathy reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1); 107*525c44eeSSandeep Tripathy /* no ECC check till row 15 */ 108*525c44eeSSandeep Tripathy if ((row_addr > 15) && (reg_val & SOTP_STATUS_1__ECC_DET)) { 109*525c44eeSSandeep Tripathy EMSG("SOTP ECC ERROR Detected ROW %d\n", row_addr); 110*525c44eeSSandeep Tripathy read_data = SOTP_ECC_ERR_DETECT; 111*525c44eeSSandeep Tripathy } 112*525c44eeSSandeep Tripathy 113*525c44eeSSandeep Tripathy /* Command done is cleared */ 114*525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE); 115*525c44eeSSandeep Tripathy io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 116*525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); 117*525c44eeSSandeep Tripathy DMSG("read done\n"); 118*525c44eeSSandeep Tripathy 119*525c44eeSSandeep Tripathy *rdata = read_data; 120*525c44eeSSandeep Tripathy return ret; 121*525c44eeSSandeep Tripathy } 122*525c44eeSSandeep Tripathy 123*525c44eeSSandeep Tripathy static TEE_Result bcm_sotp_init(void) 124*525c44eeSSandeep Tripathy { 125*525c44eeSSandeep Tripathy bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC); 126*525c44eeSSandeep Tripathy 127*525c44eeSSandeep Tripathy DMSG("bcm_sotp init done\n"); 128*525c44eeSSandeep Tripathy return TEE_SUCCESS; 129*525c44eeSSandeep Tripathy } 130*525c44eeSSandeep Tripathy 131*525c44eeSSandeep Tripathy driver_init(bcm_sotp_init); 132