]>
Commit | Line | Data |
---|---|---|
2645bc0e SA |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com> | |
4 | * | |
5 | * This driver supports the Security Fuse Processor device found on some | |
6 | * Layerscape processors. At the moment, we only support a few processors. | |
7 | * This driver was written with reference to the Layerscape SDK User | |
8 | * Guide [1] and the ATF SFP driver [2]. | |
9 | * | |
10 | * [1] https://docs.nxp.com/bundle/GUID-487B2E69-BB19-42CB-AC38-7EF18C0FE3AE/page/GUID-27FC40AD-3321-4A82-B29E-7BB49EE94F23.html | |
11 | * [2] https://source.codeaurora.org/external/qoriq/qoriq-components/atf/tree/drivers/nxp/sfp?h=github.com/master | |
12 | */ | |
13 | ||
14 | #define LOG_CATEGORY UCLASS_MISC | |
d678a59d | 15 | #include <common.h> |
2645bc0e SA |
16 | #include <clk.h> |
17 | #include <fuse.h> | |
18 | #include <misc.h> | |
19 | #include <asm/io.h> | |
20 | #include <dm/device_compat.h> | |
21 | #include <dm/read.h> | |
22 | #include <linux/bitfield.h> | |
23 | #include <power/regulator.h> | |
24 | ||
25 | DECLARE_GLOBAL_DATA_PTR; | |
26 | ||
27 | #define SFP_INGR 0x20 | |
28 | #define SFP_SVHESR 0x24 | |
29 | #define SFP_SFPCR 0x28 | |
30 | ||
31 | #define SFP_START 0x200 | |
32 | #define SFP_END 0x284 | |
33 | #define SFP_SIZE (SFP_END - SFP_START + 4) | |
34 | ||
35 | #define SFP_INGR_ERR BIT(8) | |
36 | #define SFP_INGR_INST GENMASK(7, 0) | |
37 | ||
38 | #define SFP_INGR_READFB 0x01 | |
39 | #define SFP_INGR_PROGFB 0x02 | |
40 | ||
41 | #define SFP_SFPCR_PPW GENMASK(15, 0) | |
42 | ||
43 | enum ls2_sfp_ioctl { | |
44 | LS2_SFP_IOCTL_READ, | |
45 | LS2_SFP_IOCTL_PROG, | |
46 | }; | |
47 | ||
48 | /** | |
49 | * struct ls2_sfp_priv - private data for LS2 SFP | |
50 | * @base: Base address of SFP | |
51 | * @supply: The (optional) supply for TA_PROG_SFP | |
52 | * @programmed: Whether we've already programmed the fuses since the last | |
53 | * reset. The SFP has a *very* limited amount of programming | |
54 | * cycles (two to six, depending on the model), so we try and | |
55 | * prevent accidentally performing additional programming | |
56 | * cycles. | |
57 | * @dirty: Whether the mirror registers have been written to (overridden) | |
58 | * since we've last read the fuses (either as part of the reset | |
59 | * process or using a READFB instruction). There is a much larger, | |
60 | * but still finite, limit on the number of SFP read cycles (around | |
61 | * 300,000), so we try and minimize reads as well. | |
62 | */ | |
63 | struct ls2_sfp_priv { | |
64 | void __iomem *base; | |
65 | struct udevice *supply; | |
66 | bool programmed, dirty; | |
67 | }; | |
68 | ||
69 | static u32 ls2_sfp_readl(struct ls2_sfp_priv *priv, ulong off) | |
70 | { | |
71 | u32 val = be32_to_cpu(readl(priv->base + off)); | |
72 | ||
73 | log_debug("%08x = readl(%p)\n", val, priv->base + off); | |
74 | return val; | |
75 | } | |
76 | ||
77 | static void ls2_sfp_writel(struct ls2_sfp_priv *priv, ulong val, ulong off) | |
78 | { | |
79 | log_debug("writel(%08lx, %p)\n", val, priv->base + off); | |
80 | writel(cpu_to_be32(val), priv->base + off); | |
81 | } | |
82 | ||
83 | static bool ls2_sfp_validate(struct udevice *dev, int offset, int size) | |
84 | { | |
85 | if (offset < 0 || size < 0) { | |
86 | dev_notice(dev, "size and offset must be positive\n"); | |
87 | return false; | |
88 | } | |
89 | ||
90 | if (offset & 3 || size & 3) { | |
91 | dev_notice(dev, "size and offset must be multiples of 4\n"); | |
92 | return false; | |
93 | } | |
94 | ||
95 | if (offset + size > SFP_SIZE) { | |
96 | dev_notice(dev, "size + offset must be <= %#x\n", SFP_SIZE); | |
97 | return false; | |
98 | } | |
99 | ||
100 | return true; | |
101 | } | |
102 | ||
103 | static int ls2_sfp_read(struct udevice *dev, int offset, void *buf_bytes, | |
104 | int size) | |
105 | { | |
106 | int i; | |
107 | struct ls2_sfp_priv *priv = dev_get_priv(dev); | |
108 | u32 *buf = buf_bytes; | |
109 | ||
110 | if (!ls2_sfp_validate(dev, offset, size)) | |
111 | return -EINVAL; | |
112 | ||
113 | for (i = 0; i < size; i += 4) | |
114 | buf[i >> 2] = ls2_sfp_readl(priv, SFP_START + offset + i); | |
115 | ||
116 | return size; | |
117 | } | |
118 | ||
119 | static int ls2_sfp_write(struct udevice *dev, int offset, | |
120 | const void *buf_bytes, int size) | |
121 | { | |
122 | int i; | |
123 | struct ls2_sfp_priv *priv = dev_get_priv(dev); | |
124 | const u32 *buf = buf_bytes; | |
125 | ||
126 | if (!ls2_sfp_validate(dev, offset, size)) | |
127 | return -EINVAL; | |
128 | ||
129 | for (i = 0; i < size; i += 4) | |
130 | ls2_sfp_writel(priv, buf[i >> 2], SFP_START + offset + i); | |
131 | ||
132 | priv->dirty = true; | |
133 | return size; | |
134 | } | |
135 | ||
136 | static int ls2_sfp_check_secret(struct udevice *dev) | |
137 | { | |
138 | struct ls2_sfp_priv *priv = dev_get_priv(dev); | |
139 | u32 svhesr = ls2_sfp_readl(priv, SFP_SVHESR); | |
140 | ||
141 | if (svhesr) { | |
142 | dev_warn(dev, "secret value hamming error not zero: %08x\n", | |
143 | svhesr); | |
144 | return -EIO; | |
145 | } | |
146 | return 0; | |
147 | } | |
148 | ||
149 | static int ls2_sfp_transaction(struct ls2_sfp_priv *priv, ulong inst) | |
150 | { | |
151 | u32 ingr; | |
152 | ||
153 | ls2_sfp_writel(priv, inst, SFP_INGR); | |
154 | ||
155 | do { | |
156 | ingr = ls2_sfp_readl(priv, SFP_INGR); | |
157 | } while (FIELD_GET(SFP_INGR_INST, ingr)); | |
158 | ||
159 | return FIELD_GET(SFP_INGR_ERR, ingr) ? -EIO : 0; | |
160 | } | |
161 | ||
162 | static int ls2_sfp_ioctl(struct udevice *dev, unsigned long request, void *buf) | |
163 | { | |
164 | int ret; | |
165 | struct ls2_sfp_priv *priv = dev_get_priv(dev); | |
166 | ||
167 | switch (request) { | |
168 | case LS2_SFP_IOCTL_READ: | |
169 | if (!priv->dirty) { | |
170 | dev_dbg(dev, "ignoring read request, since fuses are not dirty\n"); | |
171 | return 0; | |
172 | } | |
173 | ||
174 | ret = ls2_sfp_transaction(priv, SFP_INGR_READFB); | |
175 | if (ret) { | |
176 | dev_err(dev, "error reading fuses\n"); | |
177 | return ret; | |
178 | } | |
179 | ||
180 | ls2_sfp_check_secret(dev); | |
181 | priv->dirty = false; | |
182 | return 0; | |
183 | case LS2_SFP_IOCTL_PROG: | |
184 | if (priv->programmed) { | |
185 | dev_warn(dev, "fuses already programmed\n"); | |
186 | return -EPERM; | |
187 | } | |
188 | ||
189 | ret = ls2_sfp_check_secret(dev); | |
190 | if (ret) | |
191 | return ret; | |
192 | ||
193 | if (priv->supply) { | |
194 | ret = regulator_set_enable(priv->supply, true); | |
195 | if (ret) | |
196 | return ret; | |
197 | } | |
198 | ||
199 | ret = ls2_sfp_transaction(priv, SFP_INGR_PROGFB); | |
200 | priv->programmed = true; | |
201 | if (priv->supply) | |
202 | regulator_set_enable(priv->supply, false); | |
203 | ||
204 | if (ret) | |
205 | dev_err(dev, "error programming fuses\n"); | |
206 | return ret; | |
207 | default: | |
208 | dev_dbg(dev, "unknown ioctl %lu\n", request); | |
209 | return -EINVAL; | |
210 | } | |
211 | } | |
212 | ||
213 | static const struct misc_ops ls2_sfp_ops = { | |
214 | .read = ls2_sfp_read, | |
215 | .write = ls2_sfp_write, | |
216 | .ioctl = ls2_sfp_ioctl, | |
217 | }; | |
218 | ||
219 | static int ls2_sfp_probe(struct udevice *dev) | |
220 | { | |
221 | int ret; | |
222 | struct clk clk; | |
223 | struct ls2_sfp_priv *priv = dev_get_priv(dev); | |
224 | ulong rate; | |
225 | ||
226 | priv->base = dev_read_addr_ptr(dev); | |
227 | if (!priv->base) { | |
228 | dev_dbg(dev, "could not read register base\n"); | |
229 | return -EINVAL; | |
230 | } | |
231 | ||
4992d836 | 232 | ret = device_get_supply_regulator(dev, "ta-sfp-prog-supply", &priv->supply); |
2645bc0e SA |
233 | if (ret && ret != -ENODEV && ret != -ENOSYS) { |
234 | dev_dbg(dev, "problem getting supply (err %d)\n", ret); | |
235 | return ret; | |
236 | } | |
237 | ||
238 | ret = clk_get_by_name(dev, "sfp", &clk); | |
239 | if (ret == -ENOSYS) { | |
240 | rate = gd->bus_clk / 4; | |
241 | } else if (ret) { | |
242 | dev_dbg(dev, "could not get clock (err %d)\n", ret); | |
243 | return ret; | |
244 | } else { | |
245 | ret = clk_enable(&clk); | |
246 | if (ret) { | |
247 | dev_dbg(dev, "could not enable clock (err %d)\n", ret); | |
248 | return ret; | |
249 | } | |
250 | ||
251 | rate = clk_get_rate(&clk); | |
2645bc0e SA |
252 | if (!rate || IS_ERR_VALUE(rate)) { |
253 | ret = rate ? rate : -ENOENT; | |
254 | dev_dbg(dev, "could not get clock rate (err %d)\n", | |
255 | ret); | |
256 | return ret; | |
257 | } | |
258 | } | |
259 | ||
260 | /* sfp clock in MHz * 12 */ | |
261 | ls2_sfp_writel(priv, FIELD_PREP(SFP_SFPCR_PPW, rate * 12 / 1000000), | |
262 | SFP_SFPCR); | |
263 | ||
264 | ls2_sfp_check_secret(dev); | |
265 | return 0; | |
266 | } | |
267 | ||
268 | static const struct udevice_id ls2_sfp_ids[] = { | |
269 | { .compatible = "fsl,ls1021a-sfp" }, | |
270 | { } | |
271 | }; | |
272 | ||
273 | U_BOOT_DRIVER(ls2_sfp) = { | |
274 | .name = "ls2_sfp", | |
275 | .id = UCLASS_MISC, | |
276 | .of_match = ls2_sfp_ids, | |
277 | .probe = ls2_sfp_probe, | |
278 | .ops = &ls2_sfp_ops, | |
279 | .priv_auto = sizeof(struct ls2_sfp_priv), | |
280 | }; | |
281 | ||
282 | static int ls2_sfp_device(struct udevice **dev) | |
283 | { | |
284 | int ret = uclass_get_device_by_driver(UCLASS_MISC, | |
285 | DM_DRIVER_GET(ls2_sfp), dev); | |
286 | ||
287 | if (ret) | |
288 | log_debug("device not found (err %d)\n", ret); | |
289 | return ret; | |
290 | } | |
291 | ||
292 | int fuse_read(u32 bank, u32 word, u32 *val) | |
293 | { | |
294 | int ret; | |
295 | struct udevice *dev; | |
296 | ||
297 | ret = ls2_sfp_device(&dev); | |
298 | if (ret) | |
299 | return ret; | |
300 | ||
301 | ret = misc_ioctl(dev, LS2_SFP_IOCTL_READ, NULL); | |
302 | if (ret) | |
303 | return ret; | |
304 | ||
305 | ret = misc_read(dev, word << 2, val, sizeof(*val)); | |
306 | return ret < 0 ? ret : 0; | |
307 | } | |
308 | ||
309 | int fuse_sense(u32 bank, u32 word, u32 *val) | |
310 | { | |
311 | int ret; | |
312 | struct udevice *dev; | |
313 | ||
314 | ret = ls2_sfp_device(&dev); | |
315 | if (ret) | |
316 | return ret; | |
317 | ||
318 | ret = misc_read(dev, word << 2, val, sizeof(*val)); | |
319 | return ret < 0 ? ret : 0; | |
320 | } | |
321 | ||
322 | int fuse_prog(u32 bank, u32 word, u32 val) | |
323 | { | |
324 | int ret; | |
325 | struct udevice *dev; | |
326 | ||
327 | ret = ls2_sfp_device(&dev); | |
328 | if (ret) | |
329 | return ret; | |
330 | ||
331 | ret = misc_write(dev, word << 2, &val, sizeof(val)); | |
332 | if (ret < 0) | |
333 | return ret; | |
334 | ||
335 | return misc_ioctl(dev, LS2_SFP_IOCTL_PROG, NULL); | |
336 | } | |
337 | ||
338 | int fuse_override(u32 bank, u32 word, u32 val) | |
339 | { | |
340 | int ret; | |
341 | struct udevice *dev; | |
342 | ||
343 | ret = ls2_sfp_device(&dev); | |
344 | if (ret) | |
345 | return ret; | |
346 | ||
347 | ret = misc_write(dev, word << 2, &val, sizeof(val)); | |
348 | return ret < 0 ? ret : 0; | |
349 | } |