U-Boot GTA02: Always enable charger on startup
[u-boot.git] / board / neo1973 / gta02 / gta02.c
1 /*
2  * (C) 2006-2007 by OpenMoko, Inc.
3  * Author: Harald Welte <laforge@openmoko.org>
4  *
5  * based on existing S3C2410 startup code in u-boot:
6  *
7  * (C) Copyright 2002
8  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
9  * Marius Groeger <mgroeger@sysgo.de>
10  *
11  * (C) Copyright 2002
12  * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
13  *
14  * See file CREDITS for list of people who contributed to this
15  * project.
16  *
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.
21  *
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.
26  *
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
31  */
32
33 #include <common.h>
34 #include <s3c2440.h>
35 #include <i2c.h>
36 #include <bootmenu.h>
37 #include <asm/atomic.h>
38
39 #include "../common/neo1973.h"
40 #include "../common/jbt6k74.h"
41
42 #include "pcf50633.h"
43
44 DECLARE_GLOBAL_DATA_PTR;
45
46 /* That many seconds the power key needs to be pressed to power up */
47 #define POWER_KEY_SECONDS       1
48
49 /* If the battery voltage is below this, we can't provide stable power */
50 #define SAFE_POWER_MILLIVOLT    3400
51
52 #if defined(CONFIG_ARCH_GTA02_v1)
53 //#define M_MDIV        0x7f            /* Fout = 405.00MHz */
54 #define M_MDIV  0x7d            /* Fout = 399.00MHz */
55 #define M_PDIV  0x2
56 #define M_SDIV  0x1
57
58 #define U_M_MDIV        0x38
59 #define U_M_PDIV        0x2
60 #define U_M_SDIV        0x2
61 #else
62 #define M_MDIV 42
63 #define M_PDIV 1
64 #define M_SDIV 0
65 #define U_M_MDIV 88
66 #define U_M_PDIV 4
67 #define U_M_SDIV 2
68 #endif
69
70 extern void smedia3362_lcm_reset(int);
71 extern void glamo_core_init(void);
72
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 extern int udc_usb_maxcurrent;
78
79 char __cfg_prompt[20] = "GTA02vXX # ";
80
81 /*
82  * In >GTA02v5, use gta02_revision to test for features, not
83  * CONFIG_GTA02_REVISION or CONFIG_ARCH_GTA02_vX !
84  */
85 int gta02_revision;
86
87 static uint16_t gpb_shadow = 0; /* to work around GTA02v5 LED bug */
88
89 int gta02_get_pcb_revision(void);
90
91 static inline void delay (unsigned long loops)
92 {
93         __asm__ volatile ("1:\n"
94           "subs %0, %1, #1\n"
95           "bne 1b":"=r" (loops):"0" (loops));
96 }
97
98 enum gta02_led {
99         GTA02_LED_PWR_ORANGE    = 0,
100         GTA02_LED_PWR_BLUE      = 1,
101         GTA02_LED_AUX_RED       = 2,
102 };
103
104 /*
105  * Miscellaneous platform dependent initialisations
106  */
107
108 static void cpu_speed(int mdiv, int pdiv, int sdiv, int clkdivn)
109 {
110         S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
111
112         /* clock divide */
113         clk_power->CLKDIVN = clkdivn;
114
115         /* to reduce PLL lock time, adjust the LOCKTIME register */
116         clk_power->LOCKTIME = 0xFFFFFF;
117
118         /* configure MPLL */
119         clk_power->MPLLCON = ((mdiv << 12) + (pdiv << 4) + sdiv);
120
121         /* some delay between MPLL and UPLL */
122         delay (4000);
123
124         /* configure UPLL */
125         clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
126
127         /* some delay between MPLL and UPLL */
128         delay (8000);
129 }
130
131 int board_init(void)
132 {
133         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
134
135         /* FCLK = 200MHz values from cpu/arm920t/start.S */
136         cpu_speed(142, 7, 1, 3); /* 200MHZ, 1:2:4 */
137
138         /* set up the I/O ports */
139 #if CONFIG_GTA02_REVISION == 1
140         gpio->GPACON = 0x007E1FFF;
141         gpio->GPADAT |= (1 << 16);      /* Set GPA16 to high (nNAND_WP) */
142
143         gpio->GPBCON = 0x00155555;
144         gpio->GPBUP = 0x000007FF;
145
146         gpio->GPCCON = 0x55551155;
147         gpio->GPCUP = 0x0000FFFF;
148
149         gpio->GPDCON = 0x55555555;
150         gpio->GPDUP = 0x0000FFFF;
151
152         gpio->GPECON = 0xAAAAAAAA;
153         gpio->GPEUP = 0x0000FFFF;
154
155         gpio->GPFCON = 0x0000AAAA;
156         gpio->GPFUP = 0x000000FF;
157
158         gpio->GPGCON = 0x013DFDFA;
159         gpio->GPGUP = 0x0000FFFF;
160
161         gpio->GPHCON = 0x0028AAAA;
162         gpio->GPHUP = 0x000007FF;
163
164         gpio->GPJCON = 0x1545541;
165 #elif CONFIG_GTA02_REVISION == 2
166         gpio->GPACON = 0x007E1FFF;
167         gpio->GPADAT |= (1 << 16);      /* Set GPA16 to high (nNAND_WP) */
168
169         gpio->GPBCON = 0x00155555;
170         gpio->GPBUP = 0x000007FF;
171
172         gpio->GPCCON = 0x55415155;
173         gpio->GPCUP = 0x0000FFFF;
174
175         gpio->GPDCON = 0x55555555;
176         gpio->GPDUP = 0x0000FFFF;
177
178         gpio->GPECON = 0xAAAAAAAA;
179         gpio->GPEUP = 0x0000FFFF;
180
181         gpio->GPFCON = 0x0000AAAA;
182         gpio->GPFUP = 0x000000FF;
183
184         gpio->GPGCON = 0x0156FE7A;
185         gpio->GPGUP = 0x0000FFFF;
186
187         gpio->GPHCON = 0x001AAAAA;
188         gpio->GPHUP = 0x000007FF;
189
190         gpio->GPJCON = 0x1551544;
191         gpio->GPJUP = 0x1ffff;
192         gpio->GPJDAT |= (1 << 4);       /* Set GPJ4 to high (nGSM_EN) */
193 #elif CONFIG_GTA02_REVISION >= 3
194         gpio->GPACON = 0x007E5FFF;
195         gpio->GPADAT |= (1 << 16);      /* Set GPA16 to high (nNAND_WP) */
196
197         gpio->GPBCON = 0x00155555;
198         gpio->GPBUP = 0x000007FF;
199
200         /*
201          * PCB rev index found on C13, C15, D0, D3 and D4.  These are NC or
202          * pulled up by 10K.  Therefore to ensure no current flows when they
203          * are not interrogated, we drive them high.  When we interrogate them
204          * we make them pulled them down inputs briefly and set them high op
205          * again afterwards.
206          */
207
208         /* pulldown on "PIO_5" BT module to stop float when unpowered
209          * C13 and C15 are b0 and b1 of PCB rev index
210          */
211         gpio->GPCCON = 0x55555155;
212         gpio->GPCUP = 0x0000FFFF & ~(1 << 5);
213         gpio->GPCDAT |= (1 << 13) | (1 << 15); /* index detect -> hi */
214
215         /* D0, D3 and D4 are b2, b3 and b4 of PCB rev index */
216         gpio->GPDCON = 0x55555555;
217         gpio->GPDUP = 0x0000FFFF;
218         gpio->GPDDAT |= (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
219
220         /* pulldown on GPE11 / SPIMISO0 - goes to debug board and will float */
221         gpio->GPECON = 0xAAAAAAAA;
222         gpio->GPEUP = 0x0000FFFF & ~(1 << 11);
223
224         /* pulldown on GPF03: TP-4705+debug - debug conn will float */
225         gpio->GPFCON = 0x0000AAAA;
226         gpio->GPFUP = 0x000000FF & ~(1 << 3);
227
228         gpio->GPGCON = 0x01AAFE79;
229         gpio->GPGUP = 0x0000FFFF;
230
231         /* pulldown on GPH08: UEXTCLK, just floats!
232          * pulldown GPH0 -- nCTS0 / RTS_MODEM -- floats when GSM off
233          * pulldown GPH3 -- RXD[0] / TX_MODEM -- floats when GSM off
234          */
235         gpio->GPHCON = 0x001AAAAA;
236         gpio->GPHUP = 0x000007FF & ~(1 << 8) & ~(1 << 0) & ~(1 << 3);
237
238         /* pulldown on GPJ00: input, just floats! */
239         /* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
240         gpio->GPJCON = 0x1551544;
241         gpio->GPJUP = 0x1ffff & ~(1 << 0) & ~(1 << 7);
242         gpio->GPJDAT |= (1 << 4) | (1 << 6);
243                                         /* Set GPJ4 to high (nGSM_EN) */
244                                         /* Set GPJ6 to high (nDL_GSM) */
245         gpio->GPJDAT &= ~(1 << 5);      /* Set GPJ5 to low 3D RST */
246         gpio->GPJDAT &= ~(1 << 5);      /* Set GPJ5 to low 3D RST */
247
248         /* leaving Glamo forced to Reset# active here killed
249          * U-Boot when you touched the memory region
250          */
251
252         gpio->GPJDAT |= (1 << 5);       /* Set GPJ5 to high 3D RST */
253 #else
254 #error Please define GTA02 version
255 #endif
256
257         /* arch number of SMDK2410-Board */
258         gd->bd->bi_arch_number = MACH_TYPE_NEO1973_GTA02;
259
260         /* adress of boot parameters */
261         gd->bd->bi_boot_params = 0x30000100;
262
263         icache_enable();
264         dcache_enable();
265
266         /*
267          * Since the NOR at address 0 is replaced by SteppingStone when the AUX
268          * button is released, we would crash when an interrupt arrives (e.g.,
269          * on USB insertion).
270          *
271          * We solve this as follows: we copy the vector table to RAM at address
272          * 0x30000000 and then use the PID feature in the 920T MMU to map all
273          * addresses in the range 0x0....... to 0x3....... without actually
274          * setting up page mappings in the MMU. Thus, vectors are then
275          * retrieved from their location in RAM.
276          *
277          * Note that the mapping is done in lib_arm/interrupts.c, so that it
278          * automatically tracks whether we allow interrupts or not. This is
279          * particularly necessary when we boot, since the operating system may
280          * not expect to find this sort of mapping to be active.
281          */
282 #ifdef CONFIG_GTA02_REVISION
283         {
284                 extern char _start;
285
286                 memcpy((void *) 0x30000000, &_start, 0x40);
287         }
288 #endif
289         return 0;
290 }
291
292 static void set_revision(void)
293 {
294         int rev = gta02_get_pcb_revision();
295         char buf[32];
296
297         if (CONFIG_GTA02_REVISION < 5)
298                 gta02_revision = CONFIG_GTA02_REVISION;
299         else {
300                 switch (rev) {
301                 case 0x000:
302                         gta02_revision = 5;
303                         break;
304                 case 0x001:
305                         gta02_revision = 6;
306                         break;
307                 default:
308                         printf("Unrecognized hardware revision 0x%03x. "
309                             "Defaulting to GTA02v6.\n", rev);
310                         gta02_revision = 6;
311                 }
312         }
313         sprintf(__cfg_prompt, "GTA02v%d # ", gta02_revision);
314
315 #if 1 /* remove these after checking that Andy doesn't need them anymore */
316         printf("PCB rev: 0x%03X\n", rev);
317         /* expose in the env so we can add to kernel commandline */
318         sprintf(buf, "0x%03X", rev);
319         setenv("pcb_rev", buf);
320 #endif
321 }
322
323 static void poll_charger(void)
324 {
325         if (pcf50633_read_charger_type() == 1000)
326                 pcf50633_usb_maxcurrent(1000);
327         else /* track what the time-critical udc callback allows us */
328                 if (pcf50633_usb_last_maxcurrent != udc_usb_maxcurrent)
329                         pcf50633_usb_maxcurrent(udc_usb_maxcurrent);
330 }
331
332 static int have_int(uint8_t mask1, uint8_t mask2);
333
334 static void clear_pmu_int(void)
335 {
336         S3C24X0_INTERRUPT * const intr = S3C24X0_GetBase_INTERRUPT();
337         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
338
339         /* read the PMU's interrupt register and store what we found for later
340            use */
341         have_int(0, 0);
342
343         /* clear EINT9/GPG1 in the MCU's interrupt path */
344         gpio->EINTPEND = 1 << 9;
345         intr->SRCPND = BIT_EINT8_23;
346         intr->INTPND = BIT_EINT8_23;
347 }
348
349 static void cpu_idle(void)
350 {
351         S3C24X0_INTERRUPT * const intr = S3C24X0_GetBase_INTERRUPT();
352         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
353         S3C24X0_CLOCK_POWER * const clk = S3C24X0_GetBase_CLOCK_POWER();
354         unsigned long flags;
355
356         /*
357          * We don't want to execute interrupts throughout all this, since
358          * u-boot's interrupt handling code isn't modular, and getting a "real"
359          * interrupt without clearing it in the interrupt handler would cause
360          * us to loop permanently.
361          */
362         local_irq_save(flags);
363
364         /* enable PMU interrupts */
365         intr->INTMSK &= ~BIT_EINT8_23;
366         gpio->EINTMASK &= ~(1 << 9);
367
368         /* go idle */
369         clk->CLKCON |= 1 << 2;
370
371          /* disable PMU interrupts */
372         intr->INTMSK |= BIT_EINT8_23;
373         gpio->EINTMASK |= 1 << 9;
374
375         /* collect PMU interrupts and clear them */
376         clear_pmu_int();
377
378         /* we're safe now */
379         local_irq_restore(flags);
380 }
381
382 static int charger_is_present(void)
383 {
384         /* is charger or power adapter present? */
385         return  !!(pcf50633_reg_read(PCF50633_REG_MBCS1) & 3);
386 }
387
388 static int battery_is_present(void)
389 {
390         /* battery less than bvmlvl -> don't boot */
391         return !(pcf50633_reg_read(PCF50633_REG_BVMCTL) & 1);
392 }
393
394 static int battery_is_good(void)
395 {
396         /* battery is absent -> don't boot */
397         if (!battery_is_present())
398                 return 0;
399
400         /* we could try to boot, but we'll probably die on the way */
401         if (pcf50633_read_battvolt() < SAFE_POWER_MILLIVOLT)
402                 return 0;
403
404         return 1;
405 }
406
407 static int wait_for_power(void)
408 {
409         /*
410          * TODO: this function should also check if charger is still attached
411          * it makes no sense to wait otherwise.
412         */
413
414         int seconds = 0;
415         int led_cycle = 1;
416         int power = 1;
417
418         while (1) {
419                 poll_charger();
420
421                 /* we have plenty of external power but no visible battery ->
422                  * don't hang around trying to charge, try to boot */
423                 if (!battery_is_present() && (pcf50633_usb_last_maxcurrent >= 500))
424                         break;
425
426                 /* cpu_idle sits with interrupts off destroying USB operation
427                  * don't run it unless we are in trouble
428                  */
429                 if (!battery_is_good())
430                         cpu_idle();
431                 else
432                         udelay(1000000);
433
434                 if (neo1973_new_second()) {
435                         /*
436                          * Probe the battery only if the current LED cycle is
437                          * about to end, so that it had time to discharge.
438                          */
439                         if (led_cycle && battery_is_good())
440                                 break;
441
442                         /* check if charger is present, otherwise stop start up */
443                         if (!charger_is_present()) {
444                                 power = 0;
445                                 break;
446                         }
447                         seconds++;
448                 }
449
450                 led_cycle = !seconds || (seconds & 1);
451
452                 /*
453                  * Blink the AUX LED, unless it's broken (which is the case in
454                  * GTA02v5 it is) and draws excessive current, which we just
455                  * can't afford in this delicate situation.
456                  */
457                 if (gta02_revision > 5)
458                         neo1973_led(GTA02_LED_AUX_RED, led_cycle);
459
460                 /* alternate LED and charger cycles */
461                 pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, !led_cycle);
462
463                 /* cancel shutdown timer to keep charging
464                  * it can get triggered by lowvsys along the way but if it
465                  * didn't kill us then don't let it kill us later
466                  */
467                 pcf50633_reg_write(PCF50633_REG_OOCSHDWN, 4);
468         }
469
470         /* switch off the AUX LED */
471         neo1973_led(GTA02_LED_AUX_RED, 0);
472
473         /* do we have power now? */
474         return power;
475 }
476
477 static void pcf50633_late_init(void)
478 {
479 #ifdef CONFIG_ARCH_GTA02_v1
480         uint8_t pwren = 1;      /* always on */
481         uint8_t recent = 0;     /* antiques don't have that */
482 #else
483         uint8_t pwren = 2;      /* enabled if GPIO1 = HIGH */
484         uint8_t recent = 1;     /* always on */
485 #endif
486
487         pcf50633_reg_write(PCF50633_REG_LDO1ENA, pwren);
488         pcf50633_reg_write(PCF50633_REG_LDO2ENA, 2); /* enabled if GPIO1 = H */
489         pcf50633_reg_write(PCF50633_REG_LDO5ENA, recent);
490         pcf50633_reg_write(PCF50633_REG_LDO6ENA, recent);
491
492         pcf50633_reg_write(PCF50633_REG_MBCC5, 0xff); /* 1A USB fast charge */
493
494         pcf50633_reg_set_bit_mask(PCF50633_REG_MBCC1, 1, 1); /* charge ! */
495 }
496
497 int board_late_init(void)
498 {
499         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
500         uint8_t int1, int2;
501         char buf[32];
502         int menu_vote = 0; /* <= 0: no, > 0: yes */
503         int seconds = 0;
504         int enter_bootmenu;
505         char *env_stop_in_menu;
506
507         set_revision();
508
509         /* Initialize the Power Management Unit with a safe register set */
510         pcf50633_init();
511
512         /* obtain wake-up reason */
513         int1 = pcf50633_reg_read(PCF50633_REG_INT1);
514         int2 = pcf50633_reg_read(PCF50633_REG_INT2);
515
516         /* if there's no other reason, must be regular reset */
517         neo1973_wakeup_cause = NEO1973_WAKEUP_RESET;
518
519         if (!booted_from_nand && !booted_from_nor)
520                 goto woken_by_reset;
521
522         /* save wake-up reason in environment */
523         sprintf(buf, "0x%02x", int1);
524         setenv("pcf50633_int1", buf);
525         sprintf(buf, "0x%02x", int2);
526         setenv("pcf50633_int2", buf);
527
528         if (int1 & PCF50633_INT1_ALARM) {
529                 /* we've been woken up by RTC alarm, boot */
530                 neo1973_wakeup_cause = NEO1973_WAKEUP_ALARM;
531                 goto continue_boot;
532         }
533         if (int1 & PCF50633_INT1_USBINS) {
534                 /* we've been woken up by charger insert */
535                 neo1973_wakeup_cause = NEO1973_WAKEUP_CHARGER;
536         }
537
538         if (int2 & PCF50633_INT2_ONKEYF) {
539                 /* we've been woken up by a falling edge of the onkey */
540                 neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY;
541         }
542
543         if (neo1973_wakeup_cause == NEO1973_WAKEUP_CHARGER) {
544                 /* if we still think it was only a charger insert, boot */
545                 goto continue_boot;
546         }
547
548 woken_by_reset:
549
550         while (neo1973_wakeup_cause == NEO1973_WAKEUP_RESET ||
551             neo1973_on_key_pressed()) {
552
553         if (neo1973_aux_key_pressed())
554                         menu_vote++;
555                 else
556                         menu_vote--;
557
558                 if (neo1973_new_second())
559                         seconds++;
560                 if (seconds >= POWER_KEY_SECONDS)
561                         goto continue_boot;
562         }
563         /* Power off if minimum number of seconds not reached */
564         neo1973_poweroff();
565
566 continue_boot:
567         /* Power off if no battery is present and only 100mA is available */
568         if (!wait_for_power())
569                 neo1973_poweroff();
570
571         pcf50633_late_init();
572         cpu_speed(M_MDIV, M_PDIV, M_SDIV, 5); /* 400MHZ, 1:4:8 */
573
574         /* issue a short pulse with the vibrator */
575         neo1973_led(GTA02_LED_AUX_RED, 1);
576         neo1973_vibrator(1);
577         udelay(20000);
578         neo1973_led(GTA02_LED_AUX_RED, 0);
579         neo1973_vibrator(0);
580
581 #if defined(CONFIG_ARCH_GTA02_v1)
582         /* Glamo3362 reset and power cycle */
583         gpio->GPJDAT &= ~0x000000001;   /* GTA02v1_GPIO_3D_RESET */
584         pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0);
585         udelay(50*1000);
586         pcf50633_reg_write(PCF50633_REG_DOWN2ENA, 0x2);
587         gpio->GPJDAT |= 0x000000001;    /* GTA02v1_GPIO_3D_RESET */
588 #endif
589
590         env_stop_in_menu = getenv("stop_in_menu");
591         /* If the stop_in_menu environment variable is set, enter the
592          * boot menu */
593         if (env_stop_in_menu && strcmp(env_stop_in_menu, "yes") == 0)
594                 menu_vote = 1;
595
596         enter_bootmenu = menu_vote > 0 || booted_from_nor;
597         glamo_core_init();
598         smedia3362_lcm_reset(1);
599         if (!enter_bootmenu && getenv("splashimage"))
600                 run_command(getenv("splashimage"), 0);
601         jbt6k74_init();
602         jbt6k74_enter_state(JBT_STATE_NORMAL);
603         jbt6k74_display_onoff(1);
604         /* switch on the backlight */
605         neo1973_backlight(1);
606
607 #if 0
608         {
609                 /* check if sd card is inserted, and power-up if it is */
610                 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
611                 if (!(gpio->GPFDAT & (1 << 5)))
612                         gpio->GPBDAT &= ~(1 << 2);
613         }
614 #endif
615
616         if (enter_bootmenu) {
617                 extern struct bootmenu_setup bootmenu_setup;
618
619                 if (booted_from_nand)
620                         bootmenu_setup.comment = "NAND";
621                 if (booted_from_nor)
622                         bootmenu_setup.comment = "NOR";
623                 neo1973_bootmenu();
624                 nobootdelay = 1;
625         }
626
627         return 0;
628 }
629
630 int dram_init (void)
631 {
632         gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
633         gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
634
635         return 0;
636 }
637
638 u_int32_t get_board_rev(void)
639 {
640         return 0x300+0x10*gta02_revision;
641 }
642
643 void neo1973_poweroff(void)
644 {
645         printf("poweroff\n");
646         udc_disconnect();
647         pcf50633_reg_write(PCF50633_REG_OOCSHDWN, 0x01);
648         /* don't return to caller */
649         while (1) ;
650 }
651
652 void neo1973_backlight(int on)
653 {
654         if (on) {
655                 /* pcf50633 manual p60
656                  * "led_out should never be set to 000000, as this would result
657                  * in a deadlock making it impossible to program another value.
658                  * If led_out should be inadvertently set to 000000, the
659                  * LEDOUT register can be reset by disabling and enabling the
660                  * LED converter via control bit led_on in the LEDENA register"
661                  */
662                 pcf50633_reg_write(PCF50633_REG_LEDENA, 0x00);
663                 pcf50633_reg_write(PCF50633_REG_LEDENA, 0x01);
664                 pcf50633_reg_write(PCF50633_REG_LEDOUT, 0x3f);
665         } else
666                 pcf50633_reg_write(PCF50633_REG_LEDENA, 0x00);
667 }
668
669 /* FIXME: shared */
670 void neo1973_vibrator(int on)
671 {
672         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
673         if (on)
674 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
675                 gpio->GPGDAT |= (1 << 11);      /* GPG11 */
676 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
677                 gpio->GPBDAT |= (1 << 10);      /* GPB10 */
678 #else
679                 gpio->GPBDAT |= (1 << 3);       /* GPB3 */
680 #endif
681         else
682 #if defined(CONFIG_ARCH_GTA01_v3) || defined(CONFIG_ARCH_GTA01_v4)
683                 gpio->GPGDAT &= ~(1 << 11);     /* GPG11 */
684 #elif defined(CONFIG_ARCH_GTA01B_v2) || defined(CONFIG_ARCH_GTA01B_v3)
685                 gpio->GPBDAT &= ~(1 << 10);     /* GPB10 */
686 #else
687                 gpio->GPBDAT &= ~(1 << 3);      /* GPB3 */
688 #endif
689         gpio->GPBDAT |= gpb_shadow;
690 }
691
692 void neo1973_gsm(int on)
693 {
694         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
695
696         /* GPIO2 of PMU, GPB7(MODEM_ON)=1 and GPB5(MODEM_RST)=0 */
697         if (on) {
698 #if !defined(CONFIG_ARCH_GTA02_v1)
699                 pcf50633_reg_write(PCF50633_REG_GPIO2CFG, 0x07);
700 #endif
701                 gpio->GPBDAT &= ~(1 << 5);      /* GTA02_GPIO_MODEM_RST */
702                 gpio->GPBDAT |= (1 << 7);       /* GTA02_GPIO_MODEM_ON */
703                 gpio->GPJDAT &= ~(1 << 6);      /* GTA02_GPIO_nDL_GSM */
704         } else {
705                 gpio->GPBDAT &= ~(1 << 7);      /* GTA02_GPIO_MODEM_ON */
706 #if !defined(CONFIG_ARCH_GTA02_v1)
707                 pcf50633_reg_write(PCF50633_REG_GPIO2CFG, 0x00);
708 #endif
709                 gpio->GPJDAT |= (1 << 6);       /* GTA02_GPIO_nDL_GSM */
710         }
711 }
712
713 void neo1973_gps(int on)
714 {
715         if (on)
716                 pcf50633_reg_write(PCF50633_REG_LDO5ENA, 0x01);
717         else
718                 pcf50633_reg_write(PCF50633_REG_LDO5ENA, 0x00);
719 }
720
721 static int pwr_int_pending(void)
722 {
723         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
724
725         return !(gpio->GPGDAT & (1 << 1));      /* EINT9/GPG1 */
726 }
727
728 static int have_int(uint8_t mask1, uint8_t mask2)
729 {
730         static uint8_t pending1 = 0, pending2 = 0;
731
732         if (pwr_int_pending()) {
733                 /*
734                  * We retrieve all interupts, so that we clear any stray ones
735                  * in INT2 and INT3.
736                  */
737                 uint8_t ints[5];
738                 int i;
739
740                 for (i = 0; i != 5; i++)
741                         ints[i] = pcf50633_reg_read(PCF50633_REG_INT1+i);
742                 pending1 |= ints[0];
743                 pending2 |= ints[1];
744         }
745         if (pending1 & mask1) {
746                 pending1 &= ~mask1;
747                 return 1;
748         }
749         if (pending2 & mask2) {
750                 pending1 &= ~mask2;
751                 return 1;
752         }
753         return 0;
754 }
755
756 int neo1973_new_second(void)
757 {
758         return have_int(PCF50633_INT1_SECOND, 0);
759 }
760
761 int neo1973_on_key_pressed(void)
762 {
763         static int pressed = -1;
764
765         if (pressed == -1 ||
766             have_int(0, PCF50633_INT2_ONKEYF | PCF50633_INT2_ONKEYR))
767                 pressed = !(pcf50633_reg_read(PCF50633_REG_OOCSTAT) &
768                     PCF50633_OOCSTAT_ONKEY);
769         return pressed;
770 }
771
772 int neo1973_aux_key_pressed(void)
773 {
774         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
775
776         return !!(gpio->GPFDAT & (1 << 6));
777 }
778
779 /* The sum of all part_size[]s must equal to or greater than the NAND size,
780    i.e., 0x10000000. */
781
782 unsigned int dynpart_size[] = {
783     CFG_UBOOT_SIZE, CFG_ENV_SIZE, 0x800000, 0xa0000, 0x40000, 0x10000000, 0 };
784 char *dynpart_names[] = {
785     "u-boot", "u-boot_env", "kernel", "splash", "factory", "rootfs", NULL };
786
787
788 const char *neo1973_get_charge_status(void)
789 {
790         /* FIXME */
791         return pcf50633_charger_state();
792 }
793
794 int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd)
795 {
796         /* FIXME */
797         puts("not implemented yet\n");
798         return -1;
799 }
800
801 void neo1973_led(int led, int on)
802 {
803         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
804
805         if (led > 2)
806                 return;
807
808         if (on) {
809                 gpb_shadow |= (1 << led);
810                 gpio->GPBDAT |= gpb_shadow;
811         }
812         else {
813                 gpb_shadow &= ~(1 << led);
814                 gpio->GPBDAT = (gpio->GPBDAT | gpb_shadow) & ~(1 << led);
815         }
816 }
817
818 /**
819  * returns PCB revision information in b9,b8 and b2,b1,b0
820  * Pre-GTA02 A6 returns 0x000
821  *     GTA02 A6 returns 0x001
822  */
823
824 int gta02_get_pcb_revision(void)
825 {
826         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
827         int n;
828         u32 u;
829
830         /* make C13 and C15 pulled-down inputs */
831         gpio->GPCCON &= ~0xcc000000;
832         gpio->GPCUP  &= ~((1 << 13) | (1 << 15));
833         /* D0, D3 and D4 pulled-down inputs */
834         gpio->GPDCON &= ~0x000003c3;
835         gpio->GPDUP  &= ~((1 << 0) | (1 << 3) | (1 << 4));
836
837         /* delay after changing pulldowns */
838         u = gpio->GPCDAT;
839         u = gpio->GPDDAT;
840
841         /* read the version info */
842         u = gpio->GPCDAT;
843         n =  (u >> (13 - 0)) & 0x001;
844         n |= (u >> (15 - 1)) & 0x002;
845         u = gpio->GPDDAT;
846         n |= (u << (0 + 2))  & 0x004;
847
848         n |= (u << (8 - 3))  & 0x100;
849         n |= (u << (9 - 4))  & 0x200;
850
851         /*
852          * when not being interrogated, all of the revision GPIO
853          * are set to output HIGH without pulldown so no current flows
854          * if they are NC or pulled up.
855          */
856         /* make C13 and C15 high ouputs with no pulldowns */
857         gpio->GPCCON |= 0x44000000;
858         gpio->GPCUP  |= (1 << 13) | (1 << 15);
859         gpio->GPCDAT |= (1 << 13) | (1 << 15);
860         /* D0, D3 and D4 high ouputs with no pulldowns */
861         gpio->GPDCON |= 0x00000141;
862         gpio->GPDUP  |= (1 << 0) | (1 << 3) | (1 << 4);
863         gpio->GPDDAT |= (1 << 0) | (1 << 3) | (1 << 4);
864
865         return n;
866 }