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); }
/* * 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); }
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); }
static void _wakeupgen_save_masks(unsigned int cpu) { u8 i; for (i = 0; i < irq_banks; i++) per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu); }
static void _wakeupgen_save_masks(unsigned int cpu) { u8 i; for (i = 0; i < NR_REG_BANKS; i++) per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu); }
static void _wakeupgen_set(unsigned int irq, unsigned int cpu) { u32 val, bit_number; u8 i; if (_wakeupgen_get_irq_info(irq, &bit_number, &i)) return; val = wakeupgen_readl(i, cpu); val |= BIT(bit_number); wakeupgen_writel(val, i, cpu); }
/** * 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; }
/** * 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; }