From 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:13:47 +0200 Subject: Adding upstream version 2.8.0+dfsg. Signed-off-by: Daniel Baumann --- drivers/nxp/sfp/sfp.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 drivers/nxp/sfp/sfp.c (limited to 'drivers/nxp/sfp/sfp.c') diff --git a/drivers/nxp/sfp/sfp.c b/drivers/nxp/sfp/sfp.c new file mode 100644 index 0000000..e06c6b9 --- /dev/null +++ b/drivers/nxp/sfp/sfp.c @@ -0,0 +1,167 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static uintptr_t g_nxp_sfp_addr; +static uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)] + __aligned(CACHE_WRITEBACK_GRANULE); + +void sfp_init(uintptr_t nxp_sfp_addr) +{ + g_nxp_sfp_addr = nxp_sfp_addr; +} + +uintptr_t get_sfp_addr(void) +{ + return g_nxp_sfp_addr; +} + +uint32_t *get_sfp_srk_hash(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = + (void *) (g_nxp_sfp_addr + SFP_FUSE_REGS_OFFSET); + int i = 0; + + /* Add comparison of hash with SFP hash here */ + for (i = 0; i < SRK_HASH_SIZE/sizeof(uint32_t); i++) + srk_hash[i] = + mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]); + + return srk_hash; +} + +void set_sfp_wr_disable(void) +{ + /* + * Mark SFP Write Disable and Write Disable Lock + * Bit to prevent write to SFP fuses like + * OUID's, Key Revocation fuse etc + */ + void *sfpcr = (void *)(g_nxp_sfp_addr + SFP_SFPCR_OFFSET); + uint32_t sfpcr_val; + + sfpcr_val = sfp_read32(sfpcr); + sfpcr_val |= (SFP_SFPCR_WD | SFP_SFPCR_WDL); + sfp_write32(sfpcr, sfpcr_val); +} + +int sfp_program_fuses(void) +{ + uint32_t ingr; + uint32_t sfp_cmd_status = 0U; + int ret = 0; + + /* Program SFP fuses from mirror registers */ + sfp_write32((void *)(g_nxp_sfp_addr + SFP_INGR_OFFSET), + SFP_INGR_PROGFB_CMD); + + /* Wait until fuse programming is successful */ + do { + ingr = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET); + } while (ingr & SFP_INGR_PROGFB_CMD); + + /* Check for SFP fuse programming error */ + sfp_cmd_status = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET) + & SFP_INGR_ERROR_MASK; + + if (sfp_cmd_status != 0U) { + return ERROR_PROGFB_CMD; + } + + return ret; +} + +uint32_t sfp_read_oem_uid(uint8_t oem_uid) +{ + uint32_t val = 0U; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if (oem_uid > MAX_OEM_UID) { + ERROR("Invalid OEM UID received.\n"); + return ERROR_OEMUID_WRITE; + } + + val = sfp_read32(&sfp_ccsr_regs->oem_uid[oem_uid]); + + return val; +} + +/* + * return val: 0 - No update required. + * 1 - successful update done. + * ERROR_OEMUID_WRITE - Invalid OEM UID + */ +uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val) +{ + uint32_t val = 0U; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + val = sfp_read_oem_uid(oem_uid); + + if (val == ERROR_OEMUID_WRITE) { + return ERROR_OEMUID_WRITE; + } + + /* Counter already set. No need to do anything */ + if ((val & sfp_val) != 0U) { + return 0U; + } + + val |= sfp_val; + + INFO("SFP Value is %x for setting sfp_val = %d\n", val, sfp_val); + + sfp_write32(&sfp_ccsr_regs->oem_uid[oem_uid], val); + + return 1U; +} + +int sfp_check_its(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_ITS_MASK) != 0) { + return 1; + } else { + return 0; + } +} + +int sfp_check_oem_wp(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_WP_MASK) != 0) { + return 1; + } else { + return 0; + } +} + +/* This function returns ospr's key_revoc values.*/ +uint32_t get_key_revoc(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + return (sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_KEY_REVOC_MASK) >> + OSPR_KEY_REVOC_SHIFT; +} -- cgit v1.2.3