|
@@ -325,3 +325,127 @@ static void irq_save_secure_context(void)
|
|
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
|
|
|
+ unsigned long action, void *hcpu)
|
|
|
+{
|
|
|
+ unsigned int cpu = (unsigned int)hcpu;
|
|
|
+
|
|
|
+ switch (action) {
|
|
|
+ case CPU_ONLINE:
|
|
|
+ wakeupgen_irqmask_all(cpu, 0);
|
|
|
+ break;
|
|
|
+ case CPU_DEAD:
|
|
|
+ wakeupgen_irqmask_all(cpu, 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return NOTIFY_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block __refdata irq_hotplug_notifier = {
|
|
|
+ .notifier_call = irq_cpu_hotplug_notify,
|
|
|
+};
|
|
|
+
|
|
|
+static void __init irq_hotplug_init(void)
|
|
|
+{
|
|
|
+ register_hotcpu_notifier(&irq_hotplug_notifier);
|
|
|
+}
|
|
|
+#else
|
|
|
+static void __init irq_hotplug_init(void)
|
|
|
+{}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef CONFIG_CPU_PM
|
|
|
+static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
|
|
+{
|
|
|
+ switch (cmd) {
|
|
|
+ case CPU_CLUSTER_PM_ENTER:
|
|
|
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP)
|
|
|
+ irq_save_context();
|
|
|
+ else
|
|
|
+ irq_save_secure_context();
|
|
|
+ break;
|
|
|
+ case CPU_CLUSTER_PM_EXIT:
|
|
|
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP)
|
|
|
+ irq_sar_clear();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return NOTIFY_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block irq_notifier_block = {
|
|
|
+ .notifier_call = irq_notifier,
|
|
|
+};
|
|
|
+
|
|
|
+static void __init irq_pm_init(void)
|
|
|
+{
|
|
|
+ /* FIXME: Remove this when MPU OSWR support is added */
|
|
|
+ if (!soc_is_omap54xx())
|
|
|
+ cpu_pm_register_notifier(&irq_notifier_block);
|
|
|
+}
|
|
|
+#else
|
|
|
+static void __init irq_pm_init(void)
|
|
|
+{}
|
|
|
+#endif
|
|
|
+
|
|
|
+void __iomem *omap_get_wakeupgen_base(void)
|
|
|
+{
|
|
|
+ return wakeupgen_base;
|
|
|
+}
|
|
|
+
|
|
|
+int omap_secure_apis_support(void)
|
|
|
+{
|
|
|
+ return omap_secure_apis;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Initialise the wakeupgen module.
|
|
|
+ */
|
|
|
+int __init omap_wakeupgen_init(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ unsigned int boot_cpu = smp_processor_id();
|
|
|
+
|
|
|
+ /* 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;
|
|
|
+ omap_secure_apis = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 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;
|
|
|
+
|
|
|
+ irq_hotplug_init();
|
|
|
+ irq_pm_init();
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|