[openfirmware] [commit] r2486 - cpu/arm/mmp2
repository service
svn at openfirmware.info
Mon Aug 29 03:46:46 CEST 2011
Author: wmb
Date: Mon Aug 29 03:46:46 2011
New Revision: 2486
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2486
Log:
OLPC XO-1.75 - improvements to suspend/resume code; still not 100% working.
Modified:
cpu/arm/mmp2/dramrecal.fth
Modified: cpu/arm/mmp2/dramrecal.fth
==============================================================================
--- cpu/arm/mmp2/dramrecal.fth Mon Aug 29 03:36:56 2011 (r2485)
+++ cpu/arm/mmp2/dramrecal.fth Mon Aug 29 03:46:46 2011 (r2486)
@@ -58,20 +58,102 @@
end-code
here ddr-recal - constant /ddr-recal
-h# d000.0000 constant memctrl-pa
-h# d000.0000 constant memctrl-va
-h# d100.0000 constant sram-pa
-h# d100.0000 constant sram-va
-sram-va h# 2.0000 + constant 'ddr-recal
+label ddr-self-refresh ( r0:memctrl-va -- )
+ mov r1, #0x1 \ Block all data requests
+ str r1, [r0, #0x7e0] \ SDRAM_CTRL14
-: ddr-recal-to-sram ( -- )
+ ldr r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+ bic r1, r1, #0xc0 \ USER_SR_REQUEST field
+ orr r1, r1, #0x40 \ Enter Self Refresh value
+ str r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+
+ \ This block was commented-out in the Linux code, and the value is incorrect for OLPC in any case
+ \ mov r1, #0x03000000 \ PAD_TERM_SWITCH_MODE: Termination disabled
+ \ orr r1, r1, #0x000a \ ODT{1,0}_SWITCH_MODE: Termination controlled by Read and Write enables
+ \ str r1, [r0, #0x770] \ SDRAM_CTRL7_SDRAM_ODT_CTRL2
+
+[ifdef] notdef
+ ldr r1, [r0, #0x1e0] \ PHY_CTRL8
+ bic r1,r1,#0x07700000 \ PHY_ADCM_ZPDRV: 0 PHY_ADCM_ZNDRV: 0 (Disable drivers 6:0)
+ str r1, [r0, #0x1e0] \ PHY_CTRL8
+[then]
+
+ set r2, #0xfe086000
+ set r3, #0xfe050000
+ str r2, [r3] \ Final write to SP votes
+
+ mcr p15,0,r0,7,10,4 \ Data Synchronization Barrier
+\ dsb \ Data Synchronization Barrier
+ wfi \ Wait for interrupt
+
+[ifdef] notdef
+ ldr r1, [r0, #0x1e0] \ PHY_CTRL8
+ orr r1,r1,#0x07700000 \ PHY_ADCM_ZPDRV: 7 PHY_ADCM_ZNDRV: 7 (Enable drivers 6:0)
+ str r1, [r0, #0x1e0] \ PHY_CTRL8
+[then]
+
+ \ This block was commented-out in the Linux code, and the value is incorrect for OLPC in any case
+ \ mov r1, #0x02000000 \ PAD_TERM_SWITCH_MODE: Termination enabled during all reads
+ \ orr r1, r1, #0x000a \ ODT{1,0}_SWITCH_MODE: Termination controlled by Read and Write enables
+ \ str r1, [r0, #0x770] \ SDRAM_CTRL7_SDRAM_ODT_CTRL2
+
+ mov r1, #0x80000000 \ PHY_SYNC_EN
+ str r1, [r0, #0x240] \ PHY_CTRL14
+
+ ldr r1, [r0, #230] \ PHY_CTRL13
+ orr r1,r1,#0xf0000000 \ DLL_RESET_TIMER: 15*256 memory clocks
+\ mov r1, #0xf0000000 \ DLL_RESET_TIMER: 15*256 memory clocks
+\ orr r1, r1, #0x0040 \ DLL_PHSEL: 4 (45 + 4*3 = 57 degrees) - adjust?
+ str r1, [r0, #230] \ PHY_CTRL13
+
+ mov r1, #0x20000000 \ PHY_DLL_RESET
+ str r1, [r0, #0x240] \ PHY_CTRL14
+
+ mov r1, #0x40000000 \ DLL_UPDATE_EN
+ str r1, [r0, #0x240] \ PHY_CTRL14
+
+ ldr r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+ bic r1, r1, #0xc0 \ USER_SR_REQUEST field
+ orr r1, r1, #0x80 \ Exit Self Refresh value
+ str r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+
+ ldr r1, [r0, #0x80] \ SDRAM_CTRL1
+ orr r1, r1, #0x40 \ DLL_RESET
+ str r1, [r0, #0x80] \ SDRAM_CTRL1
+
+ mov r1, #0x01000000 \ Chip select 0
+ orr r1, r1, #0x0100 \ USER_LMR0_REQ - Initiate Mode Register Set
+ str r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+
+ \ ldr r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+ \ bic r1, r1, #0xc0 \ USER_SR_REQUEST field
+ \ orr r1, r1, #0x80 \ Exit Self Refresh value
+ \ str r1, [r0, #0x120] \ USER_INITIATED_COMMAND0
+
+ mov r1, #0x0 \ Unblock data requests
+ str r1, [r0, #0x7e0] \ SDRAM_CTRL14
+
+ mov pc, lr
+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-pa h# c0e or sram-va map-section \ Make the code cacheable
+
+\ 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
+
+ ddr-self-refresh 'ddr-self-refresh /ddr-self-refresh move
+ 'ddr-self-refresh /ddr-self-refresh sync-cache
;
stand-init: Setup DDR3 recalibration
- ddr-recal-to-sram
+ ddr-code-to-sram
;
\ Call this from OFW to perform a recalibration
@@ -82,6 +164,259 @@
mov pc,r1
c;
+\ Call this from OFW to enter self-refresh
+code do-self-refresh ( -- )
+ set r0,`memctrl-va #` \ Memory controller virtual address
+ set r1,`'ddr-self-refresh #` \ Address of ddr-self-refresh routine in SRAM
+ mov lr,pc
+ mov pc,r1
+c;
+
+: +apbc ( offset -- io-offset ) h# 01.5000 + ;
+: +apmu ( offset -- io-offset ) h# 28.2800 + ;
+: +mpmu ( offset -- io-offset ) h# 05.0000 + ;
+: +scu ( offset -- io-offset ) h# 28.2c00 + ;
+: +icu ( offset -- io-offset ) h# 28.2000 + ;
+
+: io-set ( mask offset -- ) dup io@ rot or swap io! ;
+: io-clr ( mask offset -- ) dup io@ rot invert and swap io! ;
+
+: apbc-clr-rst ( offset -- ) +apbc 4 swap io-clr ;
+: apbc-set-rst ( offset -- ) +apbc 4 swap 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
+ 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# 3f h# d8 +apmu io-clr \ PMUA_MSPRO_CLK_RES_CTRL
+ h# 1fffd h# dc +apmu io-clr \ PMUA_GLB_CLK_RES_CTRL
+\ 0 h# 68 +apmu io! \ PMUA_WTM_CLK_RES_CTRL
+ h# 9 h# 5c +apmu io-clr \ PMUA_USB_CLK_RES_CTRL
+;
+: enable-apmu-clks ( -- )
+ h# 3f h# d8 +apmu io-set \ PMUA_MSPRO_CLK_RES_CTRL
+ h# 1fffd h# dc +apmu io-set \ PMUA_GLB_CLK_RES_CTRL
+\ h# 1b h# 68 +apmu io! \ PMUA_WTM_CLK_RES_CTRL
+ h# 9 h# 5c +apmu io-set \ PMUA_USB_CLK_RES_CTRL
+;
+: disable-mpmu-clks ( -- )
+ h# a010 h# 1024 +mpmu io! \ MPMU_ACGR
+
+ h# a010 h# 0024 +mpmu io! \ 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 io! \ 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
+\ WAKEUP2: GPIO
+\ WAKEUP3: Keypress,Trackball,Rotary
+\ WAKEUP4: Timers, RTC ALARM, WDT
+\ WAKEUP5: USB PHY
+\ WAKEUP6: SDH1_CD, SDH3_CD, MSP_INS
+\ WAKEUP7: PMIC INT
+5 value sleep-depth
+: setup-wakeup-sources ( -- mask )
+ h# 0002.0094 h# 4c +mpmu io! \ RTC_ALARM, WAKEUP7, WAKEUP4, WAKEUP2
+\ h# 0002.0094 h# 104c +mpmu io! \ RTC_ALARM, WAKEUP7, WAKEUP4, WAKEUP2 ???
+ h# ff08.7fff ( mask ) \ Enable all wakeup ports
+;
+: block-irqs ( -- ) 1 h# 110 +icu io! ;
+
+0 value save-apcr
+0 value save-idlecfg
+
+: restore-run-state ( -- )
+ save-apcr h# 1000 +mpmu io! ( ) \ Restore APCR
+ save-idlecfg h# 18 +apmu io! ( ) \ Restore IDLE_CFG
+;
+: setup-sleep-state ( -- )
+ \ begin mmp2_pm_enter_lowpower_mode(state)
+
+ h# 1000 +mpmu io@ to save-apcr
+ h# 18 +apmu io@ to save-idlecfg
+
+ save-apcr ( apcr )
+ h# ac08.0000 invert and ( apcr' ) \ Clear AXISD, SLPEN, DDRCORSD, APBSD, VCXOSD
+
+ sleep-depth 5 >= if \ state at least POWER_MODE_SYS_SLEEP (turn off oscillator)
+ h# 0008.0000 or ( apcr' ) \ Set VCXOSD
+ then
+
+ h# 2000.0000 0 +mpmu io-clr \ In SP, clear SLPEN - we might set it later
+
+ sleep-depth 4 >= if \ state at least POWER_MODE_CHIP_SLEEP (turn off most of SoC)
+ h# 2008.0000 0 +mpmu io-set \ In SP, also set SLPEN, VCXOSD
+ h# 2000.0000 or ( apcr' ) \ Set SLPEN
+ setup-wakeup-sources and ( apcr' )
+ then
+
+ sleep-depth 3 >= if \ state at least POWER_MODE_APPS_SLEEP (turn off slow IO)
+ h# de00.0000 0 +mpmu io-set \ In SP, set AXISD, resvd, SPSD, DDRCORSD, APBSD resvd,
+ h# 0400.0000 or ( apcr' ) \ Set APBSD
+ then
+
+ h# 8030.0020 h# 14 +apmu io! ( apcr ) \ IN PMUA_SP_IDLE_CFG, set , DIVIDER_RESET_EN, SP_DIS_MC_SW_REQ, SP_MC_WAKE_EN, TCM_STATE_RETAIN
+
+ sleep-depth 2 >= if \ state at least POWER_MODE_APPS_IDLE (turn off fast IO and DDR)
+ h# 8800.0000 or ( apcr' ) \ Set AXISD, DDRCORSD
+ then
+
+ h# 5200.0000 or ( apcr' ) \ Set DSPSD (bit 30, reserved), SPSD (bit 28), BBSD (bit 25, resvd)
+
+ save-idlecfg 1 invert and ( apcr idle ) \ PMUA_MOH_IDLE
+
+ sleep-depth 2 >= if \ state at least POWER_MODE_APPS_IDLE
+ h# 0000.0020 or ( apcr idle' ) \ PJ_PWRDWN
+ then
+
+ sleep-depth 1 >= if \ state at least POWER_MODE_CORE_EXTIDLE
+ h# 3000.0000 invert and ( apcr idle' ) \ PJ_ISO_MODE_CNTRL - isolation controlled by processor logic and active
+ h# 000a.0000 or ( apcr idle' ) \ 2 L2 power switches, 1 L1 power switch, 3 core power switches
+ then
+
+ h# 0020.0000 or ( apcr idle' ) \ PJ_DIS_MC_SW_REQ - disable idle entry using software register bits
+ h# 0010.0000 or ( apcr idle' ) \ PJ_MC_WAKE_EN - wake memory controller when core wakes
+
+ 0 h# b0 +apmu io! ( apcr idle ) \ PMUA_MC_HW_SLP_TYPE - self-refresh power down
+
+ h# 18 +apmu io! ( apcr ) \ Set IDLE_CFG register
+ h# 1000 +mpmu io! ( ) \ Set APCR register
+
+ \ end mmp2_pm_enter_lowpower_mode(state)
+;
+
+: screen-dark
+ " screen-ih iselect h# 12 mode! 0 h# 190 lcd! iunselect" eval \ Saves 1.05W
+ 0 h# 4c +apmu io! \ Kill the display clocks - saves 100 mW
+ \ 0 h# 54 +apmu io! \ Kill the SDIO 0 clocks - insignificant savings
+ \ 0 h# 58 +apmu io! \ Kill the SDIO 1 clocks - insignificant savings
+ d# 34 gpio-clr \ Kill the WLAN power - saves 100 mW
+;
+: 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 ;
+
+: str ( -- )
+ stdin-idle-off
+ 5 h# 38 +mpmu io! \ 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# 00c0.0000 h# 8c +apmu io-set \ Power down CoreSight SRAM
+
+ \ TODO - need to power down sram/l2$
+ \ mmp2_cpu_disable_l2(0);
+ \ outer_cache.flush_range(0, -1ul);
+
+ \ TODO - handle low power island?
+
+ disable-clks
+
+ \ begin mmp2_cpu_do_idle()
+ block-irqs ( ) \ Block IRQs - will be cleared by PMU
+ do-self-refresh ( )
+
+ restore-run-state
+ \ end mmp2_cpu_do_idle()
+
+ enable-clks
+
+ ." STR out" cr
+ \ mmp2_cpu_enable_l2(0);
+
+ \ idle_cfg &= (~PMUA_MOH_SRAM_PWRDWN);
+ stdin-idle-on
+;
+
\ LICENSE_BEGIN
\ Copyright (c) 2011 FirmWorks
\
More information about the openfirmware
mailing list