s5pc110: suspend/resume support issues mitigated
authorMyungJoo Ham <MyungJoo.Ham@samsung.com>
Mon, 30 Nov 2009 12:39:19 +0000 (21:39 +0900)
committerMyungJoo Ham <MyungJoo.Ham@samsung.com>
Mon, 30 Nov 2009 12:39:19 +0000 (21:39 +0900)
Fixed Issues:
- unstable resume (freezes occasionally)
- HW Revision number corruption (probably GPIO related issue)
- USB Download

Known Issues:
- unnecessary wake-up routines (needs to be cleaned)
- current mismatch between before-suspend and after-suspend
- current not low enough (will follow kernel suspend/resume)
- Slow wake-up time.
- Some regulators need to be turned off forcibly.

board/samsung/universal/universal.c
cpu/arm_cortexa8/s5pc1xx/sleep.c
cpu/arm_cortexa8/s5pc1xx/timer.c
lib_arm/board.c

index 7048891..fbfe1e6 100644 (file)
@@ -228,7 +228,8 @@ static int board_is_j1b2(void)
 }
 
 #ifdef CONFIG_MISC_INIT_R
-static char device_info[512];
+#define LENGTH_device_info     512
+static char device_info[LENGTH_device_info];
 static int display_info = 0;
 
 static void dprintf(const char *fmt, ...)
@@ -241,6 +242,13 @@ static void dprintf(const char *fmt, ...)
        i = vsprintf(buf, fmt, args);
        va_end(args);
 
+       buf[127] = 0;
+
+       if ((strlen(device_info) + strlen(buf)) > (LENGTH_device_info - 1)) {
+               puts("Flushing device info...\n");
+               puts(device_info);
+               device_info[0] = 0;
+       }
        strcat(device_info, buf);
        puts(buf);
 }
@@ -914,6 +922,9 @@ static void init_pmic(void)
 
 #define PREVIOUS(x)            (0x3 << ((x) << 1))
 
