1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
6 #include <linux/device.h>
7 #include <linux/kernel.h>
10 #include <soc/tegra/fuse.h>
14 #define CPU_PROCESS_CORNERS 2
15 #define GPU_PROCESS_CORNERS 2
16 #define SOC_PROCESS_CORNERS 3
18 #define FUSE_CPU_SPEEDO_0 0x014
19 #define FUSE_CPU_SPEEDO_1 0x02c
20 #define FUSE_CPU_SPEEDO_2 0x030
21 #define FUSE_SOC_SPEEDO_0 0x034
22 #define FUSE_SOC_SPEEDO_1 0x038
23 #define FUSE_SOC_SPEEDO_2 0x03c
24 #define FUSE_CPU_IDDQ 0x018
25 #define FUSE_SOC_IDDQ 0x040
26 #define FUSE_GPU_IDDQ 0x128
27 #define FUSE_FT_REV 0x028
32 THRESHOLD_INDEX_COUNT
,
35 static const u32 __initconst cpu_process_speedos
[][CPU_PROCESS_CORNERS
] = {
40 static const u32 __initconst gpu_process_speedos
[][GPU_PROCESS_CORNERS
] = {
41 { UINT_MAX
, UINT_MAX
},
42 { UINT_MAX
, UINT_MAX
},
45 static const u32 __initconst soc_process_speedos
[][SOC_PROCESS_CORNERS
] = {
46 { 1950, 2100, UINT_MAX
},
47 { 1950, 2100, UINT_MAX
},
50 static u8 __init
get_speedo_revision(void)
52 return tegra_fuse_read_spare(4) << 2 |
53 tegra_fuse_read_spare(3) << 1 |
54 tegra_fuse_read_spare(2) << 0;
57 static void __init
rev_sku_to_speedo_ids(struct tegra_sku_info
*sku_info
,
58 u8 speedo_rev
, int *threshold
)
60 int sku
= sku_info
->sku_id
;
62 /* Assign to default */
63 sku_info
->cpu_speedo_id
= 0;
64 sku_info
->soc_speedo_id
= 0;
65 sku_info
->gpu_speedo_id
= 0;
66 *threshold
= THRESHOLD_INDEX_0
;
69 case 0x00: /* Engineering SKU */
70 case 0x01: /* Engineering SKU */
75 sku_info
->gpu_speedo_id
= 1;
80 sku_info
->gpu_speedo_id
= 1;
82 sku_info
->cpu_speedo_id
= 1;
86 pr_err("Tegra210: unknown SKU %#04x\n", sku
);
87 /* Using the default for the error case */
92 static int get_process_id(int value
, const u32
*speedos
, unsigned int num
)
96 for (i
= 0; i
< num
; i
++)
97 if (value
< speedos
[i
])
103 void __init
tegra210_init_speedo_data(struct tegra_sku_info
*sku_info
)
105 int cpu_speedo
[3], soc_speedo
[3];
109 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos
) !=
110 THRESHOLD_INDEX_COUNT
);
111 BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos
) !=
112 THRESHOLD_INDEX_COUNT
);
113 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos
) !=
114 THRESHOLD_INDEX_COUNT
);
116 /* Read speedo/IDDQ fuses */
117 cpu_speedo
[0] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0
);
118 cpu_speedo
[1] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_1
);
119 cpu_speedo
[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2
);
121 soc_speedo
[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0
);
122 soc_speedo
[1] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_1
);
123 soc_speedo
[2] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_2
);
126 * Determine CPU, GPU and SoC speedo values depending on speedo fusing
127 * revision. Note that GPU speedo value is fused in CPU_SPEEDO_2.
129 speedo_revision
= get_speedo_revision();
130 pr_info("Speedo Revision %u\n", speedo_revision
);
132 if (speedo_revision
>= 3) {
133 sku_info
->cpu_speedo_value
= cpu_speedo
[0];
134 sku_info
->gpu_speedo_value
= cpu_speedo
[2];
135 sku_info
->soc_speedo_value
= soc_speedo
[0];
136 } else if (speedo_revision
== 2) {
137 sku_info
->cpu_speedo_value
= (-1938 + (1095 * cpu_speedo
[0] / 100)) / 10;
138 sku_info
->gpu_speedo_value
= (-1662 + (1082 * cpu_speedo
[2] / 100)) / 10;
139 sku_info
->soc_speedo_value
= ( -705 + (1037 * soc_speedo
[0] / 100)) / 10;
141 sku_info
->cpu_speedo_value
= 2100;
142 sku_info
->gpu_speedo_value
= cpu_speedo
[2] - 75;
143 sku_info
->soc_speedo_value
= 1900;
146 if ((sku_info
->cpu_speedo_value
<= 0) ||
147 (sku_info
->gpu_speedo_value
<= 0) ||
148 (sku_info
->soc_speedo_value
<= 0)) {
149 WARN(1, "speedo value not fused\n");
153 rev_sku_to_speedo_ids(sku_info
, speedo_revision
, &index
);
155 sku_info
->gpu_process_id
= get_process_id(sku_info
->gpu_speedo_value
,
156 gpu_process_speedos
[index
],
157 GPU_PROCESS_CORNERS
);
159 sku_info
->cpu_process_id
= get_process_id(sku_info
->cpu_speedo_value
,
160 cpu_process_speedos
[index
],
161 CPU_PROCESS_CORNERS
);
163 sku_info
->soc_process_id
= get_process_id(sku_info
->soc_speedo_value
,
164 soc_process_speedos
[index
],
165 SOC_PROCESS_CORNERS
);
167 pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
168 sku_info
->gpu_speedo_id
, sku_info
->gpu_speedo_value
);