123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /*
- * Copyright (c) 2016-2020, Broadcom
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <string.h>
- #include <common/debug.h>
- #include <lib/mmio.h>
- #include <sotp.h>
- #include <platform_def.h>
- #include <platform_sotp.h>
- #ifdef USE_SOFT_SOTP
- extern uint64_t soft_sotp[];
- #endif
- #define SOTP_PROG_CONTROL (SOTP_REGS_OTP_BASE + 0x0000)
- #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN 15
- #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC 9
- #define SOTP_PROG_CONTROL__OTP_ECC_WREN 8
- #define SOTP_WRDATA_0 (SOTP_REGS_OTP_BASE + 0x0004)
- #define SOTP_WRDATA_1 (SOTP_REGS_OTP_BASE + 0x0008)
- #define SOTP_ADDR (SOTP_REGS_OTP_BASE + 0x000c)
- #define SOTP_ADDR__OTP_ROW_ADDR_R 6
- #define SOTP_ADDR_MASK 0x3FF
- #define SOTP_CTRL_0 (SOTP_REGS_OTP_BASE + 0x0010)
- #define SOTP_CTRL_0__START 0
- #define SOTP_CTRL_0__OTP_CMD 1
- #define SOTP_STATUS_0 (SOTP_REGS_OTP_BASE + 0x0018)
- #define SOTP_STATUS__FDONE 3
- #define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c)
- #define SOTP_STATUS_1__CMD_DONE 1
- #define SOTP_STATUS_1__ECC_DET 17
- #define SOTP_RDDATA_0 (SOTP_REGS_OTP_BASE + 0x0020)
- #define SOTP_RDDATA_1 (SOTP_REGS_OTP_BASE + 0x0024)
- #define SOTP_READ 0
- #define SOTP_PROG_WORD 10
- #define SOTP_STATUS__PROGOK 2
- #define SOTP_PROG_ENABLE 2
- #define SOTP_ROW_DATA_MASK 0xffffffff
- #define SOTP_ECC_ERR_BITS_MASK 0x1ff00000000
- #define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4
- #define SOTP_CHIP_CTRL_SW_MANU_PROG 5
- #define SOTP_CHIP_CTRL_SW_CID_PROG 6
- #define SOTP_CHIP_CTRL_SW_AB_DEVICE 8
- #define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9
- #define CHIP_STATE_UNPROGRAMMED 0x1
- #define CHIP_STATE_UNASSIGNED 0x2
- uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc)
- {
- #ifdef USE_SOFT_SOTP
- (void)sotp_add_ecc;
- return soft_sotp[offset];
- #else
- uint64_t read_data = 0;
- uint64_t read_data1 = 0;
- uint64_t read_data2 = 0;
- /* Check for FDONE status */
- while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) !=
- BIT(SOTP_STATUS__FDONE))
- ;
- /* Enable OTP access by CPU */
- mmio_setbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
- if (sotp_add_ecc == 1) {
- mmio_clrbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC));
- }
- if (sotp_add_ecc == 0) {
- mmio_setbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC));
- }
- mmio_write_32(SOTP_ADDR,
- ((offset & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R));
- mmio_write_32(SOTP_CTRL_0, (SOTP_READ << SOTP_CTRL_0__OTP_CMD));
- /* Start bit to tell SOTP to send command to the OTP controller */
- mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
- /* Wait for SOTP command done to be set */
- while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) !=
- BIT(SOTP_STATUS_1__CMD_DONE))
- ;
- /* Clr Start bit after command done */
- mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
- if ((offset > SOTP_DEVICE_SECURE_CFG3_ROW) &&
- (mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__ECC_DET))) {
- ERROR("SOTP ECC ERROR Detected row offset %d\n", offset);
- read_data = SOTP_ECC_ERR_DETECT;
- } else {
- read_data1 = (uint64_t)mmio_read_32(SOTP_RDDATA_0);
- read_data1 = read_data1 & 0xFFFFFFFF;
- read_data2 = (uint64_t)mmio_read_32(SOTP_RDDATA_1);
- read_data2 = (read_data2 & 0x1ff) << 32;
- read_data = read_data1 | read_data2;
- }
- /* Command done is cleared */
- mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
- /* disable OTP access by CPU */
- mmio_clrbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
- return read_data;
- #endif
- }
- void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata)
- {
- #ifdef USE_SOFT_SOTP
- (void)sotp_add_ecc;
- soft_sotp[addr] = wdata;
- #else
- uint32_t loop;
- uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D };
- uint32_t chip_state_default =
- (CHIP_STATE_UNASSIGNED|CHIP_STATE_UNPROGRAMMED);
- uint32_t chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES);
- uint32_t chip_ctrl_default = 0;
- /*
- * The override settings is required to allow the customer to program
- * the application specific keys into SOTP, before the conversion to
- * one of the AB modes.
- * At the end of write operation, the chip ctrl settings will restored
- * to the state prior to write call
- */
- if (chip_state & chip_state_default) {
- uint32_t chip_ctrl;
- chip_ctrl_default = mmio_read_32(SOTP_CHIP_CTRL);
- INFO("SOTP: enable special prog mode\n");
- chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) |
- BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) |
- BIT(SOTP_CHIP_CTRL_SW_CID_PROG) |
- BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE);
- mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl);
- }
- /* Check for FDONE status */
- while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) !=
- BIT(SOTP_STATUS__FDONE))
- ;
- /* Enable OTP access by CPU */
- mmio_setbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
- if (addr > SOTP_DEVICE_SECURE_CFG3_ROW) {
- if (sotp_add_ecc == 0) {
- mmio_clrbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
- }
- if (sotp_add_ecc == 1) {
- mmio_setbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
- }
- } else {
- mmio_clrbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
- }
- mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_ENABLE << 1));
- /*
- * In order to avoid unintentional writes / programming of the OTP
- * array, the OTP Controller must be put into programming mode before
- * it will accept program commands. This is done by writing 0xF, 0x4,
- * 0x8, 0xD with program commands prior to starting the actual
- * programming sequence
- */
- for (loop = 0; loop < 4; loop++) {
- mmio_write_32(SOTP_WRDATA_0, prog_array[loop]);
- /*
- * Start bit to tell SOTP to send command to the OTP controller
- */
- mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
- /* Wait for SOTP command done to <-- be set */
- while ((mmio_read_32(SOTP_STATUS_1) &
- BIT(SOTP_STATUS_1__CMD_DONE)) !=
- BIT(SOTP_STATUS_1__CMD_DONE))
- ;
- /* Command done is cleared w1c */
- mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
- /* Clr Start bit after command done */
- mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
- }
- /* Check for PROGOK */
- while ((mmio_read_32(SOTP_STATUS_0) & 0x4) != BIT(SOTP_STATUS__PROGOK))
- ;
- /* Set 10 bit row address */
- mmio_write_32(SOTP_ADDR,
- ((addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R));
- /* Set SOTP Row data */
- mmio_write_32(SOTP_WRDATA_0, (wdata & SOTP_ROW_DATA_MASK));
- /* Set SOTP ECC and error bits */
- mmio_write_32(SOTP_WRDATA_1, ((wdata & SOTP_ECC_ERR_BITS_MASK) >> 32));
- /* Set prog_word command */
- mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_WORD << 1));
- /* Start bit to tell SOTP to send command to the OTP controller */
- mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
- /* Wait for SOTP command done to be set */
- while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) !=
- BIT(SOTP_STATUS_1__CMD_DONE))
- ;
- /* Command done is cleared w1c */
- mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
- /* disable OTP access by CPU */
- mmio_clrbits_32(SOTP_PROG_CONTROL,
- BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
- /* Clr Start bit after command done */
- mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
- if (chip_state & chip_state_default)
- mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl_default);
- #endif
- }
- int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row)
- {
- int row;
- uint32_t status = 0;
- uint32_t status2 = 0xFFFFFFFF;
- uint64_t row_data;
- uint32_t data;
- uint32_t *temp_key = (uint32_t *)key;
- row = start_row;
- while ((keysize > 0) && (row <= end_row)) {
- row_data = sotp_mem_read(row, SOTP_ROW_ECC);
- if (!(row_data & (SOTP_ECC_ERR_DETECT | SOTP_FAIL_BITS))) {
- memcpy(temp_key++, &row_data, sizeof(uint32_t));
- keysize -= sizeof(uint32_t);
- data = (uint32_t)(row_data & SOTP_ROW_DATA_MASK);
- status |= data;
- status2 &= data;
- }
- row++;
- }
- if ((status2 == 0xFFFFFFFF) || (status == 0) || (row > end_row))
- return -1;
- return 0;
- }
- int sotp_key_erased(void)
- {
- uint64_t row_data;
- int status = 0;
- row_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
- if (row_data & SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK)
- status = 1;
- else if (mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES) &
- SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK)
- status = 1;
- return status;
- }
- /*
- * This function optimise the SOTP redundancy
- * by considering the 00- zero and 01,10,11 - one
- */
- uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data)
- {
- uint32_t opt_data;
- uint32_t opt_loop;
- uint32_t temp_data;
- opt_data = 0;
- for (opt_loop = 0; opt_loop < 16; opt_loop = opt_loop + 1) {
- temp_data = ((sotp_row_data >> (opt_loop * 2)) & 0x3);
- if (temp_data != 0x0)
- opt_data = (opt_data | (1 << opt_loop));
- }
- return opt_data;
- }
|