s5pc110: universal: change board name from "Neptune" to "Limo SDK"
[kernel/u-boot.git] / board / samsung / universal / universal.c
index 31b45c3..b1c23b2 100644 (file)
 #include <asm/arch/mmc.h>
 #include <asm/arch/power.h>
 #include <asm/arch/mem.h>
+#include <asm/arch/hs_otg.h>
+#include <asm/arch/regs-otg.h>
+#include <asm/arch/rtc.h>
+#include <asm/arch/adc.h>
 #include <asm/errno.h>
 #include <fbutils.h>
 #include <lcd.h>
@@ -46,10 +50,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define C100_MACH_START                        3000
 #define C110_MACH_START                        3100
 
-/* FIXME Neptune workaround */
-#define USE_NEPTUNE_BOARD
-#undef USE_NEPTUNE_BOARD
-
 static unsigned int board_rev;
 static unsigned int battery_soc;
 static struct s5pc110_gpio *s5pc110_gpio;
@@ -115,7 +115,7 @@ static struct i2c_gpio_bus_data i2c_gpio6 = {
 };
 
 /*
- * i2c gpio7 - aries
+ * i2c gpio7 - kessler
  * SDA: MP05[1]
  * SCL: MP05[0]
  */
@@ -176,12 +176,16 @@ static int hwrevision(int rev)
 enum {
        MACH_UNIVERSAL,
        MACH_TICKERTAPE,
-       MACH_AQUILA,
+       MACH_CHANGED,
        MACH_P1P2,      /* Don't remove it */
        MACH_GEMINUS,
        MACH_CYPRESS,
 
        MACH_WMG160 = 160,
+
+       MACH_PSEUDO_END,
+
+       MACH_KESSLER    = 3102,
 };
 
 #define SPLIT_SCREEN_FEATURE   0x100
@@ -192,7 +196,10 @@ enum {
 #define LIMO_REAL_BOARD                0x0800
 #define MEDIA_BOARD            0x1000
 #define BAMBOO_BOARD           0x2000
-#define ARIES_BOARD            0x4000
+
+/* board is MACH_KESSLER and board is like below */
+#define S1_BOARD               0x1000
+#define KESSLER_BOARD          0x4000
 #define NEPTUNE_BOARD          0x8000
 
 #define BOARD_MASK             0xFF00
@@ -202,68 +209,75 @@ static int c110_machine_id(void)
        return gd->bd->bi_arch_number - C110_MACH_START;
 }
 
-static int machine_is_aquila(void)
+static int mach_is_aquila(void)
 {
-       return c110_machine_id() == MACH_AQUILA;
+       return gd->bd->bi_arch_number == MACH_TYPE_AQUILA;
 }
 
-static int machine_is_tickertape(void)
+static int mach_is_tickertape(void)
 {
        return c110_machine_id() == MACH_TICKERTAPE;
 }
 
-static int machine_is_geminus(void)
+static int mach_is_geminus(void)
 {
        return c110_machine_id() == MACH_GEMINUS;
 }
 
-static int machine_is_cypress(void)
+static int mach_is_cypress(void)
 {
        return c110_machine_id() == MACH_CYPRESS;
 }
 
 static int board_is_limo_universal(void)
 {
-       return machine_is_aquila() && (board_rev & LIMO_UNIVERSAL_BOARD);
+       return mach_is_aquila() && (board_rev & LIMO_UNIVERSAL_BOARD);
 }
 
 static int board_is_limo_real(void)
 {
-       return machine_is_aquila() && (board_rev & LIMO_REAL_BOARD);
+       return mach_is_aquila() && (board_rev & LIMO_REAL_BOARD);
 }
 
-static int board_is_media(void)
+static int board_is_bamboo(void)
 {
-       return machine_is_aquila() && (board_rev & MEDIA_BOARD);
+       return mach_is_aquila() && (board_rev & BAMBOO_BOARD);
 }
 
-static int board_is_bamboo(void)
+static int board_is_media(void)
 {
-       return machine_is_aquila() && (board_rev & BAMBOO_BOARD);
+       return mach_is_aquila() && (board_rev & MEDIA_BOARD);
 }
 
 static int board_is_j1b2(void)
 {
-       return machine_is_aquila() && (board_rev & J1_B2_BOARD);
+       return mach_is_aquila() && (board_rev & J1_B2_BOARD);
 }
 
-static int board_is_aries(void)
+/* Kessler */
+static int mach_is_kessler(void)
 {
-       return machine_is_aquila() && (board_rev & ARIES_BOARD);
+       return gd->bd->bi_arch_number == MACH_KESSLER;
 }
 
 static int board_is_neptune(void)
 {
-       return machine_is_aquila() && (board_rev & NEPTUNE_BOARD);
+       return mach_is_kessler() && (board_rev & NEPTUNE_BOARD);
+}
+
+static int board_is_s1(void)
+{
+       return mach_is_kessler() && (board_rev & S1_BOARD);
 }
 
 /* DLNA Dongle */
-static int machine_is_wmg160(void)
+static int mach_is_wmg160(void)
 {
        return c110_machine_id() == MACH_WMG160;
 }
 
