blob: becbd0abda623cd85271acc8725cc80cc6d23f6f [file] [log] [blame]
Wolfgang Denka48c7252005-09-25 18:59:36 +02001/********************************************************************
2 *
3 * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms
4 *
5 * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/barco.c,v $
6 * $Revision: 1.4 $
7 * $Author: mleeman $
8 * $Date: 2005/03/02 16:40:20 $
9 *
10 * Last ChangeLog Entry
11 * $Log: barco.c,v $
12 * Revision 1.4 2005/03/02 16:40:20 mleeman
13 * remove empty labels (3.4 complains)
14 *
15 * Revision 1.3 2005/02/21 12:48:58 mleeman
16 * update of copyright years (feedback wd)
17 *
18 * Revision 1.2 2005/02/21 10:10:53 mleeman
19 * - split up switch statement to a function call (Linux kernel coding guidelines)
20 * ( feedback wd)
21 *
22 * Revision 1.1 2005/02/14 09:31:07 mleeman
23 * renaming of files
24 *
25 * Revision 1.1 2005/02/14 09:23:46 mleeman
26 * - moved 'barcohydra' directory to a more generic barco; since we will be
27 * supporting and adding multiple boards
28 *
29 * Revision 1.3 2005/02/10 13:57:32 mleeman
30 * fixed flash corruption: I should exit from the moment I find the correct value
31 *
32 * Revision 1.2 2005/02/09 12:56:23 mleeman
33 * add generic header to track changes in sources
34 *
35 *
36 *******************************************************************/
37
38/*
39 * (C) Copyright 2004
40 * Marc Leeman <marc.leeman@barco.com>
41 *
42 * This program is free software; you can redistribute it and/or
43 * modify it under the terms of the GNU General Public License as
44 * published by the Free Software Foundation; either version 2 of
45 * the License, or (at your option) any later version.
46 *
47 * This program is distributed in the hope that it will be useful,
48 * but WITHOUT ANY WARRANTY; without even the implied warranty of
49 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50 * GNU General Public License for more details.
51 *
52 * You should have received a copy of the GNU General Public License
53 * along with this program; if not, write to the Free Software
54 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
55 * MA 02111-1307 USA
56 */
57
58#include <common.h>
59#include <mpc824x.h>
60#include <pci.h>
61#include <malloc.h>
62#include <command.h>
63
64#include "config.h"
65#include "barco_svc.h"
66
67#define TRY_WORKING (3)
68#define BOOT_DEFAULT (2)
69#define BOOT_WORKING (1)
70
71int checkboard (void)
72{
73 /*TODO: Check processor type */
74
75 puts ( "Board: Streaming Video Card for Hydra systems "
76#ifdef CONFIG_MPC8240
77 "8240"
78#endif
79#ifdef CONFIG_MPC8245
80 "8245"
81#endif
82 " Unity ##Test not implemented yet##\n");
83 return 0;
84}
85
86long int initdram (int board_type)
87{
88 long size;
89 long new_bank0_end;
90 long mear1;
91 long emear1;
92
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +020093 size = get_ram_size (CFG_SDRAM_BASE, CFG_MAX_RAM_SIZE);
Wolfgang Denka48c7252005-09-25 18:59:36 +020094
95 new_bank0_end = size - 1;
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +020096 mear1 = mpc824x_mpc107_getreg (MEAR1);
97 emear1 = mpc824x_mpc107_getreg (EMEAR1);
Wolfgang Denka48c7252005-09-25 18:59:36 +020098 mear1 = (mear1 & 0xFFFFFF00) |
99 ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
100 emear1 = (emear1 & 0xFFFFFF00) |
101 ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200102 mpc824x_mpc107_setreg (MEAR1, mear1);
103 mpc824x_mpc107_setreg (EMEAR1, emear1);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200104
105 return (size);
106}
107
108/*
109 * Initialize PCI Devices, report devices found.
110 */
111#ifndef CONFIG_PCI_PNP
112static struct pci_config_table pci_barcohydra_config_table[] = {
113 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0f, PCI_ANY_ID,
114 pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
115 PCI_ENET0_MEMADDR,
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200116 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER } },
Wolfgang Denka48c7252005-09-25 18:59:36 +0200117 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x10, PCI_ANY_ID,
118 pci_cfgfunc_config_device, { PCI_ENET1_IOADDR,
119 PCI_ENET1_MEMADDR,
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200120 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER } },
Wolfgang Denka48c7252005-09-25 18:59:36 +0200121 { }
122};
123#endif
124
125struct pci_controller hose = {
126#ifndef CONFIG_PCI_PNP
127 config_table: pci_barcohydra_config_table,
128#endif
129};
130
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200131void pci_init_board (void)
Wolfgang Denka48c7252005-09-25 18:59:36 +0200132{
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200133 pci_mpc824x_init (&hose);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200134}
135
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200136int write_flash (char *addr, char value)
Wolfgang Denka48c7252005-09-25 18:59:36 +0200137{
138 char *adr = (char *)0xFF800000;
139 int cnt = 0;
140 char status,oldstatus;
Wolfgang Denka48c7252005-09-25 18:59:36 +0200141
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200142 *(adr+0x55) = 0xAA; udelay (1);
143 *(adr+0xAA) = 0x55; udelay (1);
144 *(adr+0x55) = 0xA0; udelay (1);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200145 *addr = value;
146
147 status = *addr;
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200148 do {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200149 oldstatus = status;
150 status = *addr;
151
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200152 if ((oldstatus & 0x40) == (status & 0x40)) {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200153 return 4;
154 }
155 cnt++;
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200156 if (cnt > 10000) {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200157 return 2;
158 }
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200159 } while ( (status & 0x20) == 0 );
Wolfgang Denka48c7252005-09-25 18:59:36 +0200160
161 oldstatus = *addr;
162 status = *addr;
163
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200164 if ((oldstatus & 0x40) == (status & 0x40)) {
165 return 0;
166 } else {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200167 *(adr+0x55) = 0xF0;
168 return 1;
169 }
170}
171
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200172unsigned update_flash (unsigned char *buf)
173{
174 switch ((*buf) & 0x3) {
175 case TRY_WORKING:
176 printf ("found 3 and converted it to 2\n");
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200177 write_flash ((char *)buf, (*buf) & 0xFE);
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200178 *((unsigned char *)0xFF800000) = 0xF0;
179 udelay (100);
180 printf ("buf [%#010x] %#010x\n", buf, (*buf));
181 /* XXX - fall through??? */
182 case BOOT_WORKING :
183 return BOOT_WORKING;
Wolfgang Denka48c7252005-09-25 18:59:36 +0200184 }
185 return BOOT_DEFAULT;
186}
187
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200188unsigned scan_flash (void)
Wolfgang Denka48c7252005-09-25 18:59:36 +0200189{
190 char section[] = "kernel";
Wolfgang Denka48c7252005-09-25 18:59:36 +0200191 int cfgFileLen = (CFG_FLASH_ERASE_SECTOR_LENGTH >> 1);
192 int sectionPtr = 0;
193 int foundItem = 0; /* 0: None, 1: section found, 2: "=" found */
194 int bufPtr;
195 unsigned char *buf;
196
197 buf = (unsigned char*)(CFG_FLASH_RANGE_BASE + CFG_FLASH_RANGE_SIZE \
198 - CFG_FLASH_ERASE_SECTOR_LENGTH);
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200199 for (bufPtr = 0; bufPtr < cfgFileLen; ++bufPtr) {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200200 if ((buf[bufPtr]==0xFF) && (*(int*)(buf+bufPtr)==0xFFFFFFFF)) {
201 return BOOT_DEFAULT;
202 }
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200203 /* This is the scanning loop, we try to find a particular
204 * quoted value
205 */
206 switch (foundItem) {
207 case 0:
208 if ((section[sectionPtr] == 0)) {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200209 ++foundItem;
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200210 } else if (buf[bufPtr] == section[sectionPtr]) {
211 ++sectionPtr;
212 } else {
213 sectionPtr = 0;
214 }
215 break;
216 case 1:
217 ++foundItem;
218 break;
219 case 2:
220 ++foundItem;
221 break;
222 case 3:
223 default:
224 return update_flash (&buf[bufPtr - 1]);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200225 }
226 }
227
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200228 printf ("Failed to read %s\n",section);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200229 return BOOT_DEFAULT;
230}
231
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200232TSBootInfo* find_boot_info (void)
Wolfgang Denka48c7252005-09-25 18:59:36 +0200233{
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200234 unsigned bootimage = scan_flash ();
235 TSBootInfo* info = (TSBootInfo*)malloc (sizeof(TSBootInfo));
Wolfgang Denka48c7252005-09-25 18:59:36 +0200236
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200237 switch (bootimage) {
238 case TRY_WORKING:
239 info->address = CFG_WORKING_KERNEL_ADDRESS;
240 break;
241 case BOOT_WORKING :
242 info->address = CFG_WORKING_KERNEL_ADDRESS;
243 break;
244 case BOOT_DEFAULT:
245 default:
246 info->address= CFG_DEFAULT_KERNEL_ADDRESS;
Wolfgang Denka48c7252005-09-25 18:59:36 +0200247
248 }
249 info->size = *((unsigned int *)(info->address ));
250
251 return info;
252}
253
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200254void barcobcd_boot (void)
Wolfgang Denka48c7252005-09-25 18:59:36 +0200255{
256 TSBootInfo* start;
257 char *bootm_args[2];
258 char *buf;
259 int cnt;
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200260 extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200261
262 buf = (char *)(0x00800000);
263 /* make certain there are enough chars to print the command line here!
264 */
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200265 bootm_args[0] = (char *)malloc (16*sizeof(char));
266 bootm_args[1] = (char *)malloc (16*sizeof(char));
Wolfgang Denka48c7252005-09-25 18:59:36 +0200267
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200268 start = find_boot_info ();
Wolfgang Denka48c7252005-09-25 18:59:36 +0200269
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200270 printf ("Booting kernel at address %#10x with size %#10x\n",
Wolfgang Denka48c7252005-09-25 18:59:36 +0200271 start->address, start->size);
272
273 /* give length of the kernel image to bootm */
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200274 sprintf (bootm_args[0],"%x",start->size);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200275 /* give address of the kernel image to bootm */
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200276 sprintf (bootm_args[1],"%x",buf);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200277
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200278 printf ("flash address: %#10x\n",start->address+8);
279 printf ("buf address: %#10x\n",buf);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200280
281 /* aha, we reserve 8 bytes here... */
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200282 for (cnt = 0; cnt < start->size ; cnt++) {
Wolfgang Denka48c7252005-09-25 18:59:36 +0200283 buf[cnt] = ((char *)start->address)[cnt+8];
284 }
285
286 /* initialise RAM memory */
287 *((unsigned int *)0xFEC00000) = 0x00141A98;
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200288 do_bootm (NULL,0,2,bootm_args);
Wolfgang Denka48c7252005-09-25 18:59:36 +0200289}
290
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200291int barcobcd_boot_image (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
Wolfgang Denka48c7252005-09-25 18:59:36 +0200292{
293#if 0
294 if (argc > 1) {
295 printf ("Usage:\n (%d) %s\n", argc, cmdtp->usage);
296 return 1;
297 }
298#endif
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200299 barcobcd_boot ();
Wolfgang Denka48c7252005-09-25 18:59:36 +0200300
301 return 0;
302}
303
304/* Currently, boot_working and boot_default are the same command. This is
305 * left in here to see what we'll do in the future */
306
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200307U_BOOT_CMD (
Wolfgang Denka48c7252005-09-25 18:59:36 +0200308 try_working, 1, 1, barcobcd_boot_image,
309 " try_working - check flash value and boot the appropriate image\n",
310 "\n"
311 );
312
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200313U_BOOT_CMD (
Wolfgang Denka48c7252005-09-25 18:59:36 +0200314 boot_working, 1, 1, barcobcd_boot_image,
315 " boot_working - check flash value and boot the appropriate image\n",
316 "\n"
317 );
318
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200319U_BOOT_CMD (
Wolfgang Denka48c7252005-09-25 18:59:36 +0200320 boot_default, 1, 1, barcobcd_boot_image,
321 " boot_default - check flash value and boot the appropriate image\n",
322 "\n"
323 );
324/*
325 * We are not using serial communication, so just provide empty functions
326 */
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200327int serial_init (void)
328{
329 return 0;
330}
331void serial_setbrg (void)
332{
333 return;
334}
335void serial_putc (const char c)
336{
337 return;
338}
339void serial_puts (const char *c)
340{
341 return;
342}
343void serial_addr (unsigned int i)
344{
345 return;
346}
347int serial_getc (void)
348{
349 return 0;
350}
351int serial_tstc (void)
352{
353 return 0;
354}
Wolfgang Denka48c7252005-09-25 18:59:36 +0200355
Wolfgang Denk27a5b0b2005-10-13 01:45:54 +0200356unsigned long post_word_load (void)
357{
358 return 0l;
359}
360void post_word_store (unsigned long val)
361{
362 return;
363}