]>
Commit | Line | Data |
---|---|---|
74652cf6 TW |
1 | /* |
2 | * (C) Copyright 2010-2011 | |
3 | * NVIDIA Corporation <www.nvidia.com> | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
b2871037 TW |
23 | |
24 | /* Tegra AP (Application Processor) code */ | |
25 | ||
150c2493 | 26 | #include <common.h> |
74652cf6 | 27 | #include <asm/io.h> |
d515362d | 28 | #include <asm/arch/gp_padctrl.h> |
150c2493 | 29 | #include <asm/arch-tegra/ap.h> |
b2871037 | 30 | #include <asm/arch-tegra/clock.h> |
150c2493 TW |
31 | #include <asm/arch-tegra/fuse.h> |
32 | #include <asm/arch-tegra/pmc.h> | |
33 | #include <asm/arch-tegra/scu.h> | |
e23bb6a4 | 34 | #include <asm/arch-tegra/tegra.h> |
150c2493 | 35 | #include <asm/arch-tegra/warmboot.h> |
74652cf6 | 36 | |
49493cb7 | 37 | int tegra_get_chip(void) |
d515362d | 38 | { |
49493cb7 TW |
39 | int rev; |
40 | struct apb_misc_gp_ctlr *gp = | |
41 | (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; | |
d515362d SG |
42 | |
43 | /* | |
44 | * This is undocumented, Chip ID is bits 15:8 of the register | |
45 | * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for | |
e23bb6a4 | 46 | * Tegra30, and 0x35 for T114. |
d515362d | 47 | */ |
d515362d | 48 | rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; |
49493cb7 TW |
49 | debug("%s: CHIPID is 0x%02X\n", __func__, rev); |
50 | ||
51 | return rev; | |
52 | } | |
53 | ||
54 | int tegra_get_sku_info(void) | |
55 | { | |
56 | int sku_id; | |
57 | struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; | |
58 | ||
59 | sku_id = readl(&fuse->sku_info) & 0xff; | |
60 | debug("%s: SKU info byte is 0x%02X\n", __func__, sku_id); | |
61 | ||
62 | return sku_id; | |
63 | } | |
64 | ||
65 | int tegra_get_chip_sku(void) | |
66 | { | |
67 | uint sku_id, chip_id; | |
d515362d | 68 | |
49493cb7 TW |
69 | chip_id = tegra_get_chip(); |
70 | sku_id = tegra_get_sku_info(); | |
d515362d | 71 | |
49493cb7 | 72 | switch (chip_id) { |
00a2749d | 73 | case CHIPID_TEGRA20: |
49493cb7 | 74 | switch (sku_id) { |
20583d04 | 75 | case SKU_ID_T20_7: |
d515362d SG |
76 | case SKU_ID_T20: |
77 | return TEGRA_SOC_T20; | |
78 | case SKU_ID_T25SE: | |
79 | case SKU_ID_AP25: | |
80 | case SKU_ID_T25: | |
81 | case SKU_ID_AP25E: | |
82 | case SKU_ID_T25E: | |
83 | return TEGRA_SOC_T25; | |
84 | } | |
85 | break; | |
b2871037 | 86 | case CHIPID_TEGRA30: |
49493cb7 | 87 | switch (sku_id) { |
eb222d1d | 88 | case SKU_ID_T33: |
b2871037 TW |
89 | case SKU_ID_T30: |
90 | return TEGRA_SOC_T30; | |
91 | } | |
92 | break; | |
e23bb6a4 | 93 | case CHIPID_TEGRA114: |
49493cb7 | 94 | switch (sku_id) { |
e23bb6a4 | 95 | case SKU_ID_T114_ENG: |
840167c2 | 96 | case SKU_ID_T114_1: |
e23bb6a4 TW |
97 | return TEGRA_SOC_T114; |
98 | } | |
99 | break; | |
d515362d | 100 | } |
49493cb7 TW |
101 | /* unknown chip/sku id */ |
102 | printf("%s: ERROR: UNKNOWN CHIP/SKU ID COMBO (0x%02X/0x%02X)\n", | |
103 | __func__, chip_id, sku_id); | |
d515362d SG |
104 | return TEGRA_SOC_UNKNOWN; |
105 | } | |
106 | ||
12b7b70c | 107 | static void enable_scu(void) |
74652cf6 TW |
108 | { |
109 | struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE; | |
110 | u32 reg; | |
111 | ||
112 | /* If SCU already setup/enabled, return */ | |
113 | if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE) | |
114 | return; | |
115 | ||
116 | /* Invalidate all ways for all processors */ | |
117 | writel(0xFFFF, &scu->scu_inv_all); | |
118 | ||
119 | /* Enable SCU - bit 0 */ | |
120 | reg = readl(&scu->scu_ctrl); | |
121 | reg |= SCU_CTRL_ENABLE; | |
122 | writel(reg, &scu->scu_ctrl); | |
123 | } | |
124 | ||
76e350b7 TW |
125 | static u32 get_odmdata(void) |
126 | { | |
127 | /* | |
128 | * ODMDATA is stored in the BCT in IRAM by the BootROM. | |
129 | * The BCT start and size are stored in the BIT in IRAM. | |
130 | * Read the data @ bct_start + (bct_size - 12). This works | |
131 | * on T20 and T30 BCTs, which are locked down. If this changes | |
132 | * in new chips (T114, etc.), we can revisit this algorithm. | |
133 | */ | |
134 | ||
135 | u32 bct_start, odmdata; | |
136 | ||
b2871037 | 137 | bct_start = readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BCTPTR); |
76e350b7 TW |
138 | odmdata = readl(bct_start + BCT_ODMDATA_OFFSET); |
139 | ||
140 | return odmdata; | |
141 | } | |
142 | ||
12b7b70c | 143 | static void init_pmc_scratch(void) |
74652cf6 | 144 | { |
29f3e3f2 | 145 | struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; |
76e350b7 | 146 | u32 odmdata; |
74652cf6 TW |
147 | int i; |
148 | ||
149 | /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */ | |
150 | for (i = 0; i < 23; i++) | |
151 | writel(0, &pmc->pmc_scratch1+i); | |
152 | ||
153 | /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */ | |
76e350b7 TW |
154 | odmdata = get_odmdata(); |
155 | writel(odmdata, &pmc->pmc_scratch20); | |
74652cf6 TW |
156 | } |
157 | ||
12b7b70c | 158 | void s_init(void) |
74652cf6 | 159 | { |
210576fc SG |
160 | /* Init PMC scratch memory */ |
161 | init_pmc_scratch(); | |
74652cf6 | 162 | |
210576fc | 163 | enable_scu(); |
74652cf6 | 164 | |
d0edce4f TW |
165 | /* init the cache */ |
166 | config_cache(); | |
74652cf6 | 167 | } |