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,
38 #include "../common/neo1973.h"
39 #include "../common/jbt6k74.h"
43 DECLARE_GLOBAL_DATA_PTR
;
45 /* That many seconds the power key needs to be pressed to power up */
46 #define POWER_KEY_SECONDS 1
48 #if defined(CONFIG_ARCH_GTA02_v1)
49 //#define M_MDIV 0x7f /* Fout = 405.00MHz */
50 #define M_MDIV 0x7d /* Fout = 399.00MHz */
66 unsigned int neo1973_wakeup_cause
;
67 extern unsigned char booted_from_nand
;
68 extern unsigned char booted_from_nor
;
69 extern int nobootdelay
;
71 int gta02_get_pcb_revision(void);
73 static inline void delay (unsigned long loops
)
75 __asm__
volatile ("1:\n"
77 "bne 1b":"=r" (loops
):"0" (loops
));
81 GTA02_LED_PWR_ORANGE
= 0,
82 GTA02_LED_PWR_BLUE
= 1,
83 GTA02_LED_AUX_RED
= 2,
87 * Miscellaneous platform dependent initialisations
92 S3C24X0_CLOCK_POWER
* const clk_power
= S3C24X0_GetBase_CLOCK_POWER();
93 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
95 /* to reduce PLL lock time, adjust the LOCKTIME register */
96 clk_power
->LOCKTIME
= 0xFFFFFF;
99 clk_power
->MPLLCON
= ((M_MDIV
<< 12) + (M_PDIV
<< 4) + M_SDIV
);
101 /* some delay between MPLL and UPLL */
105 clk_power
->UPLLCON
= ((U_M_MDIV
<< 12) + (U_M_PDIV
<< 4) + U_M_SDIV
);
108 clk_power
->CLKDIVN
= 0x05; /* 1:4:8 */
110 /* some delay between MPLL and UPLL */
113 /* set up the I/O ports */
114 #if CONFIG_GTA02_REVISION == 1
115 gpio
->GPACON
= 0x007E1FFF;
116 gpio
->GPADAT
|= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
118 gpio
->GPBCON
= 0x00155555;
119 gpio
->GPBUP
= 0x000007FF;
121 gpio
->GPCCON
= 0x55551155;
122 gpio
->GPCUP
= 0x0000FFFF;
124 gpio
->GPDCON
= 0x55555555;
125 gpio
->GPDUP
= 0x0000FFFF;
127 gpio
->GPECON
= 0xAAAAAAAA;
128 gpio
->GPEUP
= 0x0000FFFF;
130 gpio
->GPFCON
= 0x0000AAAA;
131 gpio
->GPFUP
= 0x000000FF;
133 gpio
->GPGCON
= 0x013DFDFA;
134 gpio
->GPGUP
= 0x0000FFFF;
136 gpio
->GPHCON
= 0x0028AAAA;
137 gpio
->GPHUP
= 0x000007FF;
139 gpio
->GPJCON
= 0x1545541;
140 #elif CONFIG_GTA02_REVISION == 2
141 gpio
->GPACON
= 0x007E1FFF;
142 gpio
->GPADAT
|= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
144 gpio
->GPBCON
= 0x00155555;
145 gpio
->GPBUP
= 0x000007FF;
147 gpio
->GPCCON
= 0x55415155;
148 gpio
->GPCUP
= 0x0000FFFF;
150 gpio
->GPDCON
= 0x55555555;
151 gpio
->GPDUP
= 0x0000FFFF;
153 gpio
->GPECON
= 0xAAAAAAAA;
154 gpio
->GPEUP
= 0x0000FFFF;
156 gpio
->GPFCON
= 0x0000AAAA;
157 gpio
->GPFUP
= 0x000000FF;
159 gpio
->GPGCON
= 0x0156FE7A;
160 gpio
->GPGUP
= 0x0000FFFF;
162 gpio
->GPHCON
= 0x001AAAAA;
163 gpio
->GPHUP
= 0x000007FF;
165 gpio
->GPJCON
= 0x1551544;
166 gpio
->GPJUP
= 0x1ffff;
167 gpio
->GPJDAT
|= (1 << 4); /* Set GPJ4 to high (nGSM_EN) */
168 #elif CONFIG_GTA02_REVISION >= 3
169 gpio
->GPACON
= 0x007E5FFF;
170 gpio
->GPADAT
|= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
172 gpio
->GPBCON
= 0x00155555;
173 gpio
->GPBUP
= 0x000007FF;
176 * PCB rev index found on C13, C15, D0, D3 and D4. These are NC or
177 * pulled up by 10K. Therefore to ensure no current flows when they
178 * are not interrogated, we drive them high. When we interrogate them
179 * we make them pulled them down inputs briefly and set them high op
183 /* pulldown on "PIO_5" BT module to stop float when unpowered
184 * C13 and C15 are b0 and b1 of PCB rev index
186 gpio
->GPCCON
= 0x55555155;
187 gpio
->GPCUP
= 0x0000FFFF & ~(1 << 5);
188 gpio
->GPCDAT
|= (1 << 13) | (1 << 15); /* index detect -> hi */
190 /* D0, D3 and D4 are b2, b3 and b4 of PCB rev index */
191 gpio
->GPDCON
= 0x55555555;
192 gpio
->GPDUP
= 0x0000FFFF;
193 gpio
->GPDDAT
|= (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
195 /* pulldown on GPE11 / SPIMISO0 - goes to debug board and will float */
196 gpio
->GPECON
= 0xAAAAAAAA;
197 gpio
->GPEUP
= 0x0000FFFF & ~(1 << 11);
199 /* pulldown on GPF03: TP-4705+debug - debug conn will float */
200 gpio
->GPFCON
= 0x0000AAAA;
201 gpio
->GPFUP
= 0x000000FF & ~(1 << 3);
203 gpio
->GPGCON
= 0x01AAFE79;
204 gpio
->GPGUP
= 0x0000FFFF;
206 /* pulldown on GPH08: UEXTCLK, just floats!
207 * pulldown GPH0 -- nCTS0 / RTS_MODEM -- floats when GSM off
208 * pulldown GPH3 -- RXD[0] / TX_MODEM -- floats when GSM off
210 gpio
->GPHCON
= 0x001AAAAA;
211 gpio
->GPHUP
= 0x000007FF & ~(1 << 8) & ~(1 << 0) & ~(1 << 3);
213 /* pulldown on GPJ00: input, just floats! */
214 /* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
215 gpio
->GPJCON
= 0x1551544;
216 gpio
->GPJUP
= 0x1ffff & ~(1 << 0) & ~(1 << 7);
217 gpio
->GPJDAT
|= (1 << 4) | (1 << 6);
218 /* Set GPJ4 to high (nGSM_EN) */
219 /* Set GPJ6 to high (nDL_GSM) */
220 gpio
->GPJDAT
&= ~(1 << 5); /* Set GPJ5 to low 3D RST */
221 gpio
->GPJDAT
&= ~(1 << 5); /* Set GPJ5 to low 3D RST */
223 /* leaving Glamo forced to Reset# active here killed
224 * U-Boot when you touched the memory region
227 gpio
->GPJDAT
|= (1 << 5); /* Set GPJ5 to high 3D RST */
229 #error Please define GTA02 version
232 /* arch number of SMDK2410-Board */
233 gd
->bd
->bi_arch_number
= MACH_TYPE_NEO1973_GTA02
;
235 /* adress of boot parameters */
236 gd
->bd
->bi_boot_params
= 0x30000100;
242 * Since the NOR is replaced by SteppingStone when the AUX button is
243 * released, we have to wait for this and copy our exception vectors
244 * before we can let u-boot enable interrupts.
246 if (booted_from_nor
) {
249 while (neo1973_aux_key_pressed());
250 memcpy((void *) 0, &_start
, 0x40);
256 int board_late_init(void)
258 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
261 int menu_vote
= 0; /* <= 0: no, > 0: yes */
263 int rev
= gta02_get_pcb_revision();
265 printf("PCB rev: 0x%03X\n", rev
);
266 /* expose in the env so we can add to kernel commandline */
267 sprintf(buf
, "0x%03X", rev
);
268 setenv("pcb_rev", buf
);
270 /* Initialize the Power Management Unit with a safe register set */
273 /* obtain wake-up reason */
274 int1
= pcf50633_reg_read(PCF50633_REG_INT1
);
275 int2
= pcf50633_reg_read(PCF50633_REG_INT2
);
277 /* switch on one of the power led's */
278 neo1973_led(GTA02_LED_PWR_ORANGE
, 1);
280 /* issue a short pulse with the vibrator */
285 #if defined(CONFIG_ARCH_GTA02_v1)
286 /* Glamo3362 reset and power cycle */
287 gpio
->GPJDAT
&= ~0x000000001; /* GTA02v1_GPIO_3D_RESET */
288 pcf50633_reg_write(PCF50633_REG_DOWN2ENA
, 0);
290 pcf50633_reg_write(PCF50633_REG_DOWN2ENA
, 0x2);
291 gpio
->GPJDAT
|= 0x000000001; /* GTA02v1_GPIO_3D_RESET */
294 /* if there's no other reason, must be regular reset */
295 neo1973_wakeup_cause
= NEO1973_WAKEUP_RESET
;
297 if (!booted_from_nand
&& !booted_from_nor
)
300 /* save wake-up reason in environment */
301 sprintf(buf
, "0x%02x", int1
);
302 setenv("pcf50633_int1", buf
);
303 sprintf(buf
, "0x%02x", int2
);
304 setenv("pcf50633_int2", buf
);
306 if (int1
& PCF50633_INT1_ALARM
) {
307 /* we've been woken up by RTC alarm, boot */
308 neo1973_wakeup_cause
= NEO1973_WAKEUP_ALARM
;
311 if (int1
& PCF50633_INT1_USBINS
) {
312 /* we've been woken up by charger insert */
313 neo1973_wakeup_cause
= NEO1973_WAKEUP_CHARGER
;
316 if (int2
& PCF50633_INT2_ONKEYF
) {
317 /* we've been woken up by a falling edge of the onkey */
318 neo1973_wakeup_cause
= NEO1973_WAKEUP_POWER_KEY
;
321 if (neo1973_wakeup_cause
== NEO1973_WAKEUP_CHARGER
) {
322 /* if we still think it was only a charger insert, boot */
328 while (neo1973_wakeup_cause
== NEO1973_WAKEUP_RESET
||
329 neo1973_on_key_pressed()) {
330 if (neo1973_aux_key_pressed())
335 if (neo1973_new_second())
337 if (seconds
>= POWER_KEY_SECONDS
)
340 /* Power off if minimum number of seconds not reached */
345 jbt6k74_enter_state(JBT_STATE_NORMAL
);
346 jbt6k74_display_onoff(1);
350 /* check if sd card is inserted, and power-up if it is */
351 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
352 if (!(gpio
->GPFDAT
& (1 << 5)))
353 gpio
->GPBDAT
&= ~(1 << 2);
357 if (menu_vote
> 0 || booted_from_nor
) {
358 extern struct bootmenu_setup bootmenu_setup
;
360 if (booted_from_nand
)
361 bootmenu_setup
.comment
= "NAND";
363 bootmenu_setup
.comment
= "NOR";
373 gd
->bd
->bi_dram
[0].start
= PHYS_SDRAM_1
;
374 gd
->bd
->bi_dram
[0].size
= PHYS_SDRAM_1_SIZE
;
379 u_int32_t
get_board_rev(void)
381 return 0x300+0x10*CONFIG_GTA02_REVISION
;
384 void neo1973_poweroff(void)
386 printf("poweroff\n");
388 pcf50633_reg_write(PCF50633_REG_OOCSHDWN
, 0x01);
389 /* don't return to caller */
393 void neo1973_backlight(int on
)
396 pcf50633_reg_write(PCF50633_REG_LEDENA
, 0x01);
398 pcf50633_reg_write(PCF50633_REG_LEDENA
, 0x00);
402 void neo1973_vibrator(int on
)
404 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
406 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
407 gpio
->GPGDAT
|= (1 << 11); /* GPG11 */
408 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
409 gpio
->GPBDAT
|= (1 << 10); /* GPB10 */
411 gpio
->GPBDAT
|= (1 << 3); /* GPB3 */
414 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
415 gpio
->GPGDAT
&= ~(1 << 11); /* GPG11 */
416 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
417 gpio
->GPBDAT
&= ~(1 << 10); /* GPB10 */
419 gpio
->GPBDAT
&= ~(1 << 3); /* GPB3 */
423 void neo1973_gsm(int on
)
425 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
427 /* GPIO2 of PMU, GPB7(MODEM_ON)=1 and GPB5(MODEM_RST)=0 */
429 #if !defined(CONFIG_ARCH_GTA02_v1)
430 pcf50633_reg_write(PCF50633_REG_GPIO2CFG
, 0x07);
432 gpio
->GPBDAT
&= ~(1 << 5); /* GTA02_GPIO_MODEM_RST */
433 gpio
->GPBDAT
|= (1 << 7); /* GTA02_GPIO_MODEM_ON */
434 gpio
->GPJDAT
&= ~(1 << 6); /* GTA02_GPIO_nDL_GSM */
436 gpio
->GPBDAT
&= ~(1 << 7); /* GTA02_GPIO_MODEM_ON */
437 #if !defined(CONFIG_ARCH_GTA02_v1)
438 pcf50633_reg_write(PCF50633_REG_GPIO2CFG
, 0x00);
440 gpio
->GPJDAT
|= (1 << 6); /* GTA02_GPIO_nDL_GSM */
444 void neo1973_gps(int on
)
447 pcf50633_reg_write(PCF50633_REG_LDO5ENA
, 0x01);
449 pcf50633_reg_write(PCF50633_REG_LDO5ENA
, 0x00);
452 static int pwr_int_pending(void)
454 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
456 return !(gpio
->GPGDAT
& (1 << 1)); /* EINT9/GPG1 */
459 static int have_int(uint8_t mask1
, uint8_t mask2
)
461 static uint8_t pending1
= 0, pending2
= 0;
463 if (pwr_int_pending()) {
465 * We retrieve all interupts, so that we clear any stray ones
471 for (i
= 0; i
!= 5; i
++)
472 ints
[i
] = pcf50633_reg_read(PCF50633_REG_INT1
+i
);
476 if (pending1
& mask1
) {
480 if (pending2
& mask2
) {
487 int neo1973_new_second(void)
489 return have_int(PCF50633_INT1_SECOND
, 0);
492 int neo1973_on_key_pressed(void)
494 static int pressed
= -1;
497 have_int(0, PCF50633_INT2_ONKEYF
| PCF50633_INT2_ONKEYR
))
498 pressed
= !(pcf50633_reg_read(PCF50633_REG_OOCSTAT
) &
499 PCF50633_OOCSTAT_ONKEY
);
503 int neo1973_aux_key_pressed(void)
505 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
507 return !!(gpio
->GPFDAT
& (1 << 6));
510 /* The sum of all part_size[]s must equal to or greater than the NAND size,
513 unsigned int dynpart_size
[] = {
514 CFG_UBOOT_SIZE
, CFG_ENV_SIZE
, 0x800000, 0xa0000, 0x40000, 0x10000000, 0 };
515 char *dynpart_names
[] = {
516 "u-boot", "u-boot_env", "kernel", "splash", "factory", "rootfs", NULL
};
519 const char *neo1973_get_charge_status(void)
522 return pcf50633_charger_state();
525 int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd
)
528 puts("not implemented yet\n");
532 void neo1973_led(int led
, int on
)
534 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
536 printf("switching led %u %u\n", led
, on
);
541 gpio
->GPBDAT
|= (1 << led
);
543 gpio
->GPBDAT
&= ~(1 << led
);
547 * returns PCB revision information in b9,b8 and b2,b1,b0
548 * Pre-GTA02 A6 returns 0x000
549 * GTA02 A6 returns 0x101
552 int gta02_get_pcb_revision(void)
554 S3C24X0_GPIO
* const gpio
= S3C24X0_GetBase_GPIO();
558 /* make C13 and C15 pulled-down inputs */
559 gpio
->GPCCON
&= ~0xcc000000;
560 gpio
->GPCUP
&= ~((1 << 13) | (1 << 15));
561 /* D0, D3 and D4 pulled-down inputs */
562 gpio
->GPDCON
&= ~0x000003c3;
563 gpio
->GPDUP
&= ~((1 << 0) | (1 << 3) | (1 << 4));
565 /* delay after changing pulldowns */
569 /* read the version info */
571 n
= (u
>> (13 - 0)) & 0x001;
572 n
|= (u
>> (15 - 1)) & 0x002;
574 n
|= (u
<< (0 + 2)) & 0x004;
576 n
|= (u
<< (8 - 3)) & 0x100;
577 n
|= (u
<< (9 - 4)) & 0x200;
580 * when not being interrogated, all of the revision GPIO
581 * are set to output HIGH without pulldown so no current flows
582 * if they are NC or pulled up.
584 /* make C13 and C15 high ouputs with no pulldowns */
585 gpio
->GPCCON
|= 0x44000000;
586 gpio
->GPCUP
|= (1 << 13) | (1 << 15);
587 gpio
->GPCDAT
|= (1 << 13) | (1 << 15);
588 /* D0, D3 and D4 high ouputs with no pulldowns */
589 gpio
->GPDCON
|= 0x00000141;
590 gpio
->GPDUP
|= (1 << 0) | (1 << 3) | (1 << 4);
591 gpio
->GPDDAT
|= (1 << 0) | (1 << 3) | (1 << 4);