static inline void omap5_irq_save_context(void) { u32 i, val; for (i = 0; i < irq_banks; i++) { /* Save the CPUx interrupt mask for IRQ 0 to 159 */ val = wakeupgen_readl(i, 0); sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i); val = wakeupgen_readl(i, 1); sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i); sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i); sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i); } /* Save AuxBoot* registers */ val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET); val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET); /* Set the Backup Bit Mask status */ val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); val |= SAR_BACKUP_STATUS_WAKEUPGEN; __raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); }
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); }
/* * 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); /* * 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; }