109f455dcSMasahiro Yamada /* 209f455dcSMasahiro Yamada * (C) Copyright 2010-2014 309f455dcSMasahiro Yamada * NVIDIA Corporation <www.nvidia.com> 409f455dcSMasahiro Yamada * 509f455dcSMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 609f455dcSMasahiro Yamada */ 709f455dcSMasahiro Yamada 809f455dcSMasahiro Yamada /* Tegra AP (Application Processor) code */ 909f455dcSMasahiro Yamada 1009f455dcSMasahiro Yamada #include <common.h> 1109f455dcSMasahiro Yamada #include <asm/io.h> 1209f455dcSMasahiro Yamada #include <asm/arch/gp_padctrl.h> 1373169874SIan Campbell #include <asm/arch/mc.h> 1409f455dcSMasahiro Yamada #include <asm/arch-tegra/ap.h> 1509f455dcSMasahiro Yamada #include <asm/arch-tegra/clock.h> 1609f455dcSMasahiro Yamada #include <asm/arch-tegra/fuse.h> 1709f455dcSMasahiro Yamada #include <asm/arch-tegra/pmc.h> 1809f455dcSMasahiro Yamada #include <asm/arch-tegra/scu.h> 1909f455dcSMasahiro Yamada #include <asm/arch-tegra/tegra.h> 2009f455dcSMasahiro Yamada #include <asm/arch-tegra/warmboot.h> 2109f455dcSMasahiro Yamada 2209f455dcSMasahiro Yamada int tegra_get_chip(void) 2309f455dcSMasahiro Yamada { 2409f455dcSMasahiro Yamada int rev; 2509f455dcSMasahiro Yamada struct apb_misc_gp_ctlr *gp = 2609f455dcSMasahiro Yamada (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; 2709f455dcSMasahiro Yamada 2809f455dcSMasahiro Yamada /* 2909f455dcSMasahiro Yamada * This is undocumented, Chip ID is bits 15:8 of the register 3009f455dcSMasahiro Yamada * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for 3109f455dcSMasahiro Yamada * Tegra30, 0x35 for T114, and 0x40 for Tegra124. 3209f455dcSMasahiro Yamada */ 3309f455dcSMasahiro Yamada rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; 3409f455dcSMasahiro Yamada debug("%s: CHIPID is 0x%02X\n", __func__, rev); 3509f455dcSMasahiro Yamada 3609f455dcSMasahiro Yamada return rev; 3709f455dcSMasahiro Yamada } 3809f455dcSMasahiro Yamada 3909f455dcSMasahiro Yamada int tegra_get_sku_info(void) 4009f455dcSMasahiro Yamada { 4109f455dcSMasahiro Yamada int sku_id; 4209f455dcSMasahiro Yamada struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; 4309f455dcSMasahiro Yamada 4409f455dcSMasahiro Yamada sku_id = readl(&fuse->sku_info) & 0xff; 4509f455dcSMasahiro Yamada debug("%s: SKU info byte is 0x%02X\n", __func__, sku_id); 4609f455dcSMasahiro Yamada 4709f455dcSMasahiro Yamada return sku_id; 4809f455dcSMasahiro Yamada } 4909f455dcSMasahiro Yamada 5009f455dcSMasahiro Yamada int tegra_get_chip_sku(void) 5109f455dcSMasahiro Yamada { 5209f455dcSMasahiro Yamada uint sku_id, chip_id; 5309f455dcSMasahiro Yamada 5409f455dcSMasahiro Yamada chip_id = tegra_get_chip(); 5509f455dcSMasahiro Yamada sku_id = tegra_get_sku_info(); 5609f455dcSMasahiro Yamada 5709f455dcSMasahiro Yamada switch (chip_id) { 5809f455dcSMasahiro Yamada case CHIPID_TEGRA20: 5909f455dcSMasahiro Yamada switch (sku_id) { 6009f455dcSMasahiro Yamada case SKU_ID_T20_7: 6109f455dcSMasahiro Yamada case SKU_ID_T20: 6209f455dcSMasahiro Yamada return TEGRA_SOC_T20; 6309f455dcSMasahiro Yamada case SKU_ID_T25SE: 6409f455dcSMasahiro Yamada case SKU_ID_AP25: 6509f455dcSMasahiro Yamada case SKU_ID_T25: 6609f455dcSMasahiro Yamada case SKU_ID_AP25E: 6709f455dcSMasahiro Yamada case SKU_ID_T25E: 6809f455dcSMasahiro Yamada return TEGRA_SOC_T25; 6909f455dcSMasahiro Yamada } 7009f455dcSMasahiro Yamada break; 7109f455dcSMasahiro Yamada case CHIPID_TEGRA30: 7209f455dcSMasahiro Yamada switch (sku_id) { 7309f455dcSMasahiro Yamada case SKU_ID_T33: 7409f455dcSMasahiro Yamada case SKU_ID_T30: 7509f455dcSMasahiro Yamada case SKU_ID_TM30MQS_P_A3: 7609f455dcSMasahiro Yamada default: 7709f455dcSMasahiro Yamada return TEGRA_SOC_T30; 7809f455dcSMasahiro Yamada } 7909f455dcSMasahiro Yamada break; 8009f455dcSMasahiro Yamada case CHIPID_TEGRA114: 8109f455dcSMasahiro Yamada switch (sku_id) { 8209f455dcSMasahiro Yamada case SKU_ID_T114_ENG: 8309f455dcSMasahiro Yamada case SKU_ID_T114_1: 8409f455dcSMasahiro Yamada default: 8509f455dcSMasahiro Yamada return TEGRA_SOC_T114; 8609f455dcSMasahiro Yamada } 8709f455dcSMasahiro Yamada break; 8809f455dcSMasahiro Yamada case CHIPID_TEGRA124: 8909f455dcSMasahiro Yamada switch (sku_id) { 9009f455dcSMasahiro Yamada case SKU_ID_T124_ENG: 9109f455dcSMasahiro Yamada default: 9209f455dcSMasahiro Yamada return TEGRA_SOC_T124; 9309f455dcSMasahiro Yamada } 9409f455dcSMasahiro Yamada break; 9509f455dcSMasahiro Yamada } 9609f455dcSMasahiro Yamada 9709f455dcSMasahiro Yamada /* unknown chip/sku id */ 9809f455dcSMasahiro Yamada printf("%s: ERROR: UNKNOWN CHIP/SKU ID COMBO (0x%02X/0x%02X)\n", 9909f455dcSMasahiro Yamada __func__, chip_id, sku_id); 10009f455dcSMasahiro Yamada return TEGRA_SOC_UNKNOWN; 10109f455dcSMasahiro Yamada } 10209f455dcSMasahiro Yamada 10309f455dcSMasahiro Yamada static void enable_scu(void) 10409f455dcSMasahiro Yamada { 10509f455dcSMasahiro Yamada struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE; 10609f455dcSMasahiro Yamada u32 reg; 10709f455dcSMasahiro Yamada 10809f455dcSMasahiro Yamada /* Only enable the SCU on T20/T25 */ 10909f455dcSMasahiro Yamada if (tegra_get_chip() != CHIPID_TEGRA20) 11009f455dcSMasahiro Yamada return; 11109f455dcSMasahiro Yamada 11209f455dcSMasahiro Yamada /* If SCU already setup/enabled, return */ 11309f455dcSMasahiro Yamada if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE) 11409f455dcSMasahiro Yamada return; 11509f455dcSMasahiro Yamada 11609f455dcSMasahiro Yamada /* Invalidate all ways for all processors */ 11709f455dcSMasahiro Yamada writel(0xFFFF, &scu->scu_inv_all); 11809f455dcSMasahiro Yamada 11909f455dcSMasahiro Yamada /* Enable SCU - bit 0 */ 12009f455dcSMasahiro Yamada reg = readl(&scu->scu_ctrl); 12109f455dcSMasahiro Yamada reg |= SCU_CTRL_ENABLE; 12209f455dcSMasahiro Yamada writel(reg, &scu->scu_ctrl); 12309f455dcSMasahiro Yamada } 12409f455dcSMasahiro Yamada 12509f455dcSMasahiro Yamada static u32 get_odmdata(void) 12609f455dcSMasahiro Yamada { 12709f455dcSMasahiro Yamada /* 12809f455dcSMasahiro Yamada * ODMDATA is stored in the BCT in IRAM by the BootROM. 12909f455dcSMasahiro Yamada * The BCT start and size are stored in the BIT in IRAM. 13009f455dcSMasahiro Yamada * Read the data @ bct_start + (bct_size - 12). This works 13109f455dcSMasahiro Yamada * on BCTs for currently supported SoCs, which are locked down. 13209f455dcSMasahiro Yamada * If this changes in new chips, we can revisit this algorithm. 13309f455dcSMasahiro Yamada */ 134*f49357baSThierry Reding unsigned long bct_start; 135*f49357baSThierry Reding u32 odmdata; 13609f455dcSMasahiro Yamada 13709f455dcSMasahiro Yamada bct_start = readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BCTPTR); 13809f455dcSMasahiro Yamada odmdata = readl(bct_start + BCT_ODMDATA_OFFSET); 13909f455dcSMasahiro Yamada 14009f455dcSMasahiro Yamada return odmdata; 14109f455dcSMasahiro Yamada } 14209f455dcSMasahiro Yamada 14309f455dcSMasahiro Yamada static void init_pmc_scratch(void) 14409f455dcSMasahiro Yamada { 14509f455dcSMasahiro Yamada struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 14609f455dcSMasahiro Yamada u32 odmdata; 14709f455dcSMasahiro Yamada int i; 14809f455dcSMasahiro Yamada 14909f455dcSMasahiro Yamada /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */ 15009f455dcSMasahiro Yamada for (i = 0; i < 23; i++) 15109f455dcSMasahiro Yamada writel(0, &pmc->pmc_scratch1+i); 15209f455dcSMasahiro Yamada 15309f455dcSMasahiro Yamada /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */ 15409f455dcSMasahiro Yamada odmdata = get_odmdata(); 15509f455dcSMasahiro Yamada writel(odmdata, &pmc->pmc_scratch20); 15609f455dcSMasahiro Yamada } 15709f455dcSMasahiro Yamada 15873169874SIan Campbell #ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE 15973169874SIan Campbell void protect_secure_section(void) 16073169874SIan Campbell { 16173169874SIan Campbell struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE; 16273169874SIan Campbell 16373169874SIan Campbell /* Must be MB aligned */ 16473169874SIan Campbell BUILD_BUG_ON(CONFIG_ARMV7_SECURE_BASE & 0xFFFFF); 16573169874SIan Campbell BUILD_BUG_ON(CONFIG_ARMV7_SECURE_RESERVE_SIZE & 0xFFFFF); 16673169874SIan Campbell 16773169874SIan Campbell writel(CONFIG_ARMV7_SECURE_BASE, &mc->mc_security_cfg0); 16873169874SIan Campbell writel(CONFIG_ARMV7_SECURE_RESERVE_SIZE >> 20, &mc->mc_security_cfg1); 16973169874SIan Campbell } 17073169874SIan Campbell #endif 17173169874SIan Campbell 17279cf644eSThierry Reding #if defined(CONFIG_ARMV7_NONSEC) 17379cf644eSThierry Reding static void smmu_flush(struct mc_ctlr *mc) 17479cf644eSThierry Reding { 17579cf644eSThierry Reding (void)readl(&mc->mc_smmu_config); 17679cf644eSThierry Reding } 17779cf644eSThierry Reding 17879cf644eSThierry Reding static void smmu_enable(void) 17979cf644eSThierry Reding { 18079cf644eSThierry Reding struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE; 18179cf644eSThierry Reding u32 value; 18279cf644eSThierry Reding 18379cf644eSThierry Reding /* 18479cf644eSThierry Reding * Enable translation for all clients since access to this register 18579cf644eSThierry Reding * is restricted to TrustZone-secured requestors. The kernel will use 18679cf644eSThierry Reding * the per-SWGROUP enable bits to enable or disable translations. 18779cf644eSThierry Reding */ 18879cf644eSThierry Reding writel(0xffffffff, &mc->mc_smmu_translation_enable_0); 18979cf644eSThierry Reding writel(0xffffffff, &mc->mc_smmu_translation_enable_1); 19079cf644eSThierry Reding writel(0xffffffff, &mc->mc_smmu_translation_enable_2); 19179cf644eSThierry Reding writel(0xffffffff, &mc->mc_smmu_translation_enable_3); 19279cf644eSThierry Reding 19379cf644eSThierry Reding /* 19479cf644eSThierry Reding * Enable SMMU globally since access to this register is restricted 19579cf644eSThierry Reding * to TrustZone-secured requestors. 19679cf644eSThierry Reding */ 19779cf644eSThierry Reding value = readl(&mc->mc_smmu_config); 19879cf644eSThierry Reding value |= TEGRA_MC_SMMU_CONFIG_ENABLE; 19979cf644eSThierry Reding writel(value, &mc->mc_smmu_config); 20079cf644eSThierry Reding 20179cf644eSThierry Reding smmu_flush(mc); 20279cf644eSThierry Reding } 20379cf644eSThierry Reding #else 20479cf644eSThierry Reding static void smmu_enable(void) 20579cf644eSThierry Reding { 20679cf644eSThierry Reding } 20779cf644eSThierry Reding #endif 20879cf644eSThierry Reding 20909f455dcSMasahiro Yamada void s_init(void) 21009f455dcSMasahiro Yamada { 21109f455dcSMasahiro Yamada /* Init PMC scratch memory */ 21209f455dcSMasahiro Yamada init_pmc_scratch(); 21309f455dcSMasahiro Yamada 21409f455dcSMasahiro Yamada enable_scu(); 21509f455dcSMasahiro Yamada 21609f455dcSMasahiro Yamada /* init the cache */ 21709f455dcSMasahiro Yamada config_cache(); 21809f455dcSMasahiro Yamada 21979cf644eSThierry Reding /* enable SMMU */ 22079cf644eSThierry Reding smmu_enable(); 22179cf644eSThierry Reding 22209f455dcSMasahiro Yamada /* init vpr */ 22309f455dcSMasahiro Yamada config_vpr(); 22409f455dcSMasahiro Yamada } 225