Ejemplo n.º 1
0
/*
 * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
 * ROM code. WakeupGen IP is integrated along with GIC to manage the
 * interrupt wakeups from CPU low power states. It manages
 * masking/unmasking of Shared peripheral interrupts(SPI). So the
 * interrupt enable/disable control should be in sync and consistent
 * at WakeupGen and GIC so that interrupts are not lost.
 */
static void irq_save_context(void)
{
	if (!sar_base)
		sar_base = omap4_get_sar_ram_base();

	if (cpu_is_omap54xx())
		omap5_irq_save_context();
	else
		omap4_irq_save_context();
}
static void irq_save_context(void)
{
	u32 i, val;

	if (omap_rev() == OMAP4430_REV_ES1_0)
		return;

	if (!sar_base)
		sar_base = omap4_get_sar_ram_base();

	for (i = 0; i < NR_REG_BANKS; i++) {
		/*                                               */
		val = wakeupgen_readl(i, 0);
		sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
		val = wakeupgen_readl(i, 1);
		sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);

		/*
                                                        
                                                          
                                                          
                                                           
                                                   
   */
		sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
		sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
	}

	/*                         */
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);

	/*                               */
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);

	/*                               */
	val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
	__raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET);
	val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
	__raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET);

	/*                                */
	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
	val |= SAR_BACKUP_STATUS_WAKEUPGEN;
	__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
}
/*
 * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
 * ROM code. WakeupGen IP is integrated along with GIC to manage the
 * interrupt wakeups from CPU low power states. It manages
 * masking/unmasking of Shared peripheral interrupts(SPI). So the
 * interrupt enable/disable control should be in sync and consistent
 * at WakeupGen and GIC so that interrupts are not lost.
 */
static void irq_save_context(void)
{
	u32 i, val;

	if (omap_rev() == OMAP4430_REV_ES1_0)
		return;

	if (!sar_base)
		sar_base = omap4_get_sar_ram_base();

	for (i = 0; i < NR_REG_BANKS; i++) {
		/* Save the CPUx interrupt mask for IRQ 0 to 127 */
		val = wakeupgen_readl(i, 0);
		sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
		val = wakeupgen_readl(i, 1);
		sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);

		/*
		 * Disable the secure interrupts for CPUx. The restore
		 * code blindly restores secure and non-secure interrupt
		 * masks from SAR RAM. Secure interrupts are not suppose
		 * to be enabled from HLOS. So overwrite the SAR location
		 * so that the secure interrupt remains disabled.
		 */
		sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
		sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
	}

	/* Save AuxBoot* registers */
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);

	/* Save SyncReq generation logic */
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);

	/* Save SyncReq generation logic */
	val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
	__raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET);
	val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
	__raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET);

	/* Set the Backup Bit Mask status */
	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
	val |= SAR_BACKUP_STATUS_WAKEUPGEN;
	__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
}
Ejemplo n.º 4
0
/*
 * Continue initialise the wakeupgen initialization after sar
 * is initialized
 */
void __init omap_wakeupgen_init_finish(void)
{
	int i;
	unsigned int max_spi_reg;
	/*
	 * Find out how many interrupts are supported.
	 * OMAP4 supports max of 128 SPIs where as GIC can support
	 * up to 1020 interrupt sources. On OMAP4, maximum SPIs are
	 * fused in DIST_CTR bit-fields as 128. Hence the code is safe
	 * from reserved register writes since its well within 1020.
	 */
	max_spi_reg = gic_readl(GIC_DIST_CTR, 0) & 0x1f;

	/*
	 * Set CPU0 GIC backup flag permanently for omap4460/70 GP,
	 * this is needed because of the ROM code bug that breaks
	 * GIC during wakeup from device off. This errata fix also
	 * clears the GIC save area during init to prevent restoring
	 * garbage to the GIC.
	 */
	if ((cpu_is_omap446x() || cpu_is_omap447x()) &&
	    omap_type() == OMAP2_DEVICE_TYPE_GP)
		pm44xx_errata |= PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx;

	if (cpu_is_omap44xx() && (omap_type() == OMAP2_DEVICE_TYPE_GP)) {
		sar_base = omap4_get_sar_ram_base();

		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx))
			for (i = SAR_BACKUP_STATUS_OFFSET;
			     i < WAKEUPGENENB_OFFSET_CPU0; i += 4)
				sar_writel(0, i, 0);

		sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_CPU0_OFFSET, 0);
		sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_CPU1_OFFSET, 0);
		for (i = 0; i < max_spi_reg; i++)
			sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_SPI_OFFSET,
				   i);

		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx))
			__raw_writel(SAR_BACKUP_STATUS_GIC_CPU0,
				     sar_base + SAR_BACKUP_STATUS_OFFSET);

	} else {
		l3_main_3_oh = omap_hwmod_lookup("l3_main_3");
		if (!l3_main_3_oh)
			pr_err("%s: failed to get l3_main_3_oh\n", __func__);
	}
}
Ejemplo n.º 5
0
/*
 * For kexec, we must set CPU1_WAKEUP_NS_PA_ADDR to point to
 * current kernel's secondary_startup() early before
 * clockdomains_init(). Otherwise clockdomain_init() can
 * wake CPU1 and cause a hang.
 */
