blob: 34be6c28c1923984f946d95d9f12ac6cf30ff997 [file] [log] [blame]
Patrick Delaunay0c4656b2018-05-17 15:24:06 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 */
5
Patrick Delaunay0c4656b2018-05-17 15:24:06 +02006#include <command.h>
Patrick Delaunayf81ddc12019-06-21 15:26:50 +02007#include <fuse.h>
Patrick Delaunay0c4656b2018-05-17 15:24:06 +02008#include <misc.h>
9#include <errno.h>
10#include <dm/device.h>
11#include <dm/uclass.h>
Patrick Delaunayd592d132019-02-04 11:26:22 +010012#include <power/stpmic1.h>
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020013
14#define STM32MP_OTP_BANK 0
Patrick Delaunayd592d132019-02-04 11:26:22 +010015#define STM32MP_NVM_BANK 1
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020016
17/*
18 * The 'fuse' command API
19 */
20int fuse_read(u32 bank, u32 word, u32 *val)
21{
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +020022 int ret;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020023 struct udevice *dev;
24
25 switch (bank) {
26 case STM32MP_OTP_BANK:
27 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -070028 DM_DRIVER_GET(stm32mp_bsec),
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020029 &dev);
30 if (ret)
31 return ret;
32 ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
33 val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +020034 if (ret != 4)
35 ret = -EINVAL;
36 else
37 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020038 break;
39
Patrick Delaunayd592d132019-02-04 11:26:22 +010040#ifdef CONFIG_PMIC_STPMIC1
41 case STM32MP_NVM_BANK:
Patrick Delaunayc9a5d392019-08-02 13:08:03 +020042 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -070043 DM_DRIVER_GET(stpmic1_nvm),
Patrick Delaunayc9a5d392019-08-02 13:08:03 +020044 &dev);
45 if (ret)
46 return ret;
Patrick Delaunayd592d132019-02-04 11:26:22 +010047 *val = 0;
Patrick Delaunayc9a5d392019-08-02 13:08:03 +020048 ret = misc_read(dev, -word, val, 1);
49 if (ret != 1)
50 ret = -EINVAL;
51 else
52 ret = 0;
Patrick Delaunayd592d132019-02-04 11:26:22 +010053 break;
54#endif /* CONFIG_PMIC_STPMIC1 */
55
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020056 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
65int 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,
Simon Glass65130cd2020-12-28 20:34:56 -070073 DM_DRIVER_GET(stm32mp_bsec),
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020074 &dev);
75 if (ret)
76 return ret;
77 ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET,
78 &val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +020079 if (ret != 4)
80 ret = -EINVAL;
81 else
82 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020083 break;
Patrick Delaunayd592d132019-02-04 11:26:22 +010084
85#ifdef CONFIG_PMIC_STPMIC1
86 case STM32MP_NVM_BANK:
Patrick Delaunayc9a5d392019-08-02 13:08:03 +020087 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -070088 DM_DRIVER_GET(stpmic1_nvm),
Patrick Delaunayc9a5d392019-08-02 13:08:03 +020089 &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;
Patrick Delaunayd592d132019-02-04 11:26:22 +010097 break;
98#endif /* CONFIG_PMIC_STPMIC1 */
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020099
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
109int 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,
Simon Glass65130cd2020-12-28 20:34:56 -0700117 DM_DRIVER_GET(stm32mp_bsec),
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200118 &dev);
119 if (ret)
120 return ret;
121 ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200122 if (ret != 4)
123 ret = -EINVAL;
124 else
125 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200126 break;
127
Patrick Delaunayd592d132019-02-04 11:26:22 +0100128#ifdef CONFIG_PMIC_STPMIC1
129 case STM32MP_NVM_BANK:
Patrick Delaunayc9a5d392019-08-02 13:08:03 +0200130 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -0700131 DM_DRIVER_GET(stpmic1_nvm),
Patrick Delaunayc9a5d392019-08-02 13:08:03 +0200132 &dev);
133 if (ret)
134 return ret;
Patrick Delaunayd592d132019-02-04 11:26:22 +0100135 *val = 0;
Patrick Delaunayc9a5d392019-08-02 13:08:03 +0200136 ret = misc_read(dev, word, val, 1);
137 if (ret != 1)
138 ret = -EINVAL;
139 else
140 ret = 0;
Patrick Delaunayd592d132019-02-04 11:26:22 +0100141 break;
142#endif /* CONFIG_PMIC_STPMIC1 */
143
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200144 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
153int 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,
Simon Glass65130cd2020-12-28 20:34:56 -0700161 DM_DRIVER_GET(stm32mp_bsec),
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200162 &dev);
163 if (ret)
164 return ret;
165 ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
166 &val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200167 if (ret != 4)
168 ret = -EINVAL;
169 else
170 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200171 break;
172
Patrick Delaunayd592d132019-02-04 11:26:22 +0100173#ifdef CONFIG_PMIC_STPMIC1
174 case STM32MP_NVM_BANK:
Patrick Delaunayc9a5d392019-08-02 13:08:03 +0200175 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -0700176 DM_DRIVER_GET(stpmic1_nvm),
Patrick Delaunayc9a5d392019-08-02 13:08:03 +0200177 &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;
Patrick Delaunayd592d132019-02-04 11:26:22 +0100185 break;
186#endif /* CONFIG_PMIC_STPMIC1 */
187
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200188 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}