diff options
Diffstat (limited to 'arch/arm/mach-tegra/fuse.c')
-rw-r--r-- | arch/arm/mach-tegra/fuse.c | 107 |
1 files changed, 74 insertions, 33 deletions
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index 1fa26d9a1a68..17fdd4086e6f 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c | |||
@@ -23,20 +23,70 @@ | |||
23 | #include <mach/iomap.h> | 23 | #include <mach/iomap.h> |
24 | 24 | ||
25 | #include "fuse.h" | 25 | #include "fuse.h" |
26 | #include "apbio.h" | ||
26 | 27 | ||
27 | #define FUSE_UID_LOW 0x108 | 28 | #define FUSE_UID_LOW 0x108 |
28 | #define FUSE_UID_HIGH 0x10c | 29 | #define FUSE_UID_HIGH 0x10c |
29 | #define FUSE_SKU_INFO 0x110 | 30 | #define FUSE_SKU_INFO 0x110 |
30 | #define FUSE_SPARE_BIT 0x200 | 31 | #define FUSE_SPARE_BIT 0x200 |
31 | 32 | ||
32 | static inline u32 fuse_readl(unsigned long offset) | 33 | int tegra_sku_id; |
34 | int tegra_cpu_process_id; | ||
35 | int tegra_core_process_id; | ||
36 | enum tegra_revision tegra_revision; | ||
37 | |||
38 | /* The BCT to use at boot is specified by board straps that can be read | ||
39 | * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs. | ||
40 | */ | ||
41 | int tegra_bct_strapping; | ||
42 | |||
43 | #define STRAP_OPT 0x008 | ||
44 | #define GMI_AD0 (1 << 4) | ||
45 | #define GMI_AD1 (1 << 5) | ||
46 | #define RAM_ID_MASK (GMI_AD0 | GMI_AD1) | ||
47 | #define RAM_CODE_SHIFT 4 | ||
48 | |||
49 | static const char *tegra_revision_name[TEGRA_REVISION_MAX] = { | ||
50 | [TEGRA_REVISION_UNKNOWN] = "unknown", | ||
51 | [TEGRA_REVISION_A01] = "A01", | ||
52 | [TEGRA_REVISION_A02] = "A02", | ||
53 | [TEGRA_REVISION_A03] = "A03", | ||
54 | [TEGRA_REVISION_A03p] = "A03 prime", | ||
55 | [TEGRA_REVISION_A04] = "A04", | ||
56 | }; | ||
57 | |||
58 | static inline u32 tegra_fuse_readl(unsigned long offset) | ||
59 | { | ||
60 | return tegra_apb_readl(TEGRA_FUSE_BASE + offset); | ||
61 | } | ||
62 | |||
63 | static inline bool get_spare_fuse(int bit) | ||
33 | { | 64 | { |
34 | return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); | 65 | return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4); |
35 | } | 66 | } |
36 | 67 | ||
37 | static inline void fuse_writel(u32 value, unsigned long offset) | 68 | static enum tegra_revision tegra_get_revision(void) |
38 | { | 69 | { |
39 | writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); | 70 | void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804; |
71 | u32 id = readl(chip_id); | ||
72 | u32 minor_rev = (id >> 16) & 0xf; | ||
73 | u32 chipid = (id >> 8) & 0xff; | ||
74 | |||
75 | switch (minor_rev) { | ||
76 | case 1: | ||
77 | return TEGRA_REVISION_A01; | ||
78 | case 2: | ||
79 | return TEGRA_REVISION_A02; | ||
80 | case 3: | ||
81 | if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19))) | ||
82 | return TEGRA_REVISION_A03p; | ||
83 | else | ||
84 | return TEGRA_REVISION_A03; | ||
85 | case 4: | ||
86 | return TEGRA_REVISION_A04; | ||
87 | default: | ||
88 | return TEGRA_REVISION_UNKNOWN; | ||
89 | } | ||
40 | } | 90 | } |
41 | 91 | ||
42 | void tegra_init_fuse(void) | 92 | void tegra_init_fuse(void) |
@@ -45,40 +95,31 @@ void tegra_init_fuse(void) | |||
45 | reg |= 1 << 28; | 95 | reg |= 1 << 28; |
46 | writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); | 96 | writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); |
47 | 97 | ||
48 | pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", | 98 | reg = tegra_fuse_readl(FUSE_SKU_INFO); |
49 | tegra_sku_id(), tegra_cpu_process_id(), | 99 | tegra_sku_id = reg & 0xFF; |
50 | tegra_core_process_id()); | ||
51 | } | ||
52 | 100 | ||
53 | unsigned long long tegra_chip_uid(void) | 101 | reg = tegra_fuse_readl(FUSE_SPARE_BIT); |
54 | { | 102 | tegra_cpu_process_id = (reg >> 6) & 3; |
55 | unsigned long long lo, hi; | ||
56 | 103 | ||
57 | lo = fuse_readl(FUSE_UID_LOW); | 104 | reg = tegra_fuse_readl(FUSE_SPARE_BIT); |
58 | hi = fuse_readl(FUSE_UID_HIGH); | 105 | tegra_core_process_id = (reg >> 12) & 3; |
59 | return (hi << 32ull) | lo; | ||
60 | } | ||
61 | 106 | ||
62 | int tegra_sku_id(void) | 107 | reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT); |
63 | { | 108 | tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; |
64 | int sku_id; | ||
65 | u32 reg = fuse_readl(FUSE_SKU_INFO); | ||
66 | sku_id = reg & 0xFF; | ||
67 | return sku_id; | ||
68 | } | ||
69 | 109 | ||
70 | int tegra_cpu_process_id(void) | 110 | tegra_revision = tegra_get_revision(); |
71 | { | 111 | |
72 | int cpu_process_id; | 112 | pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", |
73 | u32 reg = fuse_readl(FUSE_SPARE_BIT); | 113 | tegra_revision_name[tegra_get_revision()], |
74 | cpu_process_id = (reg >> 6) & 3; | 114 | tegra_sku_id, tegra_cpu_process_id, |
75 | return cpu_process_id; | 115 | tegra_core_process_id); |
76 | } | 116 | } |
77 | 117 | ||
78 | int tegra_core_process_id(void) | 118 | unsigned long long tegra_chip_uid(void) |
79 | { | 119 | { |
80 | int core_process_id; | 120 | unsigned long long lo, hi; |
81 | u32 reg = fuse_readl(FUSE_SPARE_BIT); | 121 | |
82 | core_process_id = (reg >> 12) & 3; | 122 | lo = tegra_fuse_readl(FUSE_UID_LOW); |
83 | return core_process_id; | 123 | hi = tegra_fuse_readl(FUSE_UID_HIGH); |
124 | return (hi << 32ull) | lo; | ||
84 | } | 125 | } |