gpb-shadow.patch
[u-boot-openmoko/mini2440.git] / board / neo1973 / gta02 / gta02.c
blob4cc21601197d7d5eec7f69d14cc75f61ffb64b7c
1 /*
2 * (C) 2006-2007 by OpenMoko, Inc.
3 * Author: Harald Welte <laforge@openmoko.org>
5 * based on existing S3C2410 startup code in u-boot:
7 * (C) Copyright 2002
8 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
9 * Marius Groeger <mgroeger@sysgo.de>
11 * (C) Copyright 2002
12 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
14 * See file CREDITS for list of people who contributed to this
15 * project.
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,
30 * MA 02111-1307 USA
33 #include <common.h>
34 #include <s3c2440.h>
35 #include <i2c.h>
36 #include <bootmenu.h>
38 #include "../common/neo1973.h"
39 #include "../common/jbt6k74.h"
41 #include "pcf50633.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 */
51 #define M_PDIV 0x2
52 #define M_SDIV 0x1
54 #define U_M_MDIV 0x38
55 #define U_M_PDIV 0x2
56 #define U_M_SDIV 0x2
57 #else
58 #define M_MDIV 42
59 #define M_PDIV 1
60 #define M_SDIV 0
61 #define U_M_MDIV 88
62 #define U_M_PDIV 4
63 #define U_M_SDIV 2
64 #endif
66 unsigned int neo1973_wakeup_cause;
67 extern unsigned char booted_from_nand;
68 extern unsigned char booted_from_nor;
69 extern int nobootdelay;
70 char __cfg_prompt[20] = "GTA02vXX # ";
73 * In >GTA02v5, use gta02_revision to test for features, not
74 * CONFIG_GTA02_REVISION or CONFIG_ARCH_GTA02_vX !
76 int gta02_revision;
78 static uint16_t gpb_shadow = 0; /* to work around GTA02v5 LED bug */
80 int gta02_get_pcb_revision(void);
82 static inline void delay (unsigned long loops)
84 __asm__ volatile ("1:\n"
85 "subs %0, %1, #1\n"
86 "bne 1b":"=r" (loops):"0" (loops));
89 enum gta02_led {
90 GTA02_LED_PWR_ORANGE = 0,
91 GTA02_LED_PWR_BLUE = 1,
92 GTA02_LED_AUX_RED = 2,
96 * Miscellaneous platform dependent initialisations
99 int board_init(void)
101 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
102 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
104 /* to reduce PLL lock time, adjust the LOCKTIME register */
105 clk_power->LOCKTIME = 0xFFFFFF;
107 /* configure MPLL */
108 clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
110 /* some delay between MPLL and UPLL */
111 delay (4000);
113 /* configure UPLL */
114 clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
116 /* clock divide */
117 clk_power->CLKDIVN = 0x05; /* 1:4:8 */
119 /* some delay between MPLL and UPLL */
120 delay (8000);
122 /* set up the I/O ports */
123 #if CONFIG_GTA02_REVISION == 1
124 gpio->GPACON = 0x007E1FFF;
125 gpio->GPADAT |= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
127 gpio->GPBCON = 0x00155555;
128 gpio->GPBUP = 0x000007FF;
130 gpio->GPCCON = 0x55551155;
131 gpio->GPCUP = 0x0000FFFF;
133 gpio->GPDCON = 0x55555555;
134 gpio->GPDUP = 0x0000FFFF;
136 gpio->GPECON = 0xAAAAAAAA;
137 gpio->GPEUP = 0x0000FFFF;
139 gpio->GPFCON = 0x0000AAAA;
140 gpio->GPFUP = 0x000000FF;
142 gpio->GPGCON = 0x013DFDFA;
143 gpio->GPGUP = 0x0000FFFF;
145 gpio->GPHCON = 0x0028AAAA;
146 gpio->GPHUP = 0x000007FF;
148 gpio->GPJCON = 0x1545541;
149 #elif CONFIG_GTA02_REVISION == 2
150 gpio->GPACON = 0x007E1FFF;
151 gpio->GPADAT |= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
153 gpio->GPBCON = 0x00155555;
154 gpio->GPBUP = 0x000007FF;
156 gpio->GPCCON = 0x55415155;
157 gpio->GPCUP = 0x0000FFFF;
159 gpio->GPDCON = 0x55555555;
160 gpio->GPDUP = 0x0000FFFF;
162 gpio->GPECON = 0xAAAAAAAA;
163 gpio->GPEUP = 0x0000FFFF;
165 gpio->GPFCON = 0x0000AAAA;
166 gpio->GPFUP = 0x000000FF;
168 gpio->GPGCON = 0x0156FE7A;
169 gpio->GPGUP = 0x0000FFFF;
171 gpio->GPHCON = 0x001AAAAA;
172 gpio->GPHUP = 0x000007FF;
174 gpio->GPJCON = 0x1551544;
175 gpio->GPJUP = 0x1ffff;
176 gpio->GPJDAT |= (1 << 4); /* Set GPJ4 to high (nGSM_EN) */
177 #elif CONFIG_GTA02_REVISION >= 3
178 gpio->GPACON = 0x007E5FFF;
179 gpio->GPADAT |= (1 << 16); /* Set GPA16 to high (nNAND_WP) */
181 gpio->GPBCON = 0x00155555;
182 gpio->GPBUP = 0x000007FF;
185 * PCB rev index found on C13, C15, D0, D3 and D4. These are NC or
186 * pulled up by 10K. Therefore to ensure no current flows when they
187 * are not interrogated, we drive them high. When we interrogate them
188 * we make them pulled them down inputs briefly and set them high op
189 * again afterwards.
192 /* pulldown on "PIO_5" BT module to stop float when unpowered
193 * C13 and C15 are b0 and b1 of PCB rev index
195 gpio->GPCCON = 0x55555155;
196 gpio->GPCUP = 0x0000FFFF & ~(1 << 5);
197 gpio->GPCDAT |= (1 << 13) | (1 << 15); /* index detect -> hi */
199 /* D0, D3 and D4 are b2, b3 and b4 of PCB rev index */
200 gpio->GPDCON = 0x55555555;
201 gpio->GPDUP = 0x0000FFFF;
202 gpio->GPDDAT |= (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
204 /* pulldown on GPE11 / SPIMISO0 - goes to debug board and will float */
205 gpio->GPECON = 0xAAAAAAAA;
206 gpio->GPEUP = 0x0000FFFF & ~(1 << 11);
208 /* pulldown on GPF03: TP-4705+debug - debug conn will float */
209 gpio->GPFCON = 0x0000AAAA;
210 gpio->GPFUP = 0x000000FF & ~(1 << 3);
212 gpio->GPGCON = 0x01AAFE79;
213 gpio->GPGUP = 0x0000FFFF;
215 /* pulldown on GPH08: UEXTCLK, just floats!
216 * pulldown GPH0 -- nCTS0 / RTS_MODEM -- floats when GSM off
217 * pulldown GPH3 -- RXD[0] / TX_MODEM -- floats when GSM off
219 gpio->GPHCON = 0x001AAAAA;
220 gpio->GPHUP = 0x000007FF & ~(1 << 8) & ~(1 << 0) & ~(1 << 3);
222 /* pulldown on GPJ00: input, just floats! */
223 /* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
224 gpio->GPJCON = 0x1551544;
225 gpio->GPJUP = 0x1ffff & ~(1 << 0) & ~(1 << 7);
226 gpio->GPJDAT |= (1 << 4) | (1 << 6);
227 /* Set GPJ4 to high (nGSM_EN) */
228 /* Set GPJ6 to high (nDL_GSM) */
229 gpio->GPJDAT &= ~(1 << 5); /* Set GPJ5 to low 3D RST */
230 gpio->GPJDAT &= ~(1 << 5); /* Set GPJ5 to low 3D RST */
232 /* leaving Glamo forced to Reset# active here killed
233 * U-Boot when you touched the memory region
236 gpio->GPJDAT |= (1 << 5); /* Set GPJ5 to high 3D RST */
237 #else
238 #error Please define GTA02 version
239 #endif
241 /* arch number of SMDK2410-Board */
242 gd->bd->bi_arch_number = MACH_TYPE_NEO1973_GTA02;
244 /* adress of boot parameters */
245 gd->bd->bi_boot_params = 0x30000100;
247 icache_enable();
248 dcache_enable();
251 * Since the NOR is replaced by SteppingStone when the AUX button is
252 * released, we have to wait for this and copy our exception vectors
253 * before we can let u-boot enable interrupts.
255 if (booted_from_nor) {
256 extern char _start;
258 while (neo1973_aux_key_pressed());
259 memcpy((void *) 0, &_start, 0x40);
262 return 0;
265 static void set_revision(void)
267 int rev = gta02_get_pcb_revision();
268 char buf[32];
270 if (CONFIG_GTA02_REVISION < 5)
271 gta02_revision = CONFIG_GTA02_REVISION;
272 else {
273 switch (rev) {
274 case 0x000:
275 gta02_revision = 5;
276 break;
277 case 0x001:
278 gta02_revision = 6;
279 break;
280 default:
281 printf("Unrecognized hardware revision 0x%03x. "
282 "Defaulting to GTA02v6.\n", rev);
283 gta02_revision = 6;
286 sprintf(__cfg_prompt, "GTA02v%d # ", gta02_revision);
288 #if 1 /* remove these after checking that Andy doesn't need them anymore */
289 printf("PCB rev: 0x%03X\n", rev);
290 /* expose in the env so we can add to kernel commandline */
291 sprintf(buf, "0x%03X", rev);
292 setenv("pcb_rev", buf);
293 #endif
296 int board_late_init(void)
298 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
299 uint8_t int1, int2;
300 char buf[32];
301 int menu_vote = 0; /* <= 0: no, > 0: yes */
302 int seconds = 0;
304 set_revision();
306 /* Initialize the Power Management Unit with a safe register set */
307 pcf50633_init();
309 /* obtain wake-up reason */
310 int1 = pcf50633_reg_read(PCF50633_REG_INT1);
311 int2 = pcf50633_reg_read(PCF50633_REG_INT2);
313 /* switch on one of the power led's */
314 neo1973_led(GTA02_LED_PWR_ORANGE, 1);
316 /* issue a short pulse with the vibrator */
317 neo1973_vibrator(1);
318 udelay(20000);
319 neo1973_vibrator(0);
321 #if defined(CONFIG_ARCH_GTA02_v1)
322 /* Glamo3362 reset and power cycle */
323 gpio->GPJDAT &= ~0x000000001; /* GTA02v1_GPIO_3D_RESET */
324 pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0);
325 udelay(50*1000);
326 pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0x2);
327 gpio->GPJDAT |= 0x000000001; /* GTA02v1_GPIO_3D_RESET */
328 #endif
330 /* if there's no other reason, must be regular reset */
331 neo1973_wakeup_cause = NEO1973_WAKEUP_RESET;
333 if (!booted_from_nand && !booted_from_nor)
334 goto woken_by_reset;
336 /* save wake-up reason in environment */
337 sprintf(buf, "0x%02x", int1);
338 setenv("pcf50633_int1", buf);
339 sprintf(buf, "0x%02x", int2);
340 setenv("pcf50633_int2", buf);
342 if (int1 & PCF50633_INT1_ALARM) {
343 /* we've been woken up by RTC alarm, boot */
344 neo1973_wakeup_cause = NEO1973_WAKEUP_ALARM;
345 goto continue_boot;
347 if (int1 & PCF50633_INT1_USBINS) {
348 /* we've been woken up by charger insert */
349 neo1973_wakeup_cause = NEO1973_WAKEUP_CHARGER;
352 if (int2 & PCF50633_INT2_ONKEYF) {
353 /* we've been woken up by a falling edge of the onkey */
354 neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY;
357 if (neo1973_wakeup_cause == NEO1973_WAKEUP_CHARGER) {
358 /* if we still think it was only a charger insert, boot */
359 goto continue_boot;
362 woken_by_reset:
364 while (neo1973_wakeup_cause == NEO1973_WAKEUP_RESET ||
365 neo1973_on_key_pressed()) {
366 if (neo1973_aux_key_pressed())
367 menu_vote++;
368 else
369 menu_vote--;
371 if (neo1973_new_second())
372 seconds++;
373 if (seconds >= POWER_KEY_SECONDS)
374 goto continue_boot;
376 /* Power off if minimum number of seconds not reached */
377 neo1973_poweroff();
379 continue_boot:
380 jbt6k74_init();
381 jbt6k74_enter_state(JBT_STATE_NORMAL);
382 jbt6k74_display_onoff(1);
384 #if 0
386 /* check if sd card is inserted, and power-up if it is */
387 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
388 if (!(gpio->GPFDAT & (1 << 5)))
389 gpio->GPBDAT &= ~(1 << 2);
391 #endif
393 if (menu_vote > 0 || booted_from_nor) {
394 extern struct bootmenu_setup bootmenu_setup;
396 if (booted_from_nand)
397 bootmenu_setup.comment = "NAND";
398 if (booted_from_nor)
399 bootmenu_setup.comment = "NOR";
400 neo1973_bootmenu();
401 nobootdelay = 1;
404 return 0;
407 int dram_init (void)
409 gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
410 gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
412 return 0;
415 u_int32_t get_board_rev(void)
417 return 0x300+0x10*gta02_revision;
420 void neo1973_poweroff(void)
422 printf("poweroff\n");
423 udc_disconnect();
424 pcf50633_reg_write(PCF50633_REG_OOCSHDWN, 0x01);
425 /* don't return to caller */
426 while (1) ;
429 void neo1973_backlight(int on)
431 if (on)
432 pcf50633_reg_write(PCF50633_REG_LEDENA, 0x01);
433 else
434 pcf50633_reg_write(PCF50633_REG_LEDENA, 0x00);
437 /* FIXME: shared */
438 void neo1973_vibrator(int on)
440 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
441 if (on)
442 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
443 gpio->GPGDAT |= (1 << 11); /* GPG11 */
444 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
445 gpio->GPBDAT |= (1 << 10); /* GPB10 */
446 #else
447 gpio->GPBDAT |= (1 << 3); /* GPB3 */
448 #endif
449 else
450 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
451 gpio->GPGDAT &= ~(1 << 11); /* GPG11 */
452 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
453 gpio->GPBDAT &= ~(1 << 10); /* GPB10 */
454 #else
455 gpio->GPBDAT &= ~(1 << 3); /* GPB3 */
456 #endif
457 gpio->GPBDAT |= gpb_shadow;
460 void neo1973_gsm(int on)
462 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
464 /* GPIO2 of PMU, GPB7(MODEM_ON)=1 and GPB5(MODEM_RST)=0 */
465 if (on) {
466 #if !defined(CONFIG_ARCH_GTA02_v1)
467 pcf50633_reg_write(PCF50633_REG_GPIO2CFG, 0x07);
468 #endif
469 gpio->GPBDAT &= ~(1 << 5); /* GTA02_GPIO_MODEM_RST */
470 gpio->GPBDAT |= (1 << 7); /* GTA02_GPIO_MODEM_ON */
471 gpio->GPJDAT &= ~(1 << 6); /* GTA02_GPIO_nDL_GSM */
472 } else {
473 gpio->GPBDAT &= ~(1 << 7); /* GTA02_GPIO_MODEM_ON */
474 #if !defined(CONFIG_ARCH_GTA02_v1)
475 pcf50633_reg_write(PCF50633_REG_GPIO2CFG, 0x00);
476 #endif
477 gpio->GPJDAT |= (1 << 6); /* GTA02_GPIO_nDL_GSM */
481 void neo1973_gps(int on)
483 if (on)
484 pcf50633_reg_write(PCF50633_REG_LDO5ENA, 0x01);
485 else
486 pcf50633_reg_write(PCF50633_REG_LDO5ENA, 0x00);
489 static int pwr_int_pending(void)
491 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
493 return !(gpio->GPGDAT & (1 << 1)); /* EINT9/GPG1 */
496 static int have_int(uint8_t mask1, uint8_t mask2)
498 static uint8_t pending1 = 0, pending2 = 0;
500 if (pwr_int_pending()) {
502 * We retrieve all interupts, so that we clear any stray ones
503 * in INT2 and INT3.
505 uint8_t ints[5];
506 int i;
508 for (i = 0; i != 5; i++)
509 ints[i] = pcf50633_reg_read(PCF50633_REG_INT1+i);
510 pending1 |= ints[0];
511 pending2 |= ints[1];
513 if (pending1 & mask1) {
514 pending1 &= ~mask1;
515 return 1;
517 if (pending2 & mask2) {
518 pending1 &= ~mask2;
519 return 1;
521 return 0;
524 int neo1973_new_second(void)
526 return have_int(PCF50633_INT1_SECOND, 0);
529 int neo1973_on_key_pressed(void)
531 static int pressed = -1;
533 if (pressed == -1 ||
534 have_int(0, PCF50633_INT2_ONKEYF | PCF50633_INT2_ONKEYR))
535 pressed = !(pcf50633_reg_read(PCF50633_REG_OOCSTAT) &
536 PCF50633_OOCSTAT_ONKEY);
537 return pressed;
540 int neo1973_aux_key_pressed(void)
542 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
544 return !!(gpio->GPFDAT & (1 << 6));
547 /* The sum of all part_size[]s must equal to or greater than the NAND size,
548 i.e., 0x10000000. */
550 unsigned int dynpart_size[] = {
551 CFG_UBOOT_SIZE, CFG_ENV_SIZE, 0x800000, 0xa0000, 0x40000, 0x10000000, 0 };
552 char *dynpart_names[] = {
553 "u-boot", "u-boot_env", "kernel", "splash", "factory", "rootfs", NULL };
556 const char *neo1973_get_charge_status(void)
558 /* FIXME */
559 return pcf50633_charger_state();
562 int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd)
564 /* FIXME */
565 puts("not implemented yet\n");
566 return -1;
569 void neo1973_led(int led, int on)
571 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
573 printf("switching led %u %u\n", led, on);
574 if (led > 2)
575 return;
577 if (on) {
578 gpb_shadow |= (1 << led);
579 gpio->GPBDAT |= gpb_shadow;
581 else {
582 gpb_shadow &= ~(1 << led);
583 gpio->GPBDAT = (gpio->GPBDAT | gpb_shadow) & ~(1 << led);
588 * returns PCB revision information in b9,b8 and b2,b1,b0
589 * Pre-GTA02 A6 returns 0x000
590 * GTA02 A6 returns 0x001
593 int gta02_get_pcb_revision(void)
595 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
596 int n;
597 u32 u;
599 /* make C13 and C15 pulled-down inputs */
600 gpio->GPCCON &= ~0xcc000000;
601 gpio->GPCUP &= ~((1 << 13) | (1 << 15));
602 /* D0, D3 and D4 pulled-down inputs */
603 gpio->GPDCON &= ~0x000003c3;
604 gpio->GPDUP &= ~((1 << 0) | (1 << 3) | (1 << 4));
606 /* delay after changing pulldowns */
607 u = gpio->GPCDAT;
608 u = gpio->GPDDAT;
610 /* read the version info */
611 u = gpio->GPCDAT;
612 n = (u >> (13 - 0)) & 0x001;
613 n |= (u >> (15 - 1)) & 0x002;
614 u = gpio->GPDDAT;
615 n |= (u << (0 + 2)) & 0x004;
617 n |= (u << (8 - 3)) & 0x100;
618 n |= (u << (9 - 4)) & 0x200;
621 * when not being interrogated, all of the revision GPIO
622 * are set to output HIGH without pulldown so no current flows
623 * if they are NC or pulled up.
625 /* make C13 and C15 high ouputs with no pulldowns */
626 gpio->GPCCON |= 0x44000000;
627 gpio->GPCUP |= (1 << 13) | (1 << 15);
628 gpio->GPCDAT |= (1 << 13) | (1 << 15);
629 /* D0, D3 and D4 high ouputs with no pulldowns */
630 gpio->GPDCON |= 0x00000141;
631 gpio->GPDUP |= (1 << 0) | (1 << 3) | (1 << 4);
632 gpio->GPDDAT |= (1 << 0) | (1 << 3) | (1 << 4);
634 return n;