static void tegra_cache_smc(bool enable, u32 arg) { void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; bool need_affinity_switch; bool can_switch_affinity; bool l2x0_enabled; cpumask_t local_cpu_mask; cpumask_t saved_cpu_mask; unsigned long flags; long ret; /* * ISSUE : Some registers of PL310 controler must be written * from Secure context (and from CPU0)! * * When called form Normal we obtain an abort or do nothing. * Instructions that must be called in Secure: * - Write to Control register (L2X0_CTRL==0x100) * - Write in Auxiliary controler (L2X0_AUX_CTRL==0x104) * - Invalidate all entries (L2X0_INV_WAY==0x77C), * mandatory at boot time. * - Tag and Data RAM Latency Control Registers * (0x108 & 0x10C) must be written in Secure. */ need_affinity_switch = (smp_processor_id() != 0); can_switch_affinity = !irqs_disabled(); WARN_ON(need_affinity_switch && !can_switch_affinity); if (need_affinity_switch && can_switch_affinity) { cpu_set(0, local_cpu_mask); sched_getaffinity(0, &saved_cpu_mask); ret = sched_setaffinity(0, &local_cpu_mask); WARN_ON(ret != 0); } local_irq_save(flags); l2x0_enabled = readl_relaxed(p + L2X0_CTRL) & 1; if (enable && !l2x0_enabled) tegra_generic_smc(0xFFFFF100, 0x00000001, arg); else if (!enable && l2x0_enabled) tegra_generic_smc(0xFFFFF100, 0x00000002, arg); local_irq_restore(flags); if (need_affinity_switch && can_switch_affinity) { ret = sched_setaffinity(0, &saved_cpu_mask); WARN_ON(ret != 0); } }
static void tegra_cpu_reset_handler_enable(void) { void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_BASE); #ifndef CONFIG_TRUSTED_FOUNDATIONS void __iomem *evp_cpu_reset = IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); unsigned long reg; #endif BUG_ON(is_enabled); BUG_ON(tegra_cpu_reset_handler_size > TEGRA_RESET_HANDLER_SIZE); memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, tegra_cpu_reset_handler_size); #ifdef CONFIG_TRUSTED_FOUNDATIONS tegra_generic_smc(0xFFFFF200, TEGRA_RESET_HANDLER_BASE + tegra_cpu_reset_handler_offset, 0); #else /* NOTE: This must be the one and only write to the EVP CPU reset vector in the entire system. */ writel(TEGRA_RESET_HANDLER_BASE + tegra_cpu_reset_handler_offset, evp_cpu_reset); wmb(); reg = readl(evp_cpu_reset); /* Prevent further modifications to the physical reset vector. NOTE: Has no effect on chips prior to Tegra3. */ reg = readl(sb_ctrl); reg |= 2; writel(reg, sb_ctrl); wmb(); #endif is_enabled = true; }
static void tegra_cpu_reset_handler_enable(void) { void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_BASE); #if defined(CONFIG_TEGRA_USE_SECURE_KERNEL) unsigned long cpu_common_reset_handler = (TEGRA_RESET_HANDLER_BASE + tegra_cpu_reset_handler_offset); #else void __iomem *evp_cpu_reset = IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); unsigned long reg; #endif BUG_ON(is_enabled); BUG_ON(tegra_cpu_reset_handler_size > TEGRA_RESET_HANDLER_SIZE); memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, tegra_cpu_reset_handler_size); #if defined(CONFIG_TEGRA_USE_SECURE_KERNEL) tegra_generic_smc(0xFFFFF200, cpu_common_reset_handler, 0); #if defined(CONFIG_ARCH_TEGRA_14x_SOC) /* setup LP resume vectors */ lp_resume_vectors[PMC_LP_STATE_LP0] = virt_to_phys(tegra_resume); lp_resume_vectors[PMC_LP_STATE_LP1] = cpu_common_reset_handler; lp_resume_vectors[PMC_LP_STATE_LP1BB] = cpu_common_reset_handler; #endif #else /* NOTE: This must be the one and only write to the EVP CPU reset vector in the entire system. */ writel(TEGRA_RESET_HANDLER_BASE + tegra_cpu_reset_handler_offset, evp_cpu_reset); wmb(); reg = readl(evp_cpu_reset); /* * Prevent further modifications to the physical reset vector. * NOTE: Has no effect on chips prior to Tegra30. */ if (tegra_chip_id != TEGRA_CHIPID_TEGRA2) { reg = readl(sb_ctrl); reg |= 2; writel(reg, sb_ctrl); wmb(); } #endif is_enabled = true; }
static void tegra_cpu_reset_handler_enable(void) { void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_BASE); #if !defined(CONFIG_TEGRA_USE_SECURE_KERNEL) void __iomem *evp_cpu_reset = IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100); void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE); unsigned long reg; #endif BUG_ON(is_enabled); BUG_ON(tegra_cpu_reset_handler_size > TEGRA_RESET_HANDLER_SIZE); memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, tegra_cpu_reset_handler_size); #if defined(CONFIG_TEGRA_USE_SECURE_KERNEL) tegra_generic_smc(0x82000001, TEGRA_RESET_HANDLER_BASE + tegra_cpu_reset_handler_offset, 0); #else /* NOTE: This must be the one and only write to the EVP CPU reset vector in the entire system. */ writel(TEGRA_RESET_HANDLER_BASE + tegra_cpu_reset_handler_offset, evp_cpu_reset); wmb(); reg = readl(evp_cpu_reset); /* * Prevent further modifications to the physical reset vector. * NOTE: Has no effect on chips prior to Tegra30. */ if (tegra_get_chip_id() != TEGRA_CHIPID_TEGRA2) { reg = readl(sb_ctrl); reg |= 2; writel(reg, sb_ctrl); wmb(); } #endif is_enabled = true; }
static inline void tegra_init_cache_tz(bool init) { void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; u32 aux_ctrl; BUG_ON(smp_processor_id() != 0); if (init) { /* init L2 from secureos */ tegra_generic_smc(0xFFFFF100, 0x00000001, 0x0); /* common init called for outer call hookup */ aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); l2x0_init(p, aux_ctrl, 0xFFFFFFFF); /* use our outer_disable() routine */ outer_cache.disable = tegra_l2x0_disable_tz; } else { /* reenable L2 in secureos */ aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); tegra_generic_smc_uncached(0xFFFFF100, 0x00000004, aux_ctrl); } }