suspend 時,最後 callmx5_suspend_enter( )
會 call 到 suspend_in_iram(suspend_param1, NULL, NULL);
suspend_in_iram 是一個 function pointer.
void (*suspend_in_iram)(void *param1, void *param2, void* param3) = NULL;
在 pm_init 時:
suspend_param1 = cpu_is_mx51() ?
(void *)SUSPEND_ID_MX51:
(void *)SUSPEND_ID_MX53;
memcpy(suspend_iram_base, cpu_do_suspend_workaround,SZ_4K);
suspend_in_iram = (void *)suspend_iram_base;
也就是..把cpu_do_suspend_workaround 這塊區域copy 到 suspend_iram_base 中。
再把 suspend_iram_base 指定給 suspend_in_iram( )
這是因為suspend 時,dram 會disable, 進入 self-refresh,所以不能 access。
所以要把 dram 中的 code 先 copy 到 internal ram (iram) 中,才可以執行。
cpu_do_suspend_workaround 是 assembly code: suspend.S
parameter 1 是 chip ID, 因為這個 function 是mx50,mx51, mx53 共用的。
這段assembly code,作 invalid cache, set ddr to self-refresh mode.
set dd pin to high-z, 然後就進入 wait for interrupt 模式:
/*
* PLL1 workaround as the following: For mx51 only.
* Before enter WFI
* (1) switch DDR and ARM to PLL2
* (2) Disable AREN bit to avoid PLL1 restart during MFN change)
* (3) set PLL1 to ~864Mhz with MFI = 8, MFN = 180, MFD = 179
* thus the equation |MFN/(MFD+1)| < 1
* (4) Manual restart PLL1
* (5) Wait PLL1 lock
* After CPU out of WFI
* (6) Set PLL1 to 800Mhz with only change MFN to 60, others keep
* (7) Wait MFN change complete by delay 4.6us,
* (8) Switch DDR and ARM back to PLL1
*/