Merge remote branch 'git-master/android-tegra-2.6.36' into 0112-1120
[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  *
6  * Author:
7  *      Colin Cross <ccross@android.com>
8  *
9  * This software is licensed under the terms of the GNU General Public
10  * License version 2, as published by the Free Software Foundation, and
11  * may be copied, distributed, and modified under those terms.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/io.h>
22
23 #include <mach/iomap.h>
24
25 #include "fuse.h"
26 #include "apbio.h"
27
28 #define FUSE_SKU_INFO           0x110
29 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
30 #define FUSE_UID_LOW            0x108
31 #define FUSE_UID_HIGH           0x10c
32 #define FUSE_SPARE_BIT          0x200
33 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
34 #define FUSE_VENDOR_CODE        0x200
35 #define FUSE_VENDOR_CODE_MASK   0xf
36 #define FUSE_FAB_CODE           0x204
37 #define FUSE_FAB_CODE_MASK      0x3f
38 #define FUSE_LOT_CODE_0         0x208
39 #define FUSE_LOT_CODE_1         0x20c
40 #define FUSE_WAFER_ID           0x210
41 #define FUSE_WAFER_ID_MASK      0x3f
42 #define FUSE_X_COORDINATE       0x214
43 #define FUSE_X_COORDINATE_MASK  0x1ff
44 #define FUSE_Y_COORDINATE       0x218
45 #define FUSE_Y_COORDINATE_MASK  0x1ff
46 #define FUSE_SPARE_BIT          0x244
47 #endif
48
49 static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
50         [TEGRA_REVISION_UNKNOWN] = "unknown",
51 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
52         [TEGRA_REVISION_A02] = "A02",
53         [TEGRA_REVISION_A03] = "A03",
54         [TEGRA_REVISION_A03p] = "A03 prime",
55 #elif CONFIG_ARCH_TEGRA_3x_SOC
56         [TEGRA_REVISION_A01] = "A01",
57 #endif
58 };
59
60 u32 tegra_fuse_readl(unsigned long offset)
61 {
62         return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
63 }
64
65 void tegra_fuse_writel(u32 value, unsigned long offset)
66 {
67         tegra_apb_writel(value, TEGRA_FUSE_BASE + offset);
68 }
69
70 static inline bool get_spare_fuse(int bit)
71 {
72         return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
73 }
74
75 void tegra_init_fuse(void)
76 {
77         u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
78         reg |= 1 << 28;
79         writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
80 // !!! FIXME !!! add tegra3 stub
81 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
82         tegra_init_speedo_data();
83 #endif
84
85         pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
86                 tegra_revision_name[tegra_get_revision()],
87                 tegra_sku_id(), tegra_cpu_process_id(),
88                 tegra_core_process_id());
89 }
90
91 unsigned long long tegra_chip_uid(void)
92 {
93 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
94         unsigned long long lo, hi;
95
96         lo = tegra_fuse_readl(FUSE_UID_LOW);
97         hi = tegra_fuse_readl(FUSE_UID_HIGH);
98         return (hi << 32ull) | lo;
99 #else
100         u64 uid = 0ull;
101         u32 reg;
102         u32 cid;
103         u32 vendor;
104         u32 fab;
105         u32 lot;
106         u32 wafer;
107         u32 x;
108         u32 y;
109         u32 i;
110
111         /* This used to be so much easier in prior chips. Unfortunately, there
112            is no one-stop shopping for the unique id anymore. It must be
113            constructed from various bits of information burned into the fuses
114            during the manufacturing process. The 64-bit unique id is formed
115            by concatenating several bit fields. The notation used for the
116            various fields is <fieldname:size_in_bits> with the UID composed
117            thusly:
118
119             <CID:4><VENDOR:4><FAB:6><LOT:26><WAFER:6><X:9><Y:9>
120
121            Where:
122
123                 Field    Bits  Position Data
124                 -------  ----  -------- ----------------------------------------
125                 CID        4     60     Chip id (encoded as zero for T30)
126                 VENDOR     4     56     Vendor code
127                 FAB        6     50     FAB code
128                 LOT       26     24     Lot code (5-digit base-36-coded-decimal,
129                                             re-encoded to 26 bits binary)
130                 WAFER      6     18     Wafer id
131                 X          9      9     Wafer X-coordinate
132                 Y          9      0     Wafer Y-coordinate
133                 -------  ----
134                 Total     64
135         */
136
137         /* Get the chip id and encode each chip variant as a unique value. */
138         reg = readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + 0x804));
139         reg = (reg & 0xFF00) >> 8;
140
141         switch (reg) {
142         case 0x30:
143                 cid = 0;
144                 break;
145
146         default:
147                 BUG();
148                 break;
149         }
150
151         vendor = tegra_fuse_readl(FUSE_VENDOR_CODE) & FUSE_VENDOR_CODE_MASK;
152         fab = tegra_fuse_readl(FUSE_FAB_CODE) & FUSE_FAB_CODE_MASK;
153
154         /* Lot code must be re-encoded from a 5 digit base-36 'BCD' number
155            to a binary number. */
156         lot = 0;
157         reg = tegra_fuse_readl(FUSE_LOT_CODE_1) << 2;
158
159         for (i = 0; i < 5; ++i) {
160                 u32 digit = (reg & 0xFC000000) >> 26;
161                 BUG_ON(digit >= 36);
162                 lot *= 36;
163                 lot += digit;
164                 reg <<= 6;
165         }
166
167         wafer = tegra_fuse_readl(FUSE_WAFER_ID) & FUSE_WAFER_ID_MASK;
168         x = tegra_fuse_readl(FUSE_X_COORDINATE) & FUSE_X_COORDINATE_MASK;
169         y = tegra_fuse_readl(FUSE_Y_COORDINATE) & FUSE_Y_COORDINATE_MASK;
170
171         uid = ((unsigned long long)cid  << 60ull)
172             | ((unsigned long long)vendor << 56ull)
173             | ((unsigned long long)fab << 50ull)
174             | ((unsigned long long)lot << 24ull)
175             | ((unsigned long long)wafer << 18ull)
176             | ((unsigned long long)x << 9ull)
177             | ((unsigned long long)y << 0ull);
178         return uid;
179 #endif
180 }
181
182 unsigned int tegra_spare_fuse(int bit)
183 {
184         BUG_ON(bit < 0 || bit > 61);
185         return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
186 }
187
188 int tegra_sku_id(void)
189 {
190         int sku_id;
191         u32 reg = tegra_fuse_readl(FUSE_SKU_INFO);
192         sku_id = reg & 0xFF;
193         return sku_id;
194 }
195
196 enum tegra_revision tegra_get_revision(void)
197 {
198         void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
199         u32 id = readl(chip_id);
200
201         switch ((id >> 16) & 0xf) {
202 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
203         case 2:
204                 return TEGRA_REVISION_A02;
205         case 3:
206                 if (get_spare_fuse(18) || get_spare_fuse(19))
207                         return TEGRA_REVISION_A03p;
208                 else
209                         return TEGRA_REVISION_A03;
210 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
211         case 1:\r
212                 return TEGRA_REVISION_A01;
213 #endif
214         default:
215                 return TEGRA_REVISION_UNKNOWN;
216         }
217 }