Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: tegra: fuse: add functions to access chip revision

Add function to get chip revision, and print it out at boot time.

Restructure the fuse access to just use cached variables instead
of always reading the fuses, and export those variables directly
instead of using accessor functions.

Add a SKU ID table of currently known values.

Based on code originally by Colin Cross <ccross@android.com>.

Changes since v1:

* Add A01 minor rev support
* Don't decode for A03p on anything but T2x

Signed-off-by: Olof Johansson <olof@lixom.net>
Acked-by: Stephen Warren <swarren@nvidia.com>

+86 -33
+58 -27
arch/arm/mach-tegra/fuse.c
··· 30 30 #define FUSE_SKU_INFO 0x110 31 31 #define FUSE_SPARE_BIT 0x200 32 32 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 + static const char *tegra_revision_name[TEGRA_REVISION_MAX] = { 39 + [TEGRA_REVISION_UNKNOWN] = "unknown", 40 + [TEGRA_REVISION_A01] = "A01", 41 + [TEGRA_REVISION_A02] = "A02", 42 + [TEGRA_REVISION_A03] = "A03", 43 + [TEGRA_REVISION_A03p] = "A03 prime", 44 + [TEGRA_REVISION_A04] = "A04", 45 + }; 46 + 33 47 static inline u32 tegra_fuse_readl(unsigned long offset) 34 48 { 35 49 return tegra_apb_readl(TEGRA_FUSE_BASE + offset); 50 + } 51 + 52 + static inline bool get_spare_fuse(int bit) 53 + { 54 + return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4); 55 + } 56 + 57 + static enum tegra_revision tegra_get_revision(void) 58 + { 59 + void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804; 60 + u32 id = readl(chip_id); 61 + u32 minor_rev = (id >> 16) & 0xf; 62 + u32 chipid = (id >> 8) & 0xff; 63 + 64 + switch (minor_rev) { 65 + case 1: 66 + return TEGRA_REVISION_A01; 67 + case 2: 68 + return TEGRA_REVISION_A02; 69 + case 3: 70 + if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19))) 71 + return TEGRA_REVISION_A03p; 72 + else 73 + return TEGRA_REVISION_A03; 74 + case 4: 75 + return TEGRA_REVISION_A04; 76 + default: 77 + return TEGRA_REVISION_UNKNOWN; 78 + } 36 79 } 37 80 38 81 void tegra_init_fuse(void) ··· 84 41 reg |= 1 << 28; 85 42 writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); 86 43 87 - pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", 88 - tegra_sku_id(), tegra_cpu_process_id(), 89 - tegra_core_process_id()); 44 + reg = tegra_fuse_readl(FUSE_SKU_INFO); 45 + tegra_sku_id = reg & 0xFF; 46 + 47 + reg = tegra_fuse_readl(FUSE_SPARE_BIT); 48 + tegra_cpu_process_id = (reg >> 6) & 3; 49 + 50 + reg = tegra_fuse_readl(FUSE_SPARE_BIT); 51 + tegra_core_process_id = (reg >> 12) & 3; 52 + 53 + tegra_revision = tegra_get_revision(); 54 + 55 + pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", 56 + tegra_revision_name[tegra_get_revision()], 57 + tegra_sku_id, tegra_cpu_process_id, 58 + tegra_core_process_id); 90 59 } 91 60 92 61 unsigned long long tegra_chip_uid(void) ··· 108 53 lo = tegra_fuse_readl(FUSE_UID_LOW); 109 54 hi = tegra_fuse_readl(FUSE_UID_HIGH); 110 55 return (hi << 32ull) | lo; 111 - } 112 - 113 - int tegra_sku_id(void) 114 - { 115 - int sku_id; 116 - u32 reg = tegra_fuse_readl(FUSE_SKU_INFO); 117 - sku_id = reg & 0xFF; 118 - return sku_id; 119 - } 120 - 121 - int tegra_cpu_process_id(void) 122 - { 123 - int cpu_process_id; 124 - u32 reg = tegra_fuse_readl(FUSE_SPARE_BIT); 125 - cpu_process_id = (reg >> 6) & 3; 126 - return cpu_process_id; 127 - } 128 - 129 - int tegra_core_process_id(void) 130 - { 131 - int core_process_id; 132 - u32 reg = tegra_fuse_readl(FUSE_SPARE_BIT); 133 - core_process_id = (reg >> 12) & 3; 134 - return core_process_id; 135 56 }
+27 -5
arch/arm/mach-tegra/fuse.h
··· 1 1 /* 2 - * arch/arm/mach-tegra/fuse.c 3 - * 4 2 * Copyright (C) 2010 Google, Inc. 5 3 * 6 4 * Author: ··· 15 17 * 16 18 */ 17 19 20 + #ifndef __MACH_TEGRA_FUSE_H 21 + #define __MACH_TEGRA_FUSE_H 22 + 23 + enum tegra_revision { 24 + TEGRA_REVISION_UNKNOWN = 0, 25 + TEGRA_REVISION_A01, 26 + TEGRA_REVISION_A02, 27 + TEGRA_REVISION_A03, 28 + TEGRA_REVISION_A03p, 29 + TEGRA_REVISION_A04, 30 + TEGRA_REVISION_MAX, 31 + }; 32 + 33 + #define SKU_ID_T20 8 34 + #define SKU_ID_T25SE 20 35 + #define SKU_ID_AP25 23 36 + #define SKU_ID_T25 24 37 + #define SKU_ID_AP25E 27 38 + #define SKU_ID_T25E 28 39 + 40 + extern int tegra_sku_id; 41 + extern int tegra_cpu_process_id; 42 + extern int tegra_core_process_id; 43 + extern enum tegra_revision tegra_revision; 44 + 18 45 unsigned long long tegra_chip_uid(void); 19 - int tegra_sku_id(void); 20 - int tegra_cpu_process_id(void); 21 - int tegra_core_process_id(void); 22 46 void tegra_init_fuse(void); 47 + 48 + #endif
+1 -1
arch/arm/mach-tegra/tegra2_clocks.c
··· 720 720 { 721 721 tegra2_pll_clk_init(c); 722 722 723 - if (tegra_sku_id() == 7) 723 + if (tegra_sku_id == 7) 724 724 c->max_rate = 750000000; 725 725 } 726 726