1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. |
4 | */ |
5 | |
6 | #include <linux/device.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/bug.h> |
9 | |
10 | #include <soc/tegra/fuse.h> |
11 | |
12 | #include "fuse.h" |
13 | |
14 | #define CPU_PROCESS_CORNERS 2 |
15 | #define GPU_PROCESS_CORNERS 2 |
16 | #define SOC_PROCESS_CORNERS 2 |
17 | |
18 | #define FUSE_CPU_SPEEDO_0 0x14 |
19 | #define FUSE_CPU_SPEEDO_1 0x2c |
20 | #define FUSE_CPU_SPEEDO_2 0x30 |
21 | #define FUSE_SOC_SPEEDO_0 0x34 |
22 | #define FUSE_SOC_SPEEDO_1 0x38 |
23 | #define FUSE_SOC_SPEEDO_2 0x3c |
24 | #define FUSE_CPU_IDDQ 0x18 |
25 | #define FUSE_SOC_IDDQ 0x40 |
26 | #define FUSE_GPU_IDDQ 0x128 |
27 | #define FUSE_FT_REV 0x28 |
28 | |
29 | enum { |
30 | THRESHOLD_INDEX_0, |
31 | THRESHOLD_INDEX_1, |
32 | THRESHOLD_INDEX_COUNT, |
33 | }; |
34 | |
35 | static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = { |
36 | {2190, UINT_MAX}, |
37 | {0, UINT_MAX}, |
38 | }; |
39 | |
40 | static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = { |
41 | {1965, UINT_MAX}, |
42 | {0, UINT_MAX}, |
43 | }; |
44 | |
45 | static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = { |
46 | {2101, UINT_MAX}, |
47 | {0, UINT_MAX}, |
48 | }; |
49 | |
50 | static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info, |
51 | int *threshold) |
52 | { |
53 | int sku = sku_info->sku_id; |
54 | |
55 | /* Assign to default */ |
56 | sku_info->cpu_speedo_id = 0; |
57 | sku_info->soc_speedo_id = 0; |
58 | sku_info->gpu_speedo_id = 0; |
59 | *threshold = THRESHOLD_INDEX_0; |
60 | |
61 | switch (sku) { |
62 | case 0x00: /* Eng sku */ |
63 | case 0x0F: |
64 | case 0x23: |
65 | /* Using the default */ |
66 | break; |
67 | case 0x83: |
68 | sku_info->cpu_speedo_id = 2; |
69 | break; |
70 | |
71 | case 0x1F: |
72 | case 0x87: |
73 | case 0x27: |
74 | sku_info->cpu_speedo_id = 2; |
75 | sku_info->soc_speedo_id = 0; |
76 | sku_info->gpu_speedo_id = 1; |
77 | *threshold = THRESHOLD_INDEX_0; |
78 | break; |
79 | case 0x81: |
80 | case 0x21: |
81 | case 0x07: |
82 | sku_info->cpu_speedo_id = 1; |
83 | sku_info->soc_speedo_id = 1; |
84 | sku_info->gpu_speedo_id = 1; |
85 | *threshold = THRESHOLD_INDEX_1; |
86 | break; |
87 | case 0x49: |
88 | case 0x4A: |
89 | case 0x48: |
90 | sku_info->cpu_speedo_id = 4; |
91 | sku_info->soc_speedo_id = 2; |
92 | sku_info->gpu_speedo_id = 3; |
93 | *threshold = THRESHOLD_INDEX_1; |
94 | break; |
95 | default: |
96 | pr_err("Tegra Unknown SKU %d\n" , sku); |
97 | /* Using the default for the error case */ |
98 | break; |
99 | } |
100 | } |
101 | |
102 | void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info) |
103 | { |
104 | int i, threshold, soc_speedo_0_value; |
105 | |
106 | BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != |
107 | THRESHOLD_INDEX_COUNT); |
108 | BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) != |
109 | THRESHOLD_INDEX_COUNT); |
110 | BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != |
111 | THRESHOLD_INDEX_COUNT); |
112 | |
113 | sku_info->cpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0); |
114 | if (sku_info->cpu_speedo_value == 0) { |
115 | pr_warn("Tegra Warning: Speedo value not fused.\n" ); |
116 | WARN_ON(1); |
117 | return; |
118 | } |
119 | |
120 | /* GPU Speedo is stored in CPU_SPEEDO_2 */ |
121 | sku_info->gpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2); |
122 | soc_speedo_0_value = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0); |
123 | |
124 | rev_sku_to_speedo_ids(sku_info, threshold: &threshold); |
125 | |
126 | sku_info->cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ); |
127 | |
128 | for (i = 0; i < GPU_PROCESS_CORNERS; i++) |
129 | if (sku_info->gpu_speedo_value < |
130 | gpu_process_speedos[threshold][i]) |
131 | break; |
132 | sku_info->gpu_process_id = i; |
133 | |
134 | for (i = 0; i < CPU_PROCESS_CORNERS; i++) |
135 | if (sku_info->cpu_speedo_value < |
136 | cpu_process_speedos[threshold][i]) |
137 | break; |
138 | sku_info->cpu_process_id = i; |
139 | |
140 | for (i = 0; i < SOC_PROCESS_CORNERS; i++) |
141 | if (soc_speedo_0_value < |
142 | soc_process_speedos[threshold][i]) |
143 | break; |
144 | sku_info->soc_process_id = i; |
145 | |
146 | pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n" , |
147 | sku_info->gpu_speedo_id, sku_info->gpu_speedo_value); |
148 | } |
149 | |