1 /* 2 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/of.h> 20 #include <linux/of_address.h> 21 #include <linux/io.h> 22 23 #include <soc/tegra/fuse.h> 24 25 #include "fuse.h" 26 27 #define APBMISC_BASE 0x70000800 28 #define APBMISC_SIZE 0x64 29 #define FUSE_SKU_INFO 0x10 30 31 #define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4 32 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \ 33 (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) 34 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \ 35 (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) 36 37 static void __iomem *apbmisc_base; 38 static void __iomem *strapping_base; 39 static bool long_ram_code; 40 41 u32 tegra_read_chipid(void) 42 { 43 return readl_relaxed(apbmisc_base + 4); 44 } 45 46 u8 tegra_get_chip_id(void) 47 { 48 if (!apbmisc_base) { 49 WARN(1, "Tegra Chip ID not yet available\n"); 50 return 0; 51 } 52 53 return (tegra_read_chipid() >> 8) & 0xff; 54 } 55 56 u32 tegra_read_straps(void) 57 { 58 if (strapping_base) 59 return readl_relaxed(strapping_base); 60 else 61 return 0; 62 } 63 64 u32 tegra_read_ram_code(void) 65 { 66 u32 straps = tegra_read_straps(); 67 68 if (long_ram_code) 69 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG; 70 else 71 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT; 72 73 return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT; 74 } 75 76 static const struct of_device_id apbmisc_match[] __initconst = { 77 { .compatible = "nvidia,tegra20-apbmisc", }, 78 {}, 79 }; 80 81 void __init tegra_init_revision(void) 82 { 83 u32 id, chip_id, minor_rev; 84 int rev; 85 86 id = tegra_read_chipid(); 87 chip_id = (id >> 8) & 0xff; 88 minor_rev = (id >> 16) & 0xf; 89 90 switch (minor_rev) { 91 case 1: 92 rev = TEGRA_REVISION_A01; 93 break; 94 case 2: 95 rev = TEGRA_REVISION_A02; 96 break; 97 case 3: 98 if (chip_id == TEGRA20 && (tegra20_spare_fuse_early(18) || 99 tegra20_spare_fuse_early(19))) 100 rev = TEGRA_REVISION_A03p; 101 else 102 rev = TEGRA_REVISION_A03; 103 break; 104 case 4: 105 rev = TEGRA_REVISION_A04; 106 break; 107 default: 108 rev = TEGRA_REVISION_UNKNOWN; 109 } 110 111 tegra_sku_info.revision = rev; 112 113 if (chip_id == TEGRA20) 114 tegra_sku_info.sku_id = tegra20_fuse_early(FUSE_SKU_INFO); 115 else 116 tegra_sku_info.sku_id = tegra30_fuse_readl(FUSE_SKU_INFO); 117 } 118 119 void __init tegra_init_apbmisc(void) 120 { 121 struct device_node *np; 122 123 np = of_find_matching_node(NULL, apbmisc_match); 124 apbmisc_base = of_iomap(np, 0); 125 if (!apbmisc_base) { 126 pr_warn("ioremap tegra apbmisc failed. using %08x instead\n", 127 APBMISC_BASE); 128 apbmisc_base = ioremap(APBMISC_BASE, APBMISC_SIZE); 129 } 130 131 strapping_base = of_iomap(np, 1); 132 if (!strapping_base) 133 pr_err("ioremap tegra strapping_base failed\n"); 134 135 long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code"); 136 } 137