/*
 * 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__);
	}
}
/*
 * 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);

	irq_hotplug_init();
	irq_pm_init();

	return 0;
}
/**
 * omap_wakeupgen_check_interrupts() - sanity check for pending interrupts
 * @report_string:	what is used to report
 *
 * Return false if there are no pending interrupts, else, if there
 * are pending interrupts, return true.
 *
 * NOTE: if report_string is not NULL, then logic will search beyond
 * the first occurance and report all such pending events. if report_string
 * is NULL, search returns true at the very first occurance of event.
 */
bool omap_wakeupgen_check_interrupts(char *report_string)
{
	int i, k;
	u32 gica, wakea_c0, wakea_c1;
	int ret = false;

	for (i = 0; i < spi_irq_banks - 1; i++) {
		gica = gic_readl(GIC_DIST_PENDING_SET, i + 1);

		/*
		 * HACK: On OMAP4 GP devices 8th (secure) interrupt
		 * is constantly pending and thus preventing suspend.
		 * The source of this interrupt is CONTROL_CORE_SEC_STATUS
		 * register. This register can't be cleared on GP device
		 * because it is accessible for write only from secure
		 * privileged mode. So just ignore 8th interrupt in this check.
		 */
		if (i == 0 && cpu_is_omap44xx() &&
		    (omap_type() == OMAP2_DEVICE_TYPE_GP))
			gica &= ~(1 << 8);

		wakea_c0 = wakeupgen_readl(i, 0);
		wakea_c1 = wakeupgen_readl(i, 1);

		/* If there is nothing pending, nothing to report */
		if (!gica)
			continue;

		/* report register dump for debug */
		pr_debug("%s: %s: IRQ Bank = %d GIC Pending status=0x%08x "
		       "GIC Enable = 0x%08x Wakeupgen Config ="
		       "cpu0=0x%08x cpu1=0x%08x\n",
		       __func__, report_string, i, gica,
		       gic_readl(GIC_DIST_ENABLE_SET, i + 1),
		       wakea_c0, wakea_c1);

		k = 0;
		while (gica) {
			if (gica & 0x1) {
				struct irq_desc *desc;
				const char *name, *wc0, *wc1;
				int irq;

				/* Return true if pending interrupts */
				ret = true;

				/*
				 * we need to search for more ONLY if
				 * there is something to report
				 */
				if (!report_string)
					goto quit_search;

				/* Grab the current wakeup state for CPU0,1 */
				wc0 = (wakea_c0 & 0x1) ? "yes" : "no";
				wc1 = (wakea_c1 & 0x1) ? "yes" : "no";
				/* Since we skip GIC PPI and SGI, base 32 */
				irq = 32 + i * 32 + k;
				desc = irq_to_desc(irq);
				if (desc && desc->action &&
				    desc->action->name) {
					name = desc->action->name;
				} else if (irq == OMAP44XX_IRQ_PRCM) {
					name = NULL;
					print_prcm_wakeirq(irq, report_string);
				} else {
					name = "unknown";
				}

				if (name)
					pr_info("%s: IRQ %d(%s)(OMAP-IRQ=%d) "\
						"Pending! Wakeup Enable: "\
						"CPU0=%s,CPU1=%s\n",
						report_string, irq, name,
						(irq - 32), wc0, wc1);
			}
			k++;
			gica >>= 1;
			wakea_c0 >>= 1;
			wakea_c1 >>= 1;
		}
	}

quit_search:
	return ret;
}
static void gic_save_context(void)
{
	u8 i;
	u32 val;

	offset= 0;
	/* Save CPU 0 Interrupt Set Enable register */
	val = gic_readl(GIC_DIST_ENABLE_SET, 0);
	gic_context[offset] = val;
	offset++;

	/* Save all SPI Set Enable register */
	for (i = 0; i < max_spi_reg; i++) {
		val = gic_readl(GIC_DIST_ENABLE_SET + SPI_ENABLE_SET_OFFSET, i);
		gic_context[offset] = val;
		offset++;
	}
	
	/* Save SGI priority registers (Software Generated Interrupt) */
	for (i = 0; i < 4; i++) {
		val = gic_readl(GIC_DIST_PRI, i);

		/* Save the priority bits of the Interrupts */
		gic_context[offset] = val;
		offset++;
	}
	/* Save PPI priority registers (Private Peripheral Intterupts) */
	for (i = 0; i < 4; i++) {
		val = gic_readl(GIC_DIST_PRI + PPI_PRI_OFFSET, i);

		/* Save the priority bits of the Interrupts */
		gic_context[offset] = val;
		offset++;
	}
	/* SPI priority registers - 4 interrupts/register */
	for (i = 0; i < (max_spi_irq / 4); i++) {
		val = gic_readl((GIC_DIST_PRI + SPI_PRI_OFFSET), i);
		gic_context[offset] = val;
		offset++;
	}
	
	/* SPI Interrupt Target registers - 4 interrupts/register
	 * ICDIPTR0 ~ ICDIPTR7 are read-only
	 */
	for (i = 0; i < (max_spi_irq / 4); i++) {
		val = gic_readl((GIC_DIST_TARGET + SPI_TARGET_OFFSET), i);
		gic_context[offset] = val;
		offset++;
	}

	/* SPI Interrupt Congigeration eegisters- 16 interrupts/register */
	for (i = 0; i < (max_spi_irq / 16); i++) {
		val = gic_readl((GIC_DIST_CONFIG + SPI_CONFIG_OFFSET), i);
		gic_context[offset] = val;
		offset++;
	}
	offset--;

#ifdef CONFIG_SPRD_PM_DEBUG
	printk("****** %s, save %d gic registers \n ", __func__, offset);
	dump_gic_saved_context();
#endif
	return;
}
Example #5
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;
}
Example #6
0
/**
 * omap_wakeupgen_check_interrupts() - sanity check for pending interrupts
 * @report_string:	what is used to report
 *
 * Return false if there are no pending interrupts, else, if there
 * are pending interrupts, return true.
 *
 * NOTE: if report_string is not NULL, then logic will search beyond
 * the first occurance and report all such pending events. if report_string
 * is NULL, search returns true at the very first occurance of event.
 */
