1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Add a directory by kernel instead of a common root, add qnap-301w and rpi4 kernel 6.1 suppport

This commit is contained in:
Ycarus (Yannick Chabanois) 2023-04-22 08:07:24 +02:00
parent e910436a7a
commit 46837ec4c0
9459 changed files with 362648 additions and 116345 deletions

View file

@ -0,0 +1,47 @@
#
# (C) Copyright 2003-2006
# 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 = $(obj)lib$(BOARD).o
COBJS := $(BOARD).o cmd_stk52xx.o cmd_tb5200.o cam5200_flash.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
cam5200_flash.o: cam5200_flash.c
$(CC) $(CFLAGS) -c -o $@ $<
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,784 @@
/*
* (C) Copyright 2006
* 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 <common.h>
#include <mpc5xxx.h>
#include <asm/processor.h>
#if defined(CONFIG_CAM5200) && defined(CONFIG_CAM5200_NIOSFLASH)
#if 0
#define DEBUGF(x...) printf(x)
#else
#define DEBUGF(x...)
#endif
#define swap16(x) __swab16(x)
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
/*
* CAM5200 is a TQM5200B based board. Additionally it also features
* a NIOS cpu. The NIOS CPU peripherals are accessible through MPC5xxx
* Local Bus on CS5. This includes 32 bit wide RAM and SRAM as well as
* 16 bit wide flash device. Big Endian order on a 32 bit CS5 makes
* access to flash chip slightly more complicated as additional byte
* swapping is necessary within each 16 bit wide flash 'word'.
*
* This driver's task is to handle both flash devices: 32 bit TQM5200B
* flash chip and 16 bit NIOS cpu flash chip. In the below
* flash_addr_table table we use least significant address bit to mark
* 16 bit flash bank and two sets of routines *_32 and *_16 to handle
* specifics of both flashes.
*/
static unsigned long flash_addr_table[][CONFIG_SYS_MAX_FLASH_BANKS] = {
{CONFIG_SYS_BOOTCS_START, CONFIG_SYS_CS5_START | 1}
};
/*-----------------------------------------------------------------------
* Functions
*/
static int write_word(flash_info_t * info, ulong dest, ulong data);
#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
static int write_word_32(flash_info_t * info, ulong dest, ulong data);
static int write_word_16(flash_info_t * info, ulong dest, ulong data);
static int flash_erase_32(flash_info_t * info, int s_first, int s_last);
static int flash_erase_16(flash_info_t * info, int s_first, int s_last);
static ulong flash_get_size_32(vu_long * addr, flash_info_t * info);
static ulong flash_get_size_16(vu_long * addr, flash_info_t * info);
#endif
void flash_print_info(flash_info_t * info)
{
int i, k;
int size, erased;
volatile unsigned long *flash;
if (info->flash_id == FLASH_UNKNOWN) {
printf("missing or unknown FLASH type\n");
return;
}
switch (info->flash_id & FLASH_VENDMASK) {
case FLASH_MAN_AMD:
printf("AMD ");
break;
case FLASH_MAN_FUJ:
printf("FUJITSU ");
break;
default:
printf("Unknown Vendor ");
break;
}
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_S29GL128N:
printf ("S29GL128N (256 Mbit, uniform sector size)\n");
break;
case FLASH_AM320B:
printf ("29LV320B (32 Mbit, bottom boot sect)\n");
break;
case FLASH_AM320T:
printf ("29LV320T (32 Mbit, top boot sect)\n");
break;
default:
printf("Unknown Chip Type\n");
break;
}
printf(" Size: %ld KB in %d Sectors\n",
info->size >> 10, info->sector_count);
printf(" Sector Start Addresses:");
for (i = 0; i < info->sector_count; ++i) {
/*
* Check if whole sector is erased
*/
if (i != (info->sector_count - 1))
size = info->start[i + 1] - info->start[i];
else
size = info->start[0] + info->size - info->start[i];
erased = 1;
flash = (volatile unsigned long *)info->start[i];
size = size >> 2; /* divide by 4 for longword access */
for (k = 0; k < size; k++) {
if (*flash++ != 0xffffffff) {
erased = 0;
break;
}
}
if ((i % 5) == 0)
printf("\n ");
printf(" %08lX%s%s", info->start[i],
erased ? " E" : " ",
info->protect[i] ? "RO " : " ");
}
printf("\n");
return;
}
/*
* The following code cannot be run from FLASH!
*/
#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
static ulong flash_get_size(vu_long * addr, flash_info_t * info)
{
DEBUGF("get_size: FLASH ADDR %08lx\n", addr);
/* bit 0 used for big flash marking */
if ((ulong)addr & 0x1)
return flash_get_size_16((vu_long *)((ulong)addr & 0xfffffffe), info);
else
return flash_get_size_32(addr, info);
}
static ulong flash_get_size_32(vu_long * addr, flash_info_t * info)
#else
static ulong flash_get_size(vu_long * addr, flash_info_t * info)
#endif
{
short i;
CONFIG_SYS_FLASH_WORD_SIZE value;
ulong base = (ulong) addr;
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) addr;
DEBUGF("get_size32: FLASH ADDR: %08x\n", (unsigned)addr);
/* Write auto select command: read Manufacturer ID */
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00900090;
udelay(1000);
value = addr2[0];
DEBUGF("FLASH MANUFACT: %x\n", value);
switch (value) {
case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_MANUFACT:
info->flash_id = FLASH_MAN_AMD;
break;
default:
info->flash_id = FLASH_UNKNOWN;
info->sector_count = 0;
info->size = 0;
return (0); /* no or unknown flash */
}
value = addr2[1]; /* device ID */
DEBUGF("\nFLASH DEVICEID: %x\n", value);
switch (value) {
case AMD_ID_MIRROR:
DEBUGF("Mirror Bit flash: addr[14] = %08lX addr[15] = %08lX\n",
addr[14], addr[15]);
switch(addr[14]) {
case AMD_ID_GL128N_2:
if (addr[15] != AMD_ID_GL128N_3) {
DEBUGF("Chip: S29GL128N -> unknown\n");
info->flash_id = FLASH_UNKNOWN;
} else {
DEBUGF("Chip: S29GL128N\n");
info->flash_id += FLASH_S29GL128N;
info->sector_count = 128;
info->size = 0x02000000;
}
break;
default:
info->flash_id = FLASH_UNKNOWN;
return(0);
}
break;
default:
info->flash_id = FLASH_UNKNOWN;
return (0); /* => no or unknown flash */
}
/* set up sector start address table */
for (i = 0; i < info->sector_count; i++)
info->start[i] = base + (i * 0x00040000);
/* 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 */
addr2 = (volatile CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[i]);
info->protect[i] = addr2[2] & 1;
}
/* issue bank reset to return to read mode */
addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0;
return (info->size);
}
static int wait_for_DQ7_32(flash_info_t * info, int sect)
{
ulong start, now, last;
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr =
(CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
start = get_timer(0);
last = start;
while ((addr[0] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
(CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) {
if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
printf("Timeout\n");
return -1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
putc('.');
last = now;
}
}
return 0;
}
#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
int flash_erase(flash_info_t * info, int s_first, int s_last)
{
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) {
return flash_erase_16(info, s_first, s_last);
} else {
return flash_erase_32(info, s_first, s_last);
}
}
static int flash_erase_32(flash_info_t * info, int s_first, int s_last)
#else
int flash_erase(flash_info_t * info, int s_first, int s_last)
#endif
{
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
int flag, prot, sect;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN)
printf("- missing\n");
else
printf("- no sectors to erase\n");
return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf("Can't erase unknown flash type - aborted\n");
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!", prot);
printf("\n");
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00300030; /* sector erase */
/*
* Wait for each sector to complete, it's more
* reliable. According to AMD Spec, you must
* issue all erase commands within a specified
* timeout. This has been seen to fail, especially
* if printf()s are included (for debug)!!
*/
wait_for_DQ7_32(info, sect);
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* wait at least 80us - let's wait 1 ms */
udelay(1000);
/* reset to read mode */
addr = (CONFIG_SYS_FLASH_WORD_SIZE *) info->start[0];
addr[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
printf(" 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));
}
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
static int write_word(flash_info_t * info, ulong dest, ulong data)
{
if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) {
return write_word_16(info, dest, data);
} else {
return write_word_32(info, dest, data);
}
}
static int write_word_32(flash_info_t * info, ulong dest, ulong data)
#else
static int write_word(flash_info_t * info, ulong dest, ulong data)
#endif
{
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
volatile CONFIG_SYS_FLASH_WORD_SIZE *dest2 = (CONFIG_SYS_FLASH_WORD_SIZE *) dest;
ulong *datap = &data;
volatile CONFIG_SYS_FLASH_WORD_SIZE *data2 =
(volatile CONFIG_SYS_FLASH_WORD_SIZE *)datap;
ulong start;
int i, flag;
/* Check if Flash is (sufficiently) erased */
if ((*((vu_long *)dest) & data) != data)
return (2);
for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00A000A0;
dest2[i] = data2[i];
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* data polling for D7 */
start = get_timer(0);
while ((dest2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
(data2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080)) {
if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
return (1);
}
}
return (0);
}
#ifdef CONFIG_SYS_FLASH_2ND_16BIT_DEV
#undef CONFIG_SYS_FLASH_WORD_SIZE
#define CONFIG_SYS_FLASH_WORD_SIZE unsigned short
/*
* The following code cannot be run from FLASH!
*/
static ulong flash_get_size_16(vu_long * addr, flash_info_t * info)
{
short i;
CONFIG_SYS_FLASH_WORD_SIZE value;
ulong base = (ulong) addr;
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) addr;
DEBUGF("get_size16: FLASH ADDR: %08x\n", (unsigned)addr);
/* issue bank reset to return to read mode */
addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xF000F000;
/* Write auto select command: read Manufacturer ID */
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAA00AA00;
addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55005500;
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x90009000;
udelay(1000);
value = swap16(addr2[0]);
DEBUGF("FLASH MANUFACT: %x\n", value);
switch (value) {
case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_MANUFACT:
info->flash_id = FLASH_MAN_AMD;
break;
case (CONFIG_SYS_FLASH_WORD_SIZE) 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 = swap16(addr2[1]); /* device ID */
DEBUGF("\nFLASH DEVICEID: %x\n", value);
switch (value) {
case (CONFIG_SYS_FLASH_WORD_SIZE)AMD_ID_LV320B:
info->flash_id += FLASH_AM320B;
info->sector_count = 71;
info->size = 0x00400000;
break; /* => 4 MB */
case (CONFIG_SYS_FLASH_WORD_SIZE)AMD_ID_LV320T:
info->flash_id += FLASH_AM320T;
info->sector_count = 71;
info->size = 0x00400000;
break; /* => 4 MB */
default:
info->flash_id = FLASH_UNKNOWN;
return (0); /* => no or unknown flash */
}
if (info->flash_id & FLASH_BTYPE) {
/* set sector offsets for bottom boot block type */
info->start[0] = base + 0x00000000;
info->start[1] = base + 0x00002000;
info->start[2] = base + 0x00004000;
info->start[3] = base + 0x00006000;
info->start[4] = base + 0x00008000;
info->start[5] = base + 0x0000a000;
info->start[6] = base + 0x0000c000;
info->start[7] = base + 0x0000e000;
for (i = 8; i < info->sector_count; i++)
info->start[i] = base + (i * 0x00010000) - 0x00070000;
} else {
/* set sector offsets for top boot block type */
i = info->sector_count - 1;
info->start[i--] = base + info->size - 0x00002000;
info->start[i--] = base + info->size - 0x00004000;
info->start[i--] = base + info->size - 0x00006000;
info->start[i--] = base + info->size - 0x00008000;
info->start[i--] = base + info->size - 0x0000a000;
info->start[i--] = base + info->size - 0x0000c000;
info->start[i--] = base + info->size - 0x0000e000;
for (; i >= 0; i--)
info->start[i] = base + i * 0x00010000;
}
/* 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 */
addr2 = (volatile CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[i]);
info->protect[i] = addr2[2] & 1;
}
/* issue bank reset to return to read mode */
addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xF000F000;
return (info->size);
}
static int wait_for_DQ7_16(flash_info_t * info, int sect)
{
ulong start, now, last;
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr =
(CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
start = get_timer(0);
last = start;
while ((addr[0] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x80008000) !=
(CONFIG_SYS_FLASH_WORD_SIZE) 0x80008000) {
if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
printf("Timeout\n");
return -1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
putc('.');
last = now;
}
}
return 0;
}
static int flash_erase_16(flash_info_t * info, int s_first, int s_last)
{
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
int flag, prot, sect;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN)
printf("- missing\n");
else
printf("- no sectors to erase\n");
return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf("Can't erase unknown flash type - aborted\n");
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!", prot);
printf("\n");
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect <= s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAA00AA00;
addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55005500;
addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x80008000;
addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAA00AA00;
addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55005500;
addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x30003000; /* sector erase */
/*
* Wait for each sector to complete, it's more
* reliable. According to AMD Spec, you must
* issue all erase commands within a specified
* timeout. This has been seen to fail, especially
* if printf()s are included (for debug)!!
*/
wait_for_DQ7_16(info, sect);
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* wait at least 80us - let's wait 1 ms */
udelay(1000);
/* reset to read mode */
addr = (CONFIG_SYS_FLASH_WORD_SIZE *) info->start[0];
addr[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xF000F000; /* reset bank */
printf(" done\n");
return 0;
}
static int write_word_16(flash_info_t * info, ulong dest, ulong data)
{
volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
volatile CONFIG_SYS_FLASH_WORD_SIZE *dest2 = (CONFIG_SYS_FLASH_WORD_SIZE *) dest;
ulong *datap = &data;
volatile CONFIG_SYS_FLASH_WORD_SIZE *data2 =
(volatile CONFIG_SYS_FLASH_WORD_SIZE *)datap;
ulong start;
int i;
/* Check if Flash is (sufficiently) erased */
for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
if ((dest2[i] & swap16(data2[i])) != swap16(data2[i]))
return (2);
}
for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
int flag;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAA00AA00;
addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55005500;
addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xA000A000;
dest2[i] = swap16(data2[i]);
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* data polling for D7 */
start = get_timer(0);
while ((dest2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x80008000) !=
(swap16(data2[i]) & (CONFIG_SYS_FLASH_WORD_SIZE) 0x80008000)) {
if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
return (1);
}
}
}
return (0);
}
#endif /* CONFIG_SYS_FLASH_2ND_16BIT_DEV */
/*-----------------------------------------------------------------------
* 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)
{
unsigned long total_b = 0;
unsigned long size_b[CONFIG_SYS_MAX_FLASH_BANKS];
unsigned short index = 0;
int i;
DEBUGF("\n");
DEBUGF("FLASH: Index: %d\n", index);
/* Init: no FLASHes known */
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
flash_info[i].flash_id = FLASH_UNKNOWN;
flash_info[i].sector_count = -1;
flash_info[i].size = 0;
/* check whether the address is 0 */
if (flash_addr_table[index][i] == 0)
continue;
/* call flash_get_size() to initialize sector address */
size_b[i] = flash_get_size((vu_long *) flash_addr_table[index][i],
&flash_info[i]);
flash_info[i].size = size_b[i];
if (flash_info[i].flash_id == FLASH_UNKNOWN) {
printf("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
i+1, size_b[i], size_b[i] << 20);
flash_info[i].sector_count = -1;
flash_info[i].size = 0;
}
/* Monitor protection ON by default */
(void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
&flash_info[i]);
#if defined(CONFIG_ENV_IS_IN_FLASH)
(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
&flash_info[i]);
#if defined(CONFIG_ENV_ADDR_REDUND)
(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
&flash_info[i]);
#endif
#endif
total_b += flash_info[i].size;
}
return total_b;
}
#endif /* if defined(CONFIG_CAM5200) && defined(CONFIG_CAM5200_NIOSFLASH) */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
/*
* (C) Copyright 2005 - 2006
* Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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
*/
/*
* TB5200 specific functions
*/
/*#define DEBUG*/
#include <common.h>
#include <command.h>
#if defined(CONFIG_CMD_BSP)
#if defined (CONFIG_TB5200)
#define SM501_PANEL_DISPLAY_CONTROL 0x00080000UL
static void led_init(void)
{
struct mpc5xxx_gpt_0_7 *gpt = (struct mpc5xxx_gpt_0_7 *)MPC5XXX_GPT;
/* configure timer 4 for simple GPIO output */
gpt->gpt4.emsr |= 0x00000024;
}
int cmd_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct mpc5xxx_gpt_0_7 *gpt = (struct mpc5xxx_gpt_0_7 *)MPC5XXX_GPT;
led_init();
if (strcmp (argv[1], "on") == 0) {
debug ("switch status LED on\n");
gpt->gpt4.emsr |= (1 << 4);
} else if (strcmp (argv[1], "off") == 0) {
debug ("switch status LED off\n");
gpt->gpt4.emsr &= ~(1 << 4);
} else {
printf ("Usage:\nled on/off\n");
return 1;
}
return 0;
}
static void sm501_backlight (unsigned int state)
{
if (state == 1) {
*(vu_long *)(SM501_MMIO_BASE+SM501_PANEL_DISPLAY_CONTROL) |=
(1 << 26) | (1 << 27);
} else if (state == 0)
*(vu_long *)(SM501_MMIO_BASE+SM501_PANEL_DISPLAY_CONTROL) &=
~((1 << 26) | (1 << 27));
}
int cmd_backlight(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
if (strcmp (argv[1], "on") == 0) {
debug ("switch backlight on\n");
sm501_backlight (1);
} else if (strcmp (argv[1], "off") == 0) {
debug ("switch backlight off\n");
sm501_backlight (0);
} else {
printf ("Usage:\nbacklight on/off\n");
return 1;
}
return 0;
}
U_BOOT_CMD(
led , 2, 1, cmd_led,
"switch status LED on or off",
"on/off"
);
U_BOOT_CMD(
backlight , 2, 1, cmd_backlight,
"switch backlight on or off",
"on/off"
);
#endif /* CONFIG_STK52XX */
#endif

View file

@ -0,0 +1,34 @@
/*
* (C) Copyright 2004
* Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
*
* 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 SDRAM_DDR 0 /* is SDR */
/* Settings for XLB = 132 MHz */
#define SDRAM_MODE 0x00CD0000
/* #define SDRAM_MODE 0x008D0000 */ /* CAS latency 2 */
#define SDRAM_CONTROL 0x504F0000
#define SDRAM_CONFIG1 0xD2322800
/* #define SDRAM_CONFIG1 0xD2222800 */ /* CAS latency 2 */
/*#define SDRAM_CONFIG1 0xD7322800 */ /* SDRAM controller bug workaround */
#define SDRAM_CONFIG2 0x8AD70000
/*#define SDRAM_CONFIG2 0xDDD70000 */ /* SDRAM controller bug workaround */

View file

