aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/fuse.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-27 19:41:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-27 19:41:24 -0400
commit34800598b2eebe061445216473b1e4c2ff5cba99 (patch)
treea6d0eb6fe45d9480888d7ddb34840e172ed80e56 /arch/arm/mach-tegra/fuse.c
parent46b407ca4a6149c8d27fcec1881d4f184bec7c77 (diff)
parent511f1cb6d426938fabf9c6d69ce4861b66ffd919 (diff)
Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull "ARM: driver specific updates" from Arnd Bergmann: "These are all specific to some driver. They are typically the platform side of a change in the drivers directory, such as adding a new driver or extending the interface to the platform. In cases where there is no maintainer for the driver, or the maintainer prefers to have the platform changes in the same branch as the driver changes, the patches to the drivers are included as well. A much smaller set of driver updates that depend on other branches getting merged first will be sent later. The new export of tegra_chip_uid conflicts with other changes in fuse.c. In rtc-sa1100.c, the global removal of IRQF_DISABLED conflicts with the cleanup of the interrupt handling of that driver. Signed-off-by: Arnd Bergmann <arnd@arndb.de>" Fixed up aforementioned trivial conflicts. * tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (94 commits) ARM: SAMSUNG: change the name from s3c-sdhci to exynos4-sdhci mmc: sdhci-s3c: add platform data for the second capability ARM: SAMSUNG: support the second capability for samsung-soc ARM: EXYNOS: add support DMA for EXYNOS4X12 SoC ARM: EXYNOS: Add apb_pclk clkdev entry for mdma1 ARM: EXYNOS: Enable MDMA driver regulator: Remove bq24022 regulator driver rtc: sa1100: add OF support pxa: magician/hx4700: Convert to gpio-regulator from bq24022 ARM: OMAP3+: SmartReflex: fix error handling ARM: OMAP3+: SmartReflex: fix the use of debugfs_create_* API ARM: OMAP3+: SmartReflex: micro-optimization for sanity check ARM: OMAP3+: SmartReflex: misc cleanups ARM: OMAP3+: SmartReflex: move late_initcall() closer to its argument ARM: OMAP3+: SmartReflex: add missing platform_set_drvdata() ARM: OMAP3+: hwmod: add SmartReflex IRQs ARM: OMAP3+: SmartReflex: clear ERRCONFIG_VPBOUNDINTST only on a need ARM: OMAP3+: SmartReflex: Fix status masking in ERRCONFIG register ARM: OMAP3+: SmartReflex: Add a shutdown hook ARM: OMAP3+: SmartReflex Class3: disable errorgen before disable VP ... Conflicts: arch/arm/mach-tegra/Makefile arch/arm/mach-tegra/fuse.c drivers/rtc/rtc-sa1100.c
Diffstat (limited to 'arch/arm/mach-tegra/fuse.c')
-rw-r--r--arch/arm/mach-tegra/fuse.c109
1 files changed, 75 insertions, 34 deletions
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index ea49bd93c6b9..c1afb2738769 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -19,25 +19,75 @@
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/module.h> 22#include <linux/export.h>
23 23
24#include <mach/iomap.h> 24#include <mach/iomap.h>
25 25
26#include "fuse.h" 26#include "fuse.h"
27#include "apbio.h"
27 28
28#define FUSE_UID_LOW 0x108 29#define FUSE_UID_LOW 0x108
29#define FUSE_UID_HIGH 0x10c 30#define FUSE_UID_HIGH 0x10c
30#define FUSE_SKU_INFO 0x110 31#define FUSE_SKU_INFO 0x110
31#define FUSE_SPARE_BIT 0x200 32#define FUSE_SPARE_BIT 0x200
32 33
33static inline u32 fuse_readl(unsigned long offset) 34int tegra_sku_id;
35int tegra_cpu_process_id;
36int tegra_core_process_id;
37enum tegra_revision tegra_revision;
38
39/* The BCT to use at boot is specified by board straps that can be read
40 * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
41 */
42int tegra_bct_strapping;
43
44#define STRAP_OPT 0x008
45#define GMI_AD0 (1 << 4)
46#define GMI_AD1 (1 << 5)
47#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
48#define RAM_CODE_SHIFT 4
49
50static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
51 [TEGRA_REVISION_UNKNOWN] = "unknown",
52 [TEGRA_REVISION_A01] = "A01",
53 [TEGRA_REVISION_A02] = "A02",
54 [TEGRA_REVISION_A03] = "A03",
55 [TEGRA_REVISION_A03p] = "A03 prime",
56 [TEGRA_REVISION_A04] = "A04",
57};
58
59static inline u32 tegra_fuse_readl(unsigned long offset)
60{
61 return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
62}
63
64static inline bool get_spare_fuse(int bit)
34{ 65{
35 return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); 66 return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
36} 67}
37 68
38static inline void fuse_writel(u32 value, unsigned long offset) 69static enum tegra_revision tegra_get_revision(void)
39{ 70{
40 writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset)); 71 void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
72 u32 id = readl(chip_id);
73 u32 minor_rev = (id >> 16) & 0xf;
74 u32 chipid = (id >> 8) & 0xff;
75
76 switch (minor_rev) {
77 case 1:
78 return TEGRA_REVISION_A01;
79 case 2:
80 return TEGRA_REVISION_A02;
81 case 3:
82 if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19)))
83 return TEGRA_REVISION_A03p;
84 else
85 return TEGRA_REVISION_A03;
86 case 4:
87 return TEGRA_REVISION_A04;
88 default:
89 return TEGRA_REVISION_UNKNOWN;
90 }
41} 91}
42 92
43void tegra_init_fuse(void) 93void tegra_init_fuse(void)
@@ -46,41 +96,32 @@ void tegra_init_fuse(void)
46 reg |= 1 << 28; 96 reg |= 1 << 28;
47 writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); 97 writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
48 98
49 pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", 99 reg = tegra_fuse_readl(FUSE_SKU_INFO);
50 tegra_sku_id(), tegra_cpu_process_id(), 100 tegra_sku_id = reg & 0xFF;
51 tegra_core_process_id()); 101
102 reg = tegra_fuse_readl(FUSE_SPARE_BIT);
103 tegra_cpu_process_id = (reg >> 6) & 3;
104
105 reg = tegra_fuse_readl(FUSE_SPARE_BIT);
106 tegra_core_process_id = (reg >> 12) & 3;
107
108 reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
109 tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
110
111 tegra_revision = tegra_get_revision();
112
113 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
114 tegra_revision_name[tegra_get_revision()],
115 tegra_sku_id, tegra_cpu_process_id,
116 tegra_core_process_id);
52} 117}
53 118
54unsigned long long tegra_chip_uid(void) 119unsigned long long tegra_chip_uid(void)
55{ 120{
56 unsigned long long lo, hi; 121 unsigned long long lo, hi;
57 122
58 lo = fuse_readl(FUSE_UID_LOW); 123 lo = tegra_fuse_readl(FUSE_UID_LOW);
59 hi = fuse_readl(FUSE_UID_HIGH); 124 hi = tegra_fuse_readl(FUSE_UID_HIGH);
60 return (hi << 32ull) | lo; 125 return (hi << 32ull) | lo;
61} 126}
62EXPORT_SYMBOL(tegra_chip_uid); 127EXPORT_SYMBOL(tegra_chip_uid);
63
64int tegra_sku_id(void)
65{
66 int sku_id;
67 u32 reg = fuse_readl(FUSE_SKU_INFO);
68 sku_id = reg & 0xFF;
69 return sku_id;
70}
71
72int tegra_cpu_process_id(void)
73{
74 int cpu_process_id;
75 u32 reg = fuse_readl(FUSE_SPARE_BIT);
76 cpu_process_id = (reg >> 6) & 3;
77 return cpu_process_id;
78}
79
80int tegra_core_process_id(void)
81{
82 int core_process_id;
83 u32 reg = fuse_readl(FUSE_SPARE_BIT);
84 core_process_id = (reg >> 12) & 3;
85 return core_process_id;
86}