void __init omap4_mpuss_early_init(void)
{
	unsigned long startup_pa;

	if (!cpu_is_omap44xx())
		return;

	sar_base = omap4_get_sar_ram_base();

	if (cpu_is_omap443x())
		startup_pa = virt_to_phys(omap4_secondary_startup);
	else
		startup_pa = virt_to_phys(omap4460_secondary_startup);

	writel_relaxed(startup_pa, sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
}
Ejemplo n.º 6
0
		.controller_data = &lte_mcspi_config,
		.platform_data = &lte_modem_bootloader_pdata,
		.max_speed_hz = LTE_MODEM_SPI_MAX_HZ,
		.bus_num = LTE_MODEM_SPI_BUS_NUM,
		.chip_select = LTE_MODEM_SPI_CS,
		.mode = SPI_MODE_0,
	},
};

static int tuna_notifier_call(struct notifier_block *this,
					unsigned long code, void *_cmd)
{
	void __iomem *sar_base;
	unsigned int flag = REBOOT_FLAG_NORMAL;

	sar_base = omap4_get_sar_ram_base();

	if (!sar_base)
		return notifier_from_errno(-ENOMEM);

	if (code == SYS_RESTART) {
		if (_cmd) {
			if (!strcmp(_cmd, "recovery"))
				flag = REBOOT_FLAG_RECOVERY;
			else if (!strcmp(_cmd, "bootloader"))
				flag = REBOOT_FLAG_FASTBOOT;
		}
	} else if (code == SYS_POWER_OFF) {
		flag = REBOOT_FLAG_POWER_OFF;
	}
Ejemplo n.º 7
0
/*
 * Initialise OMAP4 MPUSS
 */
int __init omap4_mpuss_init(void)
{
	struct omap4_cpu_pm_info *pm_info;

	if (omap_rev() == OMAP4430_REV_ES1_0) {
		WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
		return -ENODEV;
	}

	sar_base = omap4_get_sar_ram_base();

	/* Initilaise per CPU PM information */
	pm_info = &per_cpu(omap4_pm_info, 0x0);
	pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
	pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
	pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
	if (!pm_info->pwrdm) {
		pr_err("Lookup failed for CPU0 pwrdm\n");
		return -ENODEV;
	}

	/* Clear CPU previous power domain state */
	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
	cpu_clear_prev_logic_pwrst(0);

	/* Initialise CPU0 power domain state to ON */
	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);

	pm_info = &per_cpu(omap4_pm_info, 0x1);
	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
	if (!pm_info->pwrdm) {
		pr_err("Lookup failed for CPU1 pwrdm\n");
		return -ENODEV;
	}

	/* Clear CPU previous power domain state */
	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
	cpu_clear_prev_logic_pwrst(1);

	/* Initialise CPU1 power domain state to ON */
	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);

	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
	if (!mpuss_pd) {
		pr_err("Failed to lookup MPUSS power domain\n");
		return -ENODEV;
	}
	pwrdm_clear_all_prev_pwrst(mpuss_pd);
	mpuss_clear_prev_logic_pwrst();

	/* Save device type on scratchpad for low level code to use */
	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
		__raw_writel(1, sar_base + OMAP_TYPE_OFFSET);
	else
		__raw_writel(0, sar_base + OMAP_TYPE_OFFSET);

	save_l2x0_context();

	return 0;
}
Ejemplo n.º 8
0
/*
 * Initialise the wakeupgen module.
 */
