diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2008-07-19 04:57:32 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-07-19 04:57:32 -0400 |
commit | 1efc80b53eb54770139219f99657abd92595fc86 (patch) | |
tree | 254c76b3aaf22110b116e67a8118945006cacce6 /arch | |
parent | 4f13f548cef5af1717cbbc341a1a3474f3e7466e (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')
-rw-r--r-- | arch/blackfin/Kconfig | 66 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 26 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 118 | ||||
-rw-r--r-- | arch/blackfin/mach-common/dpmc_modes.S | 600 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 225 |
5 files changed, 979 insertions, 56 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index c602727d1a9a..8f21b78b2e6f 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 | ||
882 | choice | 882 | choice |
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 |
886 | config PM_BFIN_SLEEP_DEEPER | 886 | config 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 | |||
902 | config PM_BFIN_SLEEP | 904 | config 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". | ||
911 | endchoice | 915 | endchoice |
912 | 916 | ||
913 | config PM_WAKEUP_BY_GPIO | 917 | config PM_WAKEUP_BY_GPIO |
914 | bool "Cause Wakeup Event by GPIO" | 918 | bool "Allow Wakeup from Standby by GPIO" |
915 | 919 | ||
916 | config PM_WAKEUP_GPIO_NUMBER | 920 | config 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" |
936 | endchoice | 940 | endchoice |
937 | 941 | ||
942 | comment "Possible Suspend Mem / Hibernate Wake-Up Sources" | ||
943 | depends on PM | ||
944 | |||
945 | config 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 | |||
952 | config 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 | |||
959 | config 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 | |||
966 | config 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 | |||
973 | config 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 | |||
980 | config 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 | |||
987 | config 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 | |||
938 | endmenu | 994 | endmenu |
939 | 995 | ||
940 | menu "CPU Frequency scaling" | 996 | menu "CPU Frequency scaling" |
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index d54f19085f37..ad0e75845ac2 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 | } |
473 | EXPORT_SYMBOL(get_dma_curr_addr); | 473 | EXPORT_SYMBOL(get_dma_curr_addr); |
474 | 474 | ||
475 | #ifdef CONFIG_PM | ||
476 | int 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 | |||
492 | void 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 | |||
475 | static void *__dma_memcpy(void *dest, const void *src, size_t size) | 501 | static 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 b6d89d1644cc..ecbd141e0ef2 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) | ||
191 | static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)]; | ||
192 | #else | ||
190 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 193 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
191 | static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; | 194 | static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; |
192 | static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 195 | static 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 |
207 | static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; | 210 | static 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 | ||
670 | u32 bfin_pm_setup(void) | 673 | u32 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 | ||
718 | void bfin_pm_restore(void) | 721 | void 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 | ||
749 | void 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 | |||
777 | void 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 | |||
812 | u32 bfin_pm_standby_setup(void) | ||
813 | { | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | void bfin_pm_standby_restore(void) | ||
818 | { | ||
819 | |||
820 | } | ||
821 | |||
822 | void 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 | |||
838 | void 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 | ||
749 | unsigned short get_gpio_dir(unsigned gpio) | 855 | unsigned 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 b7981d31c392..46ee77afed20 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 | ||
80 | ENTRY(_deep_sleep) | 79 | ENTRY(_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 | |||
236 | ENTRY(_set_dram_srfs) | 236 | ENTRY(_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); | 246 | 1: |
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); | ||
260 | 1: | ||
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 | |||
262 | ENTRY(_unset_dram_srfs) | 275 | ENTRY(_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 | ||
283 | ENTRY(_set_sic_iwr) | 301 | ENTRY(_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 | |||
348 | ENTRY(_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 | |||
605 | pm_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 0be805ca423f..4fe6a2366b13 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 | |||
64 | void bfin_pm_suspend_standby_enter(void) | 66 | void 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 | ||
98 | int 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 | |||
112 | int 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 | ||
126 | static 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 | |||
163 | static 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 | |||
179 | static 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 | |||
191 | static 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 | |||
203 | static 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 | |||
215 | int 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 | */ |
102 | static int bfin_pm_valid(suspend_state_t state) | 293 | static 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 | } |