Root/qiboot/src/cpu/s3c2442/gta02.c

1/*
2 * (C) Copyright 2007 OpenMoko, Inc.
3 * Author: Andy Green <andy@openmoko.com>
4 *
5 * (port_init_gta02 came out of Openmoko U-Boot)
6 *
7 * Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 */
25
26#include <qi.h>
27#include <neo_gta02.h>
28#include <serial-s3c24xx.h>
29#include <ports-s3c24xx.h>
30#include <i2c-bitbang-s3c24xx.h>
31#include <pcf50633.h>
32#include <glamo-init.h>
33#include <string.h>
34#include <ext2.h>
35
36#define GTA02_DEBUG_UART 2
37#define PCF50633_I2C_ADS 0x73
38#define BOOST_TO_400MHZ 1
39
40static int battery_condition_reasonable = 0;
41
42extern unsigned long partition_offset_blocks;
43extern unsigned long partition_length_blocks;
44
45const struct board_api board_api_gta02;
46
47struct nand_dynparts {
48    const char *name; /* name of this partition for Linux */
49    u32 good_length; /* bytes needed from good sectors in this partition */
50    u32 true_offset;
51};
52
53/*
54 * These are the NAND partitions U-Boot leaves in GTA02 NAND.
55 * The "dynparts" business means that in the case of bad blocks, all the
56 * following partitions move up accordingly to have the right amount of
57 * good blocks. To allow for this, the length of the last, largest
58 * partition is computed according to the bad blocks that went before.
59 */
60
61static struct nand_dynparts nand_dynparts[] = {
62    { "qi", 0x40000 },
63    { "depr-ub-env", 0x40000 },
64    { "kernel", 0x800000 },
65    { "depr", 0xa0000 },
66    { "identity-ext2", 0x40000 },
67    { "rootfs", 0 },
68};
69
70static u32 nand_extent_block512 = 256 * 1024 * 1024 / 512;
71
72const struct pcf50633_init pcf50633_init[] = {
73
74    { PCF50633_REG_OOCWAKE, 0xd3 }, /* wake from ONKEY,EXTON!,RTC,USB,ADP */
75    { PCF50633_REG_OOCTIM1, 0xaa }, /* debounce 14ms everything */
76    { PCF50633_REG_OOCTIM2, 0x4a },
77    { PCF50633_REG_OOCMODE, 0x55 },
78    { PCF50633_REG_OOCCTL, 0x47 },
79
80    { PCF50633_REG_GPIO2CFG, 0x00 }, /* GSM_ON = 0 */
81    { PCF50633_REG_GPIOCTL, 0x01 }, /* only GPIO1 is input */
82
83    { PCF50633_REG_SVMCTL, 0x08 }, /* 3.10V SYS vth, 62ms filter */
84    { PCF50633_REG_BVMCTL, 0x02 }, /* 2.80V BAT vth, 62ms filter */
85
86    { PCF50633_REG_AUTOENA, 0x01 }, /* always on */
87
88    { PCF50633_REG_DOWN1OUT, 0x1b }, /* 1.3V (0x1b * .025V + 0.625V) */
89    { PCF50633_REG_DOWN1ENA, 0x02 }, /* enabled if GPIO1 = HIGH */
90    { PCF50633_REG_HCLDOOUT, 21 }, /* 3.0V (21 * 0.1V + 0.9V) */
91    { PCF50633_REG_HCLDOENA, 0x01 }, /* ON by default*/
92
93    { PCF50633_REG_DOWN1OUT, 0x1b }, /* 1.3V (0x1b * .025V + 0.625V) */
94    { PCF50633_REG_DOWN1ENA, 0x02 }, /* enabled if GPIO1 = HIGH */
95
96    { PCF50633_REG_INT1M, 0x00 },
97    { PCF50633_REG_INT2M, 0x00 },
98    { PCF50633_REG_INT3M, 0x00 },
99    { PCF50633_REG_INT4M, 0x00 },
100    { PCF50633_REG_INT5M, 0x00 },
101
102    { PCF50633_REG_MBCC2, 0x28 }, /* Vbatconid=2.7V, Vmax=4.20V */
103    { PCF50633_REG_MBCC3, 0x19 }, /* 25/255 == 98mA pre-charge */
104    { PCF50633_REG_MBCC4, 0xff }, /* 255/255 == 1A adapter fast */
105    { PCF50633_REG_MBCC5, 0xff }, /* 255/255 == 1A usb fast */
106    { PCF50633_REG_MBCC6, 0x01 }, /* cutoff current 2/32 * Ichg */
107    { PCF50633_REG_MBCC7, 0x00 }, /* 1.6A max bat curr, USB 100mA */
108    { PCF50633_REG_MBCC8, 0x00 },
109    { PCF50633_REG_MBCC1, 0xff }, /* chgena */
110
111    { PCF50633_REG_LDO1ENA, 2 }, /* accel enabled if GPIO1 = H */
112    { PCF50633_REG_LDO2ENA, 2 }, /* codec enabled if GPIO1 = H */
113    { PCF50633_REG_LDO4ENA, 0 }, /* bt off */
114    { PCF50633_REG_LDO5ENA, 0 }, /* gps off */
115    { PCF50633_REG_LDO6ENA, 2 }, /* lcm enabled if GPIO1 = H */
116
117    { PCF50633_REG_BBCCTL, 0x19 }, /* 3V, 200uA, on */
118    { PCF50633_REG_OOCSHDWN, 0x04 }, /* defeat 8s death from lowsys on A5 */
119
120};
121
122static const struct board_variant board_variants[] = {
123    [0] = {
124        .name = "A5 PCB",
125        .machine_revision = 0x350,
126    },
127    [1] = {
128        .name = "A6 PCB",
129        .machine_revision = 0x360,
130    },
131    [9] = { /* 01001 */
132        .name = "A7 PCB",
133        .machine_revision = 0x360, /* report as A6 */
134    },
135};
136
137
138void port_init_gta02(void)
139{
140    unsigned int * MPLLCON = (unsigned int *)0x4c000004;
141    unsigned int * UPLLCON = (unsigned int *)0x4c000008;
142    unsigned int * CLKDIVN = (unsigned int *)0x4c000014;
143    int n;
144    u32 block512 = 0;
145    u32 start_block512 = 0;
146    const u32 GTA02_NAND_READBLOCK_SIZE = 2048;
147    extern int s3c2442_nand_is_bad_block(unsigned long block_index_512);
148
149    //CAUTION:Follow the configuration order for setting the ports.
150    // 1) setting value(GPnDAT)
151    // 2) setting control register (GPnCON)
152    // 3) configure pull-down resistor(GPnUP)
153
154    /* 32bit data bus configuration */
155    /*
156     * === PORT A GROUP
157     * Ports : GPA22 GPA21 GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12
158     * Signal : nFCE nRSTOUT nFRE nFWE ALE CLE nGCS5 nGCS4 nGCS3 nGCS2 nGCS1
159     * Binary : 1 1 1 , 1 1 1 1 , 1 1 1 1
160     * Ports : GPA11 GPA10 GPA9 GPA8 GPA7 GPA6 GPA5 GPA4 GPA3 GPA2 GPA1 GPA0
161     * Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0
162     * Binary : 1 1 1 1 , 1 1 1 1 , 1 1 1 1
163     */
164    rGPACON = 0x007E5FFF;
165    rGPADAT = 0x00000000;
166    /*
167     * ===* PORT B GROUP
168     * Ports : GPB10 GPB9 GPB8 GPB7 GPB6 GPB5 GPB4 GPB3 GPB2 GPB1 GPB0
169     * Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
170     * Setting: INPUT OUTPUT INPUT OUTPUT INPUT OUTPUT OUTPUT OUTPUT OUTPUT OUTPUT OUTPUT
171     * Binary : 00 , 01 00 , 01 00 , 01 01 , 01 01 , 01 01
172     */
173    rGPBCON = 0x00155555;
174    rGPBUP = 0x000007FF;
175    rGPBDAT = 0x00000000;
176    /*
177     * === PORT C GROUP
178     * Ports : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8 GPC7 GPC6 GPC5 GPC4 GPC3 GPC2 GPC1 GPC0
179     * Signal : VD7 VD6 VD5 VD4 VD3 VD2 VD1 VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND
180     * Binary : 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10
181     */
182    rGPCCON = 0x55555155;
183    rGPCUP = 0x0000FFFF & ~(1 << 5);
184    rGPCDAT = (1 << 13) | (1 << 15); /* index detect -> hi */
185    /*
186     * === PORT D GROUP
187     * Ports : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
188     * Signal : VD23 VD22 VD21 VD20 VD19 VD18 VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9 VD8
189     * Binary : 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 ,10 10
190     */
191    rGPDCON = 0x55555555;
192    rGPDUP = 0x0000FFFF;
193    rGPDDAT = (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
194    /*
195     * === PORT E GROUP
196     * Ports : GPE15 GPE14 GPE13 GPE12 GPE11 GPE10 GPE9 GPE8 GPE7 GPE6 GPE5 GPE4
197     * Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK I2SSDO
198     * Binary : 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 ,
199     * -------------------------------------------------------------------------------------------------------
200     * Ports : GPE3 GPE2 GPE1 GPE0
201     * Signal : I2SSDI CDCLK I2SSCLK I2SLRCK
202     * Binary : 10 10 , 10 10
203     */
204    rGPECON = 0xAAAAAAAA;
205    rGPEUP = 0x0000FFFF & ~(1 << 11);
206    rGPEDAT = 0x00000000;
207    /*
208     * === PORT F GROUP
209     * Ports : GPF7 GPF6 GPF5 GPF4 GPF3 GPF2 GPF1 GPF0
210     * Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
211     * Setting: Output Output Output Output EINT3 EINT2 EINT1 EINT0
212     * Binary : 01 01 , 01 01 , 10 10 , 10 10
213     */
214    /* pulldown on GPF03: TP-4705+debug - debug conn will float */
215    rGPFCON = 0x00008AAA;
216    rGPFUP = 0x000000FF & ~(1 << 3);
217    rGPFDAT = 0x00000000;
218
219
220    /*
221     * === PORT G GROUP
222     * Ports : GPG15 GPG14 GPG13 GPG12 GPG11 GPG10 GPG9 GPG8 GPG7 GPG6
223     * Signal : nYPON YMON nXPON XMON EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
224     * Setting: nYPON YMON nXPON XMON EINT19 Output Output Output SPICLK1 SPIMOSI1
225     * Binary : 11 11 , 11 11 , 10 01 , 01 01 , 11 11
226     * -----------------------------------------------------------------------------------------
227     * Ports : GPG5 GPG4 GPG3 GPG2 GPG1 GPG0
228     * Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
229     * Setting: SPIMISO1 LCD_PWRDN EINT11 nSS0 EINT9 EINT8
230     * Binary : 11 11 , 10 11 , 10 10
231     */
232    rGPGCON = 0x01AAFE79;
233    rGPGUP = 0x0000FFFF;
234    rGPGDAT = 0x00000000;
235
236    /*
237     * === PORT H GROUP
238     * Ports : GPH10 GPH9 GPH8 GPH7 GPH6 GPH5 GPH4 GPH3 GPH2 GPH1 GPH0
239     * Signal : CLKOUT1 CLKOUT0 UCLK RXD2 TXD2 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
240     * Binary : 10 , 10 10 , 11 11 , 10 10 , 10 10 , 10 10
241     */
242
243/*
244 * FIXME the following should be removed eventually and only the first stanza
245 * kept unconditionally. As it stands it allows TX and RTS to drive high into
246 * a powered-down GSM unit, which draws considerable fault current.
247 *
248 * However kernels earlier than andy-tracking from end Feb 2009 do not enforce
249 * the mode of these GPIOs, so Qi doing the correct thing here "breaks GSM"
250 * apparently for those users.
251 *
252 * Upgrading to current kernel will solve this, so after most distros are on
253 * 2.6.29-rc3 and later, we should return here and again disable driving out
254 * into unpowered GSM.
255 */
256
257#if 0
258    rGPHCON = 0x001AAA82; /* H1 and H2 are INPUTs to start with, not UART */
259#else
260    rGPHCON = 0x001AAAAA; /* Wrong but compatible: H1 and H2 = UART */
261#endif
262
263    /* pulldown on GPH08: UEXTCLK, just floats!
264     * pulldown GPH1 -- nCTS0 / RTS_MODEM -- floats when GSM off
265     * pulldown GPH3 -- RXD[0] / RX_MODEM -- floats when GSM off
266     */
267    rGPHUP = 0x000007FF & ~(1 << 8) & ~(1 << 1) & ~(1 << 3);
268    rGPHDAT = 0x00000000;
269
270    /* pulldown on GPJ00: input, just floats! */
271    /* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
272    rGPJCON = 0x1551544;
273    rGPJUP = 0x1ffff & ~(1 << 0) & ~(1 << 7);
274    rGPJDAT = 0x00000100;
275
276    rGPJDAT |= (1 << 4) | (1 << 6);
277                    /* Set GPJ4 to high (nGSM_EN) */
278                    /* Set GPJ6 to high (nDL_GSM) */
279    rGPJDAT &= ~(1 << 5); /* Set GPJ5 to low 3D RST */
280
281    /* leaving Glamo forced to Reset# active here killed
282     * U-Boot when you touched the memory region
283     */
284
285    rGPJDAT |= (1 << 5); /* Set GPJ5 to high 3D RST */
286
287
288    /*
289     * We have to talk to the PMU a little bit
290     */
291
292    for (n = 0; n < ARRAY_SIZE(pcf50633_init); n++)
293        i2c_write_sync(&bb_s3c24xx, PCF50633_I2C_ADS,
294                   pcf50633_init[n].index, pcf50633_init[n].value);
295
296    /* what does the battery monitoring unit say about the battery? */
297
298    battery_condition_reasonable = !(i2c_read_sync(&bb_s3c24xx,
299                    PCF50633_I2C_ADS, PCF50633_REG_BVMCTL) & 1);
300
301    if (battery_condition_reasonable) {
302        /* change CPU clocking to 400MHz 1:4:8 */
303
304        /* clock divide 1:4:8 - do it first */
305        *CLKDIVN = 5;
306        /* configure UPLL */
307        *UPLLCON = ((88 << 12) + (4 << 4) + 2);
308        /* Magic delay: Page 7-19, seven nops between UPLL and MPLL */
309        asm __volatile__ (
310            "nop\n"
311            "nop\n"
312            "nop\n"
313            "nop\n"
314            "nop\n"
315            "nop\n"
316            "nop\n"
317        );
318        /* configure MPLL */
319        *MPLLCON = ((42 << 12) + (1 << 4) + 0);
320
321        /* get debug UART working at 115kbps */
322        serial_init_115200_s3c24xx(GTA02_DEBUG_UART, 50 /* 50MHz */);
323    } else {
324        serial_init_115200_s3c24xx(GTA02_DEBUG_UART, 33 /* 33MHz */);
325    }
326
327    /* we're going to use Glamo for SD Card access, so we need to init the
328     * evil beast
329     */
330    glamo_core_init();
331
332    /*
333     * dynparts computation
334     */
335
336    n = 0;
337    while (n < ARRAY_SIZE(nand_dynparts)) {
338
339        if (nand_dynparts[n].good_length)
340            while (nand_dynparts[n].good_length) {
341                if (!s3c2442_nand_is_bad_block(block512))
342                    nand_dynparts[n].good_length -=
343                              GTA02_NAND_READBLOCK_SIZE;
344                block512 += GTA02_NAND_READBLOCK_SIZE / 512;
345            }
346        else
347            /*
348             * cannot afford to compute real size of last block
349             * set it to extent - end of last block
350             */
351            block512 = nand_extent_block512;
352
353        /* stash a copy of real offset for each partition */
354        nand_dynparts[n].true_offset = start_block512;
355
356        /* and the accurate length */
357        nand_dynparts[n].good_length = block512 - start_block512;
358
359        start_block512 = block512;
360
361        n++;
362    }
363
364    /* fix up the true start of kernel partition */
365
366    ((struct board_api *)&board_api_gta02)->kernel_source[3].
367         offset_blocks512_if_no_partition = nand_dynparts[2].true_offset;
368
369}
370
371/**
372 * returns PCB revision information in b9,b8 and b2,b1,b0
373 * Pre-GTA02 A6 returns 0x000
374 * GTA02 A6 returns 0x001
375 */
376
377int gta02_get_pcb_revision(void)
378{
379    int n;
380    u32 u;
381
382    /* make C13 and C15 pulled-down inputs */
383    rGPCCON &= ~0xcc000000;
384    rGPCUP &= ~((1 << 13) | (1 << 15));
385    /* D0, D3 and D4 pulled-down inputs */
386    rGPDCON &= ~0x000003c3;
387    rGPDUP &= ~((1 << 0) | (1 << 3) | (1 << 4));
388
389    /* delay after changing pulldowns */
390    u = rGPCDAT;
391    u = rGPDDAT;
392
393    /* read the version info */
394    u = rGPCDAT;
395    n = (u >> (13 - 0)) & 0x001;
396    n |= (u >> (15 - 1)) & 0x002;
397    u = rGPDDAT;
398    n |= (u << (0 + 2)) & 0x004;
399
400    n |= (u << (3 - 3)) & 0x008;
401    n |= (u << (4 - 4)) & 0x010;
402
403    /*
404     * when not being interrogated, all of the revision GPIO
405     * are set to output HIGH without pulldown so no current flows
406     * if they are NC or pulled up.
407     */
408    /* make C13 and C15 high ouputs with no pulldowns */
409    rGPCCON |= 0x44000000;
410    rGPCUP |= (1 << 13) | (1 << 15);
411    rGPCDAT |= (1 << 13) | (1 << 15);
412    /* D0, D3 and D4 high ouputs with no pulldowns */
413    rGPDCON |= 0x00000141;
414    rGPDUP |= (1 << 0) | (1 << 3) | (1 << 4);
415    rGPDDAT |= (1 << 0) | (1 << 3) | (1 << 4);
416
417    n &= 1;
418
419    return n;
420}
421
422int sd_card_init_gta02(void)
423{
424    extern int mmc_init(int verbose);
425
426    return mmc_init(1);
427}
428
429int sd_card_block_read_gta02(unsigned char * buf, unsigned long start512,
430                                   int blocks512)
431{
432unsigned long mmc_bread(int dev_num, unsigned long blknr, unsigned long blkcnt,
433                                     void *dst);
434
435    return mmc_bread(0, start512, blocks512, buf);
436}
437
438/* return nonzero if we believe we run on GTA02 */
439
440int is_this_board_gta02(void)
441{
442    /* look for GTA02 NOR */
443
444    *(volatile unsigned short *)(0x18000000) = 0x98;
445
446    return !!(*(volatile unsigned short *)(0x18000000) == 0x0020);
447}
448
449const struct board_variant const * get_board_variant_gta02(void)
450{
451    int rev = gta02_get_pcb_revision() & 0x1f;
452
453    if (!board_variants[rev].name)
454        return &board_variants[1]; /* A6 */
455
456    return &board_variants[rev];
457}
458
459static __attribute__ (( section (".steppingstone") )) void putc_gta02(char c)
460{
461    serial_putc_s3c24xx(GTA02_DEBUG_UART, c);
462}
463
464static void close_gta02(void)
465{
466    /* explicitly clear any pending 8s timeout */
467
468    i2c_write_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_OOCSHDWN, 0x04);
469
470    /* clear any pending timeouts by reading interrupts */
471
472    i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT1);
473    i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT2);
474    i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT3);
475    i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT4);
476    i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT5);
477
478    /* set I2C GPIO back to peripheral unit */
479
480    (bb_s3c24xx.close)();
481
482    /* aux back to being EINT */
483    rGPFCON = 0x0000AAAA;
484
485}
486
487/* Here we will care only about AUX button as polling for PWR button
488 * through i2c slows down the boot */
489
490static u8 get_ui_keys_gta02(void)
491{
492    u8 keys;
493    u8 ret = 0;
494    static u8 old_keys = 0; /* previous state for debounce */
495    static u8 older_keys = 0; /* previous debounced output for edge detect */
496
497    /* GPF6 is AUX on GTA02, map to UI_ACTION_SKIPKERNEL, down = 1 */
498    keys = !!(rGPFDAT & (1 << 6));
499
500    /* edge action */
501    if ((old_keys & 1) && !(older_keys & 1))
502        ret |= UI_ACTION_SKIPKERNEL;
503
504    older_keys = old_keys;
505    old_keys = keys;
506
507    return ret;
508}
509
510static u8 get_ui_debug_gta02(void)
511{
512    /* PWR button state can be seen in OOCSTAT b0, down = 0, map to UI_ACTION_ADD_DEBUG */
513    return !(i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_OOCSTAT) & 1);
514}
515
516static void set_ui_indication_gta02(enum ui_indication ui_indication)
517{
518
519    switch (ui_indication) {
520        case UI_IND_UPDATE_ONLY:
521            break;
522
523        case UI_IND_MOUNT_PART:
524        case UI_IND_KERNEL_PULL_OK:
525        case UI_IND_INITRAMFS_PULL_OK:
526            if (battery_condition_reasonable)
527                rGPBDAT |= 4;
528            break;
529
530        case UI_IND_KERNEL_PULL_FAIL:
531        case UI_IND_SKIPPING:
532        case UI_IND_INITRAMFS_PULL_FAIL:
533        case UI_IND_MOUNT_FAIL:
534            rGPBDAT &= ~4;
535            if (battery_condition_reasonable) {
536                rGPBDAT |= 8;
537                udelay(2000000);
538                rGPBDAT &= ~8;
539                udelay(200000);
540            }
541            break;
542
543        case UI_IND_KERNEL_START:
544        case UI_IND_MEM_TEST:
545        case UI_IND_KERNEL_PULL:
546        case UI_IND_INITRAMFS_PULL:
547            rGPBDAT &= ~4;
548            break;
549    }
550}
551
552
553void post_serial_init_gta02(void)
554{
555    if (battery_condition_reasonable)
556        puts("Battery condition reasonable\n");
557    else
558        puts("BATTERY CONDITION LOW\n");
559}
560
561/*
562 * Increment a hexadecimal digit represented by a char and
563 * return 1 if an overflow occured.
564 */
565static char inc_hexchar(char * p)
566{
567    if (*p == '9')
568        *p = 'A';
569    else if (*p != 'F')
570        (*p)++;
571    else {
572        *p = '0';
573        return 1;
574    }
575    return 0;
576}
577
578/*
579 * create and append device-specific Linux kernel commandline
580 *
581 * This takes care of legacy dyanmic partition sizing and USB Ethernet
582 * MAC address identity information.
583 */
584
585char * append_device_specific_cmdline_gta02(char * cmdline)
586{
587    int n = 0;
588    int i;
589    int len;
590    static char mac[64];
591    struct kernel_source const * real_kernel = this_kernel;
592
593    /*
594     * dynparts computation
595     */
596
597    cmdline += strlen(strcpy(cmdline,
598                   " mtdparts=physmap-flash:-(nor);neo1973-nand:"));
599
600    while (n < ARRAY_SIZE(nand_dynparts)) {
601
602        *cmdline++ = '0';
603        *cmdline++ = 'x';
604        set32(cmdline, nand_dynparts[n].good_length * 512);
605        cmdline += 8;
606        *cmdline++ = '(';
607        cmdline += strlen(strcpy(cmdline, nand_dynparts[n].name));
608        *cmdline++ = ')';
609
610        if (++n == ARRAY_SIZE(nand_dynparts))
611            *cmdline++ = ' ';
612        else
613            *cmdline++ = ',';
614
615    }
616
617    *cmdline = '\0';
618
619    /*
620     * Identity
621     */
622
623    /* position ourselves at true start of GTA02 identity partition */
624    partition_offset_blocks = nand_dynparts[4].true_offset;
625    partition_length_blocks = 0x40000 / 512;
626
627    /*
628     * lie that we are in NAND context... GTA02 specific
629     * all filesystem access is completed before we are called
630     */
631    this_kernel = &board_api_gta02.kernel_source[3];
632
633    if (!ext2fs_mount()) {
634        puts("Unable to mount ext2 filesystem\n");
635        goto bail;
636    }
637
638    len = ext2fs_open("usb");
639    if (len < 0) {
640        puts(" Open failed\n");
641        goto bail;
642    }
643
644    n = ext2fs_read(mac, sizeof(mac));
645    if (n < 0) {
646        puts(" Read failed\n");
647        goto bail;
648    }
649
650    mac[len] = '\0';
651
652    cmdline += strlen(strcpy(cmdline, " g_ether.dev_addr="));
653    cmdline += strlen(strcpy(cmdline, &mac[2]));
654
655    for (i = 0; i != 10; i++) {
656        if ((i % 3) == 2)
657            continue;
658        if (!inc_hexchar(mac + 18 - i))
659            break; /* Carry not needed. */
660    }
661
662    cmdline += strlen(strcpy(cmdline, " g_ether.host_addr="));
663    cmdline += strlen(strcpy(cmdline, &mac[2]));
664    *cmdline++ = ' ' ;
665bail:
666    this_kernel = real_kernel;
667
668    *cmdline = '\0';
669
670    return cmdline;
671}
672
673/*
674 * our API for bootloader on this machine
675 */
676
677const struct board_api board_api_gta02 = {
678    .name = "Freerunner / GTA02",
679    .linux_machine_id = 1304,
680    .linux_mem_start = 0x30000000,
681    .linux_mem_size = (128 * 1024 * 1024),
682    .linux_tag_placement = 0x30000000 + 0x100,
683    .get_board_variant = get_board_variant_gta02,
684    .is_this_board = is_this_board_gta02,
685    .port_init = port_init_gta02,
686    .post_serial_init = post_serial_init_gta02,
687    .append_device_specific_cmdline = append_device_specific_cmdline_gta02,
688    .putc = putc_gta02,
689    .close = close_gta02,
690    .get_ui_keys = get_ui_keys_gta02,
691    .get_ui_debug = get_ui_debug_gta02,
692    .set_ui_indication = set_ui_indication_gta02,
693    .commandline_board = "loglevel=4 "
694                      "console=tty0 "
695                      "console=ttySAC2,115200 "
696                      "init=/sbin/init "
697                      "ro ",
698    .commandline_board_debug = " loglevel=8",
699    .noboot = "boot/noboot-GTA02",
700    .append = "boot/append-GTA02",
701    /* these are the ways we could boot GTA02 in the order to try */
702    .kernel_source = {
703        [0] = {
704            .name = "SD Card EXT2 P1 Kernel",
705            .block_init = sd_card_init_gta02,
706            .block_read = sd_card_block_read_gta02,
707            .partition_index = 1,
708            .filesystem = FS_EXT2,
709            .filepath = "boot/uImage-GTA02.bin",
710            .commandline_append = " root=/dev/mmcblk0p1 rootdelay=1 ",
711        },
712        [1] = {
713            .name = "SD Card EXT2 P2 Kernel",
714            .block_init = sd_card_init_gta02,
715            .block_read = sd_card_block_read_gta02,
716            .partition_index = 2,
717            .filesystem = FS_EXT2,
718            .filepath = "boot/uImage-GTA02.bin",
719            .commandline_append = " root=/dev/mmcblk0p2 rootdelay=1 ",
720        },
721        [2] = {
722            .name = "SD Card EXT2 P3 Kernel",
723            .block_init = sd_card_init_gta02,
724            .block_read = sd_card_block_read_gta02,
725            .partition_index = 3,
726            .filesystem = FS_EXT2,
727            .filepath = "boot/uImage-GTA02.bin",
728            .commandline_append = " root=/dev/mmcblk0p3 rootdelay=1 ",
729        },
730        [3] = {
731            .name = "NAND Kernel",
732            .block_read = nand_read_ll,
733            /* NOTE offset below is replaced at runtime */
734            .offset_blocks512_if_no_partition = 0x80000 / 512,
735            .filesystem = FS_RAW,
736            .commandline_append = " rootfstype=jffs2 "
737                          "root=/dev/mtdblock6 ",
738        },
739    },
740};
741

Archive Download this file



interactive