aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/fuse.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/fuse.c')
-rw-r--r--arch/arm/mach-tegra/fuse.c107
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
32static inline u32 fuse_readl(unsigned long offset) 33int tegra_sku_id;
34int tegra_cpu_process_id;
35int tegra_core_process_id;
36enum 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 */
41int 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
49static 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
58static inline u32 tegra_fuse_readl(unsigned long offset)
59{
60 return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
61}
62
63static 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
37static inline void fuse_writel(u32 value, unsigned long offset) 68static 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
42void tegra_init_fuse(void) 92void 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
53unsigned 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
62int 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
70int 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
78int tegra_core_process_id(void) 118unsigned 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}