recovery: universal: update board file
[kernel/u-boot.git] / recovery / board / samsung / universal / universal.c
1 /*
2  * Copyright (C) 2009-2010 Samsung Electronics
3  */
4
5 #include <common.h>
6 #include <linux/mtd/mtd.h>
7 #include <linux/mtd/onenand.h>
8 #include <asm/io.h>
9 #include <asm/arch/cpu.h>
10 #include <asm/arch/gpio.h>
11 #include <asm/arch/keypad.h>
12 #include <asm/arch/power.h>
13 #include "recovery.h"
14 #include "onenand.h"
15
16 #ifdef RECOVERY_DEBUG
17 #define PUTS(s) serial_puts(DEBUG_MARK""s)
18 #else
19 #define PUTS(s)
20 #endif
21
22 #define C110_MACH_START         3100
23 #define C100_MACH_START         3000
24
25 /* board is MACH_AQUILA and board is like below. */
26 #define J1_B2_BOARD             0x0200
27 #define LIMO_UNIVERSAL_BOARD    0x0400
28 #define LIMO_REAL_BOARD         0x0800
29 #define MEDIA_BOARD             0x1000
30 #define BAMBOO_BOARD            0x2000
31
32 /* board is MACH_GONI and board is like below */
33 #define S1_BOARD                0x1000
34 #define KESSLER_BOARD           0x4000
35 #define SDK_BOARD               0x8000
36
37 #define BOARD_MASK              0xFF00
38
39 enum {
40         MACH_UNIVERSAL,
41         MACH_TICKERTAPE,
42         MACH_CHANGED,
43         MACH_P1P2,      /* Don't remove it */
44         MACH_GEMINUS,
45         MACH_CYPRESS,
46
47         MACH_WMG160 = 160,
48
49         MACH_PSEUDO_END,
50 };
51
52 typedef int (init_fnc_t) (void);
53
54 static bd_t bd;
55
56 static unsigned int board_rev;
57
58 static void sdelay(unsigned long usec)
59 {
60         ulong kv;
61
62         do {
63                 kv = 0x100000;
64                 while (kv)
65                         kv--;
66                 usec--;
67         } while (usec);
68 }
69
70 static int hwrevision(int rev)
71 {
72         return (board_rev & 0xf) == rev;
73 }
74
75 static int c110_machine_id(void)
76 {
77         return bd.bi_arch_number - C110_MACH_START;
78 }
79
80 static int mach_is_aquila(void)
81 {
82         return bd.bi_arch_number == MACH_TYPE_AQUILA;
83 }
84
85 static int mach_is_geminus(void)
86 {
87         return c110_machine_id() == MACH_GEMINUS;
88 }
89
90 static int board_is_limo_universal(void)
91 {
92         return mach_is_aquila() && (board_rev & LIMO_UNIVERSAL_BOARD);
93 }
94
95 static int board_is_limo_real(void)
96 {
97         return mach_is_aquila() && (board_rev & LIMO_REAL_BOARD);
98 }
99
100 /* Kessler */
101 static int mach_is_goni(void)
102 {
103         return bd.bi_arch_number == MACH_TYPE_GONI;
104 }
105
106 static int board_is_sdk(void)
107 {
108         return mach_is_goni() && (board_rev & SDK_BOARD);
109 }
110
111 /* DLNA Dongle */
112 static int mach_is_wmg160(void)
113 {
114         return c110_machine_id() == MACH_WMG160;
115 }
116
117 static void check_board_revision(int board, int rev)
118 {
119         if (board == MACH_TYPE_AQUILA) {
120                 /* Limo Real or Universal */
121                 if (rev & LIMO_UNIVERSAL_BOARD)
122                         board_rev &= ~J1_B2_BOARD;
123                 if (rev & LIMO_REAL_BOARD)
124                         board_rev &= ~(J1_B2_BOARD |
125                                         LIMO_UNIVERSAL_BOARD);
126                 if (rev & MEDIA_BOARD)
127                         board_rev &= ~(J1_B2_BOARD |
128                                         LIMO_UNIVERSAL_BOARD);
129                 if (rev & BAMBOO_BOARD)
130                         board_rev &= ~(J1_B2_BOARD |
131                                         LIMO_UNIVERSAL_BOARD |
132                                         LIMO_REAL_BOARD |
133                                         MEDIA_BOARD);
134         } else if (board == MACH_TYPE_GONI) {
135                 if (rev & KESSLER_BOARD)
136                         board_rev &= ~(J1_B2_BOARD |
137                                         LIMO_UNIVERSAL_BOARD);
138                 if (rev & SDK_BOARD)
139                         board_rev &= ~(J1_B2_BOARD |
140                                         LIMO_UNIVERSAL_BOARD);
141                 if (rev & S1_BOARD)
142                         board_rev &= ~(J1_B2_BOARD | LIMO_UNIVERSAL_BOARD |
143                                         LIMO_REAL_BOARD);
144         } else {
145                 board_rev &= ~BOARD_MASK;
146         }
147 }
148
149 static unsigned int get_hw_revision(struct s5p_gpio_bank *bank, int hwrev3)
150 {
151         unsigned int rev;
152
153         gpio_direction_input(bank, 2);
154         gpio_direction_input(bank, 3);
155         gpio_direction_input(bank, 4);
156         gpio_direction_input(bank, hwrev3);
157
158         gpio_set_pull(bank, 2, GPIO_PULL_NONE);         /* HWREV_MODE0 */
159         gpio_set_pull(bank, 3, GPIO_PULL_NONE);         /* HWREV_MODE1 */
160         gpio_set_pull(bank, 4, GPIO_PULL_NONE);         /* HWREV_MODE2 */
161         gpio_set_pull(bank, hwrev3, GPIO_PULL_NONE);    /* HWREV_MODE3 */
162
163         rev = gpio_get_value(bank, 2);
164         rev |= (gpio_get_value(bank, 3) << 1);
165         rev |= (gpio_get_value(bank, 4) << 2);
166         rev |= (gpio_get_value(bank, hwrev3) << 3);
167
168         return rev;
169 }
170
171 static void check_hw_revision(void)
172 {
173         unsigned int board = MACH_UNIVERSAL;    /* Default is Universal */
174
175         if (cpu_is_s5pc100()) {
176                 struct s5pc100_gpio *gpio =
177                         (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
178
179                 board_rev = get_hw_revision(&gpio->gpio_j0, 0);
180
181                 /* C100 TickerTape */
182                 if (board_rev == 3)
183                         board = MACH_TICKERTAPE;
184         } else {
185                 struct s5pc110_gpio *gpio =
186                         (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
187                 int hwrev3 = 1;
188
189                 board_rev = 0;
190
191                 /*
192                  * Note Check 'Aquila' board first
193                  *
194                  * TT: TickerTape
195                  * SS: SplitScreen
196                  * LRA: Limo Real Aquila
197                  * LUA: Limo Universal Aquila
198                  * OA: Old Aquila
199                  * CYP: Cypress
200                  * BB: Bamboo
201                  *
202                  * ADDR = 0xE0200000 + OFF
203                  *
204                  *       OFF    Universal BB   LRA  LUA  OA   TT   SS       CYP
205                  *   J1: 0x0264 0x10      0x10 0x00 0x00 0x00 0x00 0x00
206                  *   J2: 0x0284           0x01 0x10 0x00
207                  *   H1: 0x0C24    W           0x28 0xA8 0x1C               0x0F
208                  *   H3: 0x0C64                0x03 0x07 0x0F
209                  *   D1: 0x00C4 0x0F           0x3F 0x3F 0x0F 0xXC 0x3F
210                  *    I: 0x0224                          0x02 0x00 0x08
211                  * MP03: 0x0324                          0x9x      0xbx 0x9x
212                  * MP05: 0x0364                          0x80      0x88
213                  */
214
215                 /* C110 Aquila */
216                 if (gpio_get_value(&gpio->gpio_j1, 4) == 0) {
217                         board = MACH_TYPE_AQUILA;
218                         board_rev |= J1_B2_BOARD;
219
220                         gpio_set_pull(&gpio->gpio_j2, 6, GPIO_PULL_NONE);
221                         gpio_direction_input(&gpio->gpio_j2, 6);
222
223                         /* Check board */
224                         if (gpio_get_value(&gpio->gpio_h1, 2) == 0)
225                                 board_rev |= LIMO_UNIVERSAL_BOARD;
226
227                         if (gpio_get_value(&gpio->gpio_h3, 2) == 0)
228                                 board_rev |= LIMO_REAL_BOARD;
229
230                         if (gpio_get_value(&gpio->gpio_j2, 6) == 1)
231                                 board_rev |= MEDIA_BOARD;
232
233                         /* set gpio to default value. */
234                         gpio_set_pull(&gpio->gpio_j2, 6, GPIO_PULL_DOWN);
235                         gpio_direction_output(&gpio->gpio_j2, 6, 0);
236                 }
237
238                 /* Workaround: C110 Aquila Rev0.6 */
239                 if (board_rev == 6) {
240                         board = MACH_TYPE_AQUILA;
241                         board_rev |= LIMO_REAL_BOARD;
242                 }
243
244                 /* C110 Aquila Bamboo */
245                 if (gpio_get_value(&gpio->gpio_j2, 0) == 1) {
246                         board = MACH_TYPE_AQUILA;
247                         board_rev |= BAMBOO_BOARD;
248                 }
249
250                 /* C110 TickerTape */
251                 if (gpio_get_value(&gpio->gpio_d1, 0) == 0 &&
252                                 gpio_get_value(&gpio->gpio_d1, 1) == 0)
253                         board = MACH_TICKERTAPE;
254
255                 /* WMG160 - GPH3[0:4] = 0x00 */
256                 if (board == MACH_TICKERTAPE) {
257                         int i, wmg160 = 1;
258
259                         for (i = 0; i < 4; i++) {
260                                 if (gpio_get_value(&gpio->gpio_h3, i) != 0) {
261                                         wmg160 = 0;
262                                         break;
263                                 }
264                         }
265                         if (wmg160) {
266                                 board = MACH_WMG160;
267                                 hwrev3 = 7;
268                         }
269                 }
270
271                 /* C110 Geminus for rev0.0 */
272                 gpio_set_pull(&gpio->gpio_j1, 2, GPIO_PULL_NONE);
273                 gpio_direction_input(&gpio->gpio_j1, 2);
274                 if (gpio_get_value(&gpio->gpio_j1, 2) == 1) {
275                         board = MACH_GEMINUS;
276                         if ((board_rev & ~BOARD_MASK) == 3)
277                                 board_rev &= ~0xff;
278                 }
279                 gpio_set_pull(&gpio->gpio_j1, 2, GPIO_PULL_DOWN);
280                 gpio_direction_output(&gpio->gpio_j1, 2, 0);
281
282                 /* C110 Geminus for rev0.1 ~ */
283                 gpio_set_pull(&gpio->gpio_j0, 6, GPIO_PULL_NONE);
284                 gpio_direction_input(&gpio->gpio_j0, 6);
285                 if (gpio_get_value(&gpio->gpio_j0, 6) == 1) {
286                         board = MACH_GEMINUS;
287                         hwrev3 = 7;
288                 }
289                 gpio_set_pull(&gpio->gpio_j0, 6, GPIO_PULL_DOWN);
290
291                 /* Kessler MP0_5[6] == 1 */
292                 gpio_direction_input(&gpio->gpio_mp0_5, 6);
293                 if (gpio_get_value(&gpio->gpio_mp0_5, 6) == 1) {
294                         /* Cypress: Do this for cypress */
295                         gpio_set_pull(&gpio->gpio_j2, 2, GPIO_PULL_NONE);
296                         gpio_direction_input(&gpio->gpio_j2, 2);
297                         if (gpio_get_value(&gpio->gpio_j2, 2) == 1) {
298                                 board = MACH_CYPRESS;
299                                 gpio_direction_output(&gpio->gpio_mp0_5, 6, 0);
300                         } else {
301                                 board = MACH_TYPE_GONI;
302                                 board_rev |= KESSLER_BOARD;
303
304                                 /* Limo SDK MP0_5[4] == 1 */
305                                 gpio_direction_input(&gpio->gpio_mp0_5, 4);
306                                 if (gpio_get_value(&gpio->gpio_mp0_5, 4) == 1) {
307                                         board_rev &= ~KESSLER_BOARD;
308                                         board_rev |= SDK_BOARD;
309                                 }
310                         }
311                         gpio_set_pull(&gpio->gpio_j2, 2, GPIO_PULL_DOWN);
312                         hwrev3 = 7;
313                 } else {
314                         gpio_direction_output(&gpio->gpio_mp0_5, 6, 0);
315                         /* Goni S1 board detection */
316                         if (board == MACH_TICKERTAPE) {
317                                 board = MACH_TYPE_GONI;
318                                 board_rev |= S1_BOARD;
319                                 hwrev3 = 7;
320                         }
321                 }
322
323                 board_rev |= get_hw_revision(&gpio->gpio_j0, hwrev3);
324         }
325
326         /* Set machine id */
327         if (board < MACH_PSEUDO_END) {
328                 if (cpu_is_s5pc110())
329                         bd.bi_arch_number = C110_MACH_START + board;
330                 else
331                         bd.bi_arch_number = C100_MACH_START + board;
332         } else {
333                 bd.bi_arch_number = board;
334         }
335 }
336
337 static void show_hw_revision(void)
338 {
339         int board;
340
341         /*
342          * Workaround for Rev 0.3 + CP Ver ES 3.1
343          * it's Rev 0.4
344          */
345         if (board_is_limo_real()) {
346                 if (hwrevision(0)) {
347                         /* default is Rev 0.4 */
348                         board_rev &= ~0xf;
349                         board_rev |= 0x4;
350                 }
351         }
352
353         if (mach_is_goni() || mach_is_aquila())
354                 board = bd.bi_arch_number;
355         else if (cpu_is_s5pc110())
356                 board = bd.bi_arch_number - C110_MACH_START;
357         else
358                 board = bd.bi_arch_number - C100_MACH_START;
359
360         check_board_revision(board, board_rev);
361
362         /* Set CPU Revision */
363         if (mach_is_aquila()) {
364                 if (board_is_limo_real()) {
365                         if ((board_rev & 0xf) < 8)
366                                 s5pc1xx_set_cpu_rev(0);
367                 }
368         } else if (mach_is_goni()) {
369                 if (board_is_sdk() &&
370                         (hwrevision(2) || hwrevision(4) || hwrevision(5)))
371                         s5pc1xx_set_cpu_rev(2); /* EVT1-Fused */
372                 else
373                         s5pc1xx_set_cpu_rev(1);
374         } else if (mach_is_geminus()) {
375                 if ((board_rev & 0xf) < 1)
376                         s5pc1xx_set_cpu_rev(0);
377         } else if (mach_is_wmg160()) {
378                 if (hwrevision(5))
379                         s5pc1xx_set_cpu_rev(0);
380                 else
381                         s5pc1xx_set_cpu_rev(2);
382         } else {
383                 s5pc1xx_set_cpu_rev(0);
384         }
385
386         if (cpu_is_s5pc110())
387                 writel(0xc1100000 | (0xffff & (s5pc1xx_get_cpu_rev() ? 1 : 0)),
388                                 S5PC110_INFORM3);
389 }
390
391 static int check_keypad(void)
392 {
393         uint condition = 0;
394         uint reg, value;
395         uint col_num, row_num;
396         uint col_mask;
397         uint col_mask_shift;
398         uint row_state[4] = {0, 0, 0, 0};
399         uint i;
400         int cpu_rev;
401
402         if (cpu_is_s5pc100()) {
403                 struct s5pc100_gpio *gpio =
404                         (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
405
406                 row_num = 3;
407                 col_num = 3;
408
409                 /* Set GPH2[2:0] to KP_COL[2:0] */
410                 gpio_cfg_pin(&gpio->gpio_h2, 0, 0x3);
411                 gpio_cfg_pin(&gpio->gpio_h2, 1, 0x3);
412                 gpio_cfg_pin(&gpio->gpio_h2, 2, 0x3);
413
414                 /* Set GPH3[2:0] to KP_ROW[2:0] */
415                 gpio_cfg_pin(&gpio->gpio_h3, 0, 0x3);
416                 gpio_cfg_pin(&gpio->gpio_h3, 1, 0x3);
417                 gpio_cfg_pin(&gpio->gpio_h3, 2, 0x3);
418
419                 reg = S5PC100_KEYPAD_BASE;
420                 col_mask = S5PC1XX_KEYIFCOL_MASK;
421                 col_mask_shift = 0;
422         } else {
423                 struct s5pc110_gpio *gpio =
424                         (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
425
426                 if (mach_is_wmg160())
427                         return 0;
428
429                 if (board_is_limo_real() || board_is_limo_universal()) {
430                         row_num = 2;
431                         col_num = 3;
432                 } else {
433                         row_num = 4;
434                         col_num = 4;
435                 }
436
437                 for (i = 0; i < row_num; i++) {
438                         /* Set GPH3[3:0] to KP_ROW[3:0] */
439                         gpio_cfg_pin(&gpio->gpio_h3, i, 0x3);
440                         gpio_set_pull(&gpio->gpio_h3, i, GPIO_PULL_UP);
441                 }
442
443                 for (i = 0; i < col_num; i++)
444                         /* Set GPH2[3:0] to KP_COL[3:0] */
445                         gpio_cfg_pin(&gpio->gpio_h2, i, 0x3);
446
447                 reg = S5PC110_KEYPAD_BASE;
448                 col_mask = S5PC110_KEYIFCOLEN_MASK;
449                 col_mask_shift = 8;
450         }
451
452         /* KEYIFCOL reg clear */
453         writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
454
455         /* key_scan */
456         for (i = 0; i < col_num; i++) {
457                 value = col_mask;
458                 value &= ~(1 << i) << col_mask_shift;
459
460                 writel(value, reg + S5PC1XX_KEYIFCOL_OFFSET);
461                 sdelay(1000);
462
463                 value = readl(reg + S5PC1XX_KEYIFROW_OFFSET);
464                 row_state[i] = ~value & ((1 << row_num) - 1);
465         }
466
467         /* KEYIFCOL reg clear */
468         writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
469
470         cpu_rev = s5pc1xx_get_cpu_rev();
471         if (cpu_rev == 1) {
472                 if ((row_state[1] & 0x6) == 0x6)
473                         condition = 1;
474         } else if (cpu_rev == 2) {
475                 if ((row_state[2] & 0x6) == 0x6)
476                         condition = 1;
477         } else {
478                 if ((row_state[1] & 0x3) == 0x3)
479                         condition = 1;
480         }
481
482         return condition;
483 }
484
485 static int check_block(void)
486 {
487         struct onenand_op *onenand_ops = onenand_get_interface();
488         struct mtd_info *mtd = onenand_ops->mtd;
489         struct onenand_chip *this = mtd->priv;
490         int i;
491         int retlen = 0;
492         u32 from = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
493         u32 len = 1 << this->erase_shift;
494         u32 *buf = (u32 *)CONFIG_SYS_DOWN_ADDR;
495
496         /* check first page of bootloader*/
497         onenand_ops->read(from, len, (ssize_t *)&retlen, (u_char *)buf, 0);
498         if (retlen != len)
499                 return 1;
500
501         for (i = 0; i < (this->writesize / sizeof(this->writesize)); i++)
502                 if (*(buf + i) != 0xffffffff)
503                         return 0;
504
505         return 1;
506 }
507
508 int board_check_condition(void)
509 {
510         if (check_keypad()) {
511                 PUTS("check: manual\n");
512                 return 1;
513         }
514
515         if (check_block()) {
516                 PUTS("check: bootloader broken\n");
517                 return 2;
518         }
519
520         return 0;
521 }
522
523 int board_load_bootloader(unsigned char *buf)
524 {
525         struct mtd_info *mtd = &onenand_mtd;
526         struct onenand_chip *this = mtd->priv;
527         u32 ofs, len, retlen;
528
529         ofs = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
530         len = CONFIG_SYS_MONITOR_LEN;
531
532         mtd->read(mtd, ofs, len, &retlen, buf);
533
534         if (len != retlen)
535                 return -1;
536
537         return 0;
538 }
539
540 int board_lock_recoveryblock(void)
541 {
542         struct mtd_info *mtd = &onenand_mtd;
543         struct onenand_chip *this = mtd->priv;
544         u32 ofs = 0;
545         u32 len = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
546         int ret = 0;
547
548         /* lock-tight the recovery block */
549         if (this->lock_tight != NULL)
550                 ret = this->lock_tight(mtd, ofs, len);
551
552         return ret;
553 }
554
555 void board_update_init(void)
556 {
557         struct mtd_info *mtd = &onenand_mtd;
558         struct onenand_chip *this = mtd->priv;
559
560         /* Unlock whole block */
561         this->unlock_all(mtd);
562 }
563
564 int board_update_image(u32 *buf, u32 len)
565 {
566         struct onenand_op *onenand_ops = onenand_get_interface();
567         struct mtd_info *mtd = &onenand_mtd;
568         struct onenand_chip *this = mtd->priv;
569         u32 ofs;
570         u32 ipl_addr = 0;
571         u32 ipl_edge = CONFIG_ONENAND_START_PAGE << this->page_shift;
572         u32 recovery_addr = ipl_edge;
573         u32 recovery_edge = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
574         u32 bootloader_addr = recovery_edge;
575         int ret, retlen;
576
577         if (len > bootloader_addr) {
578                 if (*(buf + bootloader_addr/sizeof(buf)) == 0xea000012) {
579                         /* case: IPL + Recovery + bootloader */
580                         PUTS("target: ipl + recovery + bootloader\n");
581                         ofs = ipl_addr;
582                         /* len = bootloader_edge; */
583                 } else {
584                         /* case: unknown format */
585                         PUTS("target: unknown\n");
586                         return 1;
587                 }
588         } else {
589                 if (*(buf + recovery_addr/sizeof(buf)) == 0xea000012 &&
590                         *(buf + recovery_addr/sizeof(buf) - 1) == 0x00000000) {
591                         /* case: old image (IPL + bootloader) */
592                         PUTS("target: ipl + bootloader (old type)\n");
593                         ofs = ipl_addr;
594                         /* len = recovery_edge; */
595                 } else {
596                         /* case: bootloader only */
597                         PUTS("target: bootloader\n");
598                         ofs = bootloader_addr;
599                         /* len = bootloader_edge - recovery_edge; */
600                 }
601         }
602
603 #ifdef CONFIG_S5PC1XX
604         /* Workaround: for prevent revision mismatch */
605         if (cpu_is_s5pc110() && (ofs == 0)) {
606                 int img_rev;
607
608                 if (*buf == 0xea000012)
609                         img_rev = 0;
610                 else if (*(buf + 0x400) == 0xea000012)
611                         img_rev = 2;
612                 else
613                         img_rev = 1;
614
615                 if (img_rev != s5pc1xx_get_cpu_rev()) {
616                         PUTS("target check: CPU revision mismatch!\n");
617                         PUTS("target check: system is ");
618                         if (s5pc1xx_get_cpu_rev() == 1)
619                                 serial_puts("EVT1\n");
620                         else if (s5pc1xx_get_cpu_rev() == 2)
621                                 serial_puts("EVT1-Fused\n");
622                         else
623                                 serial_puts("EVT0\n");
624                         PUTS("target check: download image is ");
625                         if (img_rev == 1)
626                                 serial_puts("EVT1\n");
627                         else if (img_rev == 2)
628                                 serial_puts("EVT1-Fused\n");
629                         else
630                                 serial_puts("EVT0\n");
631                         PUTS("try again.");
632                         return 1;
633                 }
634         }
635 #endif
636
637         /* Erase */
638         ret = onenand_ops->erase(ofs, len, 0);
639         if (ret)
640                 return ret;
641
642         /* Write */
643         onenand_ops->write(ofs, len, (ssize_t *)&retlen, (u_char *)buf);
644         if (ret)
645                 return ret;
646
647         return 0;
648 }
649
650 void board_recovery_init(void)
651 {
652         struct s5pc110_gpio *gpio_base =
653                 (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
654
655         /* basic arch cpu dependent setup */
656         arch_cpu_init();
657
658         /* Check H/W Revision */
659         check_hw_revision();
660
661         show_hw_revision();
662
663         /* set GPIO to enable UART2 */
664         gpio_cfg_pin(&gpio_base->gpio_a1, 0, 0x2);
665         gpio_cfg_pin(&gpio_base->gpio_a1, 1, 0x2);
666
667         /* UART_SEL MP0_5[7] at S5PC110 */
668         gpio_direction_output(&gpio_base->gpio_mp0_5, 7, 0x1);
669         gpio_set_pull(&gpio_base->gpio_mp0_5, 7, GPIO_PULL_DOWN);
670 }