int __init omap_wakeupgen_init(void)
{
	int i;
	unsigned int boot_cpu = smp_processor_id();
	unsigned int max_spi_reg;

	/* Not supported on OMAP4 ES1.0 silicon */
	if (omap_rev() == OMAP4430_REV_ES1_0) {
		WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
		return -EPERM;
	}

	/* Static mapping, never released */
	wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
	if (WARN_ON(!wakeupgen_base))
		return -ENOMEM;

	if (cpu_is_omap44xx()) {
		irq_banks = OMAP4_NR_BANKS;
		max_irqs = OMAP4_NR_IRQS;
		secure_api_index = OMAP4_HAL_SAVEGIC_INDEX;
		secure_hw_api_index = OMAP4_HAL_SAVEHW_INDEX;
		secure_hal_save_all_api_index = OMAP4_HAL_SAVEALL_INDEX;
		secure_ram_api_index  = OMAP4_HAL_SAVESECURERAM_INDEX;
	} else if (cpu_is_omap54xx()) {
		secure_api_index = OMAP5_HAL_SAVEGIC_INDEX;
		secure_hw_api_index = OMAP5_HAL_SAVEHW_INDEX;
		secure_hal_save_all_api_index = OMAP5_HAL_SAVEALL_INDEX;
		secure_ram_api_index  = OMAP5_HAL_SAVESECURERAM_INDEX;
	}

	/* Clear all IRQ bitmasks at wakeupGen level */
	for (i = 0; i < irq_banks; i++) {
		wakeupgen_writel(0, i, CPU0_ID);
		wakeupgen_writel(0, i, CPU1_ID);
	}

	/*
	 * Override GIC architecture specific functions to add
	 * OMAP WakeupGen interrupt controller along with GIC
	 */
	gic_arch_extn.irq_mask = wakeupgen_mask;
	gic_arch_extn.irq_unmask = wakeupgen_unmask;
	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;

	/*
	 * FIXME: Add support to set_smp_affinity() once the core
	 * GIC code has necessary hooks in place.
	 */

	/* Associate all the IRQs to boot CPU like GIC init does. */
	for (i = 0; i < max_irqs; i++)
		irq_target_cpu[i] = boot_cpu;

	/*
	 * Find out how many interrupts are supported.
	 * OMAP4 supports max of 128 SPIs where as GIC can support
	 * up to 1020 interrupt sources. On OMAP4, maximum SPIs are
	 * fused in DIST_CTR bit-fields as 128. Hence the code is safe
	 * from reserved register writes since its well within 1020.
	 */
	max_spi_reg = gic_readl(GIC_DIST_CTR, 0) & 0x1f;

	spi_irq_banks = min(max_spi_reg, irq_banks);

	/*
	 * Set CPU0 GIC backup flag permanently for omap4460 GP,
	 * this is needed because of the ROM code bug that breaks
	 * GIC during wakeup from device off. This errata fix also
	 * clears the GIC save area during init to prevent restoring
	 * garbage to the GIC.
	 */
	if (cpu_is_omap446x() && omap_type() == OMAP2_DEVICE_TYPE_GP)
		pm44xx_errata |= PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx;

	if (cpu_is_omap44xx() && (omap_type() == OMAP2_DEVICE_TYPE_GP)) {
		sar_base = omap4_get_sar_ram_base();

		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx))
			for (i = SAR_BACKUP_STATUS_OFFSET;
			     i < WAKEUPGENENB_OFFSET_CPU0; i += 4)
				sar_writel(0, i, 0);

		sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_CPU0_OFFSET, 0);
		sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_CPU1_OFFSET, 0);
		for (i = 0; i < max_spi_reg; i++)
			sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_SPI_OFFSET,
				   i);

		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx))
			__raw_writel(SAR_BACKUP_STATUS_GIC_CPU0,
				     sar_base + SAR_BACKUP_STATUS_OFFSET);

	} else {
		l3_main_3_oh = omap_hwmod_lookup("l3_main_3");
		if (!l3_main_3_oh)
			pr_err("%s: failed to get l3_main_3_oh\n", __func__);
	}

	irq_hotplug_init();
	irq_pm_init();

	return 0;
}
Ejemplo n.º 9
0
/*
 * Initialise OMAP4 MPUSS
 */
