1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/of.h> 8 #include <linux/of_address.h> 9 #include <linux/io.h> 10 11 #include <soc/tegra/fuse.h> 12 #include <soc/tegra/common.h> 13 14 #include "fuse.h" 15 16 #define FUSE_SKU_INFO 0x10 17 18 #define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4 19 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \ 20 (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) 21 #define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \ 22 (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT) 23 24 static bool long_ram_code; 25 static u32 strapping; 26 static u32 chipid; 27 28 u32 tegra_read_chipid(void) 29 { 30 WARN(!chipid, "Tegra APB MISC not yet available\n"); 31 32 return chipid; 33 } 34 35 u8 tegra_get_chip_id(void) 36 { 37 return (tegra_read_chipid() >> 8) & 0xff; 38 } 39 40 u8 tegra_get_major_rev(void) 41 { 42 return (tegra_read_chipid() >> 4) & 0xf; 43 } 44 45 u8 tegra_get_minor_rev(void) 46 { 47 return (tegra_read_chipid() >> 16) & 0xf; 48 } 49 50 u8 tegra_get_platform(void) 51 { 52 return (tegra_read_chipid() >> 20) & 0xf; 53 } 54 55 bool tegra_is_silicon(void) 56 { 57 switch (tegra_get_chip_id()) { 58 case TEGRA194: 59 case TEGRA234: 60 if (tegra_get_platform() == 0) 61 return true; 62 63 return false; 64 } 65 66 /* 67 * Chips prior to Tegra194 have a different way of determining whether 68 * they are silicon or not. Since we never supported simulation on the 69 * older Tegra chips, don't bother extracting the information and just 70 * report that we're running on silicon. 71 */ 72 return true; 73 } 74 75 u32 tegra_read_straps(void) 76 { 77 WARN(!chipid, "Tegra ABP MISC not yet available\n"); 78 79 return strapping; 80 } 81 82 u32 tegra_read_ram_code(void) 83 { 84 u32 straps = tegra_read_straps(); 85 86 if (long_ram_code) 87 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG; 88 else 89 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT; 90 91 return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT; 92 } 93 94 static const struct of_device_id apbmisc_match[] __initconst = { 95 { .compatible = "nvidia,tegra20-apbmisc", }, 96 { .compatible = "nvidia,tegra186-misc", }, 97 { .compatible = "nvidia,tegra194-misc", }, 98 { .compatible = "nvidia,tegra234-misc", }, 99 {}, 100 }; 101 102 void __init tegra_init_revision(void) 103 { 104 u8 chip_id, minor_rev; 105 106 chip_id = tegra_get_chip_id(); 107 minor_rev = tegra_get_minor_rev(); 108 109 switch (minor_rev) { 110 case 1: 111 tegra_sku_info.revision = TEGRA_REVISION_A01; 112 break; 113 case 2: 114 tegra_sku_info.revision = TEGRA_REVISION_A02; 115 break; 116 case 3: 117 if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) || 118 tegra_fuse_read_spare(19))) 119 tegra_sku_info.revision = TEGRA_REVISION_A03p; 120 else 121 tegra_sku_info.revision = TEGRA_REVISION_A03; 122 break; 123 case 4: 124 tegra_sku_info.revision = TEGRA_REVISION_A04; 125 break; 126 default: 127 tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN; 128 } 129 130 tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO); 131 } 132 133 void __init tegra_init_apbmisc(void) 134 { 135 void __iomem *apbmisc_base, *strapping_base; 136 struct resource apbmisc, straps; 137 struct device_node *np; 138 139 np = of_find_matching_node(NULL, apbmisc_match); 140 if (!np) { 141 /* 142 * Fall back to legacy initialization for 32-bit ARM only. All 143 * 64-bit ARM device tree files for Tegra are required to have 144 * an APBMISC node. 145 * 146 * This is for backwards-compatibility with old device trees 147 * that didn't contain an APBMISC node. 148 */ 149 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) { 150 /* APBMISC registers (chip revision, ...) */ 151 apbmisc.start = 0x70000800; 152 apbmisc.end = 0x70000863; 153 apbmisc.flags = IORESOURCE_MEM; 154 155 /* strapping options */ 156 if (of_machine_is_compatible("nvidia,tegra124")) { 157 straps.start = 0x7000e864; 158 straps.end = 0x7000e867; 159 } else { 160 straps.start = 0x70000008; 161 straps.end = 0x7000000b; 162 } 163 164 straps.flags = IORESOURCE_MEM; 165 166 pr_warn("Using APBMISC region %pR\n", &apbmisc); 167 pr_warn("Using strapping options registers %pR\n", 168 &straps); 169 } else { 170 /* 171 * At this point we're not running on Tegra, so play 172 * nice with multi-platform kernels. 173 */ 174 return; 175 } 176 } else { 177 /* 178 * Extract information from the device tree if we've found a 179 * matching node. 180 */ 181 if (of_address_to_resource(np, 0, &apbmisc) < 0) { 182 pr_err("failed to get APBMISC registers\n"); 183 return; 184 } 185 186 if (of_address_to_resource(np, 1, &straps) < 0) { 187 pr_err("failed to get strapping options registers\n"); 188 return; 189 } 190 } 191 192 apbmisc_base = ioremap(apbmisc.start, resource_size(&apbmisc)); 193 if (!apbmisc_base) { 194 pr_err("failed to map APBMISC registers\n"); 195 } else { 196 chipid = readl_relaxed(apbmisc_base + 4); 197 iounmap(apbmisc_base); 198 } 199 200 strapping_base = ioremap(straps.start, resource_size(&straps)); 201 if (!strapping_base) { 202 pr_err("failed to map strapping options registers\n"); 203 } else { 204 strapping = readl_relaxed(strapping_base); 205 iounmap(strapping_base); 206 } 207 208 long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code"); 209 } 210