tegra-apbmisc.c 4.68 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5 6 7 8 9 10 11
/*
 * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
 */

#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/io.h>

#include <soc/tegra/fuse.h>
12
#include <soc/tegra/common.h>
13 14 15 16 17

#include "fuse.h"

#define FUSE_SKU_INFO	0x10

18 19 20 21 22 23 24
#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT	4
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG	\
	(0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT	\
	(0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)

static bool long_ram_code;
25 26
static u32 strapping;
static u32 chipid;
27 28 29

u32 tegra_read_chipid(void)
{
30
	WARN(!chipid, "Tegra APB MISC not yet available\n");
31

32
	return chipid;
33 34 35 36
}

u8 tegra_get_chip_id(void)
{
37
	return (tegra_read_chipid() >> 8) & 0xff;
38 39
}

40 41 42 43 44 45 46 47 48 49
u8 tegra_get_major_rev(void)
{
	return (tegra_read_chipid() >> 4) & 0xf;
}

u8 tegra_get_minor_rev(void)
{
	return (tegra_read_chipid() >> 16) & 0xf;
}

50 51 52 53 54
u8 tegra_get_platform(void)
{
	return (tegra_read_chipid() >> 20) & 0xf;
}

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
bool tegra_is_silicon(void)
{
	switch (tegra_get_chip_id()) {
	case TEGRA194:
		if (tegra_get_platform() == 0)
			return true;

		return false;
	}

	/*
	 * Chips prior to Tegra194 have a different way of determining whether
	 * they are silicon or not. Since we never supported simulation on the
	 * older Tegra chips, don't bother extracting the information and just
	 * report that we're running on silicon.
	 */
	return true;
}

74 75
u32 tegra_read_straps(void)
{
76 77
	WARN(!chipid, "Tegra ABP MISC not yet available\n");

78
	return strapping;
79 80
}

81 82 83 84 85 86 87 88 89 90 91 92
u32 tegra_read_ram_code(void)
{
	u32 straps = tegra_read_straps();

	if (long_ram_code)
		straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG;
	else
		straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT;

	return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT;
}

93 94
static const struct of_device_id apbmisc_match[] __initconst = {
	{ .compatible = "nvidia,tegra20-apbmisc", },
95
	{ .compatible = "nvidia,tegra186-misc", },
96
	{ .compatible = "nvidia,tegra194-misc", },
97 98 99 100 101
	{},
};

void __init tegra_init_revision(void)
{
102
	u8 chip_id, minor_rev;
103

104 105
	chip_id = tegra_get_chip_id();
	minor_rev = tegra_get_minor_rev();
106 107 108

	switch (minor_rev) {
	case 1:
109
		tegra_sku_info.revision = TEGRA_REVISION_A01;
110 111
		break;
	case 2:
112
		tegra_sku_info.revision = TEGRA_REVISION_A02;
113 114
		break;
	case 3:
115 116
		if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) ||
					   tegra_fuse_read_spare(19)))
117
			tegra_sku_info.revision = TEGRA_REVISION_A03p;
118
		else
119
			tegra_sku_info.revision = TEGRA_REVISION_A03;
120 121
		break;
	case 4:
122
		tegra_sku_info.revision = TEGRA_REVISION_A04;
123 124
		break;
	default:
125
		tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN;
126 127
	}

128
	tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO);
129 130 131 132
}

void __init tegra_init_apbmisc(void)
{
133
	void __iomem *apbmisc_base, *strapping_base;
134
	struct resource apbmisc, straps;
135 136 137
	struct device_node *np;

	np = of_find_matching_node(NULL, apbmisc_match);
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
	if (!np) {
		/*
		 * Fall back to legacy initialization for 32-bit ARM only. All
		 * 64-bit ARM device tree files for Tegra are required to have
		 * an APBMISC node.
		 *
		 * This is for backwards-compatibility with old device trees
		 * that didn't contain an APBMISC node.
		 */
		if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
			/* APBMISC registers (chip revision, ...) */
			apbmisc.start = 0x70000800;
			apbmisc.end = 0x70000863;
			apbmisc.flags = IORESOURCE_MEM;

			/* strapping options */
154
			if (of_machine_is_compatible("nvidia,tegra124")) {
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
				straps.start = 0x7000e864;
				straps.end = 0x7000e867;
			} else {
				straps.start = 0x70000008;
				straps.end = 0x7000000b;
			}

			straps.flags = IORESOURCE_MEM;

			pr_warn("Using APBMISC region %pR\n", &apbmisc);
			pr_warn("Using strapping options registers %pR\n",
				&straps);
		} else {
			/*
			 * At this point we're not running on Tegra, so play
			 * nice with multi-platform kernels.
			 */
			return;
		}
	} else {
		/*
		 * Extract information from the device tree if we've found a
		 * matching node.
		 */
		if (of_address_to_resource(np, 0, &apbmisc) < 0) {
			pr_err("failed to get APBMISC registers\n");
			return;
		}

		if (of_address_to_resource(np, 1, &straps) < 0) {
			pr_err("failed to get strapping options registers\n");
			return;
		}
188 189
	}

190
	apbmisc_base = ioremap(apbmisc.start, resource_size(&apbmisc));
191
	if (!apbmisc_base) {
192
		pr_err("failed to map APBMISC registers\n");
193
	} else {
194
		chipid = readl_relaxed(apbmisc_base + 4);
195 196
		iounmap(apbmisc_base);
	}
197

198
	strapping_base = ioremap(straps.start, resource_size(&straps));
199
	if (!strapping_base) {
200
		pr_err("failed to map strapping options registers\n");
201
	} else {
202
		strapping = readl_relaxed(strapping_base);
203 204
		iounmap(strapping_base);
	}
205 206

	long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
207
}