xref: /optee_os/core/drivers/ls_sfp.c (revision e5a3695bb7c649b3258287f4a17eb073eb2235e2)
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  */
ls_sfp_init(void)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 
110*e5a3695bSSriram Sriram 	rc = dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO);
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  */
ls_sfp_program_fuses(void)150011c182aSAndrew Mustea static TEE_Result ls_sfp_program_fuses(void)
151011c182aSAndrew Mustea {
152f1e5a92fSAndrew Mustea 	TEE_Result ret = TEE_SUCCESS;
153011c182aSAndrew Mustea 	struct gpio_chip *gc = NULL;
154011c182aSAndrew Mustea 	uint32_t pin = gpio_info.gpio_pin;
155011c182aSAndrew Mustea 	vaddr_t sfp_ingr_va = (vaddr_t)&sfp_regs->ingr;
156011c182aSAndrew Mustea 	uint64_t timeout = 0;
157011c182aSAndrew Mustea 
158011c182aSAndrew Mustea 	/* Enable POVDD */
159011c182aSAndrew Mustea 	gc = &gpio_info.gpio_chip.chip;
160011c182aSAndrew Mustea 
161011c182aSAndrew Mustea 	DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to HIGH",
162011c182aSAndrew Mustea 	     (uint32_t)gpio_info.gpio_chip.gpio_controller, pin);
163011c182aSAndrew Mustea 	gc->ops->set_direction(gc, pin, GPIO_DIR_OUT);
164011c182aSAndrew Mustea 	gc->ops->set_value(gc, pin, GPIO_LEVEL_HIGH);
165011c182aSAndrew Mustea 
166011c182aSAndrew Mustea 	if (gc->ops->get_value(gc, pin) != GPIO_LEVEL_HIGH) {
167011c182aSAndrew Mustea 		EMSG("Error setting POVDD to HIGH");
168011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
169011c182aSAndrew Mustea 	}
170011c182aSAndrew Mustea 
171011c182aSAndrew Mustea 	/* TA_PROG_SFP ramp rate requires up to 5ms for stability */
172011c182aSAndrew Mustea 	mdelay(5);
173011c182aSAndrew Mustea 
174011c182aSAndrew Mustea 	/* Send SFP write command */
175011c182aSAndrew Mustea 	io_write32(sfp_ingr_va, SFP_INGR_PROGFB_CMD);
176011c182aSAndrew Mustea 
177011c182aSAndrew Mustea 	/* Wait until fuse programming is successful */
178385b0436SAndrew Mustea 	timeout = timeout_init_us(SFP_INGR_FUSE_TIMEOUT_US);
179011c182aSAndrew Mustea 	while (io_read32(sfp_ingr_va) & SFP_INGR_PROGFB_CMD) {
180011c182aSAndrew Mustea 		if (timeout_elapsed(timeout)) {
181011c182aSAndrew Mustea 			EMSG("SFP fusing timed out");
182f1e5a92fSAndrew Mustea 			ret = TEE_ERROR_GENERIC;
183f1e5a92fSAndrew Mustea 			break;
184011c182aSAndrew Mustea 		}
185011c182aSAndrew Mustea 	}
186011c182aSAndrew Mustea 
187f1e5a92fSAndrew Mustea 	/* Disable POVDD */
188f1e5a92fSAndrew Mustea 	DMSG("Set GPIO %"PRIu8" pin %"PRIu32" to LOW",
189f1e5a92fSAndrew Mustea 	     gpio_info.gpio_chip.gpio_controller, pin);
190f1e5a92fSAndrew Mustea 	gc->ops->set_value(gc, pin, GPIO_LEVEL_LOW);
191f1e5a92fSAndrew Mustea 	gc->ops->set_direction(gc, pin, GPIO_DIR_IN);
192f1e5a92fSAndrew Mustea 
193f1e5a92fSAndrew Mustea 	if (ret)
194f1e5a92fSAndrew Mustea 		return ret;
195f1e5a92fSAndrew Mustea 
196011c182aSAndrew Mustea 	/* Check for SFP fuse programming error */
197011c182aSAndrew Mustea 	if (io_read32(sfp_ingr_va) & SFP_INGR_ERROR_MASK) {
198011c182aSAndrew Mustea 		EMSG("Error writing SFP fuses");
199011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
200011c182aSAndrew Mustea 	}
201011c182aSAndrew Mustea 
202011c182aSAndrew Mustea 	DMSG("Programmed fuse successfully");
203011c182aSAndrew Mustea 
204011c182aSAndrew Mustea 	return TEE_SUCCESS;
205011c182aSAndrew Mustea }
206011c182aSAndrew Mustea 
ls_sfp_read(struct ls_sfp_data * data)207011c182aSAndrew Mustea TEE_Result ls_sfp_read(struct ls_sfp_data *data)
208011c182aSAndrew Mustea {
209011c182aSAndrew Mustea 	if (!sfp_regs) {
210011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
211011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
212011c182aSAndrew Mustea 	}
213011c182aSAndrew Mustea 
214011c182aSAndrew Mustea 	if (!data)
215011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
216011c182aSAndrew Mustea 
217011c182aSAndrew Mustea 	data->ingr = io_read32((vaddr_t)&sfp_regs->ingr);
218011c182aSAndrew Mustea 	data->svhesr = io_read32((vaddr_t)&sfp_regs->svhesr);
219011c182aSAndrew Mustea 	data->sfpcr = io_read32((vaddr_t)&sfp_regs->sfpcr);
220011c182aSAndrew Mustea 	data->version = io_read32((vaddr_t)&sfp_regs->version);
221011c182aSAndrew Mustea 	data->ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0);
222011c182aSAndrew Mustea 	data->ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1);
223011c182aSAndrew Mustea 	data->dcvr0 = io_read32((vaddr_t)&sfp_regs->dcvr0);
224011c182aSAndrew Mustea 	data->dcvr1 = io_read32((vaddr_t)&sfp_regs->dcvr1);
225011c182aSAndrew Mustea 	data->drvr0 = io_read32((vaddr_t)&sfp_regs->drvr0);
226011c182aSAndrew Mustea 	data->drvr1 = io_read32((vaddr_t)&sfp_regs->drvr1);
227011c182aSAndrew Mustea 	data->fswpr = io_read32((vaddr_t)&sfp_regs->fswpr);
228011c182aSAndrew Mustea 	data->fuidr0 = io_read32((vaddr_t)&sfp_regs->fuidr0);
229011c182aSAndrew Mustea 	data->fuidr1 = io_read32((vaddr_t)&sfp_regs->fuidr1);
230011c182aSAndrew Mustea 	data->isbccr = io_read32((vaddr_t)&sfp_regs->isbccr);
231011c182aSAndrew Mustea 
232011c182aSAndrew Mustea 	for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->fspfr); ++i)
233011c182aSAndrew Mustea 		data->fspfr[i] = io_read32((vaddr_t)&sfp_regs->fspfr[i]);
234011c182aSAndrew Mustea 
235011c182aSAndrew Mustea 	for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->otpmkr); ++i)
236011c182aSAndrew Mustea 		data->otpmkr[i] = io_read32((vaddr_t)&sfp_regs->otpmkr[i]);
237011c182aSAndrew Mustea 
238011c182aSAndrew Mustea 	for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->srkhr); ++i)
239011c182aSAndrew Mustea 		data->srkhr[i] = io_read32((vaddr_t)&sfp_regs->srkhr[i]);
240011c182aSAndrew Mustea 
241011c182aSAndrew Mustea 	for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->ouidr); ++i)
242011c182aSAndrew Mustea 		data->ouidr[i] = io_read32((vaddr_t)&sfp_regs->ouidr[i]);
243011c182aSAndrew Mustea 
244011c182aSAndrew Mustea 	return TEE_SUCCESS;
245011c182aSAndrew Mustea }
246011c182aSAndrew Mustea 
ls_sfp_get_debug_level(uint32_t * dblev)247011c182aSAndrew Mustea TEE_Result ls_sfp_get_debug_level(uint32_t *dblev)
248011c182aSAndrew Mustea {
249011c182aSAndrew Mustea 	if (!sfp_regs) {
250011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
251011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
252011c182aSAndrew Mustea 	}
253011c182aSAndrew Mustea 
254011c182aSAndrew Mustea 	if (!dblev)
255011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
256011c182aSAndrew Mustea 
257011c182aSAndrew Mustea 	*dblev = io_read32((vaddr_t)&sfp_regs->ospr1) & SFP_OSPR1_DBLEV_MASK;
258011c182aSAndrew Mustea 
259011c182aSAndrew Mustea 	return TEE_SUCCESS;
260011c182aSAndrew Mustea }
261011c182aSAndrew Mustea 
ls_sfp_get_its(uint32_t * its)262011c182aSAndrew Mustea TEE_Result ls_sfp_get_its(uint32_t *its)
263011c182aSAndrew Mustea {
264011c182aSAndrew Mustea 	if (!sfp_regs) {
265011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
266011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
267011c182aSAndrew Mustea 	}
268011c182aSAndrew Mustea 
269011c182aSAndrew Mustea 	if (!its)
270011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
271011c182aSAndrew Mustea 
272999da91aSAndrew Mustea 	*its = (io_read32((vaddr_t)&sfp_regs->ospr0) & SFP_OSPR0_ITS_MASK) >>
273999da91aSAndrew Mustea 	       SFP_OSPR0_ITS_OFFSET;
274011c182aSAndrew Mustea 
275011c182aSAndrew Mustea 	return TEE_SUCCESS;
276011c182aSAndrew Mustea }
277011c182aSAndrew Mustea 
ls_sfp_get_ouid(uint32_t index,uint32_t * ouid)278011c182aSAndrew Mustea TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid)
279011c182aSAndrew Mustea {
280011c182aSAndrew Mustea 	if (!sfp_regs) {
281011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
282011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
283011c182aSAndrew Mustea 	}
284011c182aSAndrew Mustea 
285011c182aSAndrew Mustea 	if (!ouid)
286011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
287011c182aSAndrew Mustea 
288011c182aSAndrew Mustea 	if (index >= ARRAY_SIZE(sfp_regs->ouidr)) {
289011c182aSAndrew Mustea 		DMSG("Index greater or equal to ouid: %"PRIu32" >= %zu",
290011c182aSAndrew Mustea 		     index, ARRAY_SIZE(sfp_regs->ouidr));
291011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
292011c182aSAndrew Mustea 	}
293011c182aSAndrew Mustea 
294011c182aSAndrew Mustea 	*ouid = io_read32((vaddr_t)&sfp_regs->ouidr[index]);
295011c182aSAndrew Mustea 
296011c182aSAndrew Mustea 	return TEE_SUCCESS;
297011c182aSAndrew Mustea }
298011c182aSAndrew Mustea 
ls_sfp_get_sb(uint32_t * sb)299011c182aSAndrew Mustea TEE_Result ls_sfp_get_sb(uint32_t *sb)
300011c182aSAndrew Mustea {
301011c182aSAndrew Mustea 	if (!sfp_regs) {
302011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
303011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
304011c182aSAndrew Mustea 	}
305011c182aSAndrew Mustea 
306011c182aSAndrew Mustea 	if (!sb)
307011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
308011c182aSAndrew Mustea 
309999da91aSAndrew Mustea 	*sb = (io_read32((vaddr_t)&sfp_regs->sfpcr) & SFP_SFPCR_SB_MASK) >>
310999da91aSAndrew Mustea 	      SFP_SFPCR_SB_OFFSET;
311011c182aSAndrew Mustea 
312011c182aSAndrew Mustea 	return TEE_SUCCESS;
313011c182aSAndrew Mustea }
314011c182aSAndrew Mustea 
ls_sfp_get_srkh(uint32_t index,uint32_t * srkh)315011c182aSAndrew Mustea TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh)
316011c182aSAndrew Mustea {
317011c182aSAndrew Mustea 	if (!sfp_regs) {
318011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
319011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
320011c182aSAndrew Mustea 	}
321011c182aSAndrew Mustea 
322011c182aSAndrew Mustea 	if (!srkh)
323011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
324011c182aSAndrew Mustea 
325011c182aSAndrew Mustea 	if (index >= ARRAY_SIZE(sfp_regs->srkhr)) {
326011c182aSAndrew Mustea 		DMSG("Index greater or equal to srkhr: %"PRIu32" >= %zu",
327011c182aSAndrew Mustea 		     index, ARRAY_SIZE(sfp_regs->srkhr));
328011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
329011c182aSAndrew Mustea 	}
330011c182aSAndrew Mustea 
331011c182aSAndrew Mustea 	*srkh = io_read32((vaddr_t)&sfp_regs->srkhr[index]);
332011c182aSAndrew Mustea 
333011c182aSAndrew Mustea 	return TEE_SUCCESS;
334011c182aSAndrew Mustea }
335011c182aSAndrew Mustea 
ls_sfp_set_debug_level(uint32_t dblev)336011c182aSAndrew Mustea TEE_Result ls_sfp_set_debug_level(uint32_t dblev)
337011c182aSAndrew Mustea {
338011c182aSAndrew Mustea 	uint32_t ospr1 = 0;
339011c182aSAndrew Mustea 
340011c182aSAndrew Mustea 	if (!sfp_regs) {
341011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
342011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
343011c182aSAndrew Mustea 	}
344011c182aSAndrew Mustea 
345011c182aSAndrew Mustea 	if (!dblev)
346011c182aSAndrew Mustea 		return TEE_SUCCESS;
347011c182aSAndrew Mustea 
348011c182aSAndrew Mustea 	ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1);
349011c182aSAndrew Mustea 	if (ospr1 & SFP_OSPR1_DBLEV_MASK) {
350011c182aSAndrew Mustea 		DMSG("Debug level has already been fused");
351011c182aSAndrew Mustea 		return TEE_ERROR_SECURITY;
352011c182aSAndrew Mustea 	}
353011c182aSAndrew Mustea 
354011c182aSAndrew Mustea 	io_write32((vaddr_t)&sfp_regs->ospr1, ospr1 | dblev);
355011c182aSAndrew Mustea 
356011c182aSAndrew Mustea 	return ls_sfp_program_fuses();
357011c182aSAndrew Mustea }
358011c182aSAndrew Mustea 
ls_sfp_set_its_wp(void)359011c182aSAndrew Mustea TEE_Result ls_sfp_set_its_wp(void)
360011c182aSAndrew Mustea {
361011c182aSAndrew Mustea 	uint32_t ospr0 = 0;
362011c182aSAndrew Mustea 
363011c182aSAndrew Mustea 	if (!sfp_regs) {
364011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
365011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
366011c182aSAndrew Mustea 	}
367011c182aSAndrew Mustea 
368011c182aSAndrew Mustea 	ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0);
369999da91aSAndrew Mustea 	if (ospr0 & (SFP_OSPR0_WP_MASK | SFP_OSPR0_ITS_MASK)) {
370011c182aSAndrew Mustea 		DMSG("SFP is already fused");
371011c182aSAndrew Mustea 		return TEE_ERROR_SECURITY;
372011c182aSAndrew Mustea 	}
373011c182aSAndrew Mustea 
374999da91aSAndrew Mustea 	ospr0 |= SFP_OSPR0_WP_MASK | SFP_OSPR0_ITS_MASK;
375011c182aSAndrew Mustea 	io_write32((vaddr_t)&sfp_regs->ospr0, ospr0);
376011c182aSAndrew Mustea 
377011c182aSAndrew Mustea 	return ls_sfp_program_fuses();
378011c182aSAndrew Mustea }
379011c182aSAndrew Mustea 
ls_sfp_set_ouid(uint32_t index,uint32_t ouid)380011c182aSAndrew Mustea TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid)
381011c182aSAndrew Mustea {
382011c182aSAndrew Mustea 	if (!sfp_regs) {
383011c182aSAndrew Mustea 		EMSG("SFP driver not initialized");
384011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
385011c182aSAndrew Mustea 	}
386011c182aSAndrew Mustea 
387011c182aSAndrew Mustea 	if (index >= ARRAY_SIZE(sfp_regs->ouidr)) {
388011c182aSAndrew Mustea 		DMSG("Index greater or equal to ouid: %"PRIu32" >= %"PRIu32,
389011c182aSAndrew Mustea 		     index, ARRAY_SIZE(sfp_regs->ouidr));
390011c182aSAndrew Mustea 		return TEE_ERROR_BAD_PARAMETERS;
391011c182aSAndrew Mustea 	}
392011c182aSAndrew Mustea 
393011c182aSAndrew Mustea 	io_write32((vaddr_t)&sfp_regs->ouidr[index], ouid);
394011c182aSAndrew Mustea 
395011c182aSAndrew Mustea 	return ls_sfp_program_fuses();
396011c182aSAndrew Mustea }
397011c182aSAndrew Mustea 
ls_sfp_status(void)398011c182aSAndrew Mustea TEE_Result ls_sfp_status(void)
399011c182aSAndrew Mustea {
400011c182aSAndrew Mustea 	if (!sfp_regs)
401011c182aSAndrew Mustea 		return TEE_ERROR_GENERIC;
402011c182aSAndrew Mustea 
403011c182aSAndrew Mustea 	return TEE_SUCCESS;
404011c182aSAndrew Mustea }
405011c182aSAndrew Mustea 
406011c182aSAndrew Mustea driver_init(ls_sfp_init);
407