1525c44eeSSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause 2525c44eeSSandeep Tripathy /* 3525c44eeSSandeep Tripathy * Copyright 2019 Broadcom. 4525c44eeSSandeep Tripathy */ 5525c44eeSSandeep Tripathy 6525c44eeSSandeep Tripathy #include <assert.h> 7525c44eeSSandeep Tripathy #include <drivers/bcm_sotp.h> 8525c44eeSSandeep Tripathy #include <initcall.h> 9525c44eeSSandeep Tripathy #include <io.h> 10525c44eeSSandeep Tripathy #include <kernel/delay.h> 11525c44eeSSandeep Tripathy #include <mm/core_memprot.h> 12525c44eeSSandeep Tripathy #include <platform_config.h> 13525c44eeSSandeep Tripathy #include <util.h> 14525c44eeSSandeep Tripathy 15525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL 0x0 16525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN BIT(15) 17525c44eeSSandeep Tripathy #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC BIT(9) 18525c44eeSSandeep Tripathy #define SOTP_ADDR__OTP_ROW_ADDR_R 6 19525c44eeSSandeep Tripathy 20525c44eeSSandeep Tripathy #define SOTP_ADDR 0xc 21525c44eeSSandeep Tripathy 22525c44eeSSandeep Tripathy #define SOTP_CTRL_0 0x10 23525c44eeSSandeep Tripathy #define SOTP_CTRL_0__START 1 24525c44eeSSandeep Tripathy #define SOTP_READ 0 25525c44eeSSandeep Tripathy 26525c44eeSSandeep Tripathy #define SOTP_STAT_0 0x18 27525c44eeSSandeep Tripathy #define SOTP_STATUS_0__FDONE BIT(3) 28525c44eeSSandeep Tripathy 29525c44eeSSandeep Tripathy #define SOTP_STATUS_1 0x1c 30525c44eeSSandeep Tripathy #define SOTP_STATUS_1__CMD_DONE BIT(1) 31525c44eeSSandeep Tripathy #define SOTP_STATUS_1__ECC_DET BIT(17) 32525c44eeSSandeep Tripathy 33525c44eeSSandeep Tripathy #define SOTP_RDDATA_0 0x20 34525c44eeSSandeep Tripathy #define SOTP_RDDATA_1 0x24 35525c44eeSSandeep Tripathy #define SOTP_ADDR_MASK 0x3ff 36525c44eeSSandeep Tripathy 37525c44eeSSandeep Tripathy #define SOTP_ECC_ERR_DETECT BIT64(63) 38525c44eeSSandeep Tripathy 39525c44eeSSandeep Tripathy #define SOTP_TIMEOUT_US 300 40525c44eeSSandeep Tripathy 41525c44eeSSandeep Tripathy static vaddr_t bcm_sotp_base; 42525c44eeSSandeep Tripathy 43525c44eeSSandeep Tripathy static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit) 44525c44eeSSandeep Tripathy { 45525c44eeSSandeep Tripathy uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US); 46525c44eeSSandeep Tripathy 47525c44eeSSandeep Tripathy while (!(io_read32(addr) & bit)) 48525c44eeSSandeep Tripathy if (timeout_elapsed(timeout)) 49525c44eeSSandeep Tripathy return TEE_ERROR_BUSY; 50525c44eeSSandeep Tripathy return TEE_SUCCESS; 51525c44eeSSandeep Tripathy } 52525c44eeSSandeep Tripathy 53525c44eeSSandeep Tripathy TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, uint32_t sotp_add_ecc, 54525c44eeSSandeep Tripathy uint64_t *rdata) 55525c44eeSSandeep Tripathy { 56525c44eeSSandeep Tripathy uint64_t read_data = 0; 57525c44eeSSandeep Tripathy uint32_t reg_val = 0; 58525c44eeSSandeep Tripathy TEE_Result ret = TEE_SUCCESS; 59525c44eeSSandeep Tripathy 60525c44eeSSandeep Tripathy assert(bcm_sotp_base); 61525c44eeSSandeep Tripathy /* Check for FDONE status */ 62525c44eeSSandeep Tripathy ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), 63525c44eeSSandeep Tripathy SOTP_STATUS_0__FDONE); 64525c44eeSSandeep Tripathy if (ret) { 65525c44eeSSandeep Tripathy EMSG("FDONE status done wait failed"); 66525c44eeSSandeep Tripathy return ret; 67525c44eeSSandeep Tripathy } 68525c44eeSSandeep Tripathy 69525c44eeSSandeep Tripathy /* Enable OTP access by CPU */ 70525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 71525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); 72525c44eeSSandeep Tripathy 734afc3781SBharat Kumar Reddy Gooty /* ROWS does not support ECC */ 744afc3781SBharat Kumar Reddy Gooty if (row_addr <= SOTP_NO_ECC_ROWS) 754afc3781SBharat Kumar Reddy Gooty sotp_add_ecc = 0; 764afc3781SBharat Kumar Reddy Gooty 77525c44eeSSandeep Tripathy if (sotp_add_ecc == 1) { 78525c44eeSSandeep Tripathy io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 79525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_DISABLE_ECC); 80525c44eeSSandeep Tripathy } else { 81525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 82525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_DISABLE_ECC); 83525c44eeSSandeep Tripathy } 84525c44eeSSandeep Tripathy 85525c44eeSSandeep Tripathy /* 10 bit row address */ 86525c44eeSSandeep Tripathy reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R; 87525c44eeSSandeep Tripathy io_write32((bcm_sotp_base + SOTP_ADDR), reg_val); 88525c44eeSSandeep Tripathy reg_val = SOTP_READ; 89525c44eeSSandeep Tripathy io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val); 90525c44eeSSandeep Tripathy 91525c44eeSSandeep Tripathy /* Start bit to tell SOTP to send command to the OTP controller */ 92525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); 93525c44eeSSandeep Tripathy 94525c44eeSSandeep Tripathy /* Wait for SOTP command done to be set */ 95525c44eeSSandeep Tripathy ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), 96525c44eeSSandeep Tripathy SOTP_STATUS_1__CMD_DONE); 97525c44eeSSandeep Tripathy if (ret) { 98525c44eeSSandeep Tripathy EMSG("FDONE cmd done wait failed\n"); 99525c44eeSSandeep Tripathy return ret; 100525c44eeSSandeep Tripathy } 101525c44eeSSandeep Tripathy 102525c44eeSSandeep Tripathy DMSG("CMD Done\n"); 103525c44eeSSandeep Tripathy 104525c44eeSSandeep Tripathy /* Clr Start bit after command done */ 105525c44eeSSandeep Tripathy io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); 106525c44eeSSandeep Tripathy read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1); 107525c44eeSSandeep Tripathy read_data = ((read_data & 0x1ff) << 32); 108525c44eeSSandeep Tripathy read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0); 109525c44eeSSandeep Tripathy 110525c44eeSSandeep Tripathy reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1); 1114afc3781SBharat Kumar Reddy Gooty /* No ECC check till SOTP_NO_ECC_ROWS */ 1124afc3781SBharat Kumar Reddy Gooty if (row_addr > SOTP_NO_ECC_ROWS && 1134afc3781SBharat Kumar Reddy Gooty reg_val & SOTP_STATUS_1__ECC_DET) { 114525c44eeSSandeep Tripathy EMSG("SOTP ECC ERROR Detected ROW %d\n", row_addr); 115525c44eeSSandeep Tripathy read_data = SOTP_ECC_ERR_DETECT; 116525c44eeSSandeep Tripathy } 117525c44eeSSandeep Tripathy 118525c44eeSSandeep Tripathy /* Command done is cleared */ 119525c44eeSSandeep Tripathy io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE); 120525c44eeSSandeep Tripathy io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), 121525c44eeSSandeep Tripathy SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); 122525c44eeSSandeep Tripathy DMSG("read done\n"); 123525c44eeSSandeep Tripathy 124525c44eeSSandeep Tripathy *rdata = read_data; 125525c44eeSSandeep Tripathy return ret; 126525c44eeSSandeep Tripathy } 127525c44eeSSandeep Tripathy 128525c44eeSSandeep Tripathy static TEE_Result bcm_sotp_init(void) 129525c44eeSSandeep Tripathy { 130*c2e4eb43SAnton Rybakov bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC, 1); 131525c44eeSSandeep Tripathy 132525c44eeSSandeep Tripathy DMSG("bcm_sotp init done\n"); 133525c44eeSSandeep Tripathy return TEE_SUCCESS; 134525c44eeSSandeep Tripathy } 135525c44eeSSandeep Tripathy 13619ac2e24SVahid Dukandar service_init(bcm_sotp_init); 137