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 static void __iomem *apbmisc_base; 32 static void __iomem *strapping_base; 33 34 u32 tegra_read_chipid(void) 35 { 36 return readl_relaxed(apbmisc_base + 4); 37 } 38 39 u8 tegra_get_chip_id(void) 40 { 41 if (!apbmisc_base) { 42 WARN(1, "Tegra Chip ID not yet available\n"); 43 return 0; 44 } 45 46 return (tegra_read_chipid() >> 8) & 0xff; 47 } 48 49 u32 tegra_read_straps(void) 50 { 51 if (strapping_base) 52 return readl_relaxed(strapping_base); 53 else 54 return 0; 55 } 56 57 static const struct of_device_id apbmisc_match[] __initconst = { 58 { .compatible = "nvidia,tegra20-apbmisc", }, 59 {}, 60 }; 61 62 void __init tegra_init_revision(void) 63 { 64 u32 id, chip_id, minor_rev; 65 int rev; 66 67 id = tegra_read_chipid(); 68 chip_id = (id >> 8) & 0xff; 69 minor_rev = (id >> 16) & 0xf; 70 71 switch (minor_rev) { 72 case 1: 73 rev = TEGRA_REVISION_A01; 74 break; 75 case 2: 76 rev = TEGRA_REVISION_A02; 77 break; 78 case 3: 79 if (chip_id == TEGRA20 && (tegra20_spare_fuse_early(18) || 80 tegra20_spare_fuse_early(19))) 81 rev = TEGRA_REVISION_A03p; 82 else 83 rev = TEGRA_REVISION_A03; 84 break; 85 case 4: 86 rev = TEGRA_REVISION_A04; 87 break; 88 default: 89 rev = TEGRA_REVISION_UNKNOWN; 90 } 91 92 tegra_sku_info.revision = rev; 93 94 if (chip_id == TEGRA20) 95 tegra_sku_info.sku_id = tegra20_fuse_early(FUSE_SKU_INFO); 96 else 97 tegra_sku_info.sku_id = tegra30_fuse_readl(FUSE_SKU_INFO); 98 } 99 100 void __init tegra_init_apbmisc(void) 101 { 102 struct device_node *np; 103 104 np = of_find_matching_node(NULL, apbmisc_match); 105 apbmisc_base = of_iomap(np, 0); 106 if (!apbmisc_base) { 107 pr_warn("ioremap tegra apbmisc failed. using %08x instead\n", 108 APBMISC_BASE); 109 apbmisc_base = ioremap(APBMISC_BASE, APBMISC_SIZE); 110 } 111 112 strapping_base = of_iomap(np, 1); 113 if (!strapping_base) 114 pr_err("ioremap tegra strapping_base failed\n"); 115 } 116