arm: tegra: hard code calib_base values
[linux-3.10.git] / arch / arm / mach-tegra / tegra12x_fuse_offsets.h
1 /*
2  * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
3  *
4  * this program is free software; you can redistribute it and/or modify
5  * it under the terms of the gnu general public license as published by
6  * the free software foundation; either version 2 of the license, or
7  * (at your option) any later version.
8  *
9  * this program is distributed in the hope that it will be useful, but without
10  * any warranty; without even the implied warranty of merchantability or
11  * fitness for a particular purpose.  see the gnu general public license for
12  * more details.
13  *
14  * you should have received a copy of the gnu general public license along
15  * with this program; if not, write to the free software foundation, inc.,
16  * 51 franklin street, fifth floor, boston, ma  02110-1301, usa.
17  */
18
19 #include <mach/tegra_fuse.h>
20 #include <mach/hardware.h>
21
22 #include "apbio.h"
23 #include "fuse.h"
24 #include "iomap.h"
25
26 #ifndef __TEGRA12x_FUSE_OFFSETS_H
27 #define __TEGRA12x_FUSE_OFFSETS_H
28
29 /* private_key4 */
30 #define DEVKEY_START_OFFSET             0x2A
31 #define DEVKEY_START_BIT                12
32
33 /* arm_debug_dis */
34 #define JTAG_START_OFFSET               0x0
35 #define JTAG_START_BIT                  3
36
37 /* security_mode */
38 #define ODM_PROD_START_OFFSET           0x0
39 #define ODM_PROD_START_BIT              11
40
41 /* boot_device_info */
42 #define SB_DEVCFG_START_OFFSET          0x2C
43 #define SB_DEVCFG_START_BIT             12
44
45 /* reserved_sw[2:0] */
46 #define SB_DEVSEL_START_OFFSET          0x2C
47 #define SB_DEVSEL_START_BIT             28
48
49 /* private_key0 -> private_key3 (SBK) */
50 #define SBK_START_OFFSET                0x22
51 #define SBK_START_BIT                   12
52
53 /* reserved_sw[7:4] */
54 #define SW_RESERVED_START_OFFSET        0x2E
55 #define SW_RESERVED_START_BIT           0
56
57 /* reserved_sw[3] */
58 #define IGNORE_DEVSEL_START_OFFSET      0x2C
59 #define IGNORE_DEVSEL_START_BIT         31
60
61 /* public key */
62 #define PUBLIC_KEY_START_OFFSET         0x0A
63 #define PUBLIC_KEY_START_BIT            30
64
65 /* pkc_disable */
66 #define PKC_DISABLE_START_OFFSET        0x5A
67 #define PKC_DISABLE_START_BIT           9
68
69 /* video vp8 enable */
70 #define VP8_ENABLE_START_OFFSET         0x2E
71 #define VP8_ENABLE_START_BIT            4
72
73 /* odm lock */
74 #define ODM_LOCK_START_OFFSET           0x0
75 #define ODM_LOCK_START_BIT              6
76
77 /* reserved_odm0 -> reserved_odm7 */
78 #define ODM_RESERVED_DEVSEL_START_OFFSET        0x2E
79 #define ODM_RESERVED_START_BIT                  5
80
81 #define FUSE_VENDOR_CODE        0x200
82 #define FUSE_VENDOR_CODE_MASK   0xf
83 #define FUSE_FAB_CODE           0x204
84 #define FUSE_FAB_CODE_MASK      0x3f
85 #define FUSE_LOT_CODE_0         0x208
86 #define FUSE_LOT_CODE_1         0x20c
87 #define FUSE_WAFER_ID           0x210
88 #define FUSE_WAFER_ID_MASK      0x3f
89 #define FUSE_X_COORDINATE       0x214
90 #define FUSE_X_COORDINATE_MASK  0x1ff
91 #define FUSE_Y_COORDINATE       0x218
92 #define FUSE_Y_COORDINATE_MASK  0x1ff
93 #define FUSE_GPU_INFO           0x390
94 #define FUSE_GPU_INFO_MASK      (1<<2)
95 #define FUSE_SPARE_BIT          0x300
96 /* fuse registers used in public fuse data read API */
97 #define FUSE_TEST_PROGRAM_REVISION_0    0x128
98 /* fuse spare bits are used to get Tj-ADT values */
99 #define NUM_TSENSOR_SPARE_BITS  28
100 /* tsensor calibration register */
101 #define FUSE_TSENSOR_CALIB_0    0x198
102 /* sparse realignment register */
103 #define FUSE_SPARE_REALIGNMENT_REG_0 0x2fc
104 /* tsensor8_calib */
105 #define FUSE_TSENSOR_CALIB_8 0x280
106
107 #define FUSE_BASE_CP_SHIFT      0
108 #define FUSE_BASE_CP_MASK       0x3ff
109 #define FUSE_BASE_FT_SHIFT      10
110 #define FUSE_BASE_FT_MASK       0x7ff
111 #define FUSE_SHIFT_CP_SHIFT     0
112 #define FUSE_SHIFT_CP_MASK      0x3f
113 #define FUSE_SHIFT_CP_BITS      6
114 #define FUSE_SHIFT_FT_SHIFT     21
115 #define FUSE_SHIFT_FT_MASK      0x1f
116 #define FUSE_SHIFT_FT_BITS      5
117
118 #define TEGRA_FUSE_SUPPLY       "vpp_fuse"
119
120 int fuse_pgm_cycles[] = {130, 168, 0, 0, 192, 384, 0, 0, 120, 480, 0, 0, 260};
121
122 #define CHK_ERR(x) \
123 { \
124         if (x) { \
125                 pr_err("%s: sysfs_create_file fail(%d)!", __func__, x); \
126                 return x; \
127         } \
128 }
129
130 DEVICE_ATTR(public_key, 0440, tegra_fuse_show, tegra_fuse_store);
131 DEVICE_ATTR(pkc_disable, 0440, tegra_fuse_show, tegra_fuse_store);
132 DEVICE_ATTR(vp8_enable, 0440, tegra_fuse_show, tegra_fuse_store);
133 DEVICE_ATTR(odm_lock, 0440, tegra_fuse_show, tegra_fuse_store);
134
135 int tegra_fuse_get_revision(u32 *rev)
136 {
137         /* fuse revision */
138         *rev = tegra_fuse_readl(FUSE_TEST_PROGRAM_REVISION_0);
139         return 0;
140 }
141
142 int tegra_fuse_get_tsensor_calibration_data(u32 *calib)
143 {
144         /* tsensor calibration fuse */
145         *calib = tegra_fuse_readl(FUSE_TSENSOR_CALIB_0);
146         return 0;
147 }
148
149 int tegra_fuse_get_tsensor_spare_bits(u32 *spare_bits)
150 {
151         u32 value;
152         int i;
153
154         BUG_ON(NUM_TSENSOR_SPARE_BITS > (sizeof(u32) * 8));
155         if (!spare_bits)
156                 return -ENOMEM;
157         *spare_bits = 0;
158         /* spare bits 0-27 */
159         for (i = 0; i < NUM_TSENSOR_SPARE_BITS; i++) {
160                 value = tegra_fuse_readl(FUSE_SPARE_BIT +
161                         (i << 2));
162                 if (value)
163                         *spare_bits |= BIT(i);
164         }
165         return 0;
166 }
167
168 unsigned long long tegra_chip_uid(void)
169 {
170
171         u64 uid = 0ull;
172         u32 reg;
173         u32 cid;
174         u32 vendor;
175         u32 fab;
176         u32 lot;
177         u32 wafer;
178         u32 x;
179         u32 y;
180         u32 i;
181
182         /* This used to be so much easier in prior chips. Unfortunately, there
183            is no one-stop shopping for the unique id anymore. It must be
184            constructed from various bits of information burned into the fuses
185            during the manufacturing process. The 64-bit unique id is formed
186            by concatenating several bit fields. The notation used for the
187            various fields is <fieldname:size_in_bits> with the UID composed
188            thusly:
189
190            <CID:4><VENDOR:4><FAB:6><LOT:26><WAFER:6><X:9><Y:9>
191
192            Where:
193
194                 Field    Bits  Position Data
195                 -------  ----  -------- ----------------------------------------
196                 CID        4     60     Chip id
197                 VENDOR     4     56     Vendor code
198                 FAB        6     50     FAB code
199                 LOT       26     24     Lot code (5-digit base-36-coded-decimal,
200                                         re-encoded to 26 bits binary)
201                 WAFER      6     18     Wafer id
202                 X          9      9     Wafer X-coordinate
203                 Y          9      0     Wafer Y-coordinate
204                 -------  ----
205                 Total     64
206         */
207
208         /* chip id is 3 for tegra 12x */
209         cid = 3;
210
211         vendor = tegra_fuse_readl(FUSE_VENDOR_CODE) & FUSE_VENDOR_CODE_MASK;
212         fab = tegra_fuse_readl(FUSE_FAB_CODE) & FUSE_FAB_CODE_MASK;
213
214         /* Lot code must be re-encoded from a 5 digit base-36 'BCD' number
215            to a binary number. */
216         lot = 0;
217         reg = tegra_fuse_readl(FUSE_LOT_CODE_0) << 2;
218
219         for (i = 0; i < 5; ++i) {
220                 u32 digit = (reg & 0xFC000000) >> 26;
221                 BUG_ON(digit >= 36);
222                 lot *= 36;
223                 lot += digit;
224                 reg <<= 6;
225         }
226
227         wafer = tegra_fuse_readl(FUSE_WAFER_ID) & FUSE_WAFER_ID_MASK;
228         x = tegra_fuse_readl(FUSE_X_COORDINATE) & FUSE_X_COORDINATE_MASK;
229         y = tegra_fuse_readl(FUSE_Y_COORDINATE) & FUSE_Y_COORDINATE_MASK;
230
231         uid = ((unsigned long long)cid  << 60ull)
232             | ((unsigned long long)vendor << 56ull)
233             | ((unsigned long long)fab << 50ull)
234             | ((unsigned long long)lot << 24ull)
235             | ((unsigned long long)wafer << 18ull)
236             | ((unsigned long long)x << 9ull)
237             | ((unsigned long long)y << 0ull);
238         return uid;
239 }
240
241
242
243 static int tsensor_calib_offset[] = {
244         [0] = 0x198,
245         [1] = 0x184,
246         [2] = 0x188,
247         [3] = 0x22c,
248         [4] = 0x254,
249         [5] = 0x258,
250         [6] = 0x25c,
251         [7] = 0x260,
252 };
253
254 int tegra_fuse_get_tsensor_calib(int index, u32 *calib)
255 {
256         if (index < 0 || index > 7)
257                 return -EINVAL;
258         *calib = tegra_fuse_readl(tsensor_calib_offset[index]);
259         return 0;
260 }
261
262
263 int tegra_fuse_calib_base_get_cp(u32 *base_cp, s32 *shifted_cp)
264 {
265         s32 cp;
266         u32 val = tegra_fuse_readl(FUSE_TSENSOR_CALIB_8);
267
268         *base_cp = (((val) &
269                 (FUSE_BASE_CP_MASK << FUSE_BASE_CP_SHIFT))
270                 >> FUSE_BASE_CP_SHIFT);
271
272         if (!(*base_cp)) {
273                 pr_warning("soctherm: WARNING: Improper FUSE_BASE_CP. Using hard coded value (1400).\n");
274                 *base_cp = 1400;
275         }
276
277         val = tegra_fuse_readl(FUSE_SPARE_REALIGNMENT_REG_0);
278         cp = (((val) &
279                 (FUSE_SHIFT_CP_MASK << FUSE_SHIFT_CP_SHIFT))
280                 >> FUSE_SHIFT_CP_SHIFT);
281         *shifted_cp = ((s32)(cp)
282                 << (32 - FUSE_SHIFT_CP_BITS)
283                 >> (32 - FUSE_SHIFT_CP_BITS));
284         return 0;
285 }
286
287 int tegra_fuse_calib_base_get_ft(u32 *base_ft, s32 *shifted_ft)
288 {
289         s32 ft;
290         u32 val = tegra_fuse_readl(FUSE_TSENSOR_CALIB_8);
291
292         *base_ft = (((val) &
293                 (FUSE_BASE_FT_MASK << FUSE_BASE_FT_SHIFT))
294                 >> FUSE_BASE_FT_SHIFT);
295
296         if (!(*base_ft)) {
297                 pr_warning("soctherm: WARNING: Improper FUSE_BASE_FT. Using hard coded value (652).\n");
298                 *base_ft = 652;
299         }
300
301         ft = (((val) &
302                 (FUSE_SHIFT_FT_MASK << FUSE_SHIFT_FT_SHIFT))
303                 >> FUSE_SHIFT_FT_SHIFT);
304         *shifted_ft = ((s32)(ft) <<
305                 (32 - FUSE_SHIFT_FT_BITS) >>
306                 (32 - FUSE_SHIFT_FT_BITS));
307         return 0;
308 }
309
310 int tegra_fuse_add_sysfs_variables(struct platform_device *pdev,
311                                         bool odm_security_mode)
312 {
313         dev_attr_odm_lock.attr.mode = 0640;
314         if (odm_security_mode) {
315                 dev_attr_public_key.attr.mode =  0440;
316                 dev_attr_pkc_disable.attr.mode = 0440;
317                 dev_attr_vp8_enable.attr.mode = 0440;
318         } else {
319                 dev_attr_public_key.attr.mode =  0640;
320                 dev_attr_pkc_disable.attr.mode = 0640;
321                 dev_attr_vp8_enable.attr.mode = 0640;
322         }
323         CHK_ERR(sysfs_create_file(&pdev->dev.kobj, &dev_attr_public_key.attr));
324         CHK_ERR(sysfs_create_file(&pdev->dev.kobj, &dev_attr_pkc_disable.attr));
325         CHK_ERR(sysfs_create_file(&pdev->dev.kobj, &dev_attr_vp8_enable.attr));
326         CHK_ERR(sysfs_create_file(&pdev->dev.kobj, &dev_attr_odm_lock.attr));
327
328         return 0;
329 }
330
331 int tegra_fuse_rm_sysfs_variables(struct platform_device *pdev)
332 {
333         sysfs_remove_file(&pdev->dev.kobj, &dev_attr_public_key.attr);
334         sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pkc_disable.attr);
335         sysfs_remove_file(&pdev->dev.kobj, &dev_attr_vp8_enable.attr);
336         sysfs_remove_file(&pdev->dev.kobj, &dev_attr_odm_lock.attr);
337
338         return 0;
339 }
340
341 int tegra_fuse_ch_sysfs_perm(struct kobject *kobj)
342 {
343         CHK_ERR(sysfs_chmod_file(kobj, &dev_attr_public_key.attr, 0440));
344         CHK_ERR(sysfs_chmod_file(kobj, &dev_attr_pkc_disable.attr, 0440));
345         CHK_ERR(sysfs_chmod_file(kobj, &dev_attr_vp8_enable.attr, 0440));
346
347         return 0;
348 }
349 #endif /* __TEGRA12x_FUSE_OFFSETS_H */