source: SVN/laguna/u-boot-2008.10/board/cavium/cns3000/vega.c @ 58

Last change on this file since 58 was 58, checked in by Tim Harvey, 2 years ago

laguna: Enable external clockgen on boards without clockgen detection

Enable the external pci clockgen on boards where our detection mechanism is
not available to us. This includes: GW2386, GW2391, and GW2393.

Note that on the GW2386, only certain revision/special combinations have the
external clockgen, so we additionally add support for determining a board's
revision and special number.

Signed-off-by: Pushpal Sidhu <psidhu@…>

File size: 11.0 KB
Line 
1/*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
5 *
6 * (C) Copyright 2002
7 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
8 *
9 * (C) Copyright 2003
10 * Texas Instruments, <www.ti.com>
11 * Kshitij Gupta <Kshitij@ti.com>
12 *
13 * (C) Copyright 2004
14 * ARM Ltd.
15 * Philippe Robin, <philippe.robin@arm.com>
16 *
17 * See file CREDITS for list of people who contributed to this
18 * project.
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License as
22 * published by the Free Software Foundation; either version 2 of
23 * the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
33 * MA 02111-1307 USA
34 */
35/*
36 * The RealView Emulation BaseBoard provides timers and soft reset
37 * - the cpu code does not need to provide these.
38 */
39#include <common.h>
40#include <i2c.h>
41
42DECLARE_GLOBAL_DATA_PTR;
43
44static ulong timestamp;
45static ulong lastdec;
46uint8_t model[16];
47uint8_t rev;
48int sp;
49
50#define READ_TIMER1 (*(volatile ulong *)(CFG_TIMERBASE))
51#define READ_TIMER2 (*(volatile ulong *)(CFG_TIMERBASE + 0x10))
52
53static void timer_init(void);
54
55#if defined(CONFIG_SHOW_BOOT_PROGRESS)
56void show_boot_progress(int progress)
57{
58        printf("Boot reached stage %d\n", progress);
59}
60#endif
61
62#define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF)
63
64static inline void delay (unsigned long loops)
65{
66        __asm__ volatile ("1:\n"
67                "subs %0, %1, #1\n"
68                "bne 1b":"=r" (loops):"0" (loops));
69}
70
71
72#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val))
73#define IO_READ(addr) (*(volatile unsigned int *)(addr))
74#define PCIE_CLK_GATE_REG 0x77000014
75#define MISC_PCIE0_REG 0x76000900
76#define MISC_PCIE1_REG 0x76000A00
77#define PCIE0_CTRL 0x7600095C
78#define PCIE1_CTRL 0x76000A5C
79#define PMU_SOFT_RST   0x77000004
80#define PCIE0_PHY_ERRATA 0x76000940
81#define PCIE1_PHY_ERRATA 0x76000A40
82#define GPIOA_DIR 0x74000008
83#define GPIOA_OUT 0x74000000
84#define GPIOB_DIR 0x74800008
85#define GPIOB_IN  0x74800004
86#define GPIOB_OUT 0x74800000
87
88static void pcie_init(void)
89{
90        unsigned char eeprom;
91        unsigned int temp;
92        unsigned char external_clkgen;
93        int gpio_perst = -1;
94
95        /* Errata C-01 */
96        IO_WRITE(PCIE0_PHY_ERRATA, 0xe2c);
97        IO_WRITE(PCIE1_PHY_ERRATA, 0xe2c);
98
99#ifdef GPIOA_PERST
100        gpio_perst = GPIOA_PERST;
101        if (strncmp(model, "GW2391", 6) == 0) {
102                gpio_perst = 8;
103        }
104#endif
105
106        /**
107         * All boards with external PCI clockgen have GPIOB26 high at powerup.
108         * However, exceptions exist with the GW2386 after a certain revision
109         * and special number, the GW2391, and GW2393.
110         */
111        if (strncmp(model, "GW2386", 6) == 0) {
112                if ((sp == 217) && (rev >= 'E'))
113                        external_clkgen = 1;
114                else if ((sp == 0) && (rev == 'D'))
115                        external_clkgen = 1;
116                else
117                        external_clkgen = 0;
118        }
119        else if (strncmp(model, "GW2391", 6) == 0) {
120                if (rev >= 'C')
121                        external_clkgen = 1;
122                else
123                        external_clkgen = 0;
124        }
125        else if (strncmp(model, "GW2393", 6) == 0)
126                external_clkgen = 1;
127        else
128                external_clkgen = (IO_READ(GPIOB_IN) & (1 << 26)) ? 1 : 0;
129
130        printf("PCI:   PERST:GPIOA%d clock:%s\n", gpio_perst,
131               external_clkgen ? "external" : "internal");
132
133        /* enable and assert PERST# */
134        if (gpio_perst != -1) {
135                temp = IO_READ(GPIOA_DIR);
136                temp |= (1 << gpio_perst);  /* output */
137                IO_WRITE(GPIOA_DIR, temp);
138
139                temp = IO_READ(GPIOA_OUT);
140                temp &= ~(1 << gpio_perst); /* low */
141                IO_WRITE(GPIOA_OUT, temp);
142        }
143
144        i2c_read(0x51, 0x43, 1, &eeprom, 1);
145
146        /* pcie0 init */
147        if (eeprom & 0x2) {
148                if (external_clkgen) {
149                        /* select external clock */
150                        temp = IO_READ(MISC_PCIE0_REG);
151                        temp &= ~(1 << 11);
152                        IO_WRITE(MISC_PCIE0_REG, temp);
153                } else {
154                        /* enable PCIe Ref clock 0 */
155                        temp = IO_READ(PCIE_CLK_GATE_REG);
156                        temp |= (1 << 28);
157                        IO_WRITE(PCIE_CLK_GATE_REG, temp);
158                        /* select internal clock */
159                        temp = IO_READ(MISC_PCIE0_REG);
160                        temp |= (1 << 11);
161                        IO_WRITE(MISC_PCIE0_REG, temp);
162                }
163
164                /* soft reset PCIe0 */
165                temp = IO_READ(PMU_SOFT_RST);
166                temp &= ~(1 << 17);
167                IO_WRITE(PMU_SOFT_RST, temp);
168                temp |= (1 << 17);
169                IO_WRITE(PMU_SOFT_RST, temp);
170                /* exit L1 and enable LTSSM */
171                temp = IO_READ(PCIE0_CTRL);
172                temp |= 0x3;
173                IO_WRITE(PCIE0_CTRL, temp);
174        }
175
176        /* pcie1 init */
177        if (eeprom & 0x4) {
178                if (external_clkgen) {
179                        /* select external clock */
180                        temp = IO_READ(MISC_PCIE1_REG);
181                        temp &= ~(1 << 11);
182                        IO_WRITE(MISC_PCIE1_REG, temp);
183                } else {
184                        /* enable PCIe Ref clock 1 */
185                        temp = IO_READ(PCIE_CLK_GATE_REG);
186                        temp |= (1 << 29);
187                        IO_WRITE(PCIE_CLK_GATE_REG, temp);
188                        /* select internal clock */
189                        temp = IO_READ(MISC_PCIE1_REG);
190                        temp |= (1 << 11);
191                        IO_WRITE(MISC_PCIE1_REG, temp);
192                }
193
194                /* soft reset PCIe1 */
195                temp = IO_READ(PMU_SOFT_RST);
196                temp &= ~(1 << 18);
197                IO_WRITE(PMU_SOFT_RST, temp);
198                temp |= (1 << 18);
199                IO_WRITE(PMU_SOFT_RST, temp);
200                /* exit L1 and enable LTSSM */
201                temp = IO_READ(PCIE1_CTRL);
202                temp |= 0x3;
203                IO_WRITE(PCIE1_CTRL, temp);
204        }
205
206        /* de-assert PERST# after some delay for clock to become stable */
207        if (gpio_perst != -1) {
208                udelay(1000);
209                temp = IO_READ(GPIOA_OUT);
210                temp |= (1 << gpio_perst); /* high */
211                IO_WRITE(GPIOA_OUT, temp);
212        }
213}
214
215/*
216 * Miscellaneous platform dependent initialisations
217 */
218
219int board_init (void)
220{
221        gd->bd->bi_arch_number = 2635;
222
223        /* adress of boot parameters */
224        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x00000100;
225
226        gd->flags = 0;
227
228        icache_enable ();
229        timer_init();
230#ifdef CONFIG_AHCI_CNS3000
231        //dram_init();
232        scsi_init();
233#endif
234        return 0;
235}
236
237
238int misc_init_r (void)
239{
240        int i;
241        uint8_t eeprom_enetaddr[6];
242        uint8_t env_enetaddr[6];
243        uint32_t serial = 0;
244        uint8_t date[4];
245
246        char ethaddr[20];
247
248        char *tmp = getenv("ethaddr");
249        char *tmp1 = getenv("eth1addr");
250        char *tmp2 = getenv("eth2addr");
251        char *end;
252
253        i2c_read(0x51, 0x20, 1, date, 4);
254        i2c_read(0x51, 0x18, 1, eeprom_enetaddr, 4);
255        serial |= ((eeprom_enetaddr[0]) | (eeprom_enetaddr[1] << 8) |
256                  (eeprom_enetaddr[2] << 16) | (eeprom_enetaddr[3] << 24));
257
258
259        printf("Gateworks Corporation Copyright 2010\n");
260        printf("Model Number: %s\n", model);
261        printf("Manufacturer Date: %02x-%02x-%02x%02x\n", date[0], date[1],
262               date[2], date[3]);
263        printf("Serial #: %i\n", serial);       
264
265        i2c_read(0x51, 0x0, 1, eeprom_enetaddr, 6);
266
267        for (i = 0; i < 6; i++) {
268                env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
269                if (tmp)
270                        tmp = (*end) ? end+1 : end;
271        }
272
273        if (!tmp) {
274                sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
275                        eeprom_enetaddr[0], eeprom_enetaddr[1],
276                        eeprom_enetaddr[2], eeprom_enetaddr[3],
277                        eeprom_enetaddr[4], eeprom_enetaddr[5]) ;       
278                printf("### Setting environment from ROM MAC address = \"%s\"\n",
279                        ethaddr);
280                setenv("ethaddr", ethaddr);
281        }
282
283        i2c_read(0x51, 0x6, 1, eeprom_enetaddr, 6);
284
285        for (i = 0; i < 6; i++) {
286                env_enetaddr[i] = tmp1 ? simple_strtoul(tmp1, &end, 16) : 0;
287                if (tmp1)
288                        tmp1 = (*end) ? end+1 : end;
289        }
290
291        if (!tmp1) {
292                sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
293                        eeprom_enetaddr[0], eeprom_enetaddr[1],
294                        eeprom_enetaddr[2], eeprom_enetaddr[3],
295                        eeprom_enetaddr[4], eeprom_enetaddr[5]) ;       
296                printf("### Setting environment from ROM MAC address = \"%s\"\n",
297                        ethaddr);
298                setenv("eth1addr", ethaddr);
299        }
300
301        i2c_read(0x51, 0xc, 1, eeprom_enetaddr, 6);
302
303        for (i = 0; i < 6; i++) {
304                env_enetaddr[i] = tmp2 ? simple_strtoul(tmp2, &end, 16) : 0;
305                if (tmp2)
306                        tmp2 = (*end) ? end+1 : end;
307        }
308
309        if (!tmp2) {
310                sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
311                        eeprom_enetaddr[0], eeprom_enetaddr[1],
312                        eeprom_enetaddr[2], eeprom_enetaddr[3],
313                        eeprom_enetaddr[4], eeprom_enetaddr[5]) ;       
314                printf("### Setting environment from ROM MAC address = \"%s\"\n",
315                        ethaddr);
316                setenv("eth2addr", ethaddr);
317        }
318
319        return (0);
320}
321
322/*************************************************************
323 Routine:checkboard
324 Description: Check Board Identity
325*************************************************************/
326int checkboard(void)
327{
328        int i;
329
330        /* determine board model */
331        i2c_read(0x51, 0x30, 1, model, 16);
332
333        /* determine board revision */
334        rev = '\0';
335        for (i = sizeof(model) - 1; i >= 0; i--) {
336                if (model[i] >= 'A') {
337                        rev = model[i];
338                        break;
339                }
340        }
341
342        /* determine board sp number (assume 3 digit special number) */
343        sp = 0;
344        for (i = sizeof(model) - 4; i > 0; i--) {
345                if (model[i - 1] == 'S' && model[i] == 'P') {
346                        /* Convert SPXXX to numeric */
347                        sp = (sp * 10) + (model[i+1] - '0');
348                        sp = (sp * 10) + (model[i+2] - '0');
349                        sp = (sp * 10) + (model[i+3] - '0');
350                        break;
351                }
352        }
353
354        pcie_init();
355        return (0);
356}
357
358/******************************
359 Routine:
360 Description:
361******************************/
362int dram_init (void)
363{
364        unsigned char eeprom;
365        unsigned int temp = 0x01000000;
366        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
367
368        i2c_read(0x51, 0x2b, 1, &eeprom, 1);
369        gd->bd->bi_dram[0].size = temp << eeprom;
370
371        return 0;
372}
373
374/*
375 * Start the timer
376 * U-Boot expects a 32 bit timer, running at CFG_HZ == 1000
377 */
378#include "cns3000.h"
379
380#define PMU_REG_VALUE(addr) (*((volatile unsigned int *)(CNS3000_VEGA_PMU_BASE+addr)))
381#define CLK_GATE_REG PMU_REG_VALUE(0)
382#define SOFT_RST_REG PMU_REG_VALUE(4)
383#define HS_REG PMU_REG_VALUE(8)
384
385static void timer_init(void)
386{
387        // Setup timer to be a 1khz timer to make things easy
388        CLK_GATE_REG |= (1 << 14);
389        SOFT_RST_REG &= (~(1 << 14));
390        SOFT_RST_REG |= (1 << 14);
391        //HS_REG |= (1 << 14);
392        /*
393         * Now setup timer1
394         */     
395        *(volatile ulong *)(CFG_TIMERBASE + 0x00) = CFG_TIMER_RELOAD;
396        *(volatile ulong *)(CFG_TIMERBASE + 0x04) = CFG_TIMER_RELOAD;
397        *(volatile ulong *)(CFG_TIMERBASE + 0x30) |= 0x0203;    /* Enabled,
398                                                                 * down counter,
399                                                                 * no interrupt,
400                                                                 * 32-bit,
401                                                                 */
402
403        reset_timer_masked();
404}
405
406int interrupt_init (void){
407        return 0;
408}
409
410// udelay, exactly what it says, delay 1us
411void udelay (unsigned long usec)
412{
413
414        /*
415         *  This could possibly be a problem due to overflow
416         *  If usec is greater than 57266230 then we would have
417         *  an overflow and it wouldn't work right
418         */
419
420        *(volatile ulong *)(CFG_TIMERBASE + 0x30) &= ~0x8;      /* Disable */
421        *(volatile ulong *)(CFG_TIMERBASE + 0x10) = 75000000 / 1000000 * usec;
422        *(volatile ulong *)(CFG_TIMERBASE + 0x14) = 0;
423        *(volatile ulong *)(CFG_TIMERBASE + 0x30) |= 0x0408;    /* Enabled, */
424
425        while (READ_TIMER2 != 0);
426}
427
428// timestamp ticks at 1ms
429ulong get_timer (ulong base)
430{
431        return get_timer_masked () - base;
432}
433
434void reset_timer_masked (void)
435{
436        /* reset time */
437        lastdec = READ_TIMER1;
438        timestamp = 0;              /* start "advancing" time stamp from 0 */
439}
440
441/* ASSUMES 1kHz timer */
442ulong get_timer_masked(void)
443{
444        ulong now = READ_TIMER1;
445
446        if (lastdec >= now) {
447                /* normal mode */
448                timestamp += lastdec - now; /* move stamp forward with absolute diff ticks */
449        } else {                        /* we have overflow of the count down timer */
450                timestamp += lastdec + TIMER_LOAD_VAL - now;
451        }
452        lastdec = now;
453        return timestamp;
454}
455
456/*
457 *  u32 get_board_rev() for ARM supplied development boards
458 */
459ARM_SUPPLIED_GET_BOARD_REV
460
Note: See TracBrowser for help on using the repository browser.