@ -0,0 +1,905 @@
/*
* (C) Copyright 2003-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* (C) Copyright 2004
* Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
*
* (C) Copyright 2004-2006
* Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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>
#include <mpc5xxx.h>
#include <pci.h>
#include <asm/processor.h>
#include <libfdt.h>
#include <netdev.h>
#ifdef CONFIG_VIDEO_SM501
#include <sm501.h>
#endif
#if defined(CONFIG_MPC5200_DDR)
#include "mt46v16m16-75.h"
#else
#include "mt48lc16m16a2-75.h"
#endif
#ifdef CONFIG_OF_LIBFDT
#include <fdt_support.h>
#endif /* CONFIG_OF_LIBFDT */
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_PS2MULT
void ps2mult_early_init(void);
#endif
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) && \
defined(CONFIG_VIDEO)
/*
* EDID block has been generated using Phoenix EDID Designer 1.3.
* This tool creates a text file containing:
*
* EDID BYTES:
*
* 0x 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
* ------------------------------------------------
* 00 | 00 FF FF FF FF FF FF 00 04 21 00 00 00 00 00 00
* 10 | 01 00 01 03 00 00 00 00 00 00 00 00 00 00 00 00
* 20 | 00 00 00 21 00 00 01 01 01 01 01 01 01 01 01 01
* 30 | 01 01 01 01 01 01 64 00 00 00 00 00 00 00 00 00
* 40 | 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
* 50 | 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00
* 60 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
* 70 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17
*
* Then this data has been manually converted to the char
* array below.
*/
static unsigned char edid_buf[128] = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
};
#endif
#ifndef CONFIG_SYS_RAMBOOT
static void sdram_start (int hi_addr)
{
long hi_addr_bit = hi_addr ? 0x01000000 : 0;
/* unlock mode register */
*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 |
hi_addr_bit;
__asm__ volatile ("sync");
/* precharge all banks */
*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 |
hi_addr_bit;
__asm__ volatile ("sync");
#if SDRAM_DDR
/* set mode register: extended mode */
*(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_EMODE;
__asm__ volatile ("sync");
/* set mode register: reset DLL */
*(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000;
__asm__ volatile ("sync");
#endif
/* precharge all banks */
*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 |
hi_addr_bit;
__asm__ volatile ("sync");
/* auto refresh */
*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 |
hi_addr_bit;
__asm__ volatile ("sync");
/* set mode register */
*(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE;
__asm__ volatile ("sync");
/* normal operation */
*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit;
__asm__ volatile ("sync");
}
#endif
/*
* ATTENTION: Although partially referenced initdram does NOT make real use
* use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
* is something else than 0x00000000.
*/
phys_size_t initdram (int board_type)
{
ulong dramsize = 0;
ulong dramsize2 = 0;
uint svr, pvr;
#ifndef CONFIG_SYS_RAMBOOT
ulong test1, test2;
/* setup SDRAM chip selects */
*(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001c; /* 512MB at 0x0 */
*(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x40000000; /* disabled */
__asm__ volatile ("sync");
/* setup config registers */
*(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1;
*(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2;
__asm__ volatile ("sync");
#if SDRAM_DDR
/* set tap delay */
*(vu_long *)MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY;
__asm__ volatile ("sync");
#endif
/* find RAM size using SDRAM CS0 only */
sdram_start(0);
test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x20000000);
sdram_start(1);
test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x20000000);
if (test1 > test2) {
sdram_start(0);
dramsize = test1;
} else {
dramsize = test2;
}
/* memory smaller than 1MB is impossible */
if (dramsize < (1 << 20)) {
dramsize = 0;
}
/* set SDRAM CS0 size according to the amount of RAM found */
if (dramsize > 0) {
*(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 +
__builtin_ffs(dramsize >> 20) - 1;
} else {
*(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */
}
/* let SDRAM CS1 start right after CS0 */
*(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001c; /* 512MB */
/* find RAM size using SDRAM CS1 only */
if (!dramsize)
sdram_start(0);
test2 = test1 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x20000000);
if (!dramsize) {
sdram_start(1);
test2 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x20000000);
}
if (test1 > test2) {
sdram_start(0);
dramsize2 = test1;
} else {
dramsize2 = test2;
}
/* memory smaller than 1MB is impossible */
if (dramsize2 < (1 << 20)) {
dramsize2 = 0;
}
/* set SDRAM CS1 size according to the amount of RAM found */
if (dramsize2 > 0) {
*(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize
| (0x13 + __builtin_ffs(dramsize2 >> 20) - 1);
} else {
*(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */
}
#else /* CONFIG_SYS_RAMBOOT */
/* retrieve size of memory connected to SDRAM CS0 */
dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF;
if (dramsize >= 0x13) {
dramsize = (1 << (dramsize - 0x13)) << 20;
} else {
dramsize = 0;
}
/* retrieve size of memory connected to SDRAM CS1 */
dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF;
if (dramsize2 >= 0x13) {
dramsize2 = (1 << (dramsize2 - 0x13)) << 20;
} else {
dramsize2 = 0;
}
#endif /* CONFIG_SYS_RAMBOOT */
/*
* On MPC5200B we need to set the special configuration delay in the
* DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
* Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
*
* "The SDelay should be written to a value of 0x00000004. It is
* required to account for changes caused by normal wafer processing
* parameters."
*/
svr = get_svr();
pvr = get_pvr();
if ((SVR_MJREV(svr) >= 2) &&
(PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) {
*(vu_long *)MPC5XXX_SDRAM_SDELAY = 0x04;
__asm__ volatile ("sync");
}
#if defined(CONFIG_TQM5200_B)
return dramsize + dramsize2;
#else
return dramsize;
#endif /* CONFIG_TQM5200_B */
}
int checkboard (void)
{
#if defined(CONFIG_AEVFIFO)
puts ("Board: AEVFIFO\n");
return 0;
#endif
#if defined(CONFIG_TQM5200S)
# define MODULE_NAME "TQM5200S"
#else
# define MODULE_NAME "TQM5200"
#endif
#if defined(CONFIG_STK52XX)
# define CARRIER_NAME "STK52xx"
#elif defined(CONFIG_TB5200)
# define CARRIER_NAME "TB5200"
#elif defined(CONFIG_CAM5200)
# define CARRIER_NAME "CAM5200"
#elif defined(CONFIG_FO300)
# define CARRIER_NAME "FO300"
#elif defined(CONFIG_CHARON)
# define CARRIER_NAME "CHARON"
#else
# error "UNKNOWN"
#endif
puts ( "Board: " MODULE_NAME " (TQ-Components GmbH)\n"
" on a " CARRIER_NAME " carrier board\n");
return 0;
}
#undef MODULE_NAME
#undef CARRIER_NAME
void flash_preinit(void)
{
/*
* Now, when we are in RAM, enable flash write
* access for detection process.
* Note that CS_BOOT cannot be cleared when
* executing in flash.
*/
*(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */
}
#ifdef CONFIG_PCI
static struct pci_controller hose;
extern void pci_mpc5xxx_init(struct pci_controller *);
void pci_init_board(void)
{
pci_mpc5xxx_init(&hose);
}
#endif
#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_RESET)
#if defined (CONFIG_MINIFAP)
#define SM501_POWER_MODE0_GATE 0x00000040UL
#define SM501_POWER_MODE1_GATE 0x00000048UL
#define POWER_MODE_GATE_GPIO_PWM_I2C 0x00000040UL
#define SM501_GPIO_DATA_DIR_HIGH 0x0001000CUL
#define SM501_GPIO_DATA_HIGH 0x00010004UL
#define SM501_GPIO_51 0x00080000UL
#endif /* CONFIG MINIFAP */
void init_ide_reset (void)
{
debug ("init_ide_reset\n");
#if defined (CONFIG_MINIFAP)
/* Configure GPIO_51 of the SM501 grafic controller as ATA reset */
/* enable GPIO control (in both power modes) */
*(vu_long *) (SM501_MMIO_BASE+SM501_POWER_MODE0_GATE) |=
POWER_MODE_GATE_GPIO_PWM_I2C;
*(vu_long *) (SM501_MMIO_BASE+SM501_POWER_MODE1_GATE) |=
POWER_MODE_GATE_GPIO_PWM_I2C;
/* configure GPIO51 as output */
*(vu_long *) (SM501_MMIO_BASE+SM501_GPIO_DATA_DIR_HIGH) |=
SM501_GPIO_51;
#else
/* Configure PSC1_4 as GPIO output for ATA reset */
*(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4;
*(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC1_4;
/* by default the ATA reset is de-asserted */
*(vu_long *) MPC5XXX_WU_GPIO_DATA_O |= GPIO_PSC1_4;
#endif
}
void ide_set_reset (int idereset)
{
debug ("ide_reset(%d)\n", idereset);
#if defined (CONFIG_MINIFAP)
if (idereset) {
*(vu_long *) (SM501_MMIO_BASE+SM501_GPIO_DATA_HIGH) &=
~SM501_GPIO_51;
} else {
*(vu_long *) (SM501_MMIO_BASE+SM501_GPIO_DATA_HIGH) |=
SM501_GPIO_51;
}
#else
if (idereset) {
*(vu_long *) MPC5XXX_WU_GPIO_DATA_O &= ~GPIO_PSC1_4;
} else {
*(vu_long *) MPC5XXX_WU_GPIO_DATA_O |= GPIO_PSC1_4;
}
#endif
}
#endif
#ifdef CONFIG_POST
/*
* Reads GPIO pin PSC6_3. A keypress is reported, if PSC6_3 is low. If PSC6_3
* is left open, no keypress is detected.
*/
int post_hotkeys_pressed(void)
{
#ifdef CONFIG_STK52XX
struct mpc5xxx_gpio *gpio;
gpio = (struct mpc5xxx_gpio*) MPC5XXX_GPIO;
/*
* Configure PSC6_0 through PSC6_3 as GPIO.
*/
gpio->port_config &= ~(0x00700000);
/* Enable GPIO for GPIO_IRDA_1 (IR_USB_CLK pin) = PSC6_3 */
gpio->simple_gpioe |= 0x20000000;
/* Configure GPIO_IRDA_1 as input */
gpio->simple_ddr &= ~(0x20000000);
return ((gpio->simple_ival & 0x20000000) ? 0 : 1);
#else
return 0;
#endif
}
#endif
#ifdef CONFIG_BOARD_EARLY_INIT_R
int board_early_init_r (void)
{
extern int usb_cpu_init(void);
#ifdef CONFIG_PS2MULT
ps2mult_early_init();
#endif /* CONFIG_PS2MULT */
#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
/* Low level USB init, required for proper kernel operation */
usb_cpu_init();
#endif
return (0);
}
#endif
#ifdef CONFIG_FO300
int silent_boot (void)
{
vu_long timer3_status;
/* Configure GPT3 as GPIO input */
*(vu_long *)MPC5XXX_GPT3_ENABLE = 0x00000004;
/* Read in TIMER_3 pin status */
timer3_status = *(vu_long *)MPC5XXX_GPT3_STATUS;
#ifdef FO300_SILENT_CONSOLE_WHEN_S1_CLOSED
/* Force silent console mode if S1 switch
* is in closed position (TIMER_3 pin status is LOW). */
if (MPC5XXX_GPT_GPIO_PIN(timer3_status) == 0)
return 1;
#else
/* Force silent console mode if S1 switch
* is in open position (TIMER_3 pin status is HIGH). */
if (MPC5XXX_GPT_GPIO_PIN(timer3_status) == 1)
return 1;
#endif
return 0;
}
int board_early_init_f (void)
{
if (silent_boot())
gd->flags |= GD_FLG_SILENT;
return 0;
}
#endif /* CONFIG_FO300 */
#if defined(CONFIG_CHARON)
#include <i2c.h>
#include <asm/io.h>
/* The TFP410 registers */
#define TFP410_REG_VEN_ID_L 0x00
#define TFP410_REG_VEN_ID_H 0x01
#define TFP410_REG_DEV_ID_L 0x02
#define TFP410_REG_DEV_ID_H 0x03
#define TFP410_REG_REV_ID 0x04
#define TFP410_REG_CTL_1_MODE 0x08
#define TFP410_REG_CTL_2_MODE 0x09
#define TFP410_REG_CTL_3_MODE 0x0A
#define TFP410_REG_CFG 0x0B
#define TFP410_REG_DE_DLY 0x32
#define TFP410_REG_DE_CTL 0x33
#define TFP410_REG_DE_TOP 0x34
#define TFP410_REG_DE_CNT_L 0x36
#define TFP410_REG_DE_CNT_H 0x37
#define TFP410_REG_DE_LIN_L 0x38
#define TFP410_REG_DE_LIN_H 0x39
#define TFP410_REG_H_RES_L 0x3A
#define TFP410_REG_H_RES_H 0x3B
#define TFP410_REG_V_RES_L 0x3C
#define TFP410_REG_V_RES_H 0x3D
static int tfp410_read_reg(int reg, uchar *buf)
{
if (i2c_read(CONFIG_SYS_TFP410_ADDR, reg, 1, buf, 1) != 0) {
puts ("Error reading the chip.\n");
return 1;
}
return 0;
}
static int tfp410_write_reg(int reg, uchar buf)
{
if (i2c_write(CONFIG_SYS_TFP410_ADDR, reg, 1, &buf, 1) != 0) {
puts ("Error writing the chip.\n");
return 1;
}
return 0;
}
typedef struct _tfp410_config {
int reg;
uchar val;
}TFP410_CONFIG;
static TFP410_CONFIG tfp410_configtbl[] = {
{TFP410_REG_CTL_1_MODE, 0x37},
{TFP410_REG_CTL_2_MODE, 0x20},
{TFP410_REG_CTL_3_MODE, 0x80},
{TFP410_REG_DE_DLY, 0x90},
{TFP410_REG_DE_CTL, 0x00},
{TFP410_REG_DE_TOP, 0x23},
{TFP410_REG_DE_CNT_H, 0x02},
{TFP410_REG_DE_CNT_L, 0x80},
{TFP410_REG_DE_LIN_H, 0x01},
{TFP410_REG_DE_LIN_L, 0xe0},
{-1, 0},
};
static int charon_last_stage_init(void)
{
volatile struct mpc5xxx_lpb *lpb =
(struct mpc5xxx_lpb *) MPC5XXX_LPB;
int oldbus = i2c_get_bus_num();
uchar buf;
int i = 0;
i2c_set_bus_num(CONFIG_SYS_TFP410_BUS);
/* check version */
if (tfp410_read_reg(TFP410_REG_DEV_ID_H, &buf) != 0)
return -1;
if (!(buf & 0x04))
return -1;
if (tfp410_read_reg(TFP410_REG_DEV_ID_L, &buf) != 0)
return -1;
if (!(buf & 0x10))
return -1;
/* OK, now init the chip */
while (tfp410_configtbl[i].reg != -1) {
int ret;
ret = tfp410_write_reg(tfp410_configtbl[i].reg,
tfp410_configtbl[i].val);
if (ret != 0)
return -1;
i++;
}
printf("TFP410 initialized.\n");
i2c_set_bus_num(oldbus);
/* set deadcycle for cs3 to 0 */
setbits_be32(&lpb->cs_deadcycle, 0xffffcfff);
return 0;
}
#endif
int last_stage_init (void)
{
/*
* auto scan for really existing devices and re-set chip select
* configuration.
*/
u16 save, tmp;
int restore;
/*
* Check for SRAM and SRAM size
*/
/* save original SRAM content */
save = *(volatile u16 *)CONFIG_SYS_CS2_START;
restore = 1;
/* write test pattern to SRAM */
*(volatile u16 *)CONFIG_SYS_CS2_START = 0xA5A5;
__asm__ volatile ("sync");
/*
* Put a different pattern on the data lines: otherwise they may float
* long enough to read back what we wrote.
*/
tmp = *(volatile u16 *)CONFIG_SYS_FLASH_BASE;
if (tmp == 0xA5A5)
puts ("!! possible error in SRAM detection\n");
if (*(volatile u16 *)CONFIG_SYS_CS2_START != 0xA5A5) {
/* no SRAM at all, disable cs */
*(vu_long *)MPC5XXX_ADDECR &= ~(1 << 18);
*(vu_long *)MPC5XXX_CS2_START = 0x0000FFFF;
*(vu_long *)MPC5XXX_CS2_STOP = 0x0000FFFF;
restore = 0;
__asm__ volatile ("sync");
} else if (*(volatile u16 *)(CONFIG_SYS_CS2_START + (1<<19)) == 0xA5A5) {
/* make sure that we access a mirrored address */
*(volatile u16 *)CONFIG_SYS_CS2_START = 0x1111;
__asm__ volatile ("sync");
if (*(volatile u16 *)(CONFIG_SYS_CS2_START + (1<<19)) == 0x1111) {
/* SRAM size = 512 kByte */
*(vu_long *)MPC5XXX_CS2_STOP = STOP_REG(CONFIG_SYS_CS2_START,
0x80000);
__asm__ volatile ("sync");
puts ("SRAM: 512 kB\n");
}
else
puts ("!! possible error in SRAM detection\n");
} else {
puts ("SRAM: 1 MB\n");
}
/* restore origianl SRAM content */
if (restore) {
*(volatile u16 *)CONFIG_SYS_CS2_START = save;
__asm__ volatile ("sync");
}
#ifndef CONFIG_TQM5200S /* The TQM5200S has no SM501 grafic controller */
/*
* Check for Grafic Controller
*/
/* save origianl FB content */
save = *(volatile u16 *)CONFIG_SYS_CS1_START;
restore = 1;
/* write test pattern to FB memory */
*(volatile u16 *)CONFIG_SYS_CS1_START = 0xA5A5;
__asm__ volatile ("sync");
/*
* Put a different pattern on the data lines: otherwise they may float
* long enough to read back what we wrote.
*/
tmp = *(volatile u16 *)CONFIG_SYS_FLASH_BASE;
if (tmp == 0xA5A5)
puts ("!! possible error in grafic controller detection\n");
if (*(volatile u16 *)CONFIG_SYS_CS1_START != 0xA5A5) {
/* no grafic controller at all, disable cs */
*(vu_long *)MPC5XXX_ADDECR &= ~(1 << 17);
*(vu_long *)MPC5XXX_CS1_START = 0x0000FFFF;
*(vu_long *)MPC5XXX_CS1_STOP = 0x0000FFFF;
restore = 0;
__asm__ volatile ("sync");
} else {
puts ("VGA: SMI501 (Voyager) with 8 MB\n");
}
/* restore origianl FB content */
if (restore) {
*(volatile u16 *)CONFIG_SYS_CS1_START = save;
__asm__ volatile ("sync");
}
#ifdef CONFIG_FO300
if (silent_boot()) {
setenv("bootdelay", "0");
disable_ctrlc(1);
}
#endif
#endif /* !CONFIG_TQM5200S */
#if defined(CONFIG_CHARON)
charon_last_stage_init();
#endif
return 0;
}
#ifdef CONFIG_VIDEO_SM501
#ifdef CONFIG_FO300
#define DISPLAY_WIDTH 800
#else
#define DISPLAY_WIDTH 640
#endif
#define DISPLAY_HEIGHT 480
#ifdef CONFIG_VIDEO_SM501_8BPP
#error CONFIG_VIDEO_SM501_8BPP not supported.
#endif /* CONFIG_VIDEO_SM501_8BPP */
#ifdef CONFIG_VIDEO_SM501_16BPP
#error CONFIG_VIDEO_SM501_16BPP not supported.
#endif /* CONFIG_VIDEO_SM501_16BPP */
#ifdef CONFIG_VIDEO_SM501_32BPP
static const SMI_REGS init_regs [] =
{
#if 0 /* CRT only */
{0x00004, 0x0},
{0x00048, 0x00021807},
{0x0004C, 0x10090a01},
{0x00054, 0x1},
{0x00040, 0x00021807},
{0x00044, 0x10090a01},
{0x00054, 0x0},
{0x80200, 0x00010000},
{0x80204, 0x0},
{0x80208, 0x0A000A00},
{0x8020C, 0x02fa027f},
{0x80210, 0x004a028b},
{0x80214, 0x020c01df},
{0x80218, 0x000201e9},
{0x80200, 0x00013306},
#else /* panel + CRT */
#ifdef CONFIG_FO300
{0x00004, 0x0},
{0x00048, 0x00021807},
{0x0004C, 0x301a0a01},
{0x00054, 0x1},
{0x00040, 0x00021807},
{0x00044, 0x091a0a01},
{0x00054, 0x0},
{0x80000, 0x0f013106},
{0x80004, 0xc428bb17},
{0x8000C, 0x00000000},
{0x80010, 0x0C800C80},
{0x80014, 0x03200000},
{0x80018, 0x01e00000},
{0x8001C, 0x00000000},
{0x80020, 0x01e00320},
{0x80024, 0x042a031f},
{0x80028, 0x0086034a},
{0x8002C, 0x020c01df},
{0x80030, 0x000201ea},
{0x80200, 0x00010000},
#else
{0x00004, 0x0},
{0x00048, 0x00021807},
{0x0004C, 0x091a0a01},
{0x00054, 0x1},
{0x00040, 0x00021807},
{0x00044, 0x091a0a01},
{0x00054, 0x0},
{0x80000, 0x0f013106},
{0x80004, 0xc428bb17},
{0x8000C, 0x00000000},
{0x80010, 0x0a000a00},
{0x80014, 0x02800000},
{0x80018, 0x01e00000},
{0x8001C, 0x00000000},
{0x80020, 0x01e00280},
{0x80024, 0x02fa027f},
{0x80028, 0x004a028b},
{0x8002C, 0x020c01df},
{0x80030, 0x000201e9},
{0x80200, 0x00010000},
#endif /* #ifdef CONFIG_FO300 */
#endif
{0, 0}
};
#endif /* CONFIG_VIDEO_SM501_32BPP */
#ifdef CONFIG_CONSOLE_EXTRA_INFO
/*
* Return text to be printed besides the logo.
*/
void video_get_info_str (int line_number, char *info)
{
if (line_number == 1) {
strcpy (info, " Board: TQM5200 (TQ-Components GmbH)");
#if defined (CONFIG_CHARON) || defined (CONFIG_FO300) || \
defined(CONFIG_STK52XX) || defined(CONFIG_TB5200)
} else if (line_number == 2) {
#if defined (CONFIG_CHARON)
strcpy (info, " on a CHARON carrier board");
#endif
#if defined (CONFIG_STK52XX)
strcpy (info, " on a STK52xx carrier board");
#endif
#if defined (CONFIG_TB5200)
strcpy (info, " on a TB5200 carrier board");
#endif
#if defined (CONFIG_FO300)
strcpy (info, " on a FO300 carrier board");
#endif
#endif
}
else {
info [0] = '\0';
}
}
#endif
/*
* Returns SM501 register base address. First thing called in the
* driver. Checks if SM501 is physically present.
*/
unsigned int board_video_init (void)
{
u16 save, tmp;
int restore, ret;
/*
* Check for Grafic Controller
*/
/* save origianl FB content */
save = *(volatile u16 *)CONFIG_SYS_CS1_START;
restore = 1;
/* write test pattern to FB memory */
*(volatile u16 *)CONFIG_SYS_CS1_START = 0xA5A5;
__asm__ volatile ("sync");
/*
* Put a different pattern on the data lines: otherwise they may float
* long enough to read back what we wrote.
*/
tmp = *(volatile u16 *)CONFIG_SYS_FLASH_BASE;
if (tmp == 0xA5A5)
puts ("!! possible error in grafic controller detection\n");
if (*(volatile u16 *)CONFIG_SYS_CS1_START != 0xA5A5) {
/* no grafic controller found */
restore = 0;
ret = 0;
} else {
ret = SM501_MMIO_BASE;
}
if (restore) {
*(volatile u16 *)CONFIG_SYS_CS1_START = save;
__asm__ volatile ("sync");
}
return ret;
}
/*
* Returns SM501 framebuffer address
*/
unsigned int board_video_get_fb (void)
{
return SM501_FB_BASE;
}
/*
* Called after initializing the SM501 and before clearing the screen.
*/
void board_validate_screen (unsigned int base)
{
}
/*
* Return a pointer to the initialization sequence.
*/
const SMI_REGS *board_get_regs (void)
{
return init_regs;
}
int board_get_width (void)
{
return DISPLAY_WIDTH;
}
int board_get_height (void)
{
return DISPLAY_HEIGHT;
}
#endif /* CONFIG_VIDEO_SM501 */
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
void ft_board_setup(void *blob, bd_t *bd)
{
ft_cpu_setup(blob, bd);
#if defined(CONFIG_VIDEO)
fdt_add_edid(blob, "smi,sm501", edid_buf);
#endif
}
#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
#if defined(CONFIG_RESET_PHY_R)
#include <miiphy.h>
void reset_phy(void)
{
/* init Micrel KSZ8993 PHY */
miiphy_write("FEC", CONFIG_PHY_ADDR, 0x01, 0x09);
}
#endif
int board_eth_init(bd_t *bis)
{
cpu_eth_init(bis); /* Built in FEC comes first */
return pci_eth_init(bis);
}

View file

@ -0,0 +1,47 @@
#
# (C) Copyright 2001-2006
# 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
ifneq ($(OBJTREE),$(SRCTREE))
$(shell mkdir -p $(obj)../tqm8xx/)
endif
LIB = $(obj)lib$(BOARD).o
COBJS = $(BOARD).o ../tqm8xx/load_sernum_ethaddr.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,368 @@
/*
* (C) Copyright 2001
* 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 <common.h>
#include <ioports.h>
#include <mpc8260.h>
/*
* I/O Port configuration table
*
* if conf is 1, then that port pin will be configured at boot time
* according to the five values podr/pdir/ppar/psor/pdat for that entry
*/
const iop_conf_t iop_conf_tab[4][32] = {
/* Port A configuration */
{ /* conf ppar psor pdir podr pdat */
/* PA31 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMTXEN */
/* PA30 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTCA */
/* PA29 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTSOC */
/* PA28 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMRXEN */
/* PA27 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRSOC */
/* PA26 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRCA */
/* PA25 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[0] */
/* PA24 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[1] */
/* PA23 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[2] */
/* PA22 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[3] */
/* PA21 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[4] */
/* PA20 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[5] */
/* PA19 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[6] */
/* PA18 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[7] */
/* PA17 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[7] */
/* PA16 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[6] */
/* PA15 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[5] */
/* PA14 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[4] */
/* PA13 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[3] */
/* PA12 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[2] */
/* PA11 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[1] */
/* PA10 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[0] */
/* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */
/* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */
/* PA7 */ { 0, 0, 0, 1, 0, 0 }, /* PA7 */
/* PA6 */ { 0, 0, 0, 1, 0, 0 }, /* PA6 */
/* PA5 */ { 0, 0, 0, 1, 0, 0 }, /* PA5 */
/* PA4 */ { 0, 0, 0, 1, 0, 0 }, /* PA4 */
/* PA3 */ { 0, 0, 0, 1, 0, 0 }, /* PA3 */
/* PA2 */ { 0, 0, 0, 1, 0, 0 }, /* PA2 */
/* PA1 */ { 0, 0, 0, 1, 0, 0 }, /* PA1 */
/* PA0 */ { 0, 0, 0, 1, 0, 0 } /* PA0 */
},
/* Port B configuration */
{ /* conf ppar psor pdir podr pdat */
/* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */
/* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */
/* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */
/* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */
/* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */
/* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */
/* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */
/* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */
/* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */
/* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */
/* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */
/* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */
/* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */
/* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */
/* PB17 */ { 0, 0, 0, 0, 0, 0 }, /* PB17 */
/* PB16 */ { 0, 0, 0, 0, 0, 0 }, /* PB16 */
/* PB15 */ { 0, 0, 0, 0, 0, 0 }, /* PB15 */
/* PB14 */ { 0, 0, 0, 0, 0, 0 }, /* PB14 */
/* PB13 */ { 0, 0, 0, 0, 0, 0 }, /* PB13 */
/* PB12 */ { 0, 0, 0, 0, 0, 0 }, /* PB12 */
/* PB11 */ { 0, 0, 0, 0, 0, 0 }, /* PB11 */
/* PB10 */ { 0, 0, 0, 0, 0, 0 }, /* PB10 */
/* PB9 */ { 0, 0, 0, 0, 0, 0 }, /* PB9 */
/* PB8 */ { 0, 0, 0, 0, 0, 0 }, /* PB8 */
/* PB7 */ { 0, 0, 0, 0, 0, 0 }, /* PB7 */
/* PB6 */ { 0, 0, 0, 0, 0, 0 }, /* PB6 */
/* PB5 */ { 0, 0, 0, 0, 0, 0 }, /* PB5 */
/* PB4 */ { 0, 0, 0, 0, 0, 0 }, /* PB4 */
/* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */
},
/* Port C */
{ /* conf ppar psor pdir podr pdat */
/* PC31 */ { 0, 0, 0, 1, 0, 0 }, /* PC31 */
/* PC30 */ { 0, 0, 0, 1, 0, 0 }, /* PC30 */
/* PC29 */ { 1, 1, 1, 0, 0, 0 }, /* SCC1 EN *CLSN */
/* PC28 */ { 0, 0, 0, 1, 0, 0 }, /* PC28 */
/* PC27 */ { 0, 0, 0, 1, 0, 0 }, /* PC27 */
/* PC26 */ { 0, 0, 0, 1, 0, 0 }, /* PC26 */
/* PC25 */ { 0, 0, 0, 1, 0, 0 }, /* PC25 */
/* PC24 */ { 0, 0, 0, 1, 0, 0 }, /* PC24 */
/* PC23 */ { 0, 1, 0, 1, 0, 0 }, /* ATMTFCLK */
/* PC22 */ { 0, 1, 0, 0, 0, 0 }, /* ATMRFCLK */
/* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RXCLK */
/* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN TXCLK */
/* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */
/* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */
/* PC17 */ { 0, 0, 0, 1, 0, 0 }, /* PC17 */
/* PC16 */ { 0, 0, 0, 1, 0, 0 }, /* PC16 */
/* PC15 */ { 0, 0, 0, 1, 0, 0 }, /* PC15 */
/* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN *CD */
/* PC13 */ { 0, 0, 0, 1, 0, 0 }, /* PC13 */
/* PC12 */ { 0, 0, 0, 1, 0, 0 }, /* PC12 */
/* PC11 */ { 0, 0, 0, 1, 0, 0 }, /* PC11 */
/* PC10 */ { 0, 0, 0, 1, 0, 0 }, /* FCC2 MDC */
/* PC9 */ { 0, 0, 0, 1, 0, 0 }, /* FCC2 MDIO */
/* PC8 */ { 0, 0, 0, 1, 0, 0 }, /* PC8 */
/* PC7 */ { 0, 0, 0, 1, 0, 0 }, /* PC7 */
/* PC6 */ { 0, 0, 0, 1, 0, 0 }, /* PC6 */
/* PC5 */ { 0, 0, 0, 1, 0, 0 }, /* PC5 */
/* PC4 */ { 0, 0, 0, 1, 0, 0 }, /* PC4 */
/* PC3 */ { 0, 0, 0, 1, 0, 0 }, /* PC3 */
/* PC2 */ { 0, 0, 0, 1, 0, 1 }, /* ENET FDE */
/* PC1 */ { 0, 0, 0, 1, 0, 0 }, /* ENET DSQE */
/* PC0 */ { 0, 0, 0, 1, 0, 0 }, /* ENET LBK */
},
/* Port D */
{ /* conf ppar psor pdir podr pdat */
/* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RxD */
/* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 EN TxD */
/* PD29 */ { 1, 1, 0, 1, 0, 0 }, /* SCC1 EN TENA */
/* PD28 */ { 0, 0, 0, 1, 0, 0 }, /* PD28 */
/* PD27 */ { 0, 0, 0, 1, 0, 0 }, /* PD27 */
/* PD26 */ { 0, 0, 0, 1, 0, 0 }, /* PD26 */
/* PD25 */ { 0, 0, 0, 1, 0, 0 }, /* PD25 */
/* PD24 */ { 0, 0, 0, 1, 0, 0 }, /* PD24 */
/* PD23 */ { 0, 0, 0, 1, 0, 0 }, /* PD23 */
/* PD22 */ { 0, 0, 0, 1, 0, 0 }, /* PD22 */
/* PD21 */ { 0, 0, 0, 1, 0, 0 }, /* PD21 */
/* PD20 */ { 0, 0, 0, 1, 0, 0 }, /* PD20 */
/* PD19 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */
/* PD18 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */
/* PD17 */ { 0, 1, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */
/* PD16 */ { 0, 1, 0, 1, 0, 0 }, /* FCC1 ATMTXPRTY */
#if defined(CONFIG_SOFT_I2C)
/* PD15 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SDA */
/* PD14 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SCL */
#else
#if defined(CONFIG_HARD_I2C)
/* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */
/* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */
#else /* normal I/O port pins */
/* PD15 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SDA */
/* PD14 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SCL */
#endif
#endif
/* PD13 */ { 0, 0, 0, 0, 0, 0 }, /* PD13 */
/* PD12 */ { 0, 0, 0, 0, 0, 0 }, /* PD12 */
/* PD11 */ { 0, 0, 0, 0, 0, 0 }, /* PD11 */
/* PD10 */ { 0, 0, 0, 0, 0, 0 }, /* PD10 */
/* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */
/* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */
/* PD7 */ { 0, 0, 0, 1, 0, 1 }, /* PD7 */
/* PD6 */ { 0, 0, 0, 1, 0, 1 }, /* PD6 */
/* PD5 */ { 0, 0, 0, 1, 0, 1 }, /* PD5 */
/* PD4 */ { 0, 0, 0, 1, 0, 1 }, /* PD4 */
/* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */
}
};
/* ------------------------------------------------------------------------- */
/* Check Board Identity:
*/
int checkboard (void)
{
char buf[64];
int i = getenv_f("serial#", buf, sizeof(buf));
puts ("Board: ");
if (i < 0 || strncmp(buf, "TQM82", 5)) {
puts ("### No HW ID - assuming TQM8260\n");
return (0);
}
puts (buf);
putc ('\n');
return 0;
}
/* ------------------------------------------------------------------------- */
/* Try SDRAM initialization with P/LSDMR=sdmr and ORx=orx
*
* This routine performs standard 8260 initialization sequence
* and calculates the available memory size. It may be called
* several times to try different SDRAM configurations on both
* 60x and local buses.
*/
static long int try_init (volatile memctl8260_t * memctl, ulong sdmr,
ulong orx, volatile uchar * base)
{
volatile uchar c = 0xff;
volatile uint *sdmr_ptr;
volatile uint *orx_ptr;
ulong maxsize, size;
int i;
/* We must be able to test a location outsize the maximum legal size
* to find out THAT we are outside; but this address still has to be
* mapped by the controller. That means, that the initial mapping has
* to be (at least) twice as large as the maximum expected size.
*/
maxsize = (1 + (~orx | 0x7fff)) / 2;
/* Since CONFIG_SYS_SDRAM_BASE is always 0 (??), we assume that
* we are configuring CS1 if base != 0
*/
sdmr_ptr = base ? &memctl->memc_lsdmr : &memctl->memc_psdmr;
orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1;
*orx_ptr = orx;
/*
* Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35):
*
* "At system reset, initialization software must set up the
* programmable parameters in the memory controller banks registers
* (ORx, BRx, P/LSDMR). After all memory parameters are configured,
* system software should execute the following initialization sequence
* for each SDRAM device.
*
* 1. Issue a PRECHARGE-ALL-BANKS command
* 2. Issue eight CBR REFRESH commands
* 3. Issue a MODE-SET command to initialize the mode register
*
* The initial commands are executed by setting P/LSDMR[OP] and
* accessing the SDRAM with a single-byte transaction."
*
* The appropriate BRx/ORx registers have already been set when we
* get here. The SDRAM can be accessed at the address CONFIG_SYS_SDRAM_BASE.
*/
*sdmr_ptr = sdmr | PSDMR_OP_PREA;
*base = c;
*sdmr_ptr = sdmr | PSDMR_OP_CBRR;
for (i = 0; i < 8; i++)
*base = c;
*sdmr_ptr = sdmr | PSDMR_OP_MRW;
*(base + CONFIG_SYS_MRS_OFFS) = c; /* setting MR on address lines */
*sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN;
*base = c;
size = get_ram_size((long *)base, maxsize);
*orx_ptr = orx | ~(size - 1);
return (size);
}
phys_size_t initdram (int board_type)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
volatile memctl8260_t *memctl = &immap->im_memctl;
#ifndef CONFIG_SYS_RAMBOOT
long size8, size9;
#endif
long psize, lsize;
psize = 16 * 1024 * 1024;
lsize = 0;
memctl->memc_psrt = CONFIG_SYS_PSRT;
memctl->memc_mptpr = CONFIG_SYS_MPTPR;
#if 0 /* Just for debugging */
#define prt_br_or(brX,orX) do { \
ulong start = memctl->memc_ ## brX & 0xFFFF8000; \
ulong sizem = ~memctl->memc_ ## orX | 0x00007FFF; \
printf ("\n" \
#brX " 0x%08x " #orX " 0x%08x " \
"==> 0x%08lx ... 0x%08lx = %ld MB\n", \
memctl->memc_ ## brX, memctl->memc_ ## orX, \
start, start+sizem, (sizem+1)>>20); \
} while (0)
prt_br_or (br0, or0);
prt_br_or (br1, or1);
prt_br_or (br2, or2);
prt_br_or (br3, or3);
#endif
#ifndef CONFIG_SYS_RAMBOOT
/* 60x SDRAM setup:
*/
size8 = try_init (memctl, CONFIG_SYS_PSDMR_8COL, CONFIG_SYS_OR1_8COL,
(uchar *) CONFIG_SYS_SDRAM_BASE);
size9 = try_init (memctl, CONFIG_SYS_PSDMR_9COL, CONFIG_SYS_OR1_9COL,
(uchar *) CONFIG_SYS_SDRAM_BASE);
if (size8 < size9) {
psize = size9;
printf ("(60x:9COL - %ld MB, ", psize >> 20);
} else {
psize = try_init (memctl, CONFIG_SYS_PSDMR_8COL, CONFIG_SYS_OR1_8COL,
(uchar *) CONFIG_SYS_SDRAM_BASE);
printf ("(60x:8COL - %ld MB, ", psize >> 20);
}
/* Local SDRAM setup:
*/
#ifdef CONFIG_SYS_INIT_LOCAL_SDRAM
memctl->memc_lsrt = CONFIG_SYS_LSRT;
size8 = try_init (memctl, CONFIG_SYS_LSDMR_8COL, CONFIG_SYS_OR2_8COL,
(uchar *) SDRAM_BASE2_PRELIM);
size9 = try_init (memctl, CONFIG_SYS_LSDMR_9COL, CONFIG_SYS_OR2_9COL,
(uchar *) SDRAM_BASE2_PRELIM);
if (size8 < size9) {
lsize = size9;
printf ("Local:9COL - %ld MB) using ", lsize >> 20);
} else {
lsize = try_init (memctl, CONFIG_SYS_LSDMR_8COL, CONFIG_SYS_OR2_8COL,
(uchar *) SDRAM_BASE2_PRELIM);
printf ("Local:8COL - %ld MB) using ", lsize >> 20);
}
#if 0
/* Set up BR2 so that the local SDRAM goes
* right after the 60x SDRAM
*/
memctl->memc_br2 = (CONFIG_SYS_BR2_PRELIM & ~BRx_BA_MSK) |
(CONFIG_SYS_SDRAM_BASE + psize);
#endif
#endif /* CONFIG_SYS_INIT_LOCAL_SDRAM */
#endif /* CONFIG_SYS_RAMBOOT */
icache_enable ();
return (psize);
}
/* ------------------------------------------------------------------------- */

View file

@ -0,0 +1,47 @@
#
# (C) Copyright 2001-2008
# 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
ifneq ($(OBJTREE),$(SRCTREE))
$(shell mkdir -p $(obj)../tqm8xx/)
endif
LIB = $(obj)lib$(BOARD).o
COBJS = $(BOARD).o ../tqm8xx/load_sernum_ethaddr.o nand.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,276 @@
/*
* (C) Copyright 2008
* Heiko Schocher, DENX Software Engineering, hs@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 <common.h>
#include <ioports.h>
#include <mpc8260.h>
#include "tqm8272.h"
/* UPM pattern for bus clock = 66.7 MHz */
static const uint upmTable67[] =
{
/* Offset UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0fa3f100, 0x0fa3b000, 0x0fa33100, 0x0fa33000,
/* 0x04 */ 0x0fa33000, 0x0fa33004, 0xfffffc01, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */
/* 0x18 */ 0x00a3fc00, 0x00a3fc00, 0x00a3fc00, 0x00a3fc00,
/* 0x1C */ 0x0fa3fc00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 100 MHz */
static const uint upmTable100[] =
{
/* Offset UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0fa3f200, 0x0fa3b000, 0x0fa33300, 0x0fa33000,
/* 0x04 */ 0x0fa33000, 0x0fa33004, 0xfffffc01, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */
/* 0x18 */ 0x00a3ff00, 0x00a3fc00, 0x00a3fc00, 0x0fa3fc00,
/* 0x1C */ 0x0fa3fc00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 133.3 MHz */
static const uint upmTable133[] =
{
/* Offset UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0fa3f300, 0x0fa3b000, 0x0fa33300, 0x0fa33000,
/* 0x04 */ 0x0fa33200, 0x0fa33004, 0xfffffc01, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */
/* 0x18 */ 0x00a3ff00, 0x00a3fc00, 0x00a3fd00, 0x0fa3fc00,
/* 0x1C */ 0x0fa3fd00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
static int chipsel = 0;
#if defined(CONFIG_CMD_NAND)
#include <nand.h>
#include <linux/mtd/mtd.h>
static u8 hwctl = 0;
static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte)
{
struct nand_chip *this = mtdinfo->priv;
ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
if (hwctl & 0x1) {
WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_CMD_OFS);
} else if (hwctl & 0x2) {
WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_ADDR_OFS);
} else {
WRITE_NAND(byte, base);
}
}
static void upmnand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
if (ctrl & NAND_CTRL_CHANGE) {
if ( ctrl & NAND_CLE )
hwctl |= 0x1;
else
hwctl &= ~0x1;
if ( ctrl & NAND_ALE )
hwctl |= 0x2;
else
hwctl &= ~0x2;
}
if (cmd != NAND_CMD_NONE)
upmnand_write_byte (mtd, cmd);
}
static u_char upmnand_read_byte(struct mtd_info *mtdinfo)
{
struct nand_chip *this = mtdinfo->priv;
ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
return READ_NAND(base);
}
static int tqm8272_dev_ready(struct mtd_info *mtdinfo)
{
/* constant delay (see also tR in the datasheet) */
udelay(12); \
return 1;
}
#ifndef CONFIG_NAND_SPL
static void tqm8272_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
int i;
for (i = 0; i< len; i++)
buf[i] = *base;
}
static void tqm8272_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
int i;
for (i = 0; i< len; i++)
*base = buf[i];
}
static int tqm8272_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
{
struct nand_chip *this = mtdinfo->priv;
unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
int i;
for (i = 0; i < len; i++)
if (buf[i] != *base)
return -1;
return 0;
}
#endif /* #ifndef CONFIG_NAND_SPL */
void board_nand_select_device(struct nand_chip *nand, int chip)
{
chipsel = chip;
}
int board_nand_init(struct nand_chip *nand)
{
static int UpmInit = 0;
volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR;
volatile memctl8260_t *memctl = &immr->im_memctl;
if (hwinf.nand == 0) return -1;
/* Setup the UPM */
if (UpmInit == 0) {
switch (hwinf.busclk_real) {
case 100000000:
upmconfig (UPMB, (uint *) upmTable100,
sizeof (upmTable100) / sizeof (uint));
break;
case 133333333:
upmconfig (UPMB, (uint *) upmTable133,
sizeof (upmTable133) / sizeof (uint));
break;
default:
upmconfig (UPMB, (uint *) upmTable67,
sizeof (upmTable67) / sizeof (uint));
break;
}
UpmInit = 1;
}
/* Setup the memctrl */
memctl->memc_or3 = CONFIG_SYS_NAND_OR;
memctl->memc_br3 = CONFIG_SYS_NAND_BR;
memctl->memc_mbmr = (MxMR_OP_NORM);
nand->ecc.mode = NAND_ECC_SOFT;
nand->cmd_ctrl = upmnand_hwcontrol;
nand->read_byte = upmnand_read_byte;
nand->dev_ready = tqm8272_dev_ready;
#ifndef CONFIG_NAND_SPL
nand->write_buf = tqm8272_write_buf;
nand->read_buf = tqm8272_read_buf;
nand->verify_buf = tqm8272_verify_buf;
#endif
/*
* Select required NAND chip
*/
board_nand_select_device(nand, 0);
return 0;
}
#endif

View file

@ -0,0 +1,960 @@
/*
* (C) Copyright 2006
* Heiko Schocher, DENX Software Engineering, hs@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 <common.h>
#include <ioports.h>
#include <mpc8260.h>
#include <command.h>
#include <netdev.h>
#ifdef CONFIG_PCI
#include <pci.h>
#include <asm/m8260_pci.h>
#endif
#include "tqm8272.h"
#if 0
#define deb_printf(fmt,arg...) \
printf ("TQM8272 %s %s: " fmt,__FILE__, __FUNCTION__, ##arg)
#else
#define deb_printf(fmt,arg...) \
do { } while (0)
#endif
#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
unsigned long board_get_cpu_clk_f (void);
#endif
/*
* I/O Port configuration table
*
* if conf is 1, then that port pin will be configured at boot time
* according to the five values podr/pdir/ppar/psor/pdat for that entry
*/
const iop_conf_t iop_conf_tab[4][32] = {
/* Port A configuration */
{ /* conf ppar psor pdir podr pdat */
/* PA31 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMTXEN */
/* PA30 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTCA */
/* PA29 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTSOC */
/* PA28 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMRXEN */
/* PA27 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRSOC */
/* PA26 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRCA */
/* PA25 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[0] */
/* PA24 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[1] */
/* PA23 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[2] */
/* PA22 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[3] */
/* PA21 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[4] */
/* PA20 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[5] */
/* PA19 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[6] */
/* PA18 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[7] */
/* PA17 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[7] */
/* PA16 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[6] */
/* PA15 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[5] */
/* PA14 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[4] */
/* PA13 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[3] */
/* PA12 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[2] */
/* PA11 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[1] */
/* PA10 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[0] */
/* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */
/* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */
/* PA7 */ { 0, 0, 0, 1, 0, 0 }, /* PA7 */
/* PA6 */ { 0, 0, 0, 1, 0, 0 }, /* PA6 */
/* PA5 */ { 0, 0, 0, 1, 0, 0 }, /* PA5 */
/* PA4 */ { 0, 0, 0, 1, 0, 0 }, /* PA4 */
/* PA3 */ { 0, 0, 0, 1, 0, 0 }, /* PA3 */
/* PA2 */ { 0, 0, 0, 1, 0, 0 }, /* PA2 */
/* PA1 */ { 0, 0, 0, 1, 0, 0 }, /* PA1 */
/* PA0 */ { 0, 0, 0, 1, 0, 0 } /* PA0 */
},
/* Port B configuration */
{ /* conf ppar psor pdir podr pdat */
/* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */
/* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */
/* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */
/* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */
/* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */
/* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */
/* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */
/* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */
/* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */
/* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */
/* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */
/* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */
/* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */
/* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */
/* PB17 */ { 0, 0, 0, 0, 0, 0 }, /* PB17 */
/* PB16 */ { 0, 0, 0, 0, 0, 0 }, /* PB16 */
/* PB15 */ { 0, 0, 0, 0, 0, 0 }, /* PB15 */
/* PB14 */ { 0, 0, 0, 0, 0, 0 }, /* PB14 */
/* PB13 */ { 0, 0, 0, 0, 0, 0 }, /* PB13 */
/* PB12 */ { 0, 0, 0, 0, 0, 0 }, /* PB12 */
/* PB11 */ { 0, 0, 0, 0, 0, 0 }, /* PB11 */
/* PB10 */ { 0, 0, 0, 0, 0, 0 }, /* PB10 */
/* PB9 */ { 0, 0, 0, 0, 0, 0 }, /* PB9 */
/* PB8 */ { 0, 0, 0, 0, 0, 0 }, /* PB8 */
/* PB7 */ { 0, 0, 0, 0, 0, 0 }, /* PB7 */
/* PB6 */ { 0, 0, 0, 0, 0, 0 }, /* PB6 */
/* PB5 */ { 0, 0, 0, 0, 0, 0 }, /* PB5 */
/* PB4 */ { 0, 0, 0, 0, 0, 0 }, /* PB4 */
/* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */
},
/* Port C */
{ /* conf ppar psor pdir podr pdat */
/* PC31 */ { 0, 0, 0, 1, 0, 0 }, /* PC31 */
/* PC30 */ { 0, 0, 0, 0, 0, 0 }, /* PC30 */
/* PC29 */ { 1, 1, 1, 0, 0, 0 }, /* SCC1 EN *CLSN */
/* PC28 */ { 0, 0, 0, 1, 0, 0 }, /* PC28 */
/* PC27 */ { 0, 0, 0, 1, 0, 0 }, /* PC27 */
/* PC26 */ { 0, 0, 0, 1, 0, 0 }, /* PC26 */
/* PC25 */ { 0, 0, 0, 1, 0, 0 }, /* PC25 */
/* PC24 */ { 0, 0, 0, 1, 0, 0 }, /* PC24 */
/* PC23 */ { 0, 1, 0, 1, 0, 0 }, /* ATMTFCLK */
/* PC22 */ { 0, 1, 0, 0, 0, 0 }, /* ATMRFCLK */
/* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RXCLK */
/* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN TXCLK */
/* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */
/* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */
/* PC17 */ { 1, 0, 0, 1, 0, 0 }, /* PC17 MDC */
/* PC16 */ { 1, 0, 0, 0, 0, 0 }, /* PC16 MDIO*/
/* PC15 */ { 0, 0, 0, 1, 0, 0 }, /* PC15 */
/* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN *CD */
/* PC13 */ { 0, 0, 0, 1, 0, 0 }, /* PC13 */
/* PC12 */ { 0, 0, 0, 1, 0, 0 }, /* PC12 */
/* PC11 */ { 0, 0, 0, 1, 0, 0 }, /* PC11 */
/* PC10 */ { 0, 0, 0, 1, 0, 0 }, /* PC10 */
/* PC9 */ { 0, 0, 0, 1, 0, 0 }, /* PC9 */
/* PC8 */ { 0, 0, 0, 1, 0, 0 }, /* PC8 */
/* PC7 */ { 0, 0, 0, 1, 0, 0 }, /* PC7 */
/* PC6 */ { 0, 0, 0, 1, 0, 0 }, /* PC6 */
/* PC5 */ { 1, 1, 0, 1, 0, 0 }, /* PC5 SMC1 TXD */
/* PC4 */ { 1, 1, 0, 0, 0, 0 }, /* PC4 SMC1 RXD */
/* PC3 */ { 0, 0, 0, 1, 0, 0 }, /* PC3 */
/* PC2 */ { 0, 0, 0, 1, 0, 1 }, /* ENET FDE */
/* PC1 */ { 0, 0, 0, 1, 0, 0 }, /* ENET DSQE */
/* PC0 */ { 0, 0, 0, 1, 0, 0 }, /* ENET LBK */
},
/* Port D */
{ /* conf ppar psor pdir podr pdat */
/* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RxD */
/* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 EN TxD */
/* PD29 */ { 1, 1, 0, 1, 0, 0 }, /* SCC1 EN TENA */
/* PD28 */ { 0, 0, 0, 1, 0, 0 }, /* PD28 */
/* PD27 */ { 0, 0, 0, 1, 0, 0 }, /* PD27 */
/* PD26 */ { 0, 0, 0, 1, 0, 0 }, /* PD26 */
/* PD25 */ { 0, 0, 0, 1, 0, 0 }, /* PD25 */
/* PD24 */ { 0, 0, 0, 1, 0, 0 }, /* PD24 */
/* PD23 */ { 0, 0, 0, 1, 0, 0 }, /* PD23 */
/* PD22 */ { 0, 0, 0, 1, 0, 0 }, /* PD22 */
/* PD21 */ { 0, 0, 0, 1, 0, 0 }, /* PD21 */
/* PD20 */ { 0, 0, 0, 1, 0, 0 }, /* PD20 */
/* PD19 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */
/* PD18 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */
/* PD17 */ { 0, 1, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */
/* PD16 */ { 0, 1, 0, 1, 0, 0 }, /* FCC1 ATMTXPRTY */
#if defined(CONFIG_SOFT_I2C)
/* PD15 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SDA */
/* PD14 */ { 1, 0, 0, 1, 1, 1 }, /* I2C SCL */
#else
#if defined(CONFIG_HARD_I2C)
/* PD15 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SDA */
/* PD14 */ { 1, 1, 1, 0, 1, 0 }, /* I2C SCL */
#else /* normal I/O port pins */
/* PD15 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SDA */
/* PD14 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SCL */
#endif
#endif
/* PD13 */ { 0, 0, 0, 0, 0, 0 }, /* PD13 */
/* PD12 */ { 0, 0, 0, 0, 0, 0 }, /* PD12 */
/* PD11 */ { 0, 0, 0, 0, 0, 0 }, /* PD11 */
/* PD10 */ { 0, 0, 0, 0, 0, 0 }, /* PD10 */
/* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */
/* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */
/* PD7 */ { 0, 0, 0, 1, 0, 1 }, /* PD7 */
/* PD6 */ { 0, 0, 0, 1, 0, 1 }, /* PD6 */
/* PD5 */ { 0, 0, 0, 1, 0, 0 }, /* PD5 */
/* PD4 */ { 0, 0, 0, 1, 0, 1 }, /* PD4 */
/* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
/* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */
}
};
/* UPM pattern for slow init */
static const uint upmTableSlow[] =
{
/* Offset UPM Read Single RAM array entry */
/* 0x00 */ 0xffffee00, 0x00ffcc80, 0x00ffcf00, 0x00ffdc00,
/* 0x04 */ 0x00ffce80, 0x00ffcc00, 0x00ffee00, 0x3fffcc07,
/* UPM Read Burst RAM array entry -> unused */
/* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry */
/* 0x18 */ 0xffffee00, 0x00ffec80, 0x00ffef00, 0x00fffc80,
/* 0x1C */ 0x00fffe00, 0x00ffec00, 0x0fffef00, 0x3fffec05,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for fast init */
static const uint upmTableFast[] =
{
/* Offset UPM Read Single RAM array entry */
/* 0x00 */ 0xffffee00, 0x00ffcc80, 0x00ffcd80, 0x00ffdc00,
/* 0x04 */ 0x00ffdc00, 0x00ffcf00, 0x00ffec00, 0x3fffcc07,
/* UPM Read Burst RAM array entry -> unused */
/* 0x08 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> unused */
/* 0x10 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry */
/* 0x18 */ 0xffffee00, 0x00ffec80, 0x00ffee80, 0x00fffc00,
/* 0x1C */ 0x00fffc00, 0x00ffec00, 0x0fffef00, 0x3fffec05,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* ------------------------------------------------------------------------- */
/* Check Board Identity:
*/
int checkboard (void)
{
char *p = (char *) HWIB_INFO_START_ADDR;
puts ("Board: ");
if (*((unsigned long *)p) == (unsigned long)CONFIG_SYS_HWINFO_MAGIC) {
puts (p);
} else {
puts ("No HWIB assuming TQM8272");
}
putc ('\n');
return 0;
}
/* ------------------------------------------------------------------------- */
#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
static int get_cas_latency (void)
{
/* get it from the option -ts in CIB */
/* default is 3 */
int ret = 3;
int pos = 0;
char *p = (char *) CIB_INFO_START_ADDR;
while ((*p != '\0') && (pos < CIB_INFO_LEN)) {
if (*p < ' ' || *p > '~') { /* ASCII strings! */
return ret;
}
if (*p == '-') {
if ((p[1] == 't') && (p[2] == 's')) {
return (p[4] - '0');
}
}
p++;
pos++;
}
return ret;
}
#endif
static ulong set_sdram_timing (volatile uint *sdmr_ptr, ulong sdmr, int col)
{
#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
int clk = board_get_cpu_clk_f ();
volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
int busmode = (immr->im_siu_conf.sc_bcr & BCR_EBM ? 1 : 0);
int cas;
sdmr = sdmr & ~(PSDMR_RFRC_MSK | PSDMR_PRETOACT_MSK | PSDMR_WRC_MSK | \
PSDMR_BUFCMD);
if (busmode) {
switch (clk) {
case 66666666:
sdmr |= (PSDMR_RFRC_66MHZ_60X | \
PSDMR_PRETOACT_66MHZ_60X | \
PSDMR_WRC_66MHZ_60X | \
PSDMR_BUFCMD_66MHZ_60X);
break;
case 100000000:
sdmr |= (PSDMR_RFRC_100MHZ_60X | \
PSDMR_PRETOACT_100MHZ_60X | \
PSDMR_WRC_100MHZ_60X | \
PSDMR_BUFCMD_100MHZ_60X);
break;
}
} else {
switch (clk) {
case 66666666:
sdmr |= (PSDMR_RFRC_66MHZ_SINGLE | \
PSDMR_PRETOACT_66MHZ_SINGLE | \
PSDMR_WRC_66MHZ_SINGLE | \
PSDMR_BUFCMD_66MHZ_SINGLE);
break;
case 100000000:
sdmr |= (PSDMR_RFRC_100MHZ_SINGLE | \
PSDMR_PRETOACT_100MHZ_SINGLE | \
PSDMR_WRC_100MHZ_SINGLE | \
PSDMR_BUFCMD_100MHZ_SINGLE);
break;
case 133333333:
sdmr |= (PSDMR_RFRC_133MHZ_SINGLE | \
PSDMR_PRETOACT_133MHZ_SINGLE | \
PSDMR_WRC_133MHZ_SINGLE | \
PSDMR_BUFCMD_133MHZ_SINGLE);
break;
}
}
cas = get_cas_latency();
sdmr &=~ (PSDMR_CL_MSK | PSDMR_LDOTOPRE_MSK);
sdmr |= cas;
sdmr |= ((cas - 1) << 6);
return sdmr;
#else
return sdmr;
#endif
}
/* Try SDRAM initialization with P/LSDMR=sdmr and ORx=orx
*
* This routine performs standard 8260 initialization sequence
* and calculates the available memory size. It may be called
* several times to try different SDRAM configurations on both
* 60x and local buses.
*/
static long int try_init (volatile memctl8260_t * memctl, ulong sdmr,
ulong orx, volatile uchar * base, int col)
{
volatile uchar c = 0xff;
volatile uint *sdmr_ptr;
volatile uint *orx_ptr;
ulong maxsize, size;
int i;
/* We must be able to test a location outsize the maximum legal size
* to find out THAT we are outside; but this address still has to be
* mapped by the controller. That means, that the initial mapping has
* to be (at least) twice as large as the maximum expected size.
*/
maxsize = (1 + (~orx | 0x7fff)) / 2;
/* Since CONFIG_SYS_SDRAM_BASE is always 0 (??), we assume that
* we are configuring CS1 if base != 0
*/
sdmr_ptr = base ? &memctl->memc_lsdmr : &memctl->memc_psdmr;
orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1;
*orx_ptr = orx;
sdmr = set_sdram_timing (sdmr_ptr, sdmr, col);
/*
* Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35):
*
* "At system reset, initialization software must set up the
* programmable parameters in the memory controller banks registers
* (ORx, BRx, P/LSDMR). After all memory parameters are configured,
* system software should execute the following initialization sequence
* for each SDRAM device.
*
* 1. Issue a PRECHARGE-ALL-BANKS command
* 2. Issue eight CBR REFRESH commands
* 3. Issue a MODE-SET command to initialize the mode register
*
* The initial commands are executed by setting P/LSDMR[OP] and
* accessing the SDRAM with a single-byte transaction."
*
* The appropriate BRx/ORx registers have already been set when we
* get here. The SDRAM can be accessed at the address CONFIG_SYS_SDRAM_BASE.
*/
*sdmr_ptr = sdmr | PSDMR_OP_PREA;
*base = c;
*sdmr_ptr = sdmr | PSDMR_OP_CBRR;
for (i = 0; i < 8; i++)
*base = c;
*sdmr_ptr = sdmr | PSDMR_OP_MRW;
*(base + CONFIG_SYS_MRS_OFFS) = c; /* setting MR on address lines */
*sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN;
*base = c;
size = get_ram_size((long *)base, maxsize);
*orx_ptr = orx | ~(size - 1);
return (size);
}
phys_size_t initdram (int board_type)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
volatile memctl8260_t *memctl = &immap->im_memctl;
#ifndef CONFIG_SYS_RAMBOOT
long size8, size9;
#endif
long psize;
psize = 16 * 1024 * 1024;
memctl->memc_psrt = CONFIG_SYS_PSRT;
memctl->memc_mptpr = CONFIG_SYS_MPTPR;
#ifndef CONFIG_SYS_RAMBOOT
/* 60x SDRAM setup:
*/
size8 = try_init (memctl, CONFIG_SYS_PSDMR_8COL, CONFIG_SYS_OR1_8COL,
(uchar *) CONFIG_SYS_SDRAM_BASE, 8);
size9 = try_init (memctl, CONFIG_SYS_PSDMR_9COL, CONFIG_SYS_OR1_9COL,
(uchar *) CONFIG_SYS_SDRAM_BASE, 9);
if (size8 < size9) {
psize = size9;
printf ("(60x:9COL - %ld MB, ", psize >> 20);
} else {
psize = try_init (memctl, CONFIG_SYS_PSDMR_8COL, CONFIG_SYS_OR1_8COL,
(uchar *) CONFIG_SYS_SDRAM_BASE, 8);
printf ("(60x:8COL - %ld MB, ", psize >> 20);
}
#endif /* CONFIG_SYS_RAMBOOT */
icache_enable ();
return (psize);
}
static inline int scanChar (char *p, int len, unsigned long *number)
{
int akt = 0;
*number = 0;
while (akt < len) {
if ((*p >= '0') && (*p <= '9')) {
*number *= 10;
*number += *p - '0';
p += 1;
} else {
if (*p == '-') return akt;
return -1;
}
akt ++;
}
return akt;
}
static int dump_hwib(void)
{
HWIB_INFO *hw = &hwinf;
char buf[64];
int i = getenv_f("serial#", buf, sizeof(buf));
volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
if (i < 0)
buf[0] = '\0';
if (hw->OK) {
printf ("HWIB on %x\n", HWIB_INFO_START_ADDR);
printf ("serial : %s\n", buf);
printf ("ethaddr: %s\n", hw->ethaddr);
printf ("FLASH : %x nr:%d\n", hw->flash, hw->flash_nr);
printf ("RAM : %x cs:%d\n", hw->ram, hw->ram_cs);
printf ("CPU : %lu\n", hw->cpunr);
printf ("CAN : %d\n", hw->can);
if (hw->eeprom) printf ("EEprom : %x\n", hw->eeprom);
else printf ("No EEprom\n");
if (hw->nand) {
printf ("NAND : %x\n", hw->nand);
printf ("NAND CS: %d\n", hw->nand_cs);
} else { printf ("No NAND\n");}
printf ("Bus %s mode.\n", (hw->Bus ? "60x" : "Single PQII"));
printf (" real : %s\n", (immr->im_siu_conf.sc_bcr & BCR_EBM ? \
"60x" : "Single PQII"));
printf ("Option : %lx\n", hw->option);
printf ("%s Security Engine\n", (hw->SecEng ? "with" : "no"));
printf ("CPM Clk: %d\n", hw->cpmcl);
printf ("CPU Clk: %d\n", hw->cpucl);
printf ("Bus Clk: %d\n", hw->buscl);
if (hw->busclk_real_ok) {
printf (" real Clk: %d\n", hw->busclk_real);
}
printf ("CAS : %d\n", get_cas_latency());
} else {
printf("HWIB @%x not OK\n", HWIB_INFO_START_ADDR);
}
return 0;
}
static inline int search_real_busclk (int *clk)
{
int part = 0, pos = 0;
char *p = (char *) CIB_INFO_START_ADDR;
int ok = 0;
while ((*p != '\0') && (pos < CIB_INFO_LEN)) {
if (*p < ' ' || *p > '~') { /* ASCII strings! */
return 0;
}
switch (part) {
default:
if (*p == '-') {
++part;
}
break;
case 3:
if (*p == '-') {
++part;
break;
}
if (*p == 'b') {
ok = 1;
p++;
break;
}
if (ok) {
switch (*p) {
case '6':
*clk = 66666666;
return 1;
break;
case '1':
if (p[1] == '3') {
*clk = 133333333;
} else {
*clk = 100000000;
}
return 1;
break;
}
}
break;
}
p++;
}
return 0;
}
int analyse_hwib (void)
{
char *p = (char *) HWIB_INFO_START_ADDR;
int anz;
int part = 1, i = 0, pos = 0;
HWIB_INFO *hw = &hwinf;
deb_printf(" %s pointer: %p\n", __FUNCTION__, p);
/* Head = TQM */
if (*((unsigned long *)p) != (unsigned long)CONFIG_SYS_HWINFO_MAGIC) {
deb_printf("No HWIB\n");
return -1;
}
p += 3;
if (scanChar (p, 4, &hw->cpunr) < 0) {
deb_printf("No CPU\n");
return -2;
}
p +=4;
hw->flash = 0x200000 << (*p - 'A');
p++;
hw->flash_nr = *p - '0';
p++;
hw->ram = 0x2000000 << (*p - 'A');
p++;
if (*p == '2') {
hw->ram_cs = 2;
p++;
}
if (*p == 'A') hw->can = 1;
if (*p == 'B') hw->can = 2;
p +=1;
p +=1; /* connector */
if (*p != '0') {
hw->eeprom = 0x1000 << (*p - 'A');
}
p++;
if ((*p < '0') || (*p > '9')) {
/* NAND before z-option */
hw->nand = 0x8000000 << (*p - 'A');
p++;
hw->nand_cs = *p - '0';
p += 2;
}
/* z-option */
anz = scanChar (p, 4, &hw->option);
if (anz < 0) {
deb_printf("No option\n");
return -3;
}
if (hw->option & 0x8) hw->Bus = 1;
p += anz;
if (*p != '-') {
deb_printf("No -\n");
return -4;
}
p++;
/* C option */
if (*p == 'E') {
hw->SecEng = 1;
p++;
}
switch (*p) {
case 'M': hw->cpucl = 266666666;
break;
case 'P': hw->cpucl = 300000000;
break;
case 'T': hw->cpucl = 400000000;
break;
default:
deb_printf("No CPU Clk: %c\n", *p);
return -5;
break;
}
p++;
switch (*p) {
case 'I': hw->cpmcl = 200000000;
break;
case 'M': hw->cpmcl = 300000000;
break;
default:
deb_printf("No CPM Clk\n");
return -6;
break;
}
p++;
switch (*p) {
case 'B': hw->buscl = 66666666;
break;
case 'E': hw->buscl = 100000000;
break;
case 'F': hw->buscl = 133333333;
break;
default:
deb_printf("No BUS Clk\n");
return -7;
break;
}
p++;
hw->OK = 1;
/* search MAC Address */
while ((*p != '\0') && (pos < CONFIG_SYS_HWINFO_SIZE)) {
if (*p < ' ' || *p > '~') { /* ASCII strings! */
return 0;
}
switch (part) {
default:
if (*p == ' ') {
++part;
i = 0;
}
break;
case 3: /* Copy MAC address */
if (*p == ' ') {
++part;
i = 0;
break;
}
hw->ethaddr[i++] = *p;
if ((i % 3) == 2)
hw->ethaddr[i++] = ':';
break;
}
p++;
}
hw->busclk_real_ok = search_real_busclk (&hw->busclk_real);
return 0;
}
#if defined(CONFIG_GET_CPU_STR_F)
/* !! This routine runs from Flash */
char get_cpu_str_f (char *buf)
{
char *p = (char *) HWIB_INFO_START_ADDR;
int i = 0;
buf[i++] = 'M';
buf[i++] = 'P';
buf[i++] = 'C';
if (*((unsigned long *)p) == (unsigned long)CONFIG_SYS_HWINFO_MAGIC) {
buf[i++] = *&p[3];
buf[i++] = *&p[4];
buf[i++] = *&p[5];
buf[i++] = *&p[6];
} else {
buf[i++] = '8';
buf[i++] = '2';
buf[i++] = '7';
buf[i++] = 'x';
}
buf[i++] = 0;
return 0;
}
#endif
#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
/* !! This routine runs from Flash */
unsigned long board_get_cpu_clk_f (void)
{
char *p = (char *) HWIB_INFO_START_ADDR;
int i = 0;
if (*((unsigned long *)p) == (unsigned long)CONFIG_SYS_HWINFO_MAGIC) {
if (search_real_busclk (&i))
return i;
}
return CONFIG_8260_CLKIN;
}
#endif
#if CONFIG_BOARD_EARLY_INIT_R
static int can_test (unsigned long off)
{
volatile unsigned char *base = (unsigned char *) (CONFIG_SYS_CAN_BASE + off);
*(base + 0x17) = 'T';
*(base + 0x18) = 'Q';
*(base + 0x19) = 'M';
if ((*(base + 0x17) != 'T') ||
(*(base + 0x18) != 'Q') ||
(*(base + 0x19) != 'M')) {
return 0;
}
return 1;
}
static int can_config_one (unsigned long off)
{
volatile unsigned char *ctrl = (unsigned char *) (CONFIG_SYS_CAN_BASE + off);
volatile unsigned char *cpu_if = (unsigned char *) (CONFIG_SYS_CAN_BASE + off + 0x02);
volatile unsigned char *clkout = (unsigned char *) (CONFIG_SYS_CAN_BASE + off + 0x1f);
unsigned char temp;
*cpu_if = 0x45;
temp = *ctrl;
temp |= 0x40;
*ctrl = temp;
*clkout = 0x20;
temp = *ctrl;
temp &= ~0x40;
*ctrl = temp;
return 0;
}
static int can_config (void)
{
int ret = 0;
can_config_one (0);
if (hwinf.can == 2) {
can_config_one (0x100);
}
/* make Test if they really there */
ret += can_test (0);
ret += can_test (0x100);
return ret;
}
static int init_can (void)
{
volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR;
volatile memctl8260_t *memctl = &immr->im_memctl;
int count = 0;
if ((hwinf.OK) && (hwinf.can)) {
memctl->memc_or4 = CONFIG_SYS_CAN_OR;
memctl->memc_br4 = CONFIG_SYS_CAN_BR;
/* upm Init */
upmconfig (UPMC, (uint *) upmTableFast,
sizeof (upmTableFast) / sizeof (uint));
memctl->memc_mcmr = (MxMR_DSx_3_CYCL |
MxMR_GPL_x4DIS |
MxMR_RLFx_2X |
MxMR_WLFx_2X |
MxMR_OP_NORM);
/* can configure */
count = can_config ();
printf ("CAN: %d @ %x\n", count, CONFIG_SYS_CAN_BASE);
if (hwinf.can != count) printf("!!! difference to HWIB\n");
} else {
printf ("CAN: No\n");
}
return 0;
}
int board_early_init_r(void)
{
analyse_hwib ();
init_can ();
return 0;
}
#endif
int do_hwib_dump (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
dump_hwib ();
return 0;
}
U_BOOT_CMD(
hwib, 1, 1, do_hwib_dump,
"dump HWIB'",
""
);
#ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
static int get_flash_timing (void)
{
/* get it from the option -tf in CIB */
/* default is 0x00000c84 */
int ret = 0x00000c84;
int pos = 0;
int nr = 0;
char *p = (char *) CIB_INFO_START_ADDR;
while ((*p != '\0') && (pos < CIB_INFO_LEN)) {
if (*p < ' ' || *p > '~') { /* ASCII strings! */
return ret;
}
if (*p == '-') {
if ((p[1] == 't') && (p[2] == 'f')) {
p += 6;
ret = 0;
while (nr < 8) {
if ((*p >= '0') && (*p <= '9')) {
ret *= 0x10;
ret += *p - '0';
p += 1;
nr ++;
} else if ((*p >= 'A') && (*p <= 'F')) {
ret *= 10;
ret += *p - '7';
p += 1;
nr ++;
} else {
if (nr < 8) return 0x00000c84;
return ret;
}
}
}
}
p++;
pos++;
}
return ret;
}
/* Update the Flash_Size and the Flash Timing */
int update_flash_size (int flash_size)
{
volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR;
volatile memctl8260_t *memctl = &immr->im_memctl;
unsigned long reg;
unsigned long tim;
/* I must use reg, otherwise the board hang */
reg = memctl->memc_or0;
reg &= ~ORxU_AM_MSK;
reg |= MEG_TO_AM(flash_size >> 20);
tim = get_flash_timing ();
reg &= ~0xfff;
reg |= (tim & 0xfff);
memctl->memc_or0 = reg;
return 0;
}
#endif
#ifdef CONFIG_PCI
struct pci_controller hose;
int board_early_init_f (void)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
immap->im_clkrst.car_sccr |= M826X_SCCR_PCI_MODE_EN;
return 0;
}
extern void pci_mpc8250_init(struct pci_controller *);
void pci_init_board(void)
{
pci_mpc8250_init(&hose);
}
#endif
int board_eth_init(bd_t *bis)
{
return pci_eth_init(bis);
}

View file

@ -0,0 +1,53 @@
/*
* (C) Copyright 2008
* Heiko Schocher, DENX Software Engineering, hs@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
*/
#ifndef _TQM8272_HEADER_H
#define _TQM8272_HEADER_H
#define _NOT_USED_ 0xFFFFFFFF
typedef struct{
int Bus;
int flash;
int flash_nr;
int ram;
int ram_cs;
int nand;
int nand_cs;
int eeprom;
int can;
unsigned long cpunr;
unsigned long option;
int SecEng;
int cpucl;
int cpmcl;
int buscl;
int busclk_real_ok;
int busclk_real;
unsigned char OK;
unsigned char ethaddr[20];
} HWIB_INFO;
static HWIB_INFO hwinf = {0, 0, 1, 0, 1, 0, 0, 0, 0, 8272, 0 ,0,
0, 0, 0, 0, 0, 0};
#endif

View file

@ -0,0 +1,48 @@
#
# (C) Copyright 2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# Copyright 2004 Freescale Semiconductor, Inc.
#
# 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 = $(obj)lib$(BOARD).o
COBJS-y += $(BOARD).o
COBJS-$(CONFIG_PCI) += pci.o
COBJS := $(COBJS-y)
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,116 @@
/*
* (C) Copyright 2005
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
* Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
*
* 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 <asm/mmu.h>
#include <asm/io.h>
#include <common.h>
#include <mpc83xx.h>
#include <pci.h>
#include <i2c.h>
#include <asm/fsl_i2c.h>
DECLARE_GLOBAL_DATA_PTR;
static struct pci_region pci1_regions[] = {
{
bus_start: CONFIG_SYS_PCI1_MEM_BASE,
phys_start: CONFIG_SYS_PCI1_MEM_PHYS,
size: CONFIG_SYS_PCI1_MEM_SIZE,
flags: PCI_REGION_MEM | PCI_REGION_PREFETCH
},
{
bus_start: CONFIG_SYS_PCI1_IO_BASE,
phys_start: CONFIG_SYS_PCI1_IO_PHYS,
size: CONFIG_SYS_PCI1_IO_SIZE,
flags: PCI_REGION_IO
},
{
bus_start: CONFIG_SYS_PCI1_MMIO_BASE,
phys_start: CONFIG_SYS_PCI1_MMIO_PHYS,
size: CONFIG_SYS_PCI1_MMIO_SIZE,
flags: PCI_REGION_MEM
},
};
/*
* pci_init_board()
*
* NOTICE: MPC8349 internally has two PCI controllers (PCI1 and PCI2) but since
* per TQM834x design physical connections to external devices (PCI sockets)
* are routed only to the PCI1 we do not account for the second one - this code
* supports PCI1 module only. Should support for the PCI2 be required in the
* future it needs a separate pci_controller structure (above) and handling -
* please refer to other boards' implementation for dual PCI host controllers,
* for example board/Marvell/db64360/pci.c, pci_init_board()
*
*/
void
pci_init_board(void)
{
volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
volatile clk83xx_t *clk = (volatile clk83xx_t *)&immr->clk;
volatile law83xx_t *pci_law = immr->sysconf.pcilaw;
struct pci_region *reg[] = { pci1_regions };
u32 reg32;
/*
* Configure PCI controller and PCI_CLK_OUTPUT
*
* WARNING! only PCI_CLK_OUTPUT1 is enabled here as this is the one
* line actually used for clocking all external PCI devices in TQM83xx.
* Enabling other PCI_CLK_OUTPUT lines may lead to board's hang for
* unknown reasons - particularly PCI_CLK_OUTPUT6 and PCI_CLK_OUTPUT7
* are known to hang the board; this issue is under investigation
* (13 oct 05)
*/
reg32 = OCCR_PCICOE1;
#if 0
/* enabling all PCI_CLK_OUTPUT lines HANGS the board... */
reg32 = 0xff000000;
#endif
if (clk->spmr & SPMR_CKID) {
/* PCI Clock is half CONFIG_83XX_CLKIN so need to set up OCCR
* fields accordingly */
reg32 |= (OCCR_PCI1CR | OCCR_PCI2CR);
reg32 |= (OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 \
| OCCR_PCICD3 | OCCR_PCICD4 | OCCR_PCICD5 \
| OCCR_PCICD6 | OCCR_PCICD7);
}
clk->occr = reg32;
udelay(2000);
/* Configure PCI Local Access Windows */
pci_law[0].bar = CONFIG_SYS_PCI1_MEM_PHYS & LAWBAR_BAR;
pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_512M;
pci_law[1].bar = CONFIG_SYS_PCI1_IO_PHYS & LAWBAR_BAR;
pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_16M;
udelay(2000);
mpc83xx_pci_init(1, reg);
}

View file

@ -0,0 +1,442 @@
/*
* (C) Copyright 2005
* 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 <common.h>
#include <ioports.h>
#include <mpc83xx.h>
#include <asm/mpc8349_pci.h>
#include <i2c.h>
#include <miiphy.h>
#include <asm/mmu.h>
#include <pci.h>
#include <flash.h>
#include <mtd/cfi_flash.h>
DECLARE_GLOBAL_DATA_PTR;
#define IOSYNC asm("eieio")
#define ISYNC asm("isync")
#define SYNC asm("sync")
#define FPW FLASH_PORT_WIDTH
#define FPWV FLASH_PORT_WIDTHV
#define DDR_MAX_SIZE_PER_CS 0x20000000
#if defined(DDR_CASLAT_20)
#define TIMING_CASLAT TIMING_CFG1_CASLAT_20
#define MODE_CASLAT DDR_MODE_CASLAT_20
#else
#define TIMING_CASLAT TIMING_CFG1_CASLAT_25
#define MODE_CASLAT DDR_MODE_CASLAT_25
#endif
#define INITIAL_CS_CONFIG (CSCONFIG_EN | CSCONFIG_ROW_BIT_12 | \
CSCONFIG_COL_BIT_9)
/* External definitions */
ulong flash_get_size (ulong base, int banknum);
/* Local functions */
static int detect_num_flash_banks(void);
static long int get_ddr_bank_size(short cs, long *base);
static void set_cs_bounds(short cs, long base, long size);
static void set_cs_config(short cs, long config);
static void set_ddr_config(void);
/* Local variable */
static volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
/**************************************************************************
* Board initialzation after relocation to RAM. Used to detect the number
* of Flash banks on TQM834x.
*/
int board_early_init_r (void) {
/* sanity check, IMMARBAR should be mirrored at offset zero of IMMR */
if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im)
return 0;
/* detect the number of Flash banks */
return detect_num_flash_banks();
}
/**************************************************************************
* DRAM initalization and size detection
*/
phys_size_t initdram (int board_type)
{
long bank_size;
long size;
int cs;
/* during size detection, set up the max DDRLAW size */
im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_BASE;
im->sysconf.ddrlaw[0].ar = (LAWAR_EN | LAWAR_SIZE_2G);
/* set CS bounds to maximum size */
for(cs = 0; cs < 4; ++cs) {
set_cs_bounds(cs,
CONFIG_SYS_DDR_BASE + (cs * DDR_MAX_SIZE_PER_CS),
DDR_MAX_SIZE_PER_CS);
set_cs_config(cs, INITIAL_CS_CONFIG);
}
/* configure ddr controller */
set_ddr_config();
udelay(200);
/* enable DDR controller */
im->ddr.sdram_cfg = (SDRAM_CFG_MEM_EN |
SDRAM_CFG_SREN |
SDRAM_CFG_SDRAM_TYPE_DDR1);
SYNC;
/* size detection */
debug("\n");
size = 0;
for(cs = 0; cs < 4; ++cs) {
debug("\nDetecting Bank%d\n", cs);
bank_size = get_ddr_bank_size(cs,
(long *)(CONFIG_SYS_DDR_BASE + size));
size += bank_size;
debug("DDR Bank%d size: %ld MiB\n\n", cs, bank_size >> 20);
/* exit if less than one bank */
if(size < DDR_MAX_SIZE_PER_CS) break;
}
return size;
}
/**************************************************************************
* checkboard()
*/
int checkboard (void)
{
puts("Board: TQM834x\n");
#ifdef CONFIG_PCI
volatile immap_t * immr;
u32 w, f;
immr = (immap_t *)CONFIG_SYS_IMMR;
if (!(immr->reset.rcwh & HRCWH_PCI_HOST)) {
printf("PCI: NOT in host mode..?!\n");
return 0;
}
/* get bus width */
w = 32;
if (immr->reset.rcwh & HRCWH_64_BIT_PCI)
w = 64;
/* get clock */
f = gd->pci_clk;
printf("PCI1: %d bit, %d MHz\n", w, f / 1000000);
#else
printf("PCI: disabled\n");
#endif
return 0;
}
/**************************************************************************
*
* Local functions
*
*************************************************************************/
/**************************************************************************
* Detect the number of flash banks (1 or 2). Store it in
* a global variable tqm834x_num_flash_banks.
* Bank detection code based on the Monitor code.
*/
static int detect_num_flash_banks(void)
{
typedef unsigned long FLASH_PORT_WIDTH;
typedef volatile unsigned long FLASH_PORT_WIDTHV;
FPWV *bank1_base;
FPWV *bank2_base;
FPW bank1_read;
FPW bank2_read;
ulong bank1_size;
ulong bank2_size;
ulong total_size;
cfi_flash_num_flash_banks = 2; /* assume two banks */
/* Get bank 1 and 2 information */
bank1_size = flash_get_size(CONFIG_SYS_FLASH_BASE, 0);
debug("Bank1 size: %lu\n", bank1_size);
bank2_size = flash_get_size(CONFIG_SYS_FLASH_BASE + bank1_size, 1);
debug("Bank2 size: %lu\n", bank2_size);
total_size = bank1_size + bank2_size;
if (bank2_size > 0) {
/* Seems like we've got bank 2, but maybe it's mirrored 1 */
/* Set the base addresses */
bank1_base = (FPWV *) (CONFIG_SYS_FLASH_BASE);
bank2_base = (FPWV *) (CONFIG_SYS_FLASH_BASE + bank1_size);
/* Put bank 2 into CFI command mode and read */
bank2_base[0x55] = 0x00980098;
IOSYNC;
ISYNC;
bank2_read = bank2_base[0x10];
/* Read from bank 1 (it's in read mode) */
bank1_read = bank1_base[0x10];
/* Reset Flash */
bank1_base[0] = 0x00F000F0;
bank2_base[0] = 0x00F000F0;
if (bank2_read == bank1_read) {
/*
* Looks like just one bank, but not sure yet. Let's
* read from bank 2 in autosoelect mode.
*/
bank2_base[0x0555] = 0x00AA00AA;
bank2_base[0x02AA] = 0x00550055;
bank2_base[0x0555] = 0x00900090;
IOSYNC;
ISYNC;
bank2_read = bank2_base[0x10];
/* Read from bank 1 (it's in read mode) */
bank1_read = bank1_base[0x10];
/* Reset Flash */
bank1_base[0] = 0x00F000F0;
bank2_base[0] = 0x00F000F0;
if (bank2_read == bank1_read) {
/*
* In both CFI command and autoselect modes,
* we got the some data reading from Flash.
* There is only one mirrored bank.
*/
cfi_flash_num_flash_banks = 1;
total_size = bank1_size;
}
}
}
debug("Number of flash banks detected: %d\n", cfi_flash_num_flash_banks);
/* set OR0 and BR0 */
set_lbc_or(0, CONFIG_SYS_OR_TIMING_FLASH |
(-(total_size) & OR_GPCM_AM));
set_lbc_br(0, (CONFIG_SYS_FLASH_BASE & BR_BA) |
(BR_MS_GPCM | BR_PS_32 | BR_V));
return (0);
}
/*************************************************************************
* Detect the size of a ddr bank. Sets CS bounds and CS config accordingly.
*/
static long int get_ddr_bank_size(short cs, long *base)
{
/* This array lists all valid DDR SDRAM configurations, with
* Bank sizes in bytes. (Refer to Table 9-27 in the MPC8349E RM).
* The last entry has to to have size equal 0 and is igonred during
* autodection. Bank sizes must be in increasing order of size
*/
struct {
long row;
long col;
long size;
} conf[] = {
{CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_8, 32 << 20},
{CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_9, 64 << 20},
{CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_10, 128 << 20},
{CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_9, 128 << 20},
{CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_10, 256 << 20},
{CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_11, 512 << 20},
{CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_10, 512 << 20},
{CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_11, 1024 << 20},
{0, 0, 0}
};
int i;
int detected;
long size;
detected = -1;
for(i = 0; conf[i].size != 0; ++i) {
/* set sdram bank configuration */
set_cs_config(cs, CSCONFIG_EN | conf[i].col | conf[i].row);
debug("Getting RAM size...\n");
size = get_ram_size(base, DDR_MAX_SIZE_PER_CS);
if((size == conf[i].size) && (i == detected + 1))
detected = i;
debug("Trying %ld x %ld (%ld MiB) at addr %p, detected: %ld MiB\n",
conf[i].row,
conf[i].col,
conf[i].size >> 20,
base,
size >> 20);
}
if(detected == -1){
/* disable empty cs */
debug("\nNo valid configurations for CS%d, disabling...\n", cs);
set_cs_config(cs, 0);
return 0;
}
debug("\nDetected configuration %ld x %ld (%ld MiB) at addr %p\n",
conf[detected].row, conf[detected].col, conf[detected].size >> 20, base);
/* configure cs ro detected params */
set_cs_config(cs, CSCONFIG_EN | conf[detected].row |
conf[detected].col);
set_cs_bounds(cs, (long)base, conf[detected].size);
return(conf[detected].size);
}
/**************************************************************************
* Sets DDR bank CS bounds.
*/
static void set_cs_bounds(short cs, long base, long size)
{
debug("Setting bounds %08lx, %08lx for cs %d\n", base, size, cs);
if(size == 0){
im->ddr.csbnds[cs].csbnds = 0x00000000;
} else {
im->ddr.csbnds[cs].csbnds =
((base >> CSBNDS_SA_SHIFT) & CSBNDS_SA) |
(((base + size - 1) >> CSBNDS_EA_SHIFT) &
CSBNDS_EA);
}
SYNC;
}
/**************************************************************************
* Sets DDR banks CS configuration.
* config == 0x00000000 disables the CS.
*/
static void set_cs_config(short cs, long config)
{
debug("Setting config %08lx for cs %d\n", config, cs);
im->ddr.cs_config[cs] = config;
SYNC;
}
/**************************************************************************
* Sets DDR clocks, timings and configuration.
*/
static void set_ddr_config(void) {
/* clock control */
im->ddr.sdram_clk_cntl = DDR_SDRAM_CLK_CNTL_SS_EN |
DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05;
SYNC;
/* timing configuration */
im->ddr.timing_cfg_1 =
(4 << TIMING_CFG1_PRETOACT_SHIFT) |
(7 << TIMING_CFG1_ACTTOPRE_SHIFT) |
(4 << TIMING_CFG1_ACTTORW_SHIFT) |
(5 << TIMING_CFG1_REFREC_SHIFT) |
(3 << TIMING_CFG1_WRREC_SHIFT) |
(3 << TIMING_CFG1_ACTTOACT_SHIFT) |
(1 << TIMING_CFG1_WRTORD_SHIFT) |
(TIMING_CFG1_CASLAT & TIMING_CASLAT);
im->ddr.timing_cfg_2 =
TIMING_CFG2_CPO_DEF |
(2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT);
SYNC;
/* don't enable DDR controller yet */
im->ddr.sdram_cfg =
SDRAM_CFG_SREN |
SDRAM_CFG_SDRAM_TYPE_DDR1;
SYNC;
/* Set SDRAM mode */
im->ddr.sdram_mode =
((DDR_MODE_EXT_MODEREG | DDR_MODE_WEAK) <<
SDRAM_MODE_ESD_SHIFT) |
((DDR_MODE_MODEREG | DDR_MODE_BLEN_4) <<
SDRAM_MODE_SD_SHIFT) |
((DDR_MODE_CASLAT << SDRAM_MODE_SD_SHIFT) &
MODE_CASLAT);
SYNC;
/* Set fast SDRAM refresh rate */
im->ddr.sdram_interval =
(DDR_REFINT_166MHZ_7US << SDRAM_INTERVAL_REFINT_SHIFT) |
(DDR_BSTOPRE << SDRAM_INTERVAL_BSTOPRE_SHIFT);
SYNC;
/* Workaround for DDR6 Erratum
* see MPC8349E Device Errata Rev.8, 2/2006
* This workaround influences the MPC internal "input enables"
* dependent on CAS latency and MPC revision. According to errata
* sheet the internal reserved registers for this workaround are
* not available from revision 2.0 and up.
*/
/* Get REVID from register SPRIDR. Skip workaround if rev >= 2.0
* (0x200)
*/
if ((im->sysconf.spridr & SPRIDR_REVID) < 0x200) {
/* There is a internal reserved register at IMMRBAR+0x2F00
* which has to be written with a certain value defined by
* errata sheet.
*/
u32 *reserved_p = (u32 *)((u8 *)im + 0x2f00);
#if defined(DDR_CASLAT_20)
*reserved_p = 0x201c0000;
#else
*reserved_p = 0x202c0000;
#endif
}
}
#ifdef CONFIG_OF_BOARD_SETUP
void ft_board_setup(void *blob, bd_t *bd)
{
ft_cpu_setup(blob, bd);
#ifdef CONFIG_PCI
ft_pci_setup(blob, bd);
#endif /* CONFIG_PCI */
}
#endif /* CONFIG_OF_BOARD_SETUP */

View file

@ -0,0 +1,50 @@
#
# (C) Copyright 2001-2006
# 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 = $(obj)lib$(BOARD).o
COBJS-y += $(BOARD).o
COBJS-y += sdram.o
COBJS-y += law.o
COBJS-y += tlb.o
COBJS-$(CONFIG_NAND) += nand.o
COBJS := $(COBJS-y)
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS) $(SOBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,79 @@
/*
* Copyright 2008 Freescale Semiconductor, Inc.
*
* (C) Copyright 2000
* 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 <common.h>
#include <asm/fsl_law.h>
#include <asm/mmu.h>
/*
* LAW(Local Access Window) configuration:
*
* Standard mapping:
*
* 0x0000_0000 0x7fff_ffff DDR 2G
* 0x8000_0000 0x9fff_ffff PCI1 MEM 512M
* 0xc000_0000 0xdfff_ffff RapidIO or PCI express 512M
* 0xe000_0000 0xe000_ffff CCSR 1M
* 0xe200_0000 0xe2ff_ffff PCI1 IO 16M
* 0xe300_0000 0xe3ff_ffff CAN and NAND Flash 16M
* 0xef00_0000 0xefff_ffff PCI express IO 16M
* 0xfc00_0000 0xffff_ffff FLASH (boot bank) 128M
*
* Big FLASH mapping:
*
* 0x0000_0000 0x7fff_ffff DDR 2G
* 0x8000_0000 0x9fff_ffff PCI1 MEM 512M
* 0xa000_0000 0xa000_ffff CCSR 1M
* 0xa200_0000 0xa2ff_ffff PCI1 IO 16M
* 0xa300_0000 0xa3ff_ffff CAN and NAND Flash 16M
* 0xaf00_0000 0xafff_ffff PCI express IO 16M
* 0xb000_0000 0xbfff_ffff RapidIO or PCI express 256M
* 0xc000_0000 0xffff_ffff FLASH (boot bank) 1G
*
* Notes:
* CCSRBAR and L2-as-SRAM don't need a configured Local Access Window.
* If flash is 8M at default position (last 8M), no LAW needed.
*/
#ifdef CONFIG_TQM_BIGFLASH
#define LAW_3_SIZE LAW_SIZE_1G
#define LAW_5_SIZE LAW_SIZE_256M
#else
#define LAW_3_SIZE LAW_SIZE_128M
#define LAW_5_SIZE LAW_SIZE_512M
#endif
struct law_entry law_table[] = {
SET_LAW(CONFIG_SYS_DDR_SDRAM_BASE, LAW_SIZE_2G, LAW_TRGT_IF_DDR),
SET_LAW(CONFIG_SYS_LBC_FLASH_BASE, LAW_3_SIZE, LAW_TRGT_IF_LBC),
#ifndef CONFIG_PCIE1
SET_LAW(CONFIG_SYS_RIO_MEM_BASE, LAW_5_SIZE, LAW_TRGT_IF_RIO),
#endif /* CONFIG_PCIE1 */
#if defined(CONFIG_CAN_DRIVER) || defined(CONFIG_NAND)
SET_LAW(CONFIG_SYS_CAN_BASE, LAW_SIZE_16M, LAW_TRGT_IF_LBC),
#endif /* CONFIG_CAN_DRIVER || CONFIG_NAND */
};
int num_law_entries = ARRAY_SIZE (law_table);

View file

@ -0,0 +1,472 @@
/*
* (C) Copyright 2008 Wolfgang Grandegger <wg@denx.de>
*
* (C) Copyright 2006
* Thomas Waehner, TQ-System GmbH, thomas.waehner@tqs.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>
#include <asm/processor.h>
#include <asm/immap_85xx.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/fsl_upm.h>
#include <ioports.h>
#include <nand.h>
DECLARE_GLOBAL_DATA_PTR;
extern uint get_lbc_clock (void);
/* index of UPM RAM array run pattern for NAND command cycle */
#define CONFIG_SYS_NAN_UPM_WRITE_CMD_OFS 0x08
/* index of UPM RAM array run pattern for NAND address cycle */
#define CONFIG_SYS_NAND_UPM_WRITE_ADDR_OFS 0x10
/* Structure for table with supported UPM timings */
struct upm_freq {
ulong freq;
const u32 *upm_patt;
uchar gpl4_disable;
uchar ehtr;
uchar ead;
};
/* NAND-FLASH UPM tables for TQM85XX according to TQM8548.pq.timing.101.doc */
/* UPM pattern for bus clock = 25 MHz */
static const u32 upm_patt_25[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff32000, 0x0fa32000, 0x3fb32005, 0xfffffc00,
/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff2c30, 0x00ff2c30, 0x0fff2c35, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3ec30, 0x00f3ec30, 0x0ff3ec35, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f32c00, 0x00f32c00, 0x0ff32c05, 0xfffffc00,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 33.3 MHz */
static const u32 upm_patt_33[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff32000, 0x0fa32100, 0x3fb32005, 0xfffffc00,
/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff2c30, 0x00ff2c30, 0x0fff2c35, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3ec30, 0x00f3ec30, 0x0ff3ec35, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f32c00, 0x00f32c00, 0x0ff32c05, 0xfffffc00,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 41.7 MHz */
static const u32 upm_patt_42[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff32000, 0x0fa32100, 0x3fb32005, 0xfffffc00,
/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff2c30, 0x00ff2c30, 0x0fff2c35, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3ec30, 0x00f3ec30, 0x0ff3ec35, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f32c00, 0x00f32c00, 0x0ff32c05, 0xfffffc00,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 50 MHz */
static const u32 upm_patt_50[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff33000, 0x0fa33100, 0x0fa33005, 0xfffffc00,
/* 0x04 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff3d30, 0x00ff3c30, 0x0fff3c35, 0xfffffc00,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3fd30, 0x00f3fc30, 0x0ff3fc35, 0xfffffc00,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f33d00, 0x00f33c00, 0x0ff33c05, 0xfffffc00,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 66.7 MHz */
static const u32 upm_patt_67[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff33000, 0x0fe33000, 0x0fa33100, 0x0fa33000,
/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff3d30, 0x00ff3c30, 0x0fff3c30, 0x0fff3c35,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3fd30, 0x00f3fc30, 0x0ff3fc30, 0x0ff3fc35,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f33d00, 0x00f33c00, 0x0ff33c00, 0x0ff33c05,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 83.3 MHz */
static const u32 upm_patt_83[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff33000, 0x0fe33000, 0x0fa33100, 0x0fa33000,
/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff3e30, 0x00ff3c30, 0x0fff3c30, 0x0fff3c35,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3fe30, 0x00f3fc30, 0x0ff3fc30, 0x0ff3fc35,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f33e00, 0x00f33c00, 0x0ff33c00, 0x0ff33c05,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 100 MHz */
static const u32 upm_patt_100[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff33100, 0x0fe33000, 0x0fa33200, 0x0fa33000,
/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff3f30, 0x00ff3c30, 0x0fff3c30, 0x0fff3c35,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3ff30, 0x00f3fc30, 0x0ff3fc30, 0x0ff3fc35,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f33f00, 0x00f33c00, 0x0ff33c00, 0x0ff33c05,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 133.3 MHz */
static const u32 upm_patt_133[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff33100, 0x0fe33000, 0x0fa33300, 0x0fa33000,
/* 0x04 */ 0x0fa33000, 0x0fa33005, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff3f30, 0x00ff3d30, 0x0fff3d30, 0x0fff3c35,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3ff30, 0x00f3fd30, 0x0ff3fd30, 0x0ff3fc35,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f33f00, 0x00f33d00, 0x0ff33d00, 0x0ff33c05,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* UPM pattern for bus clock = 166.7 MHz */
static const u32 upm_patt_167[] = {
/* Offset */ /* UPM Read Single RAM array entry -> NAND Read Data */
/* 0x00 */ 0x0ff33200, 0x0fe33000, 0x0fa33300, 0x0fa33300,
/* 0x04 */ 0x0fa33005, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write CMD */
/* 0x08 */ 0x00ff3f30, 0x00ff3f30, 0x0fff3e30, 0xffff3c35,
/* 0x0C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Read Burst RAM array entry -> NAND Write ADDR */
/* 0x10 */ 0x00f3ff30, 0x00f3ff30, 0x0ff3fe30, 0x0ff3fc35,
/* 0x14 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Single RAM array entry -> NAND Write Data */
/* 0x18 */ 0x00f33f00, 0x00f33f00, 0x0ff33e00, 0x0ff33c05,
/* 0x1C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* UPM Write Burst RAM array entry -> unused */
/* 0x20 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x24 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x28 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x2C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Refresh Timer RAM array entry -> unused */
/* 0x30 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x34 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
/* 0x38 */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
/* UPM Exception RAM array entry -> unsused */
/* 0x3C */ 0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
};
/* Supported UPM timings */
struct upm_freq upm_freq_table[] = {
/* nominal freq. | ptr to table | GPL4 dis. | EHTR | EAD */
{25000000, upm_patt_25, 1, 0, 0},
{33333333, upm_patt_33, 1, 0, 0},
{41666666, upm_patt_42, 1, 0, 0},
{50000000, upm_patt_50, 0, 0, 0},
{66666666, upm_patt_67, 0, 0, 0},
{83333333, upm_patt_83, 0, 0, 0},
{100000000, upm_patt_100, 0, 1, 1},
{133333333, upm_patt_133, 0, 1, 1},
{166666666, upm_patt_167, 0, 1, 1},
};
#define UPM_FREQS (sizeof(upm_freq_table) / sizeof(struct upm_freq))
volatile const u32 *nand_upm_patt;
/*
* write into UPMB ram
*/
static void upmb_write (u_char addr, ulong val)
{
volatile fsl_lbc_t *lbc = LBC_BASE_ADDR;
out_be32 (&lbc->mdr, val);
clrsetbits_be32(&lbc->mbmr, MxMR_MAD_MSK,
MxMR_OP_WARR | (addr & MxMR_MAD_MSK));
/* dummy access to perform write */
out_8 ((void __iomem *)CONFIG_SYS_NAND_BASE, 0);
clrbits_be32(&lbc->mbmr, MxMR_OP_WARR);
}
/*
* Initialize UPM for NAND flash access.
*/
static void nand_upm_setup (volatile fsl_lbc_t *lbc)
{
uint i, j;
uint or3 = CONFIG_SYS_OR3_PRELIM;
uint clock = get_lbc_clock ();
set_lbc_br(3, 0); /* disable bank and reset all bits */
set_lbc_br(3, CONFIG_SYS_BR3_PRELIM);
/*
* Search appropriate UPM table for bus clock.
* If the bus clock exceeds a tolerated value, take the UPM timing for
* the next higher supported frequency to ensure that access works
* (even the access may be slower then).
*/
for (i = 0; (i < UPM_FREQS) && (clock > upm_freq_table[i].freq); i++)
;
if (i >= UPM_FREQS)
/* no valid entry found */
/* take last entry with configuration for max. bus clock */
i--;
if (upm_freq_table[i].ehtr) {
/* EHTR must be set due to TQM8548 timing specification */
or3 |= OR_UPM_EHTR;
}
if (upm_freq_table[i].ead)
/* EAD must be set due to TQM8548 timing specification */
or3 |= OR_UPM_EAD;
set_lbc_or(3, or3);
/* Assign address of table */
nand_upm_patt = upm_freq_table[i].upm_patt;
for (j = 0; j < 64; j++) {
upmb_write (j, *nand_upm_patt);
nand_upm_patt++;
}
/* Put UPM back to normal operation mode */
if (upm_freq_table[i].gpl4_disable)
/* GPL4 must be disabled according to timing specification */
out_be32 (&lbc->mbmr, MxMR_OP_NORM | MxMR_GPL_x4DIS);
return;
}
static struct fsl_upm_nand fun = {
.width = 8,
.upm_cmd_offset = 0x08,
.upm_addr_offset = 0x10,
.upm_mar_chip_offset = CONFIG_SYS_NAND_CS_DIST,
.chip_offset = CONFIG_SYS_NAND_CS_DIST,
.chip_delay = NAND_BIG_DELAY_US,
.wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BUFFER,
};
void board_nand_select_device (struct nand_chip *nand, int chip)
{
}
int board_nand_init (struct nand_chip *nand)
{
volatile fsl_lbc_t *lbc = LBC_BASE_ADDR;
if (!nand_upm_patt)
nand_upm_setup (lbc);
fun.upm.io_addr = nand->IO_ADDR_R;
fun.upm.mxmr = (void __iomem *)&lbc->mbmr;
fun.upm.mdr = (void __iomem *)&lbc->mdr;
fun.upm.mar = (void __iomem *)&lbc->mar;
return fsl_upm_nand_init (nand, &fun);
}

View file

@ -0,0 +1,436 @@
/*
* (C) Copyright 2005
* Stefan Roese, DENX Software Engineering, sr@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 <common.h>
#include <asm/processor.h>
#include <asm/immap_85xx.h>
#include <asm/processor.h>
#include <asm/mmu.h>
struct sdram_conf_s {
unsigned long size;
unsigned long reg;
#ifdef CONFIG_TQM8548
unsigned long refresh;
#endif /* CONFIG_TQM8548 */
};
typedef struct sdram_conf_s sdram_conf_t;
#ifdef CONFIG_TQM8548
#ifdef CONFIG_TQM8548_AG
sdram_conf_t ddr_cs_conf[] = {
{(1024 << 20), 0x80044202, 0x0002D000}, /* 1024MB, 14x10(4) */
{ (512 << 20), 0x80044102, 0x0001A000}, /* 512MB, 13x10(4) */
{ (256 << 20), 0x80040102, 0x00014000}, /* 256MB, 13x10(4) */
{ (128 << 20), 0x80040101, 0x0000C000}, /* 128MB, 13x9(4) */
};
#else /* !CONFIG_TQM8548_AG */
sdram_conf_t ddr_cs_conf[] = {
{(512 << 20), 0x80044102, 0x0001A000}, /* 512MB, 13x10(4) */
{(256 << 20), 0x80040102, 0x00014000}, /* 256MB, 13x10(4) */
{(128 << 20), 0x80040101, 0x0000C000}, /* 128MB, 13x9(4) */
};
#endif /* CONFIG_TQM8548_AG */
#else /* !CONFIG_TQM8548 */
sdram_conf_t ddr_cs_conf[] = {
{(512 << 20), 0x80000202}, /* 512MB, 14x10(4) */
{(256 << 20), 0x80000102}, /* 256MB, 13x10(4) */
{(128 << 20), 0x80000101}, /* 128MB, 13x9(4) */
{( 64 << 20), 0x80000001}, /* 64MB, 12x9(4) */
};
#endif /* CONFIG_TQM8548 */
#define N_DDR_CS_CONF (sizeof(ddr_cs_conf) / sizeof(ddr_cs_conf[0]))
int cas_latency (void);
static phys_size_t sdram_setup(int);
/*
* Autodetect onboard DDR SDRAM on 85xx platforms
*
* NOTE: Some of the hardcoded values are hardware dependant,
* so this should be extended for other future boards
* using this routine!
*/
phys_size_t fixed_sdram(void)
{
int casl = 0;
phys_size_t dram_size = 0;
casl = cas_latency();
dram_size = sdram_setup(casl);
if ((dram_size == 0) && (casl != CONFIG_DDR_DEFAULT_CL)) {
/*
* Try again with default CAS latency
*/
printf("Problem with CAS lantency, using default CL %d/10!\n",
CONFIG_DDR_DEFAULT_CL);
dram_size = sdram_setup(CONFIG_DDR_DEFAULT_CL);
puts(" ");
}
return dram_size;
}
static phys_size_t sdram_setup(int casl)
{
int i;
volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
#ifdef CONFIG_TQM8548
volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
#if defined(CONFIG_TQM8548_AG) || defined(CONFIG_TQM8548_BE)
volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
#endif
#else /* !CONFIG_TQM8548 */
unsigned long cfg_ddr_timing1;
unsigned long cfg_ddr_mode;
#endif /* CONFIG_TQM8548 */
/*
* Disable memory controller.
*/
ddr->cs0_config = 0;
ddr->sdram_cfg = 0;
#ifdef CONFIG_TQM8548
/* Timing and refresh settings for DDR2-533 and below */
ddr->cs0_bnds = (ddr_cs_conf[0].size - 1) >> 24;
ddr->cs0_config = ddr_cs_conf[0].reg;
ddr->timing_cfg_3 = 0x00020000;
/* TIMING CFG 1, 533MHz
* PRETOACT: 4 Clocks
* ACTTOPRE: 12 Clocks
* ACTTORW: 4 Clocks
* CASLAT: 4 Clocks
* REFREC: EXT_REFREC:REFREC 53 Clocks
* WRREC: 4 Clocks
* ACTTOACT: 3 Clocks
* WRTORD: 2 Clocks
*/
ddr->timing_cfg_1 = 0x4C47D432;
/* TIMING CFG 2, 533MHz
* ADD_LAT: 3 Clocks
* CPO: READLAT + 1
* WR_LAT: 3 Clocks
* RD_TO_PRE: 2 Clocks
* WR_DATA_DELAY: 1/2 Clock
* CKE_PLS: 3 Clock
* FOUR_ACT: 14 Clocks
*/
ddr->timing_cfg_2 = 0x331848CE;
/* DDR SDRAM Mode, 533MHz
* MRS: Extended Mode Register
* OUT: Outputs enabled
* RDQS: no
* DQS: enabled
* OCD: default state
* RTT: 75 Ohms
* Posted CAS: 3 Clocks
* ODS: reduced strength
* DLL: enabled
* MR: Mode Register
* PD: fast exit
* WR: 4 Clocks
* DLL: no DLL reset
* TM: normal
* CAS latency: 4 Clocks
* BT: sequential
* Burst length: 4
*/
ddr->sdram_mode = 0x439E0642;
/* DDR SDRAM Interval, 533MHz
* REFINT: 1040 Clocks
* BSTOPRE: 256
*/
ddr->sdram_interval = (1040 << 16) | 0x100;
/*
* Workaround for erratum DDR19 according to MPC8548 Device Errata
* document, Rev. 1: DDR IO receiver must be set to an acceptable
* bias point by modifying a hidden register.
*/
if (SVR_REV (get_svr ()) < 0x21)
gur->ddrioovcr = 0x90000000; /* enable, VSEL 1.8V */
/* DDR SDRAM CFG 2
* FRC_SR: normal mode
* SR_IE: no self-refresh interrupt
* DLL_RST_DIS: don't care, leave at reset value
* DQS_CFG: differential DQS signals
* ODT_CFG: assert ODT to internal IOs only during reads to DRAM
* LVWx_CFG: don't care, leave at reset value
* NUM_PR: 1 refresh will be issued at a time
* DM_CFG: don't care, leave at reset value
* D_INIT: no data initialization
*/
ddr->sdram_cfg_2 = 0x04401000;
/* DDR SDRAM MODE 2
* MRS: Extended Mode Register 2
*/
ddr->sdram_mode_2 = 0x8000C000;
/* DDR SDRAM CLK CNTL
* CLK_ADJUST: 1/2 Clock 0x02000000
* CLK_ADJUST: 5/8 Clock 0x02800000
*/
ddr->sdram_clk_cntl = 0x02800000;
/* wait for clock stabilization */
asm ("sync;isync;msync");
udelay (1000);
#if defined(CONFIG_TQM8548_AG) || defined(CONFIG_TQM8548_BE)
/*
* Workaround for erratum DDR20 according to MPC8548 Device Errata
* document, Rev. 1: "CKE signal may not function correctly after
* assertion of HRESET"
*/
/* 1. Configure DDR register as is done in normal DDR configuration.
* Do not set DDR_SDRAM_CFG[MEM_EN].
*
* 2. Set reserved bit EEBACR[3] at offset 0x1000
*/
ecm->eebacr |= 0x10000000;
/*
* 3. Before DDR_SDRAM_CFG[MEM_EN] is set, write DDR_SDRAM_CFG_2[D_INIT]
*
* DDR_SDRAM_CFG_2:
* FRC_SR: normal mode
* SR_IE: no self-refresh interrupt
* DLL_RST_DIS: don't care, leave at reset value
* DQS_CFG: differential DQS signals
* ODT_CFG: assert ODT to internal IOs only during reads to DRAM
* LVWx_CFG: don't care, leave at reset value
* NUM_PR: 1 refresh will be issued at a time
* DM_CFG: don't care, leave at reset value
* D_INIT: enable data initialization
*/
ddr->sdram_cfg_2 |= 0x00000010;
/*
* 4. Before DDR_SDRAM_CFG[MEM_EN] set, write D3[21] to disable data
* training
*/
ddr->debug[2] |= 0x00000400;
/*
* 5. Wait 200 micro-seconds
*/
udelay (200);
/*
* 6. Set DDR_SDRAM_CFG[MEM_EN]
*
* BTW, initialize DDR_SDRAM_CFG:
* MEM_EN: enabled
* SREN: don't care, leave at reset value
* ECC_EN: no error report
* RD_EN: no registered DIMMs
* SDRAM_TYPE: DDR2
* DYN_PWR: no power management
* 32_BE: don't care, leave at reset value
* 8_BE: 4 beat burst
* NCAP: don't care, leave at reset value
* 2T_EN: 1T Timing
* BA_INTLV_CTL: no interleaving
* x32_EN: x16 organization
* PCHB8: MA[10] for auto-precharge
* HSE: half strength for single and 2-layer stacks
* (full strength for 3- and 4-layer stacks not
* yet considered)
* MEM_HALT: no halt
* BI: automatic initialization
*/
ddr->sdram_cfg = 0x83000008;
/*
* 7. Poll DDR_SDRAM_CFG_2[D_INIT] until it is cleared by hardware
*/
asm ("sync;isync;msync");
while (ddr->sdram_cfg_2 & 0x00000010)
asm ("eieio");
/*
* 8. Clear D3[21] to re-enable data training
*/
ddr->debug[2] &= ~0x00000400;
/*
* 9. Set D2(21) to force data training to run
*/
ddr->debug[1] |= 0x00000400;
/*
* 10. Poll on D2[21] until it is cleared by hardware
*/
asm ("sync;isync;msync");
while (ddr->debug[1] & 0x00000400)
asm ("eieio");
/*
* 11. Clear reserved bit EEBACR[3] at offset 0x1000
*/
ecm->eebacr &= ~0x10000000;
#else /* !(CONFIG_TQM8548_AG || CONFIG_TQM8548_BE) */
/* DDR SDRAM CLK CNTL
* MEM_EN: enabled
* SREN: don't care, leave at reset value
* ECC_EN: no error report
* RD_EN: no register DIMMs
* SDRAM_TYPE: DDR2
* DYN_PWR: no power management
* 32_BE: don't care, leave at reset value
* 8_BE: 4 beat burst
* NCAP: don't care, leave at reset value
* 2T_EN: 1T Timing
* BA_INTLV_CTL: no interleaving
* x32_EN: x16 organization
* PCHB8: MA[10] for auto-precharge
* HSE: half strength for single and 2-layer stacks
* (full strength for 3- and 4-layer stacks no yet considered)
* MEM_HALT: no halt
* BI: automatic initialization
*/
ddr->sdram_cfg = 0x83000008;
#endif /* CONFIG_TQM8548_AG || CONFIG_TQM8548_BE */
asm ("sync; isync; msync");
udelay (1000);
#else /* !CONFIG_TQM8548 */
switch (casl) {
case 20:
cfg_ddr_timing1 = 0x47405331 | (3 << 16);
cfg_ddr_mode = 0x40020002 | (2 << 4);
break;
case 25:
cfg_ddr_timing1 = 0x47405331 | (4 << 16);
cfg_ddr_mode = 0x40020002 | (6 << 4);
break;
case 30:
default:
cfg_ddr_timing1 = 0x47405331 | (5 << 16);
cfg_ddr_mode = 0x40020002 | (3 << 4);
break;
}
ddr->cs0_bnds = (ddr_cs_conf[0].size - 1) >> 24;
ddr->cs0_config = ddr_cs_conf[0].reg;
ddr->timing_cfg_1 = cfg_ddr_timing1;
ddr->timing_cfg_2 = 0x00000800; /* P9-45,may need tuning */
ddr->sdram_mode = cfg_ddr_mode;
ddr->sdram_interval = 0x05160100; /* autocharge,no open page */
ddr->err_disable = 0x0000000D;
asm ("sync; isync; msync");
udelay (1000);
ddr->sdram_cfg = 0xc2000000; /* unbuffered,no DYN_PWR */
asm ("sync; isync; msync");
udelay (1000);
#endif /* CONFIG_TQM8548 */
/*
* get_ram_size() depends on having tlbs for the DDR, but they are
* not yet setup because we don't know the size. Set up a temp
* mapping and delete it when done.
*/
setup_ddr_tlbs(CONFIG_SYS_DDR_EARLY_SIZE_MB);
for (i = 0; i < N_DDR_CS_CONF; i++) {
ddr->cs0_config = ddr_cs_conf[i].reg;
if (get_ram_size (0, ddr_cs_conf[i].size) ==
ddr_cs_conf[i].size) {
/*
* size detected -> set Chip Select Bounds Register
*/
ddr->cs0_bnds = (ddr_cs_conf[i].size - 1) >> 24;
break;
}
}
clear_ddr_tlbs(CONFIG_SYS_DDR_EARLY_SIZE_MB);
#ifdef CONFIG_TQM8548
if (i < N_DDR_CS_CONF) {
/* Adjust refresh rate for DDR2 */
ddr->timing_cfg_3 = ddr_cs_conf[i].refresh & 0x00070000;
ddr->timing_cfg_1 = (ddr->timing_cfg_1 & 0xFFFF0FFF) |
(ddr_cs_conf[i].refresh & 0x0000F000);
return ddr_cs_conf[i].size;
}
#endif /* CONFIG_TQM8548 */
/* return size if detected, else return 0 */
return (i < N_DDR_CS_CONF) ? ddr_cs_conf[i].size : 0;
}
#if defined(CONFIG_SYS_DRAM_TEST)
int testdram (void)
{
uint *pstart = (uint *) CONFIG_SYS_MEMTEST_START;
uint *pend = (uint *) CONFIG_SYS_MEMTEST_END;
uint *p;
printf ("SDRAM test phase 1:\n");
for (p = pstart; p < pend; p++)
*p = 0xaaaaaaaa;
for (p = pstart; p < pend; p++) {
if (*p != 0xaaaaaaaa) {
printf ("SDRAM test fails at: %08x\n", (uint) p);
return 1;
}
}
printf ("SDRAM test phase 2:\n");
for (p = pstart; p < pend; p++)
*p = 0x55555555;
for (p = pstart; p < pend; p++) {
if (*p != 0x55555555) {
printf ("SDRAM test fails at: %08x\n", (uint) p);
return 1;
}
}
printf ("SDRAM test passed.\n");
return 0;
}
#endif

View file

@ -0,0 +1,214 @@
/*
* Copyright 2008 Freescale Semiconductor, Inc.
*
* (C) Copyright 2000
* 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 <common.h>
#include <asm/mmu.h>
struct fsl_e_tlb_entry tlb_table[] = {
/* TLB 0 - for temp stack in cache */
SET_TLB_ENTRY (0, CONFIG_SYS_INIT_RAM_ADDR, CONFIG_SYS_INIT_RAM_ADDR,
MAS3_SX | MAS3_SW | MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
SET_TLB_ENTRY (0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
MAS3_SX | MAS3_SW | MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
SET_TLB_ENTRY (0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
MAS3_SX | MAS3_SW | MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
SET_TLB_ENTRY (0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
MAS3_SX | MAS3_SW | MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
#ifndef CONFIG_TQM_BIGFLASH
/*
* TLB 0, 1: 128M Non-cacheable, guarded
* 0xf8000000 128M FLASH
* Out of reset this entry is only 4K.
*/
SET_TLB_ENTRY (1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 1, BOOKE_PAGESZ_64M, 1),
SET_TLB_ENTRY (1, CONFIG_SYS_FLASH_BASE + 0x4000000,
CONFIG_SYS_FLASH_BASE + 0x4000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 0, BOOKE_PAGESZ_64M, 1),
/*
* TLB 2: 256M Non-cacheable, guarded
* 0x80000000 256M PCI1 MEM First half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCI1_MEM_PHYS, CONFIG_SYS_PCI1_MEM_PHYS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 2, BOOKE_PAGESZ_256M, 1),
/*
* TLB 3: 256M Non-cacheable, guarded
* 0x90000000 256M PCI1 MEM Second half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCI1_MEM_PHYS + 0x10000000,
CONFIG_SYS_PCI1_MEM_PHYS + 0x10000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 3, BOOKE_PAGESZ_256M, 1),
#ifdef CONFIG_PCIE1
/*
* TLB 4: 256M Non-cacheable, guarded
* 0xc0000000 256M PCI express MEM First half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCIE1_MEM_BUS, CONFIG_SYS_PCIE1_MEM_BUS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 4, BOOKE_PAGESZ_256M, 1),
/*
* TLB 5: 256M Non-cacheable, guarded
* 0xd0000000 256M PCI express MEM Second half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCIE1_MEM_BUS + 0x10000000,
CONFIG_SYS_PCIE1_MEM_BUS + 0x10000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 5, BOOKE_PAGESZ_256M, 1),
#else /* !CONFIG_PCIE */
/*
* TLB 4: 256M Non-cacheable, guarded
* 0xc0000000 256M Rapid IO MEM First half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_RIO_MEM_BASE, CONFIG_SYS_RIO_MEM_BASE,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 4, BOOKE_PAGESZ_256M, 1),
/*
* TLB 5: 256M Non-cacheable, guarded
* 0xd0000000 256M Rapid IO MEM Second half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_RIO_MEM_BASE + 0x10000000,
CONFIG_SYS_RIO_MEM_BASE + 0x10000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 5, BOOKE_PAGESZ_256M, 1),
#endif /* CONFIG_PCIE */
/*
* TLB 6: 64M Non-cacheable, guarded
* 0xe0000000 1M CCSRBAR
* 0xe2000000 16M PCI1 IO
* 0xe3000000 16M CAN and NAND Flash
*/
SET_TLB_ENTRY (1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 6, BOOKE_PAGESZ_64M, 1),
#ifdef CONFIG_PCIE1
/*
* TLB 9: 16M Non-cacheable, guarded
* 0xef000000 16M PCI express IO
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCIE1_IO_BUS, CONFIG_SYS_PCIE1_IO_BUS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 9, BOOKE_PAGESZ_16M, 1),
#endif /* CONFIG_PCIE */
#else /* CONFIG_TQM_BIGFLASH */
/*
* TLB 0,1,2,3: 1G Non-cacheable, guarded
* 0xc0000000 1G FLASH
* Out of reset this entry is only 4K.
*/
SET_TLB_ENTRY (1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 3, BOOKE_PAGESZ_256M, 1),
SET_TLB_ENTRY (1, CONFIG_SYS_FLASH_BASE + 0x10000000,
CONFIG_SYS_FLASH_BASE + 0x10000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 2, BOOKE_PAGESZ_256M, 1),
SET_TLB_ENTRY (1, CONFIG_SYS_FLASH_BASE + 0x20000000,
CONFIG_SYS_FLASH_BASE + 0x20000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 1, BOOKE_PAGESZ_256M, 1),
SET_TLB_ENTRY (1, CONFIG_SYS_FLASH_BASE + 0x30000000,
CONFIG_SYS_FLASH_BASE + 0x30000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 0, BOOKE_PAGESZ_256M, 1),
/*
* TLB 4: 256M Non-cacheable, guarded
* 0x80000000 256M PCI1 MEM First half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCI1_MEM_PHYS, CONFIG_SYS_PCI1_MEM_PHYS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 4, BOOKE_PAGESZ_256M, 1),
/*
* TLB 5: 256M Non-cacheable, guarded
* 0x90000000 256M PCI1 MEM Second half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCI1_MEM_PHYS + 0x10000000,
CONFIG_SYS_PCI1_MEM_PHYS + 0x10000000,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 5, BOOKE_PAGESZ_256M, 1),
#ifdef CONFIG_PCIE1
/*
* TLB 6: 256M Non-cacheable, guarded
* 0xc0000000 256M PCI express MEM First half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCIE1_MEM_BUS, CONFIG_SYS_PCIE1_MEM_BUS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 6, BOOKE_PAGESZ_256M, 1),
#else /* !CONFIG_PCIE */
/*
* TLB 6: 256M Non-cacheable, guarded
* 0xb0000000 256M Rapid IO MEM First half
*/
SET_TLB_ENTRY (1, CONFIG_SYS_RIO_MEM_BASE, CONFIG_SYS_RIO_MEM_BASE,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 6, BOOKE_PAGESZ_256M, 1),
#endif /* CONFIG_PCIE */
/*
* TLB 7: 64M Non-cacheable, guarded
* 0xa0000000 1M CCSRBAR
* 0xa2000000 16M PCI1 IO
* 0xa3000000 16M CAN and NAND Flash
*/
SET_TLB_ENTRY (1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 7, BOOKE_PAGESZ_64M, 1),
#ifdef CONFIG_PCIE1
/*
* TLB 10: 16M Non-cacheable, guarded
* 0xaf000000 16M PCI express IO
*/
SET_TLB_ENTRY (1, CONFIG_SYS_PCIE1_IO_BASE, CONFIG_SYS_PCIE1_IO_BASE,
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G,
0, 10, BOOKE_PAGESZ_16M, 1),
#endif /* CONFIG_PCIE */
#endif /* CONFIG_TQM_BIGFLASH */
};
int num_tlb_entries = ARRAY_SIZE (tlb_table);

View file

@ -0,0 +1,626 @@
/*
* (C) Copyright 2008 Wolfgang Grandegger <wg@denx.de>
*
* (C) Copyright 2006
* Thomas Waehner, TQ-Systems GmbH, thomas.waehner@tqs.de.
*
* (C) Copyright 2005
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* Copyright 2004 Freescale Semiconductor.
* (C) Copyright 2002,2003, Motorola Inc.
* Xianghua Xiao, (X.Xiao@motorola.com)
*
* (C) Copyright 2002 Scott McNutt <smcnutt@artesyncp.com>
*
* 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>
#include <pci.h>
#include <asm/processor.h>
#include <asm/immap_85xx.h>
#include <asm/fsl_pci.h>
#include <asm/io.h>
#include <asm/fsl_serdes.h>
#include <linux/compiler.h>
#include <ioports.h>
#include <flash.h>
#include <libfdt.h>
#include <fdt_support.h>
#include <netdev.h>
DECLARE_GLOBAL_DATA_PTR;
extern flash_info_t flash_info[]; /* FLASH chips info */
void local_bus_init (void);
ulong flash_get_size (ulong base, int banknum);
#ifdef CONFIG_PS2MULT
void ps2mult_early_init (void);
#endif
#ifdef CONFIG_CPM2
/*
* I/O Port configuration table
*
* if conf is 1, then that port pin will be configured at boot time
* according to the five values podr/pdir/ppar/psor/pdat for that entry
*/
const iop_conf_t iop_conf_tab[4][32] = {
/* Port A: conf, ppar, psor, pdir, podr, pdat */
{
{1, 1, 1, 0, 0, 0}, /* PA31: FCC1 MII COL */
{1, 1, 1, 0, 0, 0}, /* PA30: FCC1 MII CRS */
{1, 1, 1, 1, 0, 0}, /* PA29: FCC1 MII TX_ER */
{1, 1, 1, 1, 0, 0}, /* PA28: FCC1 MII TX_EN */
{1, 1, 1, 0, 0, 0}, /* PA27: FCC1 MII RX_DV */
{1, 1, 1, 0, 0, 0}, /* PA26: FCC1 MII RX_ER */
{0, 1, 0, 1, 0, 0}, /* PA25: FCC1 ATMTXD[0] */
{0, 1, 0, 1, 0, 0}, /* PA24: FCC1 ATMTXD[1] */
{0, 1, 0, 1, 0, 0}, /* PA23: FCC1 ATMTXD[2] */
{0, 1, 0, 1, 0, 0}, /* PA22: FCC1 ATMTXD[3] */
{1, 1, 0, 1, 0, 0}, /* PA21: FCC1 MII TxD[3] */
{1, 1, 0, 1, 0, 0}, /* PA20: FCC1 MII TxD[2] */
{1, 1, 0, 1, 0, 0}, /* PA19: FCC1 MII TxD[1] */
{1, 1, 0, 1, 0, 0}, /* PA18: FCC1 MII TxD[0] */
{1, 1, 0, 0, 0, 0}, /* PA17: FCC1 MII RxD[0] */
{1, 1, 0, 0, 0, 0}, /* PA16: FCC1 MII RxD[1] */
{1, 1, 0, 0, 0, 0}, /* PA15: FCC1 MII RxD[2] */
{1, 1, 0, 0, 0, 0}, /* PA14: FCC1 MII RxD[3] */
{0, 1, 0, 0, 0, 0}, /* PA13: FCC1 ATMRXD[3] */
{0, 1, 0, 0, 0, 0}, /* PA12: FCC1 ATMRXD[2] */
{0, 1, 0, 0, 0, 0}, /* PA11: FCC1 ATMRXD[1] */
{0, 1, 0, 0, 0, 0}, /* PA10: FCC1 ATMRXD[0] */
{0, 1, 1, 1, 0, 0}, /* PA9 : FCC1 L1TXD */
{0, 1, 1, 0, 0, 0}, /* PA8 : FCC1 L1RXD */
{0, 0, 0, 1, 0, 0}, /* PA7 : PA7 */
{0, 1, 1, 1, 0, 0}, /* PA6 : TDM A1 L1RSYNC */
{0, 0, 0, 1, 0, 0}, /* PA5 : PA5 */
{0, 0, 0, 1, 0, 0}, /* PA4 : PA4 */
{0, 0, 0, 1, 0, 0}, /* PA3 : PA3 */
{0, 0, 0, 1, 0, 0}, /* PA2 : PA2 */
{0, 0, 0, 0, 0, 0}, /* PA1 : FREERUN */
{0, 0, 0, 1, 0, 0} /* PA0 : PA0 */
},
/* Port B: conf, ppar, psor, pdir, podr, pdat */
{
{1, 1, 0, 1, 0, 0}, /* PB31: FCC2 MII TX_ER */
{1, 1, 0, 0, 0, 0}, /* PB30: FCC2 MII RX_DV */
{1, 1, 1, 1, 0, 0}, /* PB29: FCC2 MII TX_EN */
{1, 1, 0, 0, 0, 0}, /* PB28: FCC2 MII RX_ER */
{1, 1, 0, 0, 0, 0}, /* PB27: FCC2 MII COL */
{1, 1, 0, 0, 0, 0}, /* PB26: FCC2 MII CRS */
{1, 1, 0, 1, 0, 0}, /* PB25: FCC2 MII TxD[3] */
{1, 1, 0, 1, 0, 0}, /* PB24: FCC2 MII TxD[2] */
{1, 1, 0, 1, 0, 0}, /* PB23: FCC2 MII TxD[1] */
{1, 1, 0, 1, 0, 0}, /* PB22: FCC2 MII TxD[0] */
{1, 1, 0, 0, 0, 0}, /* PB21: FCC2 MII RxD[0] */
{1, 1, 0, 0, 0, 0}, /* PB20: FCC2 MII RxD[1] */
{1, 1, 0, 0, 0, 0}, /* PB19: FCC2 MII RxD[2] */
{1, 1, 0, 0, 0, 0}, /* PB18: FCC2 MII RxD[3] */
{1, 1, 0, 0, 0, 0}, /* PB17: FCC3:RX_DIV */
{1, 1, 0, 0, 0, 0}, /* PB16: FCC3:RX_ERR */
{1, 1, 0, 1, 0, 0}, /* PB15: FCC3:TX_ERR */
{1, 1, 0, 1, 0, 0}, /* PB14: FCC3:TX_EN */
{1, 1, 0, 0, 0, 0}, /* PB13: FCC3:COL */
{1, 1, 0, 0, 0, 0}, /* PB12: FCC3:CRS */
{1, 1, 0, 0, 0, 0}, /* PB11: FCC3:RXD */
{1, 1, 0, 0, 0, 0}, /* PB10: FCC3:RXD */
{1, 1, 0, 0, 0, 0}, /* PB9 : FCC3:RXD */
{1, 1, 0, 0, 0, 0}, /* PB8 : FCC3:RXD */
{1, 1, 0, 1, 0, 0}, /* PB7 : FCC3:TXD */
{1, 1, 0, 1, 0, 0}, /* PB6 : FCC3:TXD */
{1, 1, 0, 1, 0, 0}, /* PB5 : FCC3:TXD */
{1, 1, 0, 1, 0, 0}, /* PB4 : FCC3:TXD */
{0, 0, 0, 0, 0, 0}, /* PB3 : pin doesn't exist */
{0, 0, 0, 0, 0, 0}, /* PB2 : pin doesn't exist */
{0, 0, 0, 0, 0, 0}, /* PB1 : pin doesn't exist */
{0, 0, 0, 0, 0, 0} /* PB0 : pin doesn't exist */
},
/* Port C: conf, ppar, psor, pdir, podr, pdat */
{
{0, 0, 0, 1, 0, 0}, /* PC31: PC31 */
{0, 0, 0, 1, 0, 0}, /* PC30: PC30 */
{0, 1, 1, 0, 0, 0}, /* PC29: SCC1 EN *CLSN */
{0, 0, 0, 1, 0, 0}, /* PC28: PC28 */
{0, 0, 0, 1, 0, 0}, /* PC27: UART Clock in */
{0, 0, 0, 1, 0, 0}, /* PC26: PC26 */
{0, 0, 0, 1, 0, 0}, /* PC25: PC25 */
{0, 0, 0, 1, 0, 0}, /* PC24: PC24 */
{0, 1, 0, 1, 0, 0}, /* PC23: ATMTFCLK */
{0, 1, 0, 0, 0, 0}, /* PC22: ATMRFCLK */
{1, 1, 0, 0, 0, 0}, /* PC21: SCC1 EN RXCLK */
{1, 1, 0, 0, 0, 0}, /* PC20: SCC1 EN TXCLK */
{1, 1, 0, 0, 0, 0}, /* PC19: FCC2 MII RX_CLK CLK13 */
{1, 1, 0, 0, 0, 0}, /* PC18: FCC Tx Clock (CLK14) */
{1, 1, 0, 0, 0, 0}, /* PC17: PC17 */
{1, 1, 0, 0, 0, 0}, /* PC16: FCC Tx Clock (CLK16) */
{0, 1, 0, 0, 0, 0}, /* PC15: PC15 */
{0, 1, 0, 0, 0, 0}, /* PC14: SCC1 EN *CD */
{0, 1, 0, 0, 0, 0}, /* PC13: PC13 */
{0, 1, 0, 1, 0, 0}, /* PC12: PC12 */
{0, 0, 0, 1, 0, 0}, /* PC11: LXT971 transmit control */
{0, 0, 0, 1, 0, 0}, /* PC10: FETHMDC */
{0, 0, 0, 0, 0, 0}, /* PC9 : FETHMDIO */
{0, 0, 0, 1, 0, 0}, /* PC8 : PC8 */
{0, 0, 0, 1, 0, 0}, /* PC7 : PC7 */
{0, 0, 0, 1, 0, 0}, /* PC6 : PC6 */
{0, 0, 0, 1, 0, 0}, /* PC5 : PC5 */
{0, 0, 0, 1, 0, 0}, /* PC4 : PC4 */
{0, 0, 0, 1, 0, 0}, /* PC3 : PC3 */
{0, 0, 0, 1, 0, 1}, /* PC2 : ENET FDE */
{0, 0, 0, 1, 0, 0}, /* PC1 : ENET DSQE */
{0, 0, 0, 1, 0, 0}, /* PC0 : ENET LBK */
},
/* Port D: conf, ppar, psor, pdir, podr, pdat */
{
#ifdef CONFIG_TQM8560
{1, 1, 0, 0, 0, 0}, /* PD31: SCC1 EN RxD */
{1, 1, 1, 1, 0, 0}, /* PD30: SCC1 EN TxD */
{1, 1, 0, 1, 0, 0}, /* PD29: SCC1 EN TENA */
#else /* !CONFIG_TQM8560 */
{0, 0, 0, 0, 0, 0}, /* PD31: PD31 */
{0, 0, 0, 0, 0, 0}, /* PD30: PD30 */
{0, 0, 0, 0, 0, 0}, /* PD29: PD29 */
#endif /* CONFIG_TQM8560 */
{1, 1, 0, 0, 0, 0}, /* PD28: PD28 */
{1, 1, 0, 1, 0, 0}, /* PD27: PD27 */
{1, 1, 0, 1, 0, 0}, /* PD26: PD26 */
{0, 0, 0, 1, 0, 0}, /* PD25: PD25 */
{0, 0, 0, 1, 0, 0}, /* PD24: PD24 */
{0, 0, 0, 1, 0, 0}, /* PD23: PD23 */
{0, 0, 0, 1, 0, 0}, /* PD22: PD22 */
{0, 0, 0, 1, 0, 0}, /* PD21: PD21 */
{0, 0, 0, 1, 0, 0}, /* PD20: PD20 */
{0, 0, 0, 1, 0, 0}, /* PD19: PD19 */
{0, 0, 0, 1, 0, 0}, /* PD18: PD18 */
{0, 1, 0, 0, 0, 0}, /* PD17: FCC1 ATMRXPRTY */
{0, 1, 0, 1, 0, 0}, /* PD16: FCC1 ATMTXPRTY */
{0, 1, 1, 0, 1, 0}, /* PD15: I2C SDA */
{0, 0, 0, 1, 0, 0}, /* PD14: LED */
{0, 0, 0, 0, 0, 0}, /* PD13: PD13 */
{0, 0, 0, 0, 0, 0}, /* PD12: PD12 */
{0, 0, 0, 0, 0, 0}, /* PD11: PD11 */
{0, 0, 0, 0, 0, 0}, /* PD10: PD10 */
{0, 1, 0, 1, 0, 0}, /* PD9 : SMC1 TXD */
{0, 1, 0, 0, 0, 0}, /* PD8 : SMC1 RXD */
{0, 0, 0, 1, 0, 1}, /* PD7 : PD7 */
{0, 0, 0, 1, 0, 1}, /* PD6 : PD6 */
{0, 0, 0, 1, 0, 1}, /* PD5 : PD5 */
{0, 0, 0, 1, 0, 1}, /* PD4 : PD4 */
{0, 0, 0, 0, 0, 0}, /* PD3 : pin doesn't exist */
{0, 0, 0, 0, 0, 0}, /* PD2 : pin doesn't exist */
{0, 0, 0, 0, 0, 0}, /* PD1 : pin doesn't exist */
{0, 0, 0, 0, 0, 0} /* PD0 : pin doesn't exist */
}
};
#endif /* CONFIG_CPM2 */
#define CASL_STRING1 "casl=xx"
#define CASL_STRING2 "casl="
static const int casl_table[] = { 20, 25, 30 };
#define N_CASL (sizeof(casl_table) / sizeof(casl_table[0]))
int cas_latency (void)
{
char buf[128];
int casl;
int val;
int i;
casl = CONFIG_DDR_DEFAULT_CL;
i = getenv_f("serial#", buf, sizeof(buf));
if (i >0) {
if (strncmp(buf + strlen (buf) - strlen (CASL_STRING1),
CASL_STRING2, strlen (CASL_STRING2)) == 0) {
val = simple_strtoul (buf + strlen (buf) - 2, NULL, 10);
for (i = 0; i < N_CASL; ++i) {
if (val == casl_table[i]) {
return val;
}
}
}
}
return casl;
}
int checkboard (void)
{
char buf[64];
int i = getenv_f("serial#", buf, sizeof(buf));
printf ("Board: %s", CONFIG_BOARDNAME);
if (i > 0) {
puts(", serial# ");
puts(buf);
}
putc ('\n');
/*
* Initialize local bus.
*/
local_bus_init ();
return 0;
}
int misc_init_r (void)
{
/*
* Adjust flash start and offset to detected values
*/
gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize;
gd->bd->bi_flashoffset = 0;
/*
* Recalculate CS configuration if second FLASH bank is available
*/
if (flash_info[0].size > 0) {
set_lbc_or(1, ((-flash_info[0].size) & 0xffff8000) |
(CONFIG_SYS_OR1_PRELIM & 0x00007fff));
set_lbc_br(1, gd->bd->bi_flashstart |
(CONFIG_SYS_BR1_PRELIM & 0x00007fff));
/*
* Re-check to get correct base address for bank 1
*/
flash_get_size (gd->bd->bi_flashstart, 0);
} else {
set_lbc_or(1, 0);
set_lbc_br(1, 0);
}
/*
* If bank 1 is equipped, bank 0 is mapped after bank 1
*/
set_lbc_or(0, ((-flash_info[1].size) & 0xffff8000) |
(CONFIG_SYS_OR0_PRELIM & 0x00007fff));
set_lbc_br(0, (gd->bd->bi_flashstart + flash_info[0].size) |
(CONFIG_SYS_BR0_PRELIM & 0x00007fff));
/*
* Re-check to get correct base address for bank 0
*/
flash_get_size (gd->bd->bi_flashstart + flash_info[0].size, 1);
/*
* Re-do flash protection upon new addresses
*/
flash_protect (FLAG_PROTECT_CLEAR,
gd->bd->bi_flashstart, 0xffffffff,
&flash_info[CONFIG_SYS_MAX_FLASH_BANKS - 1]);
/* Monitor protection ON by default */
flash_protect (FLAG_PROTECT_SET,
CONFIG_SYS_MONITOR_BASE, 0xffffffff,
&flash_info[CONFIG_SYS_MAX_FLASH_BANKS - 1]);
/* Environment protection ON by default */
flash_protect (FLAG_PROTECT_SET,
CONFIG_ENV_ADDR,
CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
&flash_info[CONFIG_SYS_MAX_FLASH_BANKS - 1]);
#ifdef CONFIG_ENV_ADDR_REDUND
/* Redundant environment protection ON by default */
flash_protect (FLAG_PROTECT_SET,
CONFIG_ENV_ADDR_REDUND,
CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
&flash_info[CONFIG_SYS_MAX_FLASH_BANKS - 1]);
#endif
return 0;
}
#ifdef CONFIG_CAN_DRIVER
/*
* Initialize UPMC RAM
*/
static void upmc_write (u_char addr, uint val)
{
volatile fsl_lbc_t *lbc = LBC_BASE_ADDR;
out_be32 (&lbc->mdr, val);
clrsetbits_be32(&lbc->mcmr, MxMR_MAD_MSK,
MxMR_OP_WARR | (addr & MxMR_MAD_MSK));
/* dummy access to perform write */
out_8 ((void __iomem *)CONFIG_SYS_CAN_BASE, 0);
/* normal operation */
clrbits_be32(&lbc->mcmr, MxMR_OP_WARR);
}
#endif /* CONFIG_CAN_DRIVER */
uint get_lbc_clock (void)
{
volatile fsl_lbc_t *lbc = LBC_BASE_ADDR;
sys_info_t sys_info;
ulong clkdiv = lbc->lcrr & LCRR_CLKDIV;
get_sys_info (&sys_info);
if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
#ifdef CONFIG_MPC8548
/*
* Yes, the entire PQ38 family use the same
* bit-representation for twice the clock divider value.
*/
clkdiv *= 2;
#endif
return sys_info.freqSystemBus / clkdiv;
}
puts("Invalid clock divider value in CONFIG_SYS_LBC_LCRR\n");
return 0;
}
/*
* Initialize Local Bus
*/
void local_bus_init (void)
{
volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
volatile fsl_lbc_t *lbc = LBC_BASE_ADDR;
uint lbc_mhz = get_lbc_clock () / 1000000;
#ifdef CONFIG_MPC8548
uint svr = get_svr ();
uint lcrr;
/*
* MPC revision < 2.0
* According to MPC8548E_Device_Errata Rev. L, Erratum LBIU1:
* Modify engineering use only register at address 0xE_0F20.
* "1. Read register at offset 0xE_0F20
* 2. And value with 0x0000_FFFF
* 3. OR result with 0x0000_0004
* 4. Write result back to offset 0xE_0F20."
*
* According to MPC8548E_Device_Errata Rev. L, Erratum LBIU2:
* Modify engineering use only register at address 0xE_0F20.
* "1. Read register at offset 0xE_0F20
* 2. And value with 0xFFFF_FFDF
* 3. Write result back to offset 0xE_0F20."
*
* Since it is the same register, we do the modification in one step.
*/
if (SVR_MAJ (svr) < 2) {
uint dummy = gur->lbiuiplldcr1;
dummy &= 0x0000FFDF;
dummy |= 0x00000004;
gur->lbiuiplldcr1 = dummy;
}
lcrr = CONFIG_SYS_LBC_LCRR;
/*
* Local Bus Clock > 83.3 MHz. According to timing
* specifications set LCRR[EADC] to 2 delay cycles.
*/
if (lbc_mhz > 83) {
lcrr &= ~LCRR_EADC;
lcrr |= LCRR_EADC_2;
}
/*
* According to MPC8548ERMAD Rev. 1.3, 13.3.1.16, 13-30
* disable PLL bypass for Local Bus Clock > 83 MHz.
*/
if (lbc_mhz >= 66)
lcrr &= (~LCRR_DBYP); /* DLL Enabled */
else
lcrr |= LCRR_DBYP; /* DLL Bypass */
lbc->lcrr = lcrr;
asm ("sync;isync;msync");
/*
* According to MPC8548ERMAD Rev.1.3 read back LCRR
* and terminate with isync
*/
lcrr = lbc->lcrr;
asm ("isync;");
/* let DLL stabilize */
udelay (500);
#else /* !CONFIG_MPC8548 */
/*
* Errata LBC11.
* Fix Local Bus clock glitch when DLL is enabled.
*
* If localbus freq is < 66MHz, DLL bypass mode must be used.
* If localbus freq is > 133MHz, DLL can be safely enabled.
* Between 66 and 133, the DLL is enabled with an override workaround.
*/
if (lbc_mhz < 66) {
lbc->lcrr = CONFIG_SYS_LBC_LCRR | LCRR_DBYP; /* DLL Bypass */
lbc->ltedr = LTEDR_BMD | LTEDR_PARD | LTEDR_WPD | LTEDR_WARA |
LTEDR_RAWA | LTEDR_CSD; /* Disable all error checking */
} else if (lbc_mhz >= 133) {
lbc->lcrr = CONFIG_SYS_LBC_LCRR & (~LCRR_DBYP); /* DLL Enabled */
} else {
/*
* On REV1 boards, need to change CLKDIV before enable DLL.
* Default CLKDIV is 8, change it to 4 temporarily.
*/
uint pvr = get_pvr ();
uint temp_lbcdll = 0;
if (pvr == PVR_85xx_REV1) {
/* FIXME: Justify the high bit here. */
lbc->lcrr = 0x10000004;
}
lbc->lcrr = CONFIG_SYS_LBC_LCRR & (~LCRR_DBYP); /* DLL Enabled */
udelay (200);
/*
* Sample LBC DLL ctrl reg, upshift it to set the
* override bits.
*/
temp_lbcdll = gur->lbcdllcr;
gur->lbcdllcr = (((temp_lbcdll & 0xff) << 16) | 0x80000000);
asm ("sync;isync;msync");
}
#endif /* !CONFIG_MPC8548 */
#ifdef CONFIG_CAN_DRIVER
/*
* According to timing specifications EAD must be
* set if Local Bus Clock is > 83 MHz.
*/
if (lbc_mhz > 83)
set_lbc_or(2, CONFIG_SYS_OR2_CAN | OR_UPM_EAD);
else
set_lbc_or(2, CONFIG_SYS_OR2_CAN);
set_lbc_br(2, CONFIG_SYS_BR2_CAN);
/* LGPL4 is UPWAIT */
out_be32(&lbc->mcmr, MxMR_DSx_3_CYCL | MxMR_GPL_x4DIS | MxMR_WLFx_3X);
/* Initialize UPMC for CAN: single read */
upmc_write (0x00, 0xFFFFED00);
upmc_write (0x01, 0xCCFFCC00);
upmc_write (0x02, 0x00FFCF00);
upmc_write (0x03, 0x00FFCF00);
upmc_write (0x04, 0x00FFDC00);
upmc_write (0x05, 0x00FFCF00);
upmc_write (0x06, 0x00FFED00);
upmc_write (0x07, 0x3FFFCC07);
/* Initialize UPMC for CAN: single write */
upmc_write (0x18, 0xFFFFED00);
upmc_write (0x19, 0xCCFFEC00);
upmc_write (0x1A, 0x00FFED80);
upmc_write (0x1B, 0x00FFED80);
upmc_write (0x1C, 0x00FFFC00);
upmc_write (0x1D, 0x0FFFEC00);
upmc_write (0x1E, 0x0FFFEF00);
upmc_write (0x1F, 0x3FFFEC05);
#endif /* CONFIG_CAN_DRIVER */
}
/*
* Initialize PCI Devices, report devices found.
*/
#ifdef CONFIG_PCI1
static struct pci_controller pci1_hose;
#endif /* CONFIG_PCI1 */
void pci_init_board (void)
{
volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
int first_free_busno = 0;
#ifdef CONFIG_PCI1
struct fsl_pci_info pci_info;
int pcie_ep;
u32 devdisr = in_be32(&gur->devdisr);
uint pci_32 = in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_PCI1_PCI32;
uint pci_arb = in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_PCI1_ARB;
uint pci_speed = CONFIG_SYS_CLK_FREQ; /* PCI PSPEED in [4:5] */
uint pci_clk_sel = in_be32(&gur->porpllsr) & MPC85xx_PORDEVSR_PCI1_SPD;
if (!(devdisr & MPC85xx_DEVDISR_PCI1)) {
SET_STD_PCI_INFO(pci_info, 1);
set_next_law(pci_info.mem_phys,
law_size_bits(pci_info.mem_size), pci_info.law);
set_next_law(pci_info.io_phys,
law_size_bits(pci_info.io_size), pci_info.law);
pcie_ep = fsl_setup_hose(&pci1_hose, pci_info.regs);
printf("PCI1: %d bit, %s MHz, %s, %s, %s\n",
(pci_32) ? 32 : 64,
(pci_speed == 33333333) ? "33" :
(pci_speed == 66666666) ? "66" : "unknown",
pci_clk_sel ? "sync" : "async",
pcie_ep ? "agent" : "host",
pci_arb ? "arbiter" : "external-arbiter");
first_free_busno = fsl_pci_init_port(&pci_info,
&pci1_hose, first_free_busno);
#ifdef CONFIG_PCIX_CHECK
if (!(in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_PCI1)) {
ushort reg16 =
PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ |
PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
uint dev = PCI_BDF(0, 0, 0);
/* PCI-X init */
if (CONFIG_SYS_CLK_FREQ < 66000000)
puts ("PCI-X will only work at 66 MHz\n");
pci_write_config_word(dev, PCIX_COMMAND, reg16);
}
#endif
} else {
printf("PCI1: disabled\n");
}
#else
setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCI1);
#endif
fsl_pcie_init_board(first_free_busno);
}
#ifdef CONFIG_OF_BOARD_SETUP
void ft_board_setup (void *blob, bd_t *bd)
{
ft_cpu_setup (blob, bd);
FT_FSL_PCI_SETUP;
}
#endif /* CONFIG_OF_BOARD_SETUP */
#ifdef CONFIG_BOARD_EARLY_INIT_R
int board_early_init_r (void)
{
#ifdef CONFIG_PS2MULT
ps2mult_early_init ();
#endif /* CONFIG_PS2MULT */
return (0);
}
#endif /* CONFIG_BOARD_EARLY_INIT_R */
int board_eth_init(bd_t *bis)
{
cpu_eth_init(bis); /* Intialize TSECs first */
return pci_eth_init(bis);
}

View file

@ -0,0 +1,44 @@
#
# (C) Copyright 2000-2006
# 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 = $(obj)lib$(BOARD).o
COBJS = $(BOARD).o load_sernum_ethaddr.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View file

@ -0,0 +1,105 @@
/*
* (C) Copyright 2000, 2001, 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
*/
#include <common.h>
#include <mpc8xx.h>
/*-----------------------------------------------------------------------
* Process Hardware Information Block:
*
* If we boot on a system fresh from factory, check if the Hardware
* Information Block exists and save the information it contains.
*
* The TQM8xxL / TQM82xx Hardware Information Block is defined as
* follows:
* - located in first flash bank
* - starts at offset 0x0003FFC0
* - size 0x00000040
*
* Internal structure:
* - sequence of ASCII character strings
* - fields separated by a single space character (0x20)
* - last field terminated by NUL character (0x00)
* - remaining space filled with NUL characters (0x00)
*
* Fields in Hardware Information Block:
* 1) Module Type
* 2) Serial Number
* 3) First MAC Address
* 4) Number of additional MAC addresses
*/
void load_sernum_ethaddr (void)
{
unsigned char *hwi;
unsigned char serial [CONFIG_SYS_HWINFO_SIZE];
unsigned char ethaddr[CONFIG_SYS_HWINFO_SIZE];
unsigned short ih, is, ie, part;
hwi = (unsigned char *)(CONFIG_SYS_FLASH_BASE + CONFIG_SYS_HWINFO_OFFSET);
ih = is = ie = 0;
if (*((unsigned long *)hwi) != (unsigned long)CONFIG_SYS_HWINFO_MAGIC) {
return;
}
part = 1;
/* copy serial # / MAC address */
while ((hwi[ih] != '\0') && (ih < CONFIG_SYS_HWINFO_SIZE)) {
if (hwi[ih] < ' ' || hwi[ih] > '~') { /* ASCII strings! */
return;
}
switch (part) {
default: /* Copy serial # */
if (hwi[ih] == ' ') {
++part;
}
serial[is++] = hwi[ih];
break;
case 3: /* Copy MAC address */
if (hwi[ih] == ' ') {
++part;
break;
}
ethaddr[ie++] = hwi[ih];
if ((ie % 3) == 2)
ethaddr[ie++] = ':';
break;
}
++ih;
}
serial[is] = '\0';
if (ie && ethaddr[ie-1] == ':')
--ie;
ethaddr[ie] = '\0';
/* set serial# and ethaddr if not yet defined */
if (getenv("serial#") == NULL) {
setenv ((char *)"serial#", (char *)serial);
}
if (getenv("ethaddr") == NULL) {
setenv ((char *)"ethaddr", (char *)ethaddr);
}
}

View file

@ -0,0 +1,744 @@
/*
* (C) Copyright 2000-2008
* 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 <common.h>
#include <hwconfig.h>
#include <mpc8xx.h>
#ifdef CONFIG_PS2MULT
#include <ps2mult.h>
#endif
#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
#include <libfdt.h>
#endif
extern flash_info_t flash_info[]; /* FLASH chips info */
DECLARE_GLOBAL_DATA_PTR;
static long int dram_size (long int, long int *, long int);
#define _NOT_USED_ 0xFFFFFFFF
/* UPM initialization table for SDRAM: 40, 50, 66 MHz CLKOUT @ CAS latency 2, tWR=2 */
const uint sdram_table[] =
{
/*
* Single Read. (Offset 0 in UPMA RAM)
*/
0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00,
0x1FF5FC47, /* last */
/*
* SDRAM Initialization (offset 5 in UPMA RAM)
*
* This is no UPM entry point. The following definition uses
* the remaining space to establish an initialization
* sequence, which is executed by a RUN command.
*
*/
0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */
/*
* Burst Read. (Offset 8 in UPMA RAM)
*/
0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00,
0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */
_NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
_NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
/*
* Single Write. (Offset 18 in UPMA RAM)
*/
0x1F0DFC04, 0xEEABBC00, 0x11B77C04, 0xEFFAFC44,
0x1FF5FC47, /* last */
_NOT_USED_, _NOT_USED_, _NOT_USED_,
/*
* Burst Write. (Offset 20 in UPMA RAM)
*/
0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00,
0xF0AFFC00, 0xF0AFFC04, 0xE1BAFC44, 0x1FF5FC47, /* last */
_NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
_NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
/*
* Refresh (Offset 30 in UPMA RAM)
*/
0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04,
0xFFFFFC84, 0xFFFFFC07, /* last */
_NOT_USED_, _NOT_USED_,
_NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
/*
* Exception. (Offset 3c in UPMA RAM)
*/
0xFFFFFC07, /* last */
_NOT_USED_, _NOT_USED_, _NOT_USED_,
};
/* ------------------------------------------------------------------------- */
/*
* Check Board Identity:
*
* Test TQ ID string (TQM8xx...)
* If present, check for "L" type (no second DRAM bank),
* otherwise "L" type is assumed as default.
*
* Set board_type to 'L' for "L" type, 'M' for "M" type, 0 else.
*/
int checkboard (void)
{
char buf[64];
int i;
int l = getenv_f("serial#", buf, sizeof(buf));
puts ("Board: ");
if (l < 0 || strncmp(buf, "TQM8", 4)) {
puts ("### No HW ID - assuming TQM8xxL\n");
return (0);
}
if ((buf[6] == 'L')) { /* a TQM8xxL type */
gd->board_type = 'L';
}
if ((buf[6] == 'M')) { /* a TQM8xxM type */
gd->board_type = 'M';
}
if ((buf[6] == 'D')) { /* a TQM885D type */
gd->board_type = 'D';
}
for (i = 0; i < l; ++i) {
if (buf[i] == ' ')
break;
putc (buf[i]);
}
#ifdef CONFIG_VIRTLAB2
puts (" (Virtlab2)");
#endif
putc ('\n');
return (0);
}
/* ------------------------------------------------------------------------- */
phys_size_t initdram (int board_type)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
long int size8, size9, size10;
long int size_b0 = 0;
long int size_b1 = 0;
upmconfig (UPMA, (uint *) sdram_table,
sizeof (sdram_table) / sizeof (uint));
/*
* Preliminary prescaler for refresh (depends on number of
* banks): This value is selected for four cycles every 62.4 us
* with two SDRAM banks or four cycles every 31.2 us with one
* bank. It will be adjusted after memory sizing.
*/
memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_8K;
/*
* The following value is used as an address (i.e. opcode) for
* the LOAD MODE REGISTER COMMAND during SDRAM initialisation. If
* the port size is 32bit the SDRAM does NOT "see" the lower two
* address lines, i.e. mar=0x00000088 -> opcode=0x00000022 for
* MICRON SDRAMs:
* -> 0 00 010 0 010
* | | | | +- Burst Length = 4
* | | | +----- Burst Type = Sequential
* | | +------- CAS Latency = 2
* | +----------- Operating Mode = Standard
* +-------------- Write Burst Mode = Programmed Burst Length
*/
memctl->memc_mar = 0x00000088;
/*
* Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at
* preliminary addresses - these have to be modified after the
* SDRAM size has been determined.
*/
memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
#ifndef CONFIG_CAN_DRIVER
if ((board_type != 'L') &&
(board_type != 'M') &&
(board_type != 'D') ) { /* only one SDRAM bank on L, M and D modules */
memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
}
#endif /* CONFIG_CAN_DRIVER */
memctl->memc_mamr = CONFIG_SYS_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */
udelay (200);
/* perform SDRAM initializsation sequence */
memctl->memc_mcr = 0x80004105; /* SDRAM bank 0 */
udelay (1);
memctl->memc_mcr = 0x80004230; /* SDRAM bank 0 - execute twice */
udelay (1);
#ifndef CONFIG_CAN_DRIVER
if ((board_type != 'L') &&
(board_type != 'M') &&
(board_type != 'D') ) { /* only one SDRAM bank on L, M and D modules */
memctl->memc_mcr = 0x80006105; /* SDRAM bank 1 */
udelay (1);
memctl->memc_mcr = 0x80006230; /* SDRAM bank 1 - execute twice */
udelay (1);
}
#endif /* CONFIG_CAN_DRIVER */
memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */
udelay (1000);
/*
* Check Bank 0 Memory Size for re-configuration
*
* try 8 column mode
*/
size8 = dram_size (CONFIG_SYS_MAMR_8COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE);
debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size8 >> 20);
udelay (1000);
/*
* try 9 column mode
*/
size9 = dram_size (CONFIG_SYS_MAMR_9COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE);
debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size9 >> 20);
udelay(1000);
#if defined(CONFIG_SYS_MAMR_10COL)
/*
* try 10 column mode
*/
size10 = dram_size (CONFIG_SYS_MAMR_10COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE);
debug ("SDRAM Bank 0 in 10 column mode: %ld MB\n", size10 >> 20);
#else
size10 = 0;
#endif /* CONFIG_SYS_MAMR_10COL */
if ((size8 < size10) && (size9 < size10)) {
size_b0 = size10;
} else if ((size8 < size9) && (size10 < size9)) {
size_b0 = size9;
memctl->memc_mamr = CONFIG_SYS_MAMR_9COL;
udelay (500);
} else {
size_b0 = size8;
memctl->memc_mamr = CONFIG_SYS_MAMR_8COL;
udelay (500);
}
debug ("SDRAM Bank 0: %ld MB\n", size_b0 >> 20);
#ifndef CONFIG_CAN_DRIVER
if ((board_type != 'L') &&
(board_type != 'M') &&
(board_type != 'D') ) { /* only one SDRAM bank on L, M and D modules */
/*
* Check Bank 1 Memory Size
* use current column settings
* [9 column SDRAM may also be used in 8 column mode,
* but then only half the real size will be used.]
*/
size_b1 = dram_size (memctl->memc_mamr, (long int *)SDRAM_BASE3_PRELIM,
SDRAM_MAX_SIZE);
debug ("SDRAM Bank 1: %ld MB\n", size_b1 >> 20);
} else {
size_b1 = 0;
}
#endif /* CONFIG_CAN_DRIVER */
udelay (1000);
/*
* Adjust refresh rate depending on SDRAM type, both banks
* For types > 128 MBit leave it at the current (fast) rate
*/
if ((size_b0 < 0x02000000) && (size_b1 < 0x02000000)) {
/* reduce to 15.6 us (62.4 us / quad) */
memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_4K;
udelay (1000);
}
/*
* Final mapping: map bigger bank first
*/
if (size_b1 > size_b0) { /* SDRAM Bank 1 is bigger - map first */
memctl->memc_or3 = ((-size_b1) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM;
memctl->memc_br3 = (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
if (size_b0 > 0) {
/*
* Position Bank 0 immediately above Bank 1
*/
memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM;
memctl->memc_br2 = ((CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V)
+ size_b1;
} else {
unsigned long reg;
/*
* No bank 0
*
* invalidate bank
*/
memctl->memc_br2 = 0;
/* adjust refresh rate depending on SDRAM type, one bank */
reg = memctl->memc_mptpr;
reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */
memctl->memc_mptpr = reg;
}
} else { /* SDRAM Bank 0 is bigger - map first */
memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM;
memctl->memc_br2 =
(CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
if (size_b1 > 0) {
/*
* Position Bank 1 immediately above Bank 0
*/
memctl->memc_or3 =
((-size_b1) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM;
memctl->memc_br3 =
((CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V)
+ size_b0;
} else {
unsigned long reg;
#ifndef CONFIG_CAN_DRIVER
/*
* No bank 1
*
* invalidate bank
*/
memctl->memc_br3 = 0;
#endif /* CONFIG_CAN_DRIVER */
/* adjust refresh rate depending on SDRAM type, one bank */
reg = memctl->memc_mptpr;
reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */
memctl->memc_mptpr = reg;
}
}
udelay (10000);
#ifdef CONFIG_CAN_DRIVER
/* UPM initialization for CAN @ CLKOUT <= 66 MHz */
/* Initialize OR3 / BR3 */
memctl->memc_or3 = CONFIG_SYS_OR3_CAN;
memctl->memc_br3 = CONFIG_SYS_BR3_CAN;
/* Initialize MBMR */
memctl->memc_mbmr = MBMR_GPL_B4DIS; /* GPL_B4 ouput line Disable */
/* Initialize UPMB for CAN: single read */
memctl->memc_mdr = 0xFFFFCC04;
memctl->memc_mcr = 0x0100 | UPMB;
memctl->memc_mdr = 0x0FFFD004;
memctl->memc_mcr = 0x0101 | UPMB;
memctl->memc_mdr = 0x0FFFC000;
memctl->memc_mcr = 0x0102 | UPMB;
memctl->memc_mdr = 0x3FFFC004;
memctl->memc_mcr = 0x0103 | UPMB;
memctl->memc_mdr = 0xFFFFDC07;
memctl->memc_mcr = 0x0104 | UPMB;
/* Initialize UPMB for CAN: single write */
memctl->memc_mdr = 0xFFFCCC04;
memctl->memc_mcr = 0x0118 | UPMB;
memctl->memc_mdr = 0xCFFCDC04;
memctl->memc_mcr = 0x0119 | UPMB;
memctl->memc_mdr = 0x3FFCC000;
memctl->memc_mcr = 0x011A | UPMB;
memctl->memc_mdr = 0xFFFCC004;
memctl->memc_mcr = 0x011B | UPMB;
memctl->memc_mdr = 0xFFFDC405;
memctl->memc_mcr = 0x011C | UPMB;
#endif /* CONFIG_CAN_DRIVER */
#ifdef CONFIG_ISP1362_USB
/* Initialize OR5 / BR5 */
memctl->memc_or5 = CONFIG_SYS_OR5_ISP1362;
memctl->memc_br5 = CONFIG_SYS_BR5_ISP1362;
#endif /* CONFIG_ISP1362_USB */
return (size_b0 + size_b1);
}
/* ------------------------------------------------------------------------- */
/*
* Check memory range for valid RAM. A simple memory test determines
* the actually available RAM size between addresses `base' and
* `base + maxsize'. Some (not all) hardware errors are detected:
* - short between address lines
* - short between data lines
*/
static long int dram_size (long int mamr_value, long int *base, long int maxsize)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
memctl->memc_mamr = mamr_value;
return (get_ram_size(base, maxsize));
}
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_MISC_INIT_R
extern void load_sernum_ethaddr(void);
int misc_init_r (void)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
load_sernum_ethaddr();
#ifdef CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ
int scy, trlx, flash_or_timing, clk_diff;
scy = (CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ & OR_SCY_MSK) >> 4;
if (CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ & OR_TRLX) {
trlx = OR_TRLX;
scy *= 2;
} else {
trlx = 0;
}
/*
* We assume that each 10MHz of bus clock require 1-clk SCY
* adjustment.
*/
clk_diff = (gd->bus_clk / 1000000) - 50;
/*
* We need proper rounding here. This is what the "+5" and "-5"
* are here for.
*/
if (clk_diff >= 0)
scy += (clk_diff + 5) / 10;
else
scy += (clk_diff - 5) / 10;
/*
* For bus frequencies above 50MHz, we want to use relaxed timing
* (OR_TRLX).
*/
if (gd->bus_clk >= 50000000)
trlx = OR_TRLX;
else
trlx = 0;
if (trlx)
scy /= 2;
if (scy > 0xf)
scy = 0xf;
if (scy < 1)
scy = 1;
flash_or_timing = (scy << 4) | trlx |
(CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ & ~(OR_TRLX | OR_SCY_MSK));
memctl->memc_or0 =
flash_or_timing | (-flash_info[0].size & OR_AM_MSK);
#else
memctl->memc_or0 =
CONFIG_SYS_OR_TIMING_FLASH | (-flash_info[0].size & OR_AM_MSK);
#endif
memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
debug ("## BR0: 0x%08x OR0: 0x%08x\n",
memctl->memc_br0, memctl->memc_or0);
if (flash_info[1].size) {
#ifdef CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ
memctl->memc_or1 = flash_or_timing |
(-flash_info[1].size & 0xFFFF8000);
#else
memctl->memc_or1 = CONFIG_SYS_OR_TIMING_FLASH |
(-flash_info[1].size & 0xFFFF8000);
#endif
memctl->memc_br1 =
((CONFIG_SYS_FLASH_BASE +
flash_info[0].
size) & BR_BA_MSK) | BR_MS_GPCM | BR_V;
debug ("## BR1: 0x%08x OR1: 0x%08x\n",
memctl->memc_br1, memctl->memc_or1);
} else {
memctl->memc_br1 = 0; /* invalidate bank */
debug ("## DISABLE BR1: 0x%08x OR1: 0x%08x\n",
memctl->memc_br1, memctl->memc_or1);
}
# ifdef CONFIG_IDE_LED
/* Configure PA15 as output port */
immap->im_ioport.iop_padir |= 0x0001;
immap->im_ioport.iop_paodr |= 0x0001;
immap->im_ioport.iop_papar &= ~0x0001;
immap->im_ioport.iop_padat &= ~0x0001; /* turn it off */
# endif
#ifdef CONFIG_NSCU
/* wake up ethernet module */
immap->im_ioport.iop_pcpar &= ~0x0004; /* GPIO pin */
immap->im_ioport.iop_pcdir |= 0x0004; /* output */
immap->im_ioport.iop_pcso &= ~0x0004; /* for clarity */
immap->im_ioport.iop_pcdat |= 0x0004; /* enable */
#endif /* CONFIG_NSCU */
return (0);
}
#endif /* CONFIG_MISC_INIT_R */
# ifdef CONFIG_IDE_LED
void ide_led (uchar led, uchar status)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
/* We have one led for both pcmcia slots */
if (status) { /* led on */
immap->im_ioport.iop_padat |= 0x0001;
} else {
immap->im_ioport.iop_padat &= ~0x0001;
}
}
# endif
#ifdef CONFIG_LCD_INFO
#include <lcd.h>
#include <version.h>
#include <timestamp.h>
void lcd_show_board_info(void)
{
char temp[32];
lcd_printf ("%s (%s - %s)\n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);
lcd_printf ("(C) 2008 DENX Software Engineering GmbH\n");
lcd_printf (" Wolfgang DENK, wd@denx.de\n");
#ifdef CONFIG_LCD_INFO_BELOW_LOGO
lcd_printf ("MPC823 CPU at %s MHz\n",
strmhz(temp, gd->cpu_clk));
lcd_printf (" %ld MB RAM, %ld MB Flash\n",
gd->ram_size >> 20,
gd->bd->bi_flashsize >> 20 );
#else
/* leave one blank line */
lcd_printf ("\nMPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash\n",
strmhz(temp, gd->cpu_clk),
gd->ram_size >> 20,
gd->bd->bi_flashsize >> 20 );
#endif /* CONFIG_LCD_INFO_BELOW_LOGO */
}
#endif /* CONFIG_LCD_INFO */
/*
* Device Tree Support
*/
#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
int fdt_set_node_and_value (void *blob,
char *nodename,
char *regname,
void *var,
int size)
{
int ret = 0;
int nodeoffset = 0;
nodeoffset = fdt_path_offset (blob, nodename);
if (nodeoffset >= 0) {
ret = fdt_setprop (blob, nodeoffset, regname, var,
size);
if (ret < 0) {
printf("ft_blob_update(): "
"cannot set %s/%s property; err: %s\n",
nodename, regname, fdt_strerror (ret));
}
} else {
printf("ft_blob_update(): "
"cannot find %s node err:%s\n",
nodename, fdt_strerror (nodeoffset));
}
return ret;
}
int fdt_del_node_name (void *blob, char *nodename)
{
int ret = 0;
int nodeoffset = 0;
nodeoffset = fdt_path_offset (blob, nodename);
if (nodeoffset >= 0) {
ret = fdt_del_node (blob, nodeoffset);
if (ret < 0) {
printf("%s: cannot delete %s; err: %s\n",
__func__, nodename, fdt_strerror (ret));
}
} else {
printf("%s: cannot find %s node err:%s\n",
__func__, nodename, fdt_strerror (nodeoffset));
}
return ret;
}
int fdt_del_prop_name (void *blob, char *nodename, char *propname)
{
int ret = 0;
int nodeoffset = 0;
nodeoffset = fdt_path_offset (blob, nodename);
if (nodeoffset >= 0) {
ret = fdt_delprop (blob, nodeoffset, propname);
if (ret < 0) {
printf("%s: cannot delete %s %s; err: %s\n",
__func__, nodename, propname,
fdt_strerror (ret));
}
} else {
printf("%s: cannot find %s node err:%s\n",
__func__, nodename, fdt_strerror (nodeoffset));
}
return ret;
}
/*
* update "brg" property in the blob
*/
void ft_blob_update (void *blob, bd_t *bd)
{
uchar enetaddr[6];
ulong brg_data = 0;
/* BRG */
brg_data = cpu_to_be32(bd->bi_busfreq);
fdt_set_node_and_value(blob,
"/soc/cpm", "brg-frequency",
&brg_data, sizeof(brg_data));
/* MAC addr */
if (eth_getenv_enetaddr("ethaddr", enetaddr)) {
fdt_set_node_and_value(blob,
"ethernet0", "local-mac-address",
enetaddr, sizeof(u8) * 6);
}
if (hwconfig_arg_cmp("fec", "off")) {
/* no FEC on this plattform, delete DTS nodes */
fdt_del_node_name (blob, "ethernet1");
fdt_del_node_name (blob, "mdio1");
/* also the aliases entries */
fdt_del_prop_name (blob, "/aliases", "ethernet1");
fdt_del_prop_name (blob, "/aliases", "mdio1");
} else {
/* adjust local-mac-address for FEC ethernet */
if (eth_getenv_enetaddr("eth1addr", enetaddr)) {
fdt_set_node_and_value(blob,
"ethernet1", "local-mac-address",
enetaddr, sizeof(u8) * 6);
}
}
}
void ft_board_setup(void *blob, bd_t *bd)
{
ft_cpu_setup(blob, bd);
ft_blob_update(blob, bd);
}
#endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
/* ---------------------------------------------------------------------------- */
/* TK885D specific initializaion */
/* ---------------------------------------------------------------------------- */
#ifdef CONFIG_TK885D
#include <miiphy.h>
int last_stage_init(void)
{
const unsigned char phy[] = {CONFIG_FEC1_PHY, CONFIG_FEC2_PHY};
unsigned short reg;
int ret, i = 100;
char *s;
mii_init();
/* Without this delay 0xff is read from the UART buffer later in
* abortboot() and autoboot is aborted */
udelay(10000);
while (tstc() && i--)
(void)getc();
/* Check if auto-negotiation is prohibited */
s = getenv("phy_auto_nego");
if (!s || !strcmp(s, "on"))
/* Nothing to do - autonegotiation by default */
return 0;
for (i = 0; i < 2; i++) {
ret = miiphy_read("FEC", phy[i], MII_BMCR, &reg);
if (ret) {
printf("Cannot read BMCR on PHY %d\n", phy[i]);
return 0;
}
/* Auto-negotiation off, hard set full duplex, 100Mbps */
ret = miiphy_write("FEC", phy[i],
MII_BMCR, (reg | BMCR_SPEED100 |
BMCR_FULLDPLX) & ~BMCR_ANENABLE);
if (ret) {
printf("Cannot write BMCR on PHY %d\n", phy[i]);
return 0;
}
}
return 0;
}
#endif

View file

@ -0,0 +1,113 @@
/*
* (C) Copyright 2000
* 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
*/
OUTPUT_ARCH(powerpc)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = + SIZEOF_HEADERS;
.text :
{
/* WARNING - the following is hand-optimized to fit within */
/* the sector layout of our flash chips! XXX FIXME XXX */
arch/powerpc/cpu/mpc8xx/start.o (.text*)
arch/powerpc/cpu/mpc8xx/traps.o (.text*)
arch/powerpc/cpu/mpc8xx/libmpc8xx.o (.text*)
arch/powerpc/lib/libpowerpc.o (.text*)
board/tqc/tqm8xx/libtqm8xx.o (.text*)
disk/libdisk.o (.text*)
drivers/net/libnet.o (.text*)
drivers/pcmcia/libpcmcia.o (.text.pcmcia_on)
drivers/pcmcia/libpcmcia.o (.text.pcmcia_hardware_enable)
drivers/rtc/librtc.o (.text*)
drivers/misc/libmisc.o (.text*)
*(.text.print_buffer)
*(.text.print_size)
. = DEFINED(env_offset) ? env_offset : .;
common/env_embedded.o (.ppcenv*)
*(.text*)
}
_etext = .;
PROVIDE (etext = .);
.rodata :
{
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
}
/* Read-write section, merged into data segment: */
. = (. + 0x00FF) & 0xFFFFFF00;
_erotext = .;
PROVIDE (erotext = .);
.reloc :
{
_GOT2_TABLE_ = .;
KEEP(*(.got2))
KEEP(*(.got))
PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
_FIXUP_TABLE_ = .;
KEEP(*(.fixup))
}
__got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
__fixup_entries = (. - _FIXUP_TABLE_)>>2;
.data :
{
*(.data*)
*(.sdata*)
}
_edata = .;
PROVIDE (edata = .);
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = .;
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
. = ALIGN(256);
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
. = ALIGN(256);
__init_end = .;
__bss_start = .;
.bss (NOLOAD) :
{
*(.bss*)
*(.sbss*)
*(COMMON)
. = ALIGN(4);
}
__bss_end__ = . ;
PROVIDE (end = .);
}