Initial revision
This commit is contained in:
parent
c609719b8d
commit
f9087a3213
522
board/RRvision/flash.c
Normal file
522
board/RRvision/flash.c
Normal file
@ -0,0 +1,522 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc8xx.h>
|
||||
|
||||
#ifndef CFG_ENV_ADDR
|
||||
#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
|
||||
#endif
|
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Functions
|
||||
*/
|
||||
static ulong flash_get_size (vu_long *addr, flash_info_t *info);
|
||||
static int write_word (flash_info_t *info, ulong dest, ulong data);
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
unsigned long flash_init (void)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *)CFG_IMMR;
|
||||
volatile memctl8xx_t *memctl = &immap->im_memctl;
|
||||
unsigned long size;
|
||||
int i;
|
||||
|
||||
/* Init: no FLASHes known */
|
||||
for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
|
||||
flash_info[i].flash_id = FLASH_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Static FLASH Bank configuration here - FIXME XXX */
|
||||
|
||||
size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
|
||||
|
||||
if (flash_info[0].flash_id == FLASH_UNKNOWN) {
|
||||
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
|
||||
size, size<<20);
|
||||
}
|
||||
|
||||
/* Remap FLASH according to real size */
|
||||
memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size & OR_AM_MSK);
|
||||
memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
|
||||
|
||||
/* Re-do sizing to get full correct info */
|
||||
size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
|
||||
|
||||
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
|
||||
/* monitor protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_MONITOR_BASE,
|
||||
CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
|
||||
&flash_info[0]);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_ENV_IS_IN_FLASH
|
||||
/* ENV protection ON by default */
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_ENV_ADDR,
|
||||
CFG_ENV_ADDR+CFG_ENV_SIZE-1,
|
||||
&flash_info[0]);
|
||||
#endif
|
||||
|
||||
flash_info[0].size = size;
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
void flash_print_info (flash_info_t *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
puts ("missing or unknown FLASH type\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_VENDMASK) {
|
||||
case FLASH_MAN_AMD: puts ("AMD "); break;
|
||||
case FLASH_MAN_FUJ: puts ("FUJITSU "); break;
|
||||
default: puts ("Unknown Vendor "); break;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_TYPEMASK) {
|
||||
case FLASH_AM400B: puts ("AM29LV400B (4 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM400T: puts ("AM29LV400T (4 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM800B: puts ("AM29LV800B (8 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM800T: puts ("AM29LV800T (8 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM160B: puts ("AM29LV160B (16 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM160T: puts ("AM29LV160T (16 Mbit, top boot sector)\n");
|
||||
break;
|
||||
case FLASH_AM320B: puts ("AM29LV320B (32 Mbit, bottom boot sect)\n");
|
||||
break;
|
||||
case FLASH_AM320T: puts ("AM29LV320T (32 Mbit, top boot sector)\n");
|
||||
break;
|
||||
default: puts ("Unknown Chip Type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf (" Size: %ld MB in %d Sectors\n",
|
||||
info->size >> 20, info->sector_count);
|
||||
|
||||
puts (" Sector Start Addresses:");
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
if ((i % 5) == 0)
|
||||
puts ("\n ");
|
||||
printf (" %08lX%s",
|
||||
info->start[i],
|
||||
info->protect[i] ? " (RO)" : " "
|
||||
);
|
||||
}
|
||||
puts ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following code cannot be run from FLASH!
|
||||
*/
|
||||
|
||||
static ulong flash_get_size (vu_long *addr, flash_info_t *info)
|
||||
{
|
||||
short i;
|
||||
ulong value;
|
||||
ulong base = (ulong)addr;
|
||||
|
||||
/* Write auto select command: read Manufacturer ID */
|
||||
addr[0x0555] = 0x00AA00AA;
|
||||
addr[0x02AA] = 0x00550055;
|
||||
addr[0x0555] = 0x00900090;
|
||||
|
||||
value = addr[0];
|
||||
|
||||
switch (value) {
|
||||
case AMD_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_AMD;
|
||||
break;
|
||||
case FUJ_MANUFACT:
|
||||
info->flash_id = FLASH_MAN_FUJ;
|
||||
break;
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
info->sector_count = 0;
|
||||
info->size = 0;
|
||||
return (0); /* no or unknown flash */
|
||||
}
|
||||
|
||||
value = addr[1]; /* device ID */
|
||||
|
||||
switch (value) {
|
||||
case AMD_ID_LV400T:
|
||||
info->flash_id += FLASH_AM400T;
|
||||
info->sector_count = 11;
|
||||
info->size = 0x00100000;
|
||||
break; /* => 1 MB */
|
||||
|
||||
case AMD_ID_LV400B:
|
||||
info->flash_id += FLASH_AM400B;
|
||||
info->sector_count = 11;
|
||||
info->size = 0x00100000;
|
||||
break; /* => 1 MB */
|
||||
|
||||
case AMD_ID_LV800T:
|
||||
info->flash_id += FLASH_AM800T;
|
||||
info->sector_count = 19;
|
||||
info->size = 0x00200000;
|
||||
break; /* => 2 MB */
|
||||
|
||||
case AMD_ID_LV800B:
|
||||
info->flash_id += FLASH_AM800B;
|
||||
info->sector_count = 19;
|
||||
info->size = 0x00200000;
|
||||
break; /* => 2 MB */
|
||||
|
||||
case AMD_ID_LV160T:
|
||||
info->flash_id += FLASH_AM160T;
|
||||
info->sector_count = 35;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
|
||||
case AMD_ID_LV160B:
|
||||
info->flash_id += FLASH_AM160B;
|
||||
info->sector_count = 35;
|
||||
info->size = 0x00400000;
|
||||
break; /* => 4 MB */
|
||||
case AMD_ID_LV320T:
|
||||
info->flash_id += FLASH_AM320T;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00800000;
|
||||
break; /* => 8 MB */
|
||||
|
||||
case AMD_ID_LV320B:
|
||||
info->flash_id += FLASH_AM320B;
|
||||
info->sector_count = 71;
|
||||
info->size = 0x00800000;
|
||||
break; /* => 8 MB */
|
||||
default:
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
return (0); /* => no or unknown flash */
|
||||
}
|
||||
|
||||
/* set up sector start address table */
|
||||
switch (value) {
|
||||
case AMD_ID_LV400B:
|
||||
case AMD_ID_LV800B:
|
||||
case AMD_ID_LV160B:
|
||||
/* set sector offsets for bottom boot block type */
|
||||
info->start[0] = base + 0x00000000;
|
||||
info->start[1] = base + 0x00008000;
|
||||
info->start[2] = base + 0x0000C000;
|
||||
info->start[3] = base + 0x00010000;
|
||||
for (i = 4; i < info->sector_count; i++) {
|
||||
info->start[i] = base + (i * 0x00020000) - 0x00060000;
|
||||
}
|
||||
break;
|
||||
case AMD_ID_LV400T:
|
||||
case AMD_ID_LV800T:
|
||||
case AMD_ID_LV160T:
|
||||
/* set sector offsets for top boot block type */
|
||||
i = info->sector_count - 1;
|
||||
info->start[i--] = base + info->size - 0x00008000;
|
||||
info->start[i--] = base + info->size - 0x0000C000;
|
||||
info->start[i--] = base + info->size - 0x00010000;
|
||||
for (; i >= 0; i--) {
|
||||
info->start[i] = base + i * 0x00020000;
|
||||
}
|
||||
break;
|
||||
case AMD_ID_LV320B:
|
||||
for (i = 0; i < info->sector_count; i++) {
|
||||
info->start[i] = base;
|
||||
/*
|
||||
* The first 8 sectors are 8 kB,
|
||||
* all the other ones are 64 kB
|
||||
*/
|
||||
base += (i < 8)
|
||||
? 2 * ( 8 << 10)
|
||||
: 2 * (64 << 10);
|
||||
}
|
||||
break;
|
||||
case AMD_ID_LV320T:
|
||||
for (i = 0; i < info->sector_count; i++) {
|
||||
info->start[i] = base;
|
||||
/*
|
||||
* The last 8 sectors are 8 kB,
|
||||
* all the other ones are 64 kB
|
||||
*/
|
||||
base += (i < (info->sector_count - 8))
|
||||
? 2 * (64 << 10)
|
||||
: 2 * ( 8 << 10);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for protected sectors */
|
||||
for (i = 0; i < info->sector_count; i++) {
|
||||
/* read sector protection at sector address, (A7 .. A0) = 0x02 */
|
||||
/* D0 = 1 if protected */
|
||||
addr = (volatile unsigned long *)(info->start[i]);
|
||||
info->protect[i] = addr[2] & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent writes to uninitialized FLASH.
|
||||
*/
|
||||
if (info->flash_id != FLASH_UNKNOWN) {
|
||||
addr = (volatile unsigned long *)info->start[0];
|
||||
|
||||
*addr = 0x00F000F0; /* reset bank */
|
||||
}
|
||||
|
||||
return (info->size);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int flash_erase (flash_info_t *info, int s_first, int s_last)
|
||||
{
|
||||
vu_long *addr = (vu_long*)(info->start[0]);
|
||||
int flag, prot, sect, l_sect;
|
||||
ulong start, now, last;
|
||||
|
||||
if ((s_first < 0) || (s_first > s_last)) {
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
puts ("- missing\n");
|
||||
} else {
|
||||
puts ("- no sectors to erase\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((info->flash_id == FLASH_UNKNOWN) ||
|
||||
(info->flash_id > FLASH_AMD_COMP)) {
|
||||
printf ("Can't erase unknown flash type %08lx - aborted\n",
|
||||
info->flash_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
prot = 0;
|
||||
for (sect=s_first; sect<=s_last; ++sect) {
|
||||
if (info->protect[sect]) {
|
||||
prot++;
|
||||
}
|
||||
}
|
||||
|
||||
if (prot) {
|
||||
printf ("- Warning: %d protected sectors will not be erased!\n",
|
||||
prot);
|
||||
} else {
|
||||
puts ("\n");
|
||||
}
|
||||
|
||||
l_sect = -1;
|
||||
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
addr[0x0555] = 0x00AA00AA;
|
||||
addr[0x02AA] = 0x00550055;
|
||||
addr[0x0555] = 0x00800080;
|
||||
addr[0x0555] = 0x00AA00AA;
|
||||
addr[0x02AA] = 0x00550055;
|
||||
|
||||
/* Start erase on unprotected sectors */
|
||||
for (sect = s_first; sect<=s_last; sect++) {
|
||||
if (info->protect[sect] == 0) { /* not protected */
|
||||
addr = (vu_long*)(info->start[sect]);
|
||||
addr[0] = 0x00300030;
|
||||
l_sect = sect;
|
||||
}
|
||||
}
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
/* wait at least 80us - let's wait 1 ms */
|
||||
udelay (1000);
|
||||
|
||||
/*
|
||||
* We wait for the last triggered sector
|
||||
*/
|
||||
if (l_sect < 0)
|
||||
goto DONE;
|
||||
|
||||
start = get_timer (0);
|
||||
last = start;
|
||||
addr = (vu_long*)(info->start[l_sect]);
|
||||
while ((addr[0] & 0x00800080) != 0x00800080) {
|
||||
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
|
||||
puts ("Timeout\n");
|
||||
return 1;
|
||||
}
|
||||
/* show that we're waiting */
|
||||
if ((now - last) > 1000) { /* every second */
|
||||
putc ('.');
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
/* reset to read mode */
|
||||
addr = (volatile unsigned long *)info->start[0];
|
||||
addr[0] = 0x00F000F0; /* reset bank */
|
||||
|
||||
puts (" done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Copy memory to flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
|
||||
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
|
||||
{
|
||||
ulong cp, wp, data;
|
||||
int i, l, rc;
|
||||
|
||||
wp = (addr & ~3); /* get lower word aligned address */
|
||||
|
||||
/*
|
||||
* handle unaligned start bytes
|
||||
*/
|
||||
if ((l = addr - wp) != 0) {
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<l; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
for (; i<4 && cnt>0; ++i) {
|
||||
data = (data << 8) | *src++;
|
||||
--cnt;
|
||||
++cp;
|
||||
}
|
||||
for (; cnt==0 && i<4; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
|
||||
if ((rc = write_word(info, wp, data)) != 0) {
|
||||
return (rc);
|
||||
}
|
||||
wp += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle word aligned part
|
||||
*/
|
||||
while (cnt >= 4) {
|
||||
data = 0;
|
||||
for (i=0; i<4; ++i) {
|
||||
data = (data << 8) | *src++;
|
||||
}
|
||||
if ((rc = write_word(info, wp, data)) != 0) {
|
||||
return (rc);
|
||||
}
|
||||
wp += 4;
|
||||
cnt -= 4;
|
||||
}
|
||||
|
||||
if (cnt == 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* handle unaligned tail bytes
|
||||
*/
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
|
||||
data = (data << 8) | *src++;
|
||||
--cnt;
|
||||
}
|
||||
for (; i<4; ++i, ++cp) {
|
||||
data = (data << 8) | (*(uchar *)cp);
|
||||
}
|
||||
|
||||
return (write_word(info, wp, data));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Write a word to Flash, returns:
|
||||
* 0 - OK
|
||||
* 1 - write timeout
|
||||
* 2 - Flash not erased
|
||||
*/
|
||||
static int write_word (flash_info_t *info, ulong dest, ulong data)
|
||||
{
|
||||
vu_long *addr = (vu_long*)(info->start[0]);
|
||||
ulong start;
|
||||
int flag;
|
||||
|
||||
/* Check if Flash is (sufficiently) erased */
|
||||
if ((*((vu_long *)dest) & data) != data) {
|
||||
return (2);
|
||||
}
|
||||
/* Disable interrupts which might cause a timeout here */
|
||||
flag = disable_interrupts();
|
||||
|
||||
addr[0x0555] = 0x00AA00AA;
|
||||
addr[0x02AA] = 0x00550055;
|
||||
addr[0x0555] = 0x00A000A0;
|
||||
|
||||
*((vu_long *)dest) = data;
|
||||
|
||||
/* re-enable interrupts if necessary */
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
/* data polling for D7 */
|
||||
start = get_timer (0);
|
||||
while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
|
||||
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
43
board/bmw/Makefile
Normal file
43
board/bmw/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# (C) Copyright 2002
|
||||
# James F. Dougherty, Broadcom Corporation, jfd@broadcom.com
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# 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 $(TOPDIR)/config.mk
|
||||
|
||||
LIB = lib$(BOARD).a
|
||||
|
||||
OBJS = $(BOARD).o flash.o ns16550.o serial.o m48t59y.o
|
||||
|
||||
SOBJS = early_init.o
|
||||
|
||||
$(LIB): .depend $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $^
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
340
board/bmw/README
Normal file
340
board/bmw/README
Normal file
@ -0,0 +1,340 @@
|
||||
Broadcom 95xx BMW CPCI Platform
|
||||
|
||||
Overview
|
||||
=========
|
||||
BMW is an MPC8245 system controller featuring:
|
||||
* 3U CPCI Form Factor
|
||||
* BCM5703 Gigabit Ethernet
|
||||
* M48T59Y NVRAM
|
||||
* 16MB DOC
|
||||
* DIP Socket for Socketed DOC up to 1GB
|
||||
* 64MB SDRAM
|
||||
* LCD Display
|
||||
* Configurable Jumper options for 66,85, and 100Mhz memory bus
|
||||
|
||||
|
||||
BMW System Address Map
|
||||
======================
|
||||
BMW uses the MPC8245 CHRP Address MAP B found in the MPC8245 Users Manual
|
||||
(P.121, Section 3.1 Address Maps, Address Map B). Other I/O devices found
|
||||
onboard the processor module are listed briefly below:
|
||||
|
||||
0x00000000 - 0x40000000 - 64MB SDRAM SIMM
|
||||
(Unregistered PC-100 SDRAM DIMM Module)
|
||||
|
||||
0xFF000000 - 0xFF001FFF - M-Systems DiskOnChip (TM) 2000
|
||||
TSOP 16MB (MD2211-D16-V3)
|
||||
|
||||
0x70000000 - 0x70001FFF - M-Systems DiskOnChip (TM) 2000
|
||||
DIP32 (Socketed 16MB - 1GB ) *
|
||||
NOTE: this is not populated on all systems.
|
||||
|
||||
0x7c000000 - 0x7c000000 - Reset Register
|
||||
(Write 0 to reset)
|
||||
|
||||
0x7c000001 - 0x7c000001 - System LED
|
||||
(Clear Bit 7 to turn on, set to shut off)
|
||||
|
||||
0x7c000002 - 0x7c000002 - M48T59 Watchdog IRQ3
|
||||
(Clear bit 7 to reset, set to assert IRQ3)
|
||||
|
||||
0x7c000003 - 0x7c000003 - M48T59 Write-Protect Register
|
||||
(Clear bit 7 to make R/W, set to make R/O)
|
||||
|
||||
0x7c002000 - 0x7c002003 - Infineon OSRAM DLR2416 4 Character
|
||||
5x7 Dot Matrix Alphanumeric Display
|
||||
(Each byte sets the appropriate character)
|
||||
|
||||
0x7c004000 - 0x7c005FF0 - SGS-THOMSON M48T59Y 8K NVRAM/RTC
|
||||
NVRAM Memory Region
|
||||
|
||||
0x7c005FF0 - 0x7c005FFF - SGS-THOMSON M48T59Y 8K NVRAM/RTC
|
||||
Realtime Clock Registers
|
||||
|
||||
0xFFF00000 - 0xFFF80000 - 512K PLCC32 BootRom
|
||||
(AMD AM29F040, ST 29W040B)
|
||||
|
||||
0xFFF00100 - System Reset Vector
|
||||
|
||||
|
||||
IO/MMU (BAT) Configuration
|
||||
======================
|
||||
The following Block-Address-Translation (BAT) configuration
|
||||
is recommended to access all I/O devices.
|
||||
|
||||
#define CFG_IBAT0L (0x00000000 | BATL_PP_10 | BATL_MEMCOHERENCE)
|
||||
#define CFG_IBAT0U (0x00000000 | BATU_BL_256M | BATU_VS | BATU_VP)
|
||||
|
||||
#define CFG_IBAT1L (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
|
||||
#define CFG_IBAT1U (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP)
|
||||
|
||||
#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
|
||||
#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP)
|
||||
|
||||
#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT)
|
||||
#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP)
|
||||
|
||||
#define CFG_DBAT0L CFG_IBAT0L
|
||||
#define CFG_DBAT0U CFG_IBAT0U
|
||||
#define CFG_DBAT1L CFG_IBAT1L
|
||||
#define CFG_DBAT1U CFG_IBAT1U
|
||||
#define CFG_DBAT2L CFG_IBAT2L
|
||||
#define CFG_DBAT2U CFG_IBAT2U
|
||||
#define CFG_DBAT3L CFG_IBAT3L
|
||||
#define CFG_DBAT3U CFG_IBAT3U
|
||||
|
||||
|
||||
Interrupt Mappings
|
||||
======================
|
||||
BMW uses MPC8245 discrete mode interrupts. With the following
|
||||
hardwired mappings:
|
||||
|
||||
BCM5701 10/100/1000 Ethernet IRQ1
|
||||
CompactPCI Interrupt A IRQ2
|
||||
RTC/Watchdog Interrupt IRQ3
|
||||
Internal NS16552 UART IRQ4
|
||||
|
||||
|
||||
Jumper Settings
|
||||
======================
|
||||
|
||||
BMW has a jumper (JP600) for selecting 66, 85, or 100Mhz memory bus.
|
||||
A jumper (X) is a 0 bit.
|
||||
|
||||
Hence 66= 10110
|
||||
85= 11000
|
||||
100= 10000
|
||||
|
||||
Jumper Settings for various Speeds
|
||||
=======================
|
||||
J1 J2 J3 J4 J5
|
||||
X X 66Mhz
|
||||
=======================
|
||||
J1 J2 J3 J4 J5
|
||||
X X X 85Mhz
|
||||
=======================
|
||||
J1 J2 J3 J4 J5
|
||||
X X X X 100Mhz
|
||||
=======================
|
||||
|
||||
Obviously, 100Mhz memory bus is recommended for optimum performance.
|
||||
|
||||
|
||||
U-Boot
|
||||
===============
|
||||
Broadcom BMW board is supported under config_BWM option.
|
||||
Supported features:
|
||||
|
||||
- NVRAM setenv/getenv (used by Linux Kernel for configuration variables)
|
||||
- BCM570x TFTP file transfer support
|
||||
- LCD Display Support
|
||||
- DOC Support - (underway)
|
||||
|
||||
|
||||
|
||||
U-Boot 1.2.0 (Aug 6 2002 - 17:44:48)
|
||||
|
||||
CPU: MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache
|
||||
Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)
|
||||
Built: Aug 6 2002 at 17:44:37
|
||||
Local Bus at 66 MHz
|
||||
DRAM: 64 MB
|
||||
FLASH: 4095 MB
|
||||
In: serial
|
||||
Out: serial
|
||||
Err: serial
|
||||
DOC: No DiskOnChip found
|
||||
Hit any key to stop autoboot: 0
|
||||
=>printenv
|
||||
bootdelay=5
|
||||
baudrate=9600
|
||||
clocks_in_mhz=1
|
||||
hostname=switch-2
|
||||
bootcmd=tftp 100000 vmlinux.img;bootm
|
||||
gateway=10.16.64.1
|
||||
ethaddr=00:00:10:18:10:10
|
||||
nfsroot=172.16.40.111:/boot/root-fs
|
||||
filesize=5ec8c
|
||||
netmask=255.255.240.0
|
||||
ipaddr=172.16.40.114
|
||||
serverip=172.16.40.111
|
||||
root=/dev/nfs
|
||||
stdin=serial
|
||||
stdout=serial
|
||||
stderr=serial
|
||||
|
||||
Environment size: 315/8172 bytes
|
||||
=>boot
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DevTools
|
||||
========
|
||||
ELDK
|
||||
DENX Embedded Linux Development Kit
|
||||
|
||||
ROM Emulator
|
||||
Grammar Engine PROMICE P1160-90-AI21E (2MBx8bit, 90ns access time)
|
||||
Grammar Engine PL32E 32Pin PLCC Emulation cables
|
||||
Grammar Engine 3VA8CON (3Volt adapter with Short cables)
|
||||
Grammar Engine FPNET PromICE Ethernet Adapters
|
||||
|
||||
ICE
|
||||
WRS/EST VisionICE-II (PPC8240)
|
||||
|
||||
|
||||
|
||||
=>reset
|
||||
|
||||
|
||||
U-Boot 1.2.0 (Aug 6 2002 - 17:44:48)
|
||||
|
||||
CPU: MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache
|
||||
Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B)
|
||||
Built: Aug 6 2002 at 17:44:37
|
||||
Local Bus at 66 MHz
|
||||
DRAM: 64 MB
|
||||
FLASH: 4095 MB
|
||||
In: serial
|
||||
Out: serial
|
||||
Err: serial
|
||||
DOC: No DiskOnChip found
|
||||
Hit any key to stop autoboot: 0
|
||||
|
||||
Broadcom BCM5701 1000Base-T: bus 0, device 13, function 0: MBAR=0x80100000
|
||||
BCM570x PCI Memory base address @0x80100000
|
||||
eth0:Broadcom BCM5701 1000Base-T: 100 Mbps half duplex link up, flow control OFF
|
||||
eth0: Broadcom BCM5701 1000Base-T @0x80100000,node addr 000010181010
|
||||
eth0: BCM5700 with Broadcom BCM5701 Integrated Copper transceiver found
|
||||
eth0: 32-bit PCI 33MHz, MTU: 1500,Rx Checksum ON
|
||||
ARP broadcast 1
|
||||
TFTP from server 172.16.40.111; our IP address is 172.16.40.114
|
||||
Filename 'vmlinux.img'.
|
||||
Load address: 0x100000
|
||||
Loading: #################################################################
|
||||
####################################T #############################
|
||||
######################
|
||||
done
|
||||
Bytes transferred = 777199 (bdbef hex)
|
||||
|
||||
eth0:Broadcom BCM5701 1000Base-T,HALT,POWER DOWN,done - offline.
|
||||
## Booting image at 00100000 ...
|
||||
Image Name: vmlinux.bin.gz
|
||||
Created: 2002-08-06 6:30:13 UTC
|
||||
Image Type: PowerPC Linux Kernel Image (gzip compressed)
|
||||
Data Size: 777135 Bytes = 758 kB = 0 MB
|
||||
Load Address: 00000000
|
||||
Entry Point: 00000000
|
||||
Verifying Checksum ... OK
|
||||
Uncompressing Kernel Image ... OK
|
||||
Memory BAT mapping: BAT2=64Mb, BAT3=0Mb, residual: 0Mb
|
||||
Linux version 2.4.19-rc3 (jfd@que) (gcc version 2.95.3 20010111 (prerelease/franzo/20010111)) #168 Mon Aug 5 23:29:20 PDT 2002
|
||||
CPU:82xx: 32 I-Cache Block Size, 32 D-Cache Block Size PVR: 0x810000
|
||||
U-Boot Environment: 0xc01b08f0
|
||||
IP PNP: 802.3 Ethernet Address=<0:0:10:18:10:10>
|
||||
cpu0: MPC8245/KAHLUA-II : BMW Platform : 64MB RAM: BPLD Rev. 6e
|
||||
NOTICE: mounting root file system via NFS
|
||||
IP PNP: switch-2: eth0 IP 172.16.40.114/255.255.240.0 gateway 10.16.64.1 server 172.16.40.111
|
||||
On node 0 totalpages: 16384
|
||||
zone(0): 16384 pages.
|
||||
zone(1): 0 pages.
|
||||
zone(2): 0 pages.
|
||||
Kernel command line: console=ttyS0,9600 ip=172.16.40.114:172.16.40.111:10.16.64.1:255.255.240.0:switch-2:eth0 root=/dev/nfs rw nfsroot=172.16.40.111:/boot/root-fs,timeo=200,retrans=500 nfsaddrs=172.16.40.114:172.16.40.111
|
||||
root_dev_setup:/dev/nfs or 00:ff
|
||||
time_init: decrementer frequency = 16.501145 MHz
|
||||
Calibrating delay loop... 175.71 BogoMIPS
|
||||
Memory: 62572k available (1396k kernel code, 436k data, 100k init, 0k highmem)
|
||||
Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
|
||||
Inode cache hash table entries: 4096 (order: 3, 32768 bytes)
|
||||
Mount-cache hash table entries: 1024 (order: 1, 8192 bytes)
|
||||
Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes)
|
||||
Page-cache hash table entries: 16384 (order: 4, 65536 bytes)
|
||||
POSIX conformance testing by UNIFIX
|
||||
PCI: Probing PCI hardware
|
||||
Linux NET4.0 for Linux 2.4
|
||||
Based upon Swansea University Computer Society NET3.039
|
||||
Initializing RT netlink socket
|
||||
Starting kswapd
|
||||
devfs: v1.12a (20020514) Richard Gooch (rgooch@atnf.csiro.au)
|
||||
devfs: devfs_debug: 0x0
|
||||
devfs: boot_options: 0x1
|
||||
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
|
||||
pty: 256 Unix98 ptys configured
|
||||
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
|
||||
Testing ttyS0 (0xf7f51500, 0xf7f51500)...
|
||||
Testing ttyS1 (0xfc004600, 0xfc004600)...
|
||||
ttyS00 at 0xf7f51500 (irq = 24) is a ST16650
|
||||
ttyS01 at 0xfc004600 (irq = 25) is a 16550A
|
||||
Real Time Clock Driver v1.10e
|
||||
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
|
||||
loop: loaded (max 8 devices)
|
||||
TFFS 5.1.1 Flash disk driver for DiskOnChip
|
||||
Copyright (C) 1998,2001 M-Systems Flash Disk Pioneers Ltd.
|
||||
DOC device(s) found: 1
|
||||
fl_init: registered device at major: 100
|
||||
fl_geninit: registered device at major: 100
|
||||
Partition check:
|
||||
fla: p1
|
||||
partition: /dev/fl/0: start_sect: 0,nr_sects: 32000 Fl_blk_size[]: 16000KB
|
||||
partition: /dev/fl/1: start_sect: 2,nr_sects: 31998 Fl_blk_size[]: 15999KB
|
||||
partition: /dev/fl/2: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB
|
||||
partition: /dev/fl/3: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB
|
||||
Broadcom Gigabit Ethernet Driver bcm5700 ver. 3.0.7 (07/17/02)
|
||||
eth0: Broadcom BCM5701 found at mem bfff0000, IRQ 1, node addr 000010181010
|
||||
eth0: Broadcom BCM5701 Integrated Copper transceiver found
|
||||
eth0: Scatter-gather ON, 64-bit DMA ON, Tx Checksum ON, Rx Checksum ON, 802.1Q VLAN ON
|
||||
bond0 registered without MII link monitoring, in bonding mode.
|
||||
rtc: unable to get misc minor
|
||||
NET4: Linux TCP/IP 1.0 for NET4.0
|
||||
IP Protocols: ICMP, UDP, TCP, IGMP
|
||||
IP: routing cache hash table of 512 buckets, 4Kbytes
|
||||
TCP: Hash tables configured (established 4096 bind 4096)
|
||||
bcm5700: eth0 NIC Link is UP, 100 Mbps half duplex
|
||||
IP-Config: Gateway not on directly connected network.
|
||||
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
|
||||
802.1Q VLAN Support v1.7 Ben Greear <greearb@candelatech.com>
|
||||
All bugs added by David S. Miller <davem@redhat.com>
|
||||
Looking up port of RPC 100003/2 on 172.16.40.111
|
||||
Looking up port of RPC 100005/1 on 172.16.40.111
|
||||
VFS: Mounted root (nfs filesystem).
|
||||
Mounted devfs on /dev
|
||||
Freeing unused kernel memory: 100k init
|
||||
INIT: version 2.78 booting
|
||||
Mounting local filesystems...
|
||||
not mounted anything
|
||||
Setting up symlinks in /dev...done.
|
||||
Setting up extra devices in /dev...done.
|
||||
Starting devfsd...Started device management daemon for /dev
|
||||
INIT: Entering runlevel: 2
|
||||
Starting internet superserver: inetd.
|
||||
|
||||
|
||||
Welcome to Linux/PPC
|
||||
MPC8245/BMW
|
||||
|
||||
|
||||
|
||||
switch-2 login: root
|
||||
Password:
|
||||
PAM_unix[49]: (login) session opened for user root by LOGIN(uid=0)
|
||||
Last login: Thu Nov 25 11:51:14 1920 on console
|
||||
|
||||
|
||||
Welcome to Linux/PPC
|
||||
MPC8245/BMW
|
||||
|
||||
|
||||
|
||||
login[49]: ROOT LOGIN on `console'
|
||||
|
||||
root@switch-2:~# cat /proc/cpuinfo
|
||||
cpu : 82xx
|
||||
revision : 16.20 (pvr 8081 1014)
|
||||
bogomips : 175.71
|
||||
vendor : Broadcom
|
||||
machine : BMW/MPC8245
|
||||
root@switch-2:~#
|
323
board/bmw/m48t59y.c
Normal file
323
board/bmw/m48t59y.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* SGS M48-T59Y TOD/NVRAM Driver
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp.
|
||||
*
|
||||
* (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* SGS M48-T59Y TOD/NVRAM Driver
|
||||
*
|
||||
* The SGS M48 an 8K NVRAM starting at offset M48_BASE_ADDR and
|
||||
* continuing for 8176 bytes. After that starts the Time-Of-Day (TOD)
|
||||
* registers which are used to set/get the internal date/time functions.
|
||||
*
|
||||
* This module implements Y2K compliance by taking full year numbers
|
||||
* and translating back and forth from the TOD 2-digit year.
|
||||
*
|
||||
* NOTE: for proper interaction with an operating system, the TOD should
|
||||
* be used to store Universal Coordinated Time (GMT) and timezone
|
||||
* conversions should be used.
|
||||
*
|
||||
* Here is a diagram of the memory layout:
|
||||
*
|
||||
* +---------------------------------------------+ 0xffe0a000
|
||||
* | Non-volatile memory | .
|
||||
* | | .
|
||||
* | (8176 bytes of Non-volatile memory) | .
|
||||
* | | .
|
||||
* +---------------------------------------------+ 0xffe0bff0
|
||||
* | Flags |
|
||||
* +---------------------------------------------+ 0xffe0bff1
|
||||
* | Unused |
|
||||
* +---------------------------------------------+ 0xffe0bff2
|
||||
* | Alarm Seconds |
|
||||
* +---------------------------------------------+ 0xffe0bff3
|
||||
* | Alarm Minutes |
|
||||
* +---------------------------------------------+ 0xffe0bff4
|
||||
* | Alarm Date |
|
||||
* +---------------------------------------------+ 0xffe0bff5
|
||||
* | Interrupts |
|
||||
* +---------------------------------------------+ 0xffe0bff6
|
||||
* | WatchDog |
|
||||
* +---------------------------------------------+ 0xffe0bff7
|
||||
* | Calibration |
|
||||
* +---------------------------------------------+ 0xffe0bff8
|
||||
* | Seconds |
|
||||
* +---------------------------------------------+ 0xffe0bff9
|
||||
* | Minutes |
|
||||
* +---------------------------------------------+ 0xffe0bffa
|
||||
* | Hours |
|
||||
* +---------------------------------------------+ 0xffe0bffb
|
||||
* | Day |
|
||||
* +---------------------------------------------+ 0xffe0bffc
|
||||
* | Date |
|
||||
* +---------------------------------------------+ 0xffe0bffd
|
||||
* | Month |
|
||||
* +---------------------------------------------+ 0xffe0bffe
|
||||
* | Year (2 digits only) |
|
||||
* +---------------------------------------------+ 0xffe0bfff
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <rtc.h>
|
||||
#include "bmw.h"
|
||||
|
||||
/*
|
||||
* Imported from mousse.h:
|
||||
*
|
||||
* TOD_REG_BASE Base of m48t59y TOD registers
|
||||
* SYS_TOD_UNPROTECT() Disable NVRAM write protect
|
||||
* SYS_TOD_PROTECT() Re-enable NVRAM write protect
|
||||
*/
|
||||
|
||||
#define YEAR 0xf
|
||||
#define MONTH 0xe
|
||||
#define DAY 0xd
|
||||
#define DAY_OF_WEEK 0xc
|
||||
#define HOUR 0xb
|
||||
#define MINUTE 0xa
|
||||
#define SECOND 0x9
|
||||
#define CONTROL 0x8
|
||||
#define WATCH 0x7
|
||||
#define INTCTL 0x6
|
||||
#define WD_DATE 0x5
|
||||
#define WD_HOUR 0x4
|
||||
#define WD_MIN 0x3
|
||||
#define WD_SEC 0x2
|
||||
#define _UNUSED 0x1
|
||||
#define FLAGS 0x0
|
||||
|
||||
#define M48_ADDR ((volatile unsigned char *) TOD_REG_BASE)
|
||||
|
||||
int m48_tod_init(void)
|
||||
{
|
||||
SYS_TOD_UNPROTECT();
|
||||
|
||||
M48_ADDR[CONTROL] = 0;
|
||||
M48_ADDR[WATCH] = 0;
|
||||
M48_ADDR[INTCTL] = 0;
|
||||
|
||||
/*
|
||||
* If the oscillator is currently stopped (as on a new part shipped
|
||||
* from the factory), start it running.
|
||||
*
|
||||
* Here is an example of the TOD bytes on a brand new M48T59Y part:
|
||||
* 00 00 00 00 00 00 00 00 00 88 8c c3 bf c8 f5 01
|
||||
*/
|
||||
|
||||
if (M48_ADDR[SECOND] & 0x80)
|
||||
M48_ADDR[SECOND] = 0;
|
||||
|
||||
/* Is battery low */
|
||||
if ( M48_ADDR[FLAGS] & 0x10) {
|
||||
printf("NOTICE: Battery low on Real-Time Clock (replace SNAPHAT).\n");
|
||||
}
|
||||
|
||||
SYS_TOD_PROTECT();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* m48_tod_set
|
||||
*/
|
||||
|
||||
static int to_bcd(int value)
|
||||
{
|
||||
return value / 10 * 16 + value % 10;
|
||||
}
|
||||
|
||||
static int from_bcd(int value)
|
||||
{
|
||||
return value / 16 * 10 + value % 16;
|
||||
}
|
||||
|
||||
static int day_of_week(int y, int m, int d) /* 0-6 ==> Sun-Sat */
|
||||
{
|
||||
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||
y -= m < 3;
|
||||
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the TOD should store the current GMT
|
||||
*/
|
||||
|
||||
int m48_tod_set(int year, /* 1980-2079 */
|
||||
int month, /* 01-12 */
|
||||
int day, /* 01-31 */
|
||||
int hour, /* 00-23 */
|
||||
int minute, /* 00-59 */
|
||||
int second) /* 00-59 */
|
||||
|
||||
{
|
||||
SYS_TOD_UNPROTECT();
|
||||
|
||||
M48_ADDR[CONTROL] |= 0x80; /* Set WRITE bit */
|
||||
|
||||
M48_ADDR[YEAR] = to_bcd(year % 100);
|
||||
M48_ADDR[MONTH] = to_bcd(month);
|
||||
M48_ADDR[DAY] = to_bcd(day);
|
||||
M48_ADDR[DAY_OF_WEEK] = day_of_week(year, month, day) + 1;
|
||||
M48_ADDR[HOUR] = to_bcd(hour);
|
||||
M48_ADDR[MINUTE] = to_bcd(minute);
|
||||
M48_ADDR[SECOND] = to_bcd(second);
|
||||
|
||||
M48_ADDR[CONTROL] &= ~0x80; /* Clear WRITE bit */
|
||||
|
||||
SYS_TOD_PROTECT();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the TOD should store the current GMT
|
||||
*/
|
||||
|
||||
int m48_tod_get(int *year, /* 1980-2079 */
|
||||
int *month, /* 01-12 */
|
||||
int *day, /* 01-31 */
|
||||
int *hour, /* 00-23 */
|
||||
int *minute, /* 00-59 */
|
||||
int *second) /* 00-59 */
|
||||
{
|
||||
int y;
|
||||
|
||||
SYS_TOD_UNPROTECT();
|
||||
|
||||
M48_ADDR[CONTROL] |= 0x40; /* Set READ bit */
|
||||
|
||||
y = from_bcd(M48_ADDR[YEAR]);
|
||||
*year = y < 80 ? 2000 + y : 1900 + y;
|
||||
*month = from_bcd(M48_ADDR[MONTH]);
|
||||
*day = from_bcd(M48_ADDR[DAY]);
|
||||
/* day_of_week = M48_ADDR[DAY_OF_WEEK] & 0xf; */
|
||||
*hour = from_bcd(M48_ADDR[HOUR]);
|
||||
*minute = from_bcd(M48_ADDR[MINUTE]);
|
||||
*second = from_bcd(M48_ADDR[SECOND] & 0x7f);
|
||||
|
||||
M48_ADDR[CONTROL] &= ~0x40; /* Clear READ bit */
|
||||
|
||||
SYS_TOD_PROTECT();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m48_tod_get_second(void)
|
||||
{
|
||||
return from_bcd(M48_ADDR[SECOND] & 0x7f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Watchdog function
|
||||
*
|
||||
* If usec is 0, the watchdog timer is disarmed.
|
||||
*
|
||||
* If usec is non-zero, the watchdog timer is armed (or re-armed) for
|
||||
* approximately usec microseconds (if the exact requested usec is
|
||||
* not supported by the chip, the next higher available value is used).
|
||||
*
|
||||
* Minimum watchdog timeout = 62500 usec
|
||||
* Maximum watchdog timeout = 124 sec (124000000 usec)
|
||||
*/
|
||||
|
||||
void m48_watchdog_arm(int usec)
|
||||
{
|
||||
int mpy, res;
|
||||
|
||||
SYS_TOD_UNPROTECT();
|
||||
|
||||
if (usec == 0) {
|
||||
res = 0;
|
||||
mpy = 0;
|
||||
} else if (usec < 2000000) { /* Resolution: 1/16s if below 2s */
|
||||
res = 0;
|
||||
mpy = (usec + 62499) / 62500;
|
||||
} else if (usec < 8000000) { /* Resolution: 1/4s if below 8s */
|
||||
res = 1;
|
||||
mpy = (usec + 249999) / 250000;
|
||||
} else if (usec < 32000000) { /* Resolution: 1s if below 32s */
|
||||
res = 2;
|
||||
mpy = (usec + 999999) / 1000000;
|
||||
} else { /* Resolution: 4s up to 124s */
|
||||
res = 3;
|
||||
mpy = (usec + 3999999) / 4000000;
|
||||
if (mpy > 31)
|
||||
mpy = 31;
|
||||
}
|
||||
|
||||
M48_ADDR[WATCH] = (0x80 | /* Steer to RST signal (IRQ = N/C) */
|
||||
mpy << 2 |
|
||||
res);
|
||||
|
||||
SYS_TOD_PROTECT();
|
||||
}
|
||||
|
||||
/*
|
||||
* U-Boot RTC support.
|
||||
*/
|
||||
void
|
||||
rtc_get( struct rtc_time *tmp )
|
||||
{
|
||||
m48_tod_get(&tmp->tm_year,
|
||||
&tmp->tm_mon,
|
||||
&tmp->tm_mday,
|
||||
&tmp->tm_hour,
|
||||
&tmp->tm_min,
|
||||
&tmp->tm_sec);
|
||||
tmp->tm_yday = 0;
|
||||
tmp->tm_isdst= 0;
|
||||
|
||||
#ifdef RTC_DEBUG
|
||||
printf( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
|
||||
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
|
||||
tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
rtc_set( struct rtc_time *tmp )
|
||||
{
|
||||
m48_tod_set(tmp->tm_year, /* 1980-2079 */
|
||||
tmp->tm_mon, /* 01-12 */
|
||||
tmp->tm_mday, /* 01-31 */
|
||||
tmp->tm_hour, /* 00-23 */
|
||||
tmp->tm_min, /* 00-59 */
|
||||
tmp->tm_sec); /* 00-59 */
|
||||
|
||||
#ifdef RTC_DEBUG
|
||||
printf( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
|
||||
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
|
||||
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
rtc_reset (void)
|
||||
{
|
||||
m48_tod_init();
|
||||
}
|
||||
|
16
board/csb226/config.mk
Normal file
16
board/csb226/config.mk
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# Linux-Kernel is expected to be at c000'8000, entry c000'8000
|
||||
#
|
||||
# we load ourself to c170'0000, the upper 1 MB of second bank
|
||||
#
|
||||
# download areas is c800'0000
|
||||
#
|
||||
|
||||
# This is the address where U-Boot lives in flash:
|
||||
#TEXT_BASE = 0
|
||||
|
||||
# FIXME: armboot does only work correctly when being compiled
|
||||
# for the addresses _after_ relocation to RAM!! Otherwhise the
|
||||
# .bss segment is assumed in flash...
|
||||
TEXT_BASE = 0xa1fe0000
|
||||
|
364
board/csb226/flash.c
Normal file
364
board/csb226/flash.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Marius Groeger <mgroeger@sysgo.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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>
|
||||
|
||||
#define FLASH_BANK_SIZE 0x02000000
|
||||
#define MAIN_SECT_SIZE 0x40000 /* 2x16 = 256k per sector */
|
||||
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
ulong flash_init(void)
|
||||
{
|
||||
int i, j;
|
||||
ulong size = 0;
|
||||
|
||||
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
|
||||
{
|
||||
ulong flashbase = 0;
|
||||
flash_info[i].flash_id =
|
||||
(INTEL_MANUFACT & FLASH_VENDMASK) |
|
||||
(INTEL_ID_28F128J3 & FLASH_TYPEMASK);
|
||||
flash_info[i].size = FLASH_BANK_SIZE;
|
||||
flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
|
||||
memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
flashbase = PHYS_FLASH_1;
|
||||
break;
|
||||
default:
|
||||
panic("configured to many flash banks!\n");
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < flash_info[i].sector_count; j++)
|
||||
{
|
||||
flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE;
|
||||
}
|
||||
size += flash_info[i].size;
|
||||
}
|
||||
|
||||
/* Protect monitor and environment sectors
|
||||
*/
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_FLASH_BASE,
|
||||
CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
|
||||
&flash_info[0]);
|
||||
|
||||
flash_protect(FLAG_PROTECT_SET,
|
||||
CFG_ENV_ADDR,
|
||||
CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
|
||||
&flash_info[0]);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
void flash_print_info (flash_info_t *info)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j=0; j<CFG_MAX_FLASH_BANKS; j++)
|
||||
{
|
||||
switch (info->flash_id & FLASH_VENDMASK)
|
||||
{
|
||||
case (INTEL_MANUFACT & FLASH_VENDMASK):
|
||||
printf("Intel: ");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown Vendor ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (info->flash_id & FLASH_TYPEMASK)
|
||||
{
|
||||
case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
|
||||
printf("28F128J3 (128Mbit)\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown Chip Type\n");
|
||||
goto Done;
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" Size: %ld MB in %d Sectors\n",
|
||||
info->size >> 20, info->sector_count);
|
||||
|
||||
printf(" Sector Start Addresses:");
|
||||
for (i = 0; i < info->sector_count; i++)
|
||||
{
|
||||
if ((i % 5) == 0)
|
||||
{
|
||||
printf ("\n ");
|
||||
}
|
||||
printf (" %08lX%s", info->start[i],
|
||||
info->protect[i] ? " (RO)" : " ");
|
||||
}
|
||||
printf ("\n");
|
||||
info++;
|
||||
}
|
||||
|
||||
Done:
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int flash_erase (flash_info_t *info, int s_first, int s_last)
|
||||
{
|
||||
int flag, prot, sect;
|
||||
int rc = ERR_OK;
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN)
|
||||
return ERR_UNKNOWN_FLASH_TYPE;
|
||||
|
||||
if ((s_first < 0) || (s_first > s_last)) {
|
||||
return ERR_INVAL;
|
||||
}
|
||||
|
||||
if ((info->flash_id & FLASH_VENDMASK) !=
|
||||
(INTEL_MANUFACT & FLASH_VENDMASK)) {
|
||||
return ERR_UNKNOWN_FLASH_VENDOR;
|
||||
}
|
||||
|
||||
prot = 0;
|
||||
for (sect=s_first; sect<=s_last; ++sect) {
|
||||
if (info->protect[sect]) {
|
||||
prot++;
|
||||
}
|
||||
}
|
||||
if (prot)
|
||||
return ERR_PROTECTED;
|
||||
|
||||
/*
|
||||
* Disable interrupts which might cause a timeout
|
||||
* here. Remember that our exception vectors are
|
||||
* at address 0 in the flash, and we don't want a
|
||||
* (ticker) exception to happen while the flash
|
||||
* chip is in programming mode.
|
||||
*/
|
||||
flag = disable_interrupts();
|
||||
|
||||
/* Start erase on unprotected sectors */
|
||||
for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
|
||||
|
||||
printf("Erasing sector %2d ... ", sect);
|
||||
|
||||
/* arm simple, non interrupt dependent timer */
|
||||
reset_timer_masked();
|
||||
|
||||
if (info->protect[sect] == 0) { /* not protected */
|
||||
/* vushort *addr = (vushort *)(info->start[sect]); */
|
||||
ushort *addr = (ushort *)(info->start[sect]);
|
||||
|
||||
*addr = 0x20; /* erase setup */
|
||||
*addr = 0xD0; /* erase confirm */
|
||||
|
||||
while ((*addr & 0x80) != 0x80) {
|
||||
if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) {
|
||||
*addr = 0xB0; /* suspend erase */
|
||||
*addr = 0xFF; /* reset to read mode */
|
||||
rc = ERR_TIMOUT;
|
||||
goto outahere;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear status register command */
|
||||
*addr = 0x50;
|
||||
/* reset to read mode */
|
||||
*addr = 0xFF;
|
||||
}
|
||||
printf("ok.\n");
|
||||
}
|
||||
if (ctrlc())
|
||||
printf("User Interrupt!\n");
|
||||
|
||||
outahere:
|
||||
|
||||
/* allow flash to settle - wait 10 ms */
|
||||
udelay_masked(10000);
|
||||
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Copy memory to flash
|
||||
*/
|
||||
|
||||
static int write_word (flash_info_t *info, ulong dest, ushort data)
|
||||
{
|
||||
/* vushort *addr = (vushort *)dest, val; */
|
||||
ushort *addr = (ushort *)dest, val;
|
||||
int rc = ERR_OK;
|
||||
int flag;
|
||||
|
||||
/* Check if Flash is (sufficiently) erased
|
||||
*/
|
||||
if ((*addr & data) != data)
|
||||
return ERR_NOT_ERASED;
|
||||
|
||||
/*
|
||||
* Disable interrupts which might cause a timeout
|
||||
* here. Remember that our exception vectors are
|
||||
* at address 0 in the flash, and we don't want a
|
||||
* (ticker) exception to happen while the flash
|
||||
* chip is in programming mode.
|
||||
*/
|
||||
flag = disable_interrupts();
|
||||
|
||||
/* clear status register command */
|
||||
*addr = 0x50;
|
||||
|
||||
/* program set-up command */
|
||||
*addr = 0x40;
|
||||
|
||||
/* latch address/data */
|
||||
*addr = data;
|
||||
|
||||
/* arm simple, non interrupt dependent timer */
|
||||
reset_timer_masked();
|
||||
|
||||
/* wait while polling the status register */
|
||||
while(((val = *addr) & 0x80) != 0x80)
|
||||
{
|
||||
if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) {
|
||||
rc = ERR_TIMOUT;
|
||||
/* suspend program command */
|
||||
*addr = 0xB0;
|
||||
goto outahere;
|
||||
}
|
||||
}
|
||||
|
||||
if(val & 0x1A) { /* check for error */
|
||||
printf("\nFlash write error %02x at address %08lx\n",
|
||||
(int)val, (unsigned long)dest);
|
||||
if(val & (1<<3)) {
|
||||
printf("Voltage range error.\n");
|
||||
rc = ERR_PROG_ERROR;
|
||||
goto outahere;
|
||||
}
|
||||
if(val & (1<<1)) {
|
||||
printf("Device protect error.\n");
|
||||
rc = ERR_PROTECTED;
|
||||
goto outahere;
|
||||
}
|
||||
if(val & (1<<4)) {
|
||||
printf("Programming error.\n");
|
||||
rc = ERR_PROG_ERROR;
|
||||
goto outahere;
|
||||
}
|
||||
rc = ERR_PROG_ERROR;
|
||||
goto outahere;
|
||||
}
|
||||
|
||||
outahere:
|
||||
/* read array command */
|
||||
*addr = 0xFF;
|
||||
|
||||
if (flag)
|
||||
enable_interrupts();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Copy memory to flash.
|
||||
*/
|
||||
|
||||
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
|
||||
{
|
||||
ulong cp, wp;
|
||||
ushort data;
|
||||
int l;
|
||||
int i, rc;
|
||||
|
||||
wp = (addr & ~1); /* get lower word aligned address */
|
||||
|
||||
/*
|
||||
* handle unaligned start bytes
|
||||
*/
|
||||
if ((l = addr - wp) != 0) {
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<l; ++i, ++cp) {
|
||||
data = (data >> 8) | (*(uchar *)cp << 8);
|
||||
}
|
||||
for (; i<2 && cnt>0; ++i) {
|
||||
data = (data >> 8) | (*src++ << 8);
|
||||
--cnt;
|
||||
++cp;
|
||||
}
|
||||
for (; cnt==0 && i<2; ++i, ++cp) {
|
||||
data = (data >> 8) | (*(uchar *)cp << 8);
|
||||
}
|
||||
|
||||
if ((rc = write_word(info, wp, data)) != 0) {
|
||||
return (rc);
|
||||
}
|
||||
wp += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle word aligned part
|
||||
*/
|
||||
while (cnt >= 2) {
|
||||
/* data = *((vushort*)src); */
|
||||
data = *((ushort*)src);
|
||||
if ((rc = write_word(info, wp, data)) != 0) {
|
||||
return (rc);
|
||||
}
|
||||
src += 2;
|
||||
wp += 2;
|
||||
cnt -= 2;
|
||||
}
|
||||
|
||||
if (cnt == 0) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle unaligned tail bytes
|
||||
*/
|
||||
data = 0;
|
||||
for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
|
||||
data = (data >> 8) | (*src++ << 8);
|
||||
--cnt;
|
||||
}
|
||||
for (; i<2; ++i, ++cp) {
|
||||
data = (data >> 8) | (*(uchar *)cp << 8);
|
||||
}
|
||||
|
||||
return write_word(info, wp, data);
|
||||
}
|
Loading…
Reference in New Issue
Block a user