2 * (C) 2006-2007 by OpenMoko, Inc.
3 * Author: Harald Welte <laforge@openmoko.org>
5 * based on existing S3C2410 startup code in u-boot:
8 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
9 * Marius Groeger <mgroeger@sysgo.de>
12 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
14 * See file CREDITS for list of people who contributed to this
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
37 #include <asm/atomic.h>
39 #include "../common/neo1973.h"
40 #include "../common/jbt6k74.h"
44 DECLARE_GLOBAL_DATA_PTR
;
46 /* That many seconds the power key needs to be pressed to power up */
47 #define POWER_KEY_SECONDS 1
49 /* If the battery voltage is below this, we can't provide stable power */
50 #define SAVE_POWER_MILLIVOLT 3600
52 #if defined(CONFIG_ARCH_GTA02_v1)
53 //#define M_MDIV 0x7f /* Fout = 405.00MHz */
54 #define M_MDIV 0x7d /* Fout = 399.00MHz */
70 extern void smedia3362_lcm_reset(int);
71 extern void glamo_core_init(void);
73 unsigned int neo1973_wakeup_cause
;
74 extern unsigned char booted_from_nand
;
75 extern unsigned char booted_from_nor
;
76 extern int nobootdelay
;
77 char __cfg_prompt
[20] = "GTA02vXX # ";
80 * In >GTA02v5, use gta02_revision to test for features, not
81 * CONFIG_GTA02_REVISION or CONFIG_ARCH_GTA02_vX !
85 static uint16_t gpb_shadow
= 0; /* to work around GTA02v5 LED bug */
87 int gta02_get_pcb_revision(void);
89 static inline void delay (unsigned long loops
)
91 __asm__
volatile ("1:\n"
93 "bne 1b":"=r" (loops
):"0" (loops
));
97 GTA02_LED_PWR_ORANGE
= 0,
98 GTA02_LED_PWR_BLUE
= 1,
99 GTA02_LED_AUX_RED
= 2,
103 * Miscellaneous platform dependent initialisations
106 static void cpu_speed(int mdiv
, int pdiv
, int sdiv
, int clkdivn
)
108 S3C24X0_CLOCK_POWER
* const clk_power
= S3C24X0_GetBase_CLOCK_POWER();
111 clk_power
->CLKDIVN
= clkdivn
;
113 /* to reduce PLL lock time, adjust the LOCKTIME register */
114 clk_power
->LOCKTIME
= 0xFFFFFF;
117 clk_power
->MPLLCON
= ((mdiv
<< 12) + (pdiv
<< 4) + sdiv
);
119 /* some delay between MPLL and UPLL */
123 clk_power
->UPLLCON
= ((U_M_MDIV
<< 12) + (U_M_PDIV
<< 4) + U_M_SDIV
);
125 /* some delay between MPLL and UPLL */
131 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
133 /* FCLK = 200MHz values from cpu/arm920t/start.S */
134 cpu_speed(142, 7, 1, 3); /* 200MHZ, 1:2:4 */
136 /* set up the I/O ports */
137 #if CONFIG_GTA02_REVISION == 1
138 gpio
->GPACON
= 0x007E1FFF;
139 gpio
->GPADAT
|= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
141 gpio
->GPBCON
= 0x00155555;
142 gpio
->GPBUP
= 0x000007FF;
144 gpio
->GPCCON
= 0x55551155;
145 gpio
->GPCUP
= 0x0000FFFF;
147 gpio
->GPDCON
= 0x55555555;
148 gpio
->GPDUP
= 0x0000FFFF;
150 gpio
->GPECON
= 0xAAAAAAAA;
151 gpio
->GPEUP
= 0x0000FFFF;
153 gpio
->GPFCON
= 0x0000AAAA;
154 gpio
->GPFUP
= 0x000000FF;
156 gpio
->GPGCON
= 0x013DFDFA;
157 gpio
->GPGUP
= 0x0000FFFF;
159 gpio
->GPHCON
= 0x0028AAAA;
160 gpio
->GPHUP
= 0x000007FF;
162 gpio
->GPJCON
= 0x1545541;
163 #elif CONFIG_GTA02_REVISION == 2
164 gpio
->GPACON
= 0x007E1FFF;
165 gpio
->GPADAT
|= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
167 gpio
->GPBCON
= 0x00155555;
168 gpio
->GPBUP
= 0x000007FF;
170 gpio
->GPCCON
= 0x55415155;
171 gpio
->GPCUP
= 0x0000FFFF;
173 gpio
->GPDCON
= 0x55555555;
174 gpio
->GPDUP
= 0x0000FFFF;
176 gpio
->GPECON
= 0xAAAAAAAA;
177 gpio
->GPEUP
= 0x0000FFFF;
179 gpio
->GPFCON
= 0x0000AAAA;
180 gpio
->GPFUP
= 0x000000FF;
182 gpio
->GPGCON
= 0x0156FE7A;
183 gpio
->GPGUP
= 0x0000FFFF;
185 gpio
->GPHCON
= 0x001AAAAA;
186 gpio
->GPHUP
= 0x000007FF;
188 gpio
->GPJCON
= 0x1551544;
189 gpio
->GPJUP
= 0x1ffff;
190 gpio
->GPJDAT
|= (1 << 4); /* Set GPJ4 to high (nGSM_EN) */
191 #elif CONFIG_GTA02_REVISION >= 3
192 gpio
->GPACON
= 0x007E5FFF;
193 gpio
->GPADAT
|= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
195 gpio
->GPBCON
= 0x00155555;
196 gpio
->GPBUP
= 0x000007FF;
199 * PCB rev index found on C13, C15, D0, D3 and D4. These are NC or
200 * pulled up by 10K. Therefore to ensure no current flows when they
201 * are not interrogated, we drive them high. When we interrogate them
202 * we make them pulled them down inputs briefly and set them high op
206 /* pulldown on "PIO_5" BT module to stop float when unpowered
207 * C13 and C15 are b0 and b1 of PCB rev index
209 gpio
->GPCCON
= 0x55555155;
210 gpio
->GPCUP
= 0x0000FFFF & ~(1 << 5);
211 gpio
->GPCDAT
|= (1 << 13) | (1 << 15); /* index detect -> hi */
213 /* D0, D3 and D4 are b2, b3 and b4 of PCB rev index */
214 gpio
->GPDCON
= 0x55555555;
215 gpio
->GPDUP
= 0x0000FFFF;
216 gpio
->GPDDAT
|= (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
218 /* pulldown on GPE11 / SPIMISO0 - goes to debug board and will float */
219 gpio
->GPECON
= 0xAAAAAAAA;
220 gpio
->GPEUP
= 0x0000FFFF & ~(1 << 11);
222 /* pulldown on GPF03: TP-4705+debug - debug conn will float */
223 gpio
->GPFCON
= 0x0000AAAA;
224 gpio
->GPFUP
= 0x000000FF & ~(1 << 3);
226 gpio
->GPGCON
= 0x01AAFE79;
227 gpio
->GPGUP
= 0x0000FFFF;
229 /* pulldown on GPH08: UEXTCLK, just floats!
230 * pulldown GPH0 -- nCTS0 / RTS_MODEM -- floats when GSM off
231 * pulldown GPH3 -- RXD[0] / TX_MODEM -- floats when GSM off
233 gpio
->GPHCON
= 0x001AAAAA;
234 gpio
->GPHUP
= 0x000007FF & ~(1 << 8) & ~(1 << 0) & ~(1 << 3);
236 /* pulldown on GPJ00: input, just floats! */
237 /* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
238 gpio
->GPJCON
= 0x1551544;
239 gpio
->GPJUP
= 0x1ffff & ~(1 << 0) & ~(1 << 7);
240 gpio
->GPJDAT
|= (1 << 4) | (1 << 6);
241 /* Set GPJ4 to high (nGSM_EN) */
242 /* Set GPJ6 to high (nDL_GSM) */
243 gpio
->GPJDAT
&= ~(1 << 5); /* Set GPJ5 to low 3D RST */
244 gpio
->GPJDAT
&= ~(1 << 5); /* Set GPJ5 to low 3D RST */
246 /* leaving Glamo forced to Reset# active here killed
247 * U-Boot when you touched the memory region
250 gpio
->GPJDAT
|= (1 << 5); /* Set GPJ5 to high 3D RST */
252 #error Please define GTA02 version
255 /* arch number of SMDK2410-Board */
256 gd
->bd
->bi_arch_number
= MACH_TYPE_NEO1973_GTA02
;
258 /* adress of boot parameters */
259 gd
->bd
->bi_boot_params
= 0x30000100;
265 * Since the NOR at address 0 is replaced by SteppingStone when the AUX
266 * button is released, we would crash when an interrupt arrives (e.g.,
269 * We solve this as follows: we copy the vector table to RAM at address
270 * 0x30000000 and then use the PID feature in the 920T MMU to map all
271 * addresses in the range 0x0....... to 0x3....... without actually
272 * setting up page mappings in the MMU. Thus, vectors are then
273 * retrieved from their location in RAM.
275 * Note that the mapping is done in lib_arm/interrupts.c, so that it
276 * automatically tracks whether we allow interrupts or not. This is
277 * particularly necessary when we boot, since the operating system may
278 * not expect to find this sort of mapping to be active.
280 #ifdef CONFIG_GTA02_REVISION
284 memcpy((void *) 0x30000000, &_start
, 0x40);
290 static void set_revision(void)
292 int rev
= gta02_get_pcb_revision();
295 if (CONFIG_GTA02_REVISION
< 5)
296 gta02_revision
= CONFIG_GTA02_REVISION
;
306 printf("Unrecognized hardware revision 0x%03x. "
307 "Defaulting to GTA02v6.\n", rev
);
311 sprintf(__cfg_prompt
, "GTA02v%d # ", gta02_revision
);
313 #if 1 /* remove these after checking that Andy doesn't need them anymore */
314 printf("PCB rev: 0x%03X\n", rev
);
315 /* expose in the env so we can add to kernel commandline */
316 sprintf(buf
, "0x%03X", rev
);
317 setenv("pcb_rev", buf
);
321 static void poll_charger(void)
323 if (pcf50633_read_charger_type() == 1000)
324 pcf50633_usb_maxcurrent(1000);
327 static int have_int(uint8_t mask1
, uint8_t mask2
);
329 static void clear_pmu_int(void)
331 S3C24X0_INTERRUPT
* const intr
= S3C24X0_GetBase_INTERRUPT();
332 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
334 /* read the PMU's interrupt register and store what we found for later
338 /* clear EINT9/GPG1 in the MCU's interrupt path */
339 gpio
->EINTPEND
= 1 << 9;
340 intr
->SRCPND
= BIT_EINT8_23
;
341 intr
->INTPND
= BIT_EINT8_23
;
344 static void cpu_idle(void)
346 S3C24X0_INTERRUPT
* const intr
= S3C24X0_GetBase_INTERRUPT();
347 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
348 S3C24X0_CLOCK_POWER
* const clk
= S3C24X0_GetBase_CLOCK_POWER();
352 * We don't want to execute interrupts throughout all this, since
353 * u-boot's interrupt handling code isn't modular, and getting a "real"
354 * interrupt without clearing it in the interrupt handler would cause
355 * us to loop permanently.
357 local_irq_save(flags
);
359 /* enable PMU interrupts */
360 intr
->INTMSK
&= ~BIT_EINT8_23
;
361 gpio
->EINTMASK
&= ~(1 << 9);
364 clk
->CLKCON
|= 1 << 2;
366 /* disable PMU interrupts */
367 intr
->INTMSK
|= BIT_EINT8_23
;
368 gpio
->EINTMASK
|= 1 << 9;
370 /* collect PMU interrupts and clear them */
374 local_irq_restore(flags
);
377 static int battery_is_good(void)
379 /* battery is present -> try to boot */
380 return !(pcf50633_reg_read(PCF50633_REG_BVMCTL
) & 1);
382 * Consider adding this later to the above condition:
383 pcf50633_read_battvolt() >= SAVE_POWER_MILLIVOLT)
387 static void wait_for_power(void)
395 /* we have plenty of external power -> try to boot */
396 if (pcf50633_usb_last_maxcurrent
>= 500)
401 if (neo1973_new_second()) {
403 * Probe the battery only if the current LED cycle is
404 * about to end, so that it had time to discharge.
406 if (led_cycle
&& battery_is_good())
411 led_cycle
= !seconds
|| (seconds
& 1);
414 * Blink the AUX LED, unless it's broken (which is the case in
415 * GTA02v5 it is) and draws excessive current, which we just
416 * can't afford in this delicate situation.
418 if (gta02_revision
> 5)
419 neo1973_led(GTA02_LED_AUX_RED
, led_cycle
);
421 /* alternate LED and charger cycles */
422 pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1
, 1, !led_cycle
);
425 /* switch off the AUX LED */
426 neo1973_led(GTA02_LED_AUX_RED
, 0);
429 static void pcf50633_late_init(void)
431 #ifdef CONFIG_ARCH_GTA02_v1
432 uint8_t pwren
= 1; /* always on */
433 uint8_t recent
= 0; /* antiques don't have that */
435 uint8_t pwren
= 2; /* enabled if GPIO1 = HIGH */
436 uint8_t recent
= 1; /* always on */
439 pcf50633_reg_write(PCF50633_REG_LDO1ENA
, pwren
);
440 pcf50633_reg_write(PCF50633_REG_LDO2ENA
, 2); /* enabled if GPIO1 = H */
441 pcf50633_reg_write(PCF50633_REG_LDO5ENA
, recent
);
442 pcf50633_reg_write(PCF50633_REG_LDO6ENA
, recent
);
444 pcf50633_reg_write(PCF50633_REG_MBCC5
, 0xff); /* 1A USB fast charge */
446 pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1
, 1, 1); /* charge ! */
449 int board_late_init(void)
451 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
454 int menu_vote
= 0; /* <= 0: no, > 0: yes */
460 /* Initialize the Power Management Unit with a safe register set */
463 /* obtain wake-up reason */
464 int1
= pcf50633_reg_read(PCF50633_REG_INT1
);
465 int2
= pcf50633_reg_read(PCF50633_REG_INT2
);
468 pcf50633_late_init();
469 cpu_speed(M_MDIV
, M_PDIV
, M_SDIV
, 5); /* 400MHZ, 1:4:8 */
471 /* issue a short pulse with the vibrator */
472 neo1973_led(GTA02_LED_AUX_RED
, 1);
475 neo1973_led(GTA02_LED_AUX_RED
, 0);
478 #if defined(CONFIG_ARCH_GTA02_v1)
479 /* Glamo3362 reset and power cycle */
480 gpio
->GPJDAT
&= ~0x000000001; /* GTA02v1_GPIO_3D_RESET */
481 pcf50633_reg_write(PCF50633_REG_DOWN2ENA
, 0);
483 pcf50633_reg_write(PCF50633_REG_DOWN2ENA
, 0x2);
484 gpio
->GPJDAT
|= 0x000000001; /* GTA02v1_GPIO_3D_RESET */
487 /* if there's no other reason, must be regular reset */
488 neo1973_wakeup_cause
= NEO1973_WAKEUP_RESET
;
490 if (!booted_from_nand
&& !booted_from_nor
)
493 /* save wake-up reason in environment */
494 sprintf(buf
, "0x%02x", int1
);
495 setenv("pcf50633_int1", buf
);
496 sprintf(buf
, "0x%02x", int2
);
497 setenv("pcf50633_int2", buf
);
499 if (int1
& PCF50633_INT1_ALARM
) {
500 /* we've been woken up by RTC alarm, boot */
501 neo1973_wakeup_cause
= NEO1973_WAKEUP_ALARM
;
504 if (int1
& PCF50633_INT1_USBINS
) {
505 /* we've been woken up by charger insert */
506 neo1973_wakeup_cause
= NEO1973_WAKEUP_CHARGER
;
509 if (int2
& PCF50633_INT2_ONKEYF
) {
510 /* we've been woken up by a falling edge of the onkey */
511 neo1973_wakeup_cause
= NEO1973_WAKEUP_POWER_KEY
;
514 if (neo1973_wakeup_cause
== NEO1973_WAKEUP_CHARGER
) {
515 /* if we still think it was only a charger insert, boot */
521 while (neo1973_wakeup_cause
== NEO1973_WAKEUP_RESET
||
522 neo1973_on_key_pressed()) {
523 if (neo1973_aux_key_pressed())
528 if (neo1973_new_second())
530 if (seconds
>= POWER_KEY_SECONDS
)
533 /* Power off if minimum number of seconds not reached */
537 enter_bootmenu
= menu_vote
> 0 || booted_from_nor
;
539 smedia3362_lcm_reset(1);
540 if (!enter_bootmenu
&& getenv("splashimage"))
541 run_command(getenv("splashimage"), 0);
543 jbt6k74_enter_state(JBT_STATE_NORMAL
);
544 jbt6k74_display_onoff(1);
545 /* switch on the backlight */
546 neo1973_backlight(1);
550 /* check if sd card is inserted, and power-up if it is */
551 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
552 if (!(gpio
->GPFDAT
& (1 << 5)))
553 gpio
->GPBDAT
&= ~(1 << 2);
557 if (enter_bootmenu
) {
558 extern struct bootmenu_setup bootmenu_setup
;
560 if (booted_from_nand
)
561 bootmenu_setup
.comment
= "NAND";
563 bootmenu_setup
.comment
= "NOR";
573 gd
->bd
->bi_dram
[0].start
= PHYS_SDRAM_1
;
574 gd
->bd
->bi_dram
[0].size
= PHYS_SDRAM_1_SIZE
;
579 u_int32_t
get_board_rev(void)
581 return 0x300+0x10*gta02_revision
;
584 void neo1973_poweroff(void)
586 printf("poweroff\n");
588 pcf50633_reg_write(PCF50633_REG_OOCSHDWN
, 0x01);
589 /* don't return to caller */
593 void neo1973_backlight(int on
)
596 /* pcf50633 manual p60
597 * "led_out should never be set to 000000, as this would result
598 * in a deadlock making it impossible to program another value.
599 * If led_out should be inadvertently set to 000000, the
600 * LEDOUT register can be reset by disabling and enabling the
601 * LED converter via control bit led_on in the LEDENA register"
603 pcf50633_reg_write(PCF50633_REG_LEDENA
, 0x00);
604 pcf50633_reg_write(PCF50633_REG_LEDENA
, 0x01);
605 pcf50633_reg_write(PCF50633_REG_LEDOUT
, 0x3f);
607 pcf50633_reg_write(PCF50633_REG_LEDENA
, 0x00);
611 void neo1973_vibrator(int on
)
613 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
615 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
616 gpio
->GPGDAT
|= (1 << 11); /* GPG11 */
617 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
618 gpio
->GPBDAT
|= (1 << 10); /* GPB10 */
620 gpio
->GPBDAT
|= (1 << 3); /* GPB3 */
623 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
624 gpio
->GPGDAT
&= ~(1 << 11); /* GPG11 */
625 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
626 gpio
->GPBDAT
&= ~(1 << 10); /* GPB10 */
628 gpio
->GPBDAT
&= ~(1 << 3); /* GPB3 */
630 gpio
->GPBDAT
|= gpb_shadow
;
633 void neo1973_gsm(int on
)
635 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
637 /* GPIO2 of PMU, GPB7(MODEM_ON)=1 and GPB5(MODEM_RST)=0 */
639 #if !defined(CONFIG_ARCH_GTA02_v1)
640 pcf50633_reg_write(PCF50633_REG_GPIO2CFG
, 0x07);
642 gpio
->GPBDAT
&= ~(1 << 5); /* GTA02_GPIO_MODEM_RST */
643 gpio
->GPBDAT
|= (1 << 7); /* GTA02_GPIO_MODEM_ON */
644 gpio
->GPJDAT
&= ~(1 << 6); /* GTA02_GPIO_nDL_GSM */
646 gpio
->GPBDAT
&= ~(1 << 7); /* GTA02_GPIO_MODEM_ON */
647 #if !defined(CONFIG_ARCH_GTA02_v1)
648 pcf50633_reg_write(PCF50633_REG_GPIO2CFG
, 0x00);
650 gpio
->GPJDAT
|= (1 << 6); /* GTA02_GPIO_nDL_GSM */
654 void neo1973_gps(int on
)
657 pcf50633_reg_write(PCF50633_REG_LDO5ENA
, 0x01);
659 pcf50633_reg_write(PCF50633_REG_LDO5ENA
, 0x00);
662 static int pwr_int_pending(void)
664 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
666 return !(gpio
->GPGDAT
& (1 << 1)); /* EINT9/GPG1 */
669 static int have_int(uint8_t mask1
, uint8_t mask2
)
671 static uint8_t pending1
= 0, pending2
= 0;
673 if (pwr_int_pending()) {
675 * We retrieve all interupts, so that we clear any stray ones
681 for (i
= 0; i
!= 5; i
++)
682 ints
[i
] = pcf50633_reg_read(PCF50633_REG_INT1
+i
);
686 if (pending1
& mask1
) {
690 if (pending2
& mask2
) {
697 int neo1973_new_second(void)
699 return have_int(PCF50633_INT1_SECOND
, 0);
702 int neo1973_on_key_pressed(void)
704 static int pressed
= -1;
707 have_int(0, PCF50633_INT2_ONKEYF
| PCF50633_INT2_ONKEYR
))
708 pressed
= !(pcf50633_reg_read(PCF50633_REG_OOCSTAT
) &
709 PCF50633_OOCSTAT_ONKEY
);
713 int neo1973_aux_key_pressed(void)
715 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
717 return !!(gpio
->GPFDAT
& (1 << 6));
720 /* The sum of all part_size[]s must equal to or greater than the NAND size,
723 unsigned int dynpart_size
[] = {
724 CFG_UBOOT_SIZE
, CFG_ENV_SIZE
, 0x800000, 0xa0000, 0x40000, 0x10000000, 0 };
725 char *dynpart_names
[] = {
726 "u-boot", "u-boot_env", "kernel", "splash", "factory", "rootfs", NULL
};
729 const char *neo1973_get_charge_status(void)
732 return pcf50633_charger_state();
735 int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd
)
738 puts("not implemented yet\n");
742 void neo1973_led(int led
, int on
)
744 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
750 gpb_shadow
|= (1 << led
);
751 gpio
->GPBDAT
|= gpb_shadow
;
754 gpb_shadow
&= ~(1 << led
);
755 gpio
->GPBDAT
= (gpio
->GPBDAT
| gpb_shadow
) & ~(1 << led
);
760 * returns PCB revision information in b9,b8 and b2,b1,b0
761 * Pre-GTA02 A6 returns 0x000
762 * GTA02 A6 returns 0x001
765 int gta02_get_pcb_revision(void)
767 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
771 /* make C13 and C15 pulled-down inputs */
772 gpio
->GPCCON
&= ~0xcc000000;
773 gpio
->GPCUP
&= ~((1 << 13) | (1 << 15));
774 /* D0, D3 and D4 pulled-down inputs */
775 gpio
->GPDCON
&= ~0x000003c3;
776 gpio
->GPDUP
&= ~((1 << 0) | (1 << 3) | (1 << 4));
778 /* delay after changing pulldowns */
782 /* read the version info */
784 n
= (u
>> (13 - 0)) & 0x001;
785 n
|= (u
>> (15 - 1)) & 0x002;
787 n
|= (u
<< (0 + 2)) & 0x004;
789 n
|= (u
<< (8 - 3)) & 0x100;
790 n
|= (u
<< (9 - 4)) & 0x200;
793 * when not being interrogated, all of the revision GPIO
794 * are set to output HIGH without pulldown so no current flows
795 * if they are NC or pulled up.
797 /* make C13 and C15 high ouputs with no pulldowns */
798 gpio
->GPCCON
|= 0x44000000;
799 gpio
->GPCUP
|= (1 << 13) | (1 << 15);
800 gpio
->GPCDAT
|= (1 << 13) | (1 << 15);
801 /* D0, D3 and D4 high ouputs with no pulldowns */
802 gpio
->GPDCON
|= 0x00000141;
803 gpio
->GPDUP
|= (1 << 0) | (1 << 3) | (1 << 4);
804 gpio
->GPDDAT
|= (1 << 0) | (1 << 3) | (1 << 4);