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 #include <soc/tegra/common.h> 25 26 #include "fuse.h" 27 28 #define FUSE_SKU_INFO 0x10 29 30 #define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4 31 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \ 32 (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) 33 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \ 34 (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) 35 36 static void __iomem *apbmisc_base; 37 static void __iomem *strapping_base; 38 static bool long_ram_code; 39 40 u32 tegra_read_chipid(void) 41 { 42 return readl_relaxed(apbmisc_base + 4); 43 } 44 45 u8 tegra_get_chip_id(void) 46 { 47 if (!apbmisc_base) { 48 WARN(1, "Tegra Chip ID not yet available\n"); 49 return 0; 50 } 51 52 return (tegra_read_chipid() >> 8) & 0xff; 53 } 54 55 u32 tegra_read_straps(void) 56 { 57 if (strapping_base) 58 return readl_relaxed(strapping_base); 59 else 60 return 0; 61 } 62 63 u32 tegra_read_ram_code(void) 64 { 65 u32 straps = tegra_read_straps(); 66 67 if (long_ram_code) 68 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG; 69 else 70 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT; 71 72 return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT; 73 } 74 75 static const struct of_device_id apbmisc_match[] __initconst = { 76 { .compatible = "nvidia,tegra20-apbmisc", }, 77 {}, 78 }; 79 80 void __init tegra_init_revision(void) 81 { 82 u32 id, chip_id, minor_rev; 83 int rev; 84 85 id = tegra_read_chipid(); 86 chip_id = (id >> 8) & 0xff; 87 minor_rev = (id >> 16) & 0xf; 88 89 switch (minor_rev) { 90 case 1: 91 rev = TEGRA_REVISION_A01; 92 break; 93 case 2: 94 rev = TEGRA_REVISION_A02; 95 break; 96 case 3: 97 if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) || 98 tegra_fuse_read_spare(19))) 99 rev = TEGRA_REVISION_A03p; 100 else 101 rev = TEGRA_REVISION_A03; 102 break; 103 case 4: 104 rev = TEGRA_REVISION_A04; 105 break; 106 default: 107 rev = TEGRA_REVISION_UNKNOWN; 108 } 109 110 tegra_sku_info.revision = rev; 111 112 tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO); 113 } 114 115 void __init tegra_init_apbmisc(void) 116 { 117 struct resource apbmisc, straps; 118 struct device_node *np; 119 120 np = of_find_matching_node(NULL, apbmisc_match); 121 if (!np) { 122 /* 123 * Fall back to legacy initialization for 32-bit ARM only. All 124 * 64-bit ARM device tree files for Tegra are required to have 125 * an APBMISC node. 126 * 127 * This is for backwards-compatibility with old device trees 128 * that didn't contain an APBMISC node. 129 */ 130 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) { 131 /* APBMISC registers (chip revision, ...) */ 132 apbmisc.start = 0x70000800; 133 apbmisc.end = 0x70000863; 134 apbmisc.flags = IORESOURCE_MEM; 135 136 /* strapping options */ 137 if (tegra_get_chip_id() == TEGRA124) { 138 straps.start = 0x7000e864; 139 straps.end = 0x7000e867; 140 } else { 141 straps.start = 0x70000008; 142 straps.end = 0x7000000b; 143 } 144 145 straps.flags = IORESOURCE_MEM; 146 147 pr_warn("Using APBMISC region %pR\n", &apbmisc); 148 pr_warn("Using strapping options registers %pR\n", 149 &straps); 150 } else { 151 /* 152 * At this point we're not running on Tegra, so play 153 * nice with multi-platform kernels. 154 */ 155 return; 156 } 157 } else { 158 /* 159 * Extract information from the device tree if we've found a 160 * matching node. 161 */ 162 if (of_address_to_resource(np, 0, &apbmisc) < 0) { 163 pr_err("failed to get APBMISC registers\n"); 164 return; 165 } 166 167 if (of_address_to_resource(np, 1, &straps) < 0) { 168 pr_err("failed to get strapping options registers\n"); 169 return; 170 } 171 } 172 173 apbmisc_base = ioremap_nocache(apbmisc.start, resource_size(&apbmisc)); 174 if (!apbmisc_base) 175 pr_err("failed to map APBMISC registers\n"); 176 177 strapping_base = ioremap_nocache(straps.start, resource_size(&straps)); 178 if (!strapping_base) 179 pr_err("failed to map strapping options registers\n"); 180 181 long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code"); 182 } 183