Author: wmb Date: Sun Sep 2 01:57:24 2012 New Revision: 3270 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3270
Log: OLPC ARM - Implemented suspend/resume for XO-4, in the process refactoring the XO-1.75 suspend/resume code so much of it could be shared.
Added: cpu/arm/mmp2/showirqs.fth cpu/arm/mmp2/wakeups.fth cpu/arm/mmp3/dramrecal.fth cpu/arm/olpc/suspend.fth Modified: cpu/arm/mmp2/dramrecal.fth cpu/arm/mmp2/socregs.fth cpu/arm/olpc/build-fw.fth
Modified: cpu/arm/mmp2/dramrecal.fth ============================================================================== --- cpu/arm/mmp2/dramrecal.fth Sun Sep 2 01:42:57 2012 (r3269) +++ cpu/arm/mmp2/dramrecal.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -1,5 +1,5 @@ \ See license at end of file -purpose: Recalibrate DDR3 DRAM +purpose: Recalibrate DDR3 DRAM (SoC-specific low-level power management factors)
\ DDR3 DRAM requires periodic recalibration to cope with parameter drift from \ temperature variation. The recalibration below affects both the DLL and @@ -189,14 +189,7 @@ end-code here ddr-self-refresh - constant /ddr-self-refresh
-memctrl-pa constant memctrl-va - : ddr-code-to-sram ( -- ) - memctrl-pa h# c02 or memctrl-va map-section \ Map the memory controller - -\ sram is already mapped by initmmu.fth -\ sram-pa h# c0e or sram-va map-section \ Make the code cacheable - ddr-recal 'ddr-recal /ddr-recal move 'ddr-recal /ddr-recal sync-cache
@@ -227,124 +220,6 @@ mov pc,r1 c;
-: apbc-clr-rst ( offset -- ) 4 swap +apbc io-clr ; -: apbc-set-rst ( offset -- ) 4 swap +apbc io-set ; - -: disable-apbc-clks ( -- ) - \ 3 h# 38 +apbc io-clr \ GPIO - 3 h# 74 +apbc io-clr \ MPMU - 3 h# 78 +apbc io-clr \ IPC - 3 h# 90 +apbc io-clr \ THSENS1 - - \ h# 38 apbc-set-rst - \ h# 74 apbc-set-rst \ MPMU - resetting this kills TIMER2, used by the SP PS/2 - h# 78 apbc-set-rst \ IPC - h# 90 apbc-set-rst \ THSENS1 -; -: enable-apbc-clks ( -- ) - \ 3 h# 38 +apbc io-set \ GPIO - 3 h# 74 +apbc io-set \ MPMU - 3 h# 78 +apbc io-set \ IPC - 3 h# 90 +apbc io-set \ THSENS1 - - \ h# 38 apbc-clr-rst - h# 74 apbc-clr-rst \ MPMU - h# 78 apbc-clr-rst \ IPC - h# 90 apbc-clr-rst \ THSENS1 -; -: disable-scu-clks ( -- ) - 0 h# 64 +scu io! \ SCU_AXIFAB_CKGT_CTRL0 - Close AXI fabric clock gate - 0 h# 68 +scu io! \ SCU_AXIFAB_CKGT_CTRL1 - h# f0 h# 1c +scu io-set \ SCU_MCB_CONF -; -: enable-scu-clks ( -- ) - h# 3003003 h# 64 +scu io! \ SCU_AXIFAB_CKGT_CTRL0 - Open AXI fabric clock gate - h# 0303030 h# 68 +scu io! \ SCU_AXIFAB_CKGT_CTRL1 - h# f0 h# 1c +scu io-clr \ SCU_MCB_CONF -; -: disable-apmu-clks ( -- ) - h# 1b h# 54 +pmua io-clr \ PMUA_SDH0_CLK_RES_CTRL - h# 1b h# 58 +pmua io-clr \ PMUA_SDH1_CLK_RES_CTRL - h# 1b h# e8 +pmua io-clr \ PMUA_SDH2_CLK_RES_CTRL - h# 1b h# d4 +pmua io-clr \ PMUA_SMC_CLK_RES_CTRL - h# 3f h# 60 +pmua io-clr \ PMUA_NF_CLK_RES_CTRL - h# 3f h# d8 +pmua io-clr \ PMUA_MSPRO_CLK_RES_CTRL - XO does not use MSPRO - h# 12 h# 10c +pmua io-clr \ PMUA_AUDIO_CLK_RES_CTRL - h# 1fffd h# dc +pmua io-clr \ PMUA_GLB_CLK_RES_CTRL -\ 0 h# 68 pmua! \ PMUA_WTM_CLK_RES_CTRL - h# 9 h# 5c +pmua io-clr \ PMUA_USB_CLK_RES_CTRL -; -: enable-apmu-clks ( -- ) - h# 1b h# 54 +pmua io-set \ PMUA_SDH0_CLK_RES_CTRL - h# 1b h# 58 +pmua io-set \ PMUA_SDH1_CLK_RES_CTRL - h# 1b h# e8 +pmua io-set \ PMUA_SDH2_CLK_RES_CTRL - h# 1b h# d4 +pmua io-set \ PMUA_SMC_CLK_RES_CTRL \ ??? what is this and why is it on? - h# 3f h# 60 +pmua io-set \ PMUA_NF_CLK_RES_CTRL \ Should this be on? -\ h# 3f h# d8 +pmua io-set \ PMUA_MSPRO_CLK_RES_CTRL - h# 12 h# 10c +pmua io-set \ PMUA_AUDIO_CLK_RES_CTRL - h# 1fffd h# dc +pmua io-set \ PMUA_GLB_CLK_RES_CTRL -\ h# 1b h# 68 pmua! \ PMUA_WTM_CLK_RES_CTRL - h# 9 h# 5c +pmua io-set \ PMUA_USB_CLK_RES_CTRL -; -: pll2? ( -- flag ) h# 34 mpmu@ h# 100 and 0<> ; -: disable-mpmu-clks ( -- ) - pll2? if h# e010 else h# a010 then ( cgr-value ) - dup h# 1024 mpmu! \ MPMU_CGR_PJ - h# 0024 mpmu! \ MPMU_CGR_SP - -\ h# 2000.0000 h# 414 +mpmu io-clr \ MPMU_PLL2_CTRL1 - h# 8000.0000 h# 0040 +mpmu io-clr \ MPMU_ISCCR1 - h# 8000.0000 h# 0044 +mpmu io-clr \ MPMU_ISCCR2 -; -: enable-mpmu-clks ( -- ) - h# dffe.fffe h# 1024 mpmu! \ MPMU_ACGR -\ h# 2000.0000 h# 0414 +mpmu io-set \ MPMU_PLL2_CTRL1 - h# 8000.0000 h# 0040 +mpmu io-set \ MPMU_ISCCR1 - h# 8000.0000 h# 0044 +mpmu io-set \ MPMU_ISCCR2 -; -: disable-twsi-clks ( -- ) - \ set RST in APBC_TWSIx_CLK_RST registers - -[ifdef] notdef - \ just disable TWSI1 clk rather than reset it since it's needed to access PMIC onkey - \ when system is waken up from low power mode */ - 0 4 +apbc io! \ Disable TWSI1 clock -[else] - h# 04 apbc-set-rst \ TWSI1 -[then] - h# 08 apbc-set-rst \ TWSI2 - h# 0c apbc-set-rst \ TWSI3 - h# 10 apbc-set-rst \ TWSI4 - h# 7c apbc-set-rst \ TWSI5 - h# 80 apbc-set-rst \ TWSI6 -; -: enable-twsi-clks ( -- ) -[ifdef] notdef - 3 4 +apbc io! \ Enable TWSI1 clock -[else] - h# 04 apbc-clr-rst \ TWSI1 -[then] - h# 08 apbc-clr-rst \ TWSI2 - h# 0c apbc-clr-rst \ TWSI3 - h# 10 apbc-clr-rst \ TWSI4 - h# 7c apbc-clr-rst \ TWSI5 - h# 80 apbc-clr-rst \ TWSI6 -; -: disable-clks ( -- ) - disable-twsi-clks - disable-apbc-clks - disable-scu-clks - disable-apmu-clks - disable-mpmu-clks -; -: enable-clks ( -- ) - enable-mpmu-clks - enable-apmu-clks - enable-scu-clks - enable-apbc-clks - enable-twsi-clks -; - \ Wakeup ports - from datasheet page 718 \ WAKEUP0: CAWAKE (MIPI-HSI wakeup) \ WAKEUP1: Audio Island @@ -362,301 +237,6 @@ ; : block-irqs ( -- ) 1 h# 110 +icu io! ;
-\ XXX we might need to set GPIOs 71 and 160 (ps2 clocks), and perhaps the dat lines too, -\ for non-sleep-mode control - or maybe for sleep mode control as inputs. -\ We also may need to enable falling edge detects. -: disable-int40 ( -- ) - d# 40 disable-interrupt - 1 h# 29.00cc io-set \ Unmask the inter-processor communications interrupt -; - -: gpio-wakeup? ( gpio# -- flag ) - h# 019800 over 5 rshift la+ l@ ( gpio# mask ) - swap h# 1f and ( mask bit# ) - 1 swap lshift and 0<> ( flag ) -; - -: .masked ( irq# -- ) - dup /l* h# 10c + icu@ ( irq# masked ) - 1 and if ( irq# ) - ." IRQ" .d ." is masked off" cr - else ( irq# ) - drop ( ) - then ( ) -; -: .selected ( irq# -- ) - dup /l* h# 100 + icu@ ( irq# n ) - dup h# 40 and if ( irq# n ) - ." IRQ" swap .d ( n ) - ." selected INT" h# 3f and .d cr ( ) - else ( irq# n ) - 2drop ( ) - then ( ) -; -: (.pending) ( d -- ) - ." pending INTs: " ( d ) - d# 64 0 do ( d ) - over 1 and if i .d then ( d ) - d2/ ( d' ) - loop ( d ) - 2drop ( ) -; -: .pending ( irq# -- ) - dup 2* /l* h# 130 + dup icu@ swap la1+ icu@ ( irq# d ) - 2dup d0= if ( irq# d ) - 3drop ( ) - else ( irq# d ) - ." IRQ " rot .d (.pending) cr ( ) - then ( ) -; - -: bit? ( n bit# -- n flag ) 1 swap lshift over and 0<> ; -: .ifbit ( n bit# msg$ -- n ) - 2>r bit? if ( n r: msg$ ) - 2r> type space ( n ) - else ( n r: msg$ ) - 2r> 2drop ( n ) - then ( n ) -; -: .enabled-ints ( -- ) - d# 64 0 do ( ) - i /l* icu@ dup h# 70 and if ( n ) - ." INT" i .d ." -> IRQ" ( n ) - 4 " 0" .ifbit ( n ) - 5 " 1" .ifbit ( n ) - 6 " 2" .ifbit ( n ) - ." Pri " h# f and .d cr ( ) - else ( n ) - drop ( ) - then ( ) - loop ( ) -; -: .int4 ( -- ) - ." INT4 - mask " h# 168 icu@ .x - ." status " h# 150 icu@ dup .x - 0 " USB " .ifbit - 1 " PMIC" .ifbit - drop cr -; -: .int5 ( -- ) - ." INT5 - mask " h# 16c icu@ .x - ." status " h# 154 icu@ dup .x - 0 " RTC " .ifbit - 1 " RTC_Alarm" .ifbit - drop cr -; -: .int9 ( -- ) - ." INT9 - mask " h# 17c icu@ .x - ." status " h# 180 icu@ dup .x - 0 " Keypad " .ifbit - 1 " Rotary " .ifbit - 2 " Trackball" .ifbit - drop cr -; -: .int17 ( -- ) - ." INT17 - mask " h# 170 icu@ .x - ." status " h# 158 icu@ dup .x ( n ) - 7 2 do ( n ) - dup 1 and if ( n ) - ." TWSI" i .d ( n ) - then ( n ) - u2/ ( n' ) - loop ( n ) - drop cr ( ) -; -: .int35 ( -- ) - ." INT35 - mask " h# 174 icu@ .x - ." status " h# 15c icu@ dup .x - d# 0 " PJ_PerfMon" .ifbit - d# 1 " L2_PA_ECC" .ifbit - d# 2 " L2_ECC" .ifbit - d# 3 " L2_UECC" .ifbit - d# 4 " DDR" .ifbit - d# 5 " Fabric0" .ifbit - d# 6 " Fabric1" .ifbit - d# 7 " Fabric2" .ifbit - d# 9 " Thermal" .ifbit - d# 10 " MainPMU" .ifbit - d# 11 " WDT2" .ifbit - d# 12 " CoreSight" .ifbit - d# 13 " PJ_Commtx" .ifbit - d# 14 " PJ_Commrx" .ifbit - drop - cr -; -: .int51 ( -- ) - ." INT51 - mask " h# 178 icu@ .x - ." status " h# 160 icu@ dup .x - 0 " HSI_CAWAKE1 " .ifbit - 1 " MIPI_HSI1" .ifbit - drop cr -; -: .int55 ( -- ) - ." INT55 - mask " h# 184 icu@ .x - ." status " h# 188 icu@ dup .x - 0 " HSI_CAWAKE0 " .ifbit - 1 " MIPI_HSI0" .ifbit - drop cr -; - -: .fiq ( -- ) - h# 304 icu@ if ." FIQ is masked off" cr then - h# 300 icu@ dup h# 40 and if ." FIQ selected INT: " h# 3f and .d cr else drop then - h# 310 icu@ h# 314 icu@ 2dup d0= if ( d ) - 2drop ( ) - else ( d ) - ." FIQ " (.pending) cr ( ) - then ( ) -; - -: .icu ( -- ) - .enabled-ints - 3 0 do i .masked i .selected i .pending loop - \ XXX should handle DMA interrupts too - .fiq - .int4 .int5 .int9 .int17 .int35 .int51 .int55 -; -string-array wakeup-bit-names - ," WU0 " - ," WU1 " - ," WU2 " - ," WU3 " - ," WU4 " - ," WU5 " - ," WU6 " - ," WU7 " - ," TIMER_1_1 " - ," TIMER_1_2 " - ," TIMER_1_3 " - ," MSP_INS " - ," AUDIO " - ," WDT1 " - ," TIMER_2_1 " - ," TIMER_2_2 " - ," TIMER_2_3 " - ," RTC_ALARM " - ," WDT2 " - ," ROTARY " - ," TRACKBALL " - ," KEYPRESS " - ," SDH3_CARD " - ," SDH1_CARD " - ," FULL_IDLE " - ," ASYNC_INT " - ," SSP1_SRDY " - ," CAWAKE " - ," resv28 " - ," SSP3_SRDY " - ," ALL_WU " - ," resv31 " -end-string-array - -string-array wakeup-mask-names - ," WU0 " - ," WU1 " - ," WU2 " - ," WU3 " - ," WU4 " - ," WU5 " - ," WU6 " - ," WU7 " - ," TIMER_1_1 " - ," TIMER_1_2 " - ," TIMER_1_3 " - ," " - ," " - ," " - ," TIMER_2_1 " - ," TIMER_2_2 " - ," TIMER_2_3 " - ," RTC_ALARM " - ," WDT2 " - ," ROTARY " - ," TRACKBALL " - ," KEYPRESS " - ," SDH3_CARD " - ," SDH1_CARD " - ," FULL_IDLE " - ," ASYNC_INT " - ," WDT1 " - ," SSP3_SRDY " - ," SSP1_SRDY " - ," CAWAKE " - ," MSP_INS " - ," resv31 " -end-string-array - -: .active-wakeups ( -- ) - ." Wakeups: " - h# 1048 mpmu@ ( n ) - d# 31 0 do ( n ) - dup 1 and if i wakeup-bit-names count type then ( n ) - u2/ ( n' ) - loop ( n ) - drop cr ( ) -; -: .wakeup-mask ( -- ) - ." Enabled wakeups: " - h# 4c mpmu@ h# 104c or ( n ) - d# 31 0 do ( n ) - dup 1 and if i wakeup-mask-names count type then ( n ) - u2/ ( n' ) - loop ( n ) - drop cr ( ) -; -: .edges ( -- ) - ." Wakeup edges: " ( ) - d# 6 0 do ( ) - h# 19800 i la+ io@ ( n ) - d# 32 0 do ( n ) - dup 1 and if ( n ) - j d# 32 * i + .d ( n ) - then ( n ) - u2/ ( n' ) - loop ( n ) - drop ( ) - loop ( ) - cr ( ) -; -: .edge-enables ( -- ) - ." Enabled edges: " - d# 160 0 do - i af@ dup h# 70 and h# 40 <> if ( n ) - dup h# 10 and if ." R" then ( n ) - dup h# 20 and if ." F" then ( n ) - dup h# 40 and if ." C" then ( n ) - i .d ( n ) - then ( n ) - drop ( ) - loop -; -: .wakeup ( -- ) .active-wakeups .wakeup-mask .edges .edge-enables ; - -: .irqstat ( -- ) h# 148 h# 130 do i icu@ . 4 +loop ; -\ !!! The problem right now is that I have woken from keyboard, but the interrupt is still asserted -\ So perhaps the interrupt handler didn't fire -: rotate-wakeup? ( -- flag ) d# 15 gpio-wakeup? ; -: kbd-wakeup? ( -- flag ) d# 71 gpio-wakeup? ; -: tpd-wakeup? ( -- flag ) d# 160 gpio-wakeup? ; -\ We need to do this in the SP interrupt handler -: clear-wakeup ( gpio# -- ) - dup af@ ( gpio# value ) - 2dup h# 40 or swap af! ( gpio# value ) - swap af! -; -\ How to wakeup from SP: -: setup-key-wakeup ( -- ) - d# 24 d# 15 do h# b0 i af! loop \ Wake SoC on game keys -[ifdef] soc-kbd-clk-gpio# - h# 220 soc-kbd-clk-gpio# af! \ Wake SoC on KBD CLK falling edge - h# 221 soc-tpd-clk-gpio# af! \ Wake SoC on TPD CLK falling edge -[then] - h# 4 h# 4c +mpmu io-set \ Pin edge (GPIO per datasheet) wakes SoC - ['] disable-int40 d# 40 interrupt-handler! - d# 40 enable-interrupt \ SP to PJ4 communications interrupt - 1 h# 29.00cc io-clr \ Unmask the inter-processor communications interrupt -; - : breadcrumb ( n -- ) h# d000.0110 l! ;
0 value save-apcr @@ -749,137 +329,31 @@ h# 1000 mpmu! ( ) \ Set APCR register
\ end mmp2_pm_enter_lowpower_mode(state) -; - -[ifdef] soc-en-kbd-pwr-gpio# -: keyboard-power-on ( -- ) soc-en-kbd-pwr-gpio# gpio-clr ; -: keyboard-power-off ( -- ) soc-en-kbd-pwr-gpio# gpio-set ; -[else] -: keyboard-power-on ( -- ) ; -: keyboard-power-off ( -- ) ; -[then] -: wlan-power-on ( -- ) en-wlan-pwr-gpio# gpio-set ; -: wlan-power-off ( -- ) en-wlan-pwr-gpio# gpio-clr h# 040 en-wlan-pwr-gpio# af! h# 040 wlan-pd-gpio# af! h# 040 wlan-reset-gpio# af! ; -: wlan-stay-on ( -- ) h# 140 en-wlan-pwr-gpio# af! h# 140 wlan-pd-gpio# af! h# 140 wlan-reset-gpio# af! ; - -0 value sleep-mask -: screen-sleep - sleep-mask 1 and if \ DCON power down - dcon-freeze - else - " dcon-suspend" $call-dcon - then - " sleep" $call-screen - " set-ack" $call-ec - - \ 0 h# 54 pmua! \ Kill the SDIO 0 clocks - insignificant savings - \ 0 h# 58 pmua! \ Kill the SDIO 1 clocks - insignificant savings - sleep-mask 2 and 0= if keyboard-power-off then \ Should save about 17 mW - sleep-mask 4 and if - wlan-stay-on - else - " /wlan" " sleep" execute-device-method drop - wlan-power-off - then \ saves 100 mW -; -: screen-wake ( -- ) - sleep-mask 4 and 0= if - wlan-power-on - " /wlan" " wake" execute-device-method drop - then - sleep-mask 2 and 0= if keyboard-power-on then - " clr-ack" $call-ec - " wake" $call-screen - sleep-mask 1 and if \ DCON power up - dcon-unfreeze - else - " dcon-resume" $call-dcon - then -; - -: stdin-idle-on ['] safe-idle to stdin-idle d# 15 enable-interrupt ; -: stdin-idle-off ['] noop to stdin-idle ( install-uart-io ) d# 15 disable-interrupt ; + h# 000c.0000 h# 8c +pmua io-set \ Power down CoreSight SRAM
-: timers-sleep ( -- ) - 0 h# 14048 io! \ Disable interrupts from the tick timer - 7 h# 1407c io! \ Clear any pending interrupts - h# f disable-interrupt \ Block timer interrupt -; -: timers-wake ( -- ) - 1 h# 14048 io! \ Enable interrupts from the tick timer - 7 h# 1407c io! \ Clear any pending interrupts - h# f enable-interrupt \ Unblock timer interrupt - reschedule-tick + block-irqs ;
: power-islands-off ( -- ) + \ TODO - need to power down sram/l2$ + \ mmp2_cpu_disable_l2(0); + \ outer_cache.flush_range(0, -1ul); + +[ifdef] use-gpio + 3 gpio-dir-out +[then] 0 h# 10c pmua! \ Turn off audio power island ; : power-islands-on ( -- ) h# 712 h# 10c pmua! \ Turn on audio power island ; - -: str ( -- ) -[ifdef] use-gpio - 3 gpio-dir-out -[then] - - disable-interrupts - suspend-usb - timers-sleep - - screen-sleep - stdin-idle-off - 5 h# 38 mpmu! \ Use 32 kHz clock instead of VCXO for slow clock - -\ OLPC: Unmask main PMU interrupt - don't know if this is necessary -\ h# 400 h# 174 +icu io-clr -\ d# 35 enable-interrupt - -\ The PMIC_INT line is unconnected on XO-1.75. Normally it would come from the EC, -\ presumably for the purpose of waking on a keystroke. -\ 4 enable-interrupt \ Route PMIC interrupt to PJ4 IRQ -\ 2 h# 168 +icu io-clr \ Enable PMIC interrupt - - setup-sleep-state - - h# 000c.0000 h# 8c +pmua io-set \ Power down CoreSight SRAM - - \ TODO - need to power down sram/l2$ - \ mmp2_cpu_disable_l2(0); - \ outer_cache.flush_range(0, -1ul); - - power-islands-off - - disable-clks - - \ begin mmp2_cpu_do_idle() - block-irqs ( ) \ Block IRQs - will be cleared by PMU -[ifdef] use-hw-s3 +: do-wfi ( -- ) + [ifdef] use-hw-s3 wfi [else] do-self-refresh [then] - - restore-run-state - \ end mmp2_cpu_do_idle() - - enable-clks - - power-islands-on - - \ mmp2_cpu_enable_l2(0); - - \ idle_cfg &= (~PMUA_MOH_SRAM_PWRDWN); - stdin-idle-on - - screen-wake - timers-wake - resume-usb - enable-interrupts - init-thermal-sensor ; -: strp ( -- ) ec-rst-pwr str ec-max-pwr .d ." mW " soc .% space ;
\ LICENSE_BEGIN \ Copyright (c) 2011 FirmWorks
Added: cpu/arm/mmp2/showirqs.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ cpu/arm/mmp2/showirqs.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -0,0 +1,169 @@ +\ See license at end of file +purpose: Display the state of the MMP2 ICU interrupt controller + +: .masked ( irq# -- ) + dup /l* h# 10c + icu@ ( irq# masked ) + 1 and if ( irq# ) + ." IRQ" .d ." is masked off" cr + else ( irq# ) + drop ( ) + then ( ) +; +: .selected ( irq# -- ) + dup /l* h# 100 + icu@ ( irq# n ) + dup h# 40 and if ( irq# n ) + ." IRQ" swap .d ( n ) + ." selected INT" h# 3f and .d cr ( ) + else ( irq# n ) + 2drop ( ) + then ( ) +; +: (.pending) ( d -- ) + ." pending INTs: " ( d ) + d# 64 0 do ( d ) + over 1 and if i .d then ( d ) + d2/ ( d' ) + loop ( d ) + 2drop ( ) +; +: .pending ( irq# -- ) + dup 2* /l* h# 130 + dup icu@ swap la1+ icu@ ( irq# d ) + 2dup d0= if ( irq# d ) + 3drop ( ) + else ( irq# d ) + ." IRQ " rot .d (.pending) cr ( ) + then ( ) +; + +: bit? ( n bit# -- n flag ) 1 swap lshift over and 0<> ; +: .ifbit ( n bit# msg$ -- n ) + 2>r bit? if ( n r: msg$ ) + 2r> type space ( n ) + else ( n r: msg$ ) + 2r> 2drop ( n ) + then ( n ) +; +: .enabled-ints ( -- ) + d# 64 0 do ( ) + i /l* icu@ dup h# 70 and if ( n ) + ." INT" i .d ." -> IRQ" ( n ) + 4 " 0" .ifbit ( n ) + 5 " 1" .ifbit ( n ) + 6 " 2" .ifbit ( n ) + ." Pri " h# f and .d cr ( ) + else ( n ) + drop ( ) + then ( ) + loop ( ) +; +: .int4 ( -- ) + ." INT4 - mask " h# 168 icu@ .x + ." status " h# 150 icu@ dup .x + 0 " USB " .ifbit + 1 " PMIC" .ifbit + drop cr +; +: .int5 ( -- ) + ." INT5 - mask " h# 16c icu@ .x + ." status " h# 154 icu@ dup .x + 0 " RTC " .ifbit + 1 " RTC_Alarm" .ifbit + drop cr +; +: .int9 ( -- ) + ." INT9 - mask " h# 17c icu@ .x + ." status " h# 180 icu@ dup .x + 0 " Keypad " .ifbit + 1 " Rotary " .ifbit + 2 " Trackball" .ifbit + drop cr +; +: .int17 ( -- ) + ." INT17 - mask " h# 170 icu@ .x + ." status " h# 158 icu@ dup .x ( n ) + 7 2 do ( n ) + dup 1 and if ( n ) + ." TWSI" i .d ( n ) + then ( n ) + u2/ ( n' ) + loop ( n ) + drop cr ( ) +; +: .int35 ( -- ) + ." INT35 - mask " h# 174 icu@ .x + ." status " h# 15c icu@ dup .x + d# 0 " PJ_PerfMon" .ifbit + d# 1 " L2_PA_ECC" .ifbit + d# 2 " L2_ECC" .ifbit + d# 3 " L2_UECC" .ifbit + d# 4 " DDR" .ifbit + d# 5 " Fabric0" .ifbit + d# 6 " Fabric1" .ifbit + d# 7 " Fabric2" .ifbit + d# 9 " Thermal" .ifbit + d# 10 " MainPMU" .ifbit + d# 11 " WDT2" .ifbit + d# 12 " CoreSight" .ifbit + d# 13 " PJ_Commtx" .ifbit + d# 14 " PJ_Commrx" .ifbit + drop + cr +; +: .int51 ( -- ) + ." INT51 - mask " h# 178 icu@ .x + ." status " h# 160 icu@ dup .x + 0 " HSI_CAWAKE1 " .ifbit + 1 " MIPI_HSI1" .ifbit + drop cr +; +: .int55 ( -- ) + ." INT55 - mask " h# 184 icu@ .x + ." status " h# 188 icu@ dup .x + 0 " HSI_CAWAKE0 " .ifbit + 1 " MIPI_HSI0" .ifbit + drop cr +; + +: .fiq ( -- ) + h# 304 icu@ if ." FIQ is masked off" cr then + h# 300 icu@ dup h# 40 and if ." FIQ selected INT: " h# 3f and .d cr else drop then + h# 310 icu@ h# 314 icu@ 2dup d0= if ( d ) + 2drop ( ) + else ( d ) + ." FIQ " (.pending) cr ( ) + then ( ) +; + +: .icu ( -- ) + .enabled-ints + 3 0 do i .masked i .selected i .pending loop + \ XXX should handle DMA interrupts too + .fiq + .int4 .int5 .int9 .int17 .int35 .int51 .int55 +; + +: .irqstat ( -- ) h# 148 h# 130 do i icu@ . 4 +loop ; + +\ LICENSE_BEGIN +\ Copyright (c) 2012 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Modified: cpu/arm/mmp2/socregs.fth ============================================================================== --- cpu/arm/mmp2/socregs.fth Sun Sep 2 01:42:57 2012 (r3269) +++ cpu/arm/mmp2/socregs.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -22,6 +22,9 @@ : mpmu@ ( offset -- l ) +mpmu io@ ; : mpmu! ( l offset -- ) +mpmu io! ;
+: mpmu-set ( bits reg# -- ) +mpmu io-set ; +: mpmu-clr ( bits reg# -- ) +mpmu io-clr ; + : pmua@ ( offset -- l ) +pmua io@ ; : pmua! ( l offset -- ) +pmua io! ;
Added: cpu/arm/mmp2/wakeups.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ cpu/arm/mmp2/wakeups.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -0,0 +1,182 @@ +\ See license at end of file +purpose: Setup keyboard wakeups and display the state of the wakeup machinery + +\ XXX we might need to set GPIOs 71 and 160 (ps2 clocks), and perhaps the dat lines too, +\ for non-sleep-mode control - or maybe for sleep mode control as inputs. +\ We also may need to enable falling edge detects. +: disable-int40 ( -- ) + d# 40 disable-interrupt + 1 h# 29.00cc io-set \ Unmask the inter-processor communications interrupt +; + +\ How to wakeup from SP: +: setup-key-wakeup ( -- ) + d# 24 d# 15 do h# b0 i af! loop \ Wake SoC on game keys +[ifdef] soc-kbd-clk-gpio# + h# 220 soc-kbd-clk-gpio# af! \ Wake SoC on KBD CLK falling edge + h# 221 soc-tpd-clk-gpio# af! \ Wake SoC on TPD CLK falling edge +[then] + h# 4 h# 4c +mpmu io-set \ Pin edge (GPIO per datasheet) wakes SoC + ['] disable-int40 d# 40 interrupt-handler! + d# 40 enable-interrupt \ SP to PJ4 communications interrupt + 1 h# 29.00cc io-clr \ Unmask the inter-processor communications interrupt +; + +\ We need to do this in the SP interrupt handler +: clear-wakeup ( gpio# -- ) + dup af@ ( gpio# value ) + 2dup h# 40 or swap af! ( gpio# value ) + swap af! +; + +: gpio-wakeup? ( gpio# -- flag ) + h# 019800 over 5 rshift la+ l@ ( gpio# mask ) + swap h# 1f and ( mask bit# ) + 1 swap lshift and 0<> ( flag ) +; + +\ !!! The problem right now is that I have woken from keyboard, but the interrupt is still asserted +\ So perhaps the interrupt handler didn't fire +: rotate-wakeup? ( -- flag ) d# 15 gpio-wakeup? ; +: kbd-wakeup? ( -- flag ) d# 71 gpio-wakeup? ; +: tpd-wakeup? ( -- flag ) d# 160 gpio-wakeup? ; + +string-array wakeup-bit-names + ," WU0 " + ," WU1 " + ," WU2 " + ," WU3 " + ," WU4 " + ," WU5 " + ," WU6 " + ," WU7 " + ," TIMER_1_1 " + ," TIMER_1_2 " + ," TIMER_1_3 " + ," MSP_INS " + ," AUDIO " + ," WDT1 " + ," TIMER_2_1 " + ," TIMER_2_2 " + ," TIMER_2_3 " + ," RTC_ALARM " + ," WDT2 " + ," ROTARY " + ," TRACKBALL " + ," KEYPRESS " + ," SDH3_CARD " + ," SDH1_CARD " + ," FULL_IDLE " + ," ASYNC_INT " + ," SSP1_SRDY " + ," CAWAKE " + ," resv28 " + ," SSP3_SRDY " + ," ALL_WU " + ," resv31 " +end-string-array + +string-array wakeup-mask-names + ," WU0 " + ," WU1 " + ," WU2 " + ," WU3 " + ," WU4 " + ," WU5 " + ," WU6 " + ," WU7 " + ," TIMER_1_1 " + ," TIMER_1_2 " + ," TIMER_1_3 " + ," " + ," " + ," " + ," TIMER_2_1 " + ," TIMER_2_2 " + ," TIMER_2_3 " + ," RTC_ALARM " + ," WDT2 " + ," ROTARY " + ," TRACKBALL " + ," KEYPRESS " + ," SDH3_CARD " + ," SDH1_CARD " + ," FULL_IDLE " + ," ASYNC_INT " + ," WDT1 " + ," SSP3_SRDY " + ," SSP1_SRDY " + ," CAWAKE " + ," MSP_INS " + ," resv31 " +end-string-array + +: .active-wakeups ( -- ) + ." Wakeups: " + h# 1048 mpmu@ ( n ) + d# 31 0 do ( n ) + dup 1 and if i wakeup-bit-names count type then ( n ) + u2/ ( n' ) + loop ( n ) + drop cr ( ) +; +: .wakeup-mask ( -- ) + ." Enabled wakeups: " + h# 4c mpmu@ h# 104c or ( n ) + d# 31 0 do ( n ) + dup 1 and if i wakeup-mask-names count type then ( n ) + u2/ ( n' ) + loop ( n ) + drop cr ( ) +; +: .edges ( -- ) + ." Wakeup edges: " ( ) + d# 6 0 do ( ) + h# 19800 i la+ io@ ( n ) + d# 32 0 do ( n ) + dup 1 and if ( n ) + j d# 32 * i + .d ( n ) + then ( n ) + u2/ ( n' ) + loop ( n ) + drop ( ) + loop ( ) + cr ( ) +; +: .edge-enables ( -- ) + ." Enabled edges: " + d# 160 0 do + i af@ dup h# 70 and h# 40 <> if ( n ) + dup h# 10 and if ." R" then ( n ) + dup h# 20 and if ." F" then ( n ) + dup h# 40 and if ." C" then ( n ) + i .d ( n ) + then ( n ) + drop ( ) + loop +; +: .wakeup ( -- ) .active-wakeups .wakeup-mask .edges .edge-enables ; + +\ LICENSE_BEGIN +\ Copyright (c) 2012 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Added: cpu/arm/mmp3/dramrecal.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ cpu/arm/mmp3/dramrecal.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -0,0 +1,323 @@ +\ See license at end of file +purpose: SoC-specific low-level power management factors + +\ First some tools for managing the DRAM reconfiguration table + +0 value table# +0 value entry# +0 value mc-cs-map + +0 value mc# +: set-mc ( mc# -- ) to mc# ; +: +mc ( offset -- adr ) h# d000.0000 + mc# if h# 1.0000 + then ; +: mc@ ( offset -- value ) +mc l@ ; +: mc! ( value offset -- ) +mc l! ; + +: +pause ( reg# -- reg#' ) h# 1.0000 or ; +: +last ( reg# -- reg#' ) h# 2.0000 or ; + +: +mct ( value register#+flags -- ) + entry# d# 32 = abort" DRAM init table overflow" + swap h# 1c8 mc! ( data1-value ) + h# 1cc mc! ( ) + table# 5 lshift + entry# or + h# 8000.0000 or ( ctrl-value ) + h# 1c0 mc! ( ) + entry# 1+ to entry# +; +: mc-table( ( mc# table# -- ) + to table# set-mc 0 to entry# + + 0 + h# 10 mc@ 1 and if h# 1000.0000 or then + h# 14 mc@ 1 and if h# 2000.0000 or then + to mc-cs-map +; +: )mc-table ( -- ) + table# 5 lshift + mc# if 3 lshift h# 700 else h# e0 then ( field mask ) + invert h# 11c pmua@ and or h# 11c pmua! +; + +: +phy-dll ( -- ) + 4 0 do i h# 300 +mct h# 1080 h# 304 +mct loop +; +: +read-leveling ( -- ) + 4 0 do h# 100 i + h# 380 +mct h# 200 h# 390 +mct loop +; +: +reset-dll ( -- ) + h# 2000.0000 h# 24c +mct \ DLL reset + h# 0003.0001 h# 160 +mct \ SDRAM INIT + h# 4000.0000 h# 24c +mct \ DLL update via pulse mode +; +: +update-mode ( -- ) + mc-cs-map h# 100 or h# 160 +mct + mc-cs-map h# 400 or h# 160 +mct +; +: +reset-sdram-dll ( -- ) h# 50 mc@ h# 40 or h# 50 +mct ; +: +zq-cal ( -- ) mc-cs-map h# 1000 or h# 160 +mct ; +: +halt-pause ( -- ) 2 h# 68 +pause +mct ; + +: +halt ( -- ) 2 h# 68 +mct ; \ SDRAM_CTRL14 - Halt scheduler +: +restart ( -- ) 0 h# 68 +last +mct ; \ SDRAM_CTRL14 - Resume scheduler + +: +cmd0 ( lowbits -- ) mc-cs-map or h# 160 +mct ; + +: make-ddr3-recal-table ( mc# -- ) + 0 mc-table( + +halt + h# 2000.0000 h# 24c +mct \ PHY_CTRL14 - PHY DLL reset + h# 4000.0000 h# 24c +mct \ PHY_CTRL14 - PHY DLL update + h# 8000.0000 h# 24c +pause +mct \ PHY_CTRL14 - Sync 2x clock + h# 50 mc@ h# 40 or + h# 50 +mct \ SDRAM_CTRL1 - set DLL_RESET bit + h# 0000.0100 +cmd0 \ USER_COMMAND0 - Send LMR0 DLL + h# 0000.0400 +cmd0 \ USER_COMMAND0 - Send LMR2 DLL + h# 0000.1000 +cmd0 \ USER_COMMAND0 - ZQ Calibration + +restart + )mc-table +; +: mc2-enabled? ( -- flag ) h# 6c pmua@ 2 and 0<> ; +: make-ddr3-recal-tables ( -- ) + 0 make-ddr3-recal-table + mc2-enabled? if + 1 make-ddr3-recal-table + else + 2 h# 190 pmua-set \ PMUA_DEBUG2 - don't wait for ack from MC2 + then +; + +0 value old-ccic +0 value old-gc +0 value old-vmeta +0 value old-aclk +0 value old-adsa +0 value old-aisl +: power-islands-off ( -- ) + h# 50 pmua@ to old-ccic 0 h# 50 pmua! \ Camera + h# cc pmua@ to old-gc 0 h# cc pmua! \ Graphics + h# a4 pmua@ to old-vmeta 0 h# a4 pmua! \ Vmeta + h# 10c pmua@ to old-aclk 0 h# 10c pmua! \ Audio clock + h# 164 pmua@ to old-adsa 0 h# 164 pmua! \ Audio DSA + h# 1e4 pmua@ to old-aisl 0 h# 1e4 pmua! \ Audio Island + h# fc0 h# 240 pmua-set \ Retain audio SRAM state (0 to power them off) +; +: power-islands-on ( -- ) + old-aisl h# 1e4 pmua! + old-adsa h# 164 pmua! + old-aclk h# 10c pmua! + old-vmeta h# a4 pmua! + old-gc h# cc pmua! + old-ccic h# 50 pmua! +; + +: +ciu ( adr -- adr' ) h# 282c00 + ; +: ciu! ( l adr -- ) +ciu io! ; +: ciu@ ( adr -- l ) +ciu io@ ; + +: sp-c1-on ( -- ) + h# 1000.0000 0 mpmu-set \ Allow SP clock shutdown in IDLE (can't DMA to TCM) +; + +: idle-cfg@ ( -- n ) h# 18 pmua@ ; \ Core-dependent +: idle-cfg! ( -- n ) h# 18 pmua! ; \ Core-dependent +: idle-cfg-clr ( mask -- ) h# 18 pmua-clr ; +: idle-cfg-set ( mask -- ) h# 18 pmua-set ; + +: cc4-set ( mask -- ) h# 248 pmua-set ; +: cc4-clr ( mask -- ) h# 248 pmua-clr ; + +0 [if] +: pj-c1 ( -- ) + h# 62 idle-cfg-clr \ light sleep after WFI + wfi +; +: pj-c1-extclk + h# 62 idle-cfg-clr \ light sleep after WFI + h# 02 idle-cfg-set \ Allow core clock shutdown (won't respond to snoops) + h# 01 cc4-set \ Mask off GIC interrupts + wfi +; +: pj-c2 + ( clean&invalidate-l1 ) \ Must do this if coherency is enabled + h# 8000.0062 idle-cfg-clr \ light sleep after WFI + + \ To set the 40 bit, you must first clean&invalidate the l1 cache + h# 22 idle-cfg-set \ Allow core clock shutdown and core powerdown + + \ Also set the 8000 bit to keep L2 cache powered on + h# 01 cc4-set \ Mask off GIC interrupts + wfi +; +[then] + +create wakeup-masks \ Bits in MPMU+0 and MPMU+1000, indexed by wakeup port number + h# 0080.0000 , h# 0040.0000 , h# 0020.0000 , h# 0010.0000 , + h# 0004.0000 , h# 0002.0000 , h# 0001.0000 , h# 0000.8000 , + +: port>bit ( port# -- ) wakeup-masks swap na+ @ ; + +: pcr! ( value -- ) dup h# 00 mpmu! h# 1000 mpmu! ; +: pcr-set ( mask -- ) dup h# 00 mpmu-set h# 1000 mpmu-set ; +: pcr-clr ( mask -- ) dup h# 00 mpmu-clr h# 1000 mpmu-clr ; +: wucrm-set ( mask -- ) dup h# 4c mpmu-set h# 104c mpmu-set ; + +\ We enable the wakeup port in both the SP and PJ registers, thus avoiding +\ any ambiguity about whether the bits are ORed or ANDed +: wakeup-port-on ( port# -- ) + dup port>bit pcr-clr + 1 swap lshift wucrm-set +; +: deep-sleep-on ( -- ) + \ Start with all wakeup ports masked off, enable specific ones later + h# beffe000 pcr! \ AXISD, SPLEN, SPSD, DDRCORSD, APBSD, RSVD, VCXOSD, MSASLPEN, UDR_POWER_OFF_EN \ Step 11 +; + +\ D2_L2_PWD 462 +\ C2_L1_L2_PWD 820004e2 \ 80 might be L2 power down bit +\ C2_L1_PWD 82000462 \ Power off SRAM by setting 40 bit +\ C2_L1R_L2_PWD 820004a2 \ Retain SRAM by not setting 40 bit +: set-idle ( mask -- ) + h# e2 and ( mask' ) \ Mask with 62 for other cores + idle-cfg@ h# 0def.fc1d and ( mask kept ) + or idle-cfg! ( ) +; +: rtc-wakeup-on ( -- ) + h# 2.0000 wucrm-set + 4 wakeup-port-on +; +code outer-flush-all ( -- ) +c; +code flush-cache-all + mcr p15, 0, r0, cr8, cr5, 0 \ instruction tlb + mcr p15, 0, r0, cr8, cr6, 0 \ data tlb + mcr p15, 0, r0, cr8, cr7, 0 \ unified tlb + + mcr p15, 0, r0, cr7, cr5, 0 \ invalid I cache + mcr p15, 0, r0, cr7, cr5, 6 \ invalid branch predictor array + mcr p15, 0, r0, cr7, cr5, 4 \ instruction barrier + mcr p15, 0, r0, cr7, cr14, 0 \ flush entire d cache + mcr p15, 0, r0, cr7, cr5, 4 \ flush prefetch buffer + isb + dsb +c; +code fw-off + mrc p15, 0, r0, cr1, cr0, 1 + bic r0,r0,1 + mcr p15, 0, r0, cr1, cr0, 1 + isb + dsb +c; +code fw-on + mrc p15, 0, r0, cr1, cr0, 1 + orr r0,r0,1 + mcr p15, 0, r0, cr1, cr0, 1 + isb + dsb +c; +code mp-off + mrc p15, 0, r0, cr1, cr0, 1 + bic r0,r0,#0x40 + mcr p15, 0, r0, cr1, cr0, 1 + isb + dsb +c; +code mp-on + mrc p15, 0, r0, cr1, cr0, 1 + orr r0,r0,#0x40 + mcr p15, 0, r0, cr1, cr0, 1 + isb + dsb +c; +: wakeup-irqs-on ( -- ) +\ 2f is high priority (f), directed to PJ (20) +\ h# 2f h# 82010 io! \ IRQ 4 - PMIC + h# 2f h# 82014 io! \ IRQ 5 - RTC +\ h# 2f h# 820c4 io! \ IRQ 49 - GPIO +; +: wakeup-irqs-off ( -- ) +\ h# 0 h# 82010 io! \ IRQ 4 - PMIC + h# 0 h# 82014 io! \ IRQ 5 - RTC +\ h# 0 h# 820c4 io! \ IRQ 49 - GPIO +; +: global-irqs-off ( -- ) + \ disable global irq of ICU for MP1, MP2, MM + 1 h# 82110 io! \ ICU_GBL_IRQ1_MSK + 1 h# 82114 io! \ ICU_GBL_IRQ2_MSK + 1 h# 8410c io! \ ICU_GBL_IRQ3_MSK + 1 h# 84110 io! \ ICU_GBL_IRQ4_MSK + 1 h# 84114 io! \ ICU_GBL_IRQ5_MSK + 1 h# 84190 io! \ ICU_GBL_IRQ6_MSK +; + +0 value apcr +: setup-sleep-state ( -- ) + sp-c1-on + + make-ddr3-recal-tables + + h# 1000 mpmu@ to apcr + + deep-sleep-on + rtc-wakeup-on + + h# 462 set-idle \ D2_L2_PWD + + \ Workaround - shut down AT clock + h# 8000.0000 idle-cfg-clr + + \ I don't think we need this because L2 is off + \ h# 8000 cc4-set \ workaround: keep SL2 power on + + wakeup-irqs-on + + flush-cache-all + \ outer-flush-all + + \ fw-off + \ mp-off +; +: restore-run-state ( -- ) + wakeup-irqs-off + + \ fw-on + \ mp-on + + \ I don't think we need this because L2 is off + \ h# 8000 cc4-clr \ workaround: keep SL2 power on + + global-irqs-off + + apcr h# 1000 mpmu! + + h# 8000.0000 idle-cfg-set \ Workaround: restore AT clock + + 0 set-idle \ C1_INCG +; + +alias do-wfi wfi + +\ LICENSE_BEGIN +\ Copyright (c) 2012 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Modified: cpu/arm/olpc/build-fw.fth ============================================================================== --- cpu/arm/olpc/build-fw.fth Sun Sep 2 01:42:57 2012 (r3269) +++ cpu/arm/olpc/build-fw.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -562,7 +562,16 @@ fload ${BP}/cpu/x86/pc/olpc/strokes.fth fload ${BP}/cpu/x86/pc/olpc/plot.fth
+fload ${BP}/cpu/arm/mmp2/showirqs.fth +fload ${BP}/cpu/arm/mmp2/wakeups.fth + +[ifdef] mmp3 +fload ${BP}/cpu/arm/mmp3/dramtable.fth +[then] +[ifdef] mmp2 fload ${BP}/cpu/arm/mmp2/dramrecal.fth +[then] +fload ${BP}/cpu/arm/olpc/suspend.fth
code halt ( -- ) wfi c;
Added: cpu/arm/olpc/suspend.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ cpu/arm/olpc/suspend.fth Sun Sep 2 01:57:24 2012 (r3270) @@ -0,0 +1,218 @@ +purpose: Common uspend/resume code for OLPC XO ARM plaforms + +: apbc-clr-rst ( offset -- ) 4 swap +apbc io-clr ; +: apbc-set-rst ( offset -- ) 4 swap +apbc io-set ; + +: disable-apbc-clks ( -- ) + \ 3 h# 38 +apbc io-clr \ GPIO + 3 h# 74 +apbc io-clr \ MPMU + 3 h# 78 +apbc io-clr \ IPC + 3 h# 90 +apbc io-clr \ THSENS1 + + \ h# 38 apbc-set-rst + \ h# 74 apbc-set-rst \ MPMU - resetting this kills TIMER2, used by the SP PS/2 + h# 78 apbc-set-rst \ IPC + h# 90 apbc-set-rst \ THSENS1 +; +: enable-apbc-clks ( -- ) + \ 3 h# 38 +apbc io-set \ GPIO + 3 h# 74 +apbc io-set \ MPMU + 3 h# 78 +apbc io-set \ IPC + 3 h# 90 +apbc io-set \ THSENS1 + + \ h# 38 apbc-clr-rst + h# 74 apbc-clr-rst \ MPMU + h# 78 apbc-clr-rst \ IPC + h# 90 apbc-clr-rst \ THSENS1 +; +: disable-scu-clks ( -- ) + 0 h# 64 +scu io! \ SCU_AXIFAB_CKGT_CTRL0 - Close AXI fabric clock gate + 0 h# 68 +scu io! \ SCU_AXIFAB_CKGT_CTRL1 + h# f0 h# 1c +scu io-set \ SCU_MCB_CONF +; +: enable-scu-clks ( -- ) + h# 3003003 h# 64 +scu io! \ SCU_AXIFAB_CKGT_CTRL0 - Open AXI fabric clock gate + h# 0303030 h# 68 +scu io! \ SCU_AXIFAB_CKGT_CTRL1 + h# f0 h# 1c +scu io-clr \ SCU_MCB_CONF +; +: disable-apmu-clks ( -- ) + h# 1b h# 54 +pmua io-clr \ PMUA_SDH0_CLK_RES_CTRL + h# 1b h# 58 +pmua io-clr \ PMUA_SDH1_CLK_RES_CTRL + h# 1b h# e8 +pmua io-clr \ PMUA_SDH2_CLK_RES_CTRL + h# 1b h# d4 +pmua io-clr \ PMUA_SMC_CLK_RES_CTRL + h# 3f h# 60 +pmua io-clr \ PMUA_NF_CLK_RES_CTRL + h# 3f h# d8 +pmua io-clr \ PMUA_MSPRO_CLK_RES_CTRL - XO does not use MSPRO + h# 12 h# 10c +pmua io-clr \ PMUA_AUDIO_CLK_RES_CTRL + h# 1fffd h# dc +pmua io-clr \ PMUA_GLB_CLK_RES_CTRL +\ 0 h# 68 pmua! \ PMUA_WTM_CLK_RES_CTRL + h# 9 h# 5c +pmua io-clr \ PMUA_USB_CLK_RES_CTRL +; +: enable-apmu-clks ( -- ) + h# 1b h# 54 +pmua io-set \ PMUA_SDH0_CLK_RES_CTRL + h# 1b h# 58 +pmua io-set \ PMUA_SDH1_CLK_RES_CTRL + h# 1b h# e8 +pmua io-set \ PMUA_SDH2_CLK_RES_CTRL + h# 1b h# d4 +pmua io-set \ PMUA_SMC_CLK_RES_CTRL \ ??? what is this and why is it on? + h# 3f h# 60 +pmua io-set \ PMUA_NF_CLK_RES_CTRL \ Should this be on? +\ h# 3f h# d8 +pmua io-set \ PMUA_MSPRO_CLK_RES_CTRL + h# 12 h# 10c +pmua io-set \ PMUA_AUDIO_CLK_RES_CTRL + h# 1fffd h# dc +pmua io-set \ PMUA_GLB_CLK_RES_CTRL +\ h# 1b h# 68 pmua! \ PMUA_WTM_CLK_RES_CTRL + h# 9 h# 5c +pmua io-set \ PMUA_USB_CLK_RES_CTRL +; +: pll2? ( -- flag ) h# 34 mpmu@ h# 100 and 0<> ; +: disable-mpmu-clks ( -- ) + pll2? if h# e010 else h# a010 then ( cgr-value ) + dup h# 1024 mpmu! \ MPMU_CGR_PJ + h# 0024 mpmu! \ MPMU_CGR_SP + +\ h# 2000.0000 h# 414 +mpmu io-clr \ MPMU_PLL2_CTRL1 + h# 8000.0000 h# 0040 +mpmu io-clr \ MPMU_ISCCR1 + h# 8000.0000 h# 0044 +mpmu io-clr \ MPMU_ISCCR2 +; +: enable-mpmu-clks ( -- ) + h# dffe.fffe h# 1024 mpmu! \ MPMU_ACGR +\ h# 2000.0000 h# 0414 +mpmu io-set \ MPMU_PLL2_CTRL1 + h# 8000.0000 h# 0040 +mpmu io-set \ MPMU_ISCCR1 + h# 8000.0000 h# 0044 +mpmu io-set \ MPMU_ISCCR2 +; +: disable-twsi-clks ( -- ) + \ set RST in APBC_TWSIx_CLK_RST registers + +[ifdef] notdef + \ just disable TWSI1 clk rather than reset it since it's needed to access PMIC onkey + \ when system is waken up from low power mode */ + 0 4 +apbc io! \ Disable TWSI1 clock +[else] + h# 04 apbc-set-rst \ TWSI1 +[then] + h# 08 apbc-set-rst \ TWSI2 + h# 0c apbc-set-rst \ TWSI3 + h# 10 apbc-set-rst \ TWSI4 + h# 7c apbc-set-rst \ TWSI5 + h# 80 apbc-set-rst \ TWSI6 +; +: enable-twsi-clks ( -- ) +[ifdef] notdef + 3 4 +apbc io! \ Enable TWSI1 clock +[else] + h# 04 apbc-clr-rst \ TWSI1 +[then] + h# 08 apbc-clr-rst \ TWSI2 + h# 0c apbc-clr-rst \ TWSI3 + h# 10 apbc-clr-rst \ TWSI4 + h# 7c apbc-clr-rst \ TWSI5 + h# 80 apbc-clr-rst \ TWSI6 +; +: disable-clks ( -- ) + disable-twsi-clks + disable-apbc-clks + disable-scu-clks + disable-apmu-clks + disable-mpmu-clks +; +: enable-clks ( -- ) + enable-mpmu-clks + enable-apmu-clks + enable-scu-clks + enable-apbc-clks + enable-twsi-clks +; + +[ifdef] soc-en-kbd-pwr-gpio# +: keyboard-power-on ( -- ) soc-en-kbd-pwr-gpio# gpio-clr ; +: keyboard-power-off ( -- ) soc-en-kbd-pwr-gpio# gpio-set ; +[else] +: keyboard-power-on ( -- ) ; +: keyboard-power-off ( -- ) ; +[then] +: wlan-power-on ( -- ) en-wlan-pwr-gpio# gpio-set ; +: wlan-power-off ( -- ) en-wlan-pwr-gpio# gpio-clr h# 040 en-wlan-pwr-gpio# af! h# 040 wlan-pd-gpio# af! h# 040 wlan-reset-gpio# af! ; +: wlan-stay-on ( -- ) h# 140 en-wlan-pwr-gpio# af! h# 140 wlan-pd-gpio# af! h# 140 wlan-reset-gpio# af! ; + +0 value sleep-mask +: screen-sleep + sleep-mask 1 and if \ DCON power down + dcon-freeze + else + " dcon-suspend" $call-dcon + then + " sleep" $call-screen + " set-ack" $call-ec + + \ 0 h# 54 pmua! \ Kill the SDIO 0 clocks - insignificant savings + \ 0 h# 58 pmua! \ Kill the SDIO 1 clocks - insignificant savings + sleep-mask 2 and 0= if keyboard-power-off then \ Should save about 17 mW + sleep-mask 4 and if + wlan-stay-on + else + " /wlan" " sleep" execute-device-method drop + wlan-power-off + then \ saves 100 mW +; +: screen-wake ( -- ) + sleep-mask 4 and 0= if + wlan-power-on + " /wlan" " wake" execute-device-method drop + then + sleep-mask 2 and 0= if keyboard-power-on then + " clr-ack" $call-ec + " wake" $call-screen + sleep-mask 1 and if \ DCON power up + dcon-unfreeze + else + " dcon-resume" $call-dcon + then +; + +: stdin-idle-on ['] safe-idle to stdin-idle d# 15 enable-interrupt ; +: stdin-idle-off ['] noop to stdin-idle ( install-uart-io ) d# 15 disable-interrupt ; + +: timers-sleep ( -- ) + 0 h# 14048 io! \ Disable interrupts from the tick timer + 7 h# 1407c io! \ Clear any pending interrupts + h# f disable-interrupt \ Block timer interrupt +; +: timers-wake ( -- ) + 1 h# 14048 io! \ Enable interrupts from the tick timer + 7 h# 1407c io! \ Clear any pending interrupts + h# f enable-interrupt \ Unblock timer interrupt + reschedule-tick +; + +: platform-off ( -- ) + disable-interrupts + suspend-usb + timers-sleep + + screen-sleep + stdin-idle-off + + disable-clks + power-islands-off +; + +: platform-on ( -- ) + power-islands-on + + enable-clks + + stdin-idle-on + + screen-wake + timers-wake + resume-usb + enable-interrupts + init-thermal-sensor +; + +: str ( -- ) + platform-off + + setup-sleep-state + do-wfi + restore-run-state + + platform-on +; + +: strp ( -- ) ec-rst-pwr str ec-max-pwr .d ." mW " soc .% space ;
openfirmware@openfirmware.info