bf60x: pm: add pint suspend and resume support
authorSteven Miao <realmz6@gmail.com>
Thu, 14 Jun 2012 10:04:01 +0000 (18:04 +0800)
committerBob Liu <lliubbo@gmail.com>
Tue, 24 Jul 2012 05:39:51 +0000 (13:39 +0800)
save and restore pint sec CTL
save and restore pint registers
add pint suspend and resume when suspend to mem

Signed-off-by: Steven Miao <realmz6@gmail.com>
Signed-off-by: Bob Liu <lliubbo@gmail.com>
arch/blackfin/include/asm/gpio.h
arch/blackfin/include/asm/irq.h
arch/blackfin/mach-bf609/pm.c
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/pm.c

index 3d84d96f7c2cdac272ec7d799be295f86ad0b6a8..98d0133346b5a57042baa2e494c3906b597fd608 100644 (file)
@@ -141,6 +141,8 @@ static inline void bfin_pm_standby_restore(void)
 
 void bfin_gpio_pm_hibernate_restore(void);
 void bfin_gpio_pm_hibernate_suspend(void);
+void bfin_pint_suspend(void);
+void bfin_pint_resume(void);
 
 # if !BFIN_GPIO_PINT
 int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
index 89de539ed0100624ead2e5ea6d7f9790eed11cf2..4ae1144a457821c9349cfa0c4026e481f86a6545 100644 (file)
 /* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */
 #include <mach/irq.h>
 
+/*
+ * pm save bfin pint registers
+ */
+struct bfin_pm_pint_save {
+       u32 mask_set;
+       u32 assign;
+       u32 edge_set;
+       u32 invert_set;
+};
+
 #if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
 # define NOP_PAD_ANOMALY_05000244 "nop; nop;"
 #else
index 8d815e0571000cb39573509437d937c0bf8fcfde..0211ebd142c4420bc62884b1a02b181c01551207 100644 (file)
@@ -342,16 +342,19 @@ static int __init bf609_init_pm(void)
                                GPIO_PE12, error);
        }
 
-       error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, "gpiope12", NULL);
+       error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND
+                               | IRQF_FORCE_RESUME, "gpiope12", NULL);
        if(error < 0)
                printk(KERN_DEBUG "Unable to get irq\n");
 #endif
 
-       error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND, "cgu0 event", NULL);
+       error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND |
+                               IRQF_FORCE_RESUME, "cgu0 event", NULL);
        if(error < 0)
                printk(KERN_DEBUG "Unable to get irq\n");
 
-       error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND, "dpm0 event", NULL);
+       error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND |
+                               IRQF_FORCE_RESUME, "dpm0 event", NULL);
        if (error < 0)
                printk(KERN_DEBUG "Unable to get irq\n");
 
index 9c7d65aee27561adf2351d1b128242192352cfa7..1aac5ebaace43c2fc8373d4c5391fc895628c19e 100644 (file)
@@ -396,24 +396,6 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc)
        raw_spin_unlock(&desc->lock);
 }
 
-static int sec_suspend(void)
-{
-       return 0;
-}
-
-static void sec_resume(void)
-{
-       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
-       udelay(100);
-       bfin_write_SEC_GCTL(SEC_GCTL_EN);
-       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
-}
-
-static struct syscore_ops sec_pm_syscore_ops = {
-       .suspend = sec_suspend,
-       .resume = sec_resume,
-};
-
 #endif
 
 #ifdef CONFIG_SMP
@@ -1093,6 +1075,9 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 }
 
 #ifdef CONFIG_PM
+static struct bfin_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS];
+static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS];
+
 static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
        u32 pint_irq;
@@ -1128,6 +1113,57 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 
        return 0;
 }
+
+void bfin_pint_suspend(void)
+{
+       u32 bank;
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+               save_pint_reg[bank].mask_set = pint[bank]->mask_set;
+               save_pint_reg[bank].assign = pint[bank]->assign;
+               save_pint_reg[bank].edge_set = pint[bank]->edge_set;
+               save_pint_reg[bank].invert_set = pint[bank]->invert_set;
+       }
+}
+
+void bfin_pint_resume(void)
+{
+       u32 bank;
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+               pint[bank]->mask_set = save_pint_reg[bank].mask_set;
+               pint[bank]->assign = save_pint_reg[bank].assign;
+               pint[bank]->edge_set = save_pint_reg[bank].edge_set;
+               pint[bank]->invert_set = save_pint_reg[bank].invert_set;
+       }
+}
+
+static int sec_suspend(void)
+{
+       u32 bank;
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++)
+               save_pint_sec_ctl[bank] = bfin_read_SEC_SCTL(bank + SIC_SYSIRQ(IRQ_PINT0));
+       return 0;
+}
+
+static void sec_resume(void)
+{
+       u32 bank;
+
+       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+       udelay(100);
+       bfin_write_SEC_GCTL(SEC_GCTL_EN);
+       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++)
+               bfin_write_SEC_SCTL(bank + SIC_SYSIRQ(IRQ_PINT0), save_pint_sec_ctl[bank]);
+}
+
+static struct syscore_ops sec_pm_syscore_ops = {
+       .suspend = sec_suspend,
+       .resume = sec_resume,
+};
 #else
 # define bfin_gpio_set_wake NULL
 #endif
index ca6655e0d653903e39999dc9a2567040fee4b6bc..4878f36066c59b3a4c40c81bbe06b059d3ead58c 100644 (file)
@@ -172,6 +172,8 @@ int bfin_pm_suspend_mem_enter(void)
 
        bfin_gpio_pm_hibernate_suspend();
 
+       bfin_pint_suspend();
+
 #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
        flushinv_all_dcache();
 #endif
@@ -190,6 +192,8 @@ int bfin_pm_suspend_mem_enter(void)
        _enable_icplb();
        _enable_dcplb();
 
+       bfin_pint_resume();
+
        bfin_gpio_pm_hibernate_restore();
        blackfin_dma_resume();