1*011c182aSAndrew Mustea // SPDX-License-Identifier: BSD-2-Clause 2*011c182aSAndrew Mustea /* 3*011c182aSAndrew Mustea * Copyright 2022 Microsoft 4*011c182aSAndrew Mustea * 5*011c182aSAndrew Mustea * Driver for the NXP LX2160A-series Security Fuse Processor (SFP). 6*011c182aSAndrew Mustea */ 7*011c182aSAndrew Mustea 8*011c182aSAndrew Mustea #include <assert.h> 9*011c182aSAndrew Mustea #include <drivers/ls_sfp.h> 10*011c182aSAndrew Mustea #include <io.h> 11*011c182aSAndrew Mustea #include <kernel/boot.h> 12*011c182aSAndrew Mustea #include <kernel/delay.h> 13*011c182aSAndrew Mustea #include <kernel/dt.h> 14*011c182aSAndrew Mustea #include <kernel/panic.h> 15*011c182aSAndrew Mustea #include <kernel/tee_time.h> 16*011c182aSAndrew Mustea #include <libfdt.h> 17*011c182aSAndrew Mustea #include <mm/core_memprot.h> 18*011c182aSAndrew Mustea #include <util.h> 19*011c182aSAndrew Mustea 20*011c182aSAndrew Mustea /** 21*011c182aSAndrew Mustea * struct ls_sfp_registers - Memory map of the SFP registers. 22*011c182aSAndrew Mustea * @rsvd0[0x8]: Reserved. 23*011c182aSAndrew Mustea * @ingr: Instruction Register. 24*011c182aSAndrew Mustea * @svhesr: Secret Value Hamming Error Status Registers. 25*011c182aSAndrew Mustea * @sfpcr: SFP Configuration Register. 26*011c182aSAndrew Mustea * @rsvd1[0x3]: Reserved. 27*011c182aSAndrew Mustea * @version: SFP Version Register. 28*011c182aSAndrew Mustea * @rsvd2[0x71]: Reserved. 29*011c182aSAndrew Mustea * @ospr0: OEM Security Policy Register 0. 30*011c182aSAndrew Mustea * @ospr1: OEM Security Policy Register 1. 31*011c182aSAndrew Mustea * @dcvr0: Debug Challenge Value Register 0. 32*011c182aSAndrew Mustea * @dcvr1: Debug Challenge Value Register 1. 33*011c182aSAndrew Mustea * @drvr0: Debug Response Value Register 0. 34*011c182aSAndrew Mustea * @drvr1: Debug Response Value Register 1 35*011c182aSAndrew Mustea * @fswpr: Factory Section Write Protect Register. 36*011c182aSAndrew Mustea * @fuidr0: Factory Unique ID Register 0. 37*011c182aSAndrew Mustea * @fuidr1: Factory Unique ID Register 1. 38*011c182aSAndrew Mustea * @isbccr: ISBC Configuration Register. 39*011c182aSAndrew Mustea * @fspfr[0x3]: Factory Scratch Pad Fuse Registers. 40*011c182aSAndrew Mustea * @otpmkr[0x8]: One Time Programmable Master Key. 41*011c182aSAndrew Mustea * @srkhr[0x8]: Super Root Key Hash. 42*011c182aSAndrew Mustea * @ouidr[0x5]: OEM Unique ID Scratch Pad Fuse Registers. 43*011c182aSAndrew Mustea */ 44*011c182aSAndrew Mustea static struct ls_sfp_registers { 45*011c182aSAndrew Mustea uint32_t rsvd0[0x8]; /* 0x000 */ 46*011c182aSAndrew Mustea uint32_t ingr; /* 0x020 */ 47*011c182aSAndrew Mustea uint32_t svhesr; /* 0x024 */ 48*011c182aSAndrew Mustea uint32_t sfpcr; /* 0x028 */ 49*011c182aSAndrew Mustea uint32_t rsvd1[0x3]; /* 0x02C */ 50*011c182aSAndrew Mustea uint32_t version; /* 0x038 */ 51*011c182aSAndrew Mustea uint32_t rsvd2[0x71]; /* 0x03C */ 52*011c182aSAndrew Mustea uint32_t ospr0; /* 0x200 */ 53*011c182aSAndrew Mustea uint32_t ospr1; /* 0x204 */ 54*011c182aSAndrew Mustea uint32_t dcvr0; /* 0x208 */ 55*011c182aSAndrew Mustea uint32_t dcvr1; /* 0x20C */ 56*011c182aSAndrew Mustea uint32_t drvr0; /* 0x210 */ 57*011c182aSAndrew Mustea uint32_t drvr1; /* 0x214 */ 58*011c182aSAndrew Mustea uint32_t fswpr; /* 0x218 */ 59*011c182aSAndrew Mustea uint32_t fuidr0; /* 0x21C */ 60*011c182aSAndrew Mustea uint32_t fuidr1; /* 0x220 */ 61*011c182aSAndrew Mustea uint32_t isbccr; /* 0x224 */ 62*011c182aSAndrew Mustea uint32_t fspfr[0x3]; /* 0x228 */ 63*011c182aSAndrew Mustea uint32_t otpmkr[0x8]; /* 0x234 */ 64*011c182aSAndrew Mustea uint32_t srkhr[0x8]; /* 0x254 */ 65*011c182aSAndrew Mustea uint32_t ouidr[0x5]; /* 0x274 */ 66*011c182aSAndrew Mustea } *sfp_regs; 67*011c182aSAndrew Mustea 68*011c182aSAndrew Mustea /** 69*011c182aSAndrew Mustea * struct ls_gpio_info - Data struct containing GPIO specific information. 70*011c182aSAndrew Mustea * @gpio_pin: GPIO pin number. 71*011c182aSAndrew Mustea * @gpio_chip: GPIO controller instance data. 72*011c182aSAndrew Mustea */ 73*011c182aSAndrew Mustea static struct ls_gpio_info { 74*011c182aSAndrew Mustea uint32_t gpio_pin; 75*011c182aSAndrew Mustea struct ls_gpio_chip_data gpio_chip; 76*011c182aSAndrew Mustea } gpio_info; 77*011c182aSAndrew Mustea 78*011c182aSAndrew Mustea /** 79*011c182aSAndrew Mustea * ls_sfp_init() - Get SFP info from the embedded device tree and initialize 80*011c182aSAndrew Mustea * sfp_regs and gpio_info. 81*011c182aSAndrew Mustea * 82*011c182aSAndrew Mustea * Return: TEE_SUCCESS or > 0 on error. 83*011c182aSAndrew Mustea */ 84*011c182aSAndrew Mustea static TEE_Result ls_sfp_init(void) 85*011c182aSAndrew Mustea { 86*011c182aSAndrew Mustea size_t size = 0; 87*011c182aSAndrew Mustea int node = 0; 88*011c182aSAndrew Mustea int rc = 0; 89*011c182aSAndrew Mustea int povdd_node = 0; 90*011c182aSAndrew Mustea int prop_len = 0; 91*011c182aSAndrew Mustea vaddr_t ctrl_base = 0; 92*011c182aSAndrew Mustea struct ls_gpio_chip_data *gc = NULL; 93*011c182aSAndrew Mustea const char *fdt_prop_gpio = "povdd-gpio-controller"; 94*011c182aSAndrew Mustea const char *fdt_prop_pin = "povdd-gpio-pin"; 95*011c182aSAndrew Mustea const fdt32_t *gpio_val = NULL; 96*011c182aSAndrew Mustea const fdt32_t *pin_val = NULL; 97*011c182aSAndrew Mustea void *fdt = get_embedded_dt(); 98*011c182aSAndrew Mustea 99*011c182aSAndrew Mustea if (!fdt) { 100*011c182aSAndrew Mustea EMSG("Unable to get the Embedded DTB, SFP init failed"); 101*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 102*011c182aSAndrew Mustea } 103*011c182aSAndrew Mustea 104*011c182aSAndrew Mustea node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-sfp"); 105*011c182aSAndrew Mustea if (node <= 0) { 106*011c182aSAndrew Mustea EMSG("Unable to find SFP FDT node - rc = 0x%#"PRIx32, rc); 107*011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 108*011c182aSAndrew Mustea } 109*011c182aSAndrew Mustea 110*011c182aSAndrew Mustea rc = dt_map_dev(fdt, node, &ctrl_base, &size); 111*011c182aSAndrew Mustea if (rc < 0) { 112*011c182aSAndrew Mustea EMSG("Unable to get SFP virtual address - rc = 0x%#"PRIx32, rc); 113*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 114*011c182aSAndrew Mustea } 115*011c182aSAndrew Mustea 116*011c182aSAndrew Mustea povdd_node = fdt_path_offset(fdt, "/povdd"); 117*011c182aSAndrew Mustea if (povdd_node <= 0) { 118*011c182aSAndrew Mustea EMSG("Unable to find POVDD FDT node - rc = 0x%#"PRIx32, 119*011c182aSAndrew Mustea povdd_node); 120*011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 121*011c182aSAndrew Mustea } 122*011c182aSAndrew Mustea 123*011c182aSAndrew Mustea sfp_regs = (struct ls_sfp_registers *)ctrl_base; 124*011c182aSAndrew Mustea 125*011c182aSAndrew Mustea gpio_val = fdt_getprop(fdt, povdd_node, fdt_prop_gpio, &prop_len); 126*011c182aSAndrew Mustea if (!gpio_val) { 127*011c182aSAndrew Mustea EMSG("Missing %s from POVDD FDT node", fdt_prop_gpio); 128*011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 129*011c182aSAndrew Mustea } 130*011c182aSAndrew Mustea 131*011c182aSAndrew Mustea pin_val = fdt_getprop(fdt, povdd_node, fdt_prop_pin, &prop_len); 132*011c182aSAndrew Mustea if (!pin_val) { 133*011c182aSAndrew Mustea EMSG("Missing %s from POVDD FDT node", fdt_prop_pin); 134*011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 135*011c182aSAndrew Mustea } 136*011c182aSAndrew Mustea 137*011c182aSAndrew Mustea gc = &gpio_info.gpio_chip; 138*011c182aSAndrew Mustea gc->gpio_controller = (uint8_t)fdt32_to_cpu(*gpio_val); 139*011c182aSAndrew Mustea gpio_info.gpio_pin = fdt32_to_cpu(*pin_val); 140*011c182aSAndrew Mustea 141*011c182aSAndrew Mustea return ls_gpio_init(gc); 142*011c182aSAndrew Mustea } 143*011c182aSAndrew Mustea 144*011c182aSAndrew Mustea /** 145*011c182aSAndrew Mustea * ls_sfp_program_fuses() - Write to fuses and verify that the correct value was 146*011c182aSAndrew Mustea * written. 147*011c182aSAndrew Mustea * 148*011c182aSAndrew Mustea * Return: TEE_SUCCESS or > 0 on error. 149*011c182aSAndrew Mustea */ 150*011c182aSAndrew Mustea static TEE_Result ls_sfp_program_fuses(void) 151*011c182aSAndrew Mustea { 152*011c182aSAndrew Mustea struct gpio_chip *gc = NULL; 153*011c182aSAndrew Mustea uint32_t pin = gpio_info.gpio_pin; 154*011c182aSAndrew Mustea vaddr_t sfp_ingr_va = (vaddr_t)&sfp_regs->ingr; 155*011c182aSAndrew Mustea uint64_t timeout = 0; 156*011c182aSAndrew Mustea 157*011c182aSAndrew Mustea /* Enable POVDD */ 158*011c182aSAndrew Mustea gc = &gpio_info.gpio_chip.chip; 159*011c182aSAndrew Mustea 160*011c182aSAndrew Mustea DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to HIGH", 161*011c182aSAndrew Mustea (uint32_t)gpio_info.gpio_chip.gpio_controller, pin); 162*011c182aSAndrew Mustea gc->ops->set_direction(gc, pin, GPIO_DIR_OUT); 163*011c182aSAndrew Mustea gc->ops->set_value(gc, pin, GPIO_LEVEL_HIGH); 164*011c182aSAndrew Mustea 165*011c182aSAndrew Mustea if (gc->ops->get_value(gc, pin) != GPIO_LEVEL_HIGH) { 166*011c182aSAndrew Mustea EMSG("Error setting POVDD to HIGH"); 167*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 168*011c182aSAndrew Mustea } 169*011c182aSAndrew Mustea 170*011c182aSAndrew Mustea /* TA_PROG_SFP ramp rate requires up to 5ms for stability */ 171*011c182aSAndrew Mustea mdelay(5); 172*011c182aSAndrew Mustea 173*011c182aSAndrew Mustea /* Send SFP write command */ 174*011c182aSAndrew Mustea io_write32(sfp_ingr_va, SFP_INGR_PROGFB_CMD); 175*011c182aSAndrew Mustea 176*011c182aSAndrew Mustea /* Wait until fuse programming is successful */ 177*011c182aSAndrew Mustea timeout = timeout_init_us(SFP_INGR_FUSE_TIMEOUT); 178*011c182aSAndrew Mustea while (io_read32(sfp_ingr_va) & SFP_INGR_PROGFB_CMD) { 179*011c182aSAndrew Mustea if (timeout_elapsed(timeout)) { 180*011c182aSAndrew Mustea EMSG("SFP fusing timed out"); 181*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 182*011c182aSAndrew Mustea } 183*011c182aSAndrew Mustea } 184*011c182aSAndrew Mustea 185*011c182aSAndrew Mustea /* Check for SFP fuse programming error */ 186*011c182aSAndrew Mustea if (io_read32(sfp_ingr_va) & SFP_INGR_ERROR_MASK) { 187*011c182aSAndrew Mustea EMSG("Error writing SFP fuses"); 188*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 189*011c182aSAndrew Mustea } 190*011c182aSAndrew Mustea 191*011c182aSAndrew Mustea DMSG("Programmed fuse successfully"); 192*011c182aSAndrew Mustea 193*011c182aSAndrew Mustea /* Disable POVDD */ 194*011c182aSAndrew Mustea DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to LOW", 195*011c182aSAndrew Mustea (uint32_t)gpio_info.gpio_chip.gpio_controller, pin); 196*011c182aSAndrew Mustea gc->ops->set_value(gc, pin, GPIO_LEVEL_LOW); 197*011c182aSAndrew Mustea gc->ops->set_direction(gc, pin, GPIO_DIR_IN); 198*011c182aSAndrew Mustea 199*011c182aSAndrew Mustea return TEE_SUCCESS; 200*011c182aSAndrew Mustea } 201*011c182aSAndrew Mustea 202*011c182aSAndrew Mustea TEE_Result ls_sfp_read(struct ls_sfp_data *data) 203*011c182aSAndrew Mustea { 204*011c182aSAndrew Mustea if (!sfp_regs) { 205*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 206*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 207*011c182aSAndrew Mustea } 208*011c182aSAndrew Mustea 209*011c182aSAndrew Mustea if (!data) 210*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 211*011c182aSAndrew Mustea 212*011c182aSAndrew Mustea data->ingr = io_read32((vaddr_t)&sfp_regs->ingr); 213*011c182aSAndrew Mustea data->svhesr = io_read32((vaddr_t)&sfp_regs->svhesr); 214*011c182aSAndrew Mustea data->sfpcr = io_read32((vaddr_t)&sfp_regs->sfpcr); 215*011c182aSAndrew Mustea data->version = io_read32((vaddr_t)&sfp_regs->version); 216*011c182aSAndrew Mustea data->ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); 217*011c182aSAndrew Mustea data->ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); 218*011c182aSAndrew Mustea data->dcvr0 = io_read32((vaddr_t)&sfp_regs->dcvr0); 219*011c182aSAndrew Mustea data->dcvr1 = io_read32((vaddr_t)&sfp_regs->dcvr1); 220*011c182aSAndrew Mustea data->drvr0 = io_read32((vaddr_t)&sfp_regs->drvr0); 221*011c182aSAndrew Mustea data->drvr1 = io_read32((vaddr_t)&sfp_regs->drvr1); 222*011c182aSAndrew Mustea data->fswpr = io_read32((vaddr_t)&sfp_regs->fswpr); 223*011c182aSAndrew Mustea data->fuidr0 = io_read32((vaddr_t)&sfp_regs->fuidr0); 224*011c182aSAndrew Mustea data->fuidr1 = io_read32((vaddr_t)&sfp_regs->fuidr1); 225*011c182aSAndrew Mustea data->isbccr = io_read32((vaddr_t)&sfp_regs->isbccr); 226*011c182aSAndrew Mustea 227*011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->fspfr); ++i) 228*011c182aSAndrew Mustea data->fspfr[i] = io_read32((vaddr_t)&sfp_regs->fspfr[i]); 229*011c182aSAndrew Mustea 230*011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->otpmkr); ++i) 231*011c182aSAndrew Mustea data->otpmkr[i] = io_read32((vaddr_t)&sfp_regs->otpmkr[i]); 232*011c182aSAndrew Mustea 233*011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->srkhr); ++i) 234*011c182aSAndrew Mustea data->srkhr[i] = io_read32((vaddr_t)&sfp_regs->srkhr[i]); 235*011c182aSAndrew Mustea 236*011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->ouidr); ++i) 237*011c182aSAndrew Mustea data->ouidr[i] = io_read32((vaddr_t)&sfp_regs->ouidr[i]); 238*011c182aSAndrew Mustea 239*011c182aSAndrew Mustea return TEE_SUCCESS; 240*011c182aSAndrew Mustea } 241*011c182aSAndrew Mustea 242*011c182aSAndrew Mustea TEE_Result ls_sfp_get_debug_level(uint32_t *dblev) 243*011c182aSAndrew Mustea { 244*011c182aSAndrew Mustea if (!sfp_regs) { 245*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 246*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 247*011c182aSAndrew Mustea } 248*011c182aSAndrew Mustea 249*011c182aSAndrew Mustea if (!dblev) 250*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 251*011c182aSAndrew Mustea 252*011c182aSAndrew Mustea *dblev = io_read32((vaddr_t)&sfp_regs->ospr1) & SFP_OSPR1_DBLEV_MASK; 253*011c182aSAndrew Mustea 254*011c182aSAndrew Mustea return TEE_SUCCESS; 255*011c182aSAndrew Mustea } 256*011c182aSAndrew Mustea 257*011c182aSAndrew Mustea TEE_Result ls_sfp_get_its(uint32_t *its) 258*011c182aSAndrew Mustea { 259*011c182aSAndrew Mustea if (!sfp_regs) { 260*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 261*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 262*011c182aSAndrew Mustea } 263*011c182aSAndrew Mustea 264*011c182aSAndrew Mustea if (!its) 265*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 266*011c182aSAndrew Mustea 267*011c182aSAndrew Mustea *its = io_read32((vaddr_t)&sfp_regs->ospr0) & SFP_OSPR0_ITS; 268*011c182aSAndrew Mustea 269*011c182aSAndrew Mustea return TEE_SUCCESS; 270*011c182aSAndrew Mustea } 271*011c182aSAndrew Mustea 272*011c182aSAndrew Mustea TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid) 273*011c182aSAndrew Mustea { 274*011c182aSAndrew Mustea if (!sfp_regs) { 275*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 276*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 277*011c182aSAndrew Mustea } 278*011c182aSAndrew Mustea 279*011c182aSAndrew Mustea if (!ouid) 280*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 281*011c182aSAndrew Mustea 282*011c182aSAndrew Mustea if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { 283*011c182aSAndrew Mustea DMSG("Index greater or equal to ouid: %"PRIu32" >= %zu", 284*011c182aSAndrew Mustea index, ARRAY_SIZE(sfp_regs->ouidr)); 285*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 286*011c182aSAndrew Mustea } 287*011c182aSAndrew Mustea 288*011c182aSAndrew Mustea *ouid = io_read32((vaddr_t)&sfp_regs->ouidr[index]); 289*011c182aSAndrew Mustea 290*011c182aSAndrew Mustea return TEE_SUCCESS; 291*011c182aSAndrew Mustea } 292*011c182aSAndrew Mustea 293*011c182aSAndrew Mustea TEE_Result ls_sfp_get_sb(uint32_t *sb) 294*011c182aSAndrew Mustea { 295*011c182aSAndrew Mustea if (!sfp_regs) { 296*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 297*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 298*011c182aSAndrew Mustea } 299*011c182aSAndrew Mustea 300*011c182aSAndrew Mustea if (!sb) 301*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 302*011c182aSAndrew Mustea 303*011c182aSAndrew Mustea *sb = io_read32((vaddr_t)&sfp_regs->sfpcr) & SFP_SFPCR_SB; 304*011c182aSAndrew Mustea 305*011c182aSAndrew Mustea return TEE_SUCCESS; 306*011c182aSAndrew Mustea } 307*011c182aSAndrew Mustea 308*011c182aSAndrew Mustea TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh) 309*011c182aSAndrew Mustea { 310*011c182aSAndrew Mustea if (!sfp_regs) { 311*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 312*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 313*011c182aSAndrew Mustea } 314*011c182aSAndrew Mustea 315*011c182aSAndrew Mustea if (!srkh) 316*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 317*011c182aSAndrew Mustea 318*011c182aSAndrew Mustea if (index >= ARRAY_SIZE(sfp_regs->srkhr)) { 319*011c182aSAndrew Mustea DMSG("Index greater or equal to srkhr: %"PRIu32" >= %zu", 320*011c182aSAndrew Mustea index, ARRAY_SIZE(sfp_regs->srkhr)); 321*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 322*011c182aSAndrew Mustea } 323*011c182aSAndrew Mustea 324*011c182aSAndrew Mustea *srkh = io_read32((vaddr_t)&sfp_regs->srkhr[index]); 325*011c182aSAndrew Mustea 326*011c182aSAndrew Mustea return TEE_SUCCESS; 327*011c182aSAndrew Mustea } 328*011c182aSAndrew Mustea 329*011c182aSAndrew Mustea TEE_Result ls_sfp_set_debug_level(uint32_t dblev) 330*011c182aSAndrew Mustea { 331*011c182aSAndrew Mustea uint32_t ospr1 = 0; 332*011c182aSAndrew Mustea 333*011c182aSAndrew Mustea if (!sfp_regs) { 334*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 335*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 336*011c182aSAndrew Mustea } 337*011c182aSAndrew Mustea 338*011c182aSAndrew Mustea if (!dblev) 339*011c182aSAndrew Mustea return TEE_SUCCESS; 340*011c182aSAndrew Mustea 341*011c182aSAndrew Mustea ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); 342*011c182aSAndrew Mustea if (ospr1 & SFP_OSPR1_DBLEV_MASK) { 343*011c182aSAndrew Mustea DMSG("Debug level has already been fused"); 344*011c182aSAndrew Mustea return TEE_ERROR_SECURITY; 345*011c182aSAndrew Mustea } 346*011c182aSAndrew Mustea 347*011c182aSAndrew Mustea io_write32((vaddr_t)&sfp_regs->ospr1, ospr1 | dblev); 348*011c182aSAndrew Mustea 349*011c182aSAndrew Mustea return ls_sfp_program_fuses(); 350*011c182aSAndrew Mustea } 351*011c182aSAndrew Mustea 352*011c182aSAndrew Mustea TEE_Result ls_sfp_set_its_wp(void) 353*011c182aSAndrew Mustea { 354*011c182aSAndrew Mustea uint32_t ospr0 = 0; 355*011c182aSAndrew Mustea 356*011c182aSAndrew Mustea if (!sfp_regs) { 357*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 358*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 359*011c182aSAndrew Mustea } 360*011c182aSAndrew Mustea 361*011c182aSAndrew Mustea ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); 362*011c182aSAndrew Mustea if (ospr0 & (SFP_OSPR0_WP | SFP_OSPR0_ITS)) { 363*011c182aSAndrew Mustea DMSG("SFP is already fused"); 364*011c182aSAndrew Mustea return TEE_ERROR_SECURITY; 365*011c182aSAndrew Mustea } 366*011c182aSAndrew Mustea 367*011c182aSAndrew Mustea ospr0 |= SFP_OSPR0_WP | SFP_OSPR0_ITS; 368*011c182aSAndrew Mustea io_write32((vaddr_t)&sfp_regs->ospr0, ospr0); 369*011c182aSAndrew Mustea 370*011c182aSAndrew Mustea return ls_sfp_program_fuses(); 371*011c182aSAndrew Mustea } 372*011c182aSAndrew Mustea 373*011c182aSAndrew Mustea TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid) 374*011c182aSAndrew Mustea { 375*011c182aSAndrew Mustea if (!sfp_regs) { 376*011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 377*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 378*011c182aSAndrew Mustea } 379*011c182aSAndrew Mustea 380*011c182aSAndrew Mustea if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { 381*011c182aSAndrew Mustea DMSG("Index greater or equal to ouid: %"PRIu32" >= %"PRIu32, 382*011c182aSAndrew Mustea index, ARRAY_SIZE(sfp_regs->ouidr)); 383*011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 384*011c182aSAndrew Mustea } 385*011c182aSAndrew Mustea 386*011c182aSAndrew Mustea io_write32((vaddr_t)&sfp_regs->ouidr[index], ouid); 387*011c182aSAndrew Mustea 388*011c182aSAndrew Mustea return ls_sfp_program_fuses(); 389*011c182aSAndrew Mustea } 390*011c182aSAndrew Mustea 391*011c182aSAndrew Mustea TEE_Result ls_sfp_status(void) 392*011c182aSAndrew Mustea { 393*011c182aSAndrew Mustea if (!sfp_regs) 394*011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 395*011c182aSAndrew Mustea 396*011c182aSAndrew Mustea return TEE_SUCCESS; 397*011c182aSAndrew Mustea } 398*011c182aSAndrew Mustea 399*011c182aSAndrew Mustea driver_init(ls_sfp_init); 400