aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2008-07-19 04:57:32 -0400
committerBryan Wu <cooloney@kernel.org>2008-07-19 04:57:32 -0400
commit1efc80b53eb54770139219f99657abd92595fc86 (patch)
tree254c76b3aaf22110b116e67a8118945006cacce6 /arch/blackfin
parent4f13f548cef5af1717cbbc341a1a3474f3e7466e (diff)
Blackfin arch: Functional power management support
Enable: PM_SUSPEND_MEM -> Blackfin Hibernate to SDRAM This feature requires a special bootloader (u-boot) supporting return from hibernate. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/Kconfig66
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c26
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c118
-rw-r--r--arch/blackfin/mach-common/dpmc_modes.S600
-rw-r--r--arch/blackfin/mach-common/pm.c225
5 files changed, 979 insertions, 56 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index c602727d1a9..8f21b78b2e6 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -880,7 +880,7 @@ config ARCH_SUSPEND_POSSIBLE
880 depends on !SMP 880 depends on !SMP
881 881
882choice 882choice
883 prompt "Default Power Saving Mode" 883 prompt "Standby Power Saving Mode"
884 depends on PM 884 depends on PM
885 default PM_BFIN_SLEEP_DEEPER 885 default PM_BFIN_SLEEP_DEEPER
886config PM_BFIN_SLEEP_DEEPER 886config PM_BFIN_SLEEP_DEEPER
@@ -899,6 +899,8 @@ config PM_BFIN_SLEEP_DEEPER
899 normal during Sleep Deeper, due to the reduced SCLK frequency. 899 normal during Sleep Deeper, due to the reduced SCLK frequency.
900 When in the sleep mode, system DMA access to L1 memory is not supported. 900 When in the sleep mode, system DMA access to L1 memory is not supported.
901 901
902 If unsure, select "Sleep Deeper".
903
902config PM_BFIN_SLEEP 904config PM_BFIN_SLEEP
903 bool "Sleep" 905 bool "Sleep"
904 help 906 help
@@ -906,15 +908,17 @@ config PM_BFIN_SLEEP
906 dissipation by disabling the clock to the processor core (CCLK). 908 dissipation by disabling the clock to the processor core (CCLK).
907 The PLL and system clock (SCLK), however, continue to operate in 909 The PLL and system clock (SCLK), however, continue to operate in
908 this mode. Typically an external event or RTC activity will wake 910 this mode. Typically an external event or RTC activity will wake
909 up the processor. When in the sleep mode, 911 up the processor. When in the sleep mode, system DMA access to L1
910 system DMA access to L1 memory is not supported. 912 memory is not supported.
913
914 If unsure, select "Sleep Deeper".
911endchoice 915endchoice
912 916
913config PM_WAKEUP_BY_GPIO 917config PM_WAKEUP_BY_GPIO
914 bool "Cause Wakeup Event by GPIO" 918 bool "Allow Wakeup from Standby by GPIO"
915 919
916config PM_WAKEUP_GPIO_NUMBER 920config PM_WAKEUP_GPIO_NUMBER
917 int "Wakeup GPIO number" 921 int "GPIO number"
918 range 0 47 922 range 0 47
919 depends on PM_WAKEUP_BY_GPIO 923 depends on PM_WAKEUP_BY_GPIO
920 default 2 if BFIN537_STAMP 924 default 2 if BFIN537_STAMP
@@ -935,6 +939,58 @@ config PM_WAKEUP_GPIO_POLAR_EDGE_B
935 bool "Both EDGE" 939 bool "Both EDGE"
936endchoice 940endchoice
937 941
942comment "Possible Suspend Mem / Hibernate Wake-Up Sources"
943 depends on PM
944
945config PM_BFIN_WAKE_RTC
946 bool "Allow Wake-Up from RESET and on-chip RTC"
947 depends on PM
948 default n
949 help
950 Enable RTC Wake-Up (Voltage Regulator Power-Up)
951
952config PM_BFIN_WAKE_PH6
953 bool "Allow Wake-Up from on-chip PHY or PH6 GP"
954 depends on PM && (BF52x || BF534 || BF536 || BF537)
955 default n
956 help
957 Enable PHY and PH6 GP Wake-Up (Voltage Regulator Power-Up)
958
959config PM_BFIN_WAKE_CAN
960 bool "Allow Wake-Up from on-chip CAN0/1"
961 depends on PM && (BF54x || BF534 || BF536 || BF537)
962 default n
963 help
964 Enable CAN0/1 Wake-Up (Voltage Regulator Power-Up)
965
966config PM_BFIN_WAKE_GP
967 bool "Allow Wake-Up from GPIOs"
968 depends on PM && BF54x
969 default n
970 help
971 Enable General-Purpose Wake-Up (Voltage Regulator Power-Up)
972
973config PM_BFIN_WAKE_USB
974 bool "Allow Wake-Up from on-chip USB"
975 depends on PM && (BF54x || BF52x)
976 default n
977 help
978 Enable USB Wake-Up (Voltage Regulator Power-Up)
979
980config PM_BFIN_WAKE_KEYPAD
981 bool "Allow Wake-Up from on-chip Keypad"
982 depends on PM && BF54x
983 default n
984 help
985 Enable Keypad Wake-Up (Voltage Regulator Power-Up)
986
987config PM_BFIN_WAKE_ROTARY
988 bool "Allow Wake-Up from on-chip Rotary"
989 depends on PM && BF54x
990 default n
991 help
992 Enable Rotary Wake-Up (Voltage Regulator Power-Up)
993
938endmenu 994endmenu
939 995
940menu "CPU Frequency scaling" 996menu "CPU Frequency scaling"
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index d54f19085f3..ad0e75845ac 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -472,6 +472,32 @@ unsigned long get_dma_curr_addr(unsigned int channel)
472} 472}
473EXPORT_SYMBOL(get_dma_curr_addr); 473EXPORT_SYMBOL(get_dma_curr_addr);
474 474
475#ifdef CONFIG_PM
476int blackfin_dma_suspend(void)
477{
478 int i;
479
480 for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
481 if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
482 printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
483 return -EBUSY;
484 }
485
486 dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
487 }
488
489 return 0;
490}
491
492void blackfin_dma_resume(void)
493{
494 int i;
495
496 for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++)
497 dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
498}
499#endif
500
475static void *__dma_memcpy(void *dest, const void *src, size_t size) 501static void *__dma_memcpy(void *dest, const void *src, size_t size)
476{ 502{
477 int direction; /* 1 - address decrease, 0 - address increase */ 503 int direction; /* 1 - address decrease, 0 - address increase */
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index b6d89d1644c..ecbd141e0ef 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -186,7 +186,10 @@ static struct str_ident {
186 char name[RESOURCE_LABEL_SIZE]; 186 char name[RESOURCE_LABEL_SIZE];
187} str_ident[MAX_RESOURCES]; 187} str_ident[MAX_RESOURCES];
188 188
189#if defined(CONFIG_PM) && !defined(CONFIG_BF54x) 189#if defined(CONFIG_PM)
190#if defined(CONFIG_BF54x)
191static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
192#else
190static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; 193static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
191static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; 194static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
192static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)]; 195static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -206,7 +209,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INT
206#ifdef BF561_FAMILY 209#ifdef BF561_FAMILY
207static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; 210static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
208#endif 211#endif
209 212#endif
210#endif /* CONFIG_PM */ 213#endif /* CONFIG_PM */
211 214
212#if defined(BF548_FAMILY) 215#if defined(BF548_FAMILY)
@@ -667,7 +670,7 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
667 return 0; 670 return 0;
668} 671}
669 672
670u32 bfin_pm_setup(void) 673u32 bfin_pm_standby_setup(void)
671{ 674{
672 u16 bank, mask, i, gpio; 675 u16 bank, mask, i, gpio;
673 676
@@ -679,7 +682,7 @@ u32 bfin_pm_setup(void)
679 gpio_bankb[bank]->maskb = 0; 682 gpio_bankb[bank]->maskb = 0;
680 683
681 if (mask) { 684 if (mask) {
682#ifdef BF537_FAMILY 685#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
683 gpio_bank_saved[bank].fer = *port_fer[bank]; 686 gpio_bank_saved[bank].fer = *port_fer[bank];
684#endif 687#endif
685 gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; 688 gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
@@ -715,7 +718,7 @@ u32 bfin_pm_setup(void)
715 return 0; 718 return 0;
716} 719}
717 720
718void bfin_pm_restore(void) 721void bfin_pm_standby_restore(void)
719{ 722{
720 u16 bank, mask, i; 723 u16 bank, mask, i;
721 724
@@ -724,7 +727,7 @@ void bfin_pm_restore(void)
724 bank = gpio_bank(i); 727 bank = gpio_bank(i);
725 728
726 if (mask) { 729 if (mask) {
727#ifdef BF537_FAMILY 730#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
728 *port_fer[bank] = gpio_bank_saved[bank].fer; 731 *port_fer[bank] = gpio_bank_saved[bank].fer;
729#endif 732#endif
730 gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; 733 gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
@@ -743,8 +746,111 @@ void bfin_pm_restore(void)
743 AWA_DUMMY_READ(maskb); 746 AWA_DUMMY_READ(maskb);
744} 747}
745 748
749void bfin_gpio_pm_hibernate_suspend(void)
750{
751 int i, bank;
752
753 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
754 bank = gpio_bank(i);
755
756#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
757 gpio_bank_saved[bank].fer = *port_fer[bank];
758#ifdef BF527_FAMILY
759 gpio_bank_saved[bank].mux = *port_mux[bank];
760#else
761 if (bank == 0)
762 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
763#endif
764#endif
765 gpio_bank_saved[bank].data = gpio_bankb[bank]->data;
766 gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
767 gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
768 gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
769 gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
770 gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
771 gpio_bank_saved[bank].maska = gpio_bankb[bank]->maska;
772 }
773
774 AWA_DUMMY_READ(maska);
775}
776
777void bfin_gpio_pm_hibernate_restore(void)
778{
779 int i, bank;
780
781 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
782 bank = gpio_bank(i);
783
784#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
785#ifdef BF527_FAMILY
786 *port_mux[bank] = gpio_bank_saved[bank].mux;
787#else
788 if (bank == 0)
789 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
790#endif
791 *port_fer[bank] = gpio_bank_saved[bank].fer;
792#endif
793 gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
794 gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir;
795 gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
796 gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
797 gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
798
799 gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data
800 | gpio_bank_saved[bank].dir;
801
802 gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska;
803 }
804 AWA_DUMMY_READ(maska);
805}
806
807
746#endif 808#endif
747#else /* BF548_FAMILY */ 809#else /* BF548_FAMILY */
810#ifdef CONFIG_PM
811
812u32 bfin_pm_standby_setup(void)
813{
814 return 0;
815}
816
817void bfin_pm_standby_restore(void)
818{
819
820}
821
822void bfin_gpio_pm_hibernate_suspend(void)
823{
824 int i, bank;
825
826 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
827 bank = gpio_bank(i);
828
829 gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
830 gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
831 gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
832 gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
833 gpio_bank_saved[bank].inen = gpio_array[bank]->port_inen;
834 gpio_bank_saved[bank].dir = gpio_array[bank]->port_dir_set;
835 }
836}
837
838void bfin_gpio_pm_hibernate_restore(void)
839{
840 int i, bank;
841
842 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
843 bank = gpio_bank(i);
844
845 gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
846 gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
847 gpio_array[bank]->port_inen = gpio_bank_saved[bank].inen;
848 gpio_array[bank]->port_dir_set = gpio_bank_saved[bank].dir;
849 gpio_array[bank]->port_set = gpio_bank_saved[bank].data
850 | gpio_bank_saved[bank].dir;
851 }
852}
853#endif
748 854
749unsigned short get_gpio_dir(unsigned gpio) 855unsigned short get_gpio_dir(unsigned gpio)
750{ 856{
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index b7981d31c39..46ee77afed2 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -7,7 +7,7 @@
7#include <linux/linkage.h> 7#include <linux/linkage.h>
8#include <asm/blackfin.h> 8#include <asm/blackfin.h>
9#include <asm/mach/irq.h> 9#include <asm/mach/irq.h>
10 10#include <asm/dpmc.h>
11 11
12.section .l1.text 12.section .l1.text
13 13
@@ -56,26 +56,25 @@ ENTRY(_hibernate_mode)
56 [--SP] = ( R7:0, P5:0 ); 56 [--SP] = ( R7:0, P5:0 );
57 [--SP] = RETS; 57 [--SP] = RETS;
58 58
59 R3 = R0;
60 R0 = IWR_DISABLE_ALL;
61 R1 = IWR_DISABLE_ALL;
62 R2 = IWR_DISABLE_ALL;
59 call _set_sic_iwr; 63 call _set_sic_iwr;
64 call _set_dram_srfs;
65 SSYNC;
60 66
61 R0 = 0xFFFF (Z); 67 R0 = 0xFFFF (Z);
62 call _set_rtc_istat; 68 call _set_rtc_istat;
63 69
64 P0.H = hi(VR_CTL); 70 P0.H = hi(VR_CTL);
65 P0.L = lo(VR_CTL); 71 P0.L = lo(VR_CTL);
66 R1 = W[P0](z);
67 BITSET (R1, 8);
68 BITCLR (R1, 0);
69 BITCLR (R1, 1);
70 W[P0] = R1.L;
71 SSYNC;
72 72
73 W[P0] = R3.L;
73 CLI R2; 74 CLI R2;
74 IDLE; 75 IDLE;
75 76.Lforever:
76 /* Actually, adding anything may not be necessary...SDRAM contents 77 jump .Lforever;
77 * are lost
78 */
79 78
80ENTRY(_deep_sleep) 79ENTRY(_deep_sleep)
81 [--SP] = ( R7:0, P5:0 ); 80 [--SP] = ( R7:0, P5:0 );
@@ -233,51 +232,70 @@ ENTRY(_sleep_deeper)
233 ( R7:0, P5:0 ) = [SP++]; 232 ( R7:0, P5:0 ) = [SP++];
234 RTS; 233 RTS;
235 234
235
236ENTRY(_set_dram_srfs) 236ENTRY(_set_dram_srfs)
237 /* set the dram to self refresh mode */ 237 /* set the dram to self refresh mode */
238#if defined(CONFIG_BF54x) 238 SSYNC;
239#if defined(EBIU_RSTCTL) /* DDR */
239 P0.H = hi(EBIU_RSTCTL); 240 P0.H = hi(EBIU_RSTCTL);
240 P0.L = lo(EBIU_RSTCTL); 241 P0.L = lo(EBIU_RSTCTL);
241 R2 = [P0]; 242 R2 = [P0];
242 R3.H = hi(SRREQ); 243 BITSET(R2, 3); /* SRREQ enter self-refresh mode */
243 R3.L = lo(SRREQ); 244 [P0] = R2;
244#else 245 SSYNC;
245 P0.H = hi(EBIU_SDGCTL); 2461:
247 R2 = [P0];
248 CC = BITTST(R2, 4);
249 if !CC JUMP 1b;
250#else /* SDRAM */
246 P0.L = lo(EBIU_SDGCTL); 251 P0.L = lo(EBIU_SDGCTL);
252 P0.H = hi(EBIU_SDGCTL);
247 R2 = [P0]; 253 R2 = [P0];
248 R3.H = hi(SRFS); 254 BITSET(R2, 24); /* SRFS enter self-refresh mode */
249 R3.L = lo(SRFS);
250#endif
251 R2 = R2|R3;
252 [P0] = R2; 255 [P0] = R2;
253 ssync; 256 SSYNC;
254#if defined(CONFIG_BF54x) 257
255.LSRR_MODE: 258 P0.L = lo(EBIU_SDSTAT);
259 P0.H = hi(EBIU_SDSTAT);
2601:
261 R2 = w[P0];
262 SSYNC;
263 cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
264 if !cc jump 1b;
265
266 P0.L = lo(EBIU_SDGCTL);
267 P0.H = hi(EBIU_SDGCTL);
256 R2 = [P0]; 268 R2 = [P0];
257 CC = BITTST(R2, 4); 269 BITCLR(R2, 0); /* SCTLE disable CLKOUT */
258 if !CC JUMP .LSRR_MODE; 270 [P0] = R2;
259#endif 271#endif
260 RTS; 272 RTS;
261 273
274
262ENTRY(_unset_dram_srfs) 275ENTRY(_unset_dram_srfs)
263 /* set the dram out of self refresh mode */ 276 /* set the dram out of self refresh mode */
264#if defined(CONFIG_BF54x) 277#if defined(EBIU_RSTCTL) /* DDR */
265 P0.H = hi(EBIU_RSTCTL); 278 P0.H = hi(EBIU_RSTCTL);
266 P0.L = lo(EBIU_RSTCTL); 279 P0.L = lo(EBIU_RSTCTL);
267 R2 = [P0]; 280 R2 = [P0];
268 R3.H = hi(SRREQ); 281 BITCLR(R2, 3); /* clear SRREQ bit */
269 R3.L = lo(SRREQ); 282 [P0] = R2;
270#else 283#elif defined(EBIU_SDGCTL) /* SDRAM */
284
285 P0.L = lo(EBIU_SDGCTL); /* release CLKOUT from self-refresh */
271 P0.H = hi(EBIU_SDGCTL); 286 P0.H = hi(EBIU_SDGCTL);
272 P0.L = lo(EBIU_SDGCTL);
273 R2 = [P0]; 287 R2 = [P0];
274 R3.H = hi(SRFS); 288 BITSET(R2, 0); /* SCTLE enable CLKOUT */
275 R3.L = lo(SRFS); 289 [P0] = R2
290 SSYNC;
291
292 P0.L = lo(EBIU_SDGCTL); /* release SDRAM from self-refresh */
293 P0.H = hi(EBIU_SDGCTL);
294 R2 = [P0];
295 BITCLR(R2, 24); /* clear SRFS bit */
296 [P0] = R2
276#endif 297#endif
277 R3 = ~R3; 298 SSYNC;
278 R2 = R2&R3;
279 [P0] = R2;
280 ssync;
281 RTS; 299 RTS;
282 300
283ENTRY(_set_sic_iwr) 301ENTRY(_set_sic_iwr)
@@ -307,6 +325,11 @@ ENTRY(_set_rtc_istat)
307 P0.L = lo(RTC_ISTAT); 325 P0.L = lo(RTC_ISTAT);
308 w[P0] = R0.L; 326 w[P0] = R0.L;
309 SSYNC; 327 SSYNC;
328#elif (ANOMALY_05000371)
329 nop;
330 nop;
331 nop;
332 nop;
310#endif 333#endif
311 RTS; 334 RTS;
312 335
@@ -318,3 +341,508 @@ ENTRY(_test_pll_locked)
318 CC = BITTST(R0,5); 341 CC = BITTST(R0,5);
319 IF !CC JUMP 1b; 342 IF !CC JUMP 1b;
320 RTS; 343 RTS;
344
345.section .text
346
347
348ENTRY(_do_hibernate)
349 [--SP] = ( R7:0, P5:0 );
350 [--SP] = RETS;
351 /* Save System MMRs */
352 R2 = R0;
353 P0.H = hi(PLL_CTL);
354 P0.L = lo(PLL_CTL);
355
356#ifdef SIC_IMASK0
357 PM_SYS_PUSH(SIC_IMASK0)
358#endif
359#ifdef SIC_IMASK1
360 PM_SYS_PUSH(SIC_IMASK1)
361#endif
362#ifdef SIC_IMASK2
363 PM_SYS_PUSH(SIC_IMASK2)
364#endif
365#ifdef SIC_IMASK
366 PM_SYS_PUSH(SIC_IMASK)
367#endif
368#ifdef SICA_IMASK0
369 PM_SYS_PUSH(SICA_IMASK0)
370#endif
371#ifdef SICA_IMASK1
372 PM_SYS_PUSH(SICA_IMASK1)
373#endif
374#ifdef SIC_IAR2
375 PM_SYS_PUSH(SIC_IAR0)
376 PM_SYS_PUSH(SIC_IAR1)
377 PM_SYS_PUSH(SIC_IAR2)
378#endif
379#ifdef SIC_IAR3
380 PM_SYS_PUSH(SIC_IAR3)
381#endif
382#ifdef SIC_IAR4
383 PM_SYS_PUSH(SIC_IAR4)
384 PM_SYS_PUSH(SIC_IAR5)
385 PM_SYS_PUSH(SIC_IAR6)
386#endif
387#ifdef SIC_IAR7
388 PM_SYS_PUSH(SIC_IAR7)
389#endif
390#ifdef SIC_IAR8
391 PM_SYS_PUSH(SIC_IAR8)
392 PM_SYS_PUSH(SIC_IAR9)
393 PM_SYS_PUSH(SIC_IAR10)
394 PM_SYS_PUSH(SIC_IAR11)
395#endif
396
397#ifdef SICA_IAR0
398 PM_SYS_PUSH(SICA_IAR0)
399 PM_SYS_PUSH(SICA_IAR1)
400 PM_SYS_PUSH(SICA_IAR2)
401 PM_SYS_PUSH(SICA_IAR3)
402 PM_SYS_PUSH(SICA_IAR4)
403 PM_SYS_PUSH(SICA_IAR5)
404 PM_SYS_PUSH(SICA_IAR6)
405 PM_SYS_PUSH(SICA_IAR7)
406#endif
407
408#ifdef SIC_IWR
409 PM_SYS_PUSH(SIC_IWR)
410#endif
411#ifdef SIC_IWR0
412 PM_SYS_PUSH(SIC_IWR0)
413#endif
414#ifdef SIC_IWR1
415 PM_SYS_PUSH(SIC_IWR1)
416#endif
417#ifdef SIC_IWR2
418 PM_SYS_PUSH(SIC_IWR2)
419#endif
420#ifdef SICA_IWR0
421 PM_SYS_PUSH(SICA_IWR0)
422#endif
423#ifdef SICA_IWR1
424 PM_SYS_PUSH(SICA_IWR1)
425#endif
426
427#ifdef PINT0_ASSIGN
428 PM_SYS_PUSH(PINT0_ASSIGN)
429 PM_SYS_PUSH(PINT1_ASSIGN)
430 PM_SYS_PUSH(PINT2_ASSIGN)
431 PM_SYS_PUSH(PINT3_ASSIGN)
432#endif
433
434 PM_SYS_PUSH(EBIU_AMBCTL0)
435 PM_SYS_PUSH(EBIU_AMBCTL1)
436 PM_SYS_PUSH16(EBIU_AMGCTL)
437
438#ifdef EBIU_FCTL
439 PM_SYS_PUSH(EBIU_MBSCTL)
440 PM_SYS_PUSH(EBIU_MODE)
441 PM_SYS_PUSH(EBIU_FCTL)
442#endif
443
444 PM_SYS_PUSH16(SYSCR)
445
446 /* Save Core MMRs */
447 P0.H = hi(SRAM_BASE_ADDRESS);
448 P0.L = lo(SRAM_BASE_ADDRESS);
449
450 PM_PUSH(DMEM_CONTROL)
451 PM_PUSH(DCPLB_ADDR0)
452 PM_PUSH(DCPLB_ADDR1)
453 PM_PUSH(DCPLB_ADDR2)
454 PM_PUSH(DCPLB_ADDR3)
455 PM_PUSH(DCPLB_ADDR4)
456 PM_PUSH(DCPLB_ADDR5)
457 PM_PUSH(DCPLB_ADDR6)
458 PM_PUSH(DCPLB_ADDR7)
459 PM_PUSH(DCPLB_ADDR8)
460 PM_PUSH(DCPLB_ADDR9)
461 PM_PUSH(DCPLB_ADDR10)
462 PM_PUSH(DCPLB_ADDR11)
463 PM_PUSH(DCPLB_ADDR12)
464 PM_PUSH(DCPLB_ADDR13)
465 PM_PUSH(DCPLB_ADDR14)
466 PM_PUSH(DCPLB_ADDR15)
467 PM_PUSH(DCPLB_DATA0)
468 PM_PUSH(DCPLB_DATA1)
469 PM_PUSH(DCPLB_DATA2)
470 PM_PUSH(DCPLB_DATA3)
471 PM_PUSH(DCPLB_DATA4)
472 PM_PUSH(DCPLB_DATA5)
473 PM_PUSH(DCPLB_DATA6)
474 PM_PUSH(DCPLB_DATA7)
475 PM_PUSH(DCPLB_DATA8)
476 PM_PUSH(DCPLB_DATA9)
477 PM_PUSH(DCPLB_DATA10)
478 PM_PUSH(DCPLB_DATA11)
479 PM_PUSH(DCPLB_DATA12)
480 PM_PUSH(DCPLB_DATA13)
481 PM_PUSH(DCPLB_DATA14)
482 PM_PUSH(DCPLB_DATA15)
483 PM_PUSH(IMEM_CONTROL)
484 PM_PUSH(ICPLB_ADDR0)
485 PM_PUSH(ICPLB_ADDR1)
486 PM_PUSH(ICPLB_ADDR2)
487 PM_PUSH(ICPLB_ADDR3)
488 PM_PUSH(ICPLB_ADDR4)
489 PM_PUSH(ICPLB_ADDR5)
490 PM_PUSH(ICPLB_ADDR6)
491 PM_PUSH(ICPLB_ADDR7)
492 PM_PUSH(ICPLB_ADDR8)
493 PM_PUSH(ICPLB_ADDR9)
494 PM_PUSH(ICPLB_ADDR10)
495 PM_PUSH(ICPLB_ADDR11)
496 PM_PUSH(ICPLB_ADDR12)
497 PM_PUSH(ICPLB_ADDR13)
498 PM_PUSH(ICPLB_ADDR14)
499 PM_PUSH(ICPLB_ADDR15)
500 PM_PUSH(ICPLB_DATA0)
501 PM_PUSH(ICPLB_DATA1)
502 PM_PUSH(ICPLB_DATA2)
503 PM_PUSH(ICPLB_DATA3)
504 PM_PUSH(ICPLB_DATA4)
505 PM_PUSH(ICPLB_DATA5)
506 PM_PUSH(ICPLB_DATA6)
507 PM_PUSH(ICPLB_DATA7)
508 PM_PUSH(ICPLB_DATA8)
509 PM_PUSH(ICPLB_DATA9)
510 PM_PUSH(ICPLB_DATA10)
511 PM_PUSH(ICPLB_DATA11)
512 PM_PUSH(ICPLB_DATA12)
513 PM_PUSH(ICPLB_DATA13)
514 PM_PUSH(ICPLB_DATA14)
515 PM_PUSH(ICPLB_DATA15)
516 PM_PUSH(EVT0)
517 PM_PUSH(EVT1)
518 PM_PUSH(EVT2)
519 PM_PUSH(EVT3)
520 PM_PUSH(EVT4)
521 PM_PUSH(EVT5)
522 PM_PUSH(EVT6)
523 PM_PUSH(EVT7)
524 PM_PUSH(EVT8)
525 PM_PUSH(EVT9)
526 PM_PUSH(EVT10)
527 PM_PUSH(EVT11)
528 PM_PUSH(EVT12)
529 PM_PUSH(EVT13)
530 PM_PUSH(EVT14)
531 PM_PUSH(EVT15)
532 PM_PUSH(IMASK)
533 PM_PUSH(ILAT)
534 PM_PUSH(IPRIO)
535 PM_PUSH(TCNTL)
536 PM_PUSH(TPERIOD)
537 PM_PUSH(TSCALE)
538 PM_PUSH(TCOUNT)
539 PM_PUSH(TBUFCTL)
540
541 /* Save Core Registers */
542 [--sp] = SYSCFG;
543 [--sp] = ( R7:0, P5:0 );
544 [--sp] = fp;
545 [--sp] = usp;
546
547 [--sp] = i0;
548 [--sp] = i1;
549 [--sp] = i2;
550 [--sp] = i3;
551
552 [--sp] = m0;
553 [--sp] = m1;
554 [--sp] = m2;
555 [--sp] = m3;
556
557 [--sp] = l0;
558 [--sp] = l1;
559 [--sp] = l2;
560 [--sp] = l3;
561
562 [--sp] = b0;
563 [--sp] = b1;
564 [--sp] = b2;
565 [--sp] = b3;
566 [--sp] = a0.x;
567 [--sp] = a0.w;
568 [--sp] = a1.x;
569 [--sp] = a1.w;
570
571 [--sp] = LC0;
572 [--sp] = LC1;
573 [--sp] = LT0;
574 [--sp] = LT1;
575 [--sp] = LB0;
576 [--sp] = LB1;
577
578 [--sp] = ASTAT;
579 [--sp] = CYCLES;
580 [--sp] = CYCLES2;
581
582 [--sp] = RETS;
583 r0 = RETI;
584 [--sp] = r0;
585 [--sp] = RETX;
586 [--sp] = RETN;
587 [--sp] = RETE;
588 [--sp] = SEQSTAT;
589
590 /* Save Magic, return address and Stack Pointer */
591 P0.H = 0;
592 P0.L = 0;
593 R0.H = 0xDEAD; /* Hibernate Magic */
594 R0.L = 0xBEEF;
595 [P0++] = R0; /* Store Hibernate Magic */
596 R0.H = pm_resume_here;
597 R0.L = pm_resume_here;
598 [P0++] = R0; /* Save Return Address */
599 [P0++] = SP; /* Save Stack Pointer */
600 P0.H = _hibernate_mode;
601 P0.L = _hibernate_mode;
602 R0 = R2;
603 call (P0); /* Goodbye */
604
605pm_resume_here:
606
607 /* Restore Core Registers */
608 SEQSTAT = [sp++];
609 RETE = [sp++];
610 RETN = [sp++];
611 RETX = [sp++];
612 r0 = [sp++];
613 RETI = r0;
614 RETS = [sp++];
615
616 CYCLES2 = [sp++];
617 CYCLES = [sp++];
618 ASTAT = [sp++];
619
620 LB1 = [sp++];
621 LB0 = [sp++];
622 LT1 = [sp++];
623 LT0 = [sp++];
624 LC1 = [sp++];
625 LC0 = [sp++];
626
627 a1.w = [sp++];
628 a1.x = [sp++];
629 a0.w = [sp++];
630 a0.x = [sp++];
631 b3 = [sp++];
632 b2 = [sp++];
633 b1 = [sp++];
634 b0 = [sp++];
635
636 l3 = [sp++];
637 l2 = [sp++];
638 l1 = [sp++];
639 l0 = [sp++];
640
641 m3 = [sp++];
642 m2 = [sp++];
643 m1 = [sp++];
644 m0 = [sp++];
645
646 i3 = [sp++];
647 i2 = [sp++];
648 i1 = [sp++];
649 i0 = [sp++];
650
651 usp = [sp++];
652 fp = [sp++];
653
654 ( R7 : 0, P5 : 0) = [ SP ++ ];
655 SYSCFG = [sp++];
656
657 /* Restore Core MMRs */
658
659 PM_POP(TBUFCTL)
660 PM_POP(TCOUNT)
661 PM_POP(TSCALE)
662 PM_POP(TPERIOD)
663 PM_POP(TCNTL)
664 PM_POP(IPRIO)
665 PM_POP(ILAT)
666 PM_POP(IMASK)
667 PM_POP(EVT15)
668 PM_POP(EVT14)
669 PM_POP(EVT13)
670 PM_POP(EVT12)
671 PM_POP(EVT11)
672 PM_POP(EVT10)
673 PM_POP(EVT9)
674 PM_POP(EVT8)
675 PM_POP(EVT7)
676 PM_POP(EVT6)
677 PM_POP(EVT5)
678 PM_POP(EVT4)
679 PM_POP(EVT3)
680 PM_POP(EVT2)
681 PM_POP(EVT1)
682 PM_POP(EVT0)
683 PM_POP(ICPLB_DATA15)
684 PM_POP(ICPLB_DATA14)
685 PM_POP(ICPLB_DATA13)
686 PM_POP(ICPLB_DATA12)
687 PM_POP(ICPLB_DATA11)
688 PM_POP(ICPLB_DATA10)
689 PM_POP(ICPLB_DATA9)
690 PM_POP(ICPLB_DATA8)
691 PM_POP(ICPLB_DATA7)
692 PM_POP(ICPLB_DATA6)
693 PM_POP(ICPLB_DATA5)
694 PM_POP(ICPLB_DATA4)
695 PM_POP(ICPLB_DATA3)
696 PM_POP(ICPLB_DATA2)
697 PM_POP(ICPLB_DATA1)
698 PM_POP(ICPLB_DATA0)
699 PM_POP(ICPLB_ADDR15)
700 PM_POP(ICPLB_ADDR14)
701 PM_POP(ICPLB_ADDR13)
702 PM_POP(ICPLB_ADDR12)
703 PM_POP(ICPLB_ADDR11)
704 PM_POP(ICPLB_ADDR10)
705 PM_POP(ICPLB_ADDR9)
706 PM_POP(ICPLB_ADDR8)
707 PM_POP(ICPLB_ADDR7)
708 PM_POP(ICPLB_ADDR6)
709 PM_POP(ICPLB_ADDR5)
710 PM_POP(ICPLB_ADDR4)
711 PM_POP(ICPLB_ADDR3)
712 PM_POP(ICPLB_ADDR2)
713 PM_POP(ICPLB_ADDR1)
714 PM_POP(ICPLB_ADDR0)
715 PM_POP(IMEM_CONTROL)
716 PM_POP(DCPLB_DATA15)
717 PM_POP(DCPLB_DATA14)
718 PM_POP(DCPLB_DATA13)
719 PM_POP(DCPLB_DATA12)
720 PM_POP(DCPLB_DATA11)
721 PM_POP(DCPLB_DATA10)
722 PM_POP(DCPLB_DATA9)
723 PM_POP(DCPLB_DATA8)
724 PM_POP(DCPLB_DATA7)
725 PM_POP(DCPLB_DATA6)
726 PM_POP(DCPLB_DATA5)
727 PM_POP(DCPLB_DATA4)
728 PM_POP(DCPLB_DATA3)
729 PM_POP(DCPLB_DATA2)
730 PM_POP(DCPLB_DATA1)
731 PM_POP(DCPLB_DATA0)
732 PM_POP(DCPLB_ADDR15)
733 PM_POP(DCPLB_ADDR14)
734 PM_POP(DCPLB_ADDR13)
735 PM_POP(DCPLB_ADDR12)
736 PM_POP(DCPLB_ADDR11)
737 PM_POP(DCPLB_ADDR10)
738 PM_POP(DCPLB_ADDR9)
739 PM_POP(DCPLB_ADDR8)
740 PM_POP(DCPLB_ADDR7)
741 PM_POP(DCPLB_ADDR6)
742 PM_POP(DCPLB_ADDR5)
743 PM_POP(DCPLB_ADDR4)
744 PM_POP(DCPLB_ADDR3)
745 PM_POP(DCPLB_ADDR2)
746 PM_POP(DCPLB_ADDR1)
747 PM_POP(DCPLB_ADDR0)
748 PM_POP(DMEM_CONTROL)
749
750 /* Restore System MMRs */
751
752 P0.H = hi(PLL_CTL);
753 P0.L = lo(PLL_CTL);
754 PM_SYS_POP16(SYSCR)
755
756#ifdef EBIU_FCTL
757 PM_SYS_POP(EBIU_FCTL)
758 PM_SYS_POP(EBIU_MODE)
759 PM_SYS_POP(EBIU_MBSCTL)
760#endif
761 PM_SYS_POP16(EBIU_AMGCTL)
762 PM_SYS_POP(EBIU_AMBCTL1)
763 PM_SYS_POP(EBIU_AMBCTL0)
764
765#ifdef PINT0_ASSIGN
766 PM_SYS_POP(PINT3_ASSIGN)
767 PM_SYS_POP(PINT2_ASSIGN)
768 PM_SYS_POP(PINT1_ASSIGN)
769 PM_SYS_POP(PINT0_ASSIGN)
770#endif
771
772#ifdef SICA_IWR1
773 PM_SYS_POP(SICA_IWR1)
774#endif
775#ifdef SICA_IWR0
776 PM_SYS_POP(SICA_IWR0)
777#endif
778#ifdef SIC_IWR2
779 PM_SYS_POP(SIC_IWR2)
780#endif
781#ifdef SIC_IWR1
782 PM_SYS_POP(SIC_IWR1)
783#endif
784#ifdef SIC_IWR0
785 PM_SYS_POP(SIC_IWR0)
786#endif
787#ifdef SIC_IWR
788 PM_SYS_POP(SIC_IWR)
789#endif
790
791#ifdef SICA_IAR0
792 PM_SYS_POP(SICA_IAR7)
793 PM_SYS_POP(SICA_IAR6)
794 PM_SYS_POP(SICA_IAR5)
795 PM_SYS_POP(SICA_IAR4)
796 PM_SYS_POP(SICA_IAR3)
797 PM_SYS_POP(SICA_IAR2)
798 PM_SYS_POP(SICA_IAR1)
799 PM_SYS_POP(SICA_IAR0)
800#endif
801
802#ifdef SIC_IAR8
803 PM_SYS_POP(SIC_IAR11)
804 PM_SYS_POP(SIC_IAR10)
805 PM_SYS_POP(SIC_IAR9)
806 PM_SYS_POP(SIC_IAR8)
807#endif
808#ifdef SIC_IAR7
809 PM_SYS_POP(SIC_IAR7)
810#endif
811#ifdef SIC_IAR6
812 PM_SYS_POP(SIC_IAR6)
813 PM_SYS_POP(SIC_IAR5)
814 PM_SYS_POP(SIC_IAR4)
815#endif
816#ifdef SIC_IAR3
817 PM_SYS_POP(SIC_IAR3)
818#endif
819#ifdef SIC_IAR2
820 PM_SYS_POP(SIC_IAR2)
821 PM_SYS_POP(SIC_IAR1)
822 PM_SYS_POP(SIC_IAR0)
823#endif
824#ifdef SICA_IMASK1
825 PM_SYS_POP(SICA_IMASK1)
826#endif
827#ifdef SICA_IMASK0
828 PM_SYS_POP(SICA_IMASK0)
829#endif
830#ifdef SIC_IMASK
831 PM_SYS_POP(SIC_IMASK)
832#endif
833#ifdef SIC_IMASK2
834 PM_SYS_POP(SIC_IMASK2)
835#endif
836#ifdef SIC_IMASK1
837 PM_SYS_POP(SIC_IMASK1)
838#endif
839#ifdef SIC_IMASK0
840 PM_SYS_POP(SIC_IMASK0)
841#endif
842
843 [--sp] = RETI; /* Clear Global Interrupt Disable */
844 SP += 4;
845
846 RETS = [SP++];
847 ( R7:0, P5:0 ) = [SP++];
848 RTS;
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 0be805ca423..4fe6a2366b1 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -38,8 +38,9 @@
38#include <linux/io.h> 38#include <linux/io.h>
39#include <linux/irq.h> 39#include <linux/irq.h>
40 40
41#include <asm/dpmc.h>
42#include <asm/gpio.h> 41#include <asm/gpio.h>
42#include <asm/dma.h>
43#include <asm/dpmc.h>
43 44
44#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H 45#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
45#define WAKEUP_TYPE PM_WAKE_HIGH 46#define WAKEUP_TYPE PM_WAKE_HIGH
@@ -61,16 +62,17 @@
61#define WAKEUP_TYPE PM_WAKE_BOTH_EDGES 62#define WAKEUP_TYPE PM_WAKE_BOTH_EDGES
62#endif 63#endif
63 64
65
64void bfin_pm_suspend_standby_enter(void) 66void bfin_pm_suspend_standby_enter(void)
65{ 67{
68 unsigned long flags;
69
66#ifdef CONFIG_PM_WAKEUP_BY_GPIO 70#ifdef CONFIG_PM_WAKEUP_BY_GPIO
67 gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); 71 gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
68#endif 72#endif
69 73
70 u32 flags;
71
72 local_irq_save(flags); 74 local_irq_save(flags);
73 bfin_pm_setup(); 75 bfin_pm_standby_setup();
74 76
75#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER 77#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
76 sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); 78 sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
@@ -78,7 +80,7 @@ void bfin_pm_suspend_standby_enter(void)
78 sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); 80 sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
79#endif 81#endif
80 82
81 bfin_pm_restore(); 83 bfin_pm_standby_restore();
82 84
83#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) 85#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
84 bfin_write_SIC_IWR0(IWR_ENABLE_ALL); 86 bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
@@ -93,6 +95,195 @@ void bfin_pm_suspend_standby_enter(void)
93 local_irq_restore(flags); 95 local_irq_restore(flags);
94} 96}
95 97
98int bf53x_suspend_l1_mem(unsigned char *memptr)
99{
100 dma_memcpy(memptr, (const void *) L1_CODE_START, L1_CODE_LENGTH);
101 dma_memcpy(memptr + L1_CODE_LENGTH, (const void *) L1_DATA_A_START,
102 L1_DATA_A_LENGTH);
103 dma_memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH,
104 (const void *) L1_DATA_B_START, L1_DATA_B_LENGTH);
105 memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH +
106 L1_DATA_B_LENGTH, (const void *) L1_SCRATCH_START,
107 L1_SCRATCH_LENGTH);
108
109 return 0;
110}
111
112int bf53x_resume_l1_mem(unsigned char *memptr)
113{
114 dma_memcpy((void *) L1_CODE_START, memptr, L1_CODE_LENGTH);
115 dma_memcpy((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH,
116 L1_DATA_A_LENGTH);
117 dma_memcpy((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH +
118 L1_DATA_A_LENGTH, L1_DATA_B_LENGTH);
119 memcpy((void *) L1_SCRATCH_START, memptr + L1_CODE_LENGTH +
120 L1_DATA_A_LENGTH + L1_DATA_B_LENGTH, L1_SCRATCH_LENGTH);
121
122 return 0;
123}
124
125#ifdef CONFIG_BFIN_WB
126static void flushinv_all_dcache(void)
127{
128 u32 way, bank, subbank, set;
129 u32 status, addr;
130 u32 dmem_ctl = bfin_read_DMEM_CONTROL();
131
132 for (bank = 0; bank < 2; ++bank) {
133 if (!(dmem_ctl & (1 << (DMC1_P - bank))))
134 continue;
135
136 for (way = 0; way < 2; ++way)
137 for (subbank = 0; subbank < 4; ++subbank)
138 for (set = 0; set < 64; ++set) {
139
140 bfin_write_DTEST_COMMAND(
141 way << 26 |
142 bank << 23 |
143 subbank << 16 |
144 set << 5
145 );
146 CSYNC();
147 status = bfin_read_DTEST_DATA0();
148
149 /* only worry about valid/dirty entries */
150 if ((status & 0x3) != 0x3)
151 continue;
152
153 /* construct the address using the tag */
154 addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
155
156 /* flush it */
157 __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
158 }
159 }
160}
161#endif
162
163static inline void dcache_disable(void)
164{
165#ifdef CONFIG_BFIN_DCACHE
166 unsigned long ctrl;
167
168#ifdef CONFIG_BFIN_WB
169 flushinv_all_dcache();
170#endif
171 SSYNC();
172 ctrl = bfin_read_DMEM_CONTROL();
173 ctrl &= ~ENDCPLB;
174 bfin_write_DMEM_CONTROL(ctrl);
175 SSYNC();
176#endif
177}
178
179static inline void dcache_enable(void)
180{
181#ifdef CONFIG_BFIN_DCACHE
182 unsigned long ctrl;
183 SSYNC();
184 ctrl = bfin_read_DMEM_CONTROL();
185 ctrl |= ENDCPLB;
186 bfin_write_DMEM_CONTROL(ctrl);
187 SSYNC();
188#endif
189}
190
191static inline void icache_disable(void)
192{
193#ifdef CONFIG_BFIN_ICACHE
194 unsigned long ctrl;
195 SSYNC();
196 ctrl = bfin_read_IMEM_CONTROL();
197 ctrl &= ~ENICPLB;
198 bfin_write_IMEM_CONTROL(ctrl);
199 SSYNC();
200#endif
201}
202
203static inline void icache_enable(void)
204{
205#ifdef CONFIG_BFIN_ICACHE
206 unsigned long ctrl;
207 SSYNC();
208 ctrl = bfin_read_IMEM_CONTROL();
209 ctrl |= ENICPLB;
210 bfin_write_IMEM_CONTROL(ctrl);
211 SSYNC();
212#endif
213}
214
215int bfin_pm_suspend_mem_enter(void)
216{
217 unsigned long flags;
218 int wakeup, ret;
219
220 unsigned char *memptr = kmalloc(L1_CODE_LENGTH + L1_DATA_A_LENGTH
221 + L1_DATA_B_LENGTH + L1_SCRATCH_LENGTH,
222 GFP_KERNEL);
223
224 if (memptr == NULL) {
225 panic("bf53x_suspend_l1_mem malloc failed");
226 return -ENOMEM;
227 }
228
229 wakeup = bfin_read_VR_CTL() & ~FREQ;
230 wakeup |= SCKELOW;
231
232 /* FIXME: merge this somehow with set_irq_wake */
233#ifdef CONFIG_PM_BFIN_WAKE_RTC
234 wakeup |= WAKE;
235#endif
236#ifdef CONFIG_PM_BFIN_WAKE_PH6
237 wakeup |= PHYWE;
238#endif
239#ifdef CONFIG_PM_BFIN_WAKE_CAN
240 wakeup |= CANWE;
241#endif
242#ifdef CONFIG_PM_BFIN_WAKE_GP
243 wakeup |= GPWE;
244#endif
245#ifdef CONFIG_PM_BFIN_WAKE_USB
246 wakeup |= USBWE;
247#endif
248#ifdef CONFIG_PM_BFIN_WAKE_KEYPAD
249 wakeup |= KPADWE;
250#endif
251#ifdef CONFIG_PM_BFIN_WAKE_ROTARY
252 wakeup |= ROTWE;
253#endif
254
255 local_irq_save(flags);
256
257 ret = blackfin_dma_suspend();
258
259 if (ret) {
260 local_irq_restore(flags);
261 kfree(memptr);
262 return ret;
263 }
264
265 bfin_gpio_pm_hibernate_suspend();
266
267 dcache_disable();
268 icache_disable();
269 bf53x_suspend_l1_mem(memptr);
270
271 do_hibernate(wakeup); /* Goodbye */
272
273 bf53x_resume_l1_mem(memptr);
274
275 icache_enable();
276 dcache_enable();
277
278 bfin_gpio_pm_hibernate_restore();
279 blackfin_dma_resume();
280
281 local_irq_restore(flags);
282 kfree(memptr);
283
284 return 0;
285}
286
96/* 287/*
97 * bfin_pm_valid - Tell the PM core that we only support the standby sleep 288 * bfin_pm_valid - Tell the PM core that we only support the standby sleep
98 * state 289 * state
@@ -101,7 +292,24 @@ void bfin_pm_suspend_standby_enter(void)
101 */ 292 */
102static int bfin_pm_valid(suspend_state_t state) 293static int bfin_pm_valid(suspend_state_t state)
103{ 294{
104 return (state == PM_SUSPEND_STANDBY); 295 return (state == PM_SUSPEND_STANDBY
296#ifndef BF533_FAMILY
297 /*
298 * On BF533/2/1:
299 * If we enter Hibernate the SCKE Pin is driven Low,
300 * so that the SDRAM enters Self Refresh Mode.
301 * However when the reset sequence that follows hibernate
302 * state is executed, SCKE is driven High, taking the
303 * SDRAM out of Self Refresh.
304 *
305 * If you reconfigure and access the SDRAM "very quickly",
306 * you are likely to avoid errors, otherwise the SDRAM
307 * start losing its contents.
308 * An external HW workaround is possible using logic gates.
309 */
310 || state == PM_SUSPEND_MEM
311#endif
312 );
105} 313}
106 314
107/* 315/*
@@ -115,10 +323,9 @@ static int bfin_pm_enter(suspend_state_t state)
115 case PM_SUSPEND_STANDBY: 323 case PM_SUSPEND_STANDBY:
116 bfin_pm_suspend_standby_enter(); 324 bfin_pm_suspend_standby_enter();
117 break; 325 break;
118
119 case PM_SUSPEND_MEM: 326 case PM_SUSPEND_MEM:
120 return -ENOTSUPP; 327 bfin_pm_suspend_mem_enter();
121 328 break;
122 default: 329 default:
123 return -EINVAL; 330 return -EINVAL;
124 } 331 }