int __init omap4_mpuss_init(void)
{
	struct omap4_cpu_pm_info *pm_info;

	if (omap_rev() == OMAP4430_REV_ES1_0) {
		WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
		return -ENODEV;
	}

	if (cpu_is_omap44xx())
		sar_base = omap4_get_sar_ram_base();

	/* Initilaise per CPU PM information */
	pm_info = &per_cpu(omap4_pm_info, 0x0);
	if (sar_base) {
		pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
		pm_info->wkup_sar_addr = sar_base +
					CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
		pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
	}
	pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
	if (!pm_info->pwrdm) {
		pr_err("Lookup failed for CPU0 pwrdm\n");
		return -ENODEV;
	}

	/* Clear CPU previous power domain state */
	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
	cpu_clear_prev_logic_pwrst(0);

	/* Initialise CPU0 power domain state to ON */
	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);

	pm_info = &per_cpu(omap4_pm_info, 0x1);
	if (sar_base) {
		pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
		pm_info->wkup_sar_addr = sar_base +
					CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
		pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
	}

	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
	if (!pm_info->pwrdm) {
		pr_err("Lookup failed for CPU1 pwrdm\n");
		return -ENODEV;
	}

	/* Clear CPU previous power domain state */
	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
	cpu_clear_prev_logic_pwrst(1);

	/* Initialise CPU1 power domain state to ON */
	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);

	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
	if (!mpuss_pd) {
		pr_err("Failed to lookup MPUSS power domain\n");
		return -ENODEV;
	}
	pwrdm_clear_all_prev_pwrst(mpuss_pd);
	mpuss_clear_prev_logic_pwrst();

	if (sar_base) {
		/* Save device type on scratchpad for low level code to use */
		writel_relaxed((omap_type() != OMAP2_DEVICE_TYPE_GP) ? 1 : 0,
			       sar_base + OMAP_TYPE_OFFSET);
		save_l2x0_context();
	}

	if (cpu_is_omap44xx()) {
		omap_pm_ops.finish_suspend = omap4_finish_suspend;
		omap_pm_ops.resume = omap4_cpu_resume;
		omap_pm_ops.scu_prepare = scu_pwrst_prepare;
		omap_pm_ops.hotplug_restart = omap4_secondary_startup;
		cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET;
	} else if (soc_is_omap54xx() || soc_is_dra7xx()) {
		cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET;
		enable_mercury_retention_mode();
	}

	if (cpu_is_omap446x())
		omap_pm_ops.hotplug_restart = omap4460_secondary_startup;

	return 0;
}
Ejemplo n.º 10
0
void lge_omap4_prm_global_warm_sw_reset(const char *cmd)
{
    void __iomem *sar_base;
    u32 v = 0;

    v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
                                OMAP4_RM_RSTCTRL);

    sar_base = omap4_get_sar_ram_base();

    if (cmd != NULL) {
        if (!strcmp(cmd, "recovery")) {
            /* Save reboot mode in scratch memory */
            restart_reason = 0x77665502;
            v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
        } else if (!strcmp(cmd, "download")) {
            /* use cold boot for web download due to USB issue */
            v |= OMAP4430_RST_GLOBAL_COLD_SW_MASK;
        } else if (!strcmp(cmd, "pmic")) {
            /* use PMIC reset */
            twl6030_pm_i2c_write_u8(0x47, 0x06);
        } else if (!strcmp(cmd, "pmicoff")) {
            if (sar_base) {
                __raw_writel(restart_reason, sar_base + 0xA0C);
                printk("Restart reason: 0x%x\n", __raw_readl(sar_base + 0xA0C));
            }
            /* use PMIC off */
            twl6030_pm_i2c_write_u8(0x07, 0x06);
        } else if (!strcmp(cmd, "hidden")) {
            restart_reason = 0x729F2000;
            v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
        } else {
            printk(KERN_EMERG "reboot: non-supported mode [%s]\n",
                   cmd);
            v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
        }
    }
    else {
        v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
    }

    /* save restart reason in scratch memory for bootloader to read it */
    if (sar_base) {
        __raw_writel(restart_reason, sar_base + 0xA0C);
        printk("Restart reason: 0x%x\n", __raw_readl(sar_base + 0xA0C));
    }
    else {
        printk(KERN_EMERG "omap4_get_sar_ram_base failed\n");
    }

    /* clear previous reboot status */
    omap4_prm_write_inst_reg(0xfff, OMAP4430_PRM_DEVICE_INST,
                             OMAP4_RM_RSTST);

    omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
                             OMAP4_RM_RSTCTRL);

    /* OCP barrier */
    v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
                                OMAP4_RM_RSTCTRL);
}