diff options
Diffstat (limited to 'arch/arm/mach-tegra/tegra_odm_fuses.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra_odm_fuses.c | 998 |
1 files changed, 998 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra_odm_fuses.c b/arch/arm/mach-tegra/tegra_odm_fuses.c new file mode 100644 index 00000000000..5dcf24e497b --- /dev/null +++ b/arch/arm/mach-tegra/tegra_odm_fuses.c | |||
@@ -0,0 +1,998 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/tegra_odm_fuses.c | ||
3 | * | ||
4 | * Copyright (c) 2010-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 | /* | ||
22 | * Fuses are one time programmable bits on the chip which are used by | ||
23 | * the chip manufacturer and device manufacturers to store chip/device | ||
24 | * configurations. The fuse bits are encapsulated in a 32 x 64 array. | ||
25 | * If a fuse bit is programmed to 1, it cannot be reverted to 0. Either | ||
26 | * another fuse bit has to be used for the same purpose or a new chip | ||
27 | * needs to be used. | ||
28 | * | ||
29 | * Each and every fuse word has its own shadow word which resides adjacent to | ||
30 | * a particular fuse word. e.g. Fuse words 0-1 form a fuse-shadow pair. | ||
31 | * So in theory we have only 32 fuse words to work with. | ||
32 | * The shadow fuse word is a mirror of the actual fuse word at all times | ||
33 | * and this is maintained while programming a particular fuse. | ||
34 | */ | ||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/io.h> | ||
38 | #include <linux/mutex.h> | ||
39 | #include <linux/err.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/sysfs.h> | ||
43 | #include <linux/kobject.h> | ||
44 | #include <linux/regulator/consumer.h> | ||
45 | #include <linux/ctype.h> | ||
46 | #include <linux/wakelock.h> | ||
47 | #include <linux/clk.h> | ||
48 | |||
49 | #include <mach/tegra_odm_fuses.h> | ||
50 | #include <mach/iomap.h> | ||
51 | |||
52 | #include "fuse.h" | ||
53 | |||
54 | #define NFUSES 64 | ||
55 | #define STATE_IDLE (0x4 << 16) | ||
56 | |||
57 | /* since fuse burning is irreversible, use this for testing */ | ||
58 | #define ENABLE_FUSE_BURNING 1 | ||
59 | |||
60 | /* fuse registers */ | ||
61 | #define FUSE_CTRL 0x000 | ||
62 | #define FUSE_REG_ADDR 0x004 | ||
63 | #define FUSE_REG_READ 0x008 | ||
64 | #define FUSE_REG_WRITE 0x00C | ||
65 | #define FUSE_TIME_PGM 0x01C | ||
66 | #define FUSE_PRIV2INTFC 0x020 | ||
67 | #define FUSE_DIS_PGM 0x02C | ||
68 | #define FUSE_WRITE_ACCESS 0x030 | ||
69 | #define FUSE_PWR_GOOD_SW 0x034 | ||
70 | |||
71 | static struct kobject *fuse_kobj; | ||
72 | |||
73 | static ssize_t fuse_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf); | ||
74 | static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
75 | const char *buf, size_t count); | ||
76 | |||
77 | static struct kobj_attribute devkey_attr = | ||
78 | __ATTR(device_key, 0440, fuse_show, fuse_store); | ||
79 | |||
80 | static struct kobj_attribute jtagdis_attr = | ||
81 | __ATTR(jtag_disable, 0440, fuse_show, fuse_store); | ||
82 | |||
83 | static struct kobj_attribute odm_prod_mode_attr = | ||
84 | __ATTR(odm_production_mode, 0444, fuse_show, fuse_store); | ||
85 | |||
86 | static struct kobj_attribute sec_boot_dev_cfg_attr = | ||
87 | __ATTR(sec_boot_dev_cfg, 0440, fuse_show, fuse_store); | ||
88 | |||
89 | static struct kobj_attribute sec_boot_dev_sel_attr = | ||
90 | __ATTR(sec_boot_dev_sel, 0440, fuse_show, fuse_store); | ||
91 | |||
92 | static struct kobj_attribute sbk_attr = | ||
93 | __ATTR(secure_boot_key, 0440, fuse_show, fuse_store); | ||
94 | |||
95 | static struct kobj_attribute sw_rsvd_attr = | ||
96 | __ATTR(sw_reserved, 0440, fuse_show, fuse_store); | ||
97 | |||
98 | static struct kobj_attribute ignore_dev_sel_straps_attr = | ||
99 | __ATTR(ignore_dev_sel_straps, 0440, fuse_show, fuse_store); | ||
100 | |||
101 | static struct kobj_attribute odm_rsvd_attr = | ||
102 | __ATTR(odm_reserved, 0440, fuse_show, fuse_store); | ||
103 | |||
104 | static u32 fuse_pgm_data[NFUSES / 2]; | ||
105 | static u32 fuse_pgm_mask[NFUSES / 2]; | ||
106 | static u32 tmp_fuse_pgm_data[NFUSES / 2]; | ||
107 | |||
108 | DEFINE_MUTEX(fuse_lock); | ||
109 | |||
110 | static struct fuse_data fuse_info; | ||
111 | struct regulator *vdd_fuse; | ||
112 | struct clk *clk_fuse; | ||
113 | |||
114 | #define FUSE_NAME_LEN 30 | ||
115 | |||
116 | struct param_info { | ||
117 | u32 *addr; | ||
118 | int sz; | ||
119 | u32 start_off; | ||
120 | int start_bit; | ||
121 | int nbits; | ||
122 | int data_offset; | ||
123 | char sysfs_name[FUSE_NAME_LEN]; | ||
124 | }; | ||
125 | |||
126 | #if defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
127 | |||
128 | /* private_key4 */ | ||
129 | #define DEVKEY_START_OFFSET 0x12 | ||
130 | #define DEVKEY_START_BIT 8 | ||
131 | |||
132 | /* arm_debug_dis */ | ||
133 | #define JTAG_START_OFFSET 0x0 | ||
134 | #define JTAG_START_BIT 24 | ||
135 | |||
136 | /* security_mode */ | ||
137 | #define ODM_PROD_START_OFFSET 0x0 | ||
138 | #define ODM_PROD_START_BIT 23 | ||
139 | |||
140 | /* boot_device_info */ | ||
141 | #define SB_DEVCFG_START_OFFSET 0x14 | ||
142 | #define SB_DEVCFG_START_BIT 8 | ||
143 | |||
144 | /* reserved_sw[2:0] */ | ||
145 | #define SB_DEVSEL_START_OFFSET 0x14 | ||
146 | #define SB_DEVSEL_START_BIT 24 | ||
147 | |||
148 | /* private_key0 -> private_key3 */ | ||
149 | #define SBK_START_OFFSET 0x0A | ||
150 | #define SBK_START_BIT 8 | ||
151 | |||
152 | /* reserved_sw[7:4] */ | ||
153 | #define SW_RESERVED_START_OFFSET 0x14 | ||
154 | #define SW_RESERVED_START_BIT 28 | ||
155 | |||
156 | /* reserved_sw[3] */ | ||
157 | #define IGNORE_DEVSEL_START_OFFSET 0x14 | ||
158 | #define IGNORE_DEVSEL_START_BIT 27 | ||
159 | |||
160 | /* reserved_odm0 -> reserved_odm7 */ | ||
161 | #define ODM_RESERVED_DEVSEL_START_OFFSET 0x16 | ||
162 | #define ODM_RESERVED_START_BIT 4 | ||
163 | |||
164 | #elif defined(CONFIG_ARCH_TEGRA_3x_SOC) | ||
165 | |||
166 | /* private_key4 */ | ||
167 | #define DEVKEY_START_OFFSET 0x16 | ||
168 | #define DEVKEY_START_BIT 22 | ||
169 | |||
170 | /* arm_debug_dis */ | ||
171 | #define JTAG_START_OFFSET 0x0 | ||
172 | #define JTAG_START_BIT 24 | ||
173 | |||
174 | /* security_mode */ | ||
175 | #define ODM_PROD_START_OFFSET 0x0 | ||
176 | #define ODM_PROD_START_BIT 23 | ||
177 | |||
178 | /* boot_device_info */ | ||
179 | #define SB_DEVCFG_START_OFFSET 0x18 | ||
180 | #define SB_DEVCFG_START_BIT 22 | ||
181 | |||
182 | /* reserved_sw[2:0] */ | ||
183 | #define SB_DEVSEL_START_OFFSET 0x1A | ||
184 | #define SB_DEVSEL_START_BIT 6 | ||
185 | |||
186 | /* private_key0 -> private_key3 */ | ||
187 | #define SBK_START_OFFSET 0x0E | ||
188 | #define SBK_START_BIT 22 | ||
189 | |||
190 | /* reserved_sw[7:4] */ | ||
191 | #define SW_RESERVED_START_OFFSET 0x1A | ||
192 | #define SW_RESERVED_START_BIT 10 | ||
193 | |||
194 | /* reserved_sw[3] */ | ||
195 | #define IGNORE_DEVSEL_START_OFFSET 0x1A | ||
196 | #define IGNORE_DEVSEL_START_BIT 9 | ||
197 | |||
198 | /* reserved_odm0 -> reserved_odm7 */ | ||
199 | #define ODM_RESERVED_DEVSEL_START_OFFSET 0x1A | ||
200 | #define ODM_RESERVED_START_BIT 14 | ||
201 | |||
202 | #else | ||
203 | |||
204 | #define DEVKEY_START_OFFSET 0x2C | ||
205 | #define DEVKEY_START_BIT 0x07 | ||
206 | |||
207 | #define JTAG_START_OFFSET 0x0 | ||
208 | #define JTAG_START_BIT 0x3 | ||
209 | |||
210 | #define ODM_PROD_START_OFFSET 0x0 | ||
211 | #define ODM_PROD_START_BIT 0x4 | ||
212 | |||
213 | #define SB_DEVCFG_START_OFFSET 0x2E | ||
214 | #define SB_DEVCFG_START_BIT 0x07 | ||
215 | |||
216 | #define SB_DEVSEL_START_OFFSET 0x2E | ||
217 | #define SB_DEVSEL_START_BIT 0x23 | ||
218 | |||
219 | #define SBK_START_OFFSET 0x24 | ||
220 | #define SBK_START_BIT 0x07 | ||
221 | |||
222 | #define SW_RESERVED_START_OFFSET 0x2E | ||
223 | #define SW_RESERVED_START_BIT 0x07 | ||
224 | |||
225 | #define IGNORE_DEVSEL_START_OFFSET 0x2E | ||
226 | #define IGNORE_DEVSEL_START_BIT 0x26 | ||
227 | |||
228 | #define ODM_RESERVED_DEVSEL_START_OFFSET 0X30 | ||
229 | #define ODM_RESERVED_START_BIT 0X0 | ||
230 | |||
231 | #endif | ||
232 | |||
233 | static struct param_info fuse_info_tbl[] = { | ||
234 | [DEVKEY] = { | ||
235 | .addr = &fuse_info.devkey, | ||
236 | .sz = sizeof(fuse_info.devkey), | ||
237 | .start_off = DEVKEY_START_OFFSET, | ||
238 | .start_bit = DEVKEY_START_BIT, | ||
239 | .nbits = 32, | ||
240 | .data_offset = 0, | ||
241 | .sysfs_name = "device_key", | ||
242 | }, | ||
243 | [JTAG_DIS] = { | ||
244 | .addr = &fuse_info.jtag_dis, | ||
245 | .sz = sizeof(fuse_info.jtag_dis), | ||
246 | .start_off = JTAG_START_OFFSET, | ||
247 | .start_bit = JTAG_START_BIT, | ||
248 | .nbits = 1, | ||
249 | .data_offset = 1, | ||
250 | .sysfs_name = "jtag_disable", | ||
251 | }, | ||
252 | [ODM_PROD_MODE] = { | ||
253 | .addr = &fuse_info.odm_prod_mode, | ||
254 | .sz = sizeof(fuse_info.odm_prod_mode), | ||
255 | .start_off = ODM_PROD_START_OFFSET, | ||
256 | .start_bit = ODM_PROD_START_BIT, | ||
257 | .nbits = 1, | ||
258 | .data_offset = 2, | ||
259 | .sysfs_name = "odm_production_mode", | ||
260 | }, | ||
261 | [SEC_BOOT_DEV_CFG] = { | ||
262 | .addr = &fuse_info.bootdev_cfg, | ||
263 | .sz = sizeof(fuse_info.bootdev_cfg), | ||
264 | .start_off = SB_DEVCFG_START_OFFSET, | ||
265 | .start_bit = SB_DEVCFG_START_BIT, | ||
266 | .nbits = 16, | ||
267 | .data_offset = 3, | ||
268 | .sysfs_name = "sec_boot_dev_cfg", | ||
269 | }, | ||
270 | [SEC_BOOT_DEV_SEL] = { | ||
271 | .addr = &fuse_info.bootdev_sel, | ||
272 | .sz = sizeof(fuse_info.bootdev_sel), | ||
273 | .start_off = SB_DEVSEL_START_OFFSET, | ||
274 | .start_bit = SB_DEVSEL_START_BIT, | ||
275 | .nbits = 3, | ||
276 | .data_offset = 4, | ||
277 | .sysfs_name = "sec_boot_dev_sel", | ||
278 | }, | ||
279 | [SBK] = { | ||
280 | .addr = fuse_info.sbk, | ||
281 | .sz = sizeof(fuse_info.sbk), | ||
282 | .start_off = SBK_START_OFFSET, | ||
283 | .start_bit = SBK_START_BIT, | ||
284 | .nbits = 128, | ||
285 | .data_offset = 5, | ||
286 | .sysfs_name = "secure_boot_key", | ||
287 | }, | ||
288 | [SW_RSVD] = { | ||
289 | .addr = &fuse_info.sw_rsvd, | ||
290 | .sz = sizeof(fuse_info.sw_rsvd), | ||
291 | .start_off = SW_RESERVED_START_OFFSET, | ||
292 | .start_bit = SW_RESERVED_START_BIT, | ||
293 | .nbits = 4, | ||
294 | .data_offset = 9, | ||
295 | .sysfs_name = "sw_reserved", | ||
296 | }, | ||
297 | [IGNORE_DEV_SEL_STRAPS] = { | ||
298 | .addr = &fuse_info.ignore_devsel_straps, | ||
299 | .sz = sizeof(fuse_info.ignore_devsel_straps), | ||
300 | .start_off = IGNORE_DEVSEL_START_OFFSET, | ||
301 | .start_bit = IGNORE_DEVSEL_START_BIT, | ||
302 | .nbits = 1, | ||
303 | .data_offset = 10, | ||
304 | .sysfs_name = "ignore_dev_sel_straps", | ||
305 | }, | ||
306 | [ODM_RSVD] = { | ||
307 | .addr = fuse_info.odm_rsvd, | ||
308 | .sz = sizeof(fuse_info.odm_rsvd), | ||
309 | .start_off = ODM_RESERVED_DEVSEL_START_OFFSET, | ||
310 | .start_bit = ODM_RESERVED_START_BIT, | ||
311 | .nbits = 256, | ||
312 | .data_offset = 11, | ||
313 | .sysfs_name = "odm_reserved", | ||
314 | }, | ||
315 | [SBK_DEVKEY_STATUS] = { | ||
316 | .sz = SBK_DEVKEY_STATUS_SZ, | ||
317 | }, | ||
318 | }; | ||
319 | |||
320 | static void wait_for_idle(void) | ||
321 | { | ||
322 | u32 reg; | ||
323 | |||
324 | do { | ||
325 | udelay(1); | ||
326 | reg = tegra_fuse_readl(FUSE_CTRL); | ||
327 | } while ((reg & (0xF << 16)) != STATE_IDLE); | ||
328 | } | ||
329 | |||
330 | #define FUSE_READ 0x1 | ||
331 | #define FUSE_WRITE 0x2 | ||
332 | #define FUSE_SENSE 0x3 | ||
333 | #define FUSE_CMD_MASK 0x3 | ||
334 | |||
335 | static u32 fuse_cmd_read(u32 addr) | ||
336 | { | ||
337 | u32 reg; | ||
338 | |||
339 | wait_for_idle(); | ||
340 | tegra_fuse_writel(addr, FUSE_REG_ADDR); | ||
341 | reg = tegra_fuse_readl(FUSE_CTRL); | ||
342 | reg &= ~FUSE_CMD_MASK; | ||
343 | reg |= FUSE_READ; | ||
344 | tegra_fuse_writel(reg, FUSE_CTRL); | ||
345 | wait_for_idle(); | ||
346 | |||
347 | reg = tegra_fuse_readl(FUSE_REG_READ); | ||
348 | return reg; | ||
349 | } | ||
350 | |||
351 | static void fuse_cmd_write(u32 value, u32 addr) | ||
352 | { | ||
353 | u32 reg; | ||
354 | |||
355 | wait_for_idle(); | ||
356 | tegra_fuse_writel(addr, FUSE_REG_ADDR); | ||
357 | tegra_fuse_writel(value, FUSE_REG_WRITE); | ||
358 | |||
359 | reg = tegra_fuse_readl(FUSE_CTRL); | ||
360 | reg &= ~FUSE_CMD_MASK; | ||
361 | reg |= FUSE_WRITE; | ||
362 | tegra_fuse_writel(reg, FUSE_CTRL); | ||
363 | wait_for_idle(); | ||
364 | } | ||
365 | |||
366 | static void fuse_cmd_sense(void) | ||
367 | { | ||
368 | u32 reg; | ||
369 | |||
370 | wait_for_idle(); | ||
371 | reg = tegra_fuse_readl(FUSE_CTRL); | ||
372 | reg &= ~FUSE_CMD_MASK; | ||
373 | reg |= FUSE_SENSE; | ||
374 | tegra_fuse_writel(reg, FUSE_CTRL); | ||
375 | wait_for_idle(); | ||
376 | } | ||
377 | |||
378 | static void get_fuse(enum fuse_io_param io_param, u32 *out) | ||
379 | { | ||
380 | int start_bit = fuse_info_tbl[io_param].start_bit; | ||
381 | int nbits = fuse_info_tbl[io_param].nbits; | ||
382 | int offset = fuse_info_tbl[io_param].start_off; | ||
383 | u32 *dst = fuse_info_tbl[io_param].addr; | ||
384 | int dst_bit = 0; | ||
385 | int i; | ||
386 | u32 val; | ||
387 | int loops; | ||
388 | |||
389 | if (out) | ||
390 | dst = out; | ||
391 | |||
392 | do { | ||
393 | val = fuse_cmd_read(offset); | ||
394 | loops = min(nbits, 32 - start_bit); | ||
395 | for (i = 0; i < loops; i++) { | ||
396 | if (val & (BIT(start_bit + i))) | ||
397 | *dst |= BIT(dst_bit); | ||
398 | else | ||
399 | *dst &= ~BIT(dst_bit); | ||
400 | dst_bit++; | ||
401 | if (dst_bit == 32) { | ||
402 | dst++; | ||
403 | dst_bit = 0; | ||
404 | } | ||
405 | } | ||
406 | nbits -= loops; | ||
407 | offset += 2; | ||
408 | start_bit = 0; | ||
409 | } while (nbits > 0); | ||
410 | } | ||
411 | |||
412 | int tegra_fuse_read(enum fuse_io_param io_param, u32 *data, int size) | ||
413 | { | ||
414 | int nbits; | ||
415 | u32 sbk[4], devkey = 0; | ||
416 | |||
417 | if (IS_ERR_OR_NULL(clk_fuse)) { | ||
418 | pr_err("fuse read disabled"); | ||
419 | return -ENODEV; | ||
420 | } | ||
421 | |||
422 | if (!data) | ||
423 | return -EINVAL; | ||
424 | |||
425 | if (size != fuse_info_tbl[io_param].sz) { | ||
426 | pr_err("%s: size mismatch(%d), %d vs %d\n", __func__, | ||
427 | (int)io_param, size, fuse_info_tbl[io_param].sz); | ||
428 | return -EINVAL; | ||
429 | } | ||
430 | |||
431 | mutex_lock(&fuse_lock); | ||
432 | |||
433 | clk_enable(clk_fuse); | ||
434 | fuse_cmd_sense(); | ||
435 | |||
436 | if (io_param == SBK_DEVKEY_STATUS) { | ||
437 | *data = 0; | ||
438 | |||
439 | get_fuse(SBK, sbk); | ||
440 | get_fuse(DEVKEY, &devkey); | ||
441 | nbits = sizeof(sbk) * BITS_PER_BYTE; | ||
442 | if (find_first_bit((unsigned long *)sbk, nbits) != nbits) | ||
443 | *data = 1; | ||
444 | else if (devkey) | ||
445 | *data = 1; | ||
446 | } else { | ||
447 | get_fuse(io_param, data); | ||
448 | } | ||
449 | |||
450 | clk_disable(clk_fuse); | ||
451 | mutex_unlock(&fuse_lock); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static bool fuse_odm_prod_mode(void) | ||
457 | { | ||
458 | u32 odm_prod_mode = 0; | ||
459 | |||
460 | clk_enable(clk_fuse); | ||
461 | get_fuse(ODM_PROD_MODE, &odm_prod_mode); | ||
462 | clk_disable(clk_fuse); | ||
463 | return (odm_prod_mode ? true : false); | ||
464 | } | ||
465 | |||
466 | static void set_fuse(enum fuse_io_param io_param, u32 *data) | ||
467 | { | ||
468 | int i, start_bit = fuse_info_tbl[io_param].start_bit; | ||
469 | int nbits = fuse_info_tbl[io_param].nbits, loops; | ||
470 | int offset = fuse_info_tbl[io_param].start_off >> 1; | ||
471 | int src_bit = 0; | ||
472 | u32 val; | ||
473 | |||
474 | do { | ||
475 | val = *data; | ||
476 | loops = min(nbits, 32 - start_bit); | ||
477 | for (i = 0; i < loops; i++) { | ||
478 | fuse_pgm_mask[offset] |= BIT(start_bit + i); | ||
479 | if (val & BIT(src_bit)) | ||
480 | fuse_pgm_data[offset] |= BIT(start_bit + i); | ||
481 | else | ||
482 | fuse_pgm_data[offset] &= ~BIT(start_bit + i); | ||
483 | src_bit++; | ||
484 | if (src_bit == 32) { | ||
485 | data++; | ||
486 | val = *data; | ||
487 | src_bit = 0; | ||
488 | } | ||
489 | } | ||
490 | nbits -= loops; | ||
491 | offset++; | ||
492 | start_bit = 0; | ||
493 | } while (nbits > 0); | ||
494 | } | ||
495 | |||
496 | static void populate_fuse_arrs(struct fuse_data *info, u32 flags) | ||
497 | { | ||
498 | u32 *src = (u32 *)info; | ||
499 | int i; | ||
500 | |||
501 | memset(fuse_pgm_data, 0, sizeof(fuse_pgm_data)); | ||
502 | memset(fuse_pgm_mask, 0, sizeof(fuse_pgm_mask)); | ||
503 | |||
504 | if ((flags & FLAGS_ODMRSVD)) { | ||
505 | set_fuse(ODM_RSVD, info->odm_rsvd); | ||
506 | flags &= ~FLAGS_ODMRSVD; | ||
507 | } | ||
508 | |||
509 | /* do not burn any more if secure mode is set */ | ||
510 | if (fuse_odm_prod_mode()) | ||
511 | goto out; | ||
512 | |||
513 | for_each_set_bit(i, (unsigned long *)&flags, MAX_PARAMS) | ||
514 | set_fuse(i, src + fuse_info_tbl[i].data_offset); | ||
515 | |||
516 | out: | ||
517 | pr_debug("ready to program"); | ||
518 | } | ||
519 | |||
520 | static void fuse_power_enable(void) | ||
521 | { | ||
522 | #if ENABLE_FUSE_BURNING | ||
523 | tegra_fuse_writel(0x1, FUSE_PWR_GOOD_SW); | ||
524 | udelay(1); | ||
525 | #endif | ||
526 | } | ||
527 | |||
528 | static void fuse_power_disable(void) | ||
529 | { | ||
530 | #if ENABLE_FUSE_BURNING | ||
531 | tegra_fuse_writel(0, FUSE_PWR_GOOD_SW); | ||
532 | udelay(1); | ||
533 | #endif | ||
534 | } | ||
535 | |||
536 | static void fuse_program_array(int pgm_cycles) | ||
537 | { | ||
538 | u32 reg, fuse_val[2]; | ||
539 | u32 *data = tmp_fuse_pgm_data, addr = 0, *mask = fuse_pgm_mask; | ||
540 | int i = 0; | ||
541 | |||
542 | fuse_cmd_sense(); | ||
543 | |||
544 | /* get the first 2 fuse bytes */ | ||
545 | fuse_val[0] = fuse_cmd_read(0); | ||
546 | fuse_val[1] = fuse_cmd_read(1); | ||
547 | |||
548 | fuse_power_enable(); | ||
549 | |||
550 | /* | ||
551 | * The fuse macro is a high density macro. Fuses are | ||
552 | * burned using an addressing mechanism, so no need to prepare | ||
553 | * the full list, but more write to control registers are needed. | ||
554 | * The only bit that can be written at first is bit 0, a special write | ||
555 | * protection bit by assumptions all other bits are at 0 | ||
556 | * | ||
557 | * The programming pulse must have a precise width of | ||
558 | * [9000, 11000] ns. | ||
559 | */ | ||
560 | if (pgm_cycles > 0) { | ||
561 | reg = pgm_cycles; | ||
562 | tegra_fuse_writel(reg, FUSE_TIME_PGM); | ||
563 | } | ||
564 | fuse_val[0] = (0x1 & ~fuse_val[0]); | ||
565 | fuse_val[1] = (0x1 & ~fuse_val[1]); | ||
566 | fuse_cmd_write(fuse_val[0], 0); | ||
567 | fuse_cmd_write(fuse_val[1], 1); | ||
568 | |||
569 | fuse_power_disable(); | ||
570 | |||
571 | /* | ||
572 | * this will allow programming of other fuses | ||
573 | * and the reading of the existing fuse values | ||
574 | */ | ||
575 | fuse_cmd_sense(); | ||
576 | |||
577 | /* Clear out all bits that have already been burned or masked out */ | ||
578 | memcpy(data, fuse_pgm_data, sizeof(fuse_pgm_data)); | ||
579 | |||
580 | for (addr = 0; addr < NFUSES; addr += 2, data++, mask++) { | ||
581 | reg = fuse_cmd_read(addr); | ||
582 | pr_debug("%d: 0x%x 0x%x 0x%x\n", addr, (u32)(*data), | ||
583 | ~reg, (u32)(*mask)); | ||
584 | *data = (*data & ~reg) & *mask; | ||
585 | } | ||
586 | |||
587 | fuse_power_enable(); | ||
588 | |||
589 | /* | ||
590 | * Finally loop on all fuses, program the non zero ones. | ||
591 | * Words 0 and 1 are written last and they contain control fuses. We | ||
592 | * need to invalidate after writing to a control word (with the exception | ||
593 | * of the master enable). This is also the reason we write them last. | ||
594 | */ | ||
595 | for (i = ARRAY_SIZE(fuse_pgm_data) - 1; i >= 0; i--) { | ||
596 | if (tmp_fuse_pgm_data[i]) { | ||
597 | fuse_cmd_write(tmp_fuse_pgm_data[i], i * 2); | ||
598 | fuse_cmd_write(tmp_fuse_pgm_data[i], (i * 2) + 1); | ||
599 | } | ||
600 | |||
601 | if (i < 2) { | ||
602 | wait_for_idle(); | ||
603 | fuse_power_disable(); | ||
604 | fuse_cmd_sense(); | ||
605 | fuse_power_enable(); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | fuse_power_disable(); | ||
610 | } | ||
611 | |||
612 | static int fuse_set(enum fuse_io_param io_param, u32 *param, int size) | ||
613 | { | ||
614 | int i, nwords = size / sizeof(u32); | ||
615 | u32 *data; | ||
616 | |||
617 | if (io_param > MAX_PARAMS) | ||
618 | return -EINVAL; | ||
619 | |||
620 | data = (u32*)kzalloc(size, GFP_KERNEL); | ||
621 | if (!data) { | ||
622 | pr_err("failed to alloc %d bytes\n", size); | ||
623 | return -ENOMEM; | ||
624 | } | ||
625 | |||
626 | get_fuse(io_param, data); | ||
627 | |||
628 | /* set only new fuse bits */ | ||
629 | for (i = 0; i < nwords; i++) { | ||
630 | param[i] = (~data[i] & param[i]); | ||
631 | } | ||
632 | |||
633 | kfree(data); | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /* | ||
638 | * Function pointer to optional board specific function | ||
639 | */ | ||
640 | int (*tegra_fuse_regulator_en)(int); | ||
641 | EXPORT_SYMBOL(tegra_fuse_regulator_en); | ||
642 | |||
643 | #define CAR_OSC_CTRL 0x50 | ||
644 | #define PMC_PLLP_OVERRIDE 0xF8 | ||
645 | #define PMC_OSC_OVERRIDE BIT(0) | ||
646 | #define PMC_OSC_FREQ_MASK (BIT(2) | BIT(3)) | ||
647 | #define PMC_OSC_FREQ_SHIFT 2 | ||
648 | #define CAR_OSC_FREQ_SHIFT 30 | ||
649 | |||
650 | #define FUSE_SENSE_DONE_BIT BIT(30) | ||
651 | #define START_DATA BIT(0) | ||
652 | #define SKIP_RAMREPAIR BIT(1) | ||
653 | #define FUSE_PGM_TIMEOUT_MS 50 | ||
654 | |||
655 | #if defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
656 | /* cycles corresponding to 13MHz, 19.2MHz, 12MHz, 26MHz */ | ||
657 | static int fuse_pgm_cycles[] = {130, 192, 120, 260}; | ||
658 | #else | ||
659 | /* cycles corresponding to 13MHz, 16.8MHz, 19.2MHz, 38.4MHz, 12MHz, 48MHz, 26MHz */ | ||
660 | static int fuse_pgm_cycles[] = {130, 168, 0, 0, 192, 384, 0, 0, 120, 480, 0, 0, 260}; | ||
661 | #endif | ||
662 | |||
663 | int tegra_fuse_program(struct fuse_data *pgm_data, u32 flags) | ||
664 | { | ||
665 | u32 reg; | ||
666 | int i = 0; | ||
667 | int index; | ||
668 | int ret; | ||
669 | int delay = FUSE_PGM_TIMEOUT_MS; | ||
670 | |||
671 | if (!pgm_data || !flags) { | ||
672 | pr_err("invalid parameter"); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | |||
676 | if (IS_ERR_OR_NULL(clk_fuse) || | ||
677 | (!tegra_fuse_regulator_en && IS_ERR_OR_NULL(vdd_fuse))) { | ||
678 | pr_err("fuse write disabled"); | ||
679 | return -ENODEV; | ||
680 | } | ||
681 | |||
682 | if (fuse_odm_prod_mode() && (flags != FLAGS_ODMRSVD)) { | ||
683 | pr_err("reserved odm fuses aren't allowed in secure mode"); | ||
684 | return -EPERM; | ||
685 | } | ||
686 | |||
687 | if ((flags & FLAGS_ODM_PROD_MODE) && | ||
688 | (flags & (FLAGS_SBK | FLAGS_DEVKEY))) { | ||
689 | pr_err("odm production mode and sbk/devkey not allowed"); | ||
690 | return -EPERM; | ||
691 | } | ||
692 | |||
693 | clk_enable(clk_fuse); | ||
694 | |||
695 | /* check that fuse options write access hasn't been disabled */ | ||
696 | mutex_lock(&fuse_lock); | ||
697 | reg = tegra_fuse_readl(FUSE_DIS_PGM); | ||
698 | mutex_unlock(&fuse_lock); | ||
699 | if (reg) { | ||
700 | pr_err("fuse programming disabled"); | ||
701 | clk_disable(clk_fuse); | ||
702 | return -EACCES; | ||
703 | } | ||
704 | |||
705 | /* enable software writes to the fuse registers */ | ||
706 | tegra_fuse_writel(0, FUSE_WRITE_ACCESS); | ||
707 | |||
708 | mutex_lock(&fuse_lock); | ||
709 | memcpy(&fuse_info, pgm_data, sizeof(fuse_info)); | ||
710 | for_each_set_bit(i, (unsigned long *)&flags, MAX_PARAMS) { | ||
711 | fuse_set((u32)i, fuse_info_tbl[i].addr, | ||
712 | fuse_info_tbl[i].sz); | ||
713 | } | ||
714 | |||
715 | #if ENABLE_FUSE_BURNING | ||
716 | if (tegra_fuse_regulator_en) | ||
717 | ret = tegra_fuse_regulator_en(1); | ||
718 | else | ||
719 | ret = regulator_enable(vdd_fuse); | ||
720 | |||
721 | if (ret) | ||
722 | BUG_ON("regulator enable fail\n"); | ||
723 | |||
724 | populate_fuse_arrs(&fuse_info, flags); | ||
725 | |||
726 | /* calculate the number of program cycles from the oscillator freq */ | ||
727 | reg = readl(IO_ADDRESS(TEGRA_PMC_BASE) + PMC_PLLP_OVERRIDE); | ||
728 | if (reg & PMC_OSC_OVERRIDE) { | ||
729 | index = (reg & PMC_OSC_FREQ_MASK) >> PMC_OSC_FREQ_SHIFT; | ||
730 | } else { | ||
731 | reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + CAR_OSC_CTRL); | ||
732 | index = reg >> CAR_OSC_FREQ_SHIFT; | ||
733 | } | ||
734 | |||
735 | pr_debug("%s: use %d programming cycles\n", __func__, fuse_pgm_cycles[index]); | ||
736 | fuse_program_array(fuse_pgm_cycles[index]); | ||
737 | |||
738 | memset(&fuse_info, 0, sizeof(fuse_info)); | ||
739 | |||
740 | if (tegra_fuse_regulator_en) | ||
741 | tegra_fuse_regulator_en(0); | ||
742 | else | ||
743 | regulator_disable(vdd_fuse); | ||
744 | #endif | ||
745 | |||
746 | mutex_unlock(&fuse_lock); | ||
747 | |||
748 | /* disable software writes to the fuse registers */ | ||
749 | tegra_fuse_writel(1, FUSE_WRITE_ACCESS); | ||
750 | |||
751 | /* apply the fuse values immediately instead of resetting the chip */ | ||
752 | fuse_cmd_sense(); | ||
753 | |||
754 | tegra_fuse_writel(START_DATA | SKIP_RAMREPAIR, FUSE_PRIV2INTFC); | ||
755 | |||
756 | /* check sense and shift done in addition to IDLE */ | ||
757 | do { | ||
758 | mdelay(1); | ||
759 | reg = tegra_fuse_readl(FUSE_CTRL); | ||
760 | reg &= (FUSE_SENSE_DONE_BIT | STATE_IDLE); | ||
761 | } while ((reg != (FUSE_SENSE_DONE_BIT | STATE_IDLE)) && (--delay > 0)); | ||
762 | |||
763 | clk_disable(clk_fuse); | ||
764 | |||
765 | return ((delay > 0) ? 0 : -ETIMEDOUT); | ||
766 | } | ||
767 | |||
768 | static int fuse_name_to_param(const char *str) | ||
769 | { | ||
770 | int i; | ||
771 | |||
772 | for (i = DEVKEY; i < ARRAY_SIZE(fuse_info_tbl); i++) { | ||
773 | if (!strcmp(str, fuse_info_tbl[i].sysfs_name)) | ||
774 | return i; | ||
775 | } | ||
776 | |||
777 | return -ENODATA; | ||
778 | } | ||
779 | |||
780 | static int char_to_xdigit(char c) | ||
781 | { | ||
782 | return (c>='0' && c<='9') ? c - '0' : | ||
783 | (c>='a' && c<='f') ? c - 'a' + 10 : | ||
784 | (c>='A' && c<='F') ? c - 'A' + 10 : -1; | ||
785 | } | ||
786 | |||
787 | #define CHK_ERR(x) \ | ||
788 | { \ | ||
789 | if (x) \ | ||
790 | { \ | ||
791 | pr_err("%s: sysfs_create_file fail(%d)!", __func__, x); \ | ||
792 | return x; \ | ||
793 | } \ | ||
794 | } | ||
795 | |||
796 | static ssize_t fuse_store(struct kobject *kobj, struct kobj_attribute *attr, | ||
797 | const char *buf, size_t count) | ||
798 | { | ||
799 | enum fuse_io_param param = fuse_name_to_param(attr->attr.name); | ||
800 | int ret, i = 0; | ||
801 | int orig_count = count; | ||
802 | struct fuse_data data = {0}; | ||
803 | u32 *raw_data = ((u32 *)&data) + fuse_info_tbl[param].data_offset; | ||
804 | u8 *raw_byte_data = (u8 *)raw_data; | ||
805 | struct wake_lock fuse_wk_lock; | ||
806 | |||
807 | if ((param == -1) || (param == -ENODATA)) { | ||
808 | pr_err("%s: invalid fuse\n", __func__); | ||
809 | return -EINVAL; | ||
810 | } | ||
811 | |||
812 | if (fuse_odm_prod_mode()) { | ||
813 | pr_err("%s: device locked. odm fuse already blown\n", __func__); | ||
814 | return -EPERM; | ||
815 | } | ||
816 | |||
817 | count--; | ||
818 | if (DIV_ROUND_UP(count, 2) > fuse_info_tbl[param].sz) { | ||
819 | pr_err("%s: fuse parameter too long, should be %d character(s)\n", | ||
820 | __func__, fuse_info_tbl[param].sz * 2); | ||
821 | return -EINVAL; | ||
822 | } | ||
823 | |||
824 | /* see if the string has 0x/x at the start */ | ||
825 | if (*buf == 'x') { | ||
826 | count -= 1; | ||
827 | buf++; | ||
828 | } else if (*(buf + 1) == 'x') { | ||
829 | count -= 2; | ||
830 | buf += 2; | ||
831 | } | ||
832 | |||
833 | /* wakelock to avoid device powering down while programming */ | ||
834 | wake_lock_init(&fuse_wk_lock, WAKE_LOCK_SUSPEND, "fuse_wk_lock"); | ||
835 | wake_lock(&fuse_wk_lock); | ||
836 | |||
837 | /* we need to fit each character into a single nibble */ | ||
838 | raw_byte_data += DIV_ROUND_UP(count, 2) - 1; | ||
839 | |||
840 | /* in case of odd number of writes, write the first one here */ | ||
841 | if (count & BIT(0)) { | ||
842 | *raw_byte_data = char_to_xdigit(*buf); | ||
843 | buf++; | ||
844 | raw_byte_data--; | ||
845 | count--; | ||
846 | } | ||
847 | |||
848 | for (i = 1; i <= count; i++, buf++) { | ||
849 | if (i & BIT(0)) { | ||
850 | *raw_byte_data = char_to_xdigit(*buf); | ||
851 | } else { | ||
852 | *raw_byte_data <<= 4; | ||
853 | *raw_byte_data |= char_to_xdigit(*buf); | ||
854 | raw_byte_data--; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | ret = tegra_fuse_program(&data, BIT(param)); | ||
859 | if (ret) { | ||
860 | pr_err("%s: fuse program fail(%d)\n", __func__, ret); | ||
861 | orig_count = ret; | ||
862 | goto done; | ||
863 | } | ||
864 | |||
865 | /* if odm prodn mode fuse is burnt, change file permissions to 0440 */ | ||
866 | if (param == ODM_PROD_MODE) { | ||
867 | CHK_ERR(sysfs_chmod_file(kobj, &attr->attr, 0440)); | ||
868 | CHK_ERR(sysfs_chmod_file(kobj, &devkey_attr.attr, 0440)); | ||
869 | CHK_ERR(sysfs_chmod_file(kobj, &jtagdis_attr.attr, 0440)); | ||
870 | CHK_ERR(sysfs_chmod_file(kobj, &sec_boot_dev_cfg_attr.attr, 0440)); | ||
871 | CHK_ERR(sysfs_chmod_file(kobj, &sec_boot_dev_sel_attr.attr, 0440)); | ||
872 | CHK_ERR(sysfs_chmod_file(kobj, &sbk_attr.attr, 0440)); | ||
873 | CHK_ERR(sysfs_chmod_file(kobj, &sw_rsvd_attr.attr, 0440)); | ||
874 | CHK_ERR(sysfs_chmod_file(kobj, &ignore_dev_sel_straps_attr.attr, 0440)); | ||
875 | CHK_ERR(sysfs_chmod_file(kobj, &odm_rsvd_attr.attr, 0440)); | ||
876 | } | ||
877 | |||
878 | done: | ||
879 | wake_unlock(&fuse_wk_lock); | ||
880 | wake_lock_destroy(&fuse_wk_lock); | ||
881 | return orig_count; | ||
882 | } | ||
883 | |||
884 | static ssize_t fuse_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) | ||
885 | { | ||
886 | enum fuse_io_param param = fuse_name_to_param(attr->attr.name); | ||
887 | u32 data[8]; | ||
888 | char str[8]; | ||
889 | int ret, i; | ||
890 | |||
891 | if ((param == -1) || (param == -ENODATA)) { | ||
892 | pr_err("%s: invalid fuse\n", __func__); | ||
893 | return -EINVAL; | ||
894 | } | ||
895 | |||
896 | if ((param == SBK) && fuse_odm_prod_mode()) { | ||
897 | pr_err("device locked. sbk read not allowed\n"); | ||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | memset(data, 0, sizeof(data)); | ||
902 | ret = tegra_fuse_read(param, data, fuse_info_tbl[param].sz); | ||
903 | if (ret) { | ||
904 | pr_err("%s: read fail(%d)\n", __func__, ret); | ||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | strcpy(buf, "0x"); | ||
909 | for (i = (fuse_info_tbl[param].sz/sizeof(u32)) - 1; i >= 0 ; i--) { | ||
910 | sprintf(str, "%08x", data[i]); | ||
911 | strcat(buf, str); | ||
912 | } | ||
913 | |||
914 | strcat(buf, "\n"); | ||
915 | return strlen(buf); | ||
916 | } | ||
917 | |||
918 | static int __init tegra_fuse_program_init(void) | ||
919 | { | ||
920 | if (!tegra_fuse_regulator_en) { | ||
921 | /* get vdd_fuse regulator */ | ||
922 | vdd_fuse = regulator_get(NULL, "vdd_fuse"); | ||
923 | if (IS_ERR_OR_NULL(vdd_fuse)) | ||
924 | pr_err("%s: no vdd_fuse. fuse write disabled\n", __func__); | ||
925 | } | ||
926 | |||
927 | clk_fuse = clk_get_sys("fuse-tegra", "fuse_burn"); | ||
928 | if (IS_ERR_OR_NULL(clk_fuse)) { | ||
929 | pr_err("%s: no clk_fuse. fuse read/write disabled\n", __func__); | ||
930 | if (!IS_ERR_OR_NULL(vdd_fuse)) { | ||
931 | regulator_put(vdd_fuse); | ||
932 | vdd_fuse = NULL; | ||
933 | } | ||
934 | return -ENODEV; | ||
935 | } | ||
936 | |||
937 | fuse_kobj = kobject_create_and_add("fuse", firmware_kobj); | ||
938 | if (!fuse_kobj) { | ||
939 | pr_err("%s: fuse_kobj create fail\n", __func__); | ||
940 | regulator_put(vdd_fuse); | ||
941 | clk_put(clk_fuse); | ||
942 | return -ENODEV; | ||
943 | } | ||
944 | |||
945 | mutex_init(&fuse_lock); | ||
946 | |||
947 | /* change fuse file permissions, if ODM production fuse is not blown */ | ||
948 | if (!fuse_odm_prod_mode()) | ||
949 | { | ||
950 | devkey_attr.attr.mode = 0640; | ||
951 | jtagdis_attr.attr.mode = 0640; | ||
952 | sec_boot_dev_cfg_attr.attr.mode = 0640; | ||
953 | sec_boot_dev_sel_attr.attr.mode = 0640; | ||
954 | sbk_attr.attr.mode = 0640; | ||
955 | sw_rsvd_attr.attr.mode = 0640; | ||
956 | ignore_dev_sel_straps_attr.attr.mode = 0640; | ||
957 | odm_rsvd_attr.attr.mode = 0640; | ||
958 | odm_prod_mode_attr.attr.mode = 0644; | ||
959 | } | ||
960 | |||
961 | CHK_ERR(sysfs_create_file(fuse_kobj, &odm_prod_mode_attr.attr)); | ||
962 | CHK_ERR(sysfs_create_file(fuse_kobj, &devkey_attr.attr)); | ||
963 | CHK_ERR(sysfs_create_file(fuse_kobj, &jtagdis_attr.attr)); | ||
964 | CHK_ERR(sysfs_create_file(fuse_kobj, &sec_boot_dev_cfg_attr.attr)); | ||
965 | CHK_ERR(sysfs_create_file(fuse_kobj, &sec_boot_dev_sel_attr.attr)); | ||
966 | CHK_ERR(sysfs_create_file(fuse_kobj, &sbk_attr.attr)); | ||
967 | CHK_ERR(sysfs_create_file(fuse_kobj, &sw_rsvd_attr.attr)); | ||
968 | CHK_ERR(sysfs_create_file(fuse_kobj, &ignore_dev_sel_straps_attr.attr)); | ||
969 | CHK_ERR(sysfs_create_file(fuse_kobj, &odm_rsvd_attr.attr)); | ||
970 | |||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static void __exit tegra_fuse_program_exit(void) | ||
975 | { | ||
976 | |||
977 | fuse_power_disable(); | ||
978 | |||
979 | if (!IS_ERR_OR_NULL(vdd_fuse)) | ||
980 | regulator_put(vdd_fuse); | ||
981 | |||
982 | if (!IS_ERR_OR_NULL(clk_fuse)) | ||
983 | clk_put(clk_fuse); | ||
984 | |||
985 | sysfs_remove_file(fuse_kobj, &odm_prod_mode_attr.attr); | ||
986 | sysfs_remove_file(fuse_kobj, &devkey_attr.attr); | ||
987 | sysfs_remove_file(fuse_kobj, &jtagdis_attr.attr); | ||
988 | sysfs_remove_file(fuse_kobj, &sec_boot_dev_cfg_attr.attr); | ||
989 | sysfs_remove_file(fuse_kobj, &sec_boot_dev_sel_attr.attr); | ||
990 | sysfs_remove_file(fuse_kobj, &sbk_attr.attr); | ||
991 | sysfs_remove_file(fuse_kobj, &sw_rsvd_attr.attr); | ||
992 | sysfs_remove_file(fuse_kobj, &ignore_dev_sel_straps_attr.attr); | ||
993 | sysfs_remove_file(fuse_kobj, &odm_rsvd_attr.attr); | ||
994 | kobject_del(fuse_kobj); | ||
995 | } | ||
996 | |||
997 | late_initcall(tegra_fuse_program_init); | ||
998 | module_exit(tegra_fuse_program_exit); | ||