diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2008-02-08 15:12:37 -0500 |
---|---|---|
committer | Bryan Wu <bryan.wu@analog.com> | 2008-02-08 15:12:37 -0500 |
commit | cfefe3c683e0d14c9ce3aeb883c55c7f30c20183 (patch) | |
tree | 77434010fc64f64606e893ce7b6f73243073ebb0 /arch/blackfin/mach-common | |
parent | 2c4f829b0ce3d2fb447acca823e141094a50daa5 (diff) |
[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.S | 32 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 126 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 44 |
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) | |||
191 | call _test_pll_locked; | 191 | call _test_pll_locked; |
192 | 192 | ||
193 | R0 = IWR_ENABLE(0); | 193 | R0 = IWR_ENABLE(0); |
194 | R1 = IWR_DISABLE_ALL; | ||
195 | R2 = IWR_DISABLE_ALL; | ||
196 | |||
194 | call _set_sic_iwr; | 197 | call _set_sic_iwr; |
195 | 198 | ||
196 | P0.H = hi(PLL_CTL); | 199 | P0.H = hi(PLL_CTL); |
@@ -237,6 +240,10 @@ ENTRY(_deep_sleep) | |||
237 | 240 | ||
238 | CLI R4; | 241 | CLI R4; |
239 | 242 | ||
243 | R0 = IWR_ENABLE(0); | ||
244 | R1 = IWR_DISABLE_ALL; | ||
245 | R2 = IWR_DISABLE_ALL; | ||
246 | |||
240 | call _set_sic_iwr; | 247 | call _set_sic_iwr; |
241 | 248 | ||
242 | call _set_dram_srfs; | 249 | call _set_dram_srfs; |
@@ -261,6 +268,9 @@ ENTRY(_deep_sleep) | |||
261 | call _test_pll_locked; | 268 | call _test_pll_locked; |
262 | 269 | ||
263 | R0 = IWR_ENABLE(0); | 270 | R0 = IWR_ENABLE(0); |
271 | R1 = IWR_DISABLE_ALL; | ||
272 | R2 = IWR_DISABLE_ALL; | ||
273 | |||
264 | call _set_sic_iwr; | 274 | call _set_sic_iwr; |
265 | 275 | ||
266 | P0.H = hi(PLL_CTL); | 276 | P0.H = hi(PLL_CTL); |
@@ -286,7 +296,13 @@ ENTRY(_sleep_deeper) | |||
286 | CLI R4; | 296 | CLI R4; |
287 | 297 | ||
288 | P3 = R0; | 298 | P3 = R0; |
299 | P4 = R1; | ||
300 | P5 = R2; | ||
301 | |||
289 | R0 = IWR_ENABLE(0); | 302 | R0 = IWR_ENABLE(0); |
303 | R1 = IWR_DISABLE_ALL; | ||
304 | R2 = IWR_DISABLE_ALL; | ||
305 | |||
290 | call _set_sic_iwr; | 306 | call _set_sic_iwr; |
291 | call _set_dram_srfs; /* Set SDRAM Self Refresh */ | 307 | call _set_dram_srfs; /* Set SDRAM Self Refresh */ |
292 | 308 | ||
@@ -327,6 +343,8 @@ ENTRY(_sleep_deeper) | |||
327 | call _test_pll_locked; | 343 | call _test_pll_locked; |
328 | 344 | ||
329 | R0 = P3; | 345 | R0 = P3; |
346 | R1 = P4; | ||
347 | R3 = P5; | ||
330 | call _set_sic_iwr; /* Set Awake from IDLE */ | 348 | call _set_sic_iwr; /* Set Awake from IDLE */ |
331 | 349 | ||
332 | P0.H = hi(PLL_CTL); | 350 | P0.H = hi(PLL_CTL); |
@@ -340,6 +358,9 @@ ENTRY(_sleep_deeper) | |||
340 | call _test_pll_locked; | 358 | call _test_pll_locked; |
341 | 359 | ||
342 | R0 = IWR_ENABLE(0); | 360 | R0 = IWR_ENABLE(0); |
361 | R1 = IWR_DISABLE_ALL; | ||
362 | R2 = IWR_DISABLE_ALL; | ||
363 | |||
343 | call _set_sic_iwr; /* Set Awake from IDLE PLL */ | 364 | call _set_sic_iwr; /* Set Awake from IDLE PLL */ |
344 | 365 | ||
345 | P0.H = hi(VR_CTL); | 366 | P0.H = hi(VR_CTL); |
@@ -417,14 +438,23 @@ ENTRY(_unset_dram_srfs) | |||
417 | RTS; | 438 | RTS; |
418 | 439 | ||
419 | ENTRY(_set_sic_iwr) | 440 | ENTRY(_set_sic_iwr) |
420 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | 441 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
421 | P0.H = hi(SIC_IWR0); | 442 | P0.H = hi(SIC_IWR0); |
422 | P0.L = lo(SIC_IWR0); | 443 | P0.L = lo(SIC_IWR0); |
444 | P1.H = hi(SIC_IWR1); | ||
445 | P1.L = lo(SIC_IWR1); | ||
446 | [P1] = R1; | ||
447 | #if defined(CONFIG_BF54x) | ||
448 | P1.H = hi(SIC_IWR2); | ||
449 | P1.L = lo(SIC_IWR2); | ||
450 | [P1] = R2; | ||
451 | #endif | ||
423 | #else | 452 | #else |
424 | P0.H = hi(SIC_IWR); | 453 | P0.H = hi(SIC_IWR); |
425 | P0.L = lo(SIC_IWR); | 454 | P0.L = lo(SIC_IWR); |
426 | #endif | 455 | #endif |
427 | [P0] = R0; | 456 | [P0] = R0; |
457 | |||
428 | SSYNC; | 458 | SSYNC; |
429 | RTS; | 459 | RTS; |
430 | 460 | ||
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 @@ | |||
1 | /* | 1 | /* |
2 | * File: arch/blackfin/mach-common/ints-priority-sc.c | 2 | * File: arch/blackfin/mach-common/ints-priority.c |
3 | * Based on: | 3 | * Based on: |
4 | * Author: | 4 | * Author: |
5 | * | 5 | * |
@@ -13,7 +13,7 @@ | |||
13 | * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> | 13 | * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> |
14 | * 2003 Metrowerks/Motorola | 14 | * 2003 Metrowerks/Motorola |
15 | * 2003 Bas Vermeulen <bas@buyways.nl> | 15 | * 2003 Bas Vermeulen <bas@buyways.nl> |
16 | * Copyright 2004-2007 Analog Devices Inc. | 16 | * Copyright 2004-2008 Analog Devices Inc. |
17 | * | 17 | * |
18 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 18 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
19 | * | 19 | * |
@@ -69,6 +69,10 @@ unsigned long irq_flags = 0x1f; | |||
69 | /* The number of spurious interrupts */ | 69 | /* The number of spurious interrupts */ |
70 | atomic_t num_spurious; | 70 | atomic_t num_spurious; |
71 | 71 | ||
72 | #ifdef CONFIG_PM | ||
73 | unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */ | ||
74 | #endif | ||
75 | |||
72 | struct ivgx { | 76 | struct ivgx { |
73 | /* irq number for request_irq, available in mach-bf533/irq.h */ | 77 | /* irq number for request_irq, available in mach-bf533/irq.h */ |
74 | unsigned int irqno; | 78 | unsigned int irqno; |
@@ -178,6 +182,27 @@ static void bfin_internal_unmask_irq(unsigned int irq) | |||
178 | SSYNC(); | 182 | SSYNC(); |
179 | } | 183 | } |
180 | 184 | ||
185 | #ifdef CONFIG_PM | ||
186 | int bfin_internal_set_wake(unsigned int irq, unsigned int state) | ||
187 | { | ||
188 | unsigned bank, bit; | ||
189 | unsigned long flags; | ||
190 | bank = (irq - (IRQ_CORETMR + 1)) / 32; | ||
191 | bit = (irq - (IRQ_CORETMR + 1)) % 32; | ||
192 | |||
193 | local_irq_save(flags); | ||
194 | |||
195 | if (state) | ||
196 | bfin_sic_iwr[bank] |= (1 << bit); | ||
197 | else | ||
198 | bfin_sic_iwr[bank] &= ~(1 << bit); | ||
199 | |||
200 | local_irq_restore(flags); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | #endif | ||
205 | |||
181 | static struct irq_chip bfin_core_irqchip = { | 206 | static struct irq_chip bfin_core_irqchip = { |
182 | .ack = ack_noop, | 207 | .ack = ack_noop, |
183 | .mask = bfin_core_mask_irq, | 208 | .mask = bfin_core_mask_irq, |
@@ -188,6 +213,9 @@ static struct irq_chip bfin_internal_irqchip = { | |||
188 | .ack = ack_noop, | 213 | .ack = ack_noop, |
189 | .mask = bfin_internal_mask_irq, | 214 | .mask = bfin_internal_mask_irq, |
190 | .unmask = bfin_internal_unmask_irq, | 215 | .unmask = bfin_internal_unmask_irq, |
216 | #ifdef CONFIG_PM | ||
217 | .set_wake = bfin_internal_set_wake, | ||
218 | #endif | ||
191 | }; | 219 | }; |
192 | 220 | ||
193 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX | 221 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX |
@@ -434,6 +462,20 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
434 | return 0; | 462 | return 0; |
435 | } | 463 | } |
436 | 464 | ||
465 | #ifdef CONFIG_PM | ||
466 | int bfin_gpio_set_wake(unsigned int irq, unsigned int state) | ||
467 | { | ||
468 | unsigned gpio = irq_to_gpio(irq); | ||
469 | |||
470 | if (state) | ||
471 | gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE); | ||
472 | else | ||
473 | gpio_pm_wakeup_free(gpio); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | #endif | ||
478 | |||
437 | static struct irq_chip bfin_gpio_irqchip = { | 479 | static struct irq_chip bfin_gpio_irqchip = { |
438 | .ack = bfin_gpio_ack_irq, | 480 | .ack = bfin_gpio_ack_irq, |
439 | .mask = bfin_gpio_mask_irq, | 481 | .mask = bfin_gpio_mask_irq, |
@@ -441,7 +483,10 @@ static struct irq_chip bfin_gpio_irqchip = { | |||
441 | .unmask = bfin_gpio_unmask_irq, | 483 | .unmask = bfin_gpio_unmask_irq, |
442 | .set_type = bfin_gpio_irq_type, | 484 | .set_type = bfin_gpio_irq_type, |
443 | .startup = bfin_gpio_irq_startup, | 485 | .startup = bfin_gpio_irq_startup, |
444 | .shutdown = bfin_gpio_irq_shutdown | 486 | .shutdown = bfin_gpio_irq_shutdown, |
487 | #ifdef CONFIG_PM | ||
488 | .set_wake = bfin_gpio_set_wake, | ||
489 | #endif | ||
445 | }; | 490 | }; |
446 | 491 | ||
447 | static void bfin_demux_gpio_irq(unsigned int inta_irq, | 492 | static void bfin_demux_gpio_irq(unsigned int inta_irq, |
@@ -487,7 +532,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq, | |||
487 | } | 532 | } |
488 | 533 | ||
489 | if (search) { | 534 | if (search) { |
490 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) { | 535 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
491 | irq += i; | 536 | irq += i; |
492 | 537 | ||
493 | mask = get_gpiop_data(i) & | 538 | mask = get_gpiop_data(i) & |
@@ -763,6 +808,74 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
763 | return 0; | 808 | return 0; |
764 | } | 809 | } |
765 | 810 | ||
811 | #ifdef CONFIG_PM | ||
812 | u32 pint_saved_masks[NR_PINT_SYS_IRQS]; | ||
813 | u32 pint_wakeup_masks[NR_PINT_SYS_IRQS]; | ||
814 | |||
815 | int bfin_gpio_set_wake(unsigned int irq, unsigned int state) | ||
816 | { | ||
817 | u32 pint_irq; | ||
818 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; | ||
819 | u32 bank = PINT_2_BANK(pint_val); | ||
820 | u32 pintbit = PINT_BIT(pint_val); | ||
821 | |||
822 | switch (bank) { | ||
823 | case 0: | ||
824 | pint_irq = IRQ_PINT0; | ||
825 | break; | ||
826 | case 2: | ||
827 | pint_irq = IRQ_PINT2; | ||
828 | break; | ||
829 | case 3: | ||
830 | pint_irq = IRQ_PINT3; | ||
831 | break; | ||
832 | case 1: | ||
833 | pint_irq = IRQ_PINT1; | ||
834 | break; | ||
835 | default: | ||
836 | return -EINVAL; | ||
837 | } | ||
838 | |||
839 | bfin_internal_set_wake(pint_irq, state); | ||
840 | |||
841 | if (state) | ||
842 | pint_wakeup_masks[bank] |= pintbit; | ||
843 | else | ||
844 | pint_wakeup_masks[bank] &= ~pintbit; | ||
845 | |||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | u32 bfin_pm_setup(void) | ||
850 | { | ||
851 | u32 val, i; | ||
852 | |||
853 | for (i = 0; i < NR_PINT_SYS_IRQS; i++) { | ||
854 | val = pint[i]->mask_clear; | ||
855 | pint_saved_masks[i] = val; | ||
856 | if (val ^ pint_wakeup_masks[i]) { | ||
857 | pint[i]->mask_clear = val; | ||
858 | pint[i]->mask_set = pint_wakeup_masks[i]; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | void bfin_pm_restore(void) | ||
866 | { | ||
867 | u32 i, val; | ||
868 | |||
869 | for (i = 0; i < NR_PINT_SYS_IRQS; i++) { | ||
870 | val = pint_saved_masks[i]; | ||
871 | if (val ^ pint_wakeup_masks[i]) { | ||
872 | pint[i]->mask_clear = pint[i]->mask_clear; | ||
873 | pint[i]->mask_set = val; | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | #endif | ||
878 | |||
766 | static struct irq_chip bfin_gpio_irqchip = { | 879 | static struct irq_chip bfin_gpio_irqchip = { |
767 | .ack = bfin_gpio_ack_irq, | 880 | .ack = bfin_gpio_ack_irq, |
768 | .mask = bfin_gpio_mask_irq, | 881 | .mask = bfin_gpio_mask_irq, |
@@ -770,7 +883,10 @@ static struct irq_chip bfin_gpio_irqchip = { | |||
770 | .unmask = bfin_gpio_unmask_irq, | 883 | .unmask = bfin_gpio_unmask_irq, |
771 | .set_type = bfin_gpio_irq_type, | 884 | .set_type = bfin_gpio_irq_type, |
772 | .startup = bfin_gpio_irq_startup, | 885 | .startup = bfin_gpio_irq_startup, |
773 | .shutdown = bfin_gpio_irq_shutdown | 886 | .shutdown = bfin_gpio_irq_shutdown, |
887 | #ifdef CONFIG_PM | ||
888 | .set_wake = bfin_gpio_set_wake, | ||
889 | #endif | ||
774 | }; | 890 | }; |
775 | 891 | ||
776 | static void bfin_demux_gpio_irq(unsigned int inta_irq, | 892 | 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 @@ | |||
4 | * Author: Cliff Brake <cbrake@accelent.com> Copyright (c) 2001 | 4 | * Author: Cliff Brake <cbrake@accelent.com> Copyright (c) 2001 |
5 | * | 5 | * |
6 | * Created: 2001 | 6 | * Created: 2001 |
7 | * Description: Power management for the bfin | 7 | * Description: Blackfin power management |
8 | * | 8 | * |
9 | * Modified: Nicolas Pitre - PXA250 support | 9 | * Modified: Nicolas Pitre - PXA250 support |
10 | * Copyright (c) 2002 Monta Vista Software, Inc. | 10 | * Copyright (c) 2002 Monta Vista Software, Inc. |
@@ -12,7 +12,7 @@ | |||
12 | * Copyright (c) 2002 Monta Vista Software, Inc. | 12 | * Copyright (c) 2002 Monta Vista Software, Inc. |
13 | * Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610 | 13 | * Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610 |
14 | * Copyright 2004 | 14 | * Copyright 2004 |
15 | * Copyright 2004-2006 Analog Devices Inc. | 15 | * Copyright 2004-2008 Analog Devices Inc. |
16 | * | 16 | * |
17 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 17 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
18 | * | 18 | * |
@@ -67,42 +67,30 @@ void bfin_pm_suspend_standby_enter(void) | |||
67 | gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); | 67 | gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #if defined(CONFIG_PM_WAKEUP_BY_GPIO) || defined(CONFIG_PM_WAKEUP_GPIO_API) | 70 | u32 flags; |
71 | { | ||
72 | u32 flags; | ||
73 | 71 | ||
74 | local_irq_save(flags); | 72 | local_irq_save(flags); |
73 | bfin_pm_setup(); | ||
75 | 74 | ||
76 | sleep_deeper(gpio_pm_setup()); /*Goto Sleep*/ | 75 | #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER |
77 | 76 | sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); | |
78 | gpio_pm_restore(); | ||
79 | |||
80 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | ||
81 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); | ||
82 | bfin_write_SIC_IWR1(IWR_ENABLE_ALL); | ||
83 | # ifdef CONFIG_BF54x | ||
84 | bfin_write_SIC_IWR2(IWR_ENABLE_ALL); | ||
85 | # endif | ||
86 | #else | 77 | #else |
87 | bfin_write_SIC_IWR(IWR_ENABLE_ALL); | 78 | sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); |
88 | #endif | 79 | #endif |
89 | 80 | ||
90 | local_irq_restore(flags); | 81 | bfin_pm_restore(); |
91 | } | ||
92 | #endif | ||
93 | 82 | ||
94 | #if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR) | 83 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
95 | sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR); | ||
96 | # if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | ||
97 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); | 84 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); |
98 | bfin_write_SIC_IWR1(IWR_ENABLE_ALL); | 85 | bfin_write_SIC_IWR1(IWR_ENABLE_ALL); |
99 | # ifdef CONFIG_BF54x | 86 | # ifdef CONFIG_BF54x |
100 | bfin_write_SIC_IWR2(IWR_ENABLE_ALL); | 87 | bfin_write_SIC_IWR2(IWR_ENABLE_ALL); |
101 | # endif | ||
102 | # else | ||
103 | bfin_write_SIC_IWR(IWR_ENABLE_ALL); | ||
104 | # endif | 88 | # endif |
105 | #endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */ | 89 | #else |
90 | bfin_write_SIC_IWR(IWR_ENABLE_ALL); | ||
91 | #endif | ||
92 | |||
93 | local_irq_restore(flags); | ||
106 | } | 94 | } |
107 | 95 | ||
108 | /* | 96 | /* |