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