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