ARM: tegra: clock: Set Tegra3 CPU maximum rate to 1.4GHz
[linux-2.6.git] / arch / arm / mach-tegra / tegra3_speedo.c
1 /*
2  * arch/arm/mach-tegra/tegra3_speedo.c
3  *
4  * Copyright (c) 2011, NVIDIA Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/err.h>
24 #include <mach/iomap.h>
25
26 #include "fuse.h"
27
28 #define PROCESS_CORNERS_NUM     4
29
30 #define FUSE_SPEEDO_CALIB_0     0x114
31
32 /* Maximum speedo levels for each core process corner */
33 static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = {
34 // proc_id 0    1
35         {180, 240}, // soc_speedo_id 0
36         {180, 240}, // soc_speedo_id 1
37         {200, 240}, // soc_speedo_id 2
38 };
39
40 /* Maximum speedo levels for each CPU process corner */
41 static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
42 // proc_id 0    1    2    3
43         {306, 338, 360, 376}, // soc_speedo_id 0
44         {306, 338, 360, 376}, // soc_speedo_id 1
45         {338, 338, 360, 376}, // soc_speedo_id 2
46 };
47
48 static int cpu_process_id;
49 static int core_process_id;
50 static int soc_speedo_id;
51
52 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
53 {
54         u32 reg;
55
56         BUG_ON(!speedo_g || !speedo_lp);
57         reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
58
59         // Speedo LP = Lower 16-bits Multiplied by 4
60         *speedo_lp = (reg & 0xFFFF) * 4;
61
62         // Speedo G = Upper 16-bits Multiplied by 4
63         *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
64 }
65
66 static int rev_sku_to_soc_speedo(int rev, int sku)
67 {
68         int soc_speedo;
69
70         switch (rev) {
71         case TEGRA_REVISION_A01:
72                 soc_speedo = 0;
73                 break;
74         case TEGRA_REVISION_A02:
75                 switch (sku) {
76                 case 0: // AP30
77                         soc_speedo = 1;
78                         break;
79                 case 1: // T30
80                         soc_speedo = 2;
81                         break;
82                 default:
83                         BUG();
84                         break;
85                 }
86                 break;
87         default:
88                 BUG();
89                 break;
90         }
91
92         pr_debug("Tegra3 SKU: %d Rev: %s Speedo: %d ",
93                  sku, tegra_get_revision_name(), soc_speedo);
94         return soc_speedo;
95 }
96
97 void tegra_init_speedo_data(void)
98 {
99         u32 cpu_speedo_val, core_speedo_val;
100         int iv;
101
102         soc_speedo_id = rev_sku_to_soc_speedo(tegra_get_revision(),
103                                               tegra_sku_id());
104         BUG_ON(soc_speedo_id >= ARRAY_SIZE(cpu_process_speedos));
105
106         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
107         pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
108         pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
109
110         cpu_process_id = -1; // out of range for valid cpu-speedo
111         for (iv = 0; iv < PROCESS_CORNERS_NUM; iv++) {
112                 if (cpu_speedo_val < cpu_process_speedos[soc_speedo_id][iv]) {
113                         cpu_process_id = iv -1;
114                         break;
115                 }
116         }
117         if (cpu_process_id == -1) {
118                 pr_err("****************************************************");
119                 pr_err("****************************************************");
120                 pr_err("* tegra3_speedo: CPU speedo value %3d out of range *",
121                        cpu_speedo_val);
122                 pr_err("****************************************************");
123                 pr_err("****************************************************");
124
125                 cpu_process_id = INVALID_PROCESS_ID;
126         }
127
128         core_process_id = -1; // out of range for valid core-speedo
129         for (iv = 0; iv < PROCESS_CORNERS_NUM; iv++) {
130                 if (core_speedo_val < core_process_speedos[soc_speedo_id][iv]) {
131                         core_process_id = iv -1;
132                         break;
133                 }
134         }
135         if (core_process_id == -1) {
136                 pr_err("*****************************************************");
137                 pr_err("*****************************************************");
138                 pr_err("* tegra3_speedo: CORE speedo value %3d out of range *",
139                        core_speedo_val);
140                 pr_err("*****************************************************");
141                 pr_err("*****************************************************");
142
143                 core_process_id = INVALID_PROCESS_ID;
144         }
145
146         pr_info("Tegra3 SKU: %d Rev: %s CPU Process: %d CORE Process: %d "
147                 "Speedo ID: %d",
148                 tegra_sku_id(), tegra_get_revision_name(),
149                 cpu_process_id, core_process_id, soc_speedo_id);
150 }
151
152 int tegra_cpu_process_id(void)
153 {
154         // FIXME: remove this when ready to deprecate invalid process-id boards
155         if (cpu_process_id == INVALID_PROCESS_ID)
156                 return 0;
157         else
158                 return cpu_process_id;
159 }
160
161 int tegra_core_process_id(void)
162 {
163         // FIXME: remove this when ready to deprecate invalid process-id boards
164         if (core_process_id == INVALID_PROCESS_ID)
165                 return 0;
166         else
167                 return core_process_id;
168 }
169
170 int tegra_soc_speedo_id(void)
171 {
172         return soc_speedo_id;
173 }