xref: /openbmc/u-boot/drivers/misc/stm32mp_fuse.c (revision c3600e1f92b772f8e50d81c4f1c233839b48f2cf)
1*c3600e1fSPatrick Delaunay // SPDX-License-Identifier: GPL-2.0+
2*c3600e1fSPatrick Delaunay /*
3*c3600e1fSPatrick Delaunay  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4*c3600e1fSPatrick Delaunay  */
5*c3600e1fSPatrick Delaunay 
6*c3600e1fSPatrick Delaunay #include <common.h>
7*c3600e1fSPatrick Delaunay #include <command.h>
8*c3600e1fSPatrick Delaunay #include <misc.h>
9*c3600e1fSPatrick Delaunay #include <errno.h>
10*c3600e1fSPatrick Delaunay #include <dm/device.h>
11*c3600e1fSPatrick Delaunay #include <dm/uclass.h>
12*c3600e1fSPatrick Delaunay 
13*c3600e1fSPatrick Delaunay #define STM32MP_OTP_BANK	0
14*c3600e1fSPatrick Delaunay 
15*c3600e1fSPatrick Delaunay /*
16*c3600e1fSPatrick Delaunay  * The 'fuse' command API
17*c3600e1fSPatrick Delaunay  */
18*c3600e1fSPatrick Delaunay int fuse_read(u32 bank, u32 word, u32 *val)
19*c3600e1fSPatrick Delaunay {
20*c3600e1fSPatrick Delaunay 	int ret = 0;
21*c3600e1fSPatrick Delaunay 	struct udevice *dev;
22*c3600e1fSPatrick Delaunay 
23*c3600e1fSPatrick Delaunay 	switch (bank) {
24*c3600e1fSPatrick Delaunay 	case STM32MP_OTP_BANK:
25*c3600e1fSPatrick Delaunay 		ret = uclass_get_device_by_driver(UCLASS_MISC,
26*c3600e1fSPatrick Delaunay 						  DM_GET_DRIVER(stm32mp_bsec),
27*c3600e1fSPatrick Delaunay 						  &dev);
28*c3600e1fSPatrick Delaunay 		if (ret)
29*c3600e1fSPatrick Delaunay 			return ret;
30*c3600e1fSPatrick Delaunay 		ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
31*c3600e1fSPatrick Delaunay 				val, 4);
32*c3600e1fSPatrick Delaunay 		break;
33*c3600e1fSPatrick Delaunay 
34*c3600e1fSPatrick Delaunay 	default:
35*c3600e1fSPatrick Delaunay 		printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
36*c3600e1fSPatrick Delaunay 		ret = -EINVAL;
37*c3600e1fSPatrick Delaunay 		break;
38*c3600e1fSPatrick Delaunay 	}
39*c3600e1fSPatrick Delaunay 
40*c3600e1fSPatrick Delaunay 	return ret;
41*c3600e1fSPatrick Delaunay }
42*c3600e1fSPatrick Delaunay 
43*c3600e1fSPatrick Delaunay int fuse_prog(u32 bank, u32 word, u32 val)
44*c3600e1fSPatrick Delaunay {
45*c3600e1fSPatrick Delaunay 	struct udevice *dev;
46*c3600e1fSPatrick Delaunay 	int ret;
47*c3600e1fSPatrick Delaunay 
48*c3600e1fSPatrick Delaunay 	switch (bank) {
49*c3600e1fSPatrick Delaunay 	case STM32MP_OTP_BANK:
50*c3600e1fSPatrick Delaunay 		ret = uclass_get_device_by_driver(UCLASS_MISC,
51*c3600e1fSPatrick Delaunay 						  DM_GET_DRIVER(stm32mp_bsec),
52*c3600e1fSPatrick Delaunay 						  &dev);
53*c3600e1fSPatrick Delaunay 		if (ret)
54*c3600e1fSPatrick Delaunay 			return ret;
55*c3600e1fSPatrick Delaunay 		ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET,
56*c3600e1fSPatrick Delaunay 				 &val, 4);
57*c3600e1fSPatrick Delaunay 		break;
58*c3600e1fSPatrick Delaunay 
59*c3600e1fSPatrick Delaunay 	default:
60*c3600e1fSPatrick Delaunay 		printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
61*c3600e1fSPatrick Delaunay 		ret = -EINVAL;
62*c3600e1fSPatrick Delaunay 		break;
63*c3600e1fSPatrick Delaunay 	}
64*c3600e1fSPatrick Delaunay 
65*c3600e1fSPatrick Delaunay 	return ret;
66*c3600e1fSPatrick Delaunay }
67*c3600e1fSPatrick Delaunay 
68*c3600e1fSPatrick Delaunay int fuse_sense(u32 bank, u32 word, u32 *val)
69*c3600e1fSPatrick Delaunay {
70*c3600e1fSPatrick Delaunay 	struct udevice *dev;
71*c3600e1fSPatrick Delaunay 	int ret;
72*c3600e1fSPatrick Delaunay 
73*c3600e1fSPatrick Delaunay 	switch (bank) {
74*c3600e1fSPatrick Delaunay 	case STM32MP_OTP_BANK:
75*c3600e1fSPatrick Delaunay 		ret = uclass_get_device_by_driver(UCLASS_MISC,
76*c3600e1fSPatrick Delaunay 						  DM_GET_DRIVER(stm32mp_bsec),
77*c3600e1fSPatrick Delaunay 						  &dev);
78*c3600e1fSPatrick Delaunay 		if (ret)
79*c3600e1fSPatrick Delaunay 			return ret;
80*c3600e1fSPatrick Delaunay 		ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4);
81*c3600e1fSPatrick Delaunay 		break;
82*c3600e1fSPatrick Delaunay 
83*c3600e1fSPatrick Delaunay 	default:
84*c3600e1fSPatrick Delaunay 		printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
85*c3600e1fSPatrick Delaunay 		ret = -EINVAL;
86*c3600e1fSPatrick Delaunay 		break;
87*c3600e1fSPatrick Delaunay 	}
88*c3600e1fSPatrick Delaunay 
89*c3600e1fSPatrick Delaunay 	return ret;
90*c3600e1fSPatrick Delaunay }
91*c3600e1fSPatrick Delaunay 
92*c3600e1fSPatrick Delaunay int fuse_override(u32 bank, u32 word, u32 val)
93*c3600e1fSPatrick Delaunay {
94*c3600e1fSPatrick Delaunay 	struct udevice *dev;
95*c3600e1fSPatrick Delaunay 	int ret;
96*c3600e1fSPatrick Delaunay 
97*c3600e1fSPatrick Delaunay 	switch (bank) {
98*c3600e1fSPatrick Delaunay 	case STM32MP_OTP_BANK:
99*c3600e1fSPatrick Delaunay 		ret = uclass_get_device_by_driver(UCLASS_MISC,
100*c3600e1fSPatrick Delaunay 						  DM_GET_DRIVER(stm32mp_bsec),
101*c3600e1fSPatrick Delaunay 						  &dev);
102*c3600e1fSPatrick Delaunay 		if (ret)
103*c3600e1fSPatrick Delaunay 			return ret;
104*c3600e1fSPatrick Delaunay 		ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
105*c3600e1fSPatrick Delaunay 				 &val, 4);
106*c3600e1fSPatrick Delaunay 		break;
107*c3600e1fSPatrick Delaunay 
108*c3600e1fSPatrick Delaunay 	default:
109*c3600e1fSPatrick Delaunay 		printf("stm32mp %s: wrong value for bank %i\n",
110*c3600e1fSPatrick Delaunay 		       __func__, bank);
111*c3600e1fSPatrick Delaunay 		ret = -EINVAL;
112*c3600e1fSPatrick Delaunay 		break;
113*c3600e1fSPatrick Delaunay 	}
114*c3600e1fSPatrick Delaunay 
115*c3600e1fSPatrick Delaunay 	return ret;
116*c3600e1fSPatrick Delaunay }
117