u-boot/board/barco/barco.c
2005-09-25 18:59:36 +02:00

340 lines
8.1 KiB
C

/********************************************************************
*
* Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms
*
* $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/barco.c,v $
* $Revision: 1.4 $
* $Author: mleeman $
* $Date: 2005/03/02 16:40:20 $
*
* Last ChangeLog Entry
* $Log: barco.c,v $
* Revision 1.4 2005/03/02 16:40:20 mleeman
* remove empty labels (3.4 complains)
*
* Revision 1.3 2005/02/21 12:48:58 mleeman
* update of copyright years (feedback wd)
*
* Revision 1.2 2005/02/21 10:10:53 mleeman
* - split up switch statement to a function call (Linux kernel coding guidelines)
* ( feedback wd)
*
* Revision 1.1 2005/02/14 09:31:07 mleeman
* renaming of files
*
* Revision 1.1 2005/02/14 09:23:46 mleeman
* - moved 'barcohydra' directory to a more generic barco; since we will be
* supporting and adding multiple boards
*
* Revision 1.3 2005/02/10 13:57:32 mleeman
* fixed flash corruption: I should exit from the moment I find the correct value
*
* Revision 1.2 2005/02/09 12:56:23 mleeman
* add generic header to track changes in sources
*
*
*******************************************************************/
/*
* (C) Copyright 2004
* Marc Leeman <marc.leeman@barco.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <mpc824x.h>
#include <pci.h>
#include <malloc.h>
#include <command.h>
#include "config.h"
#include "barco_svc.h"
#define TRY_WORKING (3)
#define BOOT_DEFAULT (2)
#define BOOT_WORKING (1)
int checkboard (void)
{
/*TODO: Check processor type */
puts ( "Board: Streaming Video Card for Hydra systems "
#ifdef CONFIG_MPC8240
"8240"
#endif
#ifdef CONFIG_MPC8245
"8245"
#endif
" Unity ##Test not implemented yet##\n");
return 0;
}
long int initdram (int board_type)
{
long size;
long new_bank0_end;
long mear1;
long emear1;
size = get_ram_size(CFG_SDRAM_BASE, CFG_MAX_RAM_SIZE);
new_bank0_end = size - 1;
mear1 = mpc824x_mpc107_getreg(MEAR1);
emear1 = mpc824x_mpc107_getreg(EMEAR1);
mear1 = (mear1 & 0xFFFFFF00) |
((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT);
emear1 = (emear1 & 0xFFFFFF00) |
((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT);
mpc824x_mpc107_setreg(MEAR1, mear1);
mpc824x_mpc107_setreg(EMEAR1, emear1);
return (size);
}
/*
* Initialize PCI Devices, report devices found.
*/
#ifndef CONFIG_PCI_PNP
static struct pci_config_table pci_barcohydra_config_table[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0f, PCI_ANY_ID,
pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
PCI_ENET0_MEMADDR,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x10, PCI_ANY_ID,
pci_cfgfunc_config_device, { PCI_ENET1_IOADDR,
PCI_ENET1_MEMADDR,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
{ }
};
#endif
struct pci_controller hose = {
#ifndef CONFIG_PCI_PNP
config_table: pci_barcohydra_config_table,
#endif
};
void pci_init_board(void)
{
pci_mpc824x_init(&hose);
}
int write_flash(char *addr, char value)
{
char *adr = (char *)0xFF800000;
int cnt = 0;
char status,oldstatus;
*(adr+0x55) = 0xAA;
udelay(1);
*(adr+0xAA) = 0x55;
udelay(1);
*(adr+0x55) = 0xA0;
udelay(1);
*addr = value;
status = *addr;
do{
oldstatus = status;
status = *addr;
if ((oldstatus & 0x40) == (status & 0x40)){
return 4;
}
cnt++;
if (cnt > 10000){
return 2;
}
}while( (status & 0x20) == 0 );
oldstatus = *addr;
status = *addr;
if ((oldstatus & 0x40) == (status & 0x40)) return 0;
else {
*(adr+0x55) = 0xF0;
return 1;
}
}
unsigned update_flash(unsigned char* buf){
switch((*buf) & 0x3){
case TRY_WORKING:
printf("found 3 and converted it to 2\n");
write_flash(buf, (*buf) & 0xFE);
*((unsigned char *)0xFF800000) = 0xF0;
udelay(100);
printf("buf [%#010x] %#010x\n",buf,(*buf));
case BOOT_WORKING :
return BOOT_WORKING;
}
return BOOT_DEFAULT;
}
unsigned scan_flash(void)
{
char section[] = "kernel";
ulong sp;
int cfgFileLen = (CFG_FLASH_ERASE_SECTOR_LENGTH >> 1);
int sectionPtr = 0;
int foundItem = 0; /* 0: None, 1: section found, 2: "=" found */
int bufPtr;
unsigned char *buf;
buf = (unsigned char*)(CFG_FLASH_RANGE_BASE + CFG_FLASH_RANGE_SIZE \
- CFG_FLASH_ERASE_SECTOR_LENGTH);
for(bufPtr = 0; bufPtr < cfgFileLen; ++bufPtr){
if ((buf[bufPtr]==0xFF) && (*(int*)(buf+bufPtr)==0xFFFFFFFF)) {
return BOOT_DEFAULT;
}
switch(foundItem)
{
/* This is the scanning loop, we try to find a particular
* quoted value
*/
case 0:
if((section[sectionPtr] == 0)){
++foundItem;
}
else if(buf[bufPtr] == section[sectionPtr]){
++sectionPtr;
}
else {
sectionPtr = 0;
}
break;
case 1:
++foundItem;
break;
case 2:
++foundItem;
break;
case 3:
default:
return update_flash(buf[bufPtr - 1]);
}
}
printf("Failed to read %s\n",section);
return BOOT_DEFAULT;
}
TSBootInfo* find_boot_info(void)
{
unsigned bootimage = scan_flash();
TSBootInfo* info = (TSBootInfo*)malloc(sizeof(TSBootInfo));
switch(bootimage){
case TRY_WORKING:
info->address = CFG_WORKING_KERNEL_ADDRESS;
break;
case BOOT_WORKING :
info->address = CFG_WORKING_KERNEL_ADDRESS;
break;
case BOOT_DEFAULT:
default:
info->address= CFG_DEFAULT_KERNEL_ADDRESS;
}
info->size = *((unsigned int *)(info->address ));
return info;
}
void barcobcd_boot(void)
{
TSBootInfo* start;
char *bootm_args[2];
char *buf;
int cnt;
buf = (char *)(0x00800000);
/* make certain there are enough chars to print the command line here!
*/
bootm_args[0]=(char *)malloc(16*sizeof(char));
bootm_args[1]=(char *)malloc(16*sizeof(char));
start = find_boot_info();
printf("Booting kernel at address %#10x with size %#10x\n",
start->address, start->size);
/* give length of the kernel image to bootm */
sprintf(bootm_args[0],"%x",start->size);
/* give address of the kernel image to bootm */
sprintf(bootm_args[1],"%x",buf);
printf("flash address: %#10x\n",start->address+8);
printf("buf address: %#10x\n",buf);
/* aha, we reserve 8 bytes here... */
for (cnt = 0; cnt < start->size ; cnt++){
buf[cnt] = ((char *)start->address)[cnt+8];
}
/* initialise RAM memory */
*((unsigned int *)0xFEC00000) = 0x00141A98;
do_bootm(NULL,0,2,bootm_args);
}
int barcobcd_boot_image(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
#if 0
if (argc > 1) {
printf ("Usage:\n (%d) %s\n", argc, cmdtp->usage);
return 1;
}
#endif
barcobcd_boot();
return 0;
}
/* Currently, boot_working and boot_default are the same command. This is
* left in here to see what we'll do in the future */
U_BOOT_CMD(
try_working, 1, 1, barcobcd_boot_image,
" try_working - check flash value and boot the appropriate image\n",
"\n"
);
U_BOOT_CMD(
boot_working, 1, 1, barcobcd_boot_image,
" boot_working - check flash value and boot the appropriate image\n",
"\n"
);
U_BOOT_CMD(
boot_default, 1, 1, barcobcd_boot_image,
" boot_default - check flash value and boot the appropriate image\n",
"\n"
);
/*
* We are not using serial communication, so just provide empty functions
*/
int serial_init(void){return 0;}
void serial_setbrg(void){}
void serial_putc(const char c){}
void serial_puts(const char *c){}
void serial_addr(unsigned int i){}
int serial_getc(void){return 0;}
int serial_tstc(void){return 0;}
unsigned long post_word_load(void){return 0l;};
void post_word_store(unsigned long val){}