bool omap_wakeupgen_check_interrupts(char *report_string)
{
	int i, k;
	u32 gica, wakea_c0, wakea_c1;
	int ret = false;

	for (i = 0; i < spi_irq_banks - 1; i++) {
		gica = gic_readl(GIC_DIST_PENDING_SET, i + 1);
		wakea_c0 = wakeupgen_readl(i, 0);
		wakea_c1 = wakeupgen_readl(i, 1);

		/* If there is nothing pending, nothing to report */
		if (!gica)
			continue;

		/* report register dump for debug */
		pr_debug("%s: %s: IRQ Bank = %d GIC Pending status=0x%08x "
		       "GIC Enable = 0x%08x Wakeupgen Config ="
		       "cpu0=0x%08x cpu1=0x%08x\n",
		       __func__, report_string, i, gica,
		       gic_readl(GIC_DIST_ENABLE_SET, i + 1),
		       wakea_c0, wakea_c1);

		k = 0;
		while (gica) {
			if (gica & 0x1) {
				struct irq_desc *desc;
				const char *name, *wc0, *wc1;
				int irq;

				/* Return true if pending interrupts */
				ret = true;

				/*
				 * we need to search for more ONLY if
				 * there is something to report
				 */
				if (!report_string)
					goto quit_search;

				/* Grab the current wakeup state for CPU0,1 */
				wc0 = (wakea_c0 & 0x1) ? "yes" : "no";
				wc1 = (wakea_c1 & 0x1) ? "yes" : "no";
				/* Since we skip GIC PPI and SGI, base 32 */
				irq = 32 + i * 32 + k;
				desc = irq_to_desc(irq);
				if (desc && desc->action &&
				    desc->action->name) {
					name = desc->action->name;
				} else if (irq == OMAP44XX_IRQ_PRCM) {
					name = NULL;
					print_prcm_wakeirq(irq, report_string);
				} else {
					name = "unknown";
				}

				if (name)
					pr_info("%s: IRQ %d(%s)(OMAP-IRQ=%d) "\
						"Pending! Wakeup Enable: "\
						"CPU0=%s,CPU1=%s\n",
						report_string, irq, name,
						(irq - 32), wc0, wc1);
			}
			k++;
			gica >>= 1;
			wakea_c0 >>= 1;
			wakea_c1 >>= 1;
		}
	}

quit_search:
	return ret;
}