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