xref: /optee_os/core/drivers/ls_sfp.c (revision 011c182a606b95697862181bc24e628cab39fcc6)
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