1 /*-
2 * Copyright (c) 2015 Michal Meloun
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/bus.h>
30 #include <sys/clock.h>
31 #include <sys/kernel.h>
32 #include <sys/limits.h>
33 #include <sys/lock.h>
34 #include <sys/mutex.h>
35 #include <sys/module.h>
36 #include <sys/resource.h>
37 #include <sys/rman.h>
38
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41
42 #include <dev/clk/clk.h>
43 #include <dev/hwreset/hwreset.h>
44 #include <dev/ofw/ofw_bus.h>
45 #include <dev/ofw/ofw_bus_subr.h>
46
47 #include <arm/nvidia/tegra_efuse.h>
48
49 #define FUSES_START 0x100
50 #define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (FUSES_START + (_r)))
51
52 struct efuse_soc;
53 struct tegra_efuse_softc {
54 device_t dev;
55 struct resource *mem_res;
56
57 struct efuse_soc *soc;
58 clk_t clk;
59 hwreset_t reset;
60 };
61
62 struct tegra_efuse_softc *dev_sc;
63 struct tegra_sku_info tegra_sku_info;
64 static char *tegra_rev_name[] = {
65 [TEGRA_REVISION_UNKNOWN] = "unknown",
66 [TEGRA_REVISION_A01] = "A01",
67 [TEGRA_REVISION_A02] = "A02",
68 [TEGRA_REVISION_A03] = "A03",
69 [TEGRA_REVISION_A03p] = "A03 prime",
70 [TEGRA_REVISION_A04] = "A04",
71 };
72
73 struct efuse_soc {
74 void (*init)(struct tegra_efuse_softc *sc,
75 struct tegra_sku_info *sku);
76 };
77
78 static void tegra124_init(struct tegra_efuse_softc *sc,
79 struct tegra_sku_info *sku);
80 struct efuse_soc tegra124_efuse_soc = {
81 .init = tegra124_init,
82 };
83
84 static void tegra210_init(struct tegra_efuse_softc *sc,
85 struct tegra_sku_info *sku);
86 struct efuse_soc tegra210_efuse_soc = {
87 .init = tegra210_init,
88 };
89
90 static struct ofw_compat_data compat_data[] = {
91 {"nvidia,tegra124-efuse", (intptr_t)&tegra124_efuse_soc},
92 {"nvidia,tegra210-efuse", (intptr_t)&tegra210_efuse_soc},
93 {NULL, 0}
94 };
95
96 /* ---------------------- Tegra 124 specific code & data --------------- */
97 #define TEGRA124_CPU_PROCESS_CORNERS 2
98 #define TEGRA124_GPU_PROCESS_CORNERS 2
99 #define TEGRA124_SOC_PROCESS_CORNERS 2
100
101 #define TEGRA124_FUSE_SKU_INFO 0x10
102 #define TEGRA124_FUSE_CPU_SPEEDO_0 0x14
103 #define TEGRA124_FUSE_CPU_IDDQ 0x18
104 #define TEGRA124_FUSE_FT_REV 0x28
105 #define TEGRA124_FUSE_CPU_SPEEDO_1 0x2c
106 #define TEGRA124_FUSE_CPU_SPEEDO_2 0x30
107 #define TEGRA124_FUSE_SOC_SPEEDO_0 0x34
108 #define TEGRA124_FUSE_SOC_SPEEDO_1 0x38
109 #define TEGRA124_FUSE_SOC_SPEEDO_2 0x3c
110 #define TEGRA124_FUSE_SOC_IDDQ 0x40
111 #define TEGRA124_FUSE_GPU_IDDQ 0x128
112
113 enum {
114 TEGRA124_THRESHOLD_INDEX_0,
115 TEGRA124_THRESHOLD_INDEX_1,
116 TEGRA124_THRESHOLD_INDEX_COUNT,
117 };
118
119 static uint32_t tegra124_cpu_process_speedos[][TEGRA124_CPU_PROCESS_CORNERS] =
120 {
121 {2190, UINT_MAX},
122 {0, UINT_MAX},
123 };
124
125 static uint32_t tegra124_gpu_process_speedos[][TEGRA124_GPU_PROCESS_CORNERS] =
126 {
127 {1965, UINT_MAX},
128 {0, UINT_MAX},
129 };
130
131 static uint32_t tegra124_soc_process_speedos[][TEGRA124_SOC_PROCESS_CORNERS] =
132 {
133 {2101, UINT_MAX},
134 {0, UINT_MAX},
135 };
136
137
138 static void
tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc * sc,struct tegra_sku_info * sku,int * threshold)139 tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
140 struct tegra_sku_info *sku, int *threshold)
141 {
142
143 /* Set default */
144 sku->cpu_speedo_id = 0;
145 sku->soc_speedo_id = 0;
146 sku->gpu_speedo_id = 0;
147 *threshold = TEGRA124_THRESHOLD_INDEX_0;
148
149 switch (sku->sku_id) {
150 case 0x00: /* Eng sku */
151 case 0x0F:
152 case 0x23:
153 /* Using the default */
154 break;
155 case 0x83:
156 sku->cpu_speedo_id = 2;
157 break;
158
159 case 0x1F:
160 case 0x87:
161 case 0x27:
162 sku->cpu_speedo_id = 2;
163 sku->soc_speedo_id = 0;
164 sku->gpu_speedo_id = 1;
165 *threshold = TEGRA124_THRESHOLD_INDEX_0;
166 break;
167 case 0x81:
168 case 0x21:
169 case 0x07:
170 sku->cpu_speedo_id = 1;
171 sku->soc_speedo_id = 1;
172 sku->gpu_speedo_id = 1;
173 *threshold = TEGRA124_THRESHOLD_INDEX_1;
174 break;
175 case 0x49:
176 case 0x4A:
177 case 0x48:
178 sku->cpu_speedo_id = 4;
179 sku->soc_speedo_id = 2;
180 sku->gpu_speedo_id = 3;
181 *threshold = TEGRA124_THRESHOLD_INDEX_1;
182 break;
183 default:
184 device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id);
185 break;
186 }
187 }
188
189 static void
tegra124_init(struct tegra_efuse_softc * sc,struct tegra_sku_info * sku)190 tegra124_init(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
191 {
192 int i, threshold;
193
194 sku->sku_id = RD4(sc, TEGRA124_FUSE_SKU_INFO);
195 sku->soc_iddq_value = RD4(sc, TEGRA124_FUSE_SOC_IDDQ);
196 sku->cpu_iddq_value = RD4(sc, TEGRA124_FUSE_CPU_IDDQ);
197 sku->gpu_iddq_value = RD4(sc, TEGRA124_FUSE_GPU_IDDQ);
198 sku->soc_speedo_value = RD4(sc, TEGRA124_FUSE_SOC_SPEEDO_0);
199 sku->cpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_0);
200 sku->gpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_2);
201
202 if (sku->cpu_speedo_value == 0) {
203 device_printf(sc->dev, "CPU Speedo value is not fused.\n");
204 return;
205 }
206
207 tegra124_rev_sku_to_speedo_ids(sc, sku, &threshold);
208
209 for (i = 0; i < TEGRA124_SOC_PROCESS_CORNERS; i++) {
210 if (sku->soc_speedo_value <
211 tegra124_soc_process_speedos[threshold][i])
212 break;
213 }
214 sku->soc_process_id = i;
215
216 for (i = 0; i < TEGRA124_CPU_PROCESS_CORNERS; i++) {
217 if (sku->cpu_speedo_value <
218 tegra124_cpu_process_speedos[threshold][i])
219 break;
220 }
221 sku->cpu_process_id = i;
222
223 for (i = 0; i < TEGRA124_GPU_PROCESS_CORNERS; i++) {
224 if (sku->gpu_speedo_value <
225 tegra124_gpu_process_speedos[threshold][i])
226 break;
227 }
228 sku->gpu_process_id = i;
229
230 }
231 /* ----------------- End of Tegra 124 specific code & data --------------- */
232
233 /* -------------------- Tegra 201 specific code & data ------------------- */
234 #define TEGRA210_CPU_PROCESS_CORNERS 2
235 #define TEGRA210_GPU_PROCESS_CORNERS 2
236 #define TEGRA210_SOC_PROCESS_CORNERS 3
237
238 #define TEGRA210_FUSE_SKU_INFO 0x010
239 #define TEGRA210_FUSE_CPU_SPEEDO_0 0x014
240 #define TEGRA210_FUSE_CPU_IDDQ 0x018
241 #define TEGRA210_FUSE_FT_REV 0x028
242 #define TEGRA210_FUSE_CPU_SPEEDO_1 0x02c
243 #define TEGRA210_FUSE_CPU_SPEEDO_2 0x030
244 #define TEGRA210_FUSE_SOC_SPEEDO_0 0x034
245 #define TEGRA210_FUSE_SOC_SPEEDO_1 0x038
246 #define TEGRA210_FUSE_SOC_SPEEDO_2 0x03c
247 #define TEGRA210_FUSE_SOC_IDDQ 0x040
248 #define TEGRA210_FUSE_GPU_IDDQ 0x128
249 #define TEGRA210_FUSE_SPARE 0x270
250
251 enum {
252 TEGRA210_THRESHOLD_INDEX_0,
253 TEGRA210_THRESHOLD_INDEX_1,
254 TEGRA210_THRESHOLD_INDEX_COUNT,
255 };
256
257 static uint32_t tegra210_cpu_process_speedos[][TEGRA210_CPU_PROCESS_CORNERS] =
258 {
259 {2119, UINT_MAX},
260 {2119, UINT_MAX},
261 };
262
263 static uint32_t tegra210_gpu_process_speedos[][TEGRA210_GPU_PROCESS_CORNERS] =
264 {
265 {UINT_MAX, UINT_MAX},
266 {UINT_MAX, UINT_MAX},
267 };
268
269 static uint32_t tegra210_soc_process_speedos[][TEGRA210_SOC_PROCESS_CORNERS] =
270 {
271 {1950, 2100, UINT_MAX},
272 {1950, 2100, UINT_MAX},
273 };
274
275 static uint32_t
tegra210_get_speedo_revision(struct tegra_efuse_softc * sc)276 tegra210_get_speedo_revision(struct tegra_efuse_softc *sc)
277 {
278 uint32_t reg;
279 uint32_t val;
280
281 val = 0;
282
283 /* Revision i encoded in spare fields */
284 reg = RD4(sc, TEGRA210_FUSE_SPARE + 2 * 4);
285 val |= (reg & 1) << 0;
286 reg = RD4(sc, TEGRA210_FUSE_SPARE + 3 * 4);
287 val |= (reg & 1) << 1;
288 reg = RD4(sc, TEGRA210_FUSE_SPARE + 4 * 4);
289 val |= (reg & 1) << 2;
290
291 return (val);
292 }
293
294
295 static void
tegra210_rev_sku_to_speedo_ids(struct tegra_efuse_softc * sc,struct tegra_sku_info * sku,int speedo_rev,int * threshold)296 tegra210_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
297 struct tegra_sku_info *sku, int speedo_rev, int *threshold)
298 {
299
300 /* Set defaults */
301 sku->cpu_speedo_id = 0;
302 sku->soc_speedo_id = 0;
303 sku->gpu_speedo_id = 0;
304 *threshold = TEGRA210_THRESHOLD_INDEX_0;
305
306 switch (sku->sku_id) {
307 case 0x00: /* Eng sku */
308 case 0x01: /* Eng sku */
309 case 0x07:
310 case 0x17:
311 case 0x27:
312 /* Use defaults */
313 if (speedo_rev >= 2)
314 sku->gpu_speedo_id = 1;
315 break;
316 case 0x13:
317 if (speedo_rev >= 2)
318 sku->gpu_speedo_id = 1;
319 sku->cpu_speedo_id = 1;
320 break;
321
322 default:
323 device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id);
324 break;
325 }
326 }
327
328
329 static void
tegra210_init(struct tegra_efuse_softc * sc,struct tegra_sku_info * sku)330 tegra210_init(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
331 {
332 int i, threshold, speedo_rev;
333 uint32_t cpu_speedo[3], soc_speedo[3];
334
335 cpu_speedo[0] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_0);
336 cpu_speedo[1] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_1);
337 cpu_speedo[2] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_2);
338 soc_speedo[0] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_0);
339 soc_speedo[1] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_1);
340 soc_speedo[2] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_2);
341
342
343 sku->cpu_iddq_value = RD4(sc, TEGRA210_FUSE_CPU_IDDQ);
344 sku->soc_iddq_value = RD4(sc, TEGRA210_FUSE_SOC_IDDQ);
345 sku->gpu_iddq_value = RD4(sc, TEGRA210_FUSE_GPU_IDDQ);
346
347 speedo_rev = tegra210_get_speedo_revision(sc);
348 device_printf(sc->dev, " Speedo revision: %u\n", speedo_rev);
349
350 if (speedo_rev >= 3) {
351 sku->cpu_speedo_value = cpu_speedo[0];
352 sku->gpu_speedo_value = cpu_speedo[2];
353 sku->soc_speedo_value = soc_speedo[0];
354 } else if (speedo_rev == 2) {
355 sku->cpu_speedo_value =
356 (-1938 + (1095 * cpu_speedo[0] / 100)) / 10;
357 sku->gpu_speedo_value =
358 (-1662 + (1082 * cpu_speedo[2] / 100)) / 10;
359 sku->soc_speedo_value =
360 ( -705 + (1037 * soc_speedo[0] / 100)) / 10;
361 } else {
362 sku->cpu_speedo_value = 2100;
363 sku->gpu_speedo_value = cpu_speedo[2] - 75;
364 sku->soc_speedo_value = 1900;
365 }
366
367 tegra210_rev_sku_to_speedo_ids(sc, sku, speedo_rev, &threshold);
368
369 for (i = 0; i < TEGRA210_SOC_PROCESS_CORNERS; i++) {
370 if (sku->soc_speedo_value <
371 tegra210_soc_process_speedos[threshold][i])
372 break;
373 }
374 sku->soc_process_id = i;
375
376 for (i = 0; i < TEGRA210_CPU_PROCESS_CORNERS; i++) {
377 if (sku->cpu_speedo_value <
378 tegra210_cpu_process_speedos[threshold][i])
379 break;
380 }
381 sku->cpu_process_id = i;
382
383 for (i = 0; i < TEGRA210_GPU_PROCESS_CORNERS; i++) {
384 if (sku->gpu_speedo_value <
385 tegra210_gpu_process_speedos[threshold][i])
386 break;
387 }
388 sku->gpu_process_id = i;
389
390 }
391
392 /* ----------------- End of Tegra 210 specific code & data --------------- */
393
394
395 uint32_t
tegra_fuse_read_4(int addr)396 tegra_fuse_read_4(int addr) {
397 if (dev_sc == NULL)
398 panic("tegra_fuse_read_4 called too early");
399 return (RD4(dev_sc, addr));
400 }
401
402 static void
tegra_efuse_dump_sku(void)403 tegra_efuse_dump_sku(void)
404 {
405 printf(" TEGRA SKU Info:\n");
406 printf(" chip_id: %u\n", tegra_sku_info.chip_id);
407 printf(" sku_id: %u\n", tegra_sku_info.sku_id);
408 printf(" cpu_process_id: %u\n", tegra_sku_info.cpu_process_id);
409 printf(" cpu_speedo_id: %u\n", tegra_sku_info.cpu_speedo_id);
410 printf(" cpu_speedo_value: %u\n", tegra_sku_info.cpu_speedo_value);
411 printf(" cpu_iddq_value: %u\n", tegra_sku_info.cpu_iddq_value);
412 printf(" soc_process_id: %u\n", tegra_sku_info.soc_process_id);
413 printf(" soc_speedo_id: %u\n", tegra_sku_info.soc_speedo_id);
414 printf(" soc_speedo_value: %u\n", tegra_sku_info.soc_speedo_value);
415 printf(" soc_iddq_value: %u\n", tegra_sku_info.soc_iddq_value);
416 printf(" gpu_process_id: %u\n", tegra_sku_info.gpu_process_id);
417 printf(" gpu_speedo_id: %u\n", tegra_sku_info.gpu_speedo_id);
418 printf(" gpu_speedo_value: %u\n", tegra_sku_info.gpu_speedo_value);
419 printf(" gpu_iddq_value: %u\n", tegra_sku_info.gpu_iddq_value);
420 printf(" revision: %s\n", tegra_rev_name[tegra_sku_info.revision]);
421 }
422
423 static int
tegra_efuse_probe(device_t dev)424 tegra_efuse_probe(device_t dev)
425 {
426 if (!ofw_bus_status_okay(dev))
427 return (ENXIO);
428
429 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
430 return (ENXIO);
431
432 return (BUS_PROBE_DEFAULT);
433 }
434
435 static int
tegra_efuse_attach(device_t dev)436 tegra_efuse_attach(device_t dev)
437 {
438 int rv, rid;
439 struct tegra_efuse_softc *sc;
440
441 sc = device_get_softc(dev);
442 sc->dev = dev;
443 sc->soc = (struct efuse_soc *)ofw_bus_search_compatible(dev,
444 compat_data)->ocd_data;
445
446 /* Get the memory resource for the register mapping. */
447 rid = 0;
448 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
449 RF_ACTIVE);
450 if (sc->mem_res == NULL) {
451 device_printf(dev, "Cannot map registers.\n");
452 rv = ENXIO;
453 goto fail;
454 }
455
456 /* OFW resources. */
457 rv = clk_get_by_ofw_name(dev, 0, "fuse", &sc->clk);
458 if (rv != 0) {
459 device_printf(dev, "Cannot get fuse clock: %d\n", rv);
460 goto fail;
461 }
462 rv = clk_enable(sc->clk);
463 if (rv != 0) {
464 device_printf(dev, "Cannot enable clock: %d\n", rv);
465 goto fail;
466 }
467 rv = hwreset_get_by_ofw_name(sc->dev, 0, "fuse", &sc->reset);
468 if (rv != 0) {
469 device_printf(dev, "Cannot get fuse reset\n");
470 goto fail;
471 }
472 rv = hwreset_deassert(sc->reset);
473 if (rv != 0) {
474 device_printf(sc->dev, "Cannot clear reset\n");
475 goto fail;
476 }
477
478 sc->soc->init(sc, &tegra_sku_info);
479
480 dev_sc = sc;
481
482 if (bootverbose)
483 tegra_efuse_dump_sku();
484 return (bus_generic_attach(dev));
485
486 fail:
487 dev_sc = NULL;
488 if (sc->clk != NULL)
489 clk_release(sc->clk);
490 if (sc->reset != NULL)
491 hwreset_release(sc->reset);
492 if (sc->mem_res != NULL)
493 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
494
495 return (rv);
496 }
497
498 static int
tegra_efuse_detach(device_t dev)499 tegra_efuse_detach(device_t dev)
500 {
501 struct tegra_efuse_softc *sc;
502 int error;
503
504 error = bus_generic_detach(dev);
505 if (error != 0)
506 return (error);
507
508 sc = device_get_softc(dev);
509 dev_sc = NULL;
510 if (sc->clk != NULL)
511 clk_release(sc->clk);
512 if (sc->reset != NULL)
513 hwreset_release(sc->reset);
514 if (sc->mem_res != NULL)
515 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
516
517 return (0);
518 }
519
520 static device_method_t tegra_efuse_methods[] = {
521 /* Device interface */
522 DEVMETHOD(device_probe, tegra_efuse_probe),
523 DEVMETHOD(device_attach, tegra_efuse_attach),
524 DEVMETHOD(device_detach, tegra_efuse_detach),
525
526 DEVMETHOD_END
527 };
528
529 static DEFINE_CLASS_0(efuse, tegra_efuse_driver, tegra_efuse_methods,
530 sizeof(struct tegra_efuse_softc));
531 EARLY_DRIVER_MODULE(tegra_efuse, simplebus, tegra_efuse_driver, NULL, NULL,
532 BUS_PASS_TIMER);
533