[ARM] tegra: fuse: Add function to get Tegra revision
authorColin Cross <ccross@android.com>
Sun, 17 Oct 2010 22:00:08 +0000 (15:00 -0700)
committerColin Cross <ccross@android.com>
Fri, 7 Jan 2011 02:54:00 +0000 (18:54 -0800)
Change-Id: I11783f5784454fec143393336195db40c9aa3160
Signed-off-by: Colin Cross <ccross@android.com>
arch/arm/mach-tegra/fuse.c
arch/arm/mach-tegra/fuse.h

index 91919171e7472d8b43305c59a0e8a797beb02c81..fcb6d05495fba8f8f536d93db64b0fd24a1f3c67 100644 (file)
@@ -43,6 +43,13 @@ static u32 *tegra_fuse_bb;
 static dma_addr_t tegra_fuse_bb_phys;
 static DECLARE_COMPLETION(tegra_fuse_wait);
 
+static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
+       [TEGRA_REVISION_UNKNOWN] = "unknown",
+       [TEGRA_REVISION_A02] = "A02",
+       [TEGRA_REVISION_A03] = "A03",
+       [TEGRA_REVISION_A03p] = "A03 prime",
+};
+
 static void fuse_dma_complete(struct tegra_dma_req *req)
 {
        complete(&tegra_fuse_wait);
@@ -136,13 +143,19 @@ void tegra_fuse_writel(u32 value, unsigned long offset)
        fuse_writel(value, offset);
 }
 
+static inline bool get_spare_fuse(int bit)
+{
+       return fuse_readl(FUSE_SPARE_BIT + bit * 4);
+}
+
 void tegra_init_fuse(void)
 {
        u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
        reg |= 1 << 28;
        writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
 
-       pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n",
+       pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
+               tegra_revision_name[tegra_get_revision()],
                tegra_sku_id(), tegra_cpu_process_id(),
                tegra_core_process_id());
 }
@@ -200,3 +213,21 @@ int tegra_core_process_id(void)
        core_process_id = (reg >> 12) & 3;
        return core_process_id;
 }
+
+enum tegra_revision tegra_get_revision(void)
+{
+       void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
+       u32 id = readl(chip_id);
+
+       switch ((id >> 16) & 0xf) {
+       case 2:
+               return TEGRA_REVISION_A02;
+       case 3:
+               if (get_spare_fuse(18) || get_spare_fuse(19))
+                       return TEGRA_REVISION_A03p;
+               else
+                       return TEGRA_REVISION_A03;
+       default:
+               return TEGRA_REVISION_UNKNOWN;
+       }
+}
index 624bbfa6e5fbc1bc2dfacd31940b3c59584e925c..8a9042635f2b6f035cfc4b313b32265c5eb736b8 100644 (file)
  *
  */
 
+enum tegra_revision {
+       TEGRA_REVISION_UNKNOWN = 0,
+       TEGRA_REVISION_A02,
+       TEGRA_REVISION_A03,
+       TEGRA_REVISION_A03p,
+       TEGRA_REVISION_MAX,
+};
+
 unsigned long long tegra_chip_uid(void);
 int tegra_sku_id(void);
 int tegra_cpu_process_id(void);
@@ -25,3 +33,4 @@ void tegra_init_fuse(void);
 void tegra_init_fuse_dma(void);
 u32 tegra_fuse_readl(unsigned long offset);
 void tegra_fuse_writel(u32 value, unsigned long offset);
+enum tegra_revision tegra_get_revision(void);