]>
Commit | Line | Data |
---|---|---|
c3600e1f PD |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2018, STMicroelectronics - All Rights Reserved | |
4 | */ | |
5 | ||
c3600e1f | 6 | #include <command.h> |
be56ab1b | 7 | #include <fuse.h> |
c3600e1f PD |
8 | #include <misc.h> |
9 | #include <errno.h> | |
10 | #include <dm/device.h> | |
11 | #include <dm/uclass.h> | |
31e45a1a | 12 | #include <power/stpmic1.h> |
c3600e1f PD |
13 | |
14 | #define STM32MP_OTP_BANK 0 | |
31e45a1a | 15 | #define STM32MP_NVM_BANK 1 |
c3600e1f PD |
16 | |
17 | /* | |
18 | * The 'fuse' command API | |
19 | */ | |
20 | int fuse_read(u32 bank, u32 word, u32 *val) | |
21 | { | |
0c8620d2 | 22 | int ret; |
c3600e1f PD |
23 | struct udevice *dev; |
24 | ||
25 | switch (bank) { | |
26 | case STM32MP_OTP_BANK: | |
27 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
65e25bea | 28 | DM_DRIVER_GET(stm32mp_bsec), |
c3600e1f PD |
29 | &dev); |
30 | if (ret) | |
31 | return ret; | |
32 | ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, | |
33 | val, 4); | |
0c8620d2 PD |
34 | if (ret != 4) |
35 | ret = -EINVAL; | |
36 | else | |
37 | ret = 0; | |
c3600e1f PD |
38 | break; |
39 | ||
31e45a1a PD |
40 | #ifdef CONFIG_PMIC_STPMIC1 |
41 | case STM32MP_NVM_BANK: | |
234a6024 | 42 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 43 | DM_DRIVER_GET(stpmic1_nvm), |
234a6024 PD |
44 | &dev); |
45 | if (ret) | |
46 | return ret; | |
31e45a1a | 47 | *val = 0; |
234a6024 PD |
48 | ret = misc_read(dev, -word, val, 1); |
49 | if (ret != 1) | |
50 | ret = -EINVAL; | |
51 | else | |
52 | ret = 0; | |
31e45a1a PD |
53 | break; |
54 | #endif /* CONFIG_PMIC_STPMIC1 */ | |
55 | ||
c3600e1f PD |
56 | default: |
57 | printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); | |
58 | ret = -EINVAL; | |
59 | break; | |
60 | } | |
61 | ||
62 | return ret; | |
63 | } | |
64 | ||
65 | int fuse_prog(u32 bank, u32 word, u32 val) | |
66 | { | |
67 | struct udevice *dev; | |
68 | int ret; | |
69 | ||
70 | switch (bank) { | |
71 | case STM32MP_OTP_BANK: | |
72 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
65e25bea | 73 | DM_DRIVER_GET(stm32mp_bsec), |
c3600e1f PD |
74 | &dev); |
75 | if (ret) | |
76 | return ret; | |
77 | ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET, | |
78 | &val, 4); | |
0c8620d2 PD |
79 | if (ret != 4) |
80 | ret = -EINVAL; | |
81 | else | |
82 | ret = 0; | |
c3600e1f PD |
83 | break; |
84 | ||
31e45a1a PD |
85 | #ifdef CONFIG_PMIC_STPMIC1 |
86 | case STM32MP_NVM_BANK: | |
234a6024 | 87 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 88 | DM_DRIVER_GET(stpmic1_nvm), |
234a6024 PD |
89 | &dev); |
90 | if (ret) | |
91 | return ret; | |
92 | ret = misc_write(dev, word, &val, 1); | |
93 | if (ret != 1) | |
94 | ret = -EINVAL; | |
95 | else | |
96 | ret = 0; | |
31e45a1a PD |
97 | break; |
98 | #endif /* CONFIG_PMIC_STPMIC1 */ | |
99 | ||
c3600e1f PD |
100 | default: |
101 | printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); | |
102 | ret = -EINVAL; | |
103 | break; | |
104 | } | |
105 | ||
106 | return ret; | |
107 | } | |
108 | ||
109 | int fuse_sense(u32 bank, u32 word, u32 *val) | |
110 | { | |
111 | struct udevice *dev; | |
112 | int ret; | |
113 | ||
114 | switch (bank) { | |
115 | case STM32MP_OTP_BANK: | |
116 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
65e25bea | 117 | DM_DRIVER_GET(stm32mp_bsec), |
c3600e1f PD |
118 | &dev); |
119 | if (ret) | |
120 | return ret; | |
121 | ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4); | |
0c8620d2 PD |
122 | if (ret != 4) |
123 | ret = -EINVAL; | |
124 | else | |
125 | ret = 0; | |
c3600e1f PD |
126 | break; |
127 | ||
31e45a1a PD |
128 | #ifdef CONFIG_PMIC_STPMIC1 |
129 | case STM32MP_NVM_BANK: | |
234a6024 | 130 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 131 | DM_DRIVER_GET(stpmic1_nvm), |
234a6024 PD |
132 | &dev); |
133 | if (ret) | |
134 | return ret; | |
31e45a1a | 135 | *val = 0; |
234a6024 PD |
136 | ret = misc_read(dev, word, val, 1); |
137 | if (ret != 1) | |
138 | ret = -EINVAL; | |
139 | else | |
140 | ret = 0; | |
31e45a1a PD |
141 | break; |
142 | #endif /* CONFIG_PMIC_STPMIC1 */ | |
143 | ||
c3600e1f PD |
144 | default: |
145 | printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); | |
146 | ret = -EINVAL; | |
147 | break; | |
148 | } | |
149 | ||
150 | return ret; | |
151 | } | |
152 | ||
153 | int fuse_override(u32 bank, u32 word, u32 val) | |
154 | { | |
155 | struct udevice *dev; | |
156 | int ret; | |
157 | ||
158 | switch (bank) { | |
159 | case STM32MP_OTP_BANK: | |
160 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
65e25bea | 161 | DM_DRIVER_GET(stm32mp_bsec), |
c3600e1f PD |
162 | &dev); |
163 | if (ret) | |
164 | return ret; | |
165 | ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, | |
166 | &val, 4); | |
0c8620d2 PD |
167 | if (ret != 4) |
168 | ret = -EINVAL; | |
169 | else | |
170 | ret = 0; | |
c3600e1f PD |
171 | break; |
172 | ||
31e45a1a PD |
173 | #ifdef CONFIG_PMIC_STPMIC1 |
174 | case STM32MP_NVM_BANK: | |
234a6024 | 175 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 176 | DM_DRIVER_GET(stpmic1_nvm), |
234a6024 PD |
177 | &dev); |
178 | if (ret) | |
179 | return ret; | |
180 | ret = misc_write(dev, -word, &val, 1); | |
181 | if (ret != 1) | |
182 | ret = -EINVAL; | |
183 | else | |
184 | ret = 0; | |
31e45a1a PD |
185 | break; |
186 | #endif /* CONFIG_PMIC_STPMIC1 */ | |
187 | ||
c3600e1f PD |
188 | default: |
189 | printf("stm32mp %s: wrong value for bank %i\n", | |
190 | __func__, bank); | |
191 | ret = -EINVAL; | |
192 | break; | |
193 | } | |
194 | ||
195 | return ret; | |
196 | } |