-static void enable_battery(void);
+static void check_battery(int mode);
+static void check_micro_usb(int intr);
 
 void i2c_init_board(void)
 {
@@ -275,15 +289,13 @@ void i2c_init_board(void)
 
        num_bus = ARRAY_SIZE(i2c_gpio);
 
-       if (machine_is_aquila()) {
-               if (board_is_aries()) {
-                       i2c_gpio[I2C_GPIO7].bus->gpio_base =
-                               (unsigned int)&gpio->gpio_mp0_5;
-               } else {
-                       i2c_gpio[I2C_GPIO6].bus->gpio_base = 0;
-                       i2c_gpio[I2C_GPIO7].bus->gpio_base = 0;
-               }
-       } else if (machine_is_cypress()) {
+       if (mach_is_aquila()) {
+               i2c_gpio[I2C_GPIO6].bus->gpio_base = 0;
+               i2c_gpio[I2C_GPIO7].bus->gpio_base = 0;
+       } else if (mach_is_kessler()) {
+               i2c_gpio[I2C_GPIO7].bus->gpio_base =
+                       (unsigned int)&gpio->gpio_mp0_5;
+       } else if (mach_is_cypress()) {
                i2c_gpio[I2C_GPIO7].bus = &i2c_cypress_gpio7;
                i2c_gpio[I2C_GPIO7].bus->gpio_base =
                        (unsigned int)&gpio->gpio_mp0_5;
@@ -299,16 +311,23 @@ void i2c_init_board(void)
 
        i2c_gpio_init(i2c_gpio, num_bus, I2C_PMIC);
 
+       /* Reset on fsa9480 early */
+       check_micro_usb(1);
        /* Reset on max17040 early */
        if (battery_soc == 0)
-               enable_battery();
+               check_battery(1);
 }
 
 #ifdef CONFIG_MISC_INIT_R
-#define DEV_INFO_LEN           512
+#define DEV_INFO_LEN           256
 static char device_info[DEV_INFO_LEN];
 static int display_info;
 
+static void empty_device_info_buffer(void)
+{
+       memset(device_info, 0x0, DEV_INFO_LEN);
+}
+
 static void dprintf(const char *fmt, ...)
 {
        va_list args;
@@ -324,9 +343,9 @@ static void dprintf(const char *fmt, ...)
        if ((strlen(device_info) + strlen(buf)) > (DEV_INFO_LEN - 1)) {
                puts("Flushing device info...\n");
                puts(device_info);
-               device_info[0] = 0;
+               empty_device_info_buffer();
        }
-       strcat(device_info, buf);
+       strncat(device_info, buf, 127);
        puts(buf);
 }
 
@@ -351,11 +370,11 @@ static void display_device_info(void)
 static const char *board_name[] = {
        "Universal",
        "TickerTape",
-       "Aquila",
+       "Kessler",
        "P1P2",         /* Don't remove it */
        "Geminus",
        "Cypress",
-       "Neptune",
+       "Limo SDK",
 };
 
 enum {
@@ -373,7 +392,7 @@ static char *display_features(int board, int board_rev)
        char *buf = feature_buffer;
        char *name = NULL;
 
-       if (board == MACH_AQUILA) {
+       if (board == MACH_TYPE_AQUILA) {
                if (board_rev & SPLIT_SCREEN_FEATURE)
                        name = "SplitScreen";
                if (board_rev & J1_B2_BOARD)
@@ -387,29 +406,32 @@ static char *display_features(int board, int board_rev)
                        name = "Media";
                if (board_rev & BAMBOO_BOARD)
                        name = "Bamboo";
-               if (board_rev & ARIES_BOARD)
-                       name = "Aries";
+       } else if (board == MACH_KESSLER) {
                if (board_rev & NEPTUNE_BOARD)
-                       name = "Neptune";
-
-               if (name)
-                       count += sprintf(buf + count, " - %s", name);
+                       name = "Limo SDK";
+               if (board_rev & S1_BOARD)
+                       name = "S1";
        }
+       if (name)
+               count += sprintf(buf + count, " - %s", name);
 
        return buf;
 }
 
 static char *get_board_name(int board)
 {
-       if (board == MACH_WMG160)
+       if (board == MACH_TYPE_AQUILA)
+               return "Aquila";
+       else if (board == MACH_KESSLER)
+               return "Kessler";
+       else if (board == MACH_WMG160)
                return "WMG160";
        return (char *) board_name[board];
 }
 
 static void check_board_revision(int board, int rev)
 {
-       switch (board) {
-       case MACH_AQUILA:
+       if (board == MACH_TYPE_AQUILA) {
                /* Limo Real or Universal */
                if (rev & LIMO_UNIVERSAL_BOARD)
                        board_rev &= ~J1_B2_BOARD;
@@ -424,46 +446,39 @@ static void check_board_revision(int board, int rev)
                                        LIMO_UNIVERSAL_BOARD |
                                        LIMO_REAL_BOARD |
                                        MEDIA_BOARD);
-               if (rev & ARIES_BOARD)
+       } else if (board == MACH_KESSLER) {
+               if (rev & KESSLER_BOARD)
                        board_rev &= ~(J1_B2_BOARD |
                                        LIMO_UNIVERSAL_BOARD);
                if (rev & NEPTUNE_BOARD)
                        board_rev &= ~(J1_B2_BOARD |
                                        LIMO_UNIVERSAL_BOARD);
-               break;
-       case MACH_CYPRESS:
-       case MACH_TICKERTAPE:
-       case MACH_GEMINUS:
-       case MACH_WMG160:
+               if (rev & S1_BOARD)
+                       board_rev &= ~(J1_B2_BOARD | LIMO_UNIVERSAL_BOARD |
+                                       LIMO_REAL_BOARD);
+       } else {
                board_rev &= ~BOARD_MASK;
-               break;
-       default:
-               break;
        }
 }
 
 static unsigned int get_hw_revision(struct s5pc1xx_gpio_bank *bank, int hwrev3)
 {
        unsigned int rev;
-       int mode3 = 1;
-
-       if (hwrev3)
-               mode3 = 7;
 
        gpio_direction_input(bank, 2);
        gpio_direction_input(bank, 3);
        gpio_direction_input(bank, 4);
-       gpio_direction_input(bank, mode3);
+       gpio_direction_input(bank, hwrev3);
 
        gpio_set_pull(bank, 2, GPIO_PULL_NONE);         /* HWREV_MODE0 */
        gpio_set_pull(bank, 3, GPIO_PULL_NONE);         /* HWREV_MODE1 */
        gpio_set_pull(bank, 4, GPIO_PULL_NONE);         /* HWREV_MODE2 */
-       gpio_set_pull(bank, mode3, GPIO_PULL_NONE);     /* HWREV_MODE3 */
+       gpio_set_pull(bank, hwrev3, GPIO_PULL_NONE);    /* HWREV_MODE3 */
 
        rev = gpio_get_value(bank, 2);
        rev |= (gpio_get_value(bank, 3) << 1);
        rev |= (gpio_get_value(bank, 4) << 2);
-       rev |= (gpio_get_value(bank, mode3) << 3);
+       rev |= (gpio_get_value(bank, hwrev3) << 3);
 
        return rev;
 }
@@ -484,7 +499,7 @@ static void check_hw_revision(void)
        } else {
                struct s5pc110_gpio *gpio =
                        (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
-               int hwrev3 = 0;
+               int hwrev3 = 1;
 
                board_rev = 0;
 
@@ -502,10 +517,10 @@ static void check_hw_revision(void)
                 * ADDR = 0xE0200000 + OFF
                 *
                 *       OFF    Universal BB   LRA  LUA  OA   TT   SS        CYP
-                *   J1: 0x0264 0x10      0x10 0x00 0x00 0x00 0x00 0x00     
-                *   J2: 0x0284           0x01 0x10 0x00 
+                *   J1: 0x0264 0x10      0x10 0x00 0x00 0x00 0x00 0x00
+                *   J2: 0x0284           0x01 0x10 0x00
                 *   H1: 0x0C24    W           0x28 0xA8 0x1C                0x0F
-                *   H3: 0x0C64                0x03 0x07 0x0F               
+                *   H3: 0x0C64                0x03 0x07 0x0F
                 *   D1: 0x00C4 0x0F           0x3F 0x3F 0x0F 0xXC 0x3F
                 *    I: 0x0224                          0x02 0x00 0x08
                 * MP03: 0x0324                          0x9x      0xbx 0x9x
@@ -514,7 +529,7 @@ static void check_hw_revision(void)
 
                /* C110 Aquila */
                if (gpio_get_value(&gpio->gpio_j1, 4) == 0) {
-                       board = MACH_AQUILA;
+                       board = MACH_TYPE_AQUILA;
                        board_rev |= J1_B2_BOARD;
 
                        gpio_set_pull(&gpio->gpio_j2, 6, GPIO_PULL_NONE);
@@ -537,13 +552,13 @@ static void check_hw_revision(void)
 
                /* Workaround: C110 Aquila Rev0.6 */
                if (board_rev == 6) {
-                       board = MACH_AQUILA;
+                       board = MACH_TYPE_AQUILA;
                        board_rev |= LIMO_REAL_BOARD;
                }
 
                /* C110 Aquila Bamboo */
                if (gpio_get_value(&gpio->gpio_j2, 0) == 1) {
-                       board = MACH_AQUILA;
+                       board = MACH_TYPE_AQUILA;
                        board_rev |= BAMBOO_BOARD;
                }
 
@@ -552,6 +567,22 @@ static void check_hw_revision(void)
                                gpio_get_value(&gpio->gpio_d1, 1) == 0)
                        board = MACH_TICKERTAPE;
 
+               /* WMG160 - GPH3[0:4] = 0x00 */
+               if (board == MACH_TICKERTAPE) {
+                       int i, wmg160 = 1;
+
+                       for (i = 0; i < 4; i++) {
+                               if (gpio_get_value(&gpio->gpio_h3, i) != 0) {
+                                       wmg160 = 0;
+                                       break;
+                               }
+                       }
+                       if (wmg160) {
+                               board = MACH_WMG160;
+                               hwrev3 = 7;
+                       }
+               }
+
                /* C110 Geminus for rev0.0 */
                gpio_set_pull(&gpio->gpio_j1, 2, GPIO_PULL_NONE);
                gpio_direction_input(&gpio->gpio_j1, 2);
@@ -568,11 +599,11 @@ static void check_hw_revision(void)
                gpio_direction_input(&gpio->gpio_j0, 6);
                if (gpio_get_value(&gpio->gpio_j0, 6) == 1) {
                        board = MACH_GEMINUS;
-                       hwrev3 = 1;
+                       hwrev3 = 7;
                }
                gpio_set_pull(&gpio->gpio_j0, 6, GPIO_PULL_DOWN);
 
-               /* Aquila - Aries MP0_5[6] == 1 */
+               /* Kessler MP0_5[6] == 1 */
                gpio_direction_input(&gpio->gpio_mp0_5, 6);
                if (gpio_get_value(&gpio->gpio_mp0_5, 6) == 1) {
                        /* Cypress: Do this for cypress */
@@ -582,42 +613,40 @@ static void check_hw_revision(void)
                                board = MACH_CYPRESS;
                                gpio_direction_output(&gpio->gpio_mp0_5, 6, 0);
                        } else {
-                               board = MACH_AQUILA;
-                               board_rev |= ARIES_BOARD;
-#ifdef USE_NEPTUNE_BOARD
-                               board_rev &= ~ARIES_BOARD;
-                               board_rev |= NEPTUNE_BOARD;
-#endif
+                               board = MACH_KESSLER;
+                               board_rev |= KESSLER_BOARD;
+
+                               /* Neptune MP0_5[4] == 1 */
+                               gpio_direction_input(&gpio->gpio_mp0_5, 4);
+                               if (gpio_get_value(&gpio->gpio_mp0_5, 4) == 1) {
+                                       board_rev &= ~KESSLER_BOARD;
+                                       board_rev |= NEPTUNE_BOARD;
+                               }
                        }
                        gpio_set_pull(&gpio->gpio_j2, 2, GPIO_PULL_DOWN);
-                       hwrev3 = 1;
-               } else
+                       hwrev3 = 7;
+               } else {
                        gpio_direction_output(&gpio->gpio_mp0_5, 6, 0);
-
-               /* WMG160 - GPH3[0:4] = 0x00 */
-               do {
-                       int i, wmg160 = 1;
-
-                       for (i = 0; i < 4; i++) {
-                               if (gpio_get_value(&gpio->gpio_h3, i) != 0) {
-                                       wmg160 = 0;
-                                       break;
-                               }
-                       }
-                       if (wmg160) {
-                               board = MACH_WMG160;
-                               hwrev3 = 1;
+                       /* Kessler S1 board detection */
+                       if (board == MACH_TICKERTAPE) {
+                               board = MACH_KESSLER;
+                               board_rev |= S1_BOARD;
+                               hwrev3 = 7;
                        }
-               } while (0);
+               }
 
                board_rev |= get_hw_revision(&gpio->gpio_j0, hwrev3);
        }
 
        /* Set machine id */
-       if (cpu_is_s5pc110())
-               gd->bd->bi_arch_number = C110_MACH_START + board;
-       else
-               gd->bd->bi_arch_number = C100_MACH_START + board;
+       if (board < MACH_PSEUDO_END) {
+               if (cpu_is_s5pc110())
+                       gd->bd->bi_arch_number = C110_MACH_START + board;
+               else
+                       gd->bd->bi_arch_number = C100_MACH_START + board;
+       } else {
+               gd->bd->bi_arch_number = board;
+       }
 
        /* Architecture Common settings */
        if (cpu_is_s5pc110()) {
@@ -646,7 +675,9 @@ static void show_hw_revision(void)
                }
        }
 
-       if (cpu_is_s5pc110())
+       if (mach_is_kessler() || mach_is_aquila())
+               board = gd->bd->bi_arch_number;
+       else if (cpu_is_s5pc110())
                board = gd->bd->bi_arch_number - C110_MACH_START;
        else
                board = gd->bd->bi_arch_number - C100_MACH_START;
@@ -654,18 +685,32 @@ static void show_hw_revision(void)
        check_board_revision(board, board_rev);
 
        /* Set CPU Revision */
-       if (machine_is_aquila()) {
+       if (mach_is_aquila()) {
                if (board_is_limo_real()) {
                        if ((board_rev & 0xf) < 8)
                                s5pc1xx_set_cpu_rev(0);
                }
-       } else if (machine_is_geminus()) {
+               else if (board_is_bamboo())
+                       s5pc1xx_set_cpu_rev(0);
+       } else if (mach_is_kessler()) {
+               if (board_is_neptune() && hwrevision(2))
+                       s5pc1xx_set_cpu_rev(2); /* EVT1-Fused */
+               else
+                       s5pc1xx_set_cpu_rev(1);
+       } else if (mach_is_geminus()) {
                if ((board_rev & 0xf) < 1)
                        s5pc1xx_set_cpu_rev(0);
+       } else if (mach_is_cypress()) {
+               s5pc1xx_set_cpu_rev(1);
        } else {
                s5pc1xx_set_cpu_rev(0);
        }
 
+       if (cpu_is_s5pc110())
+               writel(0xc1100000 | (0xffff & (s5pc1xx_get_cpu_rev() ? 1 : 0)),
+                               S5PC110_INFORM3);
+
+       empty_device_info_buffer();
        dprintf("HW Revision:\t%x (%s%s) %s\n",
                board_rev, get_board_name(board),
                display_features(board, board_rev),
@@ -679,11 +724,11 @@ static void check_auto_burn(void)
        char buf[64];
 
        if (readl(magic_base) == 0x426f6f74) {  /* ASICC: Boot */
-               printf("Auto burning bootloader\n");
+               puts("Auto burning bootloader\n");
                count += sprintf(buf + count, "run updateb; ");
        }
        if (readl(magic_base + 0x04) == 0x4b65726e) {   /* ASICC: Kern */
-               printf("Auto burning kernel\n");
+               puts("Auto burning kernel\n");
                count += sprintf(buf + count, "run updatek; ");
        }
 
@@ -784,17 +829,23 @@ static void setup_media_gpios(void)
 static void check_keypad(void)
 {
        unsigned int reg, value;
-       unsigned int col_mask, row_mask;
+       unsigned int col_num, row_num;
+       unsigned int col_mask;
+       unsigned int col_mask_shift;
+       unsigned int row_state[4];
+       unsigned int i;
        unsigned int auto_download = 0;
-       unsigned int col_value[4], i;
 
-       if (machine_is_wmg160())
+       if (mach_is_wmg160())
                return;
 
        if (cpu_is_s5pc100()) {
                struct s5pc100_gpio *gpio =
                        (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
 
+               row_num = 3;
+               col_num = 3;
+
                /* Set GPH2[2:0] to KP_COL[2:0] */
                gpio_cfg_pin(&gpio->gpio_h2, 0, 0x3);
                gpio_cfg_pin(&gpio->gpio_h2, 1, 0x3);
@@ -806,124 +857,113 @@ static void check_keypad(void)
                gpio_cfg_pin(&gpio->gpio_h3, 2, 0x3);
 
                reg = S5PC100_KEYPAD_BASE;
+               col_mask = S5PC1XX_KEYIFCOL_MASK;
+               col_mask_shift = 0;
        } else {
                if (board_is_limo_real() || board_is_limo_universal()) {
-                       row_mask = 0x00FF;
-                       col_mask = 0x0FFF;
+                       row_num = 2;
+                       col_num = 3;
                } else {
-                       row_mask = 0xFFFF;
-                       col_mask = 0xFFFF;
+                       row_num = 4;
+                       col_num = 4;
                }
 
-               for (i = 0; i < 4; i++) {
+               for (i = 0; i < row_num; i++) {
                        /* Set GPH3[3:0] to KP_ROW[3:0] */
-                       if (row_mask & (0xF << (i << 2))) {
-                               gpio_cfg_pin(&s5pc110_gpio->gpio_h3, i, 0x3);
-                               gpio_set_pull(&s5pc110_gpio->gpio_h3, i,
-                                               GPIO_PULL_UP);
-                       }
+                       gpio_cfg_pin(&s5pc110_gpio->gpio_h3, i, 0x3);
+                       gpio_set_pull(&s5pc110_gpio->gpio_h3, i, GPIO_PULL_UP);
+               }
 
+               for (i = 0; i < col_num; i++)
                        /* Set GPH2[3:0] to KP_COL[3:0] */
-                       if (col_mask & (0xF << (i << 2)))
-                               gpio_cfg_pin(&s5pc110_gpio->gpio_h2, i, 0x3);
-               }
+                       gpio_cfg_pin(&s5pc110_gpio->gpio_h2, i, 0x3);
 
                reg = S5PC110_KEYPAD_BASE;
+               col_mask = S5PC110_KEYIFCOLEN_MASK;
+               col_mask_shift = 8;
        }
-       /* init col */
-       value = 0x00;
-       writel(value, reg + S5PC1XX_KEYIFCOL_OFFSET);
-       value = readl(reg + S5PC1XX_KEYIFROW_OFFSET);
-       /* VOLUMEDOWN and CAM(Half shot) Button */
-       if ((value & KBR1) == 0) {
-               i = 0;
-               while (i < 4) {
-                       value = readl(reg + S5PC1XX_KEYIFCOL_OFFSET);
-                       value |= 0xff;
-                       value &= ~(1 << i);
-                       writel(value, reg + S5PC1XX_KEYIFCOL_OFFSET);
-                       udelay(10*1000);
-                       col_value[i++] = readl(reg + S5PC1XX_KEYIFROW_OFFSET);
-               }
-               writel(0x00, reg + S5PC1XX_KEYIFCOL_OFFSET);
 
-               /* expected value is row_value[0] = 0x00 row_value[1] = 0x01 */
-               /* workaround */
-               if (col_value[1] == 0xd && col_value[2] == 0xe && machine_is_geminus())
-                       auto_download = 1;
+       /* KEYIFCOL reg clear */
+       writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
 
-               if ((col_value[0] & 0x3) == 0x3 && (col_value[1] & 0x3) == 0x3)
-                       auto_download = 1;
+       /* key_scan */
+       for (i = 0; i < col_num; i++) {
+               value = col_mask;
+               value &= ~(1 << i) << col_mask_shift;
 
-               if ((col_value[0] & 0x3) == 0x3 && (col_value[1] & 0x3) != 0x3)
-                       display_info = 1;
+               writel(value, reg + S5PC1XX_KEYIFCOL_OFFSET);
+               udelay(1000);
+
+               value = readl(reg + S5PC1XX_KEYIFROW_OFFSET);
+               row_state[i] = ~value & ((1 << row_num) - 1);
+               if (row_state[i])
+                       printf("[%d col] row_state: 0x%x\n", i, row_state[i]);
        }
 
+       /* KEYIFCOL reg clear */
+       writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
+
+       if (mach_is_aquila() || mach_is_kessler()) {
+               /* volume down */
+               if (row_state[1] & 0x2)
+                       display_info = 1;
+               if (board_is_neptune() && hwrevision(0)) {
+                       /* home & volume down */
+                       if ((row_state[1] & 0x1) && (row_state[1] & 0x2))
+                               auto_download = 1;
+               } else if (board_is_neptune() && hwrevision(2)) {
+                       /* cam full shot & volume down */
+                       if ((row_state[1] & 0x6) && (row_state[2] & 0x4))
+                               auto_download = 1;
+               } else {
+                       /* cam full shot & volume down */
+                       if ((row_state[0] & 0x1) && (row_state[1] & 0x2))
+                               auto_download = 1;
+               }
+       } else if (mach_is_geminus())
+               /* volume down & home */
+               if ((row_state[1] & 0x2) && (row_state[2] & 0x1))
+                       auto_download = 1;
+
        if (auto_download)
                setenv("bootcmd", "usbdown");
 }
 
-static void enable_battery(void)
+static void check_battery(int mode)
 {
        unsigned char val[2];
        unsigned char addr = 0x36;      /* max17040 fuel gauge */
 
        i2c_set_bus_num(I2C_GPIO3);
 
-       if (machine_is_aquila()) {
-               if (board_is_aries() || board_is_neptune())
-                       i2c_set_bus_num(I2C_GPIO7);
-               else if (board_is_j1b2())
+       if (mach_is_aquila()) {
+               if (board_is_j1b2())
                        return;
-       } else if (machine_is_tickertape()) {
-               return;
-       } else if (machine_is_cypress()) {
+       } else if (mach_is_kessler()) {
                i2c_set_bus_num(I2C_GPIO7);
-       } else if (machine_is_geminus()) {
-               if (hwrevision(1))
-                       i2c_set_bus_num(I2C_GPIO7);
-       }
-
-       if (i2c_probe(addr)) {
-               printf("Can't found max17040 fuel gauge\n");
-               return;
-       }
-
-       val[0] = 0x54;
-       val[1] = 0x00;
-       i2c_write(addr, 0xfe, 1, val, 2);
-}
-
-static void check_battery(void)
-{
-       unsigned char val[2];
-       unsigned char addr = 0x36;      /* max17040 fuel gauge */
-
-       i2c_set_bus_num(I2C_GPIO3);
-
-       if (machine_is_aquila()) {
-               if (board_is_aries() || board_is_neptune())
-                       i2c_set_bus_num(I2C_GPIO7);
-               else if (board_is_j1b2())
-                       return;
-       } else if (machine_is_cypress()) {
+       } else if (mach_is_cypress()) {
                i2c_set_bus_num(I2C_GPIO7);
-       } else if (machine_is_geminus()) {
+       } else if (mach_is_geminus()) {
                if (hwrevision(1))
                        i2c_set_bus_num(I2C_GPIO7);
        } else
                return;
 
        if (i2c_probe(addr)) {
-               printf("Can't found max17040 fuel gauge\n");
+               puts("Can't found max17040 fuel gauge\n");
                return;
        }
 
-       i2c_read(addr, 0x04, 1, val, 1);
-
-       dprintf("battery:\t%d%%\n", val[0]);
-
-       battery_soc = val[0];
+       /* mode 0: check mode / 1: enable mode */
+       if (mode) {
+               val[0] = 0x54;
+               val[1] = 0x00;
+               i2c_write(addr, 0xfe, 1, val, 2);
+       } else {
+               i2c_read(addr, 0x04, 1, val, 1);
+               dprintf("battery:\t%d%%\n", val[0]);
+               battery_soc = val[0];
+       }
 }
 
 static void check_mhl(void)
@@ -948,7 +988,7 @@ static void check_mhl(void)
 
        /* set usb path */
        if (i2c_probe(addr)) {
-               printf("Can't found MHL Chip\n");
+               puts("Can't found MHL Chip\n");
                return;
        }
 
@@ -971,16 +1011,42 @@ static void check_mhl(void)
        i2c_read((0x72 >> 1), 0xa0, 1, val, 1);
 }
 
+static int max8998_probe(void)
+{
+       unsigned char addr = 0xCC >> 1;
+
+       i2c_set_bus_num(I2C_PMIC);
+
+       if (i2c_probe(addr)) {
+               puts("Can't found max8998\n");
+               return 1;
+       }
+
+       return 0;
+}
+
 #define CHARGER_ANIMATION_FRAME                6
+static void max8998_clear_interrupt(void)
+{
+       unsigned char addr, val[2];
+       addr = 0xCC >> 1;
+
+       if (max8998_probe())
+               return;
+
+       i2c_read(addr, 0x00, 1, val, 1);
+       i2c_read(addr, 0x01, 1, val, 1);
+       i2c_read(addr, 0x02, 1, val, 1);
+       i2c_read(addr, 0x03, 1, val, 1);
+}
+
 static int max8998_power_key(void)
 {
        unsigned char addr, val[2];
-       i2c_set_bus_num(I2C_PMIC);
        addr = 0xCC >> 1;
-       if (i2c_probe(addr)) {
-               printf("Can't found max8998\n");
+
+       if (max8998_probe())
                return 0;
-       }
 
        /* Accessing IRQ1 register */
        i2c_read(addr, 0x00, 1, val, 1);
@@ -990,32 +1056,256 @@ static int max8998_power_key(void)
        return 0;
 }
 
+static int max8998_has_ext_power_source(void)
+{
+       unsigned char addr, val[2];
+       addr = 0xCC >> 1;
+
+       if (max8998_probe())
+               return 0;
+
+       /* Accessing STATUS2 register */
+       i2c_read(addr, 0x09, 1, val, 1);
+       if (val[0] & (1 << 5))
+               return 1;
+
+       return 0;
+}
+
+struct thermister_stat {
+       short centigrade;
+       unsigned short adc;
+};
+
+static struct thermister_stat adc_to_temperature_data[] = {
+       { .centigrade = -20,    .adc = 1856, },
+       { .centigrade = -15,    .adc = 1799, },
+       { .centigrade = -10,    .adc = 1730, },
+       { .centigrade = -5,     .adc = 1649, },
+       { .centigrade = 0,      .adc = 1556, },
+       { .centigrade = 5,      .adc = 1454, },
+       { .centigrade = 10,     .adc = 1343, },
+       { .centigrade = 15,     .adc = 1227, },
+       { .centigrade = 20,     .adc = 1109, },
+       { .centigrade = 25,     .adc = 992, },
+       { .centigrade = 30,     .adc = 880, },
+       { .centigrade = 35,     .adc = 773, },
+       { .centigrade = 40,     .adc = 675, },
+       { .centigrade = 45,     .adc = 586, },
+       { .centigrade = 50,     .adc = 507, },
+       { .centigrade = 55,     .adc = 436, },
+       { .centigrade = 58,     .adc = 399, },
+       { .centigrade = 63,     .adc = 343, },
+       { .centigrade = 65,     .adc = 322, },
+};
+
+#ifndef USHRT_MAX
+#define USHRT_MAX      0xFFFFU
+#endif
+static int adc_to_temperature_centigrade(unsigned short adc)
+{
+       int i;
+       int approximation;
+       /* low_*: Greatest Lower Bound,
+        *          *          *          * high_*: Smallest Upper Bound */
+       int low_temp = 0, high_temp = 0;
+       unsigned short low_adc = 0, high_adc = USHRT_MAX;
+       for (i = 0; i < ARRAY_SIZE(adc_to_temperature_data); i++) {
+               if (adc_to_temperature_data[i].adc <= adc &&
+                               adc_to_temperature_data[i].adc >= low_adc) {
+                       low_temp = adc_to_temperature_data[i].centigrade;
+                       low_adc = adc_to_temperature_data[i].adc;
+               }
+               if (adc_to_temperature_data[i].adc >= adc &&
+                               adc_to_temperature_data[i].adc <= high_adc) {
+                       high_temp = adc_to_temperature_data[i].centigrade;
+                       high_adc = adc_to_temperature_data[i].adc;
+               }
+       }
+
+       /* Linear approximation between cloest low and high,
+        * which is the weighted average of the two. */
+
+       /* The following equation is correct only when the two are different */
+       if (low_adc == high_adc)
+               return low_temp;
+       if (ARRAY_SIZE(adc_to_temperature_data) < 2)
+               return 20; /* The room temperature */
+       if (low_adc == 0)
+               return high_temp;
+       if (high_adc == USHRT_MAX)
+               return low_temp;
+
+       approximation = low_temp * (adc - low_adc) +
+               high_temp * (high_adc - adc);
+       approximation /= high_adc - low_adc;
+
+       return approximation;
+}
+
+static unsigned short get_adc_value(int channel)
+{
+       struct s5pc110_adc *adc = (struct s5pc110_adc *) S5PC110_ADC_BASE;
+       unsigned short ret = 0;
+       unsigned int reg;
+       int ldonum = 8;
+       char buf[64];
+       unsigned int loop = 0;
+
+       if (mach_is_kessler())
+               ldonum = 4;
+       else if (mach_is_geminus())
+               ldonum = 4;
+       else if (mach_is_wmg160())
+               ldonum = 4;
+       else if (mach_is_cypress())
+               ldonum = 8;
+       else if (mach_is_tickertape())
+               ldonum = 8;
+       else if (mach_is_aquila())
+               ldonum = 8;
+       /*
+       else if (mach_is_p1p2())
+               ldonum = 4;
+       */
+
+       sprintf(buf, "pmic ldo %d on", ldonum);
+       run_command(buf, 0);
+
+       writel(channel & 0xF, &adc->adcmux);
+       writel((1 << 14) | (49 << 6), &adc->adccon);
+       writel(1000 & 0xffff, &adc->adcdly);
+       writel(readl(&adc->adccon) | (1 << 16), &adc->adccon); /* 12 bit */
+       udelay(10);
+       writel(readl(&adc->adccon) | (1 << 0), &adc->adccon); /* Enable */
+       udelay(10);
+
+       do {
+               udelay(1);
+               reg = readl(&adc->adccon);
+       } while (!(reg & (1 << 15)) && (loop++ < 1000));
+
+       ret = readl(&adc->adcdat0) & 0xFFF;
+       sprintf(buf, "pmic ldo %d off", ldonum);
+       run_command(buf, 0);
+
+       return ret;
+}
+
+static int adc_get_average_ambient_temperature(void)
+{
+       if (mach_is_kessler()) {
+               unsigned short min = USHRT_MAX;
+               unsigned short max = 0;
+               unsigned int sum = 0;
+               unsigned int measured = 0;
+               int i;
+
+               for (i = 0; i < 7; i++) {
+                       unsigned short measurement = get_adc_value(6);
+                       sum += measurement;
+                       measured++;
+                       if (min > measurement)
+                               min = measurement;
+                       if (max < measurement)
+                               max = measurement;
+               }
+               if (measured >= 3) {
+                       measured -= 2;
+                       sum -= min;
+                       sum -= max;
+               }
+               sum /= measured;
+               printf("Average Ambient Temperature = %d(ADC=%d)\n",
+                               adc_to_temperature_centigrade(sum), sum);
+               return adc_to_temperature_centigrade(sum);
+       }
+
+       return 20; /* 20 Centigrade */
+}
+
+enum temperature_level {
+       _TEMP_OK,
+       _TEMP_OK_HIGH,
+       _TEMP_OK_LOW,
+       _TEMP_TOO_HIGH,
+       _TEMP_TOO_LOW,
+};
+
+static enum temperature_level temperature_check(void)
+{
+       int temp = adc_get_average_ambient_temperature();
+       if (temp < -5)
+               return _TEMP_TOO_LOW;
+       if (temp < 0)
+               return _TEMP_OK_LOW;
+       if (temp > 63)
+               return _TEMP_TOO_HIGH;
+       if (temp > 58)
+               return _TEMP_OK_HIGH;
+       return _TEMP_OK;
+}
+
 extern void lcd_display_clear(void);
 extern int lcd_display_bitmap(ulong bmp_image, int x, int y);
 
-static void into_charge_mode(void)
+static void charger_en(int enable)
 {
-       unsigned char addr = 0xCC >> 1; /* max8998 */;
+       /* 0: disable
+        * 600: 600mA
+        * 475: 475mA
+        */
+       unsigned char addr = 0xCC >> 1; /* max8998 */
        unsigned char val[2];
+
+       if (max8998_probe())
+               return;
+
+       if (!enable) {
+               puts("Disable the charger.\n");
+               i2c_read(addr, 0x0D, 1, val, 1);
+               val[0] &= ~(0x1);
+               val[0] |= 0x1;
+               i2c_write(addr, 0x0D, 1, val, 1);
+       } else {
+               i2c_read(addr, 0x0C, 1, val, 1);
+               val[0] &= ~(0x7 << 0);
+               val[0] &= ~(0x7 << 5);
+               if (enable == 600) {
+                       val[0] |= 5; /* 600mA */
+                       val[0] |= (3 << 5); /* Stop at 150mA (25%) */
+               } else { /* Assume 475 mA */
+                       enable = 475;
+                       val[0] |= 2; /* 475mA */
+                       val[0] |= (4 << 5); /* Stop at 142.5mA (30%) */
+               }
+               i2c_write(addr, 0x0C, 1, val, 1);
+
+               i2c_read(addr, 0x0D, 1, val, 1);
+               val[0] &= ~(0x1);
+               i2c_write(addr, 0x0D, 1, val, 1);
+               printf("Enable the charger @ %dmA\n", enable);
+       }
+}
+
+void lcd_power_on(unsigned int onoff);
+extern int do_sleep (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+extern int drv_lcd_init_resume (void);
+
+static void into_charge_mode(void)
+{
        unsigned int level;
        int i, j;
        bmp_image_t *bmp;
        unsigned long len;
        ulong bmp_addr[CHARGER_ANIMATION_FRAME];
+       unsigned int reg, wakeup_stat;
+       int charger_speed = 600;
 
-       i2c_set_bus_num(I2C_PMIC);
+       max8998_clear_interrupt();
 
-       if (i2c_probe(addr)) {
-               printf("Can't found max8998\n");
-               return;
-       }
-
-       printf("Charge Mode\n");
-
-       i2c_read(addr, 0x0C, 1, val, 1);
-       val[0] &= ~(0x7 << 0);
-       val[0] |= 5;            /* 600mA */
-       i2c_write(addr, 0x0C, 1, val, 1);
+       puts("Charge Mode\n");
+       charger_en(charger_speed);
 
 #ifdef CONFIG_S5PC1XXFB
        init_font();
@@ -1035,95 +1325,233 @@ static void into_charge_mode(void)
                        int k;
 
                        bmp = gunzip_bmp(bmp_addr[j], &len);
-                       lcd_display_bitmap((ulong) bmp, 140, 202);
+                       lcd_display_bitmap((ulong)bmp, 140, 202);
                        free(bmp);
 
-                       for (k = 0; k < 10; k++)
+                       for (k = 0; k < 10; k++) {
                                if (max8998_power_key()) {
                                        lcd_display_clear();
-                                       /* FIXME don't use static function */
-                                       /* draw_samsung_logo(lcd_base); */
-                                       return;
-                               } else
+                                       goto restore_screen;
+                               } else if (!max8998_has_ext_power_source()) {
+                                       lcd_display_clear();
+                                       goto restore_screen;
+                               } else {
                                        udelay(100 * 1000);
+                               }
+                       }
                }
        }
        exit_font();
+
+       /* Disable the display to prevent flickering */
+       /* TODO: how to reenable the display later? */
+       lcd_power_on(0);
 #endif
 
-       /* EVT0: sleep 1, EVT1: sleep */
-       if (s5pc1xx_get_cpu_rev() == 0) {
-               run_command("sleep 1", 0);
-               return;
-       }
+       do {
+               struct s5pc110_rtc *rtc = (struct s5pc110_rtc *)S5PC110_RTC_BASE;
+               unsigned int org, org_ip3;
+               enum temperature_level  previous_state = _TEMP_OK;
+
+               empty_device_info_buffer();
+               if (max8998_power_key())
+                       break;
+               else if (!max8998_has_ext_power_source())
+                       break;
+
+               /* Enable RTC, SYSTIMER, ADC at CLKGATE IP3 */
+               org_ip3 = readl(0xE010046C);
+               writel(org_ip3 | (1 << 15) | (1 << 16) | (1 << 24), 0xE010046C);
+
+               reg = org = readl(&rtc->rtccon);
+               reg |= (1 << 0);
+               writel(reg, &rtc->rtccon);
+
+               reg = readl(&rtc->rtccon);
+               writel(reg | (1 << 3), &rtc->rtccon);
+               udelay(10);
+               writel(reg & ~(1 << 3), &rtc->rtccon);
+               udelay(10);
+
+               reg = readl(&rtc->rtccon);
+               reg &= ~((1 << 8) | (0xF << 4));
+               reg |= (1 << 8) | (0xD << 4); /* D: 4 Hz, 9: 64 Hz */
+               writel(reg, &rtc->rtccon);
+
+               reg = 15 * 4 - 1; /* 15 sec */
+               writel(reg, &rtc->ticcnt);
+
+               /* EVT0: sleep 1, EVT1: sleep */
+               if (cpu_is_s5pc110()) {
+                       char *name = "dummy";
+                       char *usage = "N/A";
+                       char *help = NULL;
+                       cmd_tbl_t ctt;
+                       ctt.name = name;
+                       ctt.usage = usage;
+                       ctt.help = help;
+
+                       if (s5pc1xx_get_cpu_rev() == 0) {
+                               char *argv[] = {"1", "1"};
+                               wakeup_stat = do_sleep(&ctt, 0, 2, argv);
+                       } else {
+                               char *argv[] = {"0", "0"};
+                               wakeup_stat = do_sleep(&ctt, 0, 1, argv);
+                       }
+               } else {
+                       puts("\n\n\nERROR: this is not S5PC110.\n\n\n");
+                       return;
+               }
+
+               /* Check TEMP HIGH/LOW */
+               switch (temperature_check()) {
+               case _TEMP_OK:
+                       charger_en(charger_speed);
+                       previous_state = _TEMP_OK;
+                       break;
+               case _TEMP_TOO_LOW:
+                       charger_en(0);
+                       previous_state = _TEMP_TOO_LOW;
+                       break;
+               case _TEMP_TOO_HIGH:
+                       charger_en(0);
+                       previous_state = _TEMP_TOO_HIGH;
+                       break;
+               case _TEMP_OK_LOW:
+                       if (previous_state == _TEMP_TOO_LOW) {
+                               charger_en(0);
+                       } else {
+                               charger_en(charger_speed);
+                               previous_state = _TEMP_OK;
+                       }
+                       break;
+               case _TEMP_OK_HIGH:
+                       if (previous_state == _TEMP_TOO_HIGH) {
+                               charger_en(0);
+                       } else {
+                               charger_en(charger_speed);
+                               previous_state = _TEMP_OK;
+                       }
+                       break;
+               }
+
+               writel(org, &rtc->rtccon);
+               writel(org_ip3, 0xE010046C);
+
+       } while (wakeup_stat == 0x04); /* RTC TICK */
 
-       run_command("sleep", 0);
+#ifdef CONFIG_S5PC1XXFB
+restore_screen:
+       /* TODO: Reenable logo display (not working yet) */
+       lcd_power_on(1);
+       drv_lcd_init_resume();
+#endif
 }
 
-static void check_micro_usb(int intr)
+#define S5PC110_RST_STAT       0xE010A000
+
+#define SWRESET                        (1 << 3)
+#define WDTRESET               (1 << 2)
+#define WARMRESET              (1 << 1)
+#define EXTRESET               (1 << 0)
+
+static int get_reset_status(void)
 {
-       unsigned char addr;
-       unsigned char val[2];
-       static int started_charging_once = 0;
-       char *path;
+       return readl(S5PC110_RST_STAT) & 0xf;
+}
+
+static int fsa9480_probe(void)
+{
+       unsigned char addr = 0x25;
 
        if (cpu_is_s5pc100())
-               return;
+               return 1;
 
        if (board_is_limo_real()) {
                if (hwrevision(0) || hwrevision(1))
-                       return;
+                       return 1;
        }
 
        i2c_set_bus_num(I2C_PMIC);
 
-       if (machine_is_aquila()) {
-               if (board_is_aries() || board_is_neptune())
-                       i2c_set_bus_num(I2C_GPIO6);
-       } else if (machine_is_cypress()) {
+       if (mach_is_kessler()) {
+               i2c_set_bus_num(I2C_GPIO6);
+       } else if (mach_is_cypress()) {
                i2c_set_bus_num(I2C_GPIO6);
-       } else if (machine_is_geminus()) {
+       } else if (mach_is_geminus()) {
                if (hwrevision(1))
                        i2c_set_bus_num(I2C_GPIO6);
-       } else if (machine_is_wmg160())
+       } else if (mach_is_wmg160()) {
                i2c_set_bus_num(I2C_GPIO6);
+       }
 
-       addr = 0x25;            /* fsa9480 */
        if (i2c_probe(addr)) {
-               printf("Can't found fsa9480\n");
-               return;
+               puts("Can't found fsa9480\n");
+               return 1;
        }
 
+       return 0;
+}
+
+static void check_micro_usb(int intr)
+{
+       unsigned char addr;
+       unsigned char val[2];
+       static int started_charging_once = 0;
+       char *path;
+
+       if (fsa9480_probe())
+               return;
+
+       addr = 0x25;            /* fsa9480 */
+
        /* Clear Interrupt */
        if (intr) {
                i2c_read(addr, 0x03, 1, val, 2);
-               udelay(500 * 1000);
+               return;
        }
 
        /* Read Device Type 1 */
        i2c_read(addr, 0x0a, 1, val, 1);
 
-#define FSA_DEDICATED_CHARGER  (1 << 6)
-#define FSA_UART               (1 << 3)
-#define FSA_USB                        (1 << 2)
+#define FSA_DEV1_CHARGER       (1 << 6)
+#define FSA_DEV1_UART          (1 << 3)
+#define FSA_DEV1_USB           (1 << 2)
+#define FSA_DEV2_JIG_USB_OFF   (1 << 1)
+#define FSA_DEV2_JIG_USB_ON    (1 << 0)
 
        /*
         * If USB, use default 475mA
         * If Charger, use 600mA and go to charge mode
         */
-       if ((val[0] & FSA_DEDICATED_CHARGER) && !started_charging_once) {
+       if ((val[0] & FSA_DEV1_CHARGER) && !started_charging_once) {
                started_charging_once = 1;
-               into_charge_mode();
+
+               /* If it's full, do not charge. */
+               if (battery_soc < 100)
+                       into_charge_mode();
+               else
+                       charger_en(0);
+       } else if (val[0] & FSA_DEV1_USB) {
+               if (battery_soc < 100)
+                       charger_en(475); /* enable charger and keep booting */
+               else
+                       charger_en(0);
        }
 
-       /* If Factory Mode is Boot ON-USB, go to download mode */
-       i2c_read(addr, 0x07, 1, val, 1);
+       /* If reset status is watchdog reset then skip it */
+       if (!(get_reset_status() & WDTRESET)) {
+               /* If Factory Mode is Boot ON-USB, go to download mode */
+               i2c_read(addr, 0x07, 1, val, 1);
 
-#define FSA_ADC_FAC_USB                0x19
+#define FSA_ADC_FAC_USB_OFF    0x18
+#define FSA_ADC_FAC_USB_ON     0x19
 #define FSA_ADC_FAC_UART       0x1d
 
-       if (val[0] == FSA_ADC_FAC_USB)
-               setenv("bootcmd", "usbdown");
+               if (val[0] == FSA_ADC_FAC_USB_ON ||
+                       val[0] == FSA_ADC_FAC_USB_OFF)
+                       setenv("bootcmd", "usbdown");
+       }
 
        path = getenv("usb");
 
@@ -1136,26 +1564,10 @@ static void micro_usb_switch(int path)
        unsigned char addr;
        unsigned char val[2];
 
-       i2c_set_bus_num(I2C_PMIC);
-
-       if (machine_is_aquila()) {
-               if (board_is_aries() || board_is_neptune())
-                       i2c_set_bus_num(I2C_GPIO6);
-       } else if (machine_is_cypress()) {
-               i2c_set_bus_num(I2C_GPIO6);
-       } else if (machine_is_geminus()) {
-               if (hwrevision(1))
-                       i2c_set_bus_num(I2C_GPIO6);
-       } else if (machine_is_wmg160()) {
-               i2c_set_bus_num(I2C_GPIO6);
+       if (fsa9480_probe())
                return;
-       }
 
        addr = 0x25;            /* fsa9480 */
-       if (i2c_probe(addr)) {
-               printf("Can't found fsa9480\n");
-               return;
-       }
 
        if (path)
                val[0] = 0x90;  /* VAUDIO */
@@ -1200,15 +1612,9 @@ static void init_pmic(void)
        if (cpu_is_s5pc100())
                return;
 
-       i2c_set_bus_num(I2C_PMIC);
-
        addr = 0xCC >> 1;       /* max8998 */
-       if (i2c_probe(addr)) {
-               if (i2c_probe(addr)) {
-                       printf("Can't found max8998\n");
-                       return;
-               }
-       }
+       if (max8998_probe())
+               return;
 
        /* ONOFF1 */
        i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
@@ -1224,7 +1630,7 @@ static void init_pmic(void)
        val[0] &= ~(MAX8998_LDO10 | MAX8998_LDO11 |
                        MAX8998_LDO12 | MAX8998_LDO13);
 
-       if (board_is_aries() || board_is_neptune())
+       if (mach_is_kessler())
                val[0] |= MAX8998_LDO7;         /* LDO7: VLCD_1.8V */
 
        i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
@@ -1238,7 +1644,7 @@ static void init_pmic(void)
        val[0] &= ~(MAX8998_LDO14 | MAX8998_LDO15 |
                        MAX8998_LDO16 | MAX8998_LDO17);
 
-       if (board_is_aries() || board_is_neptune())
+       if (mach_is_kessler())
                val[0] |= MAX8998_LDO17;        /* LDO17: VCC_3.0V_LCD */
 
        i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
@@ -1260,47 +1666,46 @@ static void setup_power_down_mode_registers(void)
        if (cpu_is_s5pc100())
                return;
 
-       /* Only Limo real and aries supports worked for sleep currnet */
-       if (machine_is_aquila()) {
+       /* Only Limo real and kessler supports worked for sleep currnet */
+       if (mach_is_aquila()) {
                if (board_is_limo_real())
                        /* Support */;
-               else if (board_is_aries() || board_is_neptune())
-                       /* Support */;
                else
                        return;
-       } else if (machine_is_geminus()) {
+       } else if (mach_is_kessler()) {
                /* Support */;
-       } else
+       } else if (mach_is_geminus()) {
+               /* Support */;
+       } else {
                return;
+       }
 
-       if (machine_is_aquila()) {
-               if (board_is_aries() || board_is_neptune()) {
-                       /* Aquila rev 0.9 */
-                       p = aries_powerdown_modes;
-                       ge = aries_external_powerdown_modes;
-                       mr = aries_mirror_powerdown_mode;
-                       n_p = ARRAY_SIZE(aries_powerdown_modes);
-                       n_ge = ARRAY_SIZE(aries_external_powerdown_modes);
-                       n_mr = ARRAY_SIZE(aries_mirror_powerdown_mode);
-               } else {
-                       /* Aquila rev 0.8 or lower */
-                       p = aquila_powerdown_modes;
-                       ge = aquila_external_powerdown_modes;
-                       mr = aquila_mirror_powerdown_mode;
-                       n_p = ARRAY_SIZE(aquila_powerdown_modes);
-                       n_ge = ARRAY_SIZE(aquila_external_powerdown_modes);
-                       n_mr = ARRAY_SIZE(aquila_mirror_powerdown_mode);
-               }
-       } else if (machine_is_geminus()) {
+       if (mach_is_aquila()) {
+               /* Aquila rev 0.8 or lower */
+               p = aquila_powerdown_modes;
+               ge = aquila_external_powerdown_modes;
+               mr = aquila_mirror_powerdown_mode;
+               n_p = ARRAY_SIZE(aquila_powerdown_modes);
+               n_ge = ARRAY_SIZE(aquila_external_powerdown_modes);
+               n_mr = ARRAY_SIZE(aquila_mirror_powerdown_mode);
+       } else if (mach_is_kessler()) {
+               /* Aquila rev 0.9 */
+               p = kessler_powerdown_modes;
+               ge = kessler_external_powerdown_modes;
+               mr = kessler_mirror_powerdown_mode;
+               n_p = ARRAY_SIZE(kessler_powerdown_modes);
+               n_ge = ARRAY_SIZE(kessler_external_powerdown_modes);
+               n_mr = ARRAY_SIZE(kessler_mirror_powerdown_mode);
+       } else if (mach_is_geminus()) {
                if (hwrevision(1)) {
                        /* Same as Aquila rev 0.9 */
 #if 0
-                       p = aries_powerdown_modes;
-                       ge = aries_external_powerdown_modes;
-                       mr = aries_mirror_powerdown_mode;
-                       n_p = ARRAY_SIZE(aries_powerdown_modes);
-                       n_ge = ARRAY_SIZE(aries_external_powerdown_modes);
-                       n_mr = ARRAY_SIZE(aries_mirror_powerdown_mode);
+                       p = kessler_powerdown_modes;
+                       ge = kessler_external_powerdown_modes;
+                       mr = kessler_mirror_powerdown_mode;
+                       n_p = ARRAY_SIZE(kessler_powerdown_modes);
+                       n_ge = ARRAY_SIZE(kessler_external_powerdown_modes);
+                       n_mr = ARRAY_SIZE(kessler_mirror_powerdown_mode);
 #else
                        p = aquila_powerdown_modes;
                        ge = aquila_external_powerdown_modes;
@@ -1345,31 +1750,16 @@ static void setup_power_down_mode_registers(void)
 
        for (i = 0; i < n_mr; i++) {
                unsigned int reg = readl(&mr->bank->pdn_con);
-               reg &= ~(1 << mr->number);
+               reg &= ~(0x3 << (mr->number << 1));
                if (readl(&mr->bank->dat) & (1 << mr->number))
-                       reg |= 1 << mr->number;
+                       reg |= 0x1 << (mr->number << 1);
                writel(reg, &mr->bank->pdn_con);
-
-               printf("[%8.8X] = %8.8X\n", (unsigned int) (&mr->bank->pdn_con), reg);
-
                mr++;
        }
 }
 
 #ifdef CONFIG_LCD
-struct spi_platform_data {
-       struct s5pc1xx_gpio_bank *cs_bank;
-       struct s5pc1xx_gpio_bank *clk_bank;
-       struct s5pc1xx_gpio_bank *si_bank;
-       struct s5pc1xx_gpio_bank *so_bank;
-
-       unsigned int cs_num;
-       unsigned int clk_num;
-       unsigned int si_num;
-       unsigned int so_num;
-
-       unsigned int board_is_media;
-};
+#include "../../../drivers/video/s5p-spi.h"
 
 extern void s6e63m0_set_platform_data(struct spi_platform_data *pd);
 extern void s6d16a0x_set_platform_data(struct spi_platform_data *pd);
@@ -1393,11 +1783,11 @@ void lcd_cfg_gpio(void)
                gpio_set_pull(&gpio_base->gpio_f2, i, GPIO_PULL_NONE);
 
                /* drive strength to max (24bit) */
-               gpio_set_drv(&gpio_base->gpio_f0, i, GPIO_DRV_4x);
+               gpio_set_drv(&gpio_base->gpio_f0, i, GPIO_DRV_4X);
                gpio_set_rate(&gpio_base->gpio_f0, i, GPIO_DRV_SLOW);
-               gpio_set_drv(&gpio_base->gpio_f1, i, GPIO_DRV_4x);
+               gpio_set_drv(&gpio_base->gpio_f1, i, GPIO_DRV_4X);
                gpio_set_rate(&gpio_base->gpio_f1, i, GPIO_DRV_SLOW);
-               gpio_set_drv(&gpio_base->gpio_f2, i, GPIO_DRV_4x);
+               gpio_set_drv(&gpio_base->gpio_f2, i, GPIO_DRV_4X);
                gpio_set_rate(&gpio_base->gpio_f2, i, GPIO_DRV_SLOW);
        }
 
@@ -1411,7 +1801,7 @@ void lcd_cfg_gpio(void)
                /* pull-up/down disable */
                gpio_set_pull(&gpio_base->gpio_f3, i, GPIO_PULL_NONE);
                /* drive strength to max (24bit) */
-               gpio_set_drv(&gpio_base->gpio_f3, i, GPIO_DRV_4x);
+               gpio_set_drv(&gpio_base->gpio_f3, i, GPIO_DRV_4X);
                gpio_set_rate(&gpio_base->gpio_f3, i, GPIO_DRV_SLOW);
        }
        /* display output path selection (only [1:0] valid) */
@@ -1424,8 +1814,12 @@ void lcd_cfg_gpio(void)
        gpio_cfg_pin(&gpio_base->gpio_j1, 3, GPIO_OUTPUT);
 
        /* LCD_BACKLIGHT_EN */
-       if (machine_is_geminus())
+       if (mach_is_geminus())
                gpio_cfg_pin(&gpio_base->gpio_mp0_5, 0, GPIO_OUTPUT);
+       if (board_is_neptune() && hwrevision(0)) {
+               gpio_cfg_pin(&gpio_base->gpio_mp0_4, 4, GPIO_OUTPUT);
+               gpio_direction_output(&gpio_base->gpio_mp0_4, 4, 0);
+       }
 
        /*
         * gpio pad configuration for
@@ -1436,7 +1830,7 @@ void lcd_cfg_gpio(void)
        gpio_cfg_pin(&gpio_base->gpio_mp0_4, 2, GPIO_INPUT);
        gpio_cfg_pin(&gpio_base->gpio_mp0_4, 3, GPIO_OUTPUT);
 
-       if (machine_is_aquila()) {
+       if (mach_is_aquila() || mach_is_kessler()) {
                spi_pd.cs_bank = &gpio_base->gpio_mp0_1;
                spi_pd.cs_num = 1;
                spi_pd.clk_bank = &gpio_base->gpio_mp0_4;
@@ -1446,16 +1840,16 @@ void lcd_cfg_gpio(void)
                spi_pd.so_bank = &gpio_base->gpio_mp0_4;
                spi_pd.so_num = 2;
 
-               if (board_is_neptune())
+               if (board_is_neptune() && hwrevision(0))
                        s6d16a0x_set_platform_data(&spi_pd);
                else {
                        s6e63m0_set_platform_data(&spi_pd);
                        if (board_is_media())
-                               spi_pd.board_is_media = 1;
+                               spi_pd.set_rev = 1;
                }
        }
 
-       if (machine_is_cypress()) {
+       if (mach_is_cypress()) {
 #if 0          /* universal cypress */
                /* FLCD_CS */
                gpio_cfg_pin(&gpio_base->gpio_mp0_1, 0, GPIO_OUTPUT);
@@ -1481,6 +1875,8 @@ void lcd_cfg_gpio(void)
                spi_pd.si_bank = &gpio_base->gpio_mp0_4;
                spi_pd.si_num = 2;
 
+               spi_pd.set_rev = 1;
+
                /* these data would be sent to s6e63m0 lcd panel driver. */
                s6e63m0_set_platform_data(&spi_pd);
        }
@@ -1488,26 +1884,63 @@ void lcd_cfg_gpio(void)
        return;
 }
 
+#define SWRST_REG              0x00
+#define LEDCON_REG             0x01
+#define LED_CUR_SET_REG                0x03
+#define LED_CUR_TR_REG         0x08
+
+#define SWRST                  0x01
+#define NORMAL_MODE            0x09
+#define CUR_SET                        0x63
+#define TR_SET                 0x00
 void backlight_on(unsigned int onoff)
 {
+
+       unsigned char addr;
+       unsigned char val[2];
        struct s5pc110_gpio *gpio = (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
 
        if (onoff) {
-               if (machine_is_geminus())
+               if (mach_is_geminus())
                        gpio_set_value(&gpio->gpio_mp0_5, 0, 1);
        } else {
-               if (machine_is_geminus())
+               if (mach_is_geminus())
                        gpio_set_value(&gpio->gpio_mp0_5, 0, 0);
        }
+
+       if (mach_is_kessler() && board_is_neptune() && hwrevision(0)) {
+               gpio_set_value(&gpio->gpio_mp0_4, 4, 1);
+               udelay(6);
+
+               i2c_set_bus_num(I2C_GPIO5);
+
+               addr = 0x76;
+               if (i2c_probe(addr)) {
+                       if (i2c_probe(addr)) {
+                               puts("Can't found s6d16a0x backlight i2c\n");
+                               return;
+                       }
+               }
+               val[0] = SWRST;
+               i2c_write(addr, SWRST_REG, 1, val, 1);
+               /* NORMAL MODE */
+               val[0] = CUR_SET;
+               i2c_write(addr, LED_CUR_SET_REG, 1, val, 1);
+               val[0] = TR_SET;
+               i2c_write(addr, LED_CUR_TR_REG, 1, val, 1);
+               val[0] = NORMAL_MODE;
+               i2c_write(addr, LEDCON_REG, 1, val, 1);
+               udelay(5000);
+       }
 }
 
 void reset_lcd(void)
 {
        struct s5pc110_gpio *gpio = (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
 
-       if (machine_is_aquila() || machine_is_geminus())
+       if (mach_is_aquila() || mach_is_kessler() || mach_is_geminus())
                gpio_set_value(&gpio->gpio_mp0_5, 5, 1);
-       if (machine_is_cypress())
+       if (mach_is_cypress())
                gpio_set_value(&gpio->gpio_mp0_4, 5, 1);
 }
 
@@ -1516,26 +1949,26 @@ void lcd_power_on(unsigned int onoff)
        struct s5pc110_gpio *gpio = (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
        if (onoff) {
                /* TSP_LDO_ON */
-               if (machine_is_aquila() || machine_is_geminus())
+               if (mach_is_aquila() || mach_is_geminus())
                        gpio_set_value(&gpio->gpio_j1, 3, 1);
 
-               if (machine_is_cypress())
+               if (mach_is_cypress())
                        gpio_set_value(&gpio->gpio_g2, 2, 1);
 
-               if (board_is_aries() || board_is_neptune()) {
+               if (mach_is_kessler()) {
                        unsigned char addr;
                        unsigned char val[2];
                        unsigned char val2[2];
 
-                       i2c_set_bus_num(I2C_PMIC);
+                       gpio_set_value(&gpio->gpio_j1, 3, 1);
+
                        addr = 0xCC >> 1;       /* max8998 */
-                       if (i2c_probe(addr)) {
-                               printf("Can't found max8998\n");
+                       if (max8998_probe())
                                return;
-                       }
+
                        i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
                        val[0] &= ~(MAX8998_LDO17);
-                       val[0] |= MAX8998_LDO17;        /* LDO17: VCC_3.0V_LCD */
+                       val[0] |= MAX8998_LDO17; /* LDO17: VCC_3.0V_LCD */
                        i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
 
                        i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
@@ -1551,30 +1984,29 @@ void lcd_power_on(unsigned int onoff)
                        i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
                }
        } else {
-               if (machine_is_aquila() || machine_is_geminus())
+               if (mach_is_aquila() || mach_is_geminus())
                        gpio_set_value(&gpio->gpio_j1, 3, 0);
 
-               if (machine_is_cypress())
+               if (mach_is_cypress())
                        gpio_set_value(&gpio->gpio_g2, 2, 0);
 
-               if (board_is_aries() || board_is_neptune()) {
+               if (mach_is_kessler()) {
                        unsigned char addr;
                        unsigned char val[2];
 
-                       i2c_set_bus_num(I2C_PMIC);
+                       gpio_set_value(&gpio->gpio_j1, 3, 0);
+
                        addr = 0xCC >> 1;       /* max8998 */
-                       if (i2c_probe(addr)) {
-                               printf("Can't found max8998\n");
+                       if (max8998_probe())
                                return;
-                       }
 
                        i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
-                       val[0] &= ~(1 << 7);
+                       val[0] &= ~(MAX8998_LDO7);
                        i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
                        i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
 
                        i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
-                       val[0] &= ~MAX8998_LDO17;
+                       val[0] &= ~(MAX8998_LDO17);
                        i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
                        i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
                }
@@ -1588,7 +2020,7 @@ extern void s6d16a0x_enable_ldo(unsigned int onoff);
 
 int s5p_no_lcd_support(void)
 {
-       if (machine_is_wmg160())
+       if (mach_is_wmg160())
                return 1;
        return 0;
 }
@@ -1640,7 +2072,8 @@ void init_panel_info(vidinfo_t *vid)
        vid->vl_vbpd    = 3;
        vid->vl_vfpd    = 28;
 
-       if (machine_is_aquila() || machine_is_cypress()) {
+       if (mach_is_aquila() || mach_is_kessler()
+                       || mach_is_cypress()) {
                vid->cfg_gpio = lcd_cfg_gpio;
                vid->reset_lcd = reset_lcd;
                vid->backlight_on = backlight_on;
@@ -1652,7 +2085,7 @@ void init_panel_info(vidinfo_t *vid)
                vid->reset_delay = 120000;
        }
 
-       if (board_is_neptune()) {
+       if (board_is_neptune() && hwrevision(0)) {
                vid->vl_freq    = 100;
                vid->vl_col     = 320;
                vid->vl_row     = 480;
@@ -1678,7 +2111,7 @@ void init_panel_info(vidinfo_t *vid)
                vid->vl_vfpd    = 4;
 
                vid->cfg_gpio = lcd_cfg_gpio;
-               vid->backlight_on = NULL;
+               vid->backlight_on = backlight_on;
                vid->lcd_power_on = lcd_power_on;
                vid->reset_lcd = reset_lcd;
                vid->cfg_ldo = s6d16a0x_cfg_ldo;
@@ -1690,7 +2123,7 @@ void init_panel_info(vidinfo_t *vid)
 
        }
 
-       if (machine_is_geminus()) {
+       if (mach_is_geminus()) {
                vid->vl_freq    = 60;
                vid->vl_col     = 1024,
                vid->vl_row     = 600,
@@ -1783,52 +2216,24 @@ static void setup_meminfo(void)
        setenv("meminfo", meminfo);
 }
 
-/*
- * CSA partition Migration
- * It will be deleted
- */
-static void csa_migration(void)
-{
-       unsigned int *ubi_id;
-       int i;
-
-       run_command("onenand read 0x40000000 0x400000 0x400000", 0);
-
-       for (i = 0; i < 10; i++) {
-               ubi_id = (void *) (0x40000000 + 0x40000 * i);
-               if (*ubi_id == 0x23494255) /* 0x23494255 = UBI */ {
-                       printf("CSA Migration is already done....\n");
-                       return;
-               }
-       }
-       run_command("onenand erase 0x400000 0x800000", 0);
-}
-
 int misc_init_r(void)
 {
 #ifdef CONFIG_LCD
        /* It should be located at first */
        lcd_is_enabled = 0;
 
-       if (board_is_neptune())
-               setenv("lcdinfo", "lcd=s6d16a0x");
-       else if ((board_is_limo_real() ||
-               board_is_limo_universal() ||
-               board_is_j1b2()))
-               setenv("lcdinfo", "lcd=s6e63m0");
-       /* it can't classify tl2796 with single-lcd and dual-lcd.
-       else
-               setenv("lcdinfo", "lcd=tl2796-dual");
-       */
-
-       /*
-        * env values below should be added in case that lcd panel of geminus.
-        * setenv means that lcd panel has been turned on at u-boot.
-        */
-       if (machine_is_geminus())
+       if (mach_is_aquila() || mach_is_kessler()) {
+               if (board_is_neptune() && hwrevision(0))
+                       setenv("lcdinfo", "lcd=s6d16a0x");
+               else if (board_is_media())
+                       setenv("lcdinfo", "lcd=s6e63m0");
+               else
+                       setenv("lcdinfo", "lcd=s6e63m0");
+       }
+       if (mach_is_geminus())
                setenv("lcdinfo", "lcd=lms480jc01");
-       if (board_is_media())
-               setenv("lcdinfo", "lcd=media");
+       if (mach_is_cypress())
+               setenv("lcdinfo", "lcd=s6e63m0");
 #endif
        setup_meminfo();
 
@@ -1865,14 +2270,11 @@ int misc_init_r(void)
        setup_power_down_mode_registers();
 
        /* check max17040 */
-       check_battery();
+       check_battery(0);
 
        /* check fsa9480 */
        check_micro_usb(0);
 
-       /* csa migration (temporary) */
-       csa_migration();
-
        return 0;
 }
 #endif
@@ -1882,9 +2284,20 @@ int board_init(void)
        /* Set Initial global variables */
        s5pc110_gpio = (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
 
-       gd->bd->bi_arch_number = MACH_TYPE;
+       gd->bd->bi_arch_number = MACH_TYPE_AQUILA;
        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
 
+#ifdef CONFIG_LCD
+       /* 
+        * set reserved memory region for framebuffer.
+        *
+        * this region wouldn't be rewrited by kernel so
+        * could avoid nosie screen filled by garbages
+        * after hibernation resume has been completed.
+        */
+       gd->fb_base = CONFIG_FB_RESERVED_MEM;
+#endif
+
        /* Check H/W Revision */
        check_hw_revision();
 
@@ -1925,16 +2338,21 @@ int dram_init(void)
                 * Aquila Rev0.5 4G3G1G
                 * Aquila Rev0.8 4G3G1G
                 * Aquila Rev0.9 4G3G1G
+                * Neptune Rev 0.2 4G3G1G
                 */
-               if (machine_is_aquila() &&
-                   (hwrevision(5) || hwrevision(8) || hwrevision(9))) {
-                       memconfig1 = readl(base + MEMCONFIG1_OFFSET);
-
-                       sz = (memconfig1 >> 16) & 0xFF;
-                       sz = ((unsigned char) ~sz) + 1;
-                       sz = sz << 4;
+               if (mach_is_aquila() || mach_is_kessler()) {
+                       if ((!board_is_neptune() && (hwrevision(5) ||
+                               hwrevision(8) || hwrevision(9))) ||
+                               (board_is_neptune() && hwrevision(2))) {
+                               memconfig1 = readl(base + MEMCONFIG1_OFFSET);
+
+                               sz = (memconfig1 >> 16) & 0xFF;
+                               sz = ((unsigned char) ~sz) + 1;
+                               sz = sz << 4;
+                       }
+                       if (mach_is_kessler() && board_is_s1())
+                               sz = 0;
                }
-
        }
        /*
         * bi_dram[1].size contains all DMC1 memory size
@@ -1958,55 +2376,98 @@ void board_sleep_init_late(void)
        /* MHL off */
        gpio_direction_output(&s5pc110_gpio->gpio_j2, 2, 0);
        gpio_direction_output(&s5pc110_gpio->gpio_mp0_4, 7, 0);
-       gpio_direction_output(&s5pc110_gpio->gpio_j2, 3, 0); /* MHL_ON for REV02 or higher */
-
-
+       /* MHL_ON for REV02 or higher */
+       gpio_direction_output(&s5pc110_gpio->gpio_j2, 3, 0);
 }
+
 void board_sleep_init(void)
 {
        unsigned char addr;
        unsigned char val[2];
 
-       i2c_set_bus_num(I2C_PMIC);
        addr = 0xCC >> 1;
-       if (i2c_probe(addr)) {
-               printf("Can't find max8998\n");
+       if (max8998_probe())
                return;
-       }
 
-       /* Set ONOFF1 */
-       i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
-       saved_val[0][0] = val[0];
-       saved_val[0][1] = val[1];
-       val[0] &= ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) |
-                       (1 << 1) | (1 << 0));
-       i2c_write(addr, MAX8998_REG_ONOFF1, 1, val, 1);
-       i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
-       /* Set ONOFF2 */
-       i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
-       saved_val[1][0] = val[0];
-       saved_val[1][1] = val[1];
-       val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 3) |
-                       (1 << 2) | (1 << 1) | (1 << 0));
-       val[0] |= (1 << 7);
-       i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
-       i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
-       /* Set ONOFF3 */
-       i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
-       saved_val[2][0] = val[0];
-       saved_val[2][1] = val[1];
-       val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4));
-       i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
-       i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
-       /* Set ONOFF4 */
-       i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
-       saved_val[3][0] = val[0];
-       saved_val[3][1] = val[1];
-       val[0] &= ~((1 << 7) | (1 << 6) | (1 << 4));
-       i2c_write(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
-       i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
-       printf("Turned off regulators. Preparing to sleep. [%s:%d]\n",
-                       __FILE__, __LINE__);
+       if (mach_is_kessler()) {
+               /* Set ONOFF1 */
+               i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
+               saved_val[0][0] = val[0];
+               saved_val[0][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) |
+                               (1 << 1) | (1 << 0));
+               i2c_write(addr, MAX8998_REG_ONOFF1, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
+
+               /* Set ONOFF2 */
+               i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+               saved_val[1][0] = val[0];
+               saved_val[1][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 3) |
+                               (1 << 2) | (1 << 1) | (1 << 0));
+               val[0] |= (1 << 7);
+               i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+
+               /* Set ONOFF3 */
+               i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+               saved_val[2][0] = val[0];
+               saved_val[2][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4));
+               i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+
+               /* Set ONOFF4 */
+               i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
+               saved_val[3][0] = val[0];
+               saved_val[3][1] = val[1];
+               val[0] &= ~((1 << 6) | (1 << 4));
+               i2c_write(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
+
+               printf("Turned off regulators with Kessler setting."
+                              " Preparing to sleep. [%s:%d]\n",
+                               __FILE__, __LINE__);
+       } else { /* Default */
+               /* Set ONOFF1 */
+               i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
+               saved_val[0][0] = val[0];
+               saved_val[0][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) |
+                               (1 << 1) | (1 << 0));
+               i2c_write(addr, MAX8998_REG_ONOFF1, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF1, 1, val, 1);
+
+               /* Set ONOFF2 */
+               i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+               saved_val[1][0] = val[0];
+               saved_val[1][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 3) |
+                               (1 << 2) | (1 << 1) | (1 << 0));
+               val[0] |= (1 << 7);
+               i2c_write(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF2, 1, val, 1);
+
+               /* Set ONOFF3 */
+               i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+               saved_val[2][0] = val[0];
+               saved_val[2][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4));
+               i2c_write(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF3, 1, val, 1);
+
+               /* Set ONOFF4 */
+               i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
+               saved_val[3][0] = val[0];
+               saved_val[3][1] = val[1];
+               val[0] &= ~((1 << 7) | (1 << 6) | (1 << 4));
+               i2c_write(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
+               i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
+
+               printf("Turned off regulators with default(Aquila) setting."
+                              " Preparing to sleep. [%s:%d]\n",
+                               __FILE__, __LINE__);
+       }
 }
 
 void board_sleep_resume(void)
@@ -2016,12 +2477,9 @@ void board_sleep_resume(void)
 
        show_hw_revision();
 
-       i2c_set_bus_num(I2C_PMIC);
        addr = 0xCC >> 1;
-       if (i2c_probe(addr)) {
-               printf("Can't find max8998\n");
+       if (max8998_probe())
                return;
-       }
 
        /* Set ONOFF1 */
        i2c_write(addr, MAX8998_REG_ONOFF1, 1, saved_val[0], 1);
@@ -2035,14 +2493,71 @@ void board_sleep_resume(void)
        /* Set ONOFF4 */
        i2c_write(addr, MAX8998_REG_ONOFF3+1, 1, saved_val[3], 1);
        i2c_read(addr, MAX8998_REG_ONOFF3+1, 1, val, 1);
-       printf("Waked up.\n");
+       puts("Waked up.\n");
 
        /* check max17040 */
-       check_battery();
+       check_battery(0);
 
        /* check fsa9480 */
-       check_micro_usb(1);
+       check_micro_usb(0);
+}
+
+#if defined(CONFIG_USB_GADGET_S3C_UDC_OTG)
+
+static int s5pc1xx_phy_control(int on)
+{
+       static int status;
+
+       if (on && !status) {
+#ifdef CONFIG_CMD_PMIC
+               run_command("pmic ldo 3 on", 0);
+#endif
+               /* S5PC110 */
+               if (board_is_limo_universal() ||
+                       board_is_limo_real() ||
+                       board_is_media()) {
+                       /* check usb path */
+                       if (board_is_limo_real() && !hwrevision(6))
+                               check_mhl();
+               }
+
+               if (mach_is_tickertape())
+                       /* USB_SEL: XM0ADDR_0: MP04[0] output mode */
+                       gpio_direction_output(&s5pc110_gpio->gpio_mp0_4, 0, 0);
+
+               /* USB Path to AP */
+               micro_usb_switch(0);
+               status = 1;
+       } else if (!on && status) {
+#ifdef CONFIG_CMD_PMIC
+               run_command("pmic ldo 3 off", 0);
+#endif
+               status = 0;
+       }
+       udelay(10000);
+
+       return 0;
+}
+
+struct s3c_plat_otg_data s5pc110_otg_data = {
+       .phy_control = s5pc1xx_phy_control,
+       .regs_phy = S5PC110_PHY_BASE,
+       .regs_otg = S5PC110_OTG_BASE,
+};
+
+int board_eth_init(bd_t *bis)
+{
+       int res = -1;
+
+       if (cpu_is_s5pc100())
+               return -1;
+
+       s3c_udc_probe(&s5pc110_otg_data);
+       if (usb_eth_initialize(bis) >= 0)
+               res = 0;
+       return res;
 }
+#endif
 
 #ifdef CONFIG_CMD_USBDOWN
 int usb_board_init(void)
@@ -2057,7 +2572,7 @@ int usb_board_init(void)
 
                /* PMIC */
                if (i2c_read(0x66, 0, 1, val, 2)) {
-                       printf("i2c_read error\n");
+                       puts("i2c_read error\n");
                        return 1;
                }
 
@@ -2065,7 +2580,7 @@ int usb_board_init(void)
                val[1] |= (1 << 5);
 
                if (i2c_write(0x66, 0, 1, val, 2)) {
-                       printf("i2c_write error\n");
+                       puts("i2c_write error\n");
                        return 1;
                }
                i2c_read(0x66, 0, 1, val, 2);
@@ -2082,7 +2597,7 @@ int usb_board_init(void)
                        check_mhl();
        }
 
-       if (machine_is_tickertape())
+       if (mach_is_tickertape())
                /* USB_SEL: XM0ADDR_0: MP04[0] output mode */
                gpio_direction_output(&s5pc110_gpio->gpio_mp0_4, 0, 0);
 
@@ -2096,7 +2611,7 @@ int usb_board_init(void)
 #ifdef CONFIG_GENERIC_MMC
 int s5p_no_mmc_support(void)
 {
-       if (machine_is_wmg160())
+       if (mach_is_wmg160())
                return 1;
        return 0;
 }
@@ -2109,10 +2624,10 @@ int board_mmc_init(bd_t *bis)
        int i;
 
        /* MASSMEMORY_EN: XMSMDATA7: GPJ2[7] output high */
-       if (machine_is_aquila() && (board_is_aries() || board_is_neptune()))
+       if (mach_is_kessler())
                gpio_direction_output(&s5pc110_gpio->gpio_j2, 7, 1);
 
-       if (machine_is_wmg160())
+       if (mach_is_wmg160())
                return -1;
 
        /* MMC0 Clock source = SCLKMPLL */
@@ -2150,7 +2665,12 @@ int board_mmc_init(bd_t *bis)
                /* GPG0[0:6] pull disable */
                gpio_set_pull(&s5pc110_gpio->gpio_g0, i, GPIO_PULL_NONE);
                /* GPG0[0:6] drv 4x */
-               gpio_set_drv(&s5pc110_gpio->gpio_g0, i, GPIO_DRV_4x);
+               gpio_set_drv(&s5pc110_gpio->gpio_g0, i, GPIO_DRV_4X);
+       }
+
+       if (mach_is_geminus()) {
+               gpio_direction_output(&s5pc110_gpio->gpio_j2, 7, 1);
+               gpio_set_pull(&s5pc110_gpio->gpio_j2, 7, GPIO_PULL_NONE);
        }
 
        return s5pc1xx_mmc_init(0);
@@ -2163,12 +2683,10 @@ static int pmic_status(void)
        unsigned char addr, val[2];
        int reg, i;
 
-       i2c_set_bus_num(I2C_PMIC);
        addr = 0xCC >> 1;
-       if (i2c_probe(addr)) {
-               printf("Can't found max8998\n");
+
+       if (max8998_probe())
                return -1;
-       }
 
        reg = 0x11;
        i2c_read(addr, reg, 1, val, 1);
@@ -2229,12 +2747,10 @@ static int pmic_ldo_control(int buck, int ldo, int safeout, int on)
        } else
                return -1;
 
