示例#1
0
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);
	}
}
示例#2
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;
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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);
	}
}