1011c182aSAndrew Mustea // SPDX-License-Identifier: BSD-2-Clause 2011c182aSAndrew Mustea /* 3011c182aSAndrew Mustea * Copyright 2022 Microsoft 4011c182aSAndrew Mustea * 5011c182aSAndrew Mustea * Driver for the NXP LX2160A-series Security Fuse Processor (SFP). 6011c182aSAndrew Mustea */ 7011c182aSAndrew Mustea 8011c182aSAndrew Mustea #include <assert.h> 9011c182aSAndrew Mustea #include <drivers/ls_sfp.h> 10011c182aSAndrew Mustea #include <io.h> 11011c182aSAndrew Mustea #include <kernel/boot.h> 12011c182aSAndrew Mustea #include <kernel/delay.h> 13011c182aSAndrew Mustea #include <kernel/dt.h> 14011c182aSAndrew Mustea #include <kernel/panic.h> 15011c182aSAndrew Mustea #include <kernel/tee_time.h> 16011c182aSAndrew Mustea #include <libfdt.h> 17011c182aSAndrew Mustea #include <mm/core_memprot.h> 18011c182aSAndrew Mustea #include <util.h> 19011c182aSAndrew Mustea 20011c182aSAndrew Mustea /** 21011c182aSAndrew Mustea * struct ls_sfp_registers - Memory map of the SFP registers. 22011c182aSAndrew Mustea * @rsvd0[0x8]: Reserved. 23011c182aSAndrew Mustea * @ingr: Instruction Register. 24011c182aSAndrew Mustea * @svhesr: Secret Value Hamming Error Status Registers. 25011c182aSAndrew Mustea * @sfpcr: SFP Configuration Register. 26011c182aSAndrew Mustea * @rsvd1[0x3]: Reserved. 27011c182aSAndrew Mustea * @version: SFP Version Register. 28011c182aSAndrew Mustea * @rsvd2[0x71]: Reserved. 29011c182aSAndrew Mustea * @ospr0: OEM Security Policy Register 0. 30011c182aSAndrew Mustea * @ospr1: OEM Security Policy Register 1. 31011c182aSAndrew Mustea * @dcvr0: Debug Challenge Value Register 0. 32011c182aSAndrew Mustea * @dcvr1: Debug Challenge Value Register 1. 33011c182aSAndrew Mustea * @drvr0: Debug Response Value Register 0. 34011c182aSAndrew Mustea * @drvr1: Debug Response Value Register 1 35011c182aSAndrew Mustea * @fswpr: Factory Section Write Protect Register. 36011c182aSAndrew Mustea * @fuidr0: Factory Unique ID Register 0. 37011c182aSAndrew Mustea * @fuidr1: Factory Unique ID Register 1. 38011c182aSAndrew Mustea * @isbccr: ISBC Configuration Register. 39011c182aSAndrew Mustea * @fspfr[0x3]: Factory Scratch Pad Fuse Registers. 40011c182aSAndrew Mustea * @otpmkr[0x8]: One Time Programmable Master Key. 41011c182aSAndrew Mustea * @srkhr[0x8]: Super Root Key Hash. 42011c182aSAndrew Mustea * @ouidr[0x5]: OEM Unique ID Scratch Pad Fuse Registers. 43011c182aSAndrew Mustea */ 44011c182aSAndrew Mustea static struct ls_sfp_registers { 45011c182aSAndrew Mustea uint32_t rsvd0[0x8]; /* 0x000 */ 46011c182aSAndrew Mustea uint32_t ingr; /* 0x020 */ 47011c182aSAndrew Mustea uint32_t svhesr; /* 0x024 */ 48011c182aSAndrew Mustea uint32_t sfpcr; /* 0x028 */ 49011c182aSAndrew Mustea uint32_t rsvd1[0x3]; /* 0x02C */ 50011c182aSAndrew Mustea uint32_t version; /* 0x038 */ 51011c182aSAndrew Mustea uint32_t rsvd2[0x71]; /* 0x03C */ 52011c182aSAndrew Mustea uint32_t ospr0; /* 0x200 */ 53011c182aSAndrew Mustea uint32_t ospr1; /* 0x204 */ 54011c182aSAndrew Mustea uint32_t dcvr0; /* 0x208 */ 55011c182aSAndrew Mustea uint32_t dcvr1; /* 0x20C */ 56011c182aSAndrew Mustea uint32_t drvr0; /* 0x210 */ 57011c182aSAndrew Mustea uint32_t drvr1; /* 0x214 */ 58011c182aSAndrew Mustea uint32_t fswpr; /* 0x218 */ 59011c182aSAndrew Mustea uint32_t fuidr0; /* 0x21C */ 60011c182aSAndrew Mustea uint32_t fuidr1; /* 0x220 */ 61011c182aSAndrew Mustea uint32_t isbccr; /* 0x224 */ 62011c182aSAndrew Mustea uint32_t fspfr[0x3]; /* 0x228 */ 63011c182aSAndrew Mustea uint32_t otpmkr[0x8]; /* 0x234 */ 64011c182aSAndrew Mustea uint32_t srkhr[0x8]; /* 0x254 */ 65011c182aSAndrew Mustea uint32_t ouidr[0x5]; /* 0x274 */ 66011c182aSAndrew Mustea } *sfp_regs; 67011c182aSAndrew Mustea 68011c182aSAndrew Mustea /** 69011c182aSAndrew Mustea * struct ls_gpio_info - Data struct containing GPIO specific information. 70011c182aSAndrew Mustea * @gpio_pin: GPIO pin number. 71011c182aSAndrew Mustea * @gpio_chip: GPIO controller instance data. 72011c182aSAndrew Mustea */ 73011c182aSAndrew Mustea static struct ls_gpio_info { 74011c182aSAndrew Mustea uint32_t gpio_pin; 75011c182aSAndrew Mustea struct ls_gpio_chip_data gpio_chip; 76011c182aSAndrew Mustea } gpio_info; 77011c182aSAndrew Mustea 78011c182aSAndrew Mustea /** 79011c182aSAndrew Mustea * ls_sfp_init() - Get SFP info from the embedded device tree and initialize 80011c182aSAndrew Mustea * sfp_regs and gpio_info. 81011c182aSAndrew Mustea * 82011c182aSAndrew Mustea * Return: TEE_SUCCESS or > 0 on error. 83011c182aSAndrew Mustea */ 84011c182aSAndrew Mustea static TEE_Result ls_sfp_init(void) 85011c182aSAndrew Mustea { 86011c182aSAndrew Mustea size_t size = 0; 87011c182aSAndrew Mustea int node = 0; 88011c182aSAndrew Mustea int rc = 0; 89011c182aSAndrew Mustea int povdd_node = 0; 90011c182aSAndrew Mustea int prop_len = 0; 91011c182aSAndrew Mustea vaddr_t ctrl_base = 0; 92011c182aSAndrew Mustea struct ls_gpio_chip_data *gc = NULL; 93011c182aSAndrew Mustea const char *fdt_prop_gpio = "povdd-gpio-controller"; 94011c182aSAndrew Mustea const char *fdt_prop_pin = "povdd-gpio-pin"; 95011c182aSAndrew Mustea const fdt32_t *gpio_val = NULL; 96011c182aSAndrew Mustea const fdt32_t *pin_val = NULL; 97011c182aSAndrew Mustea void *fdt = get_embedded_dt(); 98011c182aSAndrew Mustea 99011c182aSAndrew Mustea if (!fdt) { 100011c182aSAndrew Mustea EMSG("Unable to get the Embedded DTB, SFP init failed"); 101011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 102011c182aSAndrew Mustea } 103011c182aSAndrew Mustea 104011c182aSAndrew Mustea node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-sfp"); 105011c182aSAndrew Mustea if (node <= 0) { 106011c182aSAndrew Mustea EMSG("Unable to find SFP FDT node - rc = 0x%#"PRIx32, rc); 107011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 108011c182aSAndrew Mustea } 109011c182aSAndrew Mustea 110011c182aSAndrew Mustea rc = dt_map_dev(fdt, node, &ctrl_base, &size); 111011c182aSAndrew Mustea if (rc < 0) { 112011c182aSAndrew Mustea EMSG("Unable to get SFP virtual address - rc = 0x%#"PRIx32, rc); 113011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 114011c182aSAndrew Mustea } 115011c182aSAndrew Mustea 116011c182aSAndrew Mustea povdd_node = fdt_path_offset(fdt, "/povdd"); 117011c182aSAndrew Mustea if (povdd_node <= 0) { 118011c182aSAndrew Mustea EMSG("Unable to find POVDD FDT node - rc = 0x%#"PRIx32, 119011c182aSAndrew Mustea povdd_node); 120011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 121011c182aSAndrew Mustea } 122011c182aSAndrew Mustea 123011c182aSAndrew Mustea sfp_regs = (struct ls_sfp_registers *)ctrl_base; 124011c182aSAndrew Mustea 125011c182aSAndrew Mustea gpio_val = fdt_getprop(fdt, povdd_node, fdt_prop_gpio, &prop_len); 126011c182aSAndrew Mustea if (!gpio_val) { 127011c182aSAndrew Mustea EMSG("Missing %s from POVDD FDT node", fdt_prop_gpio); 128011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 129011c182aSAndrew Mustea } 130011c182aSAndrew Mustea 131011c182aSAndrew Mustea pin_val = fdt_getprop(fdt, povdd_node, fdt_prop_pin, &prop_len); 132011c182aSAndrew Mustea if (!pin_val) { 133011c182aSAndrew Mustea EMSG("Missing %s from POVDD FDT node", fdt_prop_pin); 134011c182aSAndrew Mustea return TEE_ERROR_ITEM_NOT_FOUND; 135011c182aSAndrew Mustea } 136011c182aSAndrew Mustea 137011c182aSAndrew Mustea gc = &gpio_info.gpio_chip; 138011c182aSAndrew Mustea gc->gpio_controller = (uint8_t)fdt32_to_cpu(*gpio_val); 139011c182aSAndrew Mustea gpio_info.gpio_pin = fdt32_to_cpu(*pin_val); 140011c182aSAndrew Mustea 141011c182aSAndrew Mustea return ls_gpio_init(gc); 142011c182aSAndrew Mustea } 143011c182aSAndrew Mustea 144011c182aSAndrew Mustea /** 145011c182aSAndrew Mustea * ls_sfp_program_fuses() - Write to fuses and verify that the correct value was 146011c182aSAndrew Mustea * written. 147011c182aSAndrew Mustea * 148011c182aSAndrew Mustea * Return: TEE_SUCCESS or > 0 on error. 149011c182aSAndrew Mustea */ 150011c182aSAndrew Mustea static TEE_Result ls_sfp_program_fuses(void) 151011c182aSAndrew Mustea { 152011c182aSAndrew Mustea struct gpio_chip *gc = NULL; 153011c182aSAndrew Mustea uint32_t pin = gpio_info.gpio_pin; 154011c182aSAndrew Mustea vaddr_t sfp_ingr_va = (vaddr_t)&sfp_regs->ingr; 155011c182aSAndrew Mustea uint64_t timeout = 0; 156011c182aSAndrew Mustea 157011c182aSAndrew Mustea /* Enable POVDD */ 158011c182aSAndrew Mustea gc = &gpio_info.gpio_chip.chip; 159011c182aSAndrew Mustea 160011c182aSAndrew Mustea DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to HIGH", 161011c182aSAndrew Mustea (uint32_t)gpio_info.gpio_chip.gpio_controller, pin); 162011c182aSAndrew Mustea gc->ops->set_direction(gc, pin, GPIO_DIR_OUT); 163011c182aSAndrew Mustea gc->ops->set_value(gc, pin, GPIO_LEVEL_HIGH); 164011c182aSAndrew Mustea 165011c182aSAndrew Mustea if (gc->ops->get_value(gc, pin) != GPIO_LEVEL_HIGH) { 166011c182aSAndrew Mustea EMSG("Error setting POVDD to HIGH"); 167011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 168011c182aSAndrew Mustea } 169011c182aSAndrew Mustea 170011c182aSAndrew Mustea /* TA_PROG_SFP ramp rate requires up to 5ms for stability */ 171011c182aSAndrew Mustea mdelay(5); 172011c182aSAndrew Mustea 173011c182aSAndrew Mustea /* Send SFP write command */ 174011c182aSAndrew Mustea io_write32(sfp_ingr_va, SFP_INGR_PROGFB_CMD); 175011c182aSAndrew Mustea 176011c182aSAndrew Mustea /* Wait until fuse programming is successful */ 177*385b0436SAndrew Mustea timeout = timeout_init_us(SFP_INGR_FUSE_TIMEOUT_US); 178011c182aSAndrew Mustea while (io_read32(sfp_ingr_va) & SFP_INGR_PROGFB_CMD) { 179011c182aSAndrew Mustea if (timeout_elapsed(timeout)) { 180011c182aSAndrew Mustea EMSG("SFP fusing timed out"); 181011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 182011c182aSAndrew Mustea } 183011c182aSAndrew Mustea } 184011c182aSAndrew Mustea 185011c182aSAndrew Mustea /* Check for SFP fuse programming error */ 186011c182aSAndrew Mustea if (io_read32(sfp_ingr_va) & SFP_INGR_ERROR_MASK) { 187011c182aSAndrew Mustea EMSG("Error writing SFP fuses"); 188011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 189011c182aSAndrew Mustea } 190011c182aSAndrew Mustea 191011c182aSAndrew Mustea DMSG("Programmed fuse successfully"); 192011c182aSAndrew Mustea 193011c182aSAndrew Mustea /* Disable POVDD */ 194011c182aSAndrew Mustea DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to LOW", 195011c182aSAndrew Mustea (uint32_t)gpio_info.gpio_chip.gpio_controller, pin); 196011c182aSAndrew Mustea gc->ops->set_value(gc, pin, GPIO_LEVEL_LOW); 197011c182aSAndrew Mustea gc->ops->set_direction(gc, pin, GPIO_DIR_IN); 198011c182aSAndrew Mustea 199011c182aSAndrew Mustea return TEE_SUCCESS; 200011c182aSAndrew Mustea } 201011c182aSAndrew Mustea 202011c182aSAndrew Mustea TEE_Result ls_sfp_read(struct ls_sfp_data *data) 203011c182aSAndrew Mustea { 204011c182aSAndrew Mustea if (!sfp_regs) { 205011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 206011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 207011c182aSAndrew Mustea } 208011c182aSAndrew Mustea 209011c182aSAndrew Mustea if (!data) 210011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 211011c182aSAndrew Mustea 212011c182aSAndrew Mustea data->ingr = io_read32((vaddr_t)&sfp_regs->ingr); 213011c182aSAndrew Mustea data->svhesr = io_read32((vaddr_t)&sfp_regs->svhesr); 214011c182aSAndrew Mustea data->sfpcr = io_read32((vaddr_t)&sfp_regs->sfpcr); 215011c182aSAndrew Mustea data->version = io_read32((vaddr_t)&sfp_regs->version); 216011c182aSAndrew Mustea data->ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); 217011c182aSAndrew Mustea data->ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); 218011c182aSAndrew Mustea data->dcvr0 = io_read32((vaddr_t)&sfp_regs->dcvr0); 219011c182aSAndrew Mustea data->dcvr1 = io_read32((vaddr_t)&sfp_regs->dcvr1); 220011c182aSAndrew Mustea data->drvr0 = io_read32((vaddr_t)&sfp_regs->drvr0); 221011c182aSAndrew Mustea data->drvr1 = io_read32((vaddr_t)&sfp_regs->drvr1); 222011c182aSAndrew Mustea data->fswpr = io_read32((vaddr_t)&sfp_regs->fswpr); 223011c182aSAndrew Mustea data->fuidr0 = io_read32((vaddr_t)&sfp_regs->fuidr0); 224011c182aSAndrew Mustea data->fuidr1 = io_read32((vaddr_t)&sfp_regs->fuidr1); 225011c182aSAndrew Mustea data->isbccr = io_read32((vaddr_t)&sfp_regs->isbccr); 226011c182aSAndrew Mustea 227011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->fspfr); ++i) 228011c182aSAndrew Mustea data->fspfr[i] = io_read32((vaddr_t)&sfp_regs->fspfr[i]); 229011c182aSAndrew Mustea 230011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->otpmkr); ++i) 231011c182aSAndrew Mustea data->otpmkr[i] = io_read32((vaddr_t)&sfp_regs->otpmkr[i]); 232011c182aSAndrew Mustea 233011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->srkhr); ++i) 234011c182aSAndrew Mustea data->srkhr[i] = io_read32((vaddr_t)&sfp_regs->srkhr[i]); 235011c182aSAndrew Mustea 236011c182aSAndrew Mustea for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->ouidr); ++i) 237011c182aSAndrew Mustea data->ouidr[i] = io_read32((vaddr_t)&sfp_regs->ouidr[i]); 238011c182aSAndrew Mustea 239011c182aSAndrew Mustea return TEE_SUCCESS; 240011c182aSAndrew Mustea } 241011c182aSAndrew Mustea 242011c182aSAndrew Mustea TEE_Result ls_sfp_get_debug_level(uint32_t *dblev) 243011c182aSAndrew Mustea { 244011c182aSAndrew Mustea if (!sfp_regs) { 245011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 246011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 247011c182aSAndrew Mustea } 248011c182aSAndrew Mustea 249011c182aSAndrew Mustea if (!dblev) 250011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 251011c182aSAndrew Mustea 252011c182aSAndrew Mustea *dblev = io_read32((vaddr_t)&sfp_regs->ospr1) & SFP_OSPR1_DBLEV_MASK; 253011c182aSAndrew Mustea 254011c182aSAndrew Mustea return TEE_SUCCESS; 255011c182aSAndrew Mustea } 256011c182aSAndrew Mustea 257011c182aSAndrew Mustea TEE_Result ls_sfp_get_its(uint32_t *its) 258011c182aSAndrew Mustea { 259011c182aSAndrew Mustea if (!sfp_regs) { 260011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 261011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 262011c182aSAndrew Mustea } 263011c182aSAndrew Mustea 264011c182aSAndrew Mustea if (!its) 265011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 266011c182aSAndrew Mustea 267011c182aSAndrew Mustea *its = io_read32((vaddr_t)&sfp_regs->ospr0) & SFP_OSPR0_ITS; 268011c182aSAndrew Mustea 269011c182aSAndrew Mustea return TEE_SUCCESS; 270011c182aSAndrew Mustea } 271011c182aSAndrew Mustea 272011c182aSAndrew Mustea TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid) 273011c182aSAndrew Mustea { 274011c182aSAndrew Mustea if (!sfp_regs) { 275011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 276011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 277011c182aSAndrew Mustea } 278011c182aSAndrew Mustea 279011c182aSAndrew Mustea if (!ouid) 280011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 281011c182aSAndrew Mustea 282011c182aSAndrew Mustea if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { 283011c182aSAndrew Mustea DMSG("Index greater or equal to ouid: %"PRIu32" >= %zu", 284011c182aSAndrew Mustea index, ARRAY_SIZE(sfp_regs->ouidr)); 285011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 286011c182aSAndrew Mustea } 287011c182aSAndrew Mustea 288011c182aSAndrew Mustea *ouid = io_read32((vaddr_t)&sfp_regs->ouidr[index]); 289011c182aSAndrew Mustea 290011c182aSAndrew Mustea return TEE_SUCCESS; 291011c182aSAndrew Mustea } 292011c182aSAndrew Mustea 293011c182aSAndrew Mustea TEE_Result ls_sfp_get_sb(uint32_t *sb) 294011c182aSAndrew Mustea { 295011c182aSAndrew Mustea if (!sfp_regs) { 296011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 297011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 298011c182aSAndrew Mustea } 299011c182aSAndrew Mustea 300011c182aSAndrew Mustea if (!sb) 301011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 302011c182aSAndrew Mustea 303011c182aSAndrew Mustea *sb = io_read32((vaddr_t)&sfp_regs->sfpcr) & SFP_SFPCR_SB; 304011c182aSAndrew Mustea 305011c182aSAndrew Mustea return TEE_SUCCESS; 306011c182aSAndrew Mustea } 307011c182aSAndrew Mustea 308011c182aSAndrew Mustea TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh) 309011c182aSAndrew Mustea { 310011c182aSAndrew Mustea if (!sfp_regs) { 311011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 312011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 313011c182aSAndrew Mustea } 314011c182aSAndrew Mustea 315011c182aSAndrew Mustea if (!srkh) 316011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 317011c182aSAndrew Mustea 318011c182aSAndrew Mustea if (index >= ARRAY_SIZE(sfp_regs->srkhr)) { 319011c182aSAndrew Mustea DMSG("Index greater or equal to srkhr: %"PRIu32" >= %zu", 320011c182aSAndrew Mustea index, ARRAY_SIZE(sfp_regs->srkhr)); 321011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 322011c182aSAndrew Mustea } 323011c182aSAndrew Mustea 324011c182aSAndrew Mustea *srkh = io_read32((vaddr_t)&sfp_regs->srkhr[index]); 325011c182aSAndrew Mustea 326011c182aSAndrew Mustea return TEE_SUCCESS; 327011c182aSAndrew Mustea } 328011c182aSAndrew Mustea 329011c182aSAndrew Mustea TEE_Result ls_sfp_set_debug_level(uint32_t dblev) 330011c182aSAndrew Mustea { 331011c182aSAndrew Mustea uint32_t ospr1 = 0; 332011c182aSAndrew Mustea 333011c182aSAndrew Mustea if (!sfp_regs) { 334011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 335011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 336011c182aSAndrew Mustea } 337011c182aSAndrew Mustea 338011c182aSAndrew Mustea if (!dblev) 339011c182aSAndrew Mustea return TEE_SUCCESS; 340011c182aSAndrew Mustea 341011c182aSAndrew Mustea ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); 342011c182aSAndrew Mustea if (ospr1 & SFP_OSPR1_DBLEV_MASK) { 343011c182aSAndrew Mustea DMSG("Debug level has already been fused"); 344011c182aSAndrew Mustea return TEE_ERROR_SECURITY; 345011c182aSAndrew Mustea } 346011c182aSAndrew Mustea 347011c182aSAndrew Mustea io_write32((vaddr_t)&sfp_regs->ospr1, ospr1 | dblev); 348011c182aSAndrew Mustea 349011c182aSAndrew Mustea return ls_sfp_program_fuses(); 350011c182aSAndrew Mustea } 351011c182aSAndrew Mustea 352011c182aSAndrew Mustea TEE_Result ls_sfp_set_its_wp(void) 353011c182aSAndrew Mustea { 354011c182aSAndrew Mustea uint32_t ospr0 = 0; 355011c182aSAndrew Mustea 356011c182aSAndrew Mustea if (!sfp_regs) { 357011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 358011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 359011c182aSAndrew Mustea } 360011c182aSAndrew Mustea 361011c182aSAndrew Mustea ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); 362011c182aSAndrew Mustea if (ospr0 & (SFP_OSPR0_WP | SFP_OSPR0_ITS)) { 363011c182aSAndrew Mustea DMSG("SFP is already fused"); 364011c182aSAndrew Mustea return TEE_ERROR_SECURITY; 365011c182aSAndrew Mustea } 366011c182aSAndrew Mustea 367011c182aSAndrew Mustea ospr0 |= SFP_OSPR0_WP | SFP_OSPR0_ITS; 368011c182aSAndrew Mustea io_write32((vaddr_t)&sfp_regs->ospr0, ospr0); 369011c182aSAndrew Mustea 370011c182aSAndrew Mustea return ls_sfp_program_fuses(); 371011c182aSAndrew Mustea } 372011c182aSAndrew Mustea 373011c182aSAndrew Mustea TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid) 374011c182aSAndrew Mustea { 375011c182aSAndrew Mustea if (!sfp_regs) { 376011c182aSAndrew Mustea EMSG("SFP driver not initialized"); 377011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 378011c182aSAndrew Mustea } 379011c182aSAndrew Mustea 380011c182aSAndrew Mustea if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { 381011c182aSAndrew Mustea DMSG("Index greater or equal to ouid: %"PRIu32" >= %"PRIu32, 382011c182aSAndrew Mustea index, ARRAY_SIZE(sfp_regs->ouidr)); 383011c182aSAndrew Mustea return TEE_ERROR_BAD_PARAMETERS; 384011c182aSAndrew Mustea } 385011c182aSAndrew Mustea 386011c182aSAndrew Mustea io_write32((vaddr_t)&sfp_regs->ouidr[index], ouid); 387011c182aSAndrew Mustea 388011c182aSAndrew Mustea return ls_sfp_program_fuses(); 389011c182aSAndrew Mustea } 390011c182aSAndrew Mustea 391011c182aSAndrew Mustea TEE_Result ls_sfp_status(void) 392011c182aSAndrew Mustea { 393011c182aSAndrew Mustea if (!sfp_regs) 394011c182aSAndrew Mustea return TEE_ERROR_GENERIC; 395011c182aSAndrew Mustea 396011c182aSAndrew Mustea return TEE_SUCCESS; 397011c182aSAndrew Mustea } 398011c182aSAndrew Mustea 399011c182aSAndrew Mustea driver_init(ls_sfp_init); 400