-       i2c_set_bus_num(I2C_PMIC);
        addr = 0xCC >> 1;
-       if (i2c_probe(addr)) {
-               printf("Can't found max8998\n");
+
+       if (max8998_probe())
                return -1;
-       }
 
        i2c_read(addr, reg, 1, val, 1);
        if (on)
@@ -2304,219 +2820,6 @@ U_BOOT_CMD(
 #endif
 
 #ifdef CONFIG_CMD_DEVICE_POWER
-
-enum {
-       POWER_NONE,
-       POWER_TOUCH,
-       POWER_3_TOUCHKEY,
-       POWER_LCD,
-       POWER_HAPTIC,
-       POWER_AUDIO_CODEC,
-       POWER_FM_RADIO,
-       POWER_BT_WIFI,
-       POWER_HDMI,
-};
-
-static void power_display_devices(void)
-{
-       printf("devices:\n");
-       printf("\t%d - touch\n", POWER_TOUCH);
-       printf("\t%d - 3 touchkey\n", POWER_3_TOUCHKEY);
-       printf("\t%d - LCD\n", POWER_LCD);
-       printf("\t%d - Haptic\n", POWER_HAPTIC);
-       printf("\t%d - Audio Codec\n", POWER_AUDIO_CODEC);
-       printf("\t%d - FM Radio\n", POWER_FM_RADIO);
-       printf("\t%d - BT/WiFi\n", POWER_BT_WIFI);
-       printf("\t%d - HDMI\n", POWER_HDMI);
-}
-
-static int power_hdmi(int on)
-{
-       /* HDMI_EN1: GPJ2[2] */
-       gpio_direction_output(&s5pc110_gpio->gpio_j2, 2, on);
-       /* MHL_ON: GPJ2[3] */
-       gpio_direction_output(&s5pc110_gpio->gpio_j2, 3, on);
-       return 0;
-}
-
-static int power_bt_wifi(int on)
-{
-       /* WLAN_BT_EN: GPB[5] */
-       gpio_direction_output(&s5pc110_gpio->gpio_b, 5, on);
-       return 0;
-}
-
-static int power_fm_radio(int on)
-{
-       /* FM_BUS_nRST: GPJ2[5] */
-       gpio_direction_output(&s5pc110_gpio->gpio_j2, 5, !on);
-       return 0;
-}
-
-static int power_audio_codec(int on)
-{
-       /* CODEC_LDO_EN: GPF3[4] */
-       gpio_direction_output(&s5pc110_gpio->gpio_f3, 4, on);
-       /* CODEC_XTAL_EN: GPH3[2] */
-       gpio_direction_output(&s5pc110_gpio->gpio_h3, 2, on);
-       return 0;
-}
-
-static int power_haptic(int on)
-{
-       /* HAPTIC_ON: GPJ1[1] */
-       gpio_direction_output(&s5pc110_gpio->gpio_j1, 1, on);
-       return 0;
-}
-
-static int power_lcd(int on)
-{
-       /* MLCD_ON: GPJ1[3] */
-       gpio_direction_output(&s5pc110_gpio->gpio_j1, 3, on);
-       return 0;
-}
-
-static int power_touch(int on)
-{
-       /* TOUCH_EN: GPG3[6] */
-       gpio_direction_output(&s5pc110_gpio->gpio_g3, 6, on);
-       return 0;
-}
-
-static int power_3_touchkey(int on)
-{
-       if (on) {
-               /* 3_TOUCH_EN - GPJ3[0] : (J1B2) */
-               /* 3_TOUCH_EN - GPJ3[5] : (not J1B2) */
-               if (board_rev & J1_B2_BOARD)
-                       gpio_direction_output(&s5pc110_gpio->gpio_j3, 0, on);
-               else
-                       gpio_direction_output(&s5pc110_gpio->gpio_j3, 5, on);
-
-               /* 3_TOUCH_CE - GPJ2[6] */
-               gpio_direction_output(&s5pc110_gpio->gpio_j2, 6, on);   /* TOUCH_CE */
-       } else {
-               /* 3_TOUCH_CE - GPJ2[6] */
-               gpio_direction_output(&s5pc110_gpio->gpio_j2, 6, on);   /* TOUCH_CE */
-       }
-
-       if (on) {
-               unsigned int reg;
-               unsigned char val[2];
-               unsigned char addr = 0x20;              /* mcs5000 3-touchkey */
-
-               /* Require 100ms */
-               udelay(80 * 1000);
-
-               /* 3 touchkey */
-               i2c_set_bus_num(I2C_GPIO10);
-
-               /* Workaround to probe */
-               if (i2c_probe(addr)) {
-                       if (i2c_probe(addr)) {
-                               printf("Can't found 3 touchkey\n");
-                               return -ENODEV;
-                       }
-               }
-
-#define MCS5000_TK_HW_VERSION  0x06
-#define MCS5000_TK_FW_VERSION  0x0A
-#define MCS5000_TK_MI_VERSION  0x0B
-
-               reg = MCS5000_TK_MI_VERSION;
-               i2c_read(addr, reg, 1, val, 1);
-               printf("3-touchkey:\tM/I 0x%x, ", val[0]);
-               reg = MCS5000_TK_HW_VERSION;
-               i2c_read(addr, reg, 1, val, 1);
-               printf("H/W 0x%x, ", val[0]);
-               reg = MCS5000_TK_FW_VERSION;
-               i2c_read(addr, reg, 1, val, 1);
-               printf("F/W 0x%x\n", val[0]);
-       }
-       return 0;
-}
-
-static int power_control(int device, int on)
-{
-       switch (device) {
-       case POWER_TOUCH:
-               return power_touch(on);
-       case POWER_3_TOUCHKEY:
-               return power_3_touchkey(on);
-       case POWER_LCD:
-               return power_lcd(on);
-       case POWER_HAPTIC:
-               return power_haptic(on);
-       case POWER_AUDIO_CODEC:
-               return power_audio_codec(on);
-       case POWER_FM_RADIO:
-               return power_fm_radio(on);
-       case POWER_BT_WIFI:
-               return power_bt_wifi(on);
-       case POWER_HDMI:
-               return power_hdmi(on);
-       default:
-               printf("I don't know device %d\n", device);
-               break;
-       }
-       return 0;
-}
-
-static int power_on(int on)
-{
-       power_touch(on);
-       power_3_touchkey(on);
-       power_lcd(on);
-       power_haptic(on);
-       power_audio_codec(on);
-       power_fm_radio(on);
-       power_bt_wifi(on);
-       power_hdmi(on);
-
-       return 0;
-}
-
-static int do_power(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
-{
-       int device, on;
-
-       if (!machine_is_aquila())
-               goto out;
-
-       switch (argc) {
-       case 2:
-               if (strncmp(argv[1], "on", 2) == 0)
-                       return power_on(1);
-               if (strncmp(argv[1], "off", 3) == 0)
-                       return power_on(0);
-               break;
-       case 3:
-               device = simple_strtoul(argv[1], NULL, 10);
-               if (device < 0)
-                       break;
-
-               if (strncmp(argv[2], "on", 2) == 0)
-                       on = 1;
-               else if (strncmp(argv[2], "off", 3) == 0)
-                       on = 0;
-               else
-                       break;
-               return power_control(device, on);
-       default:
-               break;
-       }
-out:
-       cmd_usage(cmdtp);
-       power_display_devices();
-       return 1;
-}
-
-U_BOOT_CMD(
-       power,          CONFIG_SYS_MAXARGS,     1, do_power,
-       "Device Power Management control",
-       "device on/off - Turn on/off the device\n"
-);
-
 static int do_microusb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
        switch (argc) {