+#define R225_229_755_756_NOT_REMOVED
+#undef R225_229_755_756_NOT_REMOVED
+
 struct gpio_powermode {
        unsigned int    conpdn;
        unsigned int    pudpdn;
@@ -955,10 +966,19 @@ static struct gpio_powermode powerdown_modes[] = {
                OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | OUTPUT0(3),
                PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3),
        }, {    /* S5PC110_GPIO_D1_OFFSET */
+#ifdef R225_229_755_756_NOT_REMOVED
+               /* Original */
                INPUT(0) | INPUT(1) | INPUT(2) | INPUT(3) |
                OUTPUT0(4) | OUTPUT0(5),
                PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
                PULL_DIS(4) | PULL_DIS(5),
+#else
+               /* For current test board only with R225-229 / R755-756 removed  */
+               INPUT(0) | INPUT(1) | INPUT(2) | INPUT(3) |
+               INPUT(4) | INPUT(5),
+               PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
+               PULL_DIS(4) | PULL_DIS(5),
+#endif
        }, {    /* S5PC110_GPIO_E0_OFFSET */
                INPUT(0) | INPUT(1) | INPUT(2) | INPUT(3) |
                INPUT(4) | INPUT(5) | INPUT(6) | INPUT(7),
@@ -995,10 +1015,19 @@ static struct gpio_powermode powerdown_modes[] = {
                PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
                PULL_DIS(4) | PULL_DIS(5) | PULL_DIS(6),
        }, {    /* S5PC110_GPIO_G1_OFFSET */
+#ifdef R225_229_755_756_NOT_REMOVED
+               /* Original */
                OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | OUTPUT0(3) |
                OUTPUT0(4) | OUTPUT0(5) | OUTPUT0(6),
                PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
                PULL_DIS(4) | PULL_DIS(5) | PULL_DIS(6),
+#else
+               /* For the current test board */
+               OUTPUT0(0) | INPUT(1) | OUTPUT0(2) | INPUT(3) |
+               INPUT(4) | INPUT(5) | INPUT(6),
+               PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
+               PULL_DIS(4) | PULL_DIS(5) | PULL_DIS(6),
+#endif
        }, {    /* S5PC110_GPIO_G2_OFFSET */
                OUTPUT0(0) | OUTPUT0(1) | OUTPUT0(2) | OUTPUT0(3) |
                OUTPUT0(4) | OUTPUT0(5) | OUTPUT0(6),
index 19e6d24..60a5f0b 100644 (file)
@@ -53,13 +53,13 @@ struct regs_to_save {
 static struct regs_to_save core_save[] = {
        { .start_address=0xE0100200, .size=7},
        { .start_address=0xE0100280, .size=2},
-       { .start_address=0xE0100300, .size=7},
+       { .start_address=0xE0100300, .size=8},
        { .start_address=0xE0100460, .size=5},
        { .start_address=0xE0100480, .size=3},
        { .start_address=0xE0100500, .size=1},
        { .start_address=0xE0107008, .size=1},
 };
-static unsigned int buf_core_save[7+2+7+5+3+1+1];
+static unsigned int buf_core_save[7+2+8+5+3+1+1];
 static struct regs_to_save gpio_save[] = {
        { .start_address=0xE0200000, .size=6},
        { .start_address=0xE0200020, .size=6},
@@ -230,6 +230,7 @@ void s5pc110_wakeup(void)
 
 static int s5pc110_sleep(int mode)
 {
+       static int counter;
        unsigned long regs_save[16];
        unsigned int value;
        int i;
@@ -251,6 +252,11 @@ static int s5pc110_sleep(int mode)
        value |= (1 << 3);
        value |= (1 << 2);
        value |= (1 << 1);
+
+       value &= ~(1 << 5);
+       value &= ~(1 << 4);
+       value &= ~(1 << 3);
+
        writel(value, S5PC110_WAKEUP_MASK);
 
        value = __raw_readl(S5PC110_EINT_WAKEUP_MASK);
@@ -316,13 +322,17 @@ static int s5pc110_sleep(int mode)
        writel(value, S5PC110_OTHERS);
 
        if (mode == SLEEP_WFI) {
-               value = 0;
                s5pc110_sleep_save_phys = (unsigned int) regs_save;
 
                value = readl(S5PC110_OTHERS);
                value |= 1;
                writel(value, S5PC110_OTHERS);
 
+               /* cache flush */
+               asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); 
+               l2_cache_disable();
+               invalidate_dcache(get_device_type());
+
 #ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
                if (s5pc110_cpu_save(regs_save) == 0) {
                        /* cache flush */
@@ -338,17 +348,16 @@ static int s5pc110_sleep(int mode)
                s5pc110_wakeup();
 
                writel(0, S5PC110_EINT_WAKEUP_MASK);
-#ifdef CONFIG_CPU_S5PC110_EVT0_ERRATA
                readl(S5PC110_EINT_WAKEUP_MASK);
                for (i = 0; i < 4; i++)
                        readl(0xE0200F40+i*4);
-#endif
                value = readl(S5PC110_WAKEUP_STAT);
                writel(0xFFFF & value, S5PC110_WAKEUP_STAT);
 
                printf("Wakeup Source: 0x%08x\n", value);
                value = readl(S5PC110_WAKEUP_STAT);
 
+
 #else
                asm("b  1f\n\t"
                        ".align 5\n\t"
@@ -364,6 +373,7 @@ static int s5pc110_sleep(int mode)
 
        show_hw_revision();
 
+       counter++;
        board_sleep_resume();
        return 0;
 }
@@ -387,3 +397,4 @@ U_BOOT_CMD(
        "S5PC110 sleep",
        "sleep - sleep mode"
 );
+
index cdba5d9..dc4a2ce 100644 (file)
@@ -65,8 +65,14 @@ int timer_init(void)
 
        /* set prescaler : 16 */
        /* set divider : 2 */
-       writel((PRESCALER_1 & 0xff) << 8, &timer->tcfg0);
-       writel((MUX_DIV_2 & 0xf) << MUX4_DIV_SHIFT, &timer->tcfg1);
+       val = readl(&timer->tcfg0);
+       val &= ~(0xff << 8);
+       val |= (PRESCALER_1 & 0xff) << 8;
+       writel(val, &timer->tcfg0);
+       val = readl(&timer->tcfg1);
+       val &= ~(0xf << MUX4_DIV_SHIFT);
+       val |= (MUX_DIV_2 & 0xF) << MUX4_DIV_SHIFT;
+       writel(val, &timer->tcfg1);
 
        if (count_value == 0) {
                /* reset initial value */
@@ -117,7 +123,7 @@ void set_timer(unsigned long t)
 /* delay x useconds */
 void udelay(unsigned long usec)
 {
-       unsigned long tmo, tmp;
+       unsigned long tmo, tmp, now, until;
 
        if (usec >= 1000) {
                /*
@@ -137,18 +143,23 @@ void udelay(unsigned long usec)
        }
 
        /* get current timestamp */
-       tmp = get_timer(0);
+       tmp = get_timer_masked();
 
        /* if setting this fordward will roll time stamp */
        /* reset "advancing" timestamp to 0, set lastdec value */
        /* else, set advancing stamp wake up time */
-       if ((tmo + tmp + 1) < tmp)
+       until = tmo + tmp + count_value;
+       if (until < tmp) {
                reset_timer_masked();
+               tmp = get_timer_masked();
+               tmo += tmp;
+
+       }
        else
                tmo += tmp;
 
-       /* loop till event */
-       while (get_timer_masked() < tmo)
+       /* loop till event */ /* FIX: consider the overflow case */
+       while ((now = get_timer_masked()) < tmo && now >= tmp)
                ;       /* nop */
 }
 
index 2410f6e..87155e0 100644 (file)
@@ -273,6 +273,10 @@ void start_armboot_resume(void)
        unsigned long addr;
 #endif
 
+       timer_init();
+       init_func_i2c();
+
+#if 0
        /* Pointer is writable since we allocated a register for it */
        gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
        /* compiler optimization barrier needed for GCC >= 3.4 */
@@ -291,6 +295,7 @@ void start_armboot_resume(void)
                        hang ();
                }
        }
+#endif
 
 #ifdef CONFIG_VFD
 #      ifndef PAGE_SIZE
@@ -321,44 +326,51 @@ void start_armboot_resume(void)
        }
 #endif /* CONFIG_LCD */
 
+#if 0
 #if defined(CONFIG_CMD_NAND)
        puts ("NAND:  ");
        nand_init();            /* go init the NAND */
 #endif
+#endif
 
 #if defined(CONFIG_CMD_ONENAND)
        onenand_init();
 #endif
 
+#if 0
 #ifdef CONFIG_HAS_DATAFLASH
        AT91F_DataflashInit();
        dataflash_print_info();
 #endif
 
+#endif
        /* initialize environment */
-       env_relocate ();
-
+       /* env_relocate (); */
+#if 0
 #ifdef CONFIG_VFD
        /* must do this after the framebuffer is allocated */
        drv_vfd_init();
 #endif /* CONFIG_VFD */
+#endif
 
 #ifdef CONFIG_SERIAL_MULTI
        serial_initialize();
 #endif
-
        stdio_init_resume ();   /* get the devices list going. */
 
+#if 0
 #if defined(CONFIG_ARCH_MISC_INIT)
        /* miscellaneous arch dependent initialisations */
        arch_misc_init ();
 #endif
+#endif
 
 #if defined(CONFIG_MISC_INIT_R)
        /* miscellaneous platform dependent initialisations */
-       misc_init_r ();
+       misc_init_r();
 #endif
 
+#if 0
        /* enable exceptions */
        enable_interrupts ();
 
@@ -390,12 +402,13 @@ extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
 #ifdef BOARD_LATE_INIT
        board_late_init ();
 #endif
-
+#endif
 #ifdef CONFIG_GENERIC_MMC
        puts ("MMC:   ");
        mmc_initialize (gd->bd);
 #endif
 
+#if 0
 #ifdef CONFIG_BITBANGMII
        bb_miiphy_init();
 #endif
@@ -405,7 +418,7 @@ extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
 #endif
        eth_initialize(gd->bd);
 #endif
-
+#endif
 }
 
 void start_armboot (void)