summaryrefslogtreecommitdiff
path: root/arch/blackfin/mach-common
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2008-02-08 23:12:37 +0300
committerBryan Wu <bryan.wu@analog.com>2008-02-08 23:12:37 +0300
commitcfefe3c683e0d14c9ce3aeb883c55c7f30c20183 (patch)
tree77434010fc64f64606e893ce7b6f73243073ebb0 /arch/blackfin/mach-common
parent2c4f829b0ce3d2fb447acca823e141094a50daa5 (diff)
downloadlinux-cfefe3c683e0d14c9ce3aeb883c55c7f30c20183.tar.xz
[Blackfin] arch: hook up set_irq_wake in Blackfin's irq code
- Add support for irq_wake on system and gpio interrupts - Remove outdated kernel options - Add option to select default PM mode - Fix various places where SIC_IWRx was only handled partially Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r--arch/blackfin/mach-common/dpmc.S32
-rw-r--r--arch/blackfin/mach-common/ints-priority.c126
-rw-r--r--arch/blackfin/mach-common/pm.c44
3 files changed, 168 insertions, 34 deletions
diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S
index b82c096e1980..b80ddd8b232d 100644
--- a/arch/blackfin/mach-common/dpmc.S
+++ b/arch/blackfin/mach-common/dpmc.S
@@ -191,6 +191,9 @@ ENTRY(_sleep_mode)
call _test_pll_locked;
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
P0.H = hi(PLL_CTL);
@@ -237,6 +240,10 @@ ENTRY(_deep_sleep)
CLI R4;
+ R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
call _set_dram_srfs;
@@ -261,6 +268,9 @@ ENTRY(_deep_sleep)
call _test_pll_locked;
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
P0.H = hi(PLL_CTL);
@@ -286,7 +296,13 @@ ENTRY(_sleep_deeper)
CLI R4;
P3 = R0;
+ P4 = R1;
+ P5 = R2;
+
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
call _set_dram_srfs; /* Set SDRAM Self Refresh */
@@ -327,6 +343,8 @@ ENTRY(_sleep_deeper)
call _test_pll_locked;
R0 = P3;
+ R1 = P4;
+ R3 = P5;
call _set_sic_iwr; /* Set Awake from IDLE */
P0.H = hi(PLL_CTL);
@@ -340,6 +358,9 @@ ENTRY(_sleep_deeper)
call _test_pll_locked;
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr; /* Set Awake from IDLE PLL */
P0.H = hi(VR_CTL);
@@ -417,14 +438,23 @@ ENTRY(_unset_dram_srfs)
RTS;
ENTRY(_set_sic_iwr)
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
P0.H = hi(SIC_IWR0);
P0.L = lo(SIC_IWR0);
+ P1.H = hi(SIC_IWR1);
+ P1.L = lo(SIC_IWR1);
+ [P1] = R1;
+#if defined(CONFIG_BF54x)
+ P1.H = hi(SIC_IWR2);
+ P1.L = lo(SIC_IWR2);
+ [P1] = R2;
+#endif
#else
P0.H = hi(SIC_IWR);
P0.L = lo(SIC_IWR);
#endif
[P0] = R0;
+
SSYNC;
RTS;
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 166dbba0c396..81d00183ae91 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -1,5 +1,5 @@
/*
- * File: arch/blackfin/mach-common/ints-priority-sc.c
+ * File: arch/blackfin/mach-common/ints-priority.c
* Based on:
* Author:
*
@@ -13,7 +13,7 @@
* 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
* 2003 Metrowerks/Motorola
* 2003 Bas Vermeulen <bas@buyways.nl>
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -69,6 +69,10 @@ unsigned long irq_flags = 0x1f;
/* The number of spurious interrupts */
atomic_t num_spurious;
+#ifdef CONFIG_PM
+unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */
+#endif
+
struct ivgx {
/* irq number for request_irq, available in mach-bf533/irq.h */
unsigned int irqno;
@@ -178,6 +182,27 @@ static void bfin_internal_unmask_irq(unsigned int irq)
SSYNC();
}
+#ifdef CONFIG_PM
+int bfin_internal_set_wake(unsigned int irq, unsigned int state)
+{
+ unsigned bank, bit;
+ unsigned long flags;
+ bank = (irq - (IRQ_CORETMR + 1)) / 32;
+ bit = (irq - (IRQ_CORETMR + 1)) % 32;
+
+ local_irq_save(flags);
+
+ if (state)
+ bfin_sic_iwr[bank] |= (1 << bit);
+ else
+ bfin_sic_iwr[bank] &= ~(1 << bit);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+#endif
+
static struct irq_chip bfin_core_irqchip = {
.ack = ack_noop,
.mask = bfin_core_mask_irq,
@@ -188,6 +213,9 @@ static struct irq_chip bfin_internal_irqchip = {
.ack = ack_noop,
.mask = bfin_internal_mask_irq,
.unmask = bfin_internal_unmask_irq,
+#ifdef CONFIG_PM
+ .set_wake = bfin_internal_set_wake,
+#endif
};
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
@@ -434,6 +462,20 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}
+#ifdef CONFIG_PM
+int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+{
+ unsigned gpio = irq_to_gpio(irq);
+
+ if (state)
+ gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
+ else
+ gpio_pm_wakeup_free(gpio);
+
+ return 0;
+}
+#endif
+
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
@@ -441,7 +483,10 @@ static struct irq_chip bfin_gpio_irqchip = {
.unmask = bfin_gpio_unmask_irq,
.set_type = bfin_gpio_irq_type,
.startup = bfin_gpio_irq_startup,
- .shutdown = bfin_gpio_irq_shutdown
+ .shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+ .set_wake = bfin_gpio_set_wake,
+#endif
};
static void bfin_demux_gpio_irq(unsigned int inta_irq,
@@ -487,7 +532,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
}
if (search) {
- for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) {
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
irq += i;
mask = get_gpiop_data(i) &
@@ -763,6 +808,74 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}
+#ifdef CONFIG_PM
+u32 pint_saved_masks[NR_PINT_SYS_IRQS];
+u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
+
+int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+{
+ u32 pint_irq;
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 bank = PINT_2_BANK(pint_val);
+ u32 pintbit = PINT_BIT(pint_val);
+
+ switch (bank) {
+ case 0:
+ pint_irq = IRQ_PINT0;
+ break;
+ case 2:
+ pint_irq = IRQ_PINT2;
+ break;
+ case 3:
+ pint_irq = IRQ_PINT3;
+ break;
+ case 1:
+ pint_irq = IRQ_PINT1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ bfin_internal_set_wake(pint_irq, state);
+
+ if (state)
+ pint_wakeup_masks[bank] |= pintbit;
+ else
+ pint_wakeup_masks[bank] &= ~pintbit;
+
+ return 0;
+}
+
+u32 bfin_pm_setup(void)
+{
+ u32 val, i;
+
+ for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
+ val = pint[i]->mask_clear;
+ pint_saved_masks[i] = val;
+ if (val ^ pint_wakeup_masks[i]) {
+ pint[i]->mask_clear = val;
+ pint[i]->mask_set = pint_wakeup_masks[i];
+ }
+ }
+
+ return 0;
+}
+
+void bfin_pm_restore(void)
+{
+ u32 i, val;
+
+ for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
+ val = pint_saved_masks[i];
+ if (val ^ pint_wakeup_masks[i]) {
+ pint[i]->mask_clear = pint[i]->mask_clear;
+ pint[i]->mask_set = val;
+ }
+ }
+}
+#endif
+
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
@@ -770,7 +883,10 @@ static struct irq_chip bfin_gpio_irqchip = {
.unmask = bfin_gpio_unmask_irq,
.set_type = bfin_gpio_irq_type,
.startup = bfin_gpio_irq_startup,
- .shutdown = bfin_gpio_irq_shutdown
+ .shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+ .set_wake = bfin_gpio_set_wake,
+#endif
};
static void bfin_demux_gpio_irq(unsigned int inta_irq,
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 81930f7d06f1..0be805ca423f 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -4,7 +4,7 @@
* Author: Cliff Brake <cbrake@accelent.com> Copyright (c) 2001
*
* Created: 2001
- * Description: Power management for the bfin
+ * Description: Blackfin power management
*
* Modified: Nicolas Pitre - PXA250 support
* Copyright (c) 2002 Monta Vista Software, Inc.
@@ -12,7 +12,7 @@
* Copyright (c) 2002 Monta Vista Software, Inc.
* Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610
* Copyright 2004
- * Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2004-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -67,42 +67,30 @@ void bfin_pm_suspend_standby_enter(void)
gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
#endif
-#if defined(CONFIG_PM_WAKEUP_BY_GPIO) || defined(CONFIG_PM_WAKEUP_GPIO_API)
- {
- u32 flags;
+ u32 flags;
- local_irq_save(flags);
+ local_irq_save(flags);
+ bfin_pm_setup();
- sleep_deeper(gpio_pm_setup()); /*Goto Sleep*/
-
- gpio_pm_restore();
-
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
- bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
- bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
-# ifdef CONFIG_BF54x
- bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
-# endif
+#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
+ sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
#else
- bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+ sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
#endif
- local_irq_restore(flags);
- }
-#endif
+ bfin_pm_restore();
-#if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR)
- sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR);
-# if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
-# ifdef CONFIG_BF54x
+# ifdef CONFIG_BF54x
bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
-# endif
-# else
- bfin_write_SIC_IWR(IWR_ENABLE_ALL);
# endif
-#endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */
+#else
+ bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+#endif
+
+ local_irq_restore(flags);
}
/*