ARM: tegra: clock: Fix speedo_id eval for max speedo value
[linux-2.6.git] / arch / arm / mach-tegra / fuse.c
1 /*
2  * arch/arm/mach-tegra/fuse.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  * Copyright (C) 2010-2011 NVIDIA Corp.
6  *
7  * Author:
8  *      Colin Cross <ccross@android.com>
9  *
10  * This software is licensed under the terms of the GNU General Public
11  * License version 2, as published by the Free Software Foundation, and
12  * may be copied, distributed, and modified under those terms.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/init.h>
24 #include <linux/string.h>
25
26 #include <mach/iomap.h>
27
28 #include "fuse.h"
29 #include "apbio.h"
30
31 #define FUSE_SKU_INFO           0x110
32 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
33 #define FUSE_UID_LOW            0x108
34 #define FUSE_UID_HIGH           0x10c
35 #define FUSE_SPARE_BIT          0x200
36 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
37 #define FUSE_VENDOR_CODE        0x200
38 #define FUSE_VENDOR_CODE_MASK   0xf
39 #define FUSE_FAB_CODE           0x204
40 #define FUSE_FAB_CODE_MASK      0x3f
41 #define FUSE_LOT_CODE_0         0x208
42 #define FUSE_LOT_CODE_1         0x20c
43 #define FUSE_WAFER_ID           0x210
44 #define FUSE_WAFER_ID_MASK      0x3f
45 #define FUSE_X_COORDINATE       0x214
46 #define FUSE_X_COORDINATE_MASK  0x1ff
47 #define FUSE_Y_COORDINATE       0x218
48 #define FUSE_Y_COORDINATE_MASK  0x1ff
49 #define FUSE_SPARE_BIT          0x244
50 #endif
51
52 static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
53         [TEGRA_REVISION_UNKNOWN] = "unknown",
54 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
55         [TEGRA_REVISION_A01] = "A01",
56 #endif
57         [TEGRA_REVISION_A02] = "A02",
58 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
59         [TEGRA_REVISION_A03] = "A03",
60         [TEGRA_REVISION_A03p] = "A03 prime",
61 #endif
62 };
63
64 u32 tegra_fuse_readl(unsigned long offset)
65 {
66         return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
67 }
68
69 void tegra_fuse_writel(u32 value, unsigned long offset)
70 {
71         tegra_apb_writel(value, TEGRA_FUSE_BASE + offset);
72 }
73
74 static inline bool get_spare_fuse(int bit)
75 {
76         return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
77 }
78
79 const char *tegra_get_revision_name(void)
80 {
81         return tegra_revision_name[tegra_get_revision()];
82 }
83
84 void tegra_init_fuse(void)
85 {
86         u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
87         reg |= 1 << 28;
88         writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
89         tegra_init_speedo_data();
90
91         pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d "
92                 "Speedo ID: %d\n",
93                 tegra_get_revision_name(),
94                 tegra_sku_id(), tegra_cpu_process_id(),
95                 tegra_core_process_id(), tegra_soc_speedo_id());
96 }
97
98 unsigned long long tegra_chip_uid(void)
99 {
100 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
101         unsigned long long lo, hi;
102
103         lo = tegra_fuse_readl(FUSE_UID_LOW);
104         hi = tegra_fuse_readl(FUSE_UID_HIGH);
105         return (hi << 32ull) | lo;
106 #else
107         u64 uid = 0ull;
108         u32 reg;
109         u32 cid;
110         u32 vendor;
111         u32 fab;
112         u32 lot;
113         u32 wafer;
114         u32 x;
115         u32 y;
116         u32 i;
117
118         /* This used to be so much easier in prior chips. Unfortunately, there
119            is no one-stop shopping for the unique id anymore. It must be
120            constructed from various bits of information burned into the fuses
121            during the manufacturing process. The 64-bit unique id is formed
122            by concatenating several bit fields. The notation used for the
123            various fields is <fieldname:size_in_bits> with the UID composed
124            thusly:
125
126             <CID:4><VENDOR:4><FAB:6><LOT:26><WAFER:6><X:9><Y:9>
127
128            Where:
129
130                 Field    Bits  Position Data
131                 -------  ----  -------- ----------------------------------------
132                 CID        4     60     Chip id (encoded as zero for T30)
133                 VENDOR     4     56     Vendor code
134                 FAB        6     50     FAB code
135                 LOT       26     24     Lot code (5-digit base-36-coded-decimal,
136                                             re-encoded to 26 bits binary)
137                 WAFER      6     18     Wafer id
138                 X          9      9     Wafer X-coordinate
139                 Y          9      0     Wafer Y-coordinate
140                 -------  ----
141                 Total     64
142         */
143
144         /* Get the chip id and encode each chip variant as a unique value. */
145         reg = readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + 0x804));
146         reg = (reg & 0xFF00) >> 8;
147
148         switch (reg) {
149         case 0x30:
150                 cid = 0;
151                 break;
152
153         default:
154                 BUG();
155                 break;
156         }
157
158         vendor = tegra_fuse_readl(FUSE_VENDOR_CODE) & FUSE_VENDOR_CODE_MASK;
159         fab = tegra_fuse_readl(FUSE_FAB_CODE) & FUSE_FAB_CODE_MASK;
160
161         /* Lot code must be re-encoded from a 5 digit base-36 'BCD' number
162            to a binary number. */
163         lot = 0;
164         reg = tegra_fuse_readl(FUSE_LOT_CODE_1) << 2;
165
166         for (i = 0; i < 5; ++i) {
167                 u32 digit = (reg & 0xFC000000) >> 26;
168                 BUG_ON(digit >= 36);
169                 lot *= 36;
170                 lot += digit;
171                 reg <<= 6;
172         }
173
174         wafer = tegra_fuse_readl(FUSE_WAFER_ID) & FUSE_WAFER_ID_MASK;
175         x = tegra_fuse_readl(FUSE_X_COORDINATE) & FUSE_X_COORDINATE_MASK;
176         y = tegra_fuse_readl(FUSE_Y_COORDINATE) & FUSE_Y_COORDINATE_MASK;
177
178         uid = ((unsigned long long)cid  << 60ull)
179             | ((unsigned long long)vendor << 56ull)
180             | ((unsigned long long)fab << 50ull)
181             | ((unsigned long long)lot << 24ull)
182             | ((unsigned long long)wafer << 18ull)
183             | ((unsigned long long)x << 9ull)
184             | ((unsigned long long)y << 0ull);
185         return uid;
186 #endif
187 }
188
189 unsigned int tegra_spare_fuse(int bit)
190 {
191         BUG_ON(bit < 0 || bit > 61);
192         return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
193 }
194
195 int tegra_sku_id(void)
196 {
197         int sku_id;
198         u32 reg = tegra_fuse_readl(FUSE_SKU_INFO);
199         sku_id = reg & 0xFF;
200         return sku_id;
201 }
202
203 struct tegra_id tegra_id;
204
205 static enum tegra_revision tegra_decode_revision(const struct tegra_id *id)
206 {
207 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
208         if ((id->chipid & 0xf0) != 0x20)
209                 return TEGRA_REVISION_UNKNOWN;
210 #endif
211 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
212         if ((id->chipid & 0xf0) != 0x30)
213                 return TEGRA_REVISION_UNKNOWN;
214
215         switch (id->major) {
216         case 0:
217                 if (id->minor != 1)
218                         return TEGRA_REVISION_UNKNOWN;
219                 else if (id->netlist == 12 && (id->patch & 0xf) == 12)
220                         return TEGRA_REVISION_A01;
221                 else if (id->netlist == 12 && (id->patch & 0xf) > 12)
222                         return TEGRA_REVISION_A02;
223                 else if (id->netlist > 12)
224                         return TEGRA_REVISION_A02;
225                 else
226                         return TEGRA_REVISION_UNKNOWN;
227         case 1:
228                 break;
229         default:
230                 return TEGRA_REVISION_UNKNOWN;
231         }
232 #endif
233
234         switch (id->minor) {
235 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
236         case 1:
237                 return TEGRA_REVISION_A01;
238 #endif
239         case 2:
240                 return TEGRA_REVISION_A02;
241 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
242         case 3:
243                 return (*(id->priv) == 'p') ? TEGRA_REVISION_A03p
244                                             : TEGRA_REVISION_A03;
245 #endif
246         default:
247                 return TEGRA_REVISION_UNKNOWN;
248         }
249 }
250
251 static enum tegra_revision tegra_set_revision(u32 chipid,
252                                         u32 major, u32 minor,
253                                         u32 nlist, u32 patch, const char *priv)
254 {
255         tegra_id.chipid  = chipid;
256         tegra_id.major   = major;
257         tegra_id.minor   = minor;
258         tegra_id.netlist = nlist;
259         tegra_id.patch   = patch;
260         tegra_id.priv    = (char *)priv;
261         tegra_id.revision = tegra_decode_revision(&tegra_id);
262         return tegra_id.revision;
263 }
264
265 enum tegra_revision tegra_get_revision(void)
266 {
267         if (tegra_id.chipid)
268                 return tegra_id.revision;
269         else {/* Boot loader did not pass a valid chip ID */
270                 void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
271                 void __iomem *netlist = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x860;
272                 u32 cid = readl(chip_id);
273                 u32 nlist = readl(netlist);
274                 char *priv = NULL;
275
276 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
277                 if (get_spare_fuse(18) || get_spare_fuse(19))
278                         priv = "p";
279 #endif
280                 return tegra_set_revision((cid >> 8) & 0xff,
281                                         (cid >> 4) & 0xf,
282                                         (cid >> 16) & 0xf,
283                                         (nlist >> 0) & 0xffff,
284                                         (nlist >> 16) & 0xffff,
285                                         priv);
286         }
287 }
288
289 static char chippriv[16]; /* Permanent buffer for private string */
290 static int __init tegra_bootloader_tegraid(char *str)
291 {
292         u32 id[5];
293         int i = 0;
294         char *priv = NULL;
295
296         do {
297                 id[i++] = simple_strtoul(str, &str, 16);
298         } while (*str++ && i < ARRAY_SIZE(id));
299
300         if (*(str - 1) == '.') {
301                 strncpy(chippriv, str, sizeof(chippriv) - 1);
302                 priv = chippriv;
303                 if (strlen(str) > sizeof(chippriv) - 1)
304                         pr_err("### tegraid.priv in kernel arg truncated\n");
305         }
306
307         while (i < ARRAY_SIZE(id))
308                 id[i++] = 0;
309
310         (void)tegra_set_revision(id[0], id[1], id[2], id[3], id[4], priv);
311         return 0;
312 }
313
314 /* tegraid=chipid.major.minor.netlist.patch[.priv] */
315 early_param("tegraid", tegra_bootloader_tegraid);