123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- /*
- * arch/arm/mach-at91/pm_slow_clock.S
- *
- * Copyright (C) 2006 Savin Zlobec
- *
- * AT91SAM9 support:
- * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
- #include <linux/linkage.h>
- #include <mach/hardware.h>
- #include <mach/at91_pmc.h>
- #include <mach/at91_ramc.h>
- #ifdef CONFIG_ARCH_AT91SAM9263
- /*
- * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
- * handle those cases both here and in the Suspend-To-RAM support.
- */
- #warning Assuming EB1 SDRAM controller is *NOT* used
- #endif
- /*
- * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
- * clock during suspend by adjusting its prescalar and divisor.
- * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
- * are errata regarding adjusting the prescalar and divisor.
- */
- #undef SLOWDOWN_MASTER_CLOCK
- #define MCKRDY_TIMEOUT 1000
- #define MOSCRDY_TIMEOUT 1000
- #define PLLALOCK_TIMEOUT 1000
- #define PLLBLOCK_TIMEOUT 1000
- pmc .req r0
- sdramc .req r1
- ramc1 .req r2
- memctrl .req r3
- tmp1 .req r4
- tmp2 .req r5
- /*
- * Wait until master clock is ready (after switching master clock source)
- */
- .macro wait_mckrdy
- mov tmp2, #MCKRDY_TIMEOUT
- 1: sub tmp2, tmp2, #1
- cmp tmp2, #0
- beq 2f
- ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MCKRDY
- beq 1b
- 2:
- .endm
- /*
- * Wait until master oscillator has stabilized.
- */
- .macro wait_moscrdy
- mov tmp2, #MOSCRDY_TIMEOUT
- 1: sub tmp2, tmp2, #1
- cmp tmp2, #0
- beq 2f
- ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MOSCS
- beq 1b
- 2:
- .endm
- /*
- * Wait until PLLA has locked.
- */
- .macro wait_pllalock
- mov tmp2, #PLLALOCK_TIMEOUT
- 1: sub tmp2, tmp2, #1
- cmp tmp2, #0
- beq 2f
- ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_LOCKA
- beq 1b
- 2:
- .endm
- /*
- * Wait until PLLB has locked.
- */
- .macro wait_pllblock
- mov tmp2, #PLLBLOCK_TIMEOUT
- 1: sub tmp2, tmp2, #1
- cmp tmp2, #0
- beq 2f
- ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_LOCKB
- beq 1b
- 2:
- .endm
- .text
- /* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
- * void __iomem *ramc1, int memctrl)
- */
- ENTRY(at91_slow_clock)
- /* Save registers on stack */
- stmfd sp!, {r4 - r12, lr}
- /*
- * Register usage:
- * R0 = Base address of AT91_PMC
- * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
- * R2 = Base address of second RAM Controller or 0 if not present
- * R3 = Memory controller
- * R4 = temporary register
- * R5 = temporary register
- */
- /* Drain write buffer */
- mov tmp1, #0
- mcr p15, 0, tmp1, c7, c10, 4
- cmp memctrl, #AT91_MEMCTRL_MC
- bne ddr_sr_enable
- /*
- * at91rm9200 Memory controller
- */
- /* Put SDRAM in self-refresh mode */
- mov tmp1, #1
- str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
- b sdr_sr_done
- /*
- * DDRSDR Memory controller
- */
- ddr_sr_enable:
- cmp memctrl, #AT91_MEMCTRL_DDRSDR
- bne sdr_sr_enable
- /* prepare for DDRAM self-refresh mode */
- ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
- str tmp1, .saved_sam9_lpr
- bic tmp1, #AT91_DDRSDRC_LPCB
- orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
- /* figure out if we use the second ram controller */
- cmp ramc1, #0
- ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
- strne tmp2, .saved_sam9_lpr1
- bicne tmp2, #AT91_DDRSDRC_LPCB
- orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
- /* Enable DDRAM self-refresh mode */
- str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
- strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
- b sdr_sr_done
- /*
- * SDRAMC Memory controller
- */
- sdr_sr_enable:
- /* Enable SDRAM self-refresh mode */
- ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
- str tmp1, .saved_sam9_lpr
- bic tmp1, #AT91_SDRAMC_LPCB
- orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
- str tmp1, [sdramc, #AT91_SDRAMC_LPR]
- sdr_sr_done:
- /* Save Master clock setting */
- ldr tmp1, [pmc, #AT91_PMC_MCKR]
- str tmp1, .saved_mckr
- /*
- * Set the Master clock source to slow clock
- */
- bic tmp1, tmp1, #AT91_PMC_CSS
- str tmp1, [pmc, #AT91_PMC_MCKR]
- wait_mckrdy
- #ifdef SLOWDOWN_MASTER_CLOCK
- /*
- * Set the Master Clock PRES and MDIV fields.
- *
- * See AT91RM9200 errata #27 and #28 for details.
- */
- mov tmp1, #0
- str tmp1, [pmc, #AT91_PMC_MCKR]
- wait_mckrdy
- #endif
- /* Save PLLA setting and disable it */
- ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
- str tmp1, .saved_pllar
- mov tmp1, #AT91_PMC_PLLCOUNT
- orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
- str tmp1, [pmc, #AT91_CKGR_PLLAR]
- /* Save PLLB setting and disable it */
- ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
- str tmp1, .saved_pllbr
- mov tmp1, #AT91_PMC_PLLCOUNT
- str tmp1, [pmc, #AT91_CKGR_PLLBR]
- /* Turn off the main oscillator */
- ldr tmp1, [pmc, #AT91_CKGR_MOR]
- bic tmp1, tmp1, #AT91_PMC_MOSCEN
- str tmp1, [pmc, #AT91_CKGR_MOR]
- /* Wait for interrupt */
- mcr p15, 0, tmp1, c7, c0, 4
- /* Turn on the main oscillator */
- ldr tmp1, [pmc, #AT91_CKGR_MOR]
- orr tmp1, tmp1, #AT91_PMC_MOSCEN
- str tmp1, [pmc, #AT91_CKGR_MOR]
- wait_moscrdy
- /* Restore PLLB setting */
- ldr tmp1, .saved_pllbr
- str tmp1, [pmc, #AT91_CKGR_PLLBR]
- tst tmp1, #(AT91_PMC_MUL & 0xff0000)
- bne 1f
- tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
- beq 2f
- 1:
- wait_pllblock
- 2:
- /* Restore PLLA setting */
- ldr tmp1, .saved_pllar
- str tmp1, [pmc, #AT91_CKGR_PLLAR]
- tst tmp1, #(AT91_PMC_MUL & 0xff0000)
- bne 3f
- tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
- beq 4f
- 3:
- wait_pllalock
- 4:
- #ifdef SLOWDOWN_MASTER_CLOCK
- /*
- * First set PRES if it was not 0,
- * than set CSS and MDIV fields.
- *
- * See AT91RM9200 errata #27 and #28 for details.
- */
- ldr tmp1, .saved_mckr
- tst tmp1, #AT91_PMC_PRES
- beq 2f
- and tmp1, tmp1, #AT91_PMC_PRES
- str tmp1, [pmc, #AT91_PMC_MCKR]
- wait_mckrdy
- #endif
- /*
- * Restore master clock setting
- */
- 2: ldr tmp1, .saved_mckr
- str tmp1, [pmc, #AT91_PMC_MCKR]
- wait_mckrdy
- /*
- * at91rm9200 Memory controller
- * Do nothing - self-refresh is automatically disabled.
- */
- cmp memctrl, #AT91_MEMCTRL_MC
- beq ram_restored
- /*
- * DDRSDR Memory controller
- */
- cmp memctrl, #AT91_MEMCTRL_DDRSDR
- bne sdr_en_restore
- /* Restore LPR on AT91 with DDRAM */
- ldr tmp1, .saved_sam9_lpr
- str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
- /* if we use the second ram controller */
- cmp ramc1, #0
- ldrne tmp2, .saved_sam9_lpr1
- strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
- b ram_restored
- /*
- * SDRAMC Memory controller
- */
- sdr_en_restore:
- /* Restore LPR on AT91 with SDRAM */
- ldr tmp1, .saved_sam9_lpr
- str tmp1, [sdramc, #AT91_SDRAMC_LPR]
- ram_restored:
- /* Restore registers, and return */
- ldmfd sp!, {r4 - r12, pc}
- .saved_mckr:
- .word 0
- .saved_pllar:
- .word 0
- .saved_pllbr:
- .word 0
- .saved_sam9_lpr:
- .word 0
- .saved_sam9_lpr1:
- .word 0
- ENTRY(at91_slow_clock_sz)
- .word .-at91_slow_clock
|