1. Specific implementation steps
①Create a new cmd_suspend.c in the ./common folder, and add the following content to this file
+#include <common.h>+#include <command.h>
+#include <def.h>
+#include <nand.h>
+#include <s3c24x0.h>
+
+extern void s3c2440_cpu_suspend(void); / /Call external function, call the following function written in assembly
+
+static void delay(volatile int d)
+{
+ while(d--);
+}
+
+int do_suspend (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+//Query the seventh chapter of the 2440 chip manual to get the working mode setting of the 2440: Now we mainly set the sleep mode, and set the relevant registers according to the data sheet.
+ /* Sleep: */+ + /* 1. Configure GPIO: For example, if you want to keep the LED on or off, the pin used to wake up the CPU should be set to interrupt function */ + /* For NAND boot: set EINT23,22 ,21 is the input pin */ There are macro definitions of pins in the S3c24x0.h file + rGPGCON &= ~((3<<30) | (3<<28) | (3<<26)); + + / * JZ2440 only S2/S3/S4 can be used as wake-up source, set their corresponding GPIO for interrupt mode*/ + rGPFCON &= ~((3<<0) | (3<<4)); + rGPFCON |= ((2<<0) | (2<<4)); + + rGPGCON &= ~(3<<6); + rGPGCON |= (2<<6); + + /* 2. Set INTMSK to block all Interrupt: In sleep mode, these pins are only used to wake up the system, when the CPU is running normally, INTMSK can be reset to make these pins used for interrupt functions */ + rINTMSK = ~0; + + /* 3. Configure wake-up source */ +
rEXTINT0 |= (6<<0) | (6<<8); /* EINT0,2 double edge trigger*/
+ rEXTINT1 |= (6<<12); /* EINT11 double edge trigger*/
+
+ /* 4. Set MISCCR[13:12]=11b, make the USB module go to sleep*/
+ rMISCCR |= (3<<12);
+
+ /* 5. Save some value in GSTATUS[4:3], they can be in Use when the system wakes up*/
+ //rGSTATUS3 = ; /* The address of the first function to be executed when the system wakes up*/
+ //rGSTATUS4 = ; /* */
+
+ /* 6. Set MISCCR[1:0] to enable Pull-up resistor for data bus */
+ rMISCCR &= ~(3);
+
+ /* 7. Clear LCDCON1.ENVID to stop LCD */
+ rLCDCON1 &= ~1;
+
+ /* 8~12 implemented using assembly , refer to the kernel source code:
+ * arch\arm\mach-s3c2410\sleep.S
+ */
+ //新建u-boot-1.1.6/cpu/arm920t/suspend.S文件
+suspend.s文件内容如下:
+#define S3C2440_REFRESH_SELF (1<<22)
+#define S3C2440_MISCCR_SDSLEEP (7<<17)
+#define S3C2440_CLKCON_POWER (1<<3)
+
+#define GSTATUS2 (0x560000B4)
+#define GSTATUS3 (0x560000B8)
+#define GSTATUS4 (0x560000BC)
+
+#define REFRESH (0x48000024)
+#define MISCCR (0x56000080)
+#define CLKCON (0x4C00000C)
+
+.globl s3c2440_cpu_suspend //全局函数
+ @@ prepare cpu to sleep
+s3c2440_cpu_suspend:
+ stmdb sp!, { r4-r12,lr }
+
+ /* GSTATUS3中存放唤醒时要执行的函数 */
+ ldr r0, =s3c2440_do_resume
+ ldr r1, =GSTATUS3
+ str r0, [r1]
+
+ ldr r1, =GSTATUS4
+ str sp, [r1]
+
+ ldr r4, =REFRESH
+ ldr r5, =MISCCR
+ ldr r6, =CLKCON
+ ldr r7, [ r4 ] @ get REFRESH
+ ldr r8, [ r5 ] @ get MISCCR
+ ldr r9, [ r6 ] @ get CLKCON
+
+ orr r7, r7, #S3C2440_REFRESH_SELF @ SDRAM sleep command
+ orr r8, r8, #S3C2440_MISCCR_SDSLEEP @ SDRAM power-down signals
+ orr r9, r9, #S3C2440_CLKCON_POWER @ power down command
+
+ teq pc, #0 @ first as a trial-run to load cache
+ bl s3c2440_do_sleep
+ teq r0, r0 @ now do it for real
+ b s3c2440_do_sleep @
+
+ @@ align next bit of code to cache line
+ .align 5
+s3c2440_do_sleep:
+ streq r7, [ r4 ] @ SDRAM sleep command
+ streq r8, [ r5 ] @ SDRAM power-down config
+ streq r9, [ r6 ] @ CPU sleep
+1: beq 1b
+ mov pc, r14
+
+s3c2440_do_resume:
+ /* 返回到do_suspend函数 */
+ ldr r1, =GSTATUS4
+ ldr sp, [r1]
+
+ ldmia sp!, { r4-r12,pc }
+ /* 8. 读这2个寄存器: rREFRESH and rCLKCON, 以便填充TLB+ * 如果不使用MMU的话,这个目的可以忽略
+ */
+
+ /* 9. 设置 REFRESH[22]=1b,让SDRAM进入self-refresh mode */
+
+ /* 10. 等待SDRAM成功进入self-refresh mode */
+
+ /* 11.设置 MISCCR[19:17]=111b以保护SDRAM信号(SCLK0,SCLK1 and SCKE) */
+
+ /* 12. 设置CLKCON的SLEEP位让系统进入sleep mode */
+ printf("suspend ...");
+ delay(1000000);
+ s3c2440_cpu_suspend(); /* 执行到这里就不会返回,直到CPU被唤醒 */
+ ++++ //修改cpu\arm920t\start.s文件,唤醒的时候类似于nREST pin,所以修改start.s文件,实现唤醒功能
+ /* 恢复运行: 重新初始化硬件 */
+ serial_init();
+ printf("wake up\n");
+
+
+ return 0;
+}
+
+
+U_BOOT_CMD(
+ suspend, 1, 0, do_suspend, //1表示只要一个参数
+ "suspend - suspend the board\n",
+ " - suspend the board"
+);
②在./common/Makefile中添加:
COBJS-y += cmd_led.o
SOBJS = suspend.o
③在Linux环境下,重新编译u-boot,得到u-boot.bin,并下载到自己的开发板中测试,输入help就会发现led命令