1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017 - 2020, Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <stdint.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <drivers/delay_timer.h> 11*91f16700Schasinglulu #include <lib/mmio.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <ocotp.h> 14*91f16700Schasinglulu #include <platform_def.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #define OTP_MAP 2 17*91f16700Schasinglulu #define OTP_NUM_WORDS 2048 18*91f16700Schasinglulu /* 19*91f16700Schasinglulu * # of tries for OTP Status. The time to execute a command varies. The slowest 20*91f16700Schasinglulu * commands are writes which also vary based on the # of bits turned on. Writing 21*91f16700Schasinglulu * 0xffffffff takes ~3800 us. 22*91f16700Schasinglulu */ 23*91f16700Schasinglulu #define OTPC_RETRIES_US 5000 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* Sequence to enable OTP program */ 26*91f16700Schasinglulu #define OTPC_PROG_EN_SEQ { 0xf, 0x4, 0x8, 0xd } 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* OTPC Commands */ 29*91f16700Schasinglulu #define OTPC_CMD_READ 0x0 30*91f16700Schasinglulu #define OTPC_CMD_OTP_PROG_ENABLE 0x2 31*91f16700Schasinglulu #define OTPC_CMD_OTP_PROG_DISABLE 0x3 32*91f16700Schasinglulu #define OTPC_CMD_PROGRAM 0x8 33*91f16700Schasinglulu #define OTPC_CMD_ECC 0x10 34*91f16700Schasinglulu #define OTPC_ECC_ADDR 0x1A 35*91f16700Schasinglulu #define OTPC_ECC_VAL 0x00EC0000 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* OTPC Status Bits */ 38*91f16700Schasinglulu #define OTPC_STAT_CMD_DONE BIT(1) 39*91f16700Schasinglulu #define OTPC_STAT_PROG_OK BIT(2) 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* OTPC register definition */ 42*91f16700Schasinglulu #define OTPC_MODE_REG_OFFSET 0x0 43*91f16700Schasinglulu #define OTPC_MODE_REG_OTPC_MODE 0 44*91f16700Schasinglulu #define OTPC_COMMAND_OFFSET 0x4 45*91f16700Schasinglulu #define OTPC_COMMAND_COMMAND_WIDTH 6 46*91f16700Schasinglulu #define OTPC_CMD_START_OFFSET 0x8 47*91f16700Schasinglulu #define OTPC_CMD_START_START 0 48*91f16700Schasinglulu #define OTPC_CPU_STATUS_OFFSET 0xc 49*91f16700Schasinglulu #define OTPC_CPUADDR_REG_OFFSET 0x28 50*91f16700Schasinglulu #define OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH 16 51*91f16700Schasinglulu #define OTPC_CPU_WRITE_REG_OFFSET 0x2c 52*91f16700Schasinglulu 53*91f16700Schasinglulu #define OTPC_CMD_MASK (BIT(OTPC_COMMAND_COMMAND_WIDTH) - 1) 54*91f16700Schasinglulu #define OTPC_ADDR_MASK (BIT(OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH) - 1) 55*91f16700Schasinglulu 56*91f16700Schasinglulu #define OTPC_MODE_REG OCOTP_REGS_BASE 57*91f16700Schasinglulu 58*91f16700Schasinglulu struct chip_otp_cfg { 59*91f16700Schasinglulu uint32_t base; 60*91f16700Schasinglulu uint32_t num_words; 61*91f16700Schasinglulu }; 62*91f16700Schasinglulu 63*91f16700Schasinglulu struct chip_otp_cfg ocotp_cfg = { 64*91f16700Schasinglulu .base = OTPC_MODE_REG, 65*91f16700Schasinglulu .num_words = 2048, 66*91f16700Schasinglulu }; 67*91f16700Schasinglulu 68*91f16700Schasinglulu struct otpc_priv { 69*91f16700Schasinglulu uint32_t base; 70*91f16700Schasinglulu struct otpc_map *map; 71*91f16700Schasinglulu int size; 72*91f16700Schasinglulu int state; 73*91f16700Schasinglulu }; 74*91f16700Schasinglulu 75*91f16700Schasinglulu struct otpc_priv otpc_info; 76*91f16700Schasinglulu 77*91f16700Schasinglulu static inline void set_command(uint32_t base, uint32_t command) 78*91f16700Schasinglulu { 79*91f16700Schasinglulu mmio_write_32(base + OTPC_COMMAND_OFFSET, command & OTPC_CMD_MASK); 80*91f16700Schasinglulu } 81*91f16700Schasinglulu 82*91f16700Schasinglulu static inline void set_cpu_address(uint32_t base, uint32_t addr) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu mmio_write_32(base + OTPC_CPUADDR_REG_OFFSET, addr & OTPC_ADDR_MASK); 85*91f16700Schasinglulu } 86*91f16700Schasinglulu 87*91f16700Schasinglulu static inline void set_start_bit(uint32_t base) 88*91f16700Schasinglulu { 89*91f16700Schasinglulu mmio_write_32(base + OTPC_CMD_START_OFFSET, 1 << OTPC_CMD_START_START); 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu static inline void reset_start_bit(uint32_t base) 93*91f16700Schasinglulu { 94*91f16700Schasinglulu mmio_write_32(base + OTPC_CMD_START_OFFSET, 0); 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu static inline void write_cpu_data(uint32_t base, uint32_t value) 98*91f16700Schasinglulu { 99*91f16700Schasinglulu mmio_write_32(base + OTPC_CPU_WRITE_REG_OFFSET, value); 100*91f16700Schasinglulu } 101*91f16700Schasinglulu 102*91f16700Schasinglulu static int poll_cpu_status(uint32_t base, uint32_t value) 103*91f16700Schasinglulu { 104*91f16700Schasinglulu uint32_t status; 105*91f16700Schasinglulu uint32_t retries; 106*91f16700Schasinglulu 107*91f16700Schasinglulu for (retries = 0; retries < OTPC_RETRIES_US; retries++) { 108*91f16700Schasinglulu status = mmio_read_32(base + OTPC_CPU_STATUS_OFFSET); 109*91f16700Schasinglulu if (status & value) 110*91f16700Schasinglulu break; 111*91f16700Schasinglulu udelay(1); 112*91f16700Schasinglulu } 113*91f16700Schasinglulu if (retries == OTPC_RETRIES_US) 114*91f16700Schasinglulu return -1; 115*91f16700Schasinglulu 116*91f16700Schasinglulu return 0; 117*91f16700Schasinglulu } 118*91f16700Schasinglulu 119*91f16700Schasinglulu static int bcm_otpc_ecc(uint32_t enable) 120*91f16700Schasinglulu { 121*91f16700Schasinglulu struct otpc_priv *priv = &otpc_info; 122*91f16700Schasinglulu int ret; 123*91f16700Schasinglulu 124*91f16700Schasinglulu set_command(priv->base, OTPC_CMD_ECC); 125*91f16700Schasinglulu set_cpu_address(priv->base, OTPC_ECC_ADDR); 126*91f16700Schasinglulu 127*91f16700Schasinglulu if (!enable) 128*91f16700Schasinglulu write_cpu_data(priv->base, OTPC_ECC_VAL); 129*91f16700Schasinglulu else 130*91f16700Schasinglulu write_cpu_data(priv->base, ~OTPC_ECC_VAL); 131*91f16700Schasinglulu 132*91f16700Schasinglulu set_start_bit(priv->base); 133*91f16700Schasinglulu ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE); 134*91f16700Schasinglulu if (ret) { 135*91f16700Schasinglulu ERROR("otp ecc op error: 0x%x", ret); 136*91f16700Schasinglulu return -1; 137*91f16700Schasinglulu } 138*91f16700Schasinglulu reset_start_bit(priv->base); 139*91f16700Schasinglulu 140*91f16700Schasinglulu return 0; 141*91f16700Schasinglulu } 142*91f16700Schasinglulu 143*91f16700Schasinglulu /* 144*91f16700Schasinglulu * bcm_otpc_read read otp data in the size of 8 byte rows. 145*91f16700Schasinglulu * bytes has to be the multiple of 8. 146*91f16700Schasinglulu * return -1 in error case, return read bytes in success. 147*91f16700Schasinglulu */ 148*91f16700Schasinglulu int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes, 149*91f16700Schasinglulu uint32_t ecc_flag) 150*91f16700Schasinglulu { 151*91f16700Schasinglulu struct otpc_priv *priv = &otpc_info; 152*91f16700Schasinglulu uint32_t *buf = val; 153*91f16700Schasinglulu uint32_t bytes_read; 154*91f16700Schasinglulu uint32_t address = offset / priv->map->word_size; 155*91f16700Schasinglulu int i, ret; 156*91f16700Schasinglulu 157*91f16700Schasinglulu if (!priv->state) { 158*91f16700Schasinglulu ERROR("OCOTP read failed\n"); 159*91f16700Schasinglulu return -1; 160*91f16700Schasinglulu } 161*91f16700Schasinglulu 162*91f16700Schasinglulu bcm_otpc_ecc(ecc_flag); 163*91f16700Schasinglulu 164*91f16700Schasinglulu for (bytes_read = 0; (bytes_read + priv->map->word_size) <= bytes;) { 165*91f16700Schasinglulu set_command(priv->base, OTPC_CMD_READ); 166*91f16700Schasinglulu set_cpu_address(priv->base, address++); 167*91f16700Schasinglulu set_start_bit(priv->base); 168*91f16700Schasinglulu ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE); 169*91f16700Schasinglulu if (ret) { 170*91f16700Schasinglulu ERROR("otp read error: 0x%x", ret); 171*91f16700Schasinglulu return -1; 172*91f16700Schasinglulu } 173*91f16700Schasinglulu 174*91f16700Schasinglulu for (i = 0; i < priv->map->otpc_row_size; i++) { 175*91f16700Schasinglulu *buf++ = mmio_read_32(priv->base + 176*91f16700Schasinglulu priv->map->data_r_offset[i]); 177*91f16700Schasinglulu bytes_read += sizeof(*buf); 178*91f16700Schasinglulu } 179*91f16700Schasinglulu 180*91f16700Schasinglulu reset_start_bit(priv->base); 181*91f16700Schasinglulu } 182*91f16700Schasinglulu 183*91f16700Schasinglulu return bytes_read; 184*91f16700Schasinglulu } 185*91f16700Schasinglulu 186*91f16700Schasinglulu int bcm_otpc_init(struct otpc_map *map) 187*91f16700Schasinglulu { 188*91f16700Schasinglulu struct otpc_priv *priv; 189*91f16700Schasinglulu 190*91f16700Schasinglulu priv = &otpc_info; 191*91f16700Schasinglulu priv->base = ocotp_cfg.base; 192*91f16700Schasinglulu priv->map = map; 193*91f16700Schasinglulu 194*91f16700Schasinglulu priv->size = 4 * ocotp_cfg.num_words; 195*91f16700Schasinglulu 196*91f16700Schasinglulu /* Enable CPU access to OTPC. */ 197*91f16700Schasinglulu mmio_setbits_32(priv->base + OTPC_MODE_REG_OFFSET, 198*91f16700Schasinglulu BIT(OTPC_MODE_REG_OTPC_MODE)); 199*91f16700Schasinglulu reset_start_bit(priv->base); 200*91f16700Schasinglulu priv->state = 1; 201*91f16700Schasinglulu VERBOSE("OTPC Initialization done\n"); 202*91f16700Schasinglulu 203*91f16700Schasinglulu return 0; 204*91f16700Schasinglulu } 205