blob: a1a27d148a9c825f70562280e01f251460ae6e32 [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
6#include <common.h>
7#include <command.h>
Patrick Delaunayf81ddc12019-06-21 15:26:50 +02008#include <fuse.h>
Patrick Delaunay0c4656b2018-05-17 15:24:06 +02009#include <misc.h>
10#include <errno.h>
11#include <dm/device.h>
12#include <dm/uclass.h>
Patrick Delaunayd592d132019-02-04 11:26:22 +010013#include <power/stpmic1.h>
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020014
15#define STM32MP_OTP_BANK 0
Patrick Delaunayd592d132019-02-04 11:26:22 +010016#define STM32MP_NVM_BANK 1
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020017
18/*
19 * The 'fuse' command API
20 */
21int fuse_read(u32 bank, u32 word, u32 *val)
22{
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +020023 int ret;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020024 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);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +020035 if (ret != 4)
36 ret = -EINVAL;
37 else
38 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020039 break;
40
Patrick Delaunayd592d132019-02-04 11:26:22 +010041#ifdef CONFIG_PMIC_STPMIC1
42 case STM32MP_NVM_BANK:
43 *val = 0;
44 ret = stpmic1_shadow_read_byte(word, (u8 *)val);
45 break;
46#endif /* CONFIG_PMIC_STPMIC1 */
47
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020048 default:
49 printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
50 ret = -EINVAL;
51 break;
52 }
53
54 return ret;
55}
56
57int fuse_prog(u32 bank, u32 word, u32 val)
58{
59 struct udevice *dev;
60 int ret;
61
62 switch (bank) {
63 case STM32MP_OTP_BANK:
64 ret = uclass_get_device_by_driver(UCLASS_MISC,
65 DM_GET_DRIVER(stm32mp_bsec),
66 &dev);
67 if (ret)
68 return ret;
69 ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET,
70 &val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +020071 if (ret != 4)
72 ret = -EINVAL;
73 else
74 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020075 break;
Patrick Delaunayd592d132019-02-04 11:26:22 +010076
77#ifdef CONFIG_PMIC_STPMIC1
78 case STM32MP_NVM_BANK:
79 ret = stpmic1_nvm_write_byte(word, (u8 *)&val);
80 break;
81#endif /* CONFIG_PMIC_STPMIC1 */
Patrick Delaunay0c4656b2018-05-17 15:24:06 +020082
83 default:
84 printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
85 ret = -EINVAL;
86 break;
87 }
88
89 return ret;
90}
91
92int fuse_sense(u32 bank, u32 word, u32 *val)
93{
94 struct udevice *dev;
95 int ret;
96
97 switch (bank) {
98 case STM32MP_OTP_BANK:
99 ret = uclass_get_device_by_driver(UCLASS_MISC,
100 DM_GET_DRIVER(stm32mp_bsec),
101 &dev);
102 if (ret)
103 return ret;
104 ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200105 if (ret != 4)
106 ret = -EINVAL;
107 else
108 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200109 break;
110
Patrick Delaunayd592d132019-02-04 11:26:22 +0100111#ifdef CONFIG_PMIC_STPMIC1
112 case STM32MP_NVM_BANK:
113 *val = 0;
114 ret = stpmic1_nvm_read_byte(word, (u8 *)val);
115 break;
116#endif /* CONFIG_PMIC_STPMIC1 */
117
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200118 default:
119 printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
120 ret = -EINVAL;
121 break;
122 }
123
124 return ret;
125}
126
127int fuse_override(u32 bank, u32 word, u32 val)
128{
129 struct udevice *dev;
130 int ret;
131
132 switch (bank) {
133 case STM32MP_OTP_BANK:
134 ret = uclass_get_device_by_driver(UCLASS_MISC,
135 DM_GET_DRIVER(stm32mp_bsec),
136 &dev);
137 if (ret)
138 return ret;
139 ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
140 &val, 4);
Patrick Delaunay7e5f8e32019-08-02 13:08:02 +0200141 if (ret != 4)
142 ret = -EINVAL;
143 else
144 ret = 0;
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200145 break;
146
Patrick Delaunayd592d132019-02-04 11:26:22 +0100147#ifdef CONFIG_PMIC_STPMIC1
148 case STM32MP_NVM_BANK:
149 ret = stpmic1_shadow_write_byte(word, (u8 *)&val);
150 break;
151#endif /* CONFIG_PMIC_STPMIC1 */
152
Patrick Delaunay0c4656b2018-05-17 15:24:06 +0200153 default:
154 printf("stm32mp %s: wrong value for bank %i\n",
155 __func__, bank);
156 ret = -EINVAL;
157 break;
158 }
159
160 return ret;
161}