arm: tegra: fix ventana build break
[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 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
52         [TEGRA_REVISION_A02] = "A02",
53         [TEGRA_REVISION_A03] = "A03",
54         [TEGRA_REVISION_A03p] = "A03 prime",
55 #elif defined(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         tegra_init_speedo_data();
81
82         pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
83                 tegra_revision_name[tegra_get_revision()],
84                 tegra_sku_id(), tegra_cpu_process_id(),
85                 tegra_core_process_id());
86 }
87
88 unsigned long long tegra_chip_uid(void)
89 {
90 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
91         unsigned long long lo, hi;
92
93         lo = tegra_fuse_readl(FUSE_UID_LOW);
94         hi = tegra_fuse_readl(FUSE_UID_HIGH);
95         return (hi << 32ull) | lo;
96 #else
97         u64 uid = 0ull;
98         u32 reg;
99         u32 cid;
100         u32 vendor;
101         u32 fab;
102         u32 lot;
103         u32 wafer;
104         u32 x;
105         u32 y;
106         u32 i;
107
108         /* This used to be so much easier in prior chips. Unfortunately, there
109            is no one-stop shopping for the unique id anymore. It must be
110            constructed from various bits of information burned into the fuses
111            during the manufacturing process. The 64-bit unique id is formed
112            by concatenating several bit fields. The notation used for the
113            various fields is <fieldname:size_in_bits> with the UID composed
114            thusly:
115
116             <CID:4><VENDOR:4><FAB:6><LOT:26><WAFER:6><X:9><Y:9>
117
118            Where:
119
120                 Field    Bits  Position Data
121                 -------  ----  -------- ----------------------------------------
122                 CID        4     60     Chip id (encoded as zero for T30)
123                 VENDOR     4     56     Vendor code
124                 FAB        6     50     FAB code
125                 LOT       26     24     Lot code (5-digit base-36-coded-decimal,
126                                             re-encoded to 26 bits binary)
127                 WAFER      6     18     Wafer id
128                 X          9      9     Wafer X-coordinate
129                 Y          9      0     Wafer Y-coordinate
130                 -------  ----
131                 Total     64
132         */
133
134         /* Get the chip id and encode each chip variant as a unique value. */
135         reg = readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + 0x804));
136         reg = (reg & 0xFF00) >> 8;
137
138         switch (reg) {
139         case 0x30:
140                 cid = 0;
141                 break;
142
143         default:
144                 BUG();
145                 break;
146         }
147
148         vendor = tegra_fuse_readl(FUSE_VENDOR_CODE) & FUSE_VENDOR_CODE_MASK;
149         fab = tegra_fuse_readl(FUSE_FAB_CODE) & FUSE_FAB_CODE_MASK;
150
151         /* Lot code must be re-encoded from a 5 digit base-36 'BCD' number
152            to a binary number. */
153         lot = 0;
154         reg = tegra_fuse_readl(FUSE_LOT_CODE_1) << 2;
155
156         for (i = 0; i < 5; ++i) {
157                 u32 digit = (reg & 0xFC000000) >> 26;
158                 BUG_ON(digit >= 36);
159                 lot *= 36;
160                 lot += digit;
161                 reg <<= 6;
162         }
163
164         wafer = tegra_fuse_readl(FUSE_WAFER_ID) & FUSE_WAFER_ID_MASK;
165         x = tegra_fuse_readl(FUSE_X_COORDINATE) & FUSE_X_COORDINATE_MASK;
166         y = tegra_fuse_readl(FUSE_Y_COORDINATE) & FUSE_Y_COORDINATE_MASK;
167
168         uid = ((unsigned long long)cid  << 60ull)
169             | ((unsigned long long)vendor << 56ull)
170             | ((unsigned long long)fab << 50ull)
171             | ((unsigned long long)lot << 24ull)
172             | ((unsigned long long)wafer << 18ull)
173             | ((unsigned long long)x << 9ull)
174             | ((unsigned long long)y << 0ull);
175         return uid;
176 #endif
177 }
178
179 unsigned int tegra_spare_fuse(int bit)
180 {
181         BUG_ON(bit < 0 || bit > 61);
182         return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
183 }
184
185 int tegra_sku_id(void)
186 {
187         int sku_id;
188         u32 reg = tegra_fuse_readl(FUSE_SKU_INFO);
189         sku_id = reg & 0xFF;
190         return sku_id;
191 }
192
193 enum tegra_revision tegra_get_revision(void)
194 {
195         void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
196         u32 id = readl(chip_id);
197
198         switch ((id >> 16) & 0xf) {
199 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
200         case 2:
201                 return TEGRA_REVISION_A02;
202         case 3:
203                 if (get_spare_fuse(18) || get_spare_fuse(19))
204                         return TEGRA_REVISION_A03p;
205                 else
206                         return TEGRA_REVISION_A03;
207 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
208         case 1:\r
209                 return TEGRA_REVISION_A01;
210 #endif
211         default:
212                 return TEGRA_REVISION_UNKNOWN;
213         }
214 }