Merge git://www.denx.de/git/u-boot

Conflicts:

	CREDITS
This commit is contained in:
Nobuhiro Iwamatsu
2007-09-23 01:29:43 +09:00
1899 changed files with 118238 additions and 140547 deletions

View File

@@ -31,7 +31,7 @@
#include <asm/cache.h>
#include <asm/mmu.h>
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
/*
* cache flushing routines for kgdb
@@ -74,4 +74,4 @@ kgdb_flush_cache_range:
SYNC
blr
#endif /* CFG_CMD_KGDB */
#endif

View File

@@ -125,7 +125,7 @@ _start_of_vectors:
/* Alignment exception. */
. = 0x600
Alignment:
EXCEPTION_PROLOG
EXCEPTION_PROLOG(SRR0, SRR1)
mfspr r4,DAR
stw r4,_DAR(r21)
mfspr r5,DSISR
@@ -143,7 +143,7 @@ Alignment:
/* Program check exception */
. = 0x700
ProgramCheck:
EXCEPTION_PROLOG
EXCEPTION_PROLOG(SRR0, SRR1)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */

View File

@@ -40,7 +40,7 @@
DECLARE_GLOBAL_DATA_PTR;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -133,7 +133,7 @@ MachineCheckException(struct pt_regs *regs)
return;
}
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -166,7 +166,7 @@ MachineCheckException(struct pt_regs *regs)
void
AlignmentException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -181,7 +181,7 @@ ProgramCheckException(struct pt_regs *regs)
unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
int i, j;
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -204,7 +204,7 @@ ProgramCheckException(struct pt_regs *regs)
void
SoftEmuException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -217,7 +217,7 @@ SoftEmuException(struct pt_regs *regs)
void
UnknownException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif

View File

@@ -31,4 +31,5 @@ PLATFORM_CPPFLAGS += -march=armv5
#
# =========================================================================
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,)
PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))

View File

@@ -0,0 +1,50 @@
#
# (C) Copyright 2000-2007
# 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$(SOC).a
COBJS = flash.o mmc.o mmc_hw.o spi.o
SOBJS = $(obj)iap_entry.o
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS) $(SOBJS)
$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
# this MUST be compiled as thumb code!
$(SOBJS):
$(CC) $(AFLAGS) -march=armv4t -c -o $(SOBJS) iap_entry.S
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

249
cpu/arm720t/lpc2292/flash.c Normal file
View File

@@ -0,0 +1,249 @@
/*
* (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com>
*
* Modified to remove all but the IAP-command related code by
* Gary Jennejohn <garyj@denx.de>
*
* 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/arch/hardware.h>
/* IAP commands use 32 bytes at the top of CPU internal sram, we
use 512 bytes below that */
#define COPY_BUFFER_LOCATION 0x40003de0
#define IAP_LOCATION 0x7ffffff1
#define IAP_CMD_PREPARE 50
#define IAP_CMD_COPY 51
#define IAP_CMD_ERASE 52
#define IAP_CMD_CHECK 53
#define IAP_CMD_ID 54
#define IAP_CMD_VERSION 55
#define IAP_CMD_COMPARE 56
#define IAP_RET_CMD_SUCCESS 0
static unsigned long command[5];
static unsigned long result[2];
extern void iap_entry(unsigned long * command, unsigned long * result);
/*-----------------------------------------------------------------------
*
*/
static int get_flash_sector(flash_info_t * info, ulong flash_addr)
{
int i;
for(i = 1; i < (info->sector_count); i++) {
if (flash_addr < (info->start[i]))
break;
}
return (i-1);
}
/*-----------------------------------------------------------------------
* This function assumes that flash_addr is aligned on 512 bytes boundary
* in flash. This function also assumes that prepare have been called
* for the sector in question.
*/
int lpc2292_copy_buffer_to_flash(flash_info_t * info, ulong flash_addr)
{
int first_sector;
int last_sector;
first_sector = get_flash_sector(info, flash_addr);
last_sector = get_flash_sector(info, flash_addr + 512 - 1);
/* prepare sectors for write */
command[0] = IAP_CMD_PREPARE;
command[1] = first_sector;
command[2] = last_sector;
iap_entry(command, result);
if (result[0] != IAP_RET_CMD_SUCCESS) {
printf("IAP prepare failed\n");
return ERR_PROG_ERROR;
}
command[0] = IAP_CMD_COPY;
command[1] = flash_addr;
command[2] = COPY_BUFFER_LOCATION;
command[3] = 512;
command[4] = CFG_SYS_CLK_FREQ >> 10;
iap_entry(command, result);
if (result[0] != IAP_RET_CMD_SUCCESS) {
printf("IAP copy failed\n");
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------
*/
int lpc2292_flash_erase (flash_info_t * info, int s_first, int s_last)
{
int flag;
int prot;
int sect;
prot = 0;
for (sect = s_first; sect <= s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot)
return ERR_PROTECTED;
flag = disable_interrupts();
printf ("Erasing %d sectors starting at sector %2d.\n"
"This make take some time ... ",
s_last - s_first + 1, s_first);
command[0] = IAP_CMD_PREPARE;
command[1] = s_first;
command[2] = s_last;
iap_entry(command, result);
if (result[0] != IAP_RET_CMD_SUCCESS) {
printf("IAP prepare failed\n");
return ERR_PROTECTED;
}
command[0] = IAP_CMD_ERASE;
command[1] = s_first;
command[2] = s_last;
command[3] = CFG_SYS_CLK_FREQ >> 10;
iap_entry(command, result);
if (result[0] != IAP_RET_CMD_SUCCESS) {
printf("IAP erase failed\n");
return ERR_PROTECTED;
}
if (flag)
enable_interrupts();
return ERR_OK;
}
int lpc2292_write_buff (flash_info_t * info, uchar * src, ulong addr,
ulong cnt)
{
int first_copy_size;
int last_copy_size;
int first_block;
int last_block;
int nbr_mid_blocks;
uchar memmap_value;
ulong i;
uchar* src_org;
uchar* dst_org;
int ret = ERR_OK;
src_org = src;
dst_org = (uchar*)addr;
first_block = addr / 512;
last_block = (addr + cnt) / 512;
nbr_mid_blocks = last_block - first_block - 1;
first_copy_size = 512 - (addr % 512);
last_copy_size = (addr + cnt) % 512;
debug("\ncopy first block: (1) %lX -> %lX 0x200 bytes, "
"(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX 0x200 bytes\n",
(ulong)(first_block * 512),
(ulong)COPY_BUFFER_LOCATION,
(ulong)src,
(ulong)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
first_copy_size,
(ulong)COPY_BUFFER_LOCATION,
(ulong)(first_block * 512));
/* copy first block */
memcpy((void*)COPY_BUFFER_LOCATION,
(void*)(first_block * 512), 512);
memcpy((void*)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
src, first_copy_size);
lpc2292_copy_buffer_to_flash(info, first_block * 512);
src += first_copy_size;
addr += first_copy_size;
/* copy middle blocks */
for (i = 0; i < nbr_mid_blocks; i++) {
debug("copy middle block: %lX -> %lX 512 bytes, "
"%lX -> %lX 512 bytes\n",
(ulong)src,
(ulong)COPY_BUFFER_LOCATION,
(ulong)COPY_BUFFER_LOCATION,
(ulong)addr);
memcpy((void*)COPY_BUFFER_LOCATION, src, 512);
lpc2292_copy_buffer_to_flash(info, addr);
src += 512;
addr += 512;
}
if (last_copy_size > 0) {
debug("copy last block: (1) %lX -> %lX 0x200 bytes, "
"(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX x200 bytes\n",
(ulong)(last_block * 512),
(ulong)COPY_BUFFER_LOCATION,
(ulong)src,
(ulong)(COPY_BUFFER_LOCATION),
last_copy_size,
(ulong)COPY_BUFFER_LOCATION,
(ulong)addr);
/* copy last block */
memcpy((void*)COPY_BUFFER_LOCATION,
(void*)(last_block * 512), 512);
memcpy((void*)COPY_BUFFER_LOCATION,
src, last_copy_size);
lpc2292_copy_buffer_to_flash(info, addr);
}
/* verify write */
memmap_value = GET8(MEMMAP);
disable_interrupts();
PUT8(MEMMAP, 01); /* we must make sure that initial 64
bytes are taken from flash when we
do the compare */
for (i = 0; i < cnt; i++) {
if (*dst_org != *src_org){
printf("Write failed. Byte %lX differs\n", i);
ret = ERR_PROG_ERROR;
break;
}
dst_org++;
src_org++;
}
PUT8(MEMMAP, memmap_value);
enable_interrupts();
return ret;
}

View File

@@ -0,0 +1,7 @@
IAP_ADDRESS: .word 0x7FFFFFF1
.globl iap_entry
iap_entry:
ldr r2, IAP_ADDRESS
bx r2
mov pc, lr

157
cpu/arm720t/lpc2292/mmc.c Normal file
View File

@@ -0,0 +1,157 @@
/*
* 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 <config.h>
#include <common.h>
#include <mmc.h>
#include <asm/errno.h>
#include <asm/arch/hardware.h>
#include <part.h>
#include <fat.h>
#include "mmc_hw.h"
#include <asm/arch/spi.h>
#ifdef CONFIG_MMC
#undef MMC_DEBUG
static block_dev_desc_t mmc_dev;
/* these are filled out by a call to mmc_hw_get_parameters */
static int hw_size; /* in kbytes */
static int hw_nr_sects;
static int hw_sect_size; /* in bytes */
block_dev_desc_t * mmc_get_dev(int dev)
{
return (block_dev_desc_t *)(&mmc_dev);
}
unsigned long mmc_block_read(int dev,
unsigned long start,
lbaint_t blkcnt,
void *buffer)
{
unsigned long rc = 0;
unsigned char *p = (unsigned char *)buffer;
unsigned long i;
unsigned long addr = start;
#ifdef MMC_DEBUG
printf("mmc_block_read: start=%lu, blkcnt=%lu\n", start,
(unsigned long)blkcnt);
#endif
for(i = 0; i < (unsigned long)blkcnt; i++) {
#ifdef MMC_DEBUG
printf("mmc_read_sector: addr=%lu, buffer=%p\n", addr, p);
#endif
(void)mmc_read_sector(addr, p);
rc++;
addr++;
p += hw_sect_size;
}
return rc;
}
/*-----------------------------------------------------------------------------
* Read hardware paramterers (sector size, size, number of sectors)
*/
static int mmc_hw_get_parameters(void)
{
unsigned char csddata[16];
unsigned int sizemult;
unsigned int size;
mmc_read_csd(csddata);
hw_sect_size = 1<<(csddata[5] & 0x0f);
size = ((csddata[6]&0x03)<<10)+(csddata[7]<<2)+(csddata[8]&0xc0);
sizemult = ((csddata[10] & 0x80)>>7)+((csddata[9] & 0x03)<<1);
hw_nr_sects = (size+1)*(1<<(sizemult+2));
hw_size = hw_nr_sects*hw_sect_size/1024;
#ifdef MMC_DEBUG
printf("mmc_hw_get_parameters: hw_sect_size=%d, hw_nr_sects=%d, "
"hw_size=%d\n", hw_sect_size, hw_nr_sects, hw_size);
#endif
return 0;
}
int mmc_init(int verbose)
{
int ret = -ENODEV;
if (verbose)
printf("mmc_init\n");
spi_init();
/* this meeds to be done twice */
mmc_hw_init();
udelay(1000);
mmc_hw_init();
mmc_hw_get_parameters();
mmc_dev.if_type = IF_TYPE_MMC;
mmc_dev.part_type = PART_TYPE_DOS;
mmc_dev.dev = 0;
mmc_dev.lun = 0;
mmc_dev.type = 0;
mmc_dev.blksz = hw_sect_size;
mmc_dev.lba = hw_nr_sects;
sprintf((char*)mmc_dev.vendor, "Unknown vendor");
sprintf((char*)mmc_dev.product, "Unknown product");
sprintf((char*)mmc_dev.revision, "N/A");
mmc_dev.removable = 0; /* should be true??? */
mmc_dev.block_read = mmc_block_read;
fat_register_device(&mmc_dev, 1);
ret = 0;
return ret;
}
int mmc_write(uchar * src, ulong dst, int size)
{
#ifdef MMC_DEBUG
printf("mmc_write: src=%p, dst=%lu, size=%u\n", src, dst, size);
#endif
/* Since mmc2info always returns 0 this function will never be called */
return 0;
}
int mmc_read(ulong src, uchar * dst, int size)
{
#ifdef MMC_DEBUG
printf("mmc_read: src=%lu, dst=%p, size=%u\n", src, dst, size);
#endif
/* Since mmc2info always returns 0 this function will never be called */
return 0;
}
int mmc2info(ulong addr)
{
/* This function is used by cmd_cp to determine if source or destination
address resides on MMC-card or not. We do not support copy to and from
MMC-card so we always return 0. */
return 0;
}
#endif /* CONFIG_MMC */

View File

@@ -0,0 +1,233 @@
/*
This code was original written by Ulrich Radig and modified by
Embedded Artists AB (www.embeddedartists.com).
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <config.h>
#include <common.h>
#include <asm/arch/hardware.h>
#include <asm/arch/spi.h>
#define MMC_Enable() PUT32(IO1CLR, 1l << 22)
#define MMC_Disable() PUT32(IO1SET, 1l << 22)
#define mmc_spi_cfg() spi_set_clock(8); spi_set_cfg(0, 1, 0);
static unsigned char Write_Command_MMC (unsigned char *CMD);
static void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer,
unsigned short int Bytes);
/* initialize the hardware */
int mmc_hw_init(void)
{
unsigned long a;
unsigned short int Timeout = 0;
unsigned char b;
unsigned char CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
/* set-up GPIO and SPI */
(*((volatile unsigned long *)PINSEL2)) &= ~(1l << 3); /* clear bit 3 */
(*((volatile unsigned long *)IO1DIR)) |= (1l << 22); /* set bit 22 (output) */
MMC_Disable();
spi_lock();
spi_set_clock(248);
spi_set_cfg(0, 1, 0);
MMC_Enable();
/* waste some time */
for(a=0; a < 20000; a++)
asm("nop");
/* Put the MMC/SD-card into SPI-mode */
for (b = 0; b < 10; b++) /* Sends min 74+ clocks to the MMC/SD-card */
spi_write(0xff);
/* Sends command CMD0 to MMC/SD-card */
while (Write_Command_MMC(CMD) != 1) {
if (Timeout++ > 200) {
MMC_Disable();
spi_unlock();
return(1); /* Abort with command 1 (return 1) */
}
}
/* Sends Command CMD1 an MMC/SD-card */
Timeout = 0;
CMD[0] = 0x41;/* Command 1 */
CMD[5] = 0xFF;
while (Write_Command_MMC(CMD) != 0) {
if (Timeout++ > 200) {
MMC_Disable();
spi_unlock();
return (2); /* Abort with command 2 (return 2) */
}
}
MMC_Disable();
spi_unlock();
return 0;
}
/* ############################################################################
Sends a command to the MMC/SD-card
######################################################################### */
static unsigned char Write_Command_MMC (unsigned char *CMD)
{
unsigned char a, tmp = 0xff;
unsigned short int Timeout = 0;
MMC_Disable();
spi_write(0xFF);
MMC_Enable();
for (a = 0; a < 0x06; a++)
spi_write(*CMD++);
while (tmp == 0xff) {
tmp = spi_read();
if (Timeout++ > 5000)
break;
}
return (tmp);
}
/* ############################################################################
Routine to read the CID register from the MMC/SD-card (16 bytes)
######################################################################### */
void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer, unsigned short
int Bytes)
{
unsigned short int a;
spi_lock();
mmc_spi_cfg();
MMC_Enable();
if (Write_Command_MMC(CMD) != 0) {
MMC_Disable();
spi_unlock();
return;
}
while (spi_read() != 0xfe) {};
for (a = 0; a < Bytes; a++)
*Buffer++ = spi_read();
/* Read the CRC-byte */
spi_read(); /* CRC - byte is discarded */
spi_read(); /* CRC - byte is discarded */
/* set MMC_Chip_Select to high (MMC/SD-card Inaktiv) */
MMC_Disable();
spi_unlock();
return;
}
/* ############################################################################
Routine to read a block (512 bytes) from the MMC/SD-card
######################################################################### */
unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
{
/* Command 16 to read aBlocks from the MMC/SD - caed */
unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
/* The addres on the MMC/SD-card is in bytes,
addr is transformed from blocks to bytes and the result is
placed into the command */
addr = addr << 9; /* addr = addr * 512 */
CMD[1] = ((addr & 0xFF000000) >> 24);
CMD[2] = ((addr & 0x00FF0000) >> 16);
CMD[3] = ((addr & 0x0000FF00) >> 8 );
MMC_Read_Block(CMD, Buffer, 512);
return (0);
}
/* ############################################################################
Routine to write a block (512 byte) to the MMC/SD-card
######################################################################### */
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
{
unsigned char tmp, a;
unsigned short int b;
/* Command 24 to write a block to the MMC/SD - card */
unsigned char CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
/* The addres on the MMC/SD-card is in bytes,
addr is transformed from blocks to bytes and the result is
placed into the command */
addr = addr << 9; /* addr = addr * 512 */
CMD[1] = ((addr & 0xFF000000) >> 24);
CMD[2] = ((addr & 0x00FF0000) >> 16);
CMD[3] = ((addr & 0x0000FF00) >> 8 );
spi_lock();
mmc_spi_cfg();
MMC_Enable();
/* Send command CMD24 to the MMC/SD-card (Write 1 Block/512 Bytes) */
tmp = Write_Command_MMC(CMD);
if (tmp != 0) {
MMC_Disable();
spi_unlock();
return(tmp);
}
/* Do a short delay and send a clock-pulse to the MMC/SD-card */
for (a = 0; a < 100; a++)
spi_read();
/* Send a start byte to the MMC/SD-card */
spi_write(0xFE);
/* Write the block (512 bytes) to the MMC/SD-card */
for (b = 0; b < 512; b++)
spi_write(*Buffer++);
/* write the CRC-Byte */
spi_write(0xFF); /* write a dummy CRC */
spi_write(0xFF); /* CRC code is not used */
/* Wait for MMC/SD-card busy */
while (spi_read() != 0xff) {};
/* set MMC_Chip_Select to high (MMC/SD-card inactive) */
MMC_Disable();
spi_unlock();
return (0);
}
/* #########################################################################
Routine to read the CSD register from the MMC/SD-card (16 bytes)
######################################################################### */
unsigned char mmc_read_csd (unsigned char *Buffer)
{
/* Command to read the CSD register */
unsigned char CMD[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
MMC_Read_Block(CMD, Buffer, 16);
return (0);
}

View File

@@ -0,0 +1,29 @@
/*
This module implements a linux character device driver for the 24c256 chip.
Copyright (C) 2006 Embedded Artists AB (www.embeddedartists.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _MMC_HW_
#define _MMC_HW_
unsigned char mmc_read_csd(unsigned char *Buffer);
unsigned char mmc_read_sector (unsigned long addr,
unsigned char *Buffer);
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer);
int mmc_hw_init(void);
#endif /* _MMC_HW_ */

40
cpu/arm720t/lpc2292/spi.c Normal file
View File

@@ -0,0 +1,40 @@
/*
This module implements an interface to the SPI on the lpc22xx.
Copyright (C) 2006 Embedded Artists AB (www.embeddedartists.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <config.h>
#include <common.h>
#include <asm/errno.h>
#include <asm/arch/hardware.h>
#include <asm/arch/spi.h>
unsigned long spi_flags;
unsigned char spi_idle = 0x00;
int spi_init(void)
{
unsigned long pinsel0_value;
/* activate spi pins */
pinsel0_value = GET32(PINSEL0);
pinsel0_value &= ~(0xFFl << 8);
pinsel0_value |= (0x55l << 8);
PUT32(PINSEL0, pinsel0_value);
return 0;
}

View File

@@ -129,8 +129,6 @@ serial_puts (const char *s)
void serial_setbrg (void)
{
DECLARE_GLOBAL_DATA_PTR;
unsigned short divisor = 0;
switch (gd->baudrate) {

View File

@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
COBJS = bcm5221.o dm9161.o ether.o i2c.o interrupts.o \
lxt972.o serial.o usb_ohci.o
lxt972.o serial.o usb.o spi.o
SOBJS = lowlevel_init.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)

View File

@@ -32,7 +32,7 @@
#ifdef CONFIG_DRIVER_ETHER
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_CMD_NET)
/*
* Name:
@@ -227,6 +227,6 @@ unsigned char bcm5221_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
return FALSE;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
#endif
#endif /* CONFIG_DRIVER_ETHER */

View File

@@ -27,7 +27,7 @@
#ifdef CONFIG_DRIVER_ETHER
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_CMD_NET)
/*
* Name:
@@ -95,7 +95,7 @@ UCHAR dm9161_GetLinkSpeed (AT91PS_EMAC p_mac)
return TRUE;
}
if ((stat1 & DM9161_100BASE_T4_HD) && (stat2 & DM9161_100HDX)) {
if ((stat1 & DM9161_100BASE_TX_HD) && (stat2 & DM9161_100HDX)) {
/*set MII for 100BaseTX and Half Duplex */
p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
@@ -140,7 +140,7 @@ UCHAR dm9161_InitPhy (AT91PS_EMAC p_mac)
at91rm9200_EmacReadPhy (p_mac, DM9161_MDINTR, &IntValue);
/* set FDX, SPD, Link, INTR masks */
IntValue |= (DM9161_FDX_MASK | DM9161_SPD_MASK |
DM9161_LINK_MASK | DM9161_INTR_MASK);
DM9161_LINK_MASK | DM9161_INTR_MASK);
at91rm9200_EmacWritePhy (p_mac, DM9161_MDINTR, &IntValue);
at91rm9200_EmacDisableMDIO (p_mac);
@@ -174,10 +174,11 @@ UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
if (!at91rm9200_EmacWritePhy (p_mac, DM9161_BMCR, &value))
return FALSE;
/* Set the Auto_negotiation Advertisement Register */
/* MII advertising for Next page, 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */
/* Set the Auto_negotiation Advertisement Register */
/* MII advertising for Next page, 100BaseTxFD and HD, */
/* 10BaseTFD and HD, IEEE 802.3 */
PhyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
if (!at91rm9200_EmacWritePhy (p_mac, DM9161_ANAR, &PhyAnar))
return FALSE;
@@ -220,6 +221,6 @@ UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
return FALSE;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
#endif
#endif /* CONFIG_DRIVER_ETHER */

View File

@@ -50,7 +50,7 @@ typedef struct {
#ifdef CONFIG_DRIVER_ETHER
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_CMD_NET)
/* alignment as per Errata #11 (64 bytes) is insufficient! */
rbf_t rbfdt[RBF_FRAMEMAX] __attribute((aligned(512)));
@@ -265,7 +265,7 @@ void eth_halt (void)
{
};
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
int at91rm9200_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short * value)
{
@@ -284,16 +284,16 @@ int at91rm9200_miiphy_write(char *devname, unsigned char addr,
return 0;
}
#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
#endif
int at91rm9200_miiphy_initialize(bd_t *bis)
{
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register("at91rm9200phy", at91rm9200_miiphy_read, at91rm9200_miiphy_write);
#endif
return 0;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
#endif
#endif /* CONFIG_DRIVER_ETHER */

View File

@@ -33,7 +33,7 @@
#ifdef CONFIG_DRIVER_ETHER
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_CMD_NET)
/*
* Name:
@@ -186,6 +186,6 @@ UCHAR lxt972_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
return (lxt972_GetLinkSpeed (p_mac));
}
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
#endif
#endif /* CONFIG_DRIVER_ETHER */

View File

@@ -0,0 +1,151 @@
/* Driver for ATMEL DataFlash support
* Author : Hamid Ikdoumi (Atmel)
*
* 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 <config.h>
#include <common.h>
#include <asm/hardware.h>
#ifdef CONFIG_HAS_DATAFLASH
#include <dataflash.h>
#define AT91C_SPI_CLK 10000000 /* Max Value = 10MHz to be compliant to
the Continuous Array Read function */
/* AC Characteristics */
/* DLYBS = tCSS = 250ns min and DLYBCT = tCSH = 250ns */
#define DATAFLASH_TCSS (0xC << 16)
#define DATAFLASH_TCHS (0x1 << 24)
#define AT91C_TIMEOUT_WRDY 200000
#define AT91C_SPI_PCS0_SERIAL_DATAFLASH 0xE /* Chip Select 0: NPCS0%1110 */
#define AT91C_SPI_PCS3_DATAFLASH_CARD 0x7 /* Chip Select 3: NPCS3%0111 */
/*-------------------------------------------------------------------*/
/* SPI DataFlash Init */
/*-------------------------------------------------------------------*/
void AT91F_SpiInit(void)
{
/* Configure PIOs */
AT91C_BASE_PIOA->PIO_ASR =
AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI |
AT91C_PA5_NPCS2 | AT91C_PA6_NPCS3 | AT91C_PA0_MISO |
AT91C_PA2_SPCK;
AT91C_BASE_PIOA->PIO_PDR =
AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI |
AT91C_PA5_NPCS2 | AT91C_PA6_NPCS3 | AT91C_PA0_MISO |
AT91C_PA2_SPCK;
/* Enable CLock */
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI;
/* Reset the SPI */
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
/* Configure SPI in Master Mode with No CS selected !!! */
AT91C_BASE_SPI->SPI_MR =
AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
/* Configure CS0 and CS3 */
*(AT91C_SPI_CSR + 0) =
AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) |
(AT91C_SPI_DLYBCT & DATAFLASH_TCHS) |
((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
*(AT91C_SPI_CSR + 3) =
AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) |
(AT91C_SPI_DLYBCT & DATAFLASH_TCHS) |
((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
}
void AT91F_SpiEnable(int cs)
{
switch(cs) {
case 0: /* Configure SPI CS0 for Serial DataFlash AT45DBxx */
AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
AT91C_BASE_SPI->SPI_MR |=
((AT91C_SPI_PCS0_SERIAL_DATAFLASH<<16) &
AT91C_SPI_PCS);
break;
case 3: /* Configure SPI CS3 for Serial DataFlash Card */
/* Set up PIO SDC_TYPE to switch on DataFlash Card */
/* and not MMC/SDCard */
AT91C_BASE_PIOB->PIO_PER =
AT91C_PIO_PB7; /* Set in PIO mode */
AT91C_BASE_PIOB->PIO_OER =
AT91C_PIO_PB7; /* Configure in output */
/* Clear Output */
AT91C_BASE_PIOB->PIO_CODR = AT91C_PIO_PB7;
/* Configure PCS */
AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
AT91C_BASE_SPI->SPI_MR |=
((AT91C_SPI_PCS3_DATAFLASH_CARD<<16) & AT91C_SPI_PCS);
break;
}
/* SPI_Enable */
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; }
/*---------------------------------------------------------------------------*/
/* \fn AT91F_SpiWrite */
/* \brief Set the PDC registers for a transfert */
/*---------------------------------------------------------------------------*/
unsigned int AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
{
unsigned int timeout;
pDesc->state = BUSY;
AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
/* Initialize the Transmit and Receive Pointer */
AT91C_BASE_SPI->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ;
AT91C_BASE_SPI->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ;
/* Intialize the Transmit and Receive Counters */
AT91C_BASE_SPI->SPI_RCR = pDesc->rx_cmd_size;
AT91C_BASE_SPI->SPI_TCR = pDesc->tx_cmd_size;
if ( pDesc->tx_data_size != 0 ) {
/* Initialize the Next Transmit and Next Receive Pointer */
AT91C_BASE_SPI->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ;
AT91C_BASE_SPI->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ;
/* Intialize the Next Transmit and Next Receive Counters */
AT91C_BASE_SPI->SPI_RNCR = pDesc->rx_data_size ;
AT91C_BASE_SPI->SPI_TNCR = pDesc->tx_data_size ;
}
/* arm simple, non interrupt dependent timer */
reset_timer_masked();
timeout = 0;
AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;
while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RXBUFF) &&
((timeout = get_timer_masked() ) < CFG_SPI_WRITE_TOUT));
AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
pDesc->state = IDLE;
if (timeout >= CFG_SPI_WRITE_TOUT){
printf("Error Timeout\n\r");
return DATAFLASH_ERROR;
}
return DATAFLASH_OK;
}
#endif

View File

@@ -0,0 +1,53 @@
/*
* (C) Copyright 2006
* DENX Software Engineering <mk@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>
#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
# ifdef CONFIG_AT91RM9200
#include <asm/arch/hardware.h>
int usb_cpu_init()
{
/* Enable USB host clock. */
*AT91C_PMC_SCER = AT91C_PMC_UHP; /* 48MHz clock enabled for UHP */
*AT91C_PMC_PCER = 1 << AT91C_ID_UHP; /* Peripheral Clock Enable Register */
return 0;
}
int usb_cpu_stop()
{
/* Initialization failed */
*AT91C_PMC_PCDR = 1 << AT91C_ID_UHP; /* Peripheral Clock Disable Register */
*AT91C_PMC_SCDR = AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */
return 0;
}
int usb_cpu_init_fail()
{
usb_cpu_stop();
}
# endif /* CONFIG_AT91RM9200 */
#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */

File diff suppressed because it is too large Load Diff

View File

@@ -1,419 +0,0 @@
/*
* URB OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
*
* usb-ohci.h
*/
static int cc_to_error[16] = {
/* mapping of the OHCI CC status to error codes */
/* No Error */ 0,
/* CRC Error */ USB_ST_CRC_ERR,
/* Bit Stuff */ USB_ST_BIT_ERR,
/* Data Togg */ USB_ST_CRC_ERR,
/* Stall */ USB_ST_STALLED,
/* DevNotResp */ -1,
/* PIDCheck */ USB_ST_BIT_ERR,
/* UnExpPID */ USB_ST_BIT_ERR,
/* DataOver */ USB_ST_BUF_ERR,
/* DataUnder */ USB_ST_BUF_ERR,
/* reservd */ -1,
/* reservd */ -1,
/* BufferOver */ USB_ST_BUF_ERR,
/* BuffUnder */ USB_ST_BUF_ERR,
/* Not Access */ -1,
/* Not Access */ -1
};
/* ED States */
#define ED_NEW 0x00
#define ED_UNLINK 0x01
#define ED_OPER 0x02
#define ED_DEL 0x04
#define ED_URB_DEL 0x08
/* usb_ohci_ed */
struct ed {
__u32 hwINFO;
__u32 hwTailP;
__u32 hwHeadP;
__u32 hwNextED;
struct ed *ed_prev;
__u8 int_period;
__u8 int_branch;
__u8 int_load;
__u8 int_interval;
__u8 state;
__u8 type;
__u16 last_iso;
struct ed *ed_rm_list;
struct usb_device *usb_dev;
__u32 unused[3];
} __attribute((aligned(16)));
typedef struct ed ed_t;
/* TD info field */
#define TD_CC 0xf0000000
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
#define TD_EC 0x0C000000
#define TD_T 0x03000000
#define TD_T_DATA0 0x02000000
#define TD_T_DATA1 0x03000000
#define TD_T_TOGGLE 0x00000000
#define TD_R 0x00040000
#define TD_DI 0x00E00000
#define TD_DI_SET(X) (((X) & 0x07)<< 21)
#define TD_DP 0x00180000
#define TD_DP_SETUP 0x00000000
#define TD_DP_IN 0x00100000
#define TD_DP_OUT 0x00080000
#define TD_ISO 0x00010000
#define TD_DEL 0x00020000
/* CC Codes */
#define TD_CC_NOERROR 0x00
#define TD_CC_CRC 0x01
#define TD_CC_BITSTUFFING 0x02
#define TD_CC_DATATOGGLEM 0x03
#define TD_CC_STALL 0x04
#define TD_DEVNOTRESP 0x05
#define TD_PIDCHECKFAIL 0x06
#define TD_UNEXPECTEDPID 0x07
#define TD_DATAOVERRUN 0x08
#define TD_DATAUNDERRUN 0x09
#define TD_BUFFEROVERRUN 0x0C
#define TD_BUFFERUNDERRUN 0x0D
#define TD_NOTACCESSED 0x0F
#define MAXPSW 1
struct td {
__u32 hwINFO;
__u32 hwCBP; /* Current Buffer Pointer */
__u32 hwNextTD; /* Next TD Pointer */
__u32 hwBE; /* Memory Buffer End Pointer */
__u16 hwPSW[MAXPSW];
__u8 unused;
__u8 index;
struct ed *ed;
struct td *next_dl_td;
struct usb_device *usb_dev;
int transfer_len;
__u32 data;
__u32 unused2[2];
} __attribute((aligned(32)));
typedef struct td td_t;
#define OHCI_ED_SKIP (1 << 14)
/*
* The HCCA (Host Controller Communications Area) is a 256 byte
* structure defined in the OHCI spec. that the host controller is
* told the base address of. It must be 256-byte aligned.
*/
#define NUM_INTS 32 /* part of the OHCI standard */
struct ohci_hcca {
__u32 int_table[NUM_INTS]; /* Interrupt ED table */
__u16 frame_no; /* current frame number */
__u16 pad1; /* set to 0 on each frame_no change */
__u32 done_head; /* info returned for an interrupt */
u8 reserved_for_hc[116];
} __attribute((aligned(256)));
/*
* Maximum number of root hub ports.
*/
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */
/*
* This is the structure of the OHCI controller's memory mapped I/O
* region. This is Memory Mapped I/O. You must use the readl() and
* writel() macros defined in asm/io.h to access these!!
*/
struct ohci_regs {
/* control and status registers */
__u32 revision;
__u32 control;
__u32 cmdstatus;
__u32 intrstatus;
__u32 intrenable;
__u32 intrdisable;
/* memory pointers */
__u32 hcca;
__u32 ed_periodcurrent;
__u32 ed_controlhead;
__u32 ed_controlcurrent;
__u32 ed_bulkhead;
__u32 ed_bulkcurrent;
__u32 donehead;
/* frame counters */
__u32 fminterval;
__u32 fmremaining;
__u32 fmnumber;
__u32 periodicstart;
__u32 lsthresh;
/* Root hub ports */
struct ohci_roothub_regs {
__u32 a;
__u32 b;
__u32 status;
__u32 portstatus[MAX_ROOT_PORTS];
} roothub;
} __attribute((aligned(32)));
/* OHCI CONTROL AND STATUS REGISTER MASKS */
/*
* HcControl (control) register masks
*/
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
/* pre-shifted values for HCFS */
# define OHCI_USB_RESET (0 << 6)
# define OHCI_USB_RESUME (1 << 6)
# define OHCI_USB_OPER (2 << 6)
# define OHCI_USB_SUSPEND (3 << 6)
/*
* HcCommandStatus (cmdstatus) register masks
*/
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_CLF (1 << 1) /* control list filled */
#define OHCI_BLF (1 << 2) /* bulk list filled */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
/*
* masks used with interrupt registers:
* HcInterruptStatus (intrstatus)
* HcInterruptEnable (intrenable)
* HcInterruptDisable (intrdisable)
*/
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
#define OHCI_INTR_SF (1 << 2) /* start frame */
#define OHCI_INTR_RD (1 << 3) /* resume detect */
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
#define OHCI_INTR_OC (1 << 30) /* ownership change */
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
/* Virtual Root HUB */
struct virt_root_hub {
int devnum; /* Address of Root Hub endpoint */
void *dev; /* was urb */
void *int_addr;
int send;
int interval;
};
/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
/* destination of request */
#define RH_INTERFACE 0x01
#define RH_ENDPOINT 0x02
#define RH_OTHER 0x03
#define RH_CLASS 0x20
#define RH_VENDOR 0x40
/* Requests: bRequest << 8 | bmRequestType */
#define RH_GET_STATUS 0x0080
#define RH_CLEAR_FEATURE 0x0100
#define RH_SET_FEATURE 0x0300
#define RH_SET_ADDRESS 0x0500
#define RH_GET_DESCRIPTOR 0x0680
#define RH_SET_DESCRIPTOR 0x0700
#define RH_GET_CONFIGURATION 0x0880
#define RH_SET_CONFIGURATION 0x0900
#define RH_GET_STATE 0x0280
#define RH_GET_INTERFACE 0x0A80
#define RH_SET_INTERFACE 0x0B00
#define RH_SYNC_FRAME 0x0C80
/* Our Vendor Specific Request */
#define RH_SET_EP 0x2000
/* Hub port features */
#define RH_PORT_CONNECTION 0x00
#define RH_PORT_ENABLE 0x01
#define RH_PORT_SUSPEND 0x02
#define RH_PORT_OVER_CURRENT 0x03
#define RH_PORT_RESET 0x04
#define RH_PORT_POWER 0x08
#define RH_PORT_LOW_SPEED 0x09
#define RH_C_PORT_CONNECTION 0x10
#define RH_C_PORT_ENABLE 0x11
#define RH_C_PORT_SUSPEND 0x12
#define RH_C_PORT_OVER_CURRENT 0x13
#define RH_C_PORT_RESET 0x14
/* Hub features */
#define RH_C_HUB_LOCAL_POWER 0x00
#define RH_C_HUB_OVER_CURRENT 0x01
#define RH_DEVICE_REMOTE_WAKEUP 0x00
#define RH_ENDPOINT_STALL 0x01
#define RH_ACK 0x01
#define RH_REQ_ERR -1
#define RH_NACK 0x00
/* OHCI ROOT HUB REGISTER MASKS */
/* roothub.portstatus [i] bits */
#define RH_PS_CCS 0x00000001 /* current connect status */
#define RH_PS_PES 0x00000002 /* port enable status*/
#define RH_PS_PSS 0x00000004 /* port suspend status */
#define RH_PS_POCI 0x00000008 /* port over current indicator */
#define RH_PS_PRS 0x00000010 /* port reset status */
#define RH_PS_PPS 0x00000100 /* port power status */
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
#define RH_PS_CSC 0x00010000 /* connect status change */
#define RH_PS_PESC 0x00020000 /* port enable status change */
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
#define RH_PS_PRSC 0x00100000 /* port reset status change */
/* roothub.status bits */
#define RH_HS_LPS 0x00000001 /* local power status */
#define RH_HS_OCI 0x00000002 /* over current indicator */
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
#define RH_HS_LPSC 0x00010000 /* local power status change */
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
/* roothub.b masks */
#define RH_B_DR 0x0000ffff /* device removable flags */
#define RH_B_PPCM 0xffff0000 /* port power control mask */
/* roothub.a masks */
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
#define RH_A_PSM (1 << 8) /* power switching mode */
#define RH_A_NPS (1 << 9) /* no power switching */
#define RH_A_DT (1 << 10) /* device type (mbz) */
#define RH_A_OCPM (1 << 11) /* over current protection mode */
#define RH_A_NOCP (1 << 12) /* no over current protection */
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
/* urb */
#define N_URB_TD 48
typedef struct
{
ed_t *ed;
__u16 length; /* number of tds associated with this request */
__u16 td_cnt; /* number of tds already serviced */
int state;
unsigned long pipe;
int actual_length;
td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
} urb_priv_t;
#define URB_DEL 1
/*
* This is the full ohci controller description
*
* Note how the "proper" USB information is just
* a subset of what the full implementation needs. (Linus)
*/
typedef struct ohci {
struct ohci_hcca *hcca; /* hcca */
/*dma_addr_t hcca_dma;*/
int irq;
int disabled; /* e.g. got a UE, we're hung */
int sleeping;
unsigned long flags; /* for HC bugs */
struct ohci_regs *regs; /* OHCI controller's memory */
ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
ed_t *ed_bulktail; /* last endpoint of bulk list */
ed_t *ed_controltail; /* last endpoint of control list */
int intrstatus;
__u32 hc_control; /* copy of the hc control reg */
struct usb_device *dev[32];
struct virt_root_hub rh;
const char *slot_name;
} ohci_t;
#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
struct ohci_device {
ed_t ed[NUM_EDS];
int ed_cnt;
};
/* hcd */
/* endpoint */
static int ep_link(ohci_t * ohci, ed_t * ed);
static int ep_unlink(ohci_t * ohci, ed_t * ed);
static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe);
/*-------------------------------------------------------------------------*/
/* we need more TDs than EDs */
#define NUM_TD 64
/* +1 so we can align the storage */
td_t gtd[NUM_TD+1];
/* pointers to aligned storage */
td_t *ptd;
/* TDs ... */
static inline struct td *
td_alloc (struct usb_device *usb_dev)
{
int i;
struct td *td;
td = NULL;
for (i = 0; i < NUM_TD; i++)
{
if (ptd[i].usb_dev == NULL)
{
td = &ptd[i];
td->usb_dev = usb_dev;
break;
}
}
return td;
}
static inline void
ed_free (struct ed *ed)
{
ed->usb_dev = NULL;
}

View File

@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
COBJS = i2c.o interrupts.o serial.o speed.o \
usb_ohci.o
usb.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))

72
cpu/arm920t/s3c24x0/usb.c Normal file
View File

@@ -0,0 +1,72 @@
/*
* (C) Copyright 2006
* DENX Software Engineering <mk@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>
#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
#if defined(CONFIG_S3C2400)
# include <s3c2400.h>
#elif defined(CONFIG_S3C2410)
# include <s3c2410.h>
#endif
int usb_cpu_init (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/*
* Set the 48 MHz UPLL clocking. Values are taken from
* "PLL value selection guide", 6-23, s3c2400_UM.pdf.
*/
clk_power->UPLLCON = ((40 << 12) + (1 << 4) + 2);
gpio->MISCCR |= 0x8; /* 1 = use pads related USB for USB host */
/*
* Enable USB host clock.
*/
clk_power->CLKCON |= (1 << 4);
return 0;
}
int usb_cpu_stop (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
/* may not want to do this */
clk_power->CLKCON &= ~(1 << 4);
return 0;
}
int usb_cpu_init_fail (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
clk_power->CLKCON &= ~(1 << 4);
return 0;
}
# endif /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */
#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */

View File

@@ -27,7 +27,9 @@
#include <config.h>
#include <version.h>
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
#include <led.h>
#endif
/*
*************************************************************************
@@ -116,6 +118,69 @@ reset:
orr r0,r0,#0xd3
msr cpsr,r0
#if CONFIG_AT91RM9200
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
bl LED_init
bl red_LED_on
#endif
#ifdef CONFIG_BOOTBINFUNC
/* code based on entry.S from ATMEL */
#define AT91C_BASE_CKGR 0xFFFFFC20
#define CKGR_MOR 0
/* Get the CKGR Base Address */
ldr r1, =AT91C_BASE_CKGR
/* Main oscillator Enable register APMC_MOR : Enable main oscillator , OSCOUNT = 0xFF */
/* ldr r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT */
ldr r0, =0x0000FF01
str r0, [r1, #CKGR_MOR]
/* Add loop to compensate Main Oscillator startup time */
ldr r0, =0x00000010
LoopOsc:
subs r0, r0, #1
bhi LoopOsc
/* scratch stack */
ldr r1, =0x00204000
/* Insure word alignment */
bic r1, r1, #3
/* Init stack SYS */
mov sp, r1
/*
* This does a lot more than just set up the memory, which
* is why it's called lowlevelinit
*/
bl lowlevelinit /* in memsetup.S */
bl icache_enable;
/* ------------------------------------
* Read/modify/write CP15 control register
* -------------------------------------
* read cp15 control register (cp15 r1) in r0
* ------------------------------------
*/
mrc p15, 0, r0, c1, c0, 0
/* Reset bit :Little Endian end fast bus mode */
ldr r3, =0xC0000080
/* Set bit :Asynchronous clock mode, Not Fast Bus */
ldr r4, =0xC0000000
bic r0, r0, r3
orr r0, r0, r4
/* write r0 in cp15 control register (cp15 r1) */
mcr p15, 0, r0, c1, c0, 0
#endif /* CONFIG_BOOTBINFUNC */
/*
* relocate exeception table
*/
ldr r0, =_start
ldr r1, =0x0
mov r2, #16
copyex:
subs r2, r2, #1
ldr r3, [r0], #4
str r3, [r1], #4
bne copyex
#endif
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
@@ -160,6 +225,26 @@ reset:
bl cpu_init_crit
#endif
#ifdef CONFIG_AT91RM9200
#ifdef CONFIG_BOOTBINFUNC
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_BOOTBINFUNC */
#else
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
@@ -178,7 +263,7 @@ copy_loop:
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
@@ -262,7 +347,11 @@ cpu_init_crit:
* find a lowlevel_init.S in your board directory.
*/
mov ip, lr
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
#else
bl lowlevel_init
#endif
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

View File

@@ -0,0 +1,49 @@
#
# (C) Copyright 2000-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
#
# 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$(SOC).a
COBJS = timer.o ether.o lxt972.o dp83848.o i2c.o nand.o
SOBJS = lowlevel_init.o reset.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
START := $(addprefix $(obj),$(START))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@@ -0,0 +1,156 @@
/*
* National Semiconductor DP83848 PHY Driver for TI DaVinci
* (TMS320DM644x) based boards.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* --------------------------------------------------------
*
* 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 <net.h>
#include <dp83848.h>
#include <asm/arch/emac_defs.h>
#ifdef CONFIG_DRIVER_TI_EMAC
#ifdef CONFIG_CMD_NET
int dp83848_is_phy_connected(int phy_addr)
{
u_int16_t id1, id2;
if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1))
return(0);
if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2))
return(0);
if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI))
return(1);
return(0);
}
int dp83848_get_link_speed(int phy_addr)
{
u_int16_t tmp;
volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR;
if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
return(0);
if (!(tmp & DP83848_LINK_STATUS)) /* link up? */
return(0);
if (!dm644x_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp))
return(0);
/* Speed doesn't matter, there is no setting for it in EMAC... */
if (tmp & DP83848_SPEED) {
if (tmp & DP83848_DUPLEX) {
/* set DM644x EMAC for Full Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
} else {
/*set DM644x EMAC for Half Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
}
return(1);
} else {
if (tmp & DP83848_DUPLEX) {
/* set DM644x EMAC for Full Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
} else {
/*set DM644x EMAC for Half Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
}
return(1);
}
return(0);
}
int dp83848_init_phy(int phy_addr)
{
int ret = 1;
if (!dp83848_get_link_speed(phy_addr)) {
/* Try another time */
udelay(100000);
ret = dp83848_get_link_speed(phy_addr);
}
/* Disable PHY Interrupts */
dm644x_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0);
return(ret);
}
int dp83848_auto_negotiate(int phy_addr)
{
u_int16_t tmp;
if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
return(0);
/* Restart Auto_negotiation */
tmp &= ~DP83848_AUTONEG; /* remove autonegotiation enable */
tmp |= DP83848_ISOLATE; /* Electrically isolate PHY */
dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
/* Set the Auto_negotiation Advertisement Register
* MII advertising for Next page, 100BaseTxFD and HD,
* 10BaseTFD and HD, IEEE 802.3
*/
tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX |
DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3;
dm644x_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp);
/* Read Control Register */
if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
return(0);
tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE;
dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
/* Restart Auto_negotiation */
tmp |= DP83848_RESTART_AUTONEG;
dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
/*check AutoNegotiate complete */
udelay(10000);
if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
return(0);
if (!(tmp & DP83848_AUTONEG_COMP))
return(0);
return (dp83848_get_link_speed(phy_addr));
}
#endif /* CONFIG_CMD_NET */
#endif /* CONFIG_DRIVER_ETHER */

View File

@@ -0,0 +1,650 @@
/*
* Ethernet driver for TI TMS320DM644x (DaVinci) chips.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
* follows:
*
* ----------------------------------------------------------------------------
*
* dm644x_emac.c
*
* TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
*
* Copyright (C) 2005 Texas Instruments.
*
* ----------------------------------------------------------------------------
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* ----------------------------------------------------------------------------
* Modifications:
* ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
* ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
*
*/
#include <common.h>
#include <command.h>
#include <net.h>
#include <miiphy.h>
#include <asm/arch/emac_defs.h>
#ifdef CONFIG_DRIVER_TI_EMAC
#ifdef CONFIG_CMD_NET
unsigned int emac_dbg = 0;
#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args)
/* Internal static functions */
static int dm644x_eth_hw_init (void);
static int dm644x_eth_open (void);
static int dm644x_eth_close (void);
static int dm644x_eth_send_packet (volatile void *packet, int length);
static int dm644x_eth_rcv_packet (void);
static void dm644x_eth_mdio_enable(void);
static int gen_init_phy(int phy_addr);
static int gen_is_phy_connected(int phy_addr);
static int gen_get_link_speed(int phy_addr);
static int gen_auto_negotiate(int phy_addr);
/* Wrappers exported to the U-Boot proper */
int eth_hw_init(void)
{
return(dm644x_eth_hw_init());
}
int eth_init(bd_t * bd)
{
return(dm644x_eth_open());
}
void eth_halt(void)
{
dm644x_eth_close();
}
int eth_send(volatile void *packet, int length)
{
return(dm644x_eth_send_packet(packet, length));
}
int eth_rx(void)
{
return(dm644x_eth_rcv_packet());
}
void eth_mdio_enable(void)
{
dm644x_eth_mdio_enable();
}
/* End of wrappers */
static u_int8_t dm644x_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
/*
* This function must be called before emac_open() if you want to override
* the default mac address.
*/
void dm644x_eth_set_mac_addr(const u_int8_t *addr)
{
int i;
for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) {
dm644x_eth_mac_addr[i] = addr[i];
}
}
/* EMAC Addresses */
static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
/* EMAC descriptors */
static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
static volatile emac_desc *emac_rx_active_head = 0;
static volatile emac_desc *emac_rx_active_tail = 0;
static int emac_rx_queue_active = 0;
/* Receive packet buffers */
static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
/* PHY address for a discovered PHY (0xff - not found) */
static volatile u_int8_t active_phy_addr = 0xff;
phy_t phy;
static void dm644x_eth_mdio_enable(void)
{
u_int32_t clkdiv;
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
adap_mdio->CONTROL = (clkdiv & 0xff) |
MDIO_CONTROL_ENABLE |
MDIO_CONTROL_FAULT |
MDIO_CONTROL_FAULT_ENABLE;
while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;}
}
/*
* Tries to find an active connected PHY. Returns 1 if address if found.
* If no active PHY (or more than one PHY) found returns 0.
* Sets active_phy_addr variable.
*/
static int dm644x_eth_phy_detect(void)
{
u_int32_t phy_act_state;
int i;
active_phy_addr = 0xff;
if ((phy_act_state = adap_mdio->ALIVE) == 0)
return(0); /* No active PHYs */
debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
for (i = 0; i < 32; i++) {
if (phy_act_state & (1 << i)) {
if (phy_act_state & ~(1 << i))
return(0); /* More than one PHY */
else {
active_phy_addr = i;
return(1);
}
}
}
return(0); /* Just to make GCC happy */
}
/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
{
int tmp;
while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
MDIO_USERACCESS0_WRITE_READ |
((reg_num & 0x1f) << 21) |
((phy_addr & 0x1f) << 16);
/* Wait for command to complete */
while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;}
if (tmp & MDIO_USERACCESS0_ACK) {
*data = tmp & 0xffff;
return(1);
}
*data = -1;
return(0);
}
/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
{
while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
MDIO_USERACCESS0_WRITE_WRITE |
((reg_num & 0x1f) << 21) |
((phy_addr & 0x1f) << 16) |
(data & 0xffff);
/* Wait for command to complete */
while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
return(1);
}
/* PHY functions for a generic PHY */
static int gen_init_phy(int phy_addr)
{
int ret = 1;
if (gen_get_link_speed(phy_addr)) {
/* Try another time */
ret = gen_get_link_speed(phy_addr);
}
return(ret);
}
static int gen_is_phy_connected(int phy_addr)
{
u_int16_t dummy;
return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy));
}
static int gen_get_link_speed(int phy_addr)
{
u_int16_t tmp;
if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04))
return(1);
return(0);
}
static int gen_auto_negotiate(int phy_addr)
{
u_int16_t tmp;
if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp))
return(0);
/* Restart Auto_negotiation */
tmp |= PHY_BMCR_AUTON;
dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp);
/*check AutoNegotiate complete */
udelay (10000);
if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp))
return(0);
if (!(tmp & PHY_BMSR_AUTN_COMP))
return(0);
return(gen_get_link_speed(phy_addr));
}
/* End of generic PHY functions */
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
{
return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1);
}
static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value)
{
return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1);
}
int dm644x_eth_miiphy_initialize(bd_t *bis)
{
miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write);
return(1);
}
#endif
/*
* This function initializes the emac hardware. It does NOT initialize
* EMAC modules power or pin multiplexors, that is done by board_init()
* much earlier in bootup process. Returns 1 on success, 0 otherwise.
*/
static int dm644x_eth_hw_init(void)
{
u_int32_t phy_id;
u_int16_t tmp;
int i;
dm644x_eth_mdio_enable();
for (i = 0; i < 256; i++) {
if (adap_mdio->ALIVE)
break;
udelay(10);
}
if (i >= 256) {
printf("No ETH PHY detected!!!\n");
return(0);
}
/* Find if a PHY is connected and get it's address */
if (!dm644x_eth_phy_detect())
return(0);
/* Get PHY ID and initialize phy_ops for a detected PHY */
if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) {
active_phy_addr = 0xff;
return(0);
}
phy_id = (tmp << 16) & 0xffff0000;
if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) {
active_phy_addr = 0xff;
return(0);
}
phy_id |= tmp & 0x0000ffff;
switch (phy_id) {
case PHY_LXT972:
sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr);
phy.init = lxt972_init_phy;
phy.is_phy_connected = lxt972_is_phy_connected;
phy.get_link_speed = lxt972_get_link_speed;
phy.auto_negotiate = lxt972_auto_negotiate;
break;
case PHY_DP83848:
sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr);
phy.init = dp83848_init_phy;
phy.is_phy_connected = dp83848_is_phy_connected;
phy.get_link_speed = dp83848_get_link_speed;
phy.auto_negotiate = dp83848_auto_negotiate;
break;
default:
sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr);
phy.init = gen_init_phy;
phy.is_phy_connected = gen_is_phy_connected;
phy.get_link_speed = gen_get_link_speed;
phy.auto_negotiate = gen_auto_negotiate;
}
return(1);
}
/* Eth device open */
static int dm644x_eth_open(void)
{
dv_reg_p addr;
u_int32_t clkdiv, cnt;
volatile emac_desc *rx_desc;
debug_emac("+ emac_open\n");
/* Reset EMAC module and disable interrupts in wrapper */
adap_emac->SOFTRESET = 1;
while (adap_emac->SOFTRESET != 0) {;}
adap_ewrap->EWCTL = 0;
for (cnt = 0; cnt < 5; cnt++) {
clkdiv = adap_ewrap->EWCTL;
}
rx_desc = emac_rx_desc;
adap_emac->TXCONTROL = 0x01;
adap_emac->RXCONTROL = 0x01;
/* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
/* Using channel 0 only - other channels are disabled */
adap_emac->MACINDEX = 0;
adap_emac->MACADDRHI =
(dm644x_eth_mac_addr[3] << 24) |
(dm644x_eth_mac_addr[2] << 16) |
(dm644x_eth_mac_addr[1] << 8) |
(dm644x_eth_mac_addr[0]);
adap_emac->MACADDRLO =
(dm644x_eth_mac_addr[5] << 8) |
(dm644x_eth_mac_addr[4]);
adap_emac->MACHASH1 = 0;
adap_emac->MACHASH2 = 0;
/* Set source MAC address - REQUIRED */
adap_emac->MACSRCADDRHI =
(dm644x_eth_mac_addr[3] << 24) |
(dm644x_eth_mac_addr[2] << 16) |
(dm644x_eth_mac_addr[1] << 8) |
(dm644x_eth_mac_addr[0]);
adap_emac->MACSRCADDRLO =
(dm644x_eth_mac_addr[4] << 8) |
(dm644x_eth_mac_addr[5]);
/* Set DMA 8 TX / 8 RX Head pointers to 0 */
addr = &adap_emac->TX0HDP;
for(cnt = 0; cnt < 16; cnt++)
*addr++ = 0;
addr = &adap_emac->RX0HDP;
for(cnt = 0; cnt < 16; cnt++)
*addr++ = 0;
/* Clear Statistics (do this before setting MacControl register) */
addr = &adap_emac->RXGOODFRAMES;
for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
*addr++ = 0;
/* No multicast addressing */
adap_emac->MACHASH1 = 0;
adap_emac->MACHASH2 = 0;
/* Create RX queue and set receive process in place */
emac_rx_active_head = emac_rx_desc;
for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
rx_desc->next = (u_int32_t)(rx_desc + 1);
rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
rx_desc++;
}
/* Set the last descriptor's "next" parameter to 0 to end the RX desc list */
rx_desc--;
rx_desc->next = 0;
emac_rx_active_tail = rx_desc;
emac_rx_queue_active = 1;
/* Enable TX/RX */
adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE;
adap_emac->RXBUFFEROFFSET = 0;
/* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */
adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN;
/* Enable ch 0 only */
adap_emac->RXUNICASTSET = 0x01;
/* Enable MII interface and Full duplex mode */
adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE);
/* Init MDIO & get link state */
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT);
if (!phy.get_link_speed(active_phy_addr))
return(0);
/* Start receive process */
adap_emac->RX0HDP = (u_int32_t)emac_rx_desc;
debug_emac("- emac_open\n");
return(1);
}
/* EMAC Channel Teardown */
static void dm644x_eth_ch_teardown(int ch)
{
dv_reg dly = 0xff;
dv_reg cnt;
debug_emac("+ emac_ch_teardown\n");
if (ch == EMAC_CH_TX) {
/* Init TX channel teardown */
adap_emac->TXTEARDOWN = 1;
for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) {
/* Wait here for Tx teardown completion interrupt to occur
* Note: A task delay can be called here to pend rather than
* occupying CPU cycles - anyway it has been found that teardown
* takes very few cpu cycles and does not affect functionality */
dly--;
udelay(1);
if (dly == 0)
break;
}
adap_emac->TX0CP = cnt;
adap_emac->TX0HDP = 0;
} else {
/* Init RX channel teardown */
adap_emac->RXTEARDOWN = 1;
for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) {
/* Wait here for Rx teardown completion interrupt to occur
* Note: A task delay can be called here to pend rather than
* occupying CPU cycles - anyway it has been found that teardown
* takes very few cpu cycles and does not affect functionality */
dly--;
udelay(1);
if (dly == 0)
break;
}
adap_emac->RX0CP = cnt;
adap_emac->RX0HDP = 0;
}
debug_emac("- emac_ch_teardown\n");
}
/* Eth device close */
static int dm644x_eth_close(void)
{
debug_emac("+ emac_close\n");
dm644x_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */
dm644x_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */
/* Reset EMAC module and disable interrupts in wrapper */
adap_emac->SOFTRESET = 1;
adap_ewrap->EWCTL = 0;
debug_emac("- emac_close\n");
return(1);
}
static int tx_send_loop = 0;
/*
* This function sends a single packet on the network and returns
* positive number (number of bytes transmitted) or negative for error
*/
static int dm644x_eth_send_packet(volatile void *packet, int length)
{
int ret_status = -1;
tx_send_loop = 0;
/* Return error if no link */
if (!phy.get_link_speed(active_phy_addr))
{
printf("WARN: emac_send_packet: No link\n");
return (ret_status);
}
/* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
{
length = EMAC_MIN_ETHERNET_PKT_SIZE;
}
/* Populate the TX descriptor */
emac_tx_desc->next = 0;
emac_tx_desc->buffer = (u_int8_t *)packet;
emac_tx_desc->buff_off_len = (length & 0xffff);
emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
EMAC_CPPI_SOP_BIT |
EMAC_CPPI_OWNERSHIP_BIT |
EMAC_CPPI_EOP_BIT);
/* Send the packet */
adap_emac->TX0HDP = (unsigned int)emac_tx_desc;
/* Wait for packet to complete or link down */
while (1) {
if (!phy.get_link_speed(active_phy_addr)) {
dm644x_eth_ch_teardown(EMAC_CH_TX);
return (ret_status);
}
if (adap_emac->TXINTSTATRAW & 0x01) {
ret_status = length;
break;
}
tx_send_loop++;
}
return(ret_status);
}
/*
* This function handles receipt of a packet from the network
*/
static int dm644x_eth_rcv_packet(void)
{
volatile emac_desc *rx_curr_desc;
volatile emac_desc *curr_desc;
volatile emac_desc *tail_desc;
int status, ret = -1;
rx_curr_desc = emac_rx_active_head;
status = rx_curr_desc->pkt_flag_len;
if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
if (status & EMAC_CPPI_RX_ERROR_FRAME) {
/* Error in packet - discard it and requeue desc */
printf("WARN: emac_rcv_pkt: Error in packet\n");
} else {
NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff));
ret = rx_curr_desc->buff_off_len & 0xffff;
}
/* Ack received packet descriptor */
adap_emac->RX0CP = (unsigned int)rx_curr_desc;
curr_desc = rx_curr_desc;
emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next;
if (status & EMAC_CPPI_EOQ_BIT) {
if (emac_rx_active_head) {
adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
} else {
emac_rx_queue_active = 0;
printf("INFO:emac_rcv_packet: RX Queue not active\n");
}
}
/* Recycle RX descriptor */
rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
rx_curr_desc->next = 0;
if (emac_rx_active_head == 0) {
printf("INFO: emac_rcv_pkt: active queue head = 0\n");
emac_rx_active_head = curr_desc;
emac_rx_active_tail = curr_desc;
if (emac_rx_queue_active != 0) {
adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
emac_rx_queue_active = 1;
}
} else {
tail_desc = emac_rx_active_tail;
emac_rx_active_tail = curr_desc;
tail_desc->next = (unsigned int)curr_desc;
status = tail_desc->pkt_flag_len;
if (status & EMAC_CPPI_EOQ_BIT) {
adap_emac->RX0HDP = (unsigned int)curr_desc;
status &= ~EMAC_CPPI_EOQ_BIT;
tail_desc->pkt_flag_len = status;
}
}
return(ret);
}
return(0);
}
#endif /* CONFIG_CMD_NET */
#endif /* CONFIG_DRIVER_TI_EMAC */

351
cpu/arm926ejs/davinci/i2c.c Normal file
View File

@@ -0,0 +1,351 @@
/*
* TI DaVinci (TMS320DM644x) I2C driver.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* --------------------------------------------------------
*
* 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>
#ifdef CONFIG_DRIVER_DAVINCI_I2C
#include <i2c.h>
#include <asm/arch/hardware.h>
#include <asm/arch/i2c_defs.h>
#define CHECK_NACK() \
do {\
if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\
REG(I2C_CON) = 0;\
return(1);\
}\
} while (0)
static int wait_for_bus(void)
{
int stat, timeout;
REG(I2C_STAT) = 0xffff;
for (timeout = 0; timeout < 10; timeout++) {
if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) {
REG(I2C_STAT) = 0xffff;
return(0);
}
REG(I2C_STAT) = stat;
udelay(50000);
}
REG(I2C_STAT) = 0xffff;
return(1);
}
static int poll_i2c_irq(int mask)
{
int stat, timeout;
for (timeout = 0; timeout < 10; timeout++) {
udelay(1000);
stat = REG(I2C_STAT);
if (stat & mask) {
return(stat);
}
}
REG(I2C_STAT) = 0xffff;
return(stat | I2C_TIMEOUT);
}
void flush_rx(void)
{
int dummy;
while (1) {
if (!(REG(I2C_STAT) & I2C_STAT_RRDY))
break;
dummy = REG(I2C_DRR);
REG(I2C_STAT) = I2C_STAT_RRDY;
udelay(1000);
}
}
void i2c_init(int speed, int slaveadd)
{
u_int32_t div, psc;
if (REG(I2C_CON) & I2C_CON_EN) {
REG(I2C_CON) = 0;
udelay (50000);
}
psc = 2;
div = (CFG_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */
REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */
REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */
REG(I2C_SCLH) = div - REG(I2C_SCLL);
REG(I2C_OA) = slaveadd;
REG(I2C_CNT) = 0;
/* Interrupts must be enabled or I2C module won't work */
REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE |
I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
/* Now enable I2C controller (get it out of reset) */
REG(I2C_CON) = I2C_CON_EN;
udelay(1000);
}
int i2c_probe(u_int8_t chip)
{
int rc = 1;
if (chip == REG(I2C_OA)) {
return(rc);
}
REG(I2C_CON) = 0;
if (wait_for_bus()) {return(1);}
/* try to read one byte from current (or only) address */
REG(I2C_CNT) = 1;
REG(I2C_SA) = chip;
REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP);
udelay (50000);
if (!(REG(I2C_STAT) & I2C_STAT_NACK)) {
rc = 0;
flush_rx();
REG(I2C_STAT) = 0xffff;
} else {
REG(I2C_STAT) = 0xffff;
REG(I2C_CON) |= I2C_CON_STP;
udelay(20000);
if (wait_for_bus()) {return(1);}
}
flush_rx();
REG(I2C_STAT) = 0xffff;
REG(I2C_CNT) = 0;
return(rc);
}
int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
{
u_int32_t tmp;
int i;
if ((alen < 0) || (alen > 2)) {
printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
return(1);
}
if (wait_for_bus()) {return(1);}
if (alen != 0) {
/* Start address phase */
tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX;
REG(I2C_CNT) = alen;
REG(I2C_SA) = chip;
REG(I2C_CON) = tmp;
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
CHECK_NACK();
switch (alen) {
case 2:
/* Send address MSByte */
if (tmp & I2C_STAT_XRDY) {
REG(I2C_DXR) = (addr >> 8) & 0xff;
} else {
REG(I2C_CON) = 0;
return(1);
}
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
CHECK_NACK();
/* No break, fall through */
case 1:
/* Send address LSByte */
if (tmp & I2C_STAT_XRDY) {
REG(I2C_DXR) = addr & 0xff;
} else {
REG(I2C_CON) = 0;
return(1);
}
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY);
CHECK_NACK();
if (!(tmp & I2C_STAT_ARDY)) {
REG(I2C_CON) = 0;
return(1);
}
}
}
/* Address phase is over, now read 'len' bytes and stop */
tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP;
REG(I2C_CNT) = len & 0xffff;
REG(I2C_SA) = chip;
REG(I2C_CON) = tmp;
for (i = 0; i < len; i++) {
tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR);
CHECK_NACK();
if (tmp & I2C_STAT_RRDY) {
buf[i] = REG(I2C_DRR);
} else {
REG(I2C_CON) = 0;
return(1);
}
}
tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
CHECK_NACK();
if (!(tmp & I2C_STAT_SCD)) {
REG(I2C_CON) = 0;
return(1);
}
flush_rx();
REG(I2C_STAT) = 0xffff;
REG(I2C_CNT) = 0;
REG(I2C_CON) = 0;
return(0);
}
int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
{
u_int32_t tmp;
int i;
if ((alen < 0) || (alen > 2)) {
printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
return(1);
}
if (len < 0) {
printf("%s(): bogus length %x\n", __FUNCTION__, len);
return(1);
}
if (wait_for_bus()) {return(1);}
/* Start address phase */
tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP;
REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen;
REG(I2C_SA) = chip;
REG(I2C_CON) = tmp;
switch (alen) {
case 2:
/* Send address MSByte */
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
CHECK_NACK();
if (tmp & I2C_STAT_XRDY) {
REG(I2C_DXR) = (addr >> 8) & 0xff;
} else {
REG(I2C_CON) = 0;
return(1);
}
/* No break, fall through */
case 1:
/* Send address LSByte */
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
CHECK_NACK();
if (tmp & I2C_STAT_XRDY) {
REG(I2C_DXR) = addr & 0xff;
} else {
REG(I2C_CON) = 0;
return(1);
}
}
for (i = 0; i < len; i++) {
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
CHECK_NACK();
if (tmp & I2C_STAT_XRDY) {
REG(I2C_DXR) = buf[i];
} else {
return(1);
}
}
tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
CHECK_NACK();
if (!(tmp & I2C_STAT_SCD)) {
REG(I2C_CON) = 0;
return(1);
}
flush_rx();
REG(I2C_STAT) = 0xffff;
REG(I2C_CNT) = 0;
REG(I2C_CON) = 0;
return(0);
}
u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg)
{
u_int8_t tmp;
i2c_read(chip, reg, 1, &tmp, 1);
return(tmp);
}
void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val)
{
u_int8_t tmp;
i2c_write(chip, reg, 1, &tmp, 1);
}
#endif /* CONFIG_DRIVER_DAVINCI_I2C */

View File

@@ -0,0 +1,707 @@
/*
* Low-level board setup code for TI DaVinci SoC based boards.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* Partially based on TI sources, original copyrights follow:
*/
/*
* Board specific setup info
*
* (C) Copyright 2003
* Texas Instruments, <www.ti.com>
* Kshitij Gupta <Kshitij@ti.com>
*
* Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004
*
* Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004
* See file CREDITS for list of people who contributed to this
* project.
*
* Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005
* See file CREDITS for list of people who contributed to this
* project.
*
* Modified for DV-EVM board by Swaminathan S, Nov 2005
* 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 <config.h>
.globl lowlevel_init
lowlevel_init:
/*-------------------------------------------------------*
* Mask all IRQs by setting all bits in the EINT default *
*-------------------------------------------------------*/
mov r1, $0
ldr r0, =EINT_ENABLE0
str r1, [r0]
ldr r0, =EINT_ENABLE1
str r1, [r0]
/*------------------------------------------------------*
* Put the GEM in reset *
*------------------------------------------------------*/
/* Put the GEM in reset */
ldr r8, PSC_GEM_FLAG_CLEAR
ldr r6, MDCTL_GEM
ldr r7, [r6]
and r7, r7, r8
str r7, [r6]
/* Enable the Power Domain Transition Command */
ldr r6, PTCMD
ldr r7, [r6]
orr r7, r7, $0x02
str r7, [r6]
/* Check for Transition Complete(PTSTAT) */
checkStatClkStopGem:
ldr r6, PTSTAT
ldr r7, [r6]
ands r7, r7, $0x02
bne checkStatClkStopGem
/* Check for GEM Reset Completion */
checkGemStatClkStop:
ldr r6, MDSTAT_GEM
ldr r7, [r6]
ands r7, r7, $0x100
bne checkGemStatClkStop
/* Do this for enabling a WDT initiated reset this is a workaround
for a chip bug. Not required under normal situations */
ldr r6, P1394
mov r10, $0
str r10, [r6]
/*------------------------------------------------------*
* Enable L1 & L2 Memories in Fast mode *
*------------------------------------------------------*/
ldr r6, DFT_ENABLE
mov r10, $0x01
str r10, [r6]
ldr r6, MMARG_BRF0
ldr r10, MMARG_BRF0_VAL
str r10, [r6]
ldr r6, DFT_ENABLE
mov r10, $0
str r10, [r6]
/*------------------------------------------------------*
* DDR2 PLL Initialization *
*------------------------------------------------------*/
/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
mov r10, $0
ldr r6, PLL2_CTL
ldr r7, PLL_CLKSRC_MASK
ldr r8, [r6]
and r8, r8, r7
mov r9, r10, lsl $8
orr r8, r8, r9
str r8, [r6]
/* Select the PLLEN source */
ldr r7, PLL_ENSRC_MASK
and r8, r8, r7
str r8, [r6]
/* Bypass the PLL */
ldr r7, PLL_BYPASS_MASK
and r8, r8, r7
str r8, [r6]
/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
mov r10, $0x20
WaitPPL2Loop:
subs r10, r10, $1
bne WaitPPL2Loop
/* Reset the PLL */
ldr r7, PLL_RESET_MASK
and r8, r8, r7
str r8, [r6]
/* Power up the PLL */
ldr r7, PLL_PWRUP_MASK
and r8, r8, r7
str r8, [r6]
/* Enable the PLL from Disable Mode */
ldr r7, PLL_DISABLE_ENABLE_MASK
and r8, r8, r7
str r8, [r6]
/* Program the PLL Multiplier */
ldr r6, PLL2_PLLM
mov r2, $0x17 /* 162 MHz */
str r2, [r6]
/* Program the PLL2 Divisor Value */
ldr r6, PLL2_DIV2
mov r3, $0x01
str r3, [r6]
/* Program the PLL2 Divisor Value */
ldr r6, PLL2_DIV1
mov r4, $0x0b /* 54 MHz */
str r4, [r6]
/* PLL2 DIV2 MMR */
ldr r8, PLL2_DIV_MASK
ldr r6, PLL2_DIV2
ldr r9, [r6]
and r8, r8, r9
mov r9, $0x01
mov r9, r9, lsl $15
orr r8, r8, r9
str r8, [r6]
/* Program the GOSET bit to take new divider values */
ldr r6, PLL2_PLLCMD
ldr r7, [r6]
orr r7, r7, $0x01
str r7, [r6]
/* Wait for Done */
ldr r6, PLL2_PLLSTAT
doneLoop_0:
ldr r7, [r6]
ands r7, r7, $0x01
bne doneLoop_0
/* PLL2 DIV1 MMR */
ldr r8, PLL2_DIV_MASK
ldr r6, PLL2_DIV1
ldr r9, [r6]
and r8, r8, r9
mov r9, $0x01
mov r9, r9, lsl $15
orr r8, r8, r9
str r8, [r6]
/* Program the GOSET bit to take new divider values */
ldr r6, PLL2_PLLCMD
ldr r7, [r6]
orr r7, r7, $0x01
str r7, [r6]
/* Wait for Done */
ldr r6, PLL2_PLLSTAT
doneLoop:
ldr r7, [r6]
ands r7, r7, $0x01
bne doneLoop
/* Wait for PLL to Reset Properly */
mov r10, $0x218
ResetPPL2Loop:
subs r10, r10, $1
bne ResetPPL2Loop
/* Bring PLL out of Reset */
ldr r6, PLL2_CTL
ldr r8, [r6]
orr r8, r8, $0x08
str r8, [r6]
/* Wait for PLL to Lock */
ldr r10, PLL_LOCK_COUNT
PLL2Lock:
subs r10, r10, $1
bne PLL2Lock
/* Enable the PLL */
ldr r6, PLL2_CTL
ldr r8, [r6]
orr r8, r8, $0x01
str r8, [r6]
/*------------------------------------------------------*
* Issue Soft Reset to DDR Module *
*------------------------------------------------------*/
/* Shut down the DDR2 LPSC Module */
ldr r8, PSC_FLAG_CLEAR
ldr r6, MDCTL_DDR2
ldr r7, [r6]
and r7, r7, r8
orr r7, r7, $0x03
str r7, [r6]
/* Enable the Power Domain Transition Command */
ldr r6, PTCMD
ldr r7, [r6]
orr r7, r7, $0x01
str r7, [r6]
/* Check for Transition Complete(PTSTAT) */
checkStatClkStop:
ldr r6, PTSTAT
ldr r7, [r6]
ands r7, r7, $0x01
bne checkStatClkStop
/* Check for DDR2 Controller Enable Completion */
checkDDRStatClkStop:
ldr r6, MDSTAT_DDR2
ldr r7, [r6]
and r7, r7, $0x1f
cmp r7, $0x03
bne checkDDRStatClkStop
/*------------------------------------------------------*
* Program DDR2 MMRs for 162MHz Setting *
*------------------------------------------------------*/
/* Program PHY Control Register */
ldr r6, DDRCTL
ldr r7, DDRCTL_VAL
str r7, [r6]
/* Program SDRAM Bank Config Register */
ldr r6, SDCFG
ldr r7, SDCFG_VAL
str r7, [r6]
/* Program SDRAM TIM-0 Config Register */
ldr r6, SDTIM0
ldr r7, SDTIM0_VAL_162MHz
str r7, [r6]
/* Program SDRAM TIM-1 Config Register */
ldr r6, SDTIM1
ldr r7, SDTIM1_VAL_162MHz
str r7, [r6]
/* Program the SDRAM Bank Config Control Register */
ldr r10, MASK_VAL
ldr r8, SDCFG
ldr r9, SDCFG_VAL
and r9, r9, r10
str r9, [r8]
/* Program SDRAM SDREF Config Register */
ldr r6, SDREF
ldr r7, SDREF_VAL
str r7, [r6]
/*------------------------------------------------------*
* Issue Soft Reset to DDR Module *
*------------------------------------------------------*/
/* Issue a Dummy DDR2 read/write */
ldr r8, DDR2_START_ADDR
ldr r7, DUMMY_VAL
str r7, [r8]
ldr r7, [r8]
/* Shut down the DDR2 LPSC Module */
ldr r8, PSC_FLAG_CLEAR
ldr r6, MDCTL_DDR2
ldr r7, [r6]
and r7, r7, r8
orr r7, r7, $0x01
str r7, [r6]
/* Enable the Power Domain Transition Command */
ldr r6, PTCMD
ldr r7, [r6]
orr r7, r7, $0x01
str r7, [r6]
/* Check for Transition Complete(PTSTAT) */
checkStatClkStop2:
ldr r6, PTSTAT
ldr r7, [r6]
ands r7, r7, $0x01
bne checkStatClkStop2
/* Check for DDR2 Controller Enable Completion */
checkDDRStatClkStop2:
ldr r6, MDSTAT_DDR2
ldr r7, [r6]
and r7, r7, $0x1f
cmp r7, $0x01
bne checkDDRStatClkStop2
/*------------------------------------------------------*
* Turn DDR2 Controller Clocks On *
*------------------------------------------------------*/
/* Enable the DDR2 LPSC Module */
ldr r6, MDCTL_DDR2
ldr r7, [r6]
orr r7, r7, $0x03
str r7, [r6]
/* Enable the Power Domain Transition Command */
ldr r6, PTCMD
ldr r7, [r6]
orr r7, r7, $0x01
str r7, [r6]
/* Check for Transition Complete(PTSTAT) */
checkStatClkEn2:
ldr r6, PTSTAT
ldr r7, [r6]
ands r7, r7, $0x01
bne checkStatClkEn2
/* Check for DDR2 Controller Enable Completion */
checkDDRStatClkEn2:
ldr r6, MDSTAT_DDR2
ldr r7, [r6]
and r7, r7, $0x1f
cmp r7, $0x03
bne checkDDRStatClkEn2
/* DDR Writes and Reads */
ldr r6, CFGTEST
mov r3, $0x01
str r3, [r6]
/*------------------------------------------------------*
* System PLL Initialization *
*------------------------------------------------------*/
/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
mov r2, $0
ldr r6, PLL1_CTL
ldr r7, PLL_CLKSRC_MASK
ldr r8, [r6]
and r8, r8, r7
mov r9, r2, lsl $8
orr r8, r8, r9
str r8, [r6]
/* Select the PLLEN source */
ldr r7, PLL_ENSRC_MASK
and r8, r8, r7
str r8, [r6]
/* Bypass the PLL */
ldr r7, PLL_BYPASS_MASK
and r8, r8, r7
str r8, [r6]
/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
mov r10, $0x20
WaitLoop:
subs r10, r10, $1
bne WaitLoop
/* Reset the PLL */
ldr r7, PLL_RESET_MASK
and r8, r8, r7
str r8, [r6]
/* Disable the PLL */
orr r8, r8, $0x10
str r8, [r6]
/* Power up the PLL */
ldr r7, PLL_PWRUP_MASK
and r8, r8, r7
str r8, [r6]
/* Enable the PLL from Disable Mode */
ldr r7, PLL_DISABLE_ENABLE_MASK
and r8, r8, r7
str r8, [r6]
/* Program the PLL Multiplier */
ldr r6, PLL1_PLLM
mov r3, $0x15 /* For 594MHz */
str r3, [r6]
/* Wait for PLL to Reset Properly */
mov r10, $0xff
ResetLoop:
subs r10, r10, $1
bne ResetLoop
/* Bring PLL out of Reset */
ldr r6, PLL1_CTL
orr r8, r8, $0x08
str r8, [r6]
/* Wait for PLL to Lock */
ldr r10, PLL_LOCK_COUNT
PLL1Lock:
subs r10, r10, $1
bne PLL1Lock
/* Enable the PLL */
orr r8, r8, $0x01
str r8, [r6]
nop
nop
nop
nop
/*------------------------------------------------------*
* AEMIF configuration for NOR Flash (double check) *
*------------------------------------------------------*/
ldr r0, _PINMUX0
ldr r1, _DEV_SETTING
str r1, [r0]
ldr r0, WAITCFG
ldr r1, WAITCFG_VAL
ldr r2, [r0]
orr r2, r2, r1
str r2, [r0]
ldr r0, ACFG3
ldr r1, ACFG3_VAL
ldr r2, [r0]
and r1, r2, r1
str r1, [r0]
ldr r0, ACFG4
ldr r1, ACFG4_VAL
ldr r2, [r0]
and r1, r2, r1
str r1, [r0]
ldr r0, ACFG5
ldr r1, ACFG5_VAL
ldr r2, [r0]
and r1, r2, r1
str r1, [r0]
/*--------------------------------------*
* VTP manual Calibration *
*--------------------------------------*/
ldr r0, VTPIOCR
ldr r1, VTP_MMR0
str r1, [r0]
ldr r0, VTPIOCR
ldr r1, VTP_MMR1
str r1, [r0]
/* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */
ldr r10, VTP_LOCK_COUNT
VTPLock:
subs r10, r10, $1
bne VTPLock
ldr r6, DFT_ENABLE
mov r10, $0x01
str r10, [r6]
ldr r6, DDRVTPR
ldr r7, [r6]
and r7, r7, $0x1f
and r8, r7, $0x3e0
orr r8, r7, r8
ldr r7, VTP_RECAL
orr r8, r7, r8
ldr r7, VTP_EN
orr r8, r7, r8
str r8, [r0]
/* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */
ldr r10, VTP_LOCK_COUNT
VTP1Lock:
subs r10, r10, $1
bne VTP1Lock
ldr r1, [r0]
ldr r2, VTP_MASK
and r2, r1, r2
str r2, [r0]
ldr r6, DFT_ENABLE
mov r10, $0
str r10, [r6]
/*
* Call board-specific lowlevel init.
* That MUST be present and THAT returns
* back to arch calling code with "mov pc, lr."
*/
b dv_board_init
.ltorg
_PINMUX0:
.word 0x01c40000 /* Device Configuration Registers */
_PINMUX1:
.word 0x01c40004 /* Device Configuration Registers */
_DEV_SETTING:
.word 0x00000c1f
WAITCFG:
.word 0x01e00004
WAITCFG_VAL:
.word 0
ACFG3:
.word 0x01e00014
ACFG3_VAL:
.word 0x3ffffffd
ACFG4:
.word 0x01e00018
ACFG4_VAL:
.word 0x3ffffffd
ACFG5:
.word 0x01e0001c
ACFG5_VAL:
.word 0x3ffffffd
MDCTL_DDR2:
.word 0x01c41a34
MDSTAT_DDR2:
.word 0x01c41834
PTCMD:
.word 0x01c41120
PTSTAT:
.word 0x01c41128
EINT_ENABLE0:
.word 0x01c48018
EINT_ENABLE1:
.word 0x01c4801c
PSC_FLAG_CLEAR:
.word 0xffffffe0
PSC_GEM_FLAG_CLEAR:
.word 0xfffffeff
/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */
DDRCTL:
.word 0x200000e4
DDRCTL_VAL:
.word 0x50006405
SDREF:
.word 0x2000000c
SDREF_VAL:
.word 0x000005c3
SDCFG:
.word 0x20000008
SDCFG_VAL:
#ifdef DDR_4BANKS
.word 0x00178622
#elif defined DDR_8BANKS
.word 0x00178632
#else
#error "Unknown DDR configuration!!!"
#endif
SDTIM0:
.word 0x20000010
SDTIM0_VAL_162MHz:
.word 0x28923211
SDTIM1:
.word 0x20000014
SDTIM1_VAL_162MHz:
.word 0x0016c722
VTPIOCR:
.word 0x200000f0 /* VTP IO Control register */
DDRVTPR:
.word 0x01c42030 /* DDR VPTR MMR */
VTP_MMR0:
.word 0x201f
VTP_MMR1:
.word 0xa01f
DFT_ENABLE:
.word 0x01c4004c
VTP_LOCK_COUNT:
.word 0x5b0
VTP_MASK:
.word 0xffffdfff
VTP_RECAL:
.word 0x40000
VTP_EN:
.word 0x02000
CFGTEST:
.word 0x80010000
MASK_VAL:
.word 0x00000fff
/* GEM Power Up & LPSC Control Register */
MDCTL_GEM:
.word 0x01c41a9c
MDSTAT_GEM:
.word 0x01c4189c
/* For WDT reset chip bug */
P1394:
.word 0x01c41a20
PLL_CLKSRC_MASK:
.word 0xfffffeff /* Mask the Clock Mode bit */
PLL_ENSRC_MASK:
.word 0xffffffdf /* Select the PLLEN source */
PLL_BYPASS_MASK:
.word 0xfffffffe /* Put the PLL in BYPASS */
PLL_RESET_MASK:
.word 0xfffffff7 /* Put the PLL in Reset Mode */
PLL_PWRUP_MASK:
.word 0xfffffffd /* PLL Power up Mask Bit */
PLL_DISABLE_ENABLE_MASK:
.word 0xffffffef /* Enable the PLL from Disable */
PLL_LOCK_COUNT:
.word 0x2000
/* PLL1-SYSTEM PLL MMRs */
PLL1_CTL:
.word 0x01c40900
PLL1_PLLM:
.word 0x01c40910
/* PLL2-SYSTEM PLL MMRs */
PLL2_CTL:
.word 0x01c40d00
PLL2_PLLM:
.word 0x01c40d10
PLL2_DIV1:
.word 0x01c40d18
PLL2_DIV2:
.word 0x01c40d1c
PLL2_PLLCMD:
.word 0x01c40d38
PLL2_PLLSTAT:
.word 0x01c40d3c
PLL2_DIV_MASK:
.word 0xffff7fff
MMARG_BRF0:
.word 0x01c42010 /* BRF margin mode 0 (R/W)*/
MMARG_BRF0_VAL:
.word 0x00444400
DDR2_START_ADDR:
.word 0x80000000
DUMMY_VAL:
.word 0xa55aa55a

View File

@@ -0,0 +1,142 @@
/*
* Intel LXT971/LXT972 PHY Driver for TI DaVinci
* (TMS320DM644x) based boards.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* --------------------------------------------------------
*
* 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 <net.h>
#include <lxt971a.h>
#include <asm/arch/emac_defs.h>
#ifdef CONFIG_DRIVER_TI_EMAC
#ifdef CONFIG_CMD_NET
int lxt972_is_phy_connected(int phy_addr)
{
u_int16_t id1, id2;
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID1, &id1))
return(0);
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID2, &id2))
return(0);
if ((id1 == (0x0013)) && ((id2 & 0xfff0) == 0x78e0))
return(1);
return(0);
}
int lxt972_get_link_speed(int phy_addr)
{
u_int16_t stat1, tmp;
volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR;
if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1))
return(0);
if (!(stat1 & PHY_LXT971_STAT2_LINK)) /* link up? */
return(0);
if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
return(0);
tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE;
dm644x_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp);
/* Read back */
if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
return(0);
/* Speed doesn't matter, there is no setting for it in EMAC... */
if (stat1 & PHY_LXT971_STAT2_100BTX) {
if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
/* set DM644x EMAC for Full Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
} else {
/*set DM644x EMAC for Half Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
}
return(1);
} else {
if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
/* set DM644x EMAC for Full Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
} else {
/*set DM644x EMAC for Half Duplex */
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
}
return(1);
}
return(0);
}
int lxt972_init_phy(int phy_addr)
{
int ret = 1;
if (!lxt972_get_link_speed(phy_addr)) {
/* Try another time */
ret = lxt972_get_link_speed(phy_addr);
}
/* Disable PHY Interrupts */
dm644x_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0);
return(ret);
}
int lxt972_auto_negotiate(int phy_addr)
{
u_int16_t tmp;
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_CTRL, &tmp))
return(0);
/* Restart Auto_negotiation */
tmp |= PHY_COMMON_CTRL_RES_AUTO;
dm644x_eth_phy_write(phy_addr, PHY_COMMON_CTRL, tmp);
/*check AutoNegotiate complete */
udelay (10000);
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_STAT, &tmp))
return(0);
if (!(tmp & PHY_COMMON_STAT_AN_COMP))
return(0);
return (lxt972_get_link_speed(phy_addr));
}
#endif /* CONFIG_CMD_NET */
#endif /* CONFIG_DRIVER_ETHER */

View File

@@ -0,0 +1,389 @@
/*
* NAND driver for TI DaVinci based boards.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* Based on Linux DaVinci NAND driver by TI. Original copyright follows:
*/
/*
*
* linux/drivers/mtd/nand/nand_davinci.c
*
* NAND Flash Driver
*
* Copyright (C) 2006 Texas Instruments.
*
* ----------------------------------------------------------------------------
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* ----------------------------------------------------------------------------
*
* Overview:
* This is a device driver for the NAND flash device found on the
* DaVinci board which utilizes the Samsung k9k2g08 part.
*
Modifications:
ver. 1.0: Feb 2005, Vinod/Sudhakar
-
*
*/
#include <common.h>
#ifdef CFG_USE_NAND
#if !defined(CFG_NAND_LEGACY)
#include <nand.h>
#include <asm/arch/nand_defs.h>
#include <asm/arch/emif_defs.h>
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd)
{
struct nand_chip *this = mtd->priv;
u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
switch (cmd) {
case NAND_CTL_SETCLE:
IO_ADDR_W |= MASK_CLE;
break;
case NAND_CTL_SETALE:
IO_ADDR_W |= MASK_ALE;
break;
}
this->IO_ADDR_W = (void *)IO_ADDR_W;
}
/* Set WP on deselect, write enable on select */
static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
{
#define GPIO_SET_DATA01 0x01c67018
#define GPIO_CLR_DATA01 0x01c6701c
#define GPIO_NAND_WP (1 << 4)
#ifdef SONATA_BOARD_GPIOWP
if (chip < 0) {
REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
} else {
REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
}
#endif
}
#ifdef CFG_NAND_HW_ECC
#ifdef CFG_NAND_LARGEPAGE
static struct nand_oobinfo davinci_nand_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 12,
.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
.oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} }
};
#elif defined(CFG_NAND_SMALLPAGE)
static struct nand_oobinfo davinci_nand_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 3,
.eccpos = {0, 1, 2},
.oobfree = { {6, 2}, {8, 8} }
};
#else
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
#endif
static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
{
emifregs emif_addr;
int dummy;
emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
dummy = emif_addr->NANDF1ECC;
dummy = emif_addr->NANDF2ECC;
dummy = emif_addr->NANDF3ECC;
dummy = emif_addr->NANDF4ECC;
emif_addr->NANDFCR |= (1 << 8);
}
static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
{
u_int32_t ecc = 0;
emifregs emif_base_addr;
emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
if (region == 1)
ecc = emif_base_addr->NANDF1ECC;
else if (region == 2)
ecc = emif_base_addr->NANDF2ECC;
else if (region == 3)
ecc = emif_base_addr->NANDF3ECC;
else if (region == 4)
ecc = emif_base_addr->NANDF4ECC;
return(ecc);
}
static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
{
u_int32_t tmp;
int region, n;
struct nand_chip *this = mtd->priv;
n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
region = 1;
while (n--) {
tmp = nand_davinci_readecc(mtd, region);
*ecc_code++ = tmp;
*ecc_code++ = tmp >> 16;
*ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
region++;
}
return(0);
}
static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
{
u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
}
static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
{
u_int32_t i;
u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8];
u_int8_t ecc_bit[24];
u_int8_t ecc_sum = 0;
u_int8_t find_bit = 0;
u_int32_t find_byte = 0;
int is_ecc_ff;
is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
nand_davinci_gen_true_ecc(ecc_nand);
nand_davinci_gen_true_ecc(ecc_calc);
for (i = 0; i <= 2; i++) {
*(ecc_nand + i) = ~(*(ecc_nand + i));
*(ecc_calc + i) = ~(*(ecc_calc + i));
}
for (i = 0; i < 8; i++) {
tmp0_bit[i] = *ecc_nand % 2;
*ecc_nand = *ecc_nand / 2;
}
for (i = 0; i < 8; i++) {
tmp1_bit[i] = *(ecc_nand + 1) % 2;
*(ecc_nand + 1) = *(ecc_nand + 1) / 2;
}
for (i = 0; i < 8; i++) {
tmp2_bit[i] = *(ecc_nand + 2) % 2;
*(ecc_nand + 2) = *(ecc_nand + 2) / 2;
}
for (i = 0; i < 8; i++) {
comp0_bit[i] = *ecc_calc % 2;
*ecc_calc = *ecc_calc / 2;
}
for (i = 0; i < 8; i++) {
comp1_bit[i] = *(ecc_calc + 1) % 2;
*(ecc_calc + 1) = *(ecc_calc + 1) / 2;
}
for (i = 0; i < 8; i++) {
comp2_bit[i] = *(ecc_calc + 2) % 2;
*(ecc_calc + 2) = *(ecc_calc + 2) / 2;
}
for (i = 0; i< 6; i++)
ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
for (i = 0; i < 8; i++)
ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
for (i = 0; i < 8; i++)
ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
for (i = 0; i < 24; i++)
ecc_sum += ecc_bit[i];
switch (ecc_sum) {
case 0:
/* Not reached because this function is not called if
ECC values are equal */
return 0;
case 1:
/* Uncorrectable error */
DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
return(-1);
case 12:
/* Correctable error */
find_byte = (ecc_bit[23] << 8) +
(ecc_bit[21] << 7) +
(ecc_bit[19] << 6) +
(ecc_bit[17] << 5) +
(ecc_bit[15] << 4) +
(ecc_bit[13] << 3) +
(ecc_bit[11] << 2) +
(ecc_bit[9] << 1) +
ecc_bit[7];
find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit);
page_data[find_byte] ^= (1 << find_bit);
return(0);
default:
if (is_ecc_ff) {
if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
return(0);
}
DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
return(-1);
}
}
static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
{
struct nand_chip *this;
int block_count = 0, i, rc;
this = mtd->priv;
block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
for (i = 0; i < block_count; i++) {
if (memcmp(read_ecc, calc_ecc, 3) != 0) {
rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
if (rc < 0) {
return(rc);
}
}
read_ecc += 3;
calc_ecc += 3;
dat += 512;
}
return(0);
}
#endif
static int nand_davinci_dev_ready(struct mtd_info *mtd)
{
emifregs emif_addr;
emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
return(emif_addr->NANDFSR & 0x1);
}
static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
{
while(!nand_davinci_dev_ready(mtd)) {;}
*NAND_CE0CLE = NAND_STATUS;
return(*NAND_CE0DATA);
}
static void nand_flash_init(void)
{
u_int32_t acfg1 = 0x3ffffffc;
u_int32_t acfg2 = 0x3ffffffc;
u_int32_t acfg3 = 0x3ffffffc;
u_int32_t acfg4 = 0x3ffffffc;
emifregs emif_regs;
/*------------------------------------------------------------------*
* NAND FLASH CHIP TIMEOUT @ 459 MHz *
* *
* AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz *
* AEMIF.CLK period = 1/76.5 MHz = 13.1 ns *
* *
*------------------------------------------------------------------*/
acfg1 = 0
| (0 << 31 ) /* selectStrobe */
| (0 << 30 ) /* extWait */
| (1 << 26 ) /* writeSetup 10 ns */
| (3 << 20 ) /* writeStrobe 40 ns */
| (1 << 17 ) /* writeHold 10 ns */
| (1 << 13 ) /* readSetup 10 ns */
| (5 << 7 ) /* readStrobe 60 ns */
| (1 << 4 ) /* readHold 10 ns */
| (3 << 2 ) /* turnAround ?? ns */
| (0 << 0 ) /* asyncSize 8-bit bus */
;
emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
emif_regs->AWCCR |= 0x10000000;
emif_regs->AB1CR = acfg1; /* 0x08244128 */;
emif_regs->AB2CR = acfg2;
emif_regs->AB3CR = acfg3;
emif_regs->AB4CR = acfg4;
emif_regs->NANDFCR = 0x00000101;
}
int board_nand_init(struct nand_chip *nand)
{
nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA;
nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA;
nand->chip_delay = 0;
nand->select_chip = nand_davinci_select_chip;
#ifdef CFG_NAND_USE_FLASH_BBT
nand->options = NAND_USE_FLASH_BBT;
#endif
#ifdef CFG_NAND_HW_ECC
#ifdef CFG_NAND_LARGEPAGE
nand->eccmode = NAND_ECC_HW12_2048;
#elif defined(CFG_NAND_SMALLPAGE)
nand->eccmode = NAND_ECC_HW3_512;
#else
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
#endif
nand->autooob = &davinci_nand_oobinfo;
nand->calculate_ecc = nand_davinci_calculate_ecc;
nand->correct_data = nand_davinci_correct_data;
nand->enable_hwecc = nand_davinci_enable_hwecc;
#else
nand->eccmode = NAND_ECC_SOFT;
#endif
/* Set address of hardware control function */
nand->hwcontrol = nand_davinci_hwcontrol;
nand->dev_ready = nand_davinci_dev_ready;
nand->waitfunc = nand_davinci_waitfunc;
nand_flash_init();
return(0);
}
#else
#error "U-Boot legacy NAND support not available for DaVinci chips"
#endif
#endif /* CFG_USE_NAND */

View File

@@ -0,0 +1,77 @@
/*
* Processor reset using WDT for TI TMS320DM644x SoC.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* -----------------------------------------------------
*
* 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
*/
.globl reset_cpu
reset_cpu:
ldr r0, WDT_TGCR
mov r1, $0x08
str r1, [r0]
ldr r1, [r0]
orr r1, r1, $0x03
str r1, [r0]
mov r1, $0
ldr r0, WDT_TIM12
str r1, [r0]
ldr r0, WDT_TIM34
str r1, [r0]
ldr r0, WDT_PRD12
str r1, [r0]
ldr r0, WDT_PRD34
str r1, [r0]
ldr r0, WDT_TCR
ldr r1, [r0]
orr r1, r1, $0x40
str r1, [r0]
ldr r0, WDT_WDTCR
ldr r1, [r0]
orr r1, r1, $0x4000
str r1, [r0]
ldr r1, WDTCR_VAL1
str r1, [r0]
ldr r1, WDTCR_VAL2
str r1, [r0]
nop
nop
nop
nop
reset_cpu_loop:
b reset_cpu_loop
WDT_TGCR:
.word 0x01c21c24
WDT_TIM12:
.word 0x01c21c10
WDT_TIM34:
.word 0x01c21c14
WDT_PRD12:
.word 0x01c21c18
WDT_PRD34:
.word 0x01c21c1c
WDT_TCR:
.word 0x01c21c20
WDT_WDTCR:
.word 0x01c21c28
WDTCR_VAL1:
.word 0xa5c64000
WDTCR_VAL2:
.word 0xda7e4000

View File

@@ -0,0 +1,165 @@
/*
* (C) Copyright 2003
* Texas Instruments <www.ti.com>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
*
* (C) Copyright 2002-2004
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* (C) Copyright 2004
* Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* 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 <arm926ejs.h>
typedef volatile struct {
u_int32_t pid12;
u_int32_t emumgt_clksped;
u_int32_t gpint_en;
u_int32_t gpdir_dat;
u_int32_t tim12;
u_int32_t tim34;
u_int32_t prd12;
u_int32_t prd34;
u_int32_t tcr;
u_int32_t tgcr;
u_int32_t wdtcr;
u_int32_t tlgc;
u_int32_t tlmr;
} davinci_timer;
davinci_timer *timer = (davinci_timer *)CFG_TIMERBASE;
#define TIMER_LOAD_VAL (CFG_HZ_CLOCK / CFG_HZ)
#define READ_TIMER timer->tim34
static ulong timestamp;
static ulong lastinc;
int timer_init(void)
{
/* We are using timer34 in unchained 32-bit mode, full speed */
timer->tcr = 0x0;
timer->tgcr = 0x0;
timer->tgcr = 0x06;
timer->tim34 = 0x0;
timer->prd34 = TIMER_LOAD_VAL;
lastinc = 0;
timer->tcr = 0x80 << 16;
timestamp = 0;
return(0);
}
void reset_timer(void)
{
reset_timer_masked();
}
ulong get_timer(ulong base)
{
return(get_timer_masked() - base);
}
void set_timer(ulong t)
{
timestamp = t;
}
void udelay(unsigned long usec)
{
udelay_masked(usec);
}
void reset_timer_masked(void)
{
lastinc = READ_TIMER;
timestamp = 0;
}
ulong get_timer_raw(void)
{
ulong now = READ_TIMER;
if (now >= lastinc) {
/* normal mode */
timestamp += now - lastinc;
} else {
/* overflow ... */
timestamp += now + TIMER_LOAD_VAL - lastinc;
}
lastinc = now;
return timestamp;
}
ulong get_timer_masked(void)
{
return(get_timer_raw() / TIMER_LOAD_VAL);
}
void udelay_masked(unsigned long usec)
{
ulong tmo;
ulong endtime;
signed long diff;
tmo = CFG_HZ_CLOCK / 1000;
tmo *= usec;
tmo /= 1000;
endtime = get_timer_raw() + tmo;
do {
ulong now = get_timer_raw();
diff = endtime - now;
} while (diff >= 0);
}
/*
* This function is derived from PowerPC code (read timebase as long long).
* On ARM it just returns the timer value.
*/
unsigned long long get_ticks(void)
{
return(get_timer(0));
}
/*
* This function is derived from PowerPC code (timebase clock frequency).
* On ARM it returns the number of timer ticks per second.
*/
ulong get_tbclk(void)
{
ulong tbclk;
tbclk = CFG_HZ;
return(tbclk);
}

View File

@@ -56,6 +56,7 @@
#define MMC_DEFAULT_RCA 1
static unsigned int mmc_rca;
static int mmc_card_is_sd;
static block_dev_desc_t mmc_blkdev;
block_dev_desc_t *mmc_get_dev(int dev)
@@ -82,7 +83,9 @@ static void mci_set_mode(unsigned long hz, unsigned long blklen)
blklen &= 0xfffc;
mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv)
| MMCI_BF(BLKLEN, blklen)));
| MMCI_BF(BLKLEN, blklen)
| MMCI_BIT(RDPROOF)
| MMCI_BIT(WRPROOF)));
}
#define RESP_NO_CRC 1
@@ -225,7 +228,7 @@ mmc_bread(int dev, unsigned long start, lbaint_t blkcnt,
*buffer++ = data;
wordcount++;
}
} while(wordcount < (512 / 4));
} while(wordcount < (mmc_blkdev.blksz / 4));
pr_debug("mmc: read %u words, waiting for BLKE\n", wordcount);
@@ -243,7 +246,7 @@ out:
fail:
mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 | NCR);
printf("mmc: bread failed, card status = ", card_status);
printf("mmc: bread failed, card status = %08x\n", card_status);
goto out;
}
@@ -371,6 +374,7 @@ static int sd_init_card(struct mmc_cid *cid, int verbose)
mmc_rca = resp[0] >> 16;
if (verbose)
printf("SD Card detected (RCA %u)\n", mmc_rca);
mmc_card_is_sd = 1;
return 0;
}
@@ -405,10 +409,64 @@ static int mmc_init_card(struct mmc_cid *cid, int verbose)
return ret;
}
static void mci_set_data_timeout(struct mmc_csd *csd)
{
static const unsigned int dtomul_to_shift[] = {
0, 4, 7, 8, 10, 12, 16, 20,
};
static const unsigned int taac_exp[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
};
static const unsigned int taac_mant[] = {
0, 10, 12, 13, 15, 60, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
unsigned int timeout_ns, timeout_clks;
unsigned int e, m;
unsigned int dtocyc, dtomul;
unsigned int shift;
u32 dtor;
e = csd->taac & 0x07;
m = (csd->taac >> 3) & 0x0f;
timeout_ns = (taac_exp[e] * taac_mant[m] + 9) / 10;
timeout_clks = csd->nsac * 100;
timeout_clks += (((timeout_ns + 9) / 10)
* ((CFG_MMC_CLK_PP + 99999) / 100000) + 9999) / 10000;
if (!mmc_card_is_sd)
timeout_clks *= 10;
else
timeout_clks *= 100;
dtocyc = timeout_clks;
dtomul = 0;
while (dtocyc > 15 && dtomul < 8) {
dtomul++;
shift = dtomul_to_shift[dtomul];
dtocyc = (timeout_clks + (1 << shift) - 1) >> shift;
}
if (dtomul >= 8) {
dtomul = 7;
dtocyc = 15;
puts("Warning: Using maximum data timeout\n");
}
dtor = (MMCI_BF(DTOMUL, dtomul)
| MMCI_BF(DTOCYC, dtocyc));
mmci_writel(DTOR, dtor);
printf("mmc: Using %u cycles data timeout (DTOR=0x%x)\n",
dtocyc << shift, dtor);
}
int mmc_init(int verbose)
{
struct mmc_cid cid;
struct mmc_csd csd;
unsigned int max_blksz;
int ret;
/* Initialize controller */
@@ -418,6 +476,8 @@ int mmc_init(int verbose)
mmci_writel(IDR, ~0UL);
mci_set_mode(CFG_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
mmc_card_is_sd = 0;
ret = sd_init_card(&cid, verbose);
if (ret) {
mmc_rca = MMC_DEFAULT_RCA;
@@ -433,6 +493,8 @@ int mmc_init(int verbose)
if (verbose)
mmc_dump_csd(&csd);
mci_set_data_timeout(&csd);
/* Initialize the blockdev structure */
mmc_blkdev.if_type = IF_TYPE_MMC;
mmc_blkdev.part_type = PART_TYPE_DOS;
@@ -444,7 +506,17 @@ int mmc_init(int verbose)
sizeof(mmc_blkdev.product));
sprintf((char *)mmc_blkdev.revision, "%x %x",
cid.prv >> 4, cid.prv & 0x0f);
mmc_blkdev.blksz = 1 << csd.read_bl_len;
/*
* If we can't use 512 byte blocks, refuse to deal with the
* card. Tons of code elsewhere seems to depend on this.
*/
max_blksz = 1 << csd.read_bl_len;
if (max_blksz < 512 || (max_blksz > 512 && !csd.read_bl_partial)) {
printf("Card does not support 512 byte reads, aborting.\n");
return -ENODEV;
}
mmc_blkdev.blksz = 512;
mmc_blkdev.lba = (csd.c_size + 1) * (1 << (csd.c_size_mult + 2));
mci_set_mode(CFG_MMC_CLK_PP, mmc_blkdev.blksz);

View File

@@ -57,6 +57,10 @@
#define MMCI_CLKDIV_SIZE 8
#define MMCI_PWSDIV_OFFSET 8
#define MMCI_PWSDIV_SIZE 3
#define MMCI_RDPROOF_OFFSET 11
#define MMCI_RDPROOF_SIZE 1
#define MMCI_WRPROOF_OFFSET 12
#define MMCI_WRPROOF_SIZE 1
#define MMCI_PDCPADV_OFFSET 14
#define MMCI_PDCPADV_SIZE 1
#define MMCI_PDCMODE_OFFSET 15

View File

@@ -20,8 +20,8 @@
* MA 02111-1307 USA
*/
#include <common.h>
#include <div64.h>
#include <asm/div64.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/processor.h>

View File

@@ -76,7 +76,6 @@ void calc_baud(void)
void serial_setbrg(void)
{
int i;
DECLARE_GLOBAL_DATA_PTR;
calc_baud();

View File

@@ -22,6 +22,8 @@
#include <i2c.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
#define bfin_read16(addr) ({ unsigned __v; \
__asm__ __volatile__ (\
"%0 = w[%1] (z);\n\t"\
@@ -68,7 +70,6 @@
#ifdef DEBUG_I2C
#define PRINTD(fmt,args...) do { \
DECLARE_GLOBAL_DATA_PTR; \
if (gd->have_console) \
printf(fmt ,##args); \
} while (0)

View File

@@ -52,6 +52,8 @@
#include <asm/io.h>
#include "serial.h"
DECLARE_GLOBAL_DATA_PTR;
unsigned long pll_div_fact;
void calc_baud(void)
@@ -74,7 +76,6 @@ void calc_baud(void)
void serial_setbrg(void)
{
int i;
DECLARE_GLOBAL_DATA_PTR;
calc_baud();

View File

@@ -52,6 +52,8 @@
#include "serial.h"
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
unsigned long pll_div_fact;
void calc_baud(void)
@@ -74,7 +76,6 @@ void calc_baud(void)
void serial_setbrg(void)
{
int i;
DECLARE_GLOBAL_DATA_PTR;
calc_baud();

View File

@@ -394,7 +394,7 @@ int serial_buffered_tstc(void)
#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
/*
AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
number 0 or number 1
@@ -500,4 +500,4 @@ void kgdb_interruptible(int yes)
return;
}
#endif /* (CONFIG_KGDB_SER_INDEX & 2) */
#endif /* CFG_CMD_KGDB */
#endif

View File

@@ -149,7 +149,7 @@ data_ok:
.progress3:
/* clear bss section in ram, size must be 4-byte aligned */
movl $_i386boot_bss_start, %eax /* BSS start */
movl $_i386boot_bss_start, %edi /* MK_CHG BSS start */
movl $_i386boot_bss_size, %ecx /* BSS size */
movl %ecx, %eax
andl $3, %eax

View File

@@ -85,7 +85,7 @@ int cpu_init (void)
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined (CONFIG_PCI)
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
pci_init();
#endif
return 0;

View File

@@ -682,7 +682,7 @@ int npe_initialize(bd_t * bis)
eth_register(dev);
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register(dev->name, npe_miiphy_read, npe_miiphy_write);
#endif

48
cpu/mcf523x/Makefile Normal file
View File

@@ -0,0 +1,48 @@
#
# (C) Copyright 2000-2004
# 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
# CFLAGS += -DET_DEBUG
LIB = lib$(CPU).a
START = start.o
COBJS = cpu.o speed.o cpu_init.o interrupts.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
START := $(addprefix $(obj),$(START))
all: $(obj).depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

27
cpu/mcf523x/config.mk Normal file
View File

@@ -0,0 +1,27 @@
#
# (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
#
# (C) Copyright 2000-2004
# 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
#
PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
PLATFORM_CPPFLAGS += -m5307 -fPIC

109
cpu/mcf523x/cpu.c Normal file
View File

@@ -0,0 +1,109 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <watchdog.h>
#include <command.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
volatile ccm_t *ccm = (ccm_t *) MMAP_CCM;
ccm->rcr = CCM_RCR_SOFTRST;
/* we don't return! */
return 0;
};
int checkcpu(void)
{
volatile ccm_t *ccm = (ccm_t *) MMAP_CCM;
u16 msk;
u16 id = 0;
u8 ver;
puts("CPU: ");
msk = (ccm->cir >> 6);
ver = (ccm->cir & 0x003f);
switch (msk) {
case 0x31:
id = 5235;
break;
}
if (id) {
printf("Freescale MCF%d (Mask:%01x Version:%x)\n", id, msk,
ver);
printf(" CPU CLK %d Mhz BUS CLK %d Mhz\n",
(int)(gd->cpu_clk / 1000000),
(int)(gd->bus_clk / 1000000));
}
return 0;
};
#if defined(CONFIG_WATCHDOG)
/* Called by macro WATCHDOG_RESET */
void watchdog_reset(void)
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
wdp->sr = 0x5555; /* Count register */
asm("nop");
wdp->sr = 0xAAAA; /* Count register */
}
int watchdog_disable(void)
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
/* UserManual, once the wdog is disabled, wdog cannot be re-enabled */
wdp->cr |= WTM_WCR_HALTED; /* halted watchdog timer */
puts("WATCHDOG:disabled\n");
return (0);
}
int watchdog_init(void)
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
u32 wdog_module = 0;
/* set timeout and enable watchdog */
wdog_module = ((CFG_CLK / CFG_HZ) * CONFIG_WATCHDOG_TIMEOUT);
wdog_module |= (wdog_module / 8192);
wdp->mr = wdog_module;
wdp->cr = WTM_WCR_EN;
puts("WATCHDOG:enabled\n");
return (0);
}
#endif /* CONFIG_WATCHDOG */

145
cpu/mcf523x/cpu_init.c Normal file
View File

@@ -0,0 +1,145 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* (C) Copyright 2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <watchdog.h>
#include <asm/immap.h>
/*
* Breath some life into the CPU...
*
* Set up the memory map,
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f(void)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
volatile wdog_t *wdog = (wdog_t *) MMAP_WDOG;
volatile scm_t *scm = (scm_t *) MMAP_SCM;
/* watchdog is enabled by default - disable the watchdog */
#ifndef CONFIG_WATCHDOG
wdog->cr = 0;
#endif
scm->rambar = (CFG_INIT_RAM_ADDR | SCM_RAMBAR_BDE);
/* Port configuration */
gpio->par_cs = 0;
#if (defined(CFG_CS0_BASE) && defined(CFG_CS0_MASK) && defined(CFG_CS0_CTRL))
fbcs->csar0 = CFG_CS0_BASE;
fbcs->cscr0 = CFG_CS0_CTRL;
fbcs->csmr0 = CFG_CS0_MASK;
#endif
#if (defined(CFG_CS1_BASE) && defined(CFG_CS1_MASK) && defined(CFG_CS1_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS1;
fbcs->csar1 = CFG_CS1_BASE;
fbcs->cscr1 = CFG_CS1_CTRL;
fbcs->csmr1 = CFG_CS1_MASK;
#endif
#if (defined(CFG_CS2_BASE) && defined(CFG_CS2_MASK) && defined(CFG_CS2_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS2;
fbcs->csar2 = CFG_CS2_BASE;
fbcs->cscr2 = CFG_CS2_CTRL;
fbcs->csmr2 = CFG_CS2_MASK;
#endif
#if (defined(CFG_CS3_BASE) && defined(CFG_CS3_MASK) && defined(CFG_CS3_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS3;
fbcs->csar3 = CFG_CS3_BASE;
fbcs->cscr3 = CFG_CS3_CTRL;
fbcs->csmr3 = CFG_CS3_MASK;
#endif
#if (defined(CFG_CS4_BASE) && defined(CFG_CS4_MASK) && defined(CFG_CS4_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS4;
fbcs->csar4 = CFG_CS4_BASE;
fbcs->cscr4 = CFG_CS4_CTRL;
fbcs->csmr4 = CFG_CS4_MASK;
#endif
#if (defined(CFG_CS5_BASE) && defined(CFG_CS5_MASK) && defined(CFG_CS5_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS5;
fbcs->csar5 = CFG_CS5_BASE;
fbcs->cscr5 = CFG_CS5_CTRL;
fbcs->csmr5 = CFG_CS5_MASK;
#endif
#if (defined(CFG_CS6_BASE) && defined(CFG_CS6_MASK) && defined(CFG_CS6_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS6;
fbcs->csar6 = CFG_CS6_BASE;
fbcs->cscr6 = CFG_CS6_CTRL;
fbcs->csmr6 = CFG_CS6_MASK;
#endif
#if (defined(CFG_CS7_BASE) && defined(CFG_CS7_MASK) && defined(CFG_CS7_CTRL))
gpio->par_cs |= GPIO_PAR_CS_CS7;
fbcs->csar7 = CFG_CS7_BASE;
fbcs->cscr7 = CFG_CS7_CTRL;
fbcs->csmr7 = CFG_CS7_MASK;
#endif
#ifdef CONFIG_FSL_I2C
gpio->par_feci2c &= ~(GPIO_PAR_FECI2C_SCL_MASK | GPIO_PAR_FECI2C_SDA_MASK);
gpio->par_feci2c |= (GPIO_PAR_FECI2C_SCL_I2CSCL | GPIO_PAR_FECI2C_SDA_I2CSDA);
#endif
icache_enable();
}
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r(void)
{
return (0);
}
void uart_port_conf(void)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
gpio->par_uart = (GPIO_PAR_UART_U0RXD | GPIO_PAR_UART_U0TXD);
break;
case 1:
gpio->par_uart =
(GPIO_PAR_UART_U1RXD_U1RXD | GPIO_PAR_UART_U1TXD_U1TXD);
break;
case 2:
gpio->par_timer = (GPIO_PAR_UART_U2RXD | GPIO_PAR_UART_U2TXD);
break;
}
}

49
cpu/mcf523x/interrupts.c Normal file
View File

@@ -0,0 +1,49 @@
/*
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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
*/
/* CPU specific interrupt routine */
#include <common.h>
#include <asm/immap.h>
int interrupt_init(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
/* Make sure all interrupts are disabled */
intp->imrl0 |= 0x1;
enable_interrupts();
return 0;
}
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
intp->icr0[CFG_TMRINTR_NO] = CFG_TMRINTR_PRI;
intp->imrl0 &= ~INTC_IPRL_INT0;
intp->imrl0 &= ~CFG_TMRINTR_MASK;
}
#endif

View File

@@ -1,7 +1,10 @@
/*
* (C) Copyright 2007 Michal Simek
*
* Michal SIMEK <monstr@monstr.eu>
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -13,7 +16,7 @@
*
* 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
* 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
@@ -22,25 +25,25 @@
* MA 02111-1307 USA
*/
.text
.globl microblaze_disable_interrupts
.ent microblaze_disable_interrupts
.align 2
microblaze_disable_interrupts:
#Make space on stack for a temporary
addi r1, r1, -4
#Save register r12
swi r12, r1, 0
#Read the MSR register
mfs r12, rmsr
#Clear the interrupt enable bit
andi r12, r12, ~2
#Save the MSR register
mts rmsr, r12
#Load register r12
lwi r12, r1, 0
#Return
rtsd r15, 8
#Update stack in the delay slot
addi r1, r1, 4
.end microblaze_disable_interrupts
#include <common.h>
#include <asm/processor.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* get_clocks() fills in gd->cpu_clock and gd->bus_clk
*/
int get_clocks(void)
{
volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
pll->syncr = PLL_SYNCR_MFD(1);
while (!(pll->synsr & PLL_SYNSR_LOCK));
gd->bus_clk = CFG_CLK;
gd->cpu_clk = (gd->bus_clk * 2);
return (0);
}

340
cpu/mcf523x/start.S Normal file
View File

@@ -0,0 +1,340 @@
/*
* Copyright (C) 2003 Josef Baumgartner <josef.baumgartner@telex.de>
* Based on code from Bernhard Kuhn <bkuhn@metrowerks.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 <config.h>
#include "version.h"
#ifndef CONFIG_IDENT_STRING
#define CONFIG_IDENT_STRING ""
#endif
#define _START _start
#define _FAULT _fault
#define SAVE_ALL \
move.w #0x2700,%sr; /* disable intrs */ \
subl #60,%sp; /* space for 15 regs */ \
moveml %d0-%d7/%a0-%a6,%sp@;
#define RESTORE_ALL \
moveml %sp@,%d0-%d7/%a0-%a6; \
addl #60,%sp; /* space for 15 regs */ \
rte;
.text
/*
* Vector table. This is used for initial platform startup.
* These vectors are to catch any un-intended traps.
*/
_vectors:
INITSP: .long 0x00000000 /* Initial SP */
INITPC: .long _START /* Initial PC */
vector02: .long _FAULT /* Access Error */
vector03: .long _FAULT /* Address Error */
vector04: .long _FAULT /* Illegal Instruction */
vector05: .long _FAULT /* Reserved */
vector06: .long _FAULT /* Reserved */
vector07: .long _FAULT /* Reserved */
vector08: .long _FAULT /* Privilege Violation */
vector09: .long _FAULT /* Trace */
vector0A: .long _FAULT /* Unimplemented A-Line */
vector0B: .long _FAULT /* Unimplemented F-Line */
vector0C: .long _FAULT /* Debug Interrupt */
vector0D: .long _FAULT /* Reserved */
vector0E: .long _FAULT /* Format Error */
vector0F: .long _FAULT /* Unitialized Int. */
/* Reserved */
vector10_17:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector18: .long _FAULT /* Spurious Interrupt */
vector19: .long _FAULT /* Autovector Level 1 */
vector1A: .long _FAULT /* Autovector Level 2 */
vector1B: .long _FAULT /* Autovector Level 3 */
vector1C: .long _FAULT /* Autovector Level 4 */
vector1D: .long _FAULT /* Autovector Level 5 */
vector1E: .long _FAULT /* Autovector Level 6 */
vector1F: .long _FAULT /* Autovector Level 7 */
/* TRAP #0 - #15 */
vector20_2F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
/* Reserved */
vector30_3F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector64_127:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector128_191:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector192_255:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.text
.globl _start
_start:
nop
nop
move.w #0x2700,%sr /* Mask off Interrupt */
/* Set vector base register at the beginning of the Flash */
move.l #CFG_FLASH_BASE, %d0
movec %d0, %VBR
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_RAM_CTRL), %d0
movec %d0, %RAMBAR1
/* invalidate and disable cache */
move.l #0x01000000, %d0 /* Invalidate cache cmd */
movec %d0, %CACR /* Invalidate cache */
nop
move.l #0, %d0
movec %d0, %ACR0
movec %d0, %ACR1
/* initialize general use internal ram */
move.l #0, %d0
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a2
move.l %d0, (%a1)
move.l %d0, (%a2)
/* set stackpointer to end of internal ram to get some stackspace for the
first c-code */
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET), %sp
clr.l %sp@-
move.l #__got_start, %a5 /* put relocation table address to a5 */
bsr cpu_init_f /* run low-level CPU init code (from flash) */
bsr board_init_f /* run low-level board init code (from flash) */
/* board_init_f() does not return */
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* r3 = dest
* r4 = src
* r5 = length in bytes
* r6 = cachelinesize
*/
.globl relocate_code
relocate_code:
link.w %a6,#0
move.l 8(%a6), %sp /* set new stack pointer */
move.l 12(%a6), %d0 /* Save copy of Global Data pointer */
move.l 16(%a6), %a0 /* Save copy of Destination Address */
move.l #CFG_MONITOR_BASE, %a1
move.l #__init_end, %a2
move.l %a0, %a3
/* copy the code to RAM */
1:
move.l (%a1)+, (%a3)+
cmp.l %a1,%a2
bgt.s 1b
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
move.l %a0, %a1
add.l #(in_ram - CFG_MONITOR_BASE), %a1
jmp (%a1)
in_ram:
clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CFG_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CFG_MONITOR_BASE),%d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
bgt.s 6b
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CFG_MONITOR_BASE),%a1
move.l %a1,%a5 /* * fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CFG_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CFG_MONITOR_BASE), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */
move.l %d0,-(%sp) /* gd */
jsr (%a1)
/*------------------------------------------------------------------------------*/
/* exception code */
.globl _fault
_fault:
jmp _fault
.globl _exc_handler
_exc_handler:
SAVE_ALL
movel %sp,%sp@-
bsr exc_handler
addql #4,%sp
RESTORE_ALL
.globl _int_handler
_int_handler:
SAVE_ALL
movel %sp,%sp@-
bsr int_handler
addql #4,%sp
RESTORE_ALL
/*------------------------------------------------------------------------------*/
/* cache functions */
.globl icache_enable
icache_enable:
move.l #0x01000000, %d0 /* Invalidate cache cmd */
movec %d0, %CACR /* Invalidate cache */
nop
move.l #(CFG_SDRAM_BASE + 0xc000), %d0 /* Setup cache mask */
movec %d0, %ACR0 /* Enable cache */
move.l #(CFG_FLASH_BASE + 0xc000), %d0 /* Setup cache mask */
movec %d0, %ACR1 /* Enable cache */
move.l #0x80400100, %d0 /* Setup cache mask */
movec %d0, %CACR /* Enable cache */
nop
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
.globl icache_disable
icache_disable:
move.l #0x00000100, %d0 /* Setup cache mask */
movec %d0, %CACR /* Disable cache */
clr.l %d0 /* Setup cache mask */
movec %d0, %ACR0
movec %d0, %ACR1
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
moveq #0, %d0
move.l %d0, (%a1)
rts
.globl icache_status
icache_status:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
move.l (%a1), %d0
rts
.globl icache_invalid
icache_invalid:
move.l #0x80600100, %d0 /* Setup cache mask */
movec %d0, %CACR /* Enable cache */
nop
rts
.globl dcache_enable
dcache_enable:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
/* No dcache, just a dummy function */
.globl dcache_disable
dcache_disable:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a1
moveq #0, %d0
move.l %d0, (%a1)
rts
.globl dcache_status
dcache_status:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a1
move.l (%a1), %d0
rts
/*------------------------------------------------------------------------------*/
.globl version_string
version_string:
.ascii U_BOOT_VERSION
.ascii " (", __DATE__, " - ", __TIME__, ")"
.ascii CONFIG_IDENT_STRING, "\0"

View File

@@ -27,8 +27,8 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).a
START =
COBJS = serial.o interrupts.o cpu.o speed.o cpu_init.o fec.o
START = start.o
COBJS = interrupts.o cpu.o speed.o cpu_init.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))

View File

@@ -28,33 +28,15 @@
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <asm/immap.h>
#ifdef CONFIG_M5271
#include <asm/immap_5271.h>
#include <asm/m5271.h>
#endif
#ifdef CONFIG_M5272
#include <asm/immap_5272.h>
#include <asm/m5272.h>
#endif
#ifdef CONFIG_M5282
#include <asm/m5282.h>
#include <asm/immap_5282.h>
#endif
#ifdef CONFIG_M5249
#include <asm/m5249.h>
#endif
#ifdef CONFIG_M5271
/*
* Both MCF5270 and MCF5271 are members of the MPC5271 family. Try to
* determine which one we are running on, based on the Chip Identification
* Register (CIR).
*/
int checkcpu (void)
int checkcpu(void)
{
char buf[32];
unsigned short cir; /* Chip Identification Register */
@@ -80,156 +62,194 @@ int checkcpu (void)
if (cpu_model)
printf("CPU: Freescale ColdFire MCF%s rev. %hu, at %s MHz\n",
cpu_model, prn, strmhz(buf, CFG_CLK));
cpu_model, prn, strmhz(buf, CFG_CLK));
else
printf("CPU: Unknown - Freescale ColdFire MCF5271 family"
" (PIN: 0x%x) rev. %hu, at %s MHz\n",
pin, prn, strmhz(buf, CFG_CLK));
" (PIN: 0x%x) rev. %hu, at %s MHz\n",
pin, prn, strmhz(buf, CFG_CLK));
return 0;
}
int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) {
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
mbar_writeByte(MCF_RCM_RCR,
MCF_RCM_RCR_SOFTRST | MCF_RCM_RCR_FRCRSTOUT);
MCF_RCM_RCR_SOFTRST | MCF_RCM_RCR_FRCRSTOUT);
return 0;
};
#if defined(CONFIG_WATCHDOG)
void watchdog_reset (void)
void watchdog_reset(void)
{
mbar_writeShort(MCF_WTM_WSR, 0x5555);
mbar_writeShort(MCF_WTM_WSR, 0xAAAA);
}
int watchdog_disable (void)
int watchdog_disable(void)
{
mbar_writeShort(MCF_WTM_WCR, 0);
return (0);
}
int watchdog_init (void)
int watchdog_init(void)
{
mbar_writeShort(MCF_WTM_WCR, MCF_WTM_WCR_EN);
return (0);
}
#endif /* #ifdef CONFIG_WATCHDOG */
#endif /* #ifdef CONFIG_WATCHDOG */
#endif
#ifdef CONFIG_M5272
int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) {
volatile wdog_t * wdp = (wdog_t *)(CFG_MBAR + MCFSIM_WRRR);
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
wdp->wdog_wrrr = 0;
udelay (1000);
udelay(1000);
/* enable watchdog, set timeout to 0 and wait */
wdp->wdog_wrrr = 1;
while (1);
while (1) ;
/* we don't return! */
return 0;
};
int checkcpu(void) {
ulong *dirp = (ulong *)(CFG_MBAR + MCFSIM_DIR);
int checkcpu(void)
{
volatile sysctrl_t *sysctrl = (sysctrl_t *) (MMAP_CFG);
uchar msk;
char *suf;
char *suf;
puts ("CPU: ");
msk = (*dirp > 28) & 0xf;
puts("CPU: ");
msk = (sysctrl->sc_dir > 28) & 0xf;
switch (msk) {
case 0x2: suf = "1K75N"; break;
case 0x4: suf = "3K75N"; break;
default:
suf = NULL;
printf ("Freescale MCF5272 (Mask:%01x)\n", msk);
break;
}
case 0x2:
suf = "1K75N";
break;
case 0x4:
suf = "3K75N";
break;
default:
suf = NULL;
printf("Freescale MCF5272 (Mask:%01x)\n", msk);
break;
}
if (suf)
printf ("Freescale MCF5272 %s\n", suf);
printf("Freescale MCF5272 %s\n", suf);
return 0;
};
#if defined(CONFIG_WATCHDOG)
/* Called by macro WATCHDOG_RESET */
void watchdog_reset (void)
void watchdog_reset(void)
{
volatile immap_t * regp = (volatile immap_t *)CFG_MBAR;
regp->wdog_reg.wdog_wcr = 0;
volatile wdog_t *wdt = (volatile wdog_t *)(MMAP_WDOG);
wdt->wdog_wcr = 0;
}
int watchdog_disable (void)
int watchdog_disable(void)
{
volatile immap_t *regp = (volatile immap_t *)CFG_MBAR;
volatile wdog_t *wdt = (volatile wdog_t *)(MMAP_WDOG);
regp->wdog_reg.wdog_wcr = 0; /* reset watchdog counter */
regp->wdog_reg.wdog_wirr = 0; /* disable watchdog interrupt */
regp->wdog_reg.wdog_wrrr = 0; /* disable watchdog timer */
wdt->wdog_wcr = 0; /* reset watchdog counter */
wdt->wdog_wirr = 0; /* disable watchdog interrupt */
wdt->wdog_wrrr = 0; /* disable watchdog timer */
puts ("WATCHDOG:disabled\n");
puts("WATCHDOG:disabled\n");
return (0);
}
int watchdog_init (void)
int watchdog_init(void)
{
volatile immap_t *regp = (volatile immap_t *)CFG_MBAR;
volatile wdog_t *wdt = (volatile wdog_t *)(MMAP_WDOG);
regp->wdog_reg.wdog_wirr = 0; /* disable watchdog interrupt */
wdt->wdog_wirr = 0; /* disable watchdog interrupt */
/* set timeout and enable watchdog */
regp->wdog_reg.wdog_wrrr = ((CONFIG_WATCHDOG_TIMEOUT * CFG_HZ) / (32768 * 1000)) - 1;
regp->wdog_reg.wdog_wcr = 0; /* reset watchdog counter */
wdt->wdog_wrrr =
((CONFIG_WATCHDOG_TIMEOUT * CFG_HZ) / (32768 * 1000)) - 1;
wdt->wdog_wcr = 0; /* reset watchdog counter */
puts ("WATCHDOG:enabled\n");
puts("WATCHDOG:enabled\n");
return (0);
}
#endif /* #ifdef CONFIG_WATCHDOG */
#endif /* #ifdef CONFIG_M5272 */
#endif /* #ifdef CONFIG_WATCHDOG */
#endif /* #ifdef CONFIG_M5272 */
#ifdef CONFIG_M5282
int checkcpu (void)
int checkcpu(void)
{
unsigned char resetsource = MCFRESET_RSR;
printf ("CPU: Freescale Coldfire MCF5282 (PIN: %2.2x REV: %2.2x)\n",
MCFCCM_CIR>>8,MCFCCM_CIR & MCFCCM_CIR_PRN_MASK);
printf ("Reset:%s%s%s%s%s%s%s\n",
(resetsource & MCFRESET_RSR_LOL) ? " Loss of Lock" : "",
(resetsource & MCFRESET_RSR_LOC) ? " Loss of Clock" : "",
(resetsource & MCFRESET_RSR_EXT) ? " External" : "",
(resetsource & MCFRESET_RSR_POR) ? " Power On" : "",
(resetsource & MCFRESET_RSR_WDR) ? " Watchdog" : "",
(resetsource & MCFRESET_RSR_SOFT) ? " Software" : "",
(resetsource & MCFRESET_RSR_LVD) ? " Low Voltage" : ""
);
printf("CPU: Freescale Coldfire MCF5282 (PIN: %2.2x REV: %2.2x)\n",
MCFCCM_CIR >> 8, MCFCCM_CIR & MCFCCM_CIR_PRN_MASK);
printf("Reset:%s%s%s%s%s%s%s\n",
(resetsource & MCFRESET_RSR_LOL) ? " Loss of Lock" : "",
(resetsource & MCFRESET_RSR_LOC) ? " Loss of Clock" : "",
(resetsource & MCFRESET_RSR_EXT) ? " External" : "",
(resetsource & MCFRESET_RSR_POR) ? " Power On" : "",
(resetsource & MCFRESET_RSR_WDR) ? " Watchdog" : "",
(resetsource & MCFRESET_RSR_SOFT) ? " Software" : "",
(resetsource & MCFRESET_RSR_LVD) ? " Low Voltage" : "");
return 0;
}
int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
MCFRESET_RCR = MCFRESET_RCR_SOFTRST;
return 0;
};
#endif
#ifdef CONFIG_M5249 /* test-only: todo... */
int checkcpu (void)
#ifdef CONFIG_M5249
int checkcpu(void)
{
char buf[32];
printf ("CPU: Freescale Coldfire MCF5249 at %s MHz\n", strmhz(buf, CFG_CLK));
printf("CPU: Freescale Coldfire MCF5249 at %s MHz\n",
strmhz(buf, CFG_CLK));
return 0;
}
int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) {
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
/* enable watchdog, set timeout to 0 and wait */
mbar_writeByte(MCFSIM_SYPCR, 0xc0);
while (1);
while (1) ;
/* we don't return! */
return 0;
};
#endif
#ifdef CONFIG_M5253
int checkcpu(void)
{
char buf[32];
unsigned char resetsource = mbar_readLong(SIM_RSR);
printf("CPU: Freescale Coldfire MCF5253 at %s MHz\n",
strmhz(buf, CFG_CLK));
if ((resetsource & SIM_RSR_HRST) || (resetsource & SIM_RSR_SWTR)) {
printf("Reset:%s%s\n",
(resetsource & SIM_RSR_HRST) ? " Hardware/ System Reset"
: "",
(resetsource & SIM_RSR_SWTR) ? " Software Watchdog" :
"");
}
return 0;
}
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
/* enable watchdog, set timeout to 0 and wait */
mbar_writeByte(SIM_SYPCR, 0xc0);
while (1) ;
/* we don't return! */
return 0;

View File

@@ -6,6 +6,10 @@
* (C) Copyright 2005
* BuS Elektronik GmbH & Co. KG <esw@bus-elektronik.de>
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
* Hayden Fraser (Hayden.Fraser@freescale.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -27,28 +31,78 @@
#include <common.h>
#include <watchdog.h>
#include <asm/immap.h>
#ifdef CONFIG_M5271
#include <asm/m5271.h>
#include <asm/immap_5271.h>
#endif
#if defined(CONFIG_M5253)
/*
* Breath some life into the CPU...
*
* Set up the memory map,
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f(void)
{
mbar_writeByte(MCFSIM_MPARK, 0x40); /* 5249 Internal Core takes priority over DMA */
mbar_writeByte(MCFSIM_SYPCR, 0x00);
mbar_writeByte(MCFSIM_SWIVR, 0x0f);
mbar_writeByte(MCFSIM_SWSR, 0x00);
mbar_writeByte(MCFSIM_SWDICR, 0x00);
mbar_writeByte(MCFSIM_TIMER1ICR, 0x00);
mbar_writeByte(MCFSIM_TIMER2ICR, 0x88);
mbar_writeByte(MCFSIM_I2CICR, 0x00);
mbar_writeByte(MCFSIM_UART1ICR, 0x00);
mbar_writeByte(MCFSIM_UART2ICR, 0x00);
mbar_writeByte(MCFSIM_ICR6, 0x00);
mbar_writeByte(MCFSIM_ICR7, 0x00);
mbar_writeByte(MCFSIM_ICR8, 0x00);
mbar_writeByte(MCFSIM_ICR9, 0x00);
mbar_writeByte(MCFSIM_QSPIICR, 0x00);
#ifdef CONFIG_M5272
#include <asm/m5272.h>
#include <asm/immap_5272.h>
#endif
mbar2_writeLong(MCFSIM_GPIO_INT_EN, 0x00000080);
mbar2_writeByte(MCFSIM_INTBASE, 0x40); /* Base interrupts at 64 */
mbar2_writeByte(MCFSIM_SPURVEC, 0x00);
#ifdef CONFIG_M5282
#include <asm/m5282.h>
#include <asm/immap_5282.h>
#endif
/*mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); */ /* Enable a 1 cycle pre-drive cycle on CS1 */
#ifdef CONFIG_M5249
#include <asm/m5249.h>
#endif
/*
* Setup chip selects...
*/
mbar_writeShort(MCFSIM_CSAR1, CFG_CSAR1);
mbar_writeShort(MCFSIM_CSCR1, CFG_CSCR1);
mbar_writeLong(MCFSIM_CSMR1, CFG_CSMR1);
mbar_writeShort(MCFSIM_CSAR0, CFG_CSAR0);
mbar_writeShort(MCFSIM_CSCR0, CFG_CSCR0);
mbar_writeLong(MCFSIM_CSMR0, CFG_CSMR0);
/* enable instruction cache now */
icache_enable();
}
/*initialize higher level parts of CPU like timers */
int cpu_init_r(void)
{
return (0);
}
void uart_port_conf(void)
{
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
break;
case 1:
break;
case 2:
break;
}
}
#endif /* #if defined(CONFIG_M5253) */
#if defined(CONFIG_M5271)
void cpu_init_f (void)
void cpu_init_f(void)
{
#ifndef CONFIG_WATCHDOG
/* Disable the watchdog if we aren't using it */
@@ -58,25 +112,35 @@ void cpu_init_f (void)
/* Set clockspeed to 100MHz */
mbar_writeShort(MCF_FMPLL_SYNCR,
MCF_FMPLL_SYNCR_MFD(0) | MCF_FMPLL_SYNCR_RFD(0));
while (!mbar_readByte(MCF_FMPLL_SYNSR) & MCF_FMPLL_SYNSR_LOCK);
/* Enable UART pins */
mbar_writeShort(MCF_GPIO_PAR_UART, MCF_GPIO_PAR_UART_U0TXD |
MCF_GPIO_PAR_UART_U0RXD |
MCF_GPIO_PAR_UART_U1RXD_UART1 |
MCF_GPIO_PAR_UART_U1TXD_UART1);
/* Enable Ethernet pins */
mbar_writeByte(MCF_GPIO_PAR_FECI2C, CFG_FECI2C);
while (!mbar_readByte(MCF_FMPLL_SYNSR) & MCF_FMPLL_SYNSR_LOCK) ;
}
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r (void)
int cpu_init_r(void)
{
return (0);
}
void uart_port_conf(void)
{
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
mbar_writeShort(MCF_GPIO_PAR_UART, MCF_GPIO_PAR_UART_U0TXD |
MCF_GPIO_PAR_UART_U0RXD);
break;
case 1:
mbar_writeShort(MCF_GPIO_PAR_UART,
MCF_GPIO_PAR_UART_U1RXD_UART1 |
MCF_GPIO_PAR_UART_U1TXD_UART1);
break;
case 2:
mbar_writeShort(MCF_GPIO_PAR_UART, 0x3000);
break;
}
}
#endif
#if defined(CONFIG_M5272)
@@ -87,69 +151,68 @@ int cpu_init_r (void)
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f (void)
void cpu_init_f(void)
{
/* if we come from RAM we assume the CPU is
* already initialized.
*/
#ifndef CONFIG_MONITOR_IS_IN_RAM
volatile immap_t *regp = (immap_t *)CFG_MBAR;
volatile sysctrl_t *sysctrl = (sysctrl_t *) (CFG_MBAR);
volatile gpio_t *gpio = (gpio_t *) (MMAP_GPIO);
volatile csctrl_t *csctrl = (csctrl_t *) (MMAP_FBCS);
volatile unsigned char *mbar;
mbar = (volatile unsigned char *) CFG_MBAR;
regp->sysctrl_reg.sc_scr = CFG_SCR;
regp->sysctrl_reg.sc_spr = CFG_SPR;
sysctrl->sc_scr = CFG_SCR;
sysctrl->sc_spr = CFG_SPR;
/* Setup Ports: */
regp->gpio_reg.gpio_pacnt = CFG_PACNT;
regp->gpio_reg.gpio_paddr = CFG_PADDR;
regp->gpio_reg.gpio_padat = CFG_PADAT;
regp->gpio_reg.gpio_pbcnt = CFG_PBCNT;
regp->gpio_reg.gpio_pbddr = CFG_PBDDR;
regp->gpio_reg.gpio_pbdat = CFG_PBDAT;
regp->gpio_reg.gpio_pdcnt = CFG_PDCNT;
gpio->gpio_pacnt = CFG_PACNT;
gpio->gpio_paddr = CFG_PADDR;
gpio->gpio_padat = CFG_PADAT;
gpio->gpio_pbcnt = CFG_PBCNT;
gpio->gpio_pbddr = CFG_PBDDR;
gpio->gpio_pbdat = CFG_PBDAT;
gpio->gpio_pdcnt = CFG_PDCNT;
/* Memory Controller: */
regp->csctrl_reg.cs_br0 = CFG_BR0_PRELIM;
regp->csctrl_reg.cs_or0 = CFG_OR0_PRELIM;
csctrl->cs_br0 = CFG_BR0_PRELIM;
csctrl->cs_or0 = CFG_OR0_PRELIM;
#if (defined(CFG_OR1_PRELIM) && defined(CFG_BR1_PRELIM))
regp->csctrl_reg.cs_br1 = CFG_BR1_PRELIM;
regp->csctrl_reg.cs_or1 = CFG_OR1_PRELIM;
csctrl->cs_br1 = CFG_BR1_PRELIM;
csctrl->cs_or1 = CFG_OR1_PRELIM;
#endif
#if defined(CFG_OR2_PRELIM) && defined(CFG_BR2_PRELIM)
regp->csctrl_reg.cs_br2 = CFG_BR2_PRELIM;
regp->csctrl_reg.cs_or2 = CFG_OR2_PRELIM;
csctrl->cs_br2 = CFG_BR2_PRELIM;
csctrl->cs_or2 = CFG_OR2_PRELIM;
#endif
#if defined(CFG_OR3_PRELIM) && defined(CFG_BR3_PRELIM)
regp->csctrl_reg.cs_br3 = CFG_BR3_PRELIM;
regp->csctrl_reg.cs_or3 = CFG_OR3_PRELIM;
csctrl->cs_br3 = CFG_BR3_PRELIM;
csctrl->cs_or3 = CFG_OR3_PRELIM;
#endif
#if defined(CFG_OR4_PRELIM) && defined(CFG_BR4_PRELIM)
regp->csctrl_reg.cs_br4 = CFG_BR4_PRELIM;
regp->csctrl_reg.cs_or4 = CFG_OR4_PRELIM;
csctrl->cs_br4 = CFG_BR4_PRELIM;
csctrl->cs_or4 = CFG_OR4_PRELIM;
#endif
#if defined(CFG_OR5_PRELIM) && defined(CFG_BR5_PRELIM)
regp->csctrl_reg.cs_br5 = CFG_BR5_PRELIM;
regp->csctrl_reg.cs_or5 = CFG_OR5_PRELIM;
csctrl->cs_br5 = CFG_BR5_PRELIM;
csctrl->cs_or5 = CFG_OR5_PRELIM;
#endif
#if defined(CFG_OR6_PRELIM) && defined(CFG_BR6_PRELIM)
regp->csctrl_reg.cs_br6 = CFG_BR6_PRELIM;
regp->csctrl_reg.cs_or6 = CFG_OR6_PRELIM;
csctrl->cs_br6 = CFG_BR6_PRELIM;
csctrl->cs_or6 = CFG_OR6_PRELIM;
#endif
#if defined(CFG_OR7_PRELIM) && defined(CFG_BR7_PRELIM)
regp->csctrl_reg.cs_br7 = CFG_BR7_PRELIM;
regp->csctrl_reg.cs_or7 = CFG_OR7_PRELIM;
csctrl->cs_br7 = CFG_BR7_PRELIM;
csctrl->cs_or7 = CFG_OR7_PRELIM;
#endif
#endif /* #ifndef CONFIG_MONITOR_IS_IN_RAM */
#endif /* #ifndef CONFIG_MONITOR_IS_IN_RAM */
/* enable instruction cache now */
icache_enable();
@@ -159,14 +222,30 @@ void cpu_init_f (void)
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r (void)
int cpu_init_r(void)
{
return (0);
}
#endif /* #if defined(CONFIG_M5272) */
void uart_port_conf(void)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
#ifdef CONFIG_M5282
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
gpio->gpio_pbcnt &= ~(GPIO_PBCNT_PB0MSK | GPIO_PBCNT_PB1MSK);
gpio->gpio_pbcnt |= (GPIO_PBCNT_URT0_TXD | GPIO_PBCNT_URT0_RXD);
break;
case 1:
gpio->gpio_pdcnt &= ~(GPIO_PDCNT_PD1MSK | GPIO_PDCNT_PD4MSK);
gpio->gpio_pdcnt |= (GPIO_PDCNT_URT1_RXD | GPIO_PDCNT_URT1_TXD);
break;
}
}
#endif /* #if defined(CONFIG_M5272) */
#if defined(CONFIG_M5282)
/*
* Breath some life into the CPU...
*
@@ -174,7 +253,7 @@ int cpu_init_r (void)
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f (void)
void cpu_init_f(void)
{
#ifndef CONFIG_WATCHDOG
/* disable watchdog if we aren't using it */
@@ -183,7 +262,11 @@ void cpu_init_f (void)
#ifndef CONFIG_MONITOR_IS_IN_RAM
/* Set speed /PLL */
MCFCLOCK_SYNCR = MCFCLOCK_SYNCR_MFD(CFG_MFD) | MCFCLOCK_SYNCR_RFD(CFG_RFD);
MCFCLOCK_SYNCR =
MCFCLOCK_SYNCR_MFD(CFG_MFD) | MCFCLOCK_SYNCR_RFD(CFG_RFD);
while (!(MCFCLOCK_SYNSR & MCFCLOCK_SYNSR_LOCK)) ;
MCFGPIO_PBCDPAR = 0xc0;
/* Set up the GPIO ports */
#ifdef CFG_PEPAR
@@ -228,29 +311,28 @@ void cpu_init_f (void)
defined(CFG_CS0_WIDTH) & defined(CFG_CS0_RO) & \
defined(CFG_CS0_WS)
MCFCSM_CSAR0 = (CFG_CS0_BASE >> 16) & 0xFFFF;
MCFCSM_CSAR0 = (CFG_CS0_BASE >> 16) & 0xFFFF;
#if (CFG_CS0_WIDTH == 8)
#define CFG_CS0_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS0_WIDTH == 16)
#define CFG_CS0_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS0_WIDTH == 32)
#define CFG_CS0_PS MCFCSM_CSCR_PS_32
#else
#error "CFG_CS0_WIDTH: Fault - wrong bus with for CS0"
#endif
MCFCSM_CSCR0 = MCFCSM_CSCR_WS(CFG_CS0_WS)
|CFG_CS0_PS
|MCFCSM_CSCR_AA;
#if (CFG_CS0_RO != 0)
MCFCSM_CSMR0 = MCFCSM_CSMR_BAM(CFG_CS0_SIZE-1)
|MCFCSM_CSMR_WP|MCFCSM_CSMR_V;
#else
MCFCSM_CSMR0 = MCFCSM_CSMR_BAM(CFG_CS0_SIZE-1)|MCFCSM_CSMR_V;
#endif
#if (CFG_CS0_WIDTH == 8)
#define CFG_CS0_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS0_WIDTH == 16)
#define CFG_CS0_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS0_WIDTH == 32)
#define CFG_CS0_PS MCFCSM_CSCR_PS_32
#else
#waring "Chip Select 0 are not initialized/used"
#error "CFG_CS0_WIDTH: Fault - wrong bus with for CS0"
#endif
MCFCSM_CSCR0 = MCFCSM_CSCR_WS(CFG_CS0_WS)
| CFG_CS0_PS | MCFCSM_CSCR_AA;
#if (CFG_CS0_RO != 0)
MCFCSM_CSMR0 = MCFCSM_CSMR_BAM(CFG_CS0_SIZE - 1)
| MCFCSM_CSMR_WP | MCFCSM_CSMR_V;
#else
MCFCSM_CSMR0 = MCFCSM_CSMR_BAM(CFG_CS0_SIZE - 1) | MCFCSM_CSMR_V;
#endif
#else
#waring "Chip Select 0 are not initialized/used"
#endif
#if defined(CFG_CS1_BASE) & defined(CFG_CS1_SIZE) & \
@@ -259,29 +341,27 @@ void cpu_init_f (void)
MCFCSM_CSAR1 = (CFG_CS1_BASE >> 16) & 0xFFFF;
#if (CFG_CS1_WIDTH == 8)
#define CFG_CS1_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS1_WIDTH == 16)
#define CFG_CS1_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS1_WIDTH == 32)
#define CFG_CS1_PS MCFCSM_CSCR_PS_32
#else
#error "CFG_CS1_WIDTH: Fault - wrong bus with for CS1"
#endif
MCFCSM_CSCR1 = MCFCSM_CSCR_WS(CFG_CS1_WS)
|CFG_CS1_PS
|MCFCSM_CSCR_AA;
#if (CFG_CS1_RO != 0)
MCFCSM_CSMR1 = MCFCSM_CSMR_BAM(CFG_CS1_SIZE-1)
|MCFCSM_CSMR_WP
|MCFCSM_CSMR_V;
#else
MCFCSM_CSMR1 = MCFCSM_CSMR_BAM(CFG_CS1_SIZE-1)
|MCFCSM_CSMR_V;
#endif
#if (CFG_CS1_WIDTH == 8)
#define CFG_CS1_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS1_WIDTH == 16)
#define CFG_CS1_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS1_WIDTH == 32)
#define CFG_CS1_PS MCFCSM_CSCR_PS_32
#else
#warning "Chip Select 1 are not initialized/used"
#error "CFG_CS1_WIDTH: Fault - wrong bus with for CS1"
#endif
MCFCSM_CSCR1 = MCFCSM_CSCR_WS(CFG_CS1_WS)
| CFG_CS1_PS | MCFCSM_CSCR_AA;
#if (CFG_CS1_RO != 0)
MCFCSM_CSMR1 = MCFCSM_CSMR_BAM(CFG_CS1_SIZE - 1)
| MCFCSM_CSMR_WP | MCFCSM_CSMR_V;
#else
MCFCSM_CSMR1 = MCFCSM_CSMR_BAM(CFG_CS1_SIZE - 1)
| MCFCSM_CSMR_V;
#endif
#else
#warning "Chip Select 1 are not initialized/used"
#endif
#if defined(CFG_CS2_BASE) & defined(CFG_CS2_SIZE) & \
@@ -290,29 +370,27 @@ void cpu_init_f (void)
MCFCSM_CSAR2 = (CFG_CS2_BASE >> 16) & 0xFFFF;
#if (CFG_CS2_WIDTH == 8)
#define CFG_CS2_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS2_WIDTH == 16)
#define CFG_CS2_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS2_WIDTH == 32)
#define CFG_CS2_PS MCFCSM_CSCR_PS_32
#else
#error "CFG_CS2_WIDTH: Fault - wrong bus with for CS2"
#endif
MCFCSM_CSCR2 = MCFCSM_CSCR_WS(CFG_CS2_WS)
|CFG_CS2_PS
|MCFCSM_CSCR_AA;
#if (CFG_CS2_RO != 0)
MCFCSM_CSMR2 = MCFCSM_CSMR_BAM(CFG_CS2_SIZE-1)
|MCFCSM_CSMR_WP
|MCFCSM_CSMR_V;
#else
MCFCSM_CSMR2 = MCFCSM_CSMR_BAM(CFG_CS2_SIZE-1)
|MCFCSM_CSMR_V;
#endif
#if (CFG_CS2_WIDTH == 8)
#define CFG_CS2_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS2_WIDTH == 16)
#define CFG_CS2_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS2_WIDTH == 32)
#define CFG_CS2_PS MCFCSM_CSCR_PS_32
#else
#warning "Chip Select 2 are not initialized/used"
#error "CFG_CS2_WIDTH: Fault - wrong bus with for CS2"
#endif
MCFCSM_CSCR2 = MCFCSM_CSCR_WS(CFG_CS2_WS)
| CFG_CS2_PS | MCFCSM_CSCR_AA;
#if (CFG_CS2_RO != 0)
MCFCSM_CSMR2 = MCFCSM_CSMR_BAM(CFG_CS2_SIZE - 1)
| MCFCSM_CSMR_WP | MCFCSM_CSMR_V;
#else
MCFCSM_CSMR2 = MCFCSM_CSMR_BAM(CFG_CS2_SIZE - 1)
| MCFCSM_CSMR_V;
#endif
#else
#warning "Chip Select 2 are not initialized/used"
#endif
#if defined(CFG_CS3_BASE) & defined(CFG_CS3_SIZE) & \
@@ -321,32 +399,30 @@ void cpu_init_f (void)
MCFCSM_CSAR3 = (CFG_CS3_BASE >> 16) & 0xFFFF;
#if (CFG_CS3_WIDTH == 8)
#define CFG_CS3_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS3_WIDTH == 16)
#define CFG_CS3_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS3_WIDTH == 32)
#define CFG_CS3_PS MCFCSM_CSCR_PS_32
#else
#error "CFG_CS3_WIDTH: Fault - wrong bus with for CS1"
#endif
MCFCSM_CSCR3 = MCFCSM_CSCR_WS(CFG_CS3_WS)
|CFG_CS3_PS
|MCFCSM_CSCR_AA;
#if (CFG_CS3_RO != 0)
MCFCSM_CSMR3 = MCFCSM_CSMR_BAM(CFG_CS3_SIZE-1)
|MCFCSM_CSMR_WP
|MCFCSM_CSMR_V;
#else
MCFCSM_CSMR3 = MCFCSM_CSMR_BAM(CFG_CS3_SIZE-1)
|MCFCSM_CSMR_V;
#endif
#if (CFG_CS3_WIDTH == 8)
#define CFG_CS3_PS MCFCSM_CSCR_PS_8
#elif (CFG_CS3_WIDTH == 16)
#define CFG_CS3_PS MCFCSM_CSCR_PS_16
#elif (CFG_CS3_WIDTH == 32)
#define CFG_CS3_PS MCFCSM_CSCR_PS_32
#else
#warning "Chip Select 3 are not initialized/used"
#error "CFG_CS3_WIDTH: Fault - wrong bus with for CS1"
#endif
MCFCSM_CSCR3 = MCFCSM_CSCR_WS(CFG_CS3_WS)
| CFG_CS3_PS | MCFCSM_CSCR_AA;
#if (CFG_CS3_RO != 0)
MCFCSM_CSMR3 = MCFCSM_CSMR_BAM(CFG_CS3_SIZE - 1)
| MCFCSM_CSMR_WP | MCFCSM_CSMR_V;
#else
MCFCSM_CSMR3 = MCFCSM_CSMR_BAM(CFG_CS3_SIZE - 1)
| MCFCSM_CSMR_V;
#endif
#else
#warning "Chip Select 3 are not initialized/used"
#endif
#endif /* CONFIG_MONITOR_IS_IN_RAM */
#endif /* CONFIG_MONITOR_IS_IN_RAM */
/* defer enabling cache until boot (see do_go) */
/* icache_enable(); */
@@ -355,10 +431,29 @@ void cpu_init_f (void)
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r (void)
int cpu_init_r(void)
{
return (0);
}
void uart_port_conf(void)
{
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
MCFGPIO_PUAPAR &= 0xFc;
MCFGPIO_PUAPAR |= 0x03;
break;
case 1:
MCFGPIO_PUAPAR &= 0xF3;
MCFGPIO_PUAPAR |= 0x0C;
break;
case 2:
MCFGPIO_PASPAR &= 0xFF0F;
MCFGPIO_PASPAR |= 0x00A0;
break;
}
}
#endif
#if defined(CONFIG_M5249)
@@ -369,33 +464,13 @@ int cpu_init_r (void)
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f (void)
void cpu_init_f(void)
{
#ifndef CFG_PLL_BYPASS
/*
* Setup the PLL to run at the specified speed
*
*/
volatile unsigned long cpll = mbar2_readLong(MCFSIM_PLLCR);
unsigned long pllcr;
#ifdef CFG_FAST_CLK
pllcr = 0x925a3100; /* ~140MHz clock (PLL bypass = 0) */
#else
pllcr = 0x135a4140; /* ~72MHz clock (PLL bypass = 0) */
#endif
cpll = cpll & 0xfffffffe; /* Set PLL bypass mode = 0 (PSTCLK = crystal) */
mbar2_writeLong(MCFSIM_PLLCR, cpll); /* Set the PLL to bypass mode (PSTCLK = crystal) */
mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* set the clock speed */
pllcr ^= 0x00000001; /* Set pll bypass to 1 */
mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* Start locking (pll bypass = 1) */
udelay(0x20); /* Wait for a lock ... */
#endif /* #ifndef CFG_PLL_BYPASS */
/*
* NOTE: by setting the GPIO_FUNCTION registers, we ensure that the UART pins
* (UART0: gpio 30,27, UART1: gpio 31, 28) will be used as UART pins
* which is their primary function.
* ~Jeremy
* (UART0: gpio 30,27, UART1: gpio 31, 28) will be used as UART pins
* which is their primary function.
* ~Jeremy
*/
mbar2_writeLong(MCFSIM_GPIO_FUNC, CFG_GPIO_FUNC);
mbar2_writeLong(MCFSIM_GPIO1_FUNC, CFG_GPIO1_FUNC);
@@ -411,7 +486,7 @@ void cpu_init_f (void)
* ~Jeremy
*
*/
mbar_writeByte(MCFSIM_MPARK, 0x30); /* 5249 Internal Core takes priority over DMA */
mbar_writeByte(MCFSIM_MPARK, 0x30); /* 5249 Internal Core takes priority over DMA */
mbar_writeByte(MCFSIM_SYPCR, 0x00);
mbar_writeByte(MCFSIM_SWIVR, 0x0f);
mbar_writeByte(MCFSIM_SWSR, 0x00);
@@ -431,7 +506,7 @@ void cpu_init_f (void)
mbar2_writeLong(MCFSIM_GPIO_INT_EN, 0x00000080);
mbar2_writeByte(MCFSIM_INTBASE, 0x40); /* Base interrupts at 64 */
mbar2_writeByte(MCFSIM_SPURVEC, 0x00);
mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); /* Enable a 1 cycle pre-drive cycle on CS1 */
mbar2_writeLong(MCFSIM_IDECONFIG1, 0x00000020); /* Enable a 1 cycle pre-drive cycle on CS1 */
/* Setup interrupt priorities for gpio7 */
/* mbar2_writeLong(MCFSIM_INTLEV5, 0x70000000); */
@@ -459,8 +534,19 @@ void cpu_init_f (void)
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r (void)
int cpu_init_r(void)
{
return (0);
}
#endif /* #if defined(CONFIG_M5249) */
void uart_port_conf(void)
{
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
break;
case 1:
break;
}
}
#endif /* #if defined(CONFIG_M5249) */

View File

@@ -1,605 +0,0 @@
/*
* (C) Copyright 2000-2004
* 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 <malloc.h>
#include <asm/fec.h>
#ifdef CONFIG_M5271
#include <asm/m5271.h>
#include <asm/immap_5271.h>
#endif
#ifdef CONFIG_M5272
#include <asm/m5272.h>
#include <asm/immap_5272.h>
#endif
#ifdef CONFIG_M5282
#include <asm/m5282.h>
#include <asm/immap_5282.h>
#endif
#include <net.h>
#include <command.h>
#ifdef CONFIG_M5272
#define FEC_ADDR (CFG_MBAR + 0x840)
#endif
#if defined(CONFIG_M5282) || defined(CONFIG_M5271)
#define FEC_ADDR (CFG_MBAR + 0x1000)
#endif
#undef ET_DEBUG
#undef MII_DEBUG
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
#ifdef CFG_DISCOVER_PHY
#include <miiphy.h>
static void mii_discover_phy (void);
#endif
/* Ethernet Transmit and Receive Buffers */
#define DBUF_LENGTH 1520
#define TX_BUF_CNT 2
#define TOUT_LOOP 100
#define PKT_MAXBUF_SIZE 1518
#define PKT_MINBUF_SIZE 64
#define PKT_MAXBLR_SIZE 1520
static char txbuf[DBUF_LENGTH];
static uint rxIdx; /* index of the current RX buffer */
static uint txIdx; /* index of the current TX buffer */
/*
* FEC Ethernet Tx and Rx buffer descriptors allocated at the
* immr->udata_bd address on Dual-Port RAM
* Provide for Double Buffering
*/
typedef volatile struct CommonBufferDescriptor {
cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
} RTXBD;
static RTXBD *rtx = NULL;
int eth_send (volatile void *packet, int length)
{
int j, rc;
volatile fec_t *fecp = (fec_t *) (FEC_ADDR);
/* section 16.9.23.3
* Wait for ready
*/
j = 0;
while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY)
&& (j < TOUT_LOOP)) {
udelay (1);
j++;
}
if (j >= TOUT_LOOP) {
printf ("TX not ready\n");
}
rtx->txbd[txIdx].cbd_bufaddr = (uint) packet;
rtx->txbd[txIdx].cbd_datlen = length;
rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
/* Activate transmit Buffer Descriptor polling */
fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */
j = 0;
while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY)
&& (j < TOUT_LOOP)) {
udelay (1);
j++;
}
if (j >= TOUT_LOOP) {
printf ("TX timeout\n");
}
#ifdef ET_DEBUG
printf ("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n",
__FILE__, __LINE__, __FUNCTION__, j, rtx->txbd[txIdx].cbd_sc,
(rtx->txbd[txIdx].cbd_sc & 0x003C) >> 2);
#endif
/* return only status bits */ ;
rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
txIdx = (txIdx + 1) % TX_BUF_CNT;
return rc;
}
int eth_rx (void)
{
int length;
volatile fec_t *fecp = (fec_t *) FEC_ADDR;
for (;;) {
/* section 16.9.23.2 */
if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
length = -1;
break; /* nothing received - leave for() loop */
}
length = rtx->rxbd[rxIdx].cbd_datlen;
if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
#ifdef ET_DEBUG
printf ("%s[%d] err: %x\n",
__FUNCTION__, __LINE__,
rtx->rxbd[rxIdx].cbd_sc);
#endif
} else {
/* Pass the packet up to the protocol layers. */
NetReceive (NetRxPackets[rxIdx], length - 4);
}
/* Give the buffer back to the FEC. */
rtx->rxbd[rxIdx].cbd_datlen = 0;
/* wrap around buffer index when necessary */
if ((rxIdx + 1) >= PKTBUFSRX) {
rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
(BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
rxIdx = 0;
} else {
rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
rxIdx++;
}
/* Try to fill Buffer Descriptors */
fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */
}
return length;
}
/**************************************************************
*
* FEC Ethernet Initialization Routine
*
*************************************************************/
#define FEC_ECNTRL_ETHER_EN 0x00000002
#define FEC_ECNTRL_RESET 0x00000001
#define FEC_RCNTRL_BC_REJ 0x00000010
#define FEC_RCNTRL_PROM 0x00000008
#define FEC_RCNTRL_MII_MODE 0x00000004
#define FEC_RCNTRL_DRT 0x00000002
#define FEC_RCNTRL_LOOP 0x00000001
#define FEC_TCNTRL_FDEN 0x00000004
#define FEC_TCNTRL_HBC 0x00000002
#define FEC_TCNTRL_GTS 0x00000001
#define FEC_RESET_DELAY 50000
int eth_init (bd_t * bd)
{
#ifndef CFG_ENET_BD_BASE
DECLARE_GLOBAL_DATA_PTR;
#endif
int i;
volatile fec_t *fecp = (fec_t *) (FEC_ADDR);
/* Whack a reset.
* A delay is required between a reset of the FEC block and
* initialization of other FEC registers because the reset takes
* some time to complete. If you don't delay, subsequent writes
* to FEC registers might get killed by the reset routine which is
* still in progress.
*/
fecp->fec_ecntrl = FEC_ECNTRL_RESET;
for (i = 0;
(fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
++i) {
udelay (1);
}
if (i == FEC_RESET_DELAY) {
printf ("FEC_RESET_DELAY timeout\n");
return 0;
}
/* We use strictly polling mode only
*/
fecp->fec_imask = 0;
/* Clear any pending interrupt */
fecp->fec_ievent = 0xffffffff;
/* Set station address */
#define ea bd->bi_enetaddr
fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) |
(ea[2] << 8) | (ea[3]);
fecp->fec_addr_high = (ea[4] << 24) | (ea[5] << 16);
#ifdef ET_DEBUG
printf ("Eth Addrs: %02x:%02x:%02x:%02x:%02x:%02x\n",
ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
#endif
#undef ea
#ifdef CONFIG_M5271
/* Clear multicast address hash table
*/
fecp->fec_ghash_table_high = 0;
fecp->fec_ghash_table_low = 0;
/* Clear individual address hash table
*/
fecp->fec_ihash_table_high = 0;
fecp->fec_ihash_table_low = 0;
#else
/* Clear multicast address hash table
*/
#ifdef CONFIG_M5282
fecp->fec_ihash_table_high = 0;
fecp->fec_ihash_table_low = 0;
#else
fecp->fec_hash_table_high = 0;
fecp->fec_hash_table_low = 0;
#endif
#endif
/* Set maximum receive buffer size.
*/
fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
/*
* Setup Buffers and Buffer Desriptors
*/
rxIdx = 0;
txIdx = 0;
if (!rtx) {
#ifdef CFG_ENET_BD_BASE
rtx = (RTXBD *) CFG_ENET_BD_BASE;
#else
rtx = (RTXBD *) (CFG_MONITOR_BASE+gd->reloc_off -
(((PKTBUFSRX+TX_BUF_CNT)*+sizeof(cbd_t)
+0xFF)
& ~0xFF)
);
debug("set ENET_DB_BASE to %lX\n",(long) rtx);
#endif
}
/*
* Setup Receiver Buffer Descriptors (13.14.24.18)
* Settings:
* Empty, Wrap
*/
for (i = 0; i < PKTBUFSRX; i++) {
rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
rtx->rxbd[i].cbd_datlen = 0; /* Reset */
rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
}
rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
/*
* Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
* Settings:
* Last, Tx CRC
*/
for (i = 0; i < TX_BUF_CNT; i++) {
rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
rtx->txbd[i].cbd_datlen = 0; /* Reset */
rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
}
rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
/* Set receive and transmit descriptor base
*/
fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
/* Enable MII mode
*/
#if 0 /* Full duplex mode */
fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;
fecp->fec_x_cntrl = FEC_TCNTRL_FDEN;
#else /* Half duplex mode */
fecp->fec_r_cntrl = (PKT_MAXBUF_SIZE << 16); /* set max frame length */
fecp->fec_r_cntrl |= FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
fecp->fec_x_cntrl = 0;
#endif
/* Set MII speed */
fecp->fec_mii_speed = (((CFG_CLK / 2) / (2500000 / 10)) + 5) / 10;
fecp->fec_mii_speed *= 2;
/* Configure port B for MII.
*/
/* port initialization was already made in cpu_init_f() */
/* Now enable the transmit and receive processing
*/
fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN;
#ifdef CFG_DISCOVER_PHY
/* wait for the PHY to wake up after reset */
mii_discover_phy ();
#endif
/* And last, try to fill Rx Buffer Descriptors */
fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */
return 1;
}
void eth_halt (void)
{
volatile fec_t *fecp = (fec_t *) FEC_ADDR;
fecp->fec_ecntrl = 0;
}
#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII)
static int phyaddr = -1; /* didn't find a PHY yet */
static uint phytype;
/* Make MII read/write commands for the FEC.
*/
#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
(REG & 0x1f) << 18))
#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
(REG & 0x1f) << 18) | \
(VAL & 0xffff))
/* Interrupt events/masks.
*/
#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
/* PHY identification
*/
#define PHY_ID_LXT970 0x78100000 /* LXT970 */
#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */
#define PHY_ID_82555 0x02a80150 /* Intel 82555 */
#define PHY_ID_QS6612 0x01814400 /* QS6612 */
#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */
#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */
#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */
/* send command to phy using mii, wait for result */
static uint mii_send (uint mii_cmd)
{
uint mii_reply;
volatile fec_t *ep = (fec_t *) (FEC_ADDR);
ep->fec_mii_data = mii_cmd; /* command to phy */
/* wait for mii complete */
while (!(ep->fec_ievent & FEC_ENET_MII)); /* spin until done */
mii_reply = ep->fec_mii_data; /* result from phy */
ep->fec_ievent = FEC_ENET_MII; /* clear MII complete */
#ifdef ET_DEBUG
printf ("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
__FILE__, __LINE__, __FUNCTION__, mii_cmd, mii_reply);
#endif
return (mii_reply & 0xffff); /* data read from phy */
}
#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */
#if defined(CFG_DISCOVER_PHY)
static void mii_discover_phy (void)
{
#define MAX_PHY_PASSES 11
uint phyno;
int pass;
phyaddr = -1; /* didn't find a PHY yet */
for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
if (pass > 1) {
/* PHY may need more time to recover from reset.
* The LXT970 needs 50ms typical, no maximum is
* specified, so wait 10ms before try again.
* With 11 passes this gives it 100ms to wake up.
*/
udelay (10000); /* wait 10ms */
}
for (phyno = 1; phyno < 32 && phyaddr < 0; ++phyno) {
phytype = mii_send (mk_mii_read (phyno, PHY_PHYIDR1));
#ifdef ET_DEBUG
printf ("PHY type 0x%x pass %d type ", phytype, pass);
#endif
if (phytype != 0xffff) {
phyaddr = phyno;
phytype <<= 16;
phytype |= mii_send (mk_mii_read (phyno,
PHY_PHYIDR2));
#ifdef ET_DEBUG
printf ("PHY @ 0x%x pass %d type ", phyno,
pass);
switch (phytype & 0xfffffff0) {
case PHY_ID_LXT970:
printf ("LXT970\n");
break;
case PHY_ID_LXT971:
printf ("LXT971\n");
break;
case PHY_ID_82555:
printf ("82555\n");
break;
case PHY_ID_QS6612:
printf ("QS6612\n");
break;
case PHY_ID_AMD79C784:
printf ("AMD79C784\n");
break;
case PHY_ID_LSI80225B:
printf ("LSI L80225/B\n");
break;
default:
printf ("0x%08x\n", phytype);
break;
}
#endif
}
}
}
if (phyaddr < 0) {
printf ("No PHY device found.\n");
}
}
#endif /* CFG_DISCOVER_PHY */
#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
static int mii_init_done = 0;
/****************************************************************************
* mii_init -- Initialize the MII for MII command without ethernet
* This function is a subset of eth_init
****************************************************************************
*/
void mii_init (void)
{
volatile fec_t *fecp = (fec_t *) (FEC_ADDR);
int i;
if (mii_init_done != 0) {
return;
}
/* Whack a reset.
* A delay is required between a reset of the FEC block and
* initialization of other FEC registers because the reset takes
* some time to complete. If you don't delay, subsequent writes
* to FEC registers might get killed by the reset routine which is
* still in progress.
*/
fecp->fec_ecntrl = FEC_ECNTRL_RESET;
for (i = 0;
(fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
++i) {
udelay (1);
}
if (i == FEC_RESET_DELAY) {
printf ("FEC_RESET_DELAY timeout\n");
return;
}
/* We use strictly polling mode only
*/
fecp->fec_imask = 0;
/* Clear any pending interrupt
*/
fecp->fec_ievent = 0xffffffff;
/* Set MII speed */
fecp->fec_mii_speed = 0x0e;
/* Configure port B for MII.
*/
/* port initialization was already made in cpu_init_f() */
/* Now enable the transmit and receive processing */
fecp->fec_ecntrl = FEC_ECNTRL_ETHER_EN;
mii_init_done = 1;
}
/*****************************************************************************
* Read and write a MII PHY register, routines used by MII Utilities
*
* FIXME: These routines are expected to return 0 on success, but mii_send
* does _not_ return an error code. Maybe 0xFFFF means error, i.e.
* no PHY connected...
* For now always return 0.
* FIXME: These routines only work after calling eth_init() at least once!
* Otherwise they hang in mii_send() !!! Sorry!
*****************************************************************************/
int mcf52x2_miiphy_read (char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
{
short rdreg; /* register working value */
#ifdef MII_DEBUG
printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
#endif
rdreg = mii_send (mk_mii_read (addr, reg));
*value = rdreg;
#ifdef MII_DEBUG
printf ("0x%04x\n", *value);
#endif
return 0;
}
int mcf52x2_miiphy_write (char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
{
short rdreg; /* register working value */
#ifdef MII_DEBUG
printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
#endif
rdreg = mii_send (mk_mii_write (addr, reg, value));
#ifdef MII_DEBUG
printf ("0x%04x\n", value);
#endif
return 0;
}
#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) */
#endif /* CFG_CMD_NET, FEC_ENET */
int mcf52x2_miiphy_initialize(bd_t *bis)
{
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
miiphy_register("mcf52x2phy", mcf52x2_miiphy_read, mcf52x2_miiphy_write);
#endif
#endif
return 0;
}

View File

@@ -1,9 +1,10 @@
/*
* (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
*
* (C) Copyright 2000-2004
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -26,140 +27,12 @@
#include <common.h>
#include <watchdog.h>
#include <asm/processor.h>
#ifdef CONFIG_M5271
#include <asm/m5271.h>
#include <asm/immap_5271.h>
#endif
#include <asm/immap.h>
#ifdef CONFIG_M5272
#include <asm/m5272.h>
#include <asm/immap_5272.h>
#endif
#ifdef CONFIG_M5282
#include <asm/m5282.h>
#include <asm/immap_5282.h>
#endif
#ifdef CONFIG_M5249
#include <asm/m5249.h>
#endif
#define NR_IRQS 31
/*
* Interrupt vector functions.
*/
struct interrupt_action {
interrupt_handler_t *handler;
void *arg;
};
static struct interrupt_action irq_vecs[NR_IRQS];
static __inline__ unsigned short get_sr (void)
int interrupt_init(void)
{
unsigned short sr;
asm volatile ("move.w %%sr,%0":"=r" (sr):);
return sr;
}
static __inline__ void set_sr (unsigned short sr)
{
asm volatile ("move.w %0,%%sr"::"r" (sr));
}
/************************************************************************/
/*
* Install and free an interrupt handler
*/
void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
{
#ifdef CONFIG_M5272
volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
#endif
int vec_base = 0;
#ifdef CONFIG_M5272
vec_base = intp->int_pivr & 0xe0;
#endif
if ((vec < vec_base) || (vec > vec_base + NR_IRQS)) {
printf ("irq_install_handler: wrong interrupt vector %d\n",
vec);
return;
}
irq_vecs[vec - vec_base].handler = handler;
irq_vecs[vec - vec_base].arg = arg;
}
void irq_free_handler (int vec)
{
#ifdef CONFIG_M5272
volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
#endif
int vec_base = 0;
#ifdef CONFIG_M5272
vec_base = intp->int_pivr & 0xe0;
#endif
if ((vec < vec_base) || (vec > vec_base + NR_IRQS)) {
return;
}
irq_vecs[vec - vec_base].handler = NULL;
irq_vecs[vec - vec_base].arg = NULL;
}
void enable_interrupts (void)
{
unsigned short sr;
sr = get_sr ();
set_sr (sr & ~0x0700);
}
int disable_interrupts (void)
{
unsigned short sr;
sr = get_sr ();
set_sr (sr | 0x0700);
return ((sr & 0x0700) == 0); /* return TRUE, if interrupts were enabled before */
}
void int_handler (struct pt_regs *fp)
{
#ifdef CONFIG_M5272
volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
#endif
int vec, vec_base = 0;
vec = (fp->vector >> 2) & 0xff;
#ifdef CONFIG_M5272
vec_base = intp->int_pivr & 0xe0;
#endif
if (irq_vecs[vec - vec_base].handler != NULL) {
irq_vecs[vec -
vec_base].handler (irq_vecs[vec - vec_base].arg);
} else {
printf ("\nBogus External Interrupt Vector %d\n", vec);
}
}
#ifdef CONFIG_M5272
int interrupt_init (void)
{
volatile intctrl_t *intp = (intctrl_t *) (CFG_MBAR + MCFSIM_ICR1);
volatile intctrl_t *intp = (intctrl_t *) (MMAP_INTC);
/* disable all external interrupts */
intp->int_icr1 = 0x88888888;
@@ -170,24 +43,59 @@ int interrupt_init (void)
/* initialize vector register */
intp->int_pivr = 0x40;
enable_interrupts ();
enable_interrupts();
return 0;
}
#endif
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
volatile intctrl_t *intp = (intctrl_t *) (CFG_INTR_BASE);
intp->int_icr1 &= ~INT_ICR1_TMR3MASK;
intp->int_icr1 |= CFG_TMRINTR_PRI;
}
#endif /* CONFIG_MCFTMR */
#endif /* CONFIG_M5272 */
#if defined(CONFIG_M5282) || defined(CONFIG_M5271)
int interrupt_init (void)
int interrupt_init(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
/* Make sure all interrupts are disabled */
intp->imrl0 |= 0x1;
enable_interrupts();
return 0;
}
#endif
#ifdef CONFIG_M5249
int interrupt_init (void)
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
enable_interrupts ();
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
intp->icr0[CFG_TMRINTR_NO] = CFG_TMRINTR_PRI;
intp->imrl0 &= ~0xFFFFFFFE;
intp->imrl0 &= ~CFG_TMRINTR_MASK;
}
#endif /* CONFIG_MCFTMR */
#endif /* CONFIG_M5282 | CONFIG_M5271 */
#if defined(CONFIG_M5249) || defined(CONFIG_M5253)
int interrupt_init(void)
{
enable_interrupts();
return 0;
}
#endif
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
mbar_writeLong(MCFSIM_IMR, mbar_readLong(MCFSIM_IMR) & ~0x00000400);
mbar_writeByte(MCFSIM_TIMER2ICR, CFG_TMRINTR_PRI);
}
#endif /* CONFIG_MCFTMR */
#endif /* CONFIG_M5249 || CONFIG_M5253 */

View File

@@ -1,215 +0,0 @@
/*
* (C) Copyright 2000-2004
* 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 <command.h>
#include <watchdog.h>
#include <asm/mcfuart.h>
#ifdef CONFIG_M5271
#include <asm/m5271.h>
#endif
#ifdef CONFIG_M5272
#include <asm/m5272.h>
#endif
#ifdef CONFIG_M5282
#include <asm/m5282.h>
#endif
#ifdef CONFIG_M5249
#include <asm/m5249.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_M5249) || defined(CONFIG_M5271)
#define DoubleClock(a) ((double)(CFG_CLK/2) / 32.0 / (double)(a))
#else
#define DoubleClock(a) ((double)(CFG_CLK) / 32.0 / (double)(a))
#endif
void rs_serial_setbaudrate(int port,int baudrate)
{
#if defined(CONFIG_M5272) || defined(CONFIG_M5249) || defined(CONFIG_M5271)
volatile unsigned char *uartp;
# ifndef CONFIG_M5271
double fraction;
# endif
double clock;
if (port == 0)
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
else
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2);
clock = DoubleClock(baudrate); /* Set baud above */
uartp[MCFUART_UBG1] = (((int)clock >> 8) & 0xff); /* set msb baud */
uartp[MCFUART_UBG2] = ((int)clock & 0xff); /* set lsb baud */
# ifndef CONFIG_M5271
fraction = ((clock - (int)clock) * 16.0) + 0.5;
uartp[MCFUART_UFPD] = ((int)fraction & 0xf); /* set baud fraction adjust */
# endif
#endif
#if defined(CONFIG_M5282)
volatile unsigned char *uartp;
long clock;
switch (port) {
case 1:
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2);
break;
case 2:
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE3);
break;
default:
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
}
clock = (long) CFG_CLK / ((long) 32 * baudrate); /* Set baud above */
uartp[MCFUART_UBG1] = (((int)clock >> 8) & 0xff); /* set msb baud */
uartp[MCFUART_UBG2] = ((int) clock & 0xff); /* set lsb baud */
#endif
};
void rs_serial_init (int port, int baudrate)
{
volatile unsigned char *uartp;
/*
* Reset UART, get it into known state...
*/
switch (port) {
case 1:
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2);
break;
#if defined(CONFIG_M5282)
case 2:
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE3);
break;
#endif
default:
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
}
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; /* reset Error pointer */
/*
* Set port for CONSOLE_BAUD_RATE, 8 data bits, 1 stop bit, no parity.
*/
uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
/* Mask UART interrupts */
uartp[MCFUART_UIMR] = 0;
/* Set clock Select Register: Tx/Rx clock is timer */
uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
rs_serial_setbaudrate (port, baudrate);
/* Enable Tx/Rx */
uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
return;
}
/****************************************************************************/
/*
* Output a single character, using UART polled mode.
* This is used for console output.
*/
void rs_put_char(char ch)
{
volatile unsigned char *uartp;
int i;
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
for (i = 0; (i < 0x10000); i++) {
if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY)
break;
}
uartp[MCFUART_UTB] = ch;
return;
}
int rs_is_char(void)
{
volatile unsigned char *uartp;
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
return((uartp[MCFUART_USR] & MCFUART_USR_RXREADY) ? 1 : 0);
}
int rs_get_char(void)
{
volatile unsigned char *uartp;
uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
return(uartp[MCFUART_URB]);
}
void serial_setbrg(void) {
rs_serial_setbaudrate(0,gd->bd->bi_baudrate);
}
int serial_init(void) {
rs_serial_init(0,gd->baudrate);
return 0;
}
void serial_putc(const char c) {
if (c == '\n')
serial_putc ('\r');
rs_put_char(c);
}
void serial_puts (const char *s) {
while (*s)
serial_putc(*s++);
}
int serial_getc(void) {
while(!rs_is_char())
WATCHDOG_RESET();
return rs_get_char();
}
int serial_tstc() {
return rs_is_char();
}

View File

@@ -2,6 +2,9 @@
* (C) Copyright 2003
* Josef Baumgartner <josef.baumgartner@telex.de>
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* Hayden Fraser (Hayden.Fraser@freescale.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -23,6 +26,7 @@
#include <common.h>
#include <asm/processor.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -31,8 +35,37 @@ DECLARE_GLOBAL_DATA_PTR;
*/
int get_clocks (void)
{
gd->cpu_clk = CFG_CLK;
#if defined(CONFIG_M5249) || defined(CONFIG_M5253)
volatile unsigned long cpll = mbar2_readLong(MCFSIM_PLLCR);
unsigned long pllcr;
#ifndef CFG_PLL_BYPASS
#ifdef CONFIG_M5249
/* Setup the PLL to run at the specified speed */
#ifdef CFG_FAST_CLK
pllcr = 0x925a3100; /* ~140MHz clock (PLL bypass = 0) */
#else
pllcr = 0x135a4140; /* ~72MHz clock (PLL bypass = 0) */
#endif
#endif /* CONFIG_M5249 */
#ifdef CONFIG_M5253
pllcr = CFG_PLLCR;
#endif /* CONFIG_M5253 */
cpll = cpll & 0xfffffffe; /* Set PLL bypass mode = 0 (PSTCLK = crystal) */
mbar2_writeLong(MCFSIM_PLLCR, cpll); /* Set the PLL to bypass mode (PSTCLK = crystal) */
mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* set the clock speed */
pllcr ^= 0x00000001; /* Set pll bypass to 1 */
mbar2_writeLong(MCFSIM_PLLCR, pllcr); /* Start locking (pll bypass = 1) */
udelay(0x20); /* Wait for a lock ... */
#endif /* #ifndef CFG_PLL_BYPASS */
#endif /* CONFIG_M5249 || CONFIG_M5253 */
gd->cpu_clk = CFG_CLK;
#if defined(CONFIG_M5249) || defined(CONFIG_M5253)
gd->bus_clk = gd->cpu_clk / 2;
#else
gd->bus_clk = gd->cpu_clk;

View File

@@ -121,7 +121,7 @@ _start:
nop
move.w #0x2700,%sr
#if defined(CONFIG_M5272) || defined(CONFIG_M5249)
#if defined(CONFIG_M5272) || defined(CONFIG_M5249) || defined(CONFIG_M5253)
move.l #(CFG_MBAR + 1), %d0 /* set MBAR address + valid flag */
move.c %d0, %MBAR
@@ -133,7 +133,7 @@ _start:
move.l #(CFG_INIT_RAM_ADDR + 1), %d0
movec %d0, %RAMBAR0
#endif /* #if defined(CONFIG_M5272) || defined(CONFIG_M5249) */
#endif /* CONFIG_M5272 || CONFIG_M5249 || CONFIG_M5253 */
#if defined(CONFIG_M5282) || defined(CONFIG_M5271)
/* Initialize IPSBAR */
@@ -159,7 +159,7 @@ _copy_flash:
_flashbar_setup:
/* Initialize FLASHBAR: locate internal Flash and validate it */
move.l #(CFG_INT_FLASH_BASE + 0x21), %d0
move.l #(CFG_INT_FLASH_BASE + CFG_INT_FLASH_ENABLE), %d0
movec %d0, %RAMBAR0
jmp _after_flashbar_copy.L /* Force jump to absolute address */
_flashbar_setup_end:
@@ -167,7 +167,7 @@ _flashbar_setup_end:
_after_flashbar_copy:
#else
/* Setup code to initialize FLASHBAR, if start from external Memory */
move.l #(CFG_INT_FLASH_BASE + 0x21), %d0
move.l #(CFG_INT_FLASH_BASE + CFG_INT_FLASH_ENABLE), %d0
movec %d0, %RAMBAR0
#endif /* (TEXT_BASE == CFG_INT_FLASH_BASE) */
@@ -326,10 +326,10 @@ clear_bss:
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */
move.l %d0,-(%sp) /* gd */
#if defined(DEBUG) && (TEXT_BASE != CFG_INT_FLASH_BASE) && \
defined(CFG_HALT_BEFOR_RAM_JUMP)
halt
#endif
#if defined(DEBUG) && (TEXT_BASE != CFG_INT_FLASH_BASE) && \
defined(CFG_HALT_BEFOR_RAM_JUMP)
halt
#endif
jsr (%a1)
/*------------------------------------------------------------------------------*/
@@ -356,6 +356,24 @@ _int_handler:
/*------------------------------------------------------------------------------*/
/* cache functions */
#ifdef CONFIG_M5271
.globl icache_enable
icache_enable:
move.l #0x01000000, %d0 /* Invalidate cache cmd */
movec %d0, %CACR /* Invalidate cache */
move.l #(CFG_SDRAM_BASE + 0xc000), %d0 /* Setup cache mask */
movec %d0, %ACR0 /* Enable cache */
move.l #0x80000200, %d0 /* Setup cache mask */
movec %d0, %CACR /* Enable cache */
nop
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
#endif
#ifdef CONFIG_M5272
.globl icache_enable
icache_enable:
@@ -389,7 +407,7 @@ icache_state_access_1:
rts
#endif
#ifdef CONFIG_M5249
#if defined(CONFIG_M5249) || defined(CONFIG_M5253)
.globl icache_enable
icache_enable:
/*
@@ -426,13 +444,29 @@ icache_state_access_2:
.globl icache_status
icache_status:
icache_state_access_3:
move.l icache_state, %d0
move.l #(icache_state), %a0
move.l (%a0), %d0
rts
.data
icache_state:
.long 0 /* cache is diabled on inirialization */
.globl dcache_enable
dcache_enable:
/* dummy function */
rts
.globl dcache_disable
dcache_disable:
/* dummy function */
rts
.globl dcache_status
dcache_status:
/* dummy function */
rts
/*------------------------------------------------------------------------------*/
.globl version_string

48
cpu/mcf532x/Makefile Normal file
View File

@@ -0,0 +1,48 @@
#
# (C) Copyright 2000-2004
# 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
# CFLAGS += -DET_DEBUG
LIB = lib$(CPU).a
START =
COBJS = cpu.o speed.o cpu_init.o interrupts.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
START := $(addprefix $(obj),$(START))
all: $(obj).depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

27
cpu/mcf532x/config.mk Normal file
View File

@@ -0,0 +1,27 @@
#
# (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
#
# (C) Copyright 2000-2004
# 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
#
PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
PLATFORM_CPPFLAGS += -m5307 -fPIC

119
cpu/mcf532x/cpu.c Normal file
View File

@@ -0,0 +1,119 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <watchdog.h>
#include <command.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
wdp->cr = 0;
udelay(1000);
/* enable watchdog, set timeout to 0 and wait */
wdp->cr = WTM_WCR_EN;
while (1) ;
/* we don't return! */
return 0;
};
int checkcpu(void)
{
volatile ccm_t *ccm = (ccm_t *) MMAP_CCM;
u16 msk;
u16 id = 0;
u8 ver;
puts("CPU: ");
msk = (ccm->cir >> 6);
ver = (ccm->cir & 0x003f);
switch (msk) {
case 0x54:
id = 5329;
break;
case 0x59:
id = 5328;
break;
case 0x61:
id = 5327;
break;
}
if (id) {
printf("Freescale MCF%d (Mask:%01x Version:%x)\n", id, msk,
ver);
printf(" CPU CLK %d Mhz BUS CLK %d Mhz\n",
(int)(gd->cpu_clk / 1000000),
(int)(gd->bus_clk / 1000000));
}
return 0;
};
#if defined(CONFIG_WATCHDOG)
/* Called by macro WATCHDOG_RESET */
void watchdog_reset(void)
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
wdp->sr = 0x5555; /* Count register */
}
int watchdog_disable(void)
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
/* UserManual, once the wdog is disabled, wdog cannot be re-enabled */
wdp->cr |= WTM_WCR_HALTED; /* halted watchdog timer */
puts("WATCHDOG:disabled\n");
return (0);
}
int watchdog_init(void)
{
volatile wdog_t *wdp = (wdog_t *) (MMAP_WDOG);
u32 wdog_module = 0;
/* set timeout and enable watchdog */
wdog_module = ((CFG_CLK / 1000) * CONFIG_WATCHDOG_TIMEOUT);
wdog_module |= (wdog_module / 8192);
wdp->mr = wdog_module;
wdp->cr = WTM_WCR_EN;
puts("WATCHDOG:enabled\n");
return (0);
}
#endif /* CONFIG_WATCHDOG */

141
cpu/mcf532x/cpu_init.c Normal file
View File

@@ -0,0 +1,141 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* (C) Copyright 2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <watchdog.h>
#include <asm/immap.h>
/*
* Breath some life into the CPU...
*
* Set up the memory map,
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f(void)
{
volatile scm1_t *scm1 = (scm1_t *) MMAP_SCM1;
volatile scm2_t *scm2 = (scm2_t *) MMAP_SCM2;
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
volatile wdog_t *wdog = (wdog_t *) MMAP_WDOG;
/* watchdog is enabled by default - disable the watchdog */
#ifndef CONFIG_WATCHDOG
wdog->cr = 0;
#endif
scm1->mpr0 = 0x77777777;
scm2->pacra = 0;
scm2->pacrb = 0;
scm2->pacrc = 0;
scm2->pacrd = 0;
scm2->pacre = 0;
scm2->pacrf = 0;
scm2->pacrg = 0;
scm1->pacrh = 0;
/* Port configuration */
gpio->par_cs = 0;
#if (defined(CFG_CS0_BASE) && defined(CFG_CS0_MASK) && defined(CFG_CS0_CTRL))
fbcs->csar0 = CFG_CS0_BASE;
fbcs->cscr0 = CFG_CS0_CTRL;
fbcs->csmr0 = CFG_CS0_MASK;
#endif
#if (defined(CFG_CS1_BASE) && defined(CFG_CS1_MASK) && defined(CFG_CS1_CTRL))
/* Latch chipselect */
gpio->par_cs |= GPIO_PAR_CS1;
fbcs->csar1 = CFG_CS1_BASE;
fbcs->cscr1 = CFG_CS1_CTRL;
fbcs->csmr1 = CFG_CS1_MASK;
#endif
#if (defined(CFG_CS2_BASE) && defined(CFG_CS2_MASK) && defined(CFG_CS2_CTRL))
gpio->par_cs |= GPIO_PAR_CS2;
fbcs->csar2 = CFG_CS2_BASE;
fbcs->cscr2 = CFG_CS2_CTRL;
fbcs->csmr2 = CFG_CS2_MASK;
#endif
#if (defined(CFG_CS3_BASE) && defined(CFG_CS3_MASK) && defined(CFG_CS3_CTRL))
gpio->par_cs |= GPIO_PAR_CS3;
fbcs->csar3 = CFG_CS3_BASE;
fbcs->cscr3 = CFG_CS3_CTRL;
fbcs->csmr3 = CFG_CS3_MASK;
#endif
#if (defined(CFG_CS4_BASE) && defined(CFG_CS4_MASK) && defined(CFG_CS4_CTRL))
gpio->par_cs |= GPIO_PAR_CS4;
fbcs->csar4 = CFG_CS4_BASE;
fbcs->cscr4 = CFG_CS4_CTRL;
fbcs->csmr4 = CFG_CS4_MASK;
#endif
#if (defined(CFG_CS5_BASE) && defined(CFG_CS5_MASK) && defined(CFG_CS5_CTRL))
gpio->par_cs |= GPIO_PAR_CS5;
fbcs->csar5 = CFG_CS5_BASE;
fbcs->cscr5 = CFG_CS5_CTRL;
fbcs->csmr5 = CFG_CS5_MASK;
#endif
#ifdef CONFIG_FSL_I2C
gpio->par_feci2c = GPIO_PAR_FECI2C_SCL_SCL | GPIO_PAR_FECI2C_SDA_SDA;
#endif
icache_enable();
}
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r(void)
{
return (0);
}
void uart_port_conf(void)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
gpio->par_uart = (GPIO_PAR_UART_TXD0 | GPIO_PAR_UART_RXD0);
break;
case 1:
gpio->par_uart =
(GPIO_PAR_UART_TXD1(3) | GPIO_PAR_UART_RXD1(3));
break;
case 2:
gpio->par_timer &= 0x0F;
gpio->par_timer |= (GPIO_PAR_TIN3_URXD2 | GPIO_PAR_TIN2_UTXD2);
break;
}
}

49
cpu/mcf532x/interrupts.c Normal file
View File

@@ -0,0 +1,49 @@
/*
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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
*/
/* CPU specific interrupt routine */
#include <common.h>
#include <asm/immap.h>
int interrupt_init(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
/* Make sure all interrupts are disabled */
intp->imrh0 |= 0xFFFFFFFF;
intp->imrl0 |= 0xFFFFFFFF;
enable_interrupts();
return 0;
}
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
intp->icr0[CFG_TMRINTR_NO] = CFG_TMRINTR_PRI;
intp->imrh0 &= ~CFG_TMRINTR_MASK;
}
#endif

216
cpu/mcf532x/speed.c Normal file
View File

@@ -0,0 +1,216 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <asm/processor.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
/* PLL min/max specifications */
#define MAX_FVCO 500000 /* KHz */
#define MAX_FSYS 80000 /* KHz */
#define MIN_FSYS 58333 /* KHz */
#define FREF 16000 /* KHz */
#define MAX_MFD 135 /* Multiplier */
#define MIN_MFD 88 /* Multiplier */
#define BUSDIV 6 /* Divider */
/*
* Low Power Divider specifications
*/
#define MIN_LPD (1 << 0) /* Divider (not encoded) */
#define MAX_LPD (1 << 15) /* Divider (not encoded) */
#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
/*
* Get the value of the current system clock
*
* Parameters:
* none
*
* Return Value:
* The current output system frequency
*/
int get_sys_clock(void)
{
volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
int divider;
/* Test to see if device is in LIMP mode */
if (ccm->misccr & CCM_MISCCR_LIMP) {
divider = ccm->cdr & CCM_CDR_LPDIV(0xF);
return (FREF / (2 << divider));
} else {
return ((FREF * pll->pfdr) / (BUSDIV * 4));
}
}
/*
* Initialize the Low Power Divider circuit
*
* Parameters:
* div Desired system frequency divider
*
* Return Value:
* The resulting output system frequency
*/
int clock_limp(int div)
{
volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
u32 temp;
/* Check bounds of divider */
if (div < MIN_LPD)
div = MIN_LPD;
if (div > MAX_LPD)
div = MAX_LPD;
/* Save of the current value of the SSIDIV so we don't overwrite the value */
temp = (ccm->cdr & CCM_CDR_SSIDIV(0xF));
/* Apply the divider to the system clock */
ccm->cdr = (CCM_CDR_LPDIV(div) | CCM_CDR_SSIDIV(temp));
ccm->misccr |= CCM_MISCCR_LIMP;
return (FREF / (3 * (1 << div)));
}
/*
* Exit low power LIMP mode
*
* Parameters:
* div Desired system frequency divider
*
* Return Value:
* The resulting output system frequency
*/
int clock_exit_limp(void)
{
volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
int fout;
/* Exit LIMP mode */
ccm->misccr &= (~CCM_MISCCR_LIMP);
/* Wait for PLL to lock */
while (!(ccm->misccr & CCM_MISCCR_PLL_LOCK)) ;
fout = get_sys_clock();
return fout;
}
/* Initialize the PLL
*
* Parameters:
* fref PLL reference clock frequency in KHz
* fsys Desired PLL output frequency in KHz
* flags Operating parameters
*
* Return Value:
* The resulting output system frequency
*/
int clock_pll(int fsys, int flags)
{
volatile u32 *sdram_workaround = (volatile u32 *)(MMAP_SDRAM + 0x80);
volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
int fref, temp, fout, mfd;
u32 i;
fref = FREF;
if (fsys == 0) {
/* Return current PLL output */
mfd = pll->pfdr;
return (fref * mfd / (BUSDIV * 4));
}
/* Check bounds of requested system clock */
if (fsys > MAX_FSYS)
fsys = MAX_FSYS;
if (fsys < MIN_FSYS)
fsys = MIN_FSYS;
/* Multiplying by 100 when calculating the temp value,
and then dividing by 100 to calculate the mfd allows
for exact values without needing to include floating
point libraries. */
temp = (100 * fsys) / fref;
mfd = (4 * BUSDIV * temp) / 100;
/* Determine the output frequency for selected values */
fout = ((fref * mfd) / (BUSDIV * 4));
/*
* Check to see if the SDRAM has already been initialized.
* If it has then the SDRAM needs to be put into self refresh
* mode before reprogramming the PLL.
*/
/*
* Initialize the PLL to generate the new system clock frequency.
* The device must be put into LIMP mode to reprogram the PLL.
*/
/* Enter LIMP mode */
clock_limp(DEFAULT_LPD);
/* Reprogram PLL for desired fsys */
pll->podr = (PLL_PODR_CPUDIV(BUSDIV / 3) | PLL_PODR_BUSDIV(BUSDIV));
pll->pfdr = mfd;
/* Exit LIMP mode */
clock_exit_limp();
/*
* Return the SDRAM to normal operation if it is in use.
*/
/* software workaround for SDRAM opeartion after exiting LIMP mode errata */
*sdram_workaround = CFG_SDRAM_BASE;
/* wait for DQS logic to relock */
for (i = 0; i < 0x200; i++) ;
return fout;
}
/*
* get_clocks() fills in gd->cpu_clock and gd->bus_clk
*/
int get_clocks(void)
{
gd->bus_clk = clock_pll(CFG_CLK / 1000, 0) * 1000;
gd->cpu_clk = (gd->bus_clk * 3);
return (0);
}

335
cpu/mcf532x/start.S Normal file
View File

@@ -0,0 +1,335 @@
/*
* Copyright (C) 2003 Josef Baumgartner <josef.baumgartner@telex.de>
* Based on code from Bernhard Kuhn <bkuhn@metrowerks.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 <config.h>
#include "version.h"
#ifndef CONFIG_IDENT_STRING
#define CONFIG_IDENT_STRING ""
#endif
#define _START _start
#define _FAULT _fault
#define SAVE_ALL \
move.w #0x2700,%sr; /* disable intrs */ \
subl #60,%sp; /* space for 15 regs */ \
moveml %d0-%d7/%a0-%a6,%sp@;
#define RESTORE_ALL \
moveml %sp@,%d0-%d7/%a0-%a6; \
addl #60,%sp; /* space for 15 regs */ \
rte;
.text
/*
* Vector table. This is used for initial platform startup.
* These vectors are to catch any un-intended traps.
*/
_vectors:
INITSP: .long 0x00000000 /* Initial SP */
INITPC: .long _START /* Initial PC */
vector02: .long _FAULT /* Access Error */
vector03: .long _FAULT /* Address Error */
vector04: .long _FAULT /* Illegal Instruction */
vector05: .long _FAULT /* Reserved */
vector06: .long _FAULT /* Reserved */
vector07: .long _FAULT /* Reserved */
vector08: .long _FAULT /* Privilege Violation */
vector09: .long _FAULT /* Trace */
vector0A: .long _FAULT /* Unimplemented A-Line */
vector0B: .long _FAULT /* Unimplemented F-Line */
vector0C: .long _FAULT /* Debug Interrupt */
vector0D: .long _FAULT /* Reserved */
vector0E: .long _FAULT /* Format Error */
vector0F: .long _FAULT /* Unitialized Int. */
/* Reserved */
vector10_17:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector18: .long _FAULT /* Spurious Interrupt */
vector19: .long _FAULT /* Autovector Level 1 */
vector1A: .long _FAULT /* Autovector Level 2 */
vector1B: .long _FAULT /* Autovector Level 3 */
vector1C: .long _FAULT /* Autovector Level 4 */
vector1D: .long _FAULT /* Autovector Level 5 */
vector1E: .long _FAULT /* Autovector Level 6 */
vector1F: .long _FAULT /* Autovector Level 7 */
/* TRAP #0 - #15 */
vector20_2F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
/* Reserved */
vector30_3F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector64_127:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector128_191:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector192_255:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.text
.globl _start
_start:
nop
nop
move.w #0x2700,%sr /* Mask off Interrupt */
/* Set vector base register at the beginning of the Flash */
move.l #CFG_FLASH_BASE, %d0
movec %d0, %VBR
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_RAM_CTRL), %d0
movec %d0, %RAMBAR0
/* invalidate and disable cache */
move.l #0x01000000, %d0 /* Invalidate cache cmd */
movec %d0, %CACR /* Invalidate cache */
move.l #0, %d0
movec %d0, %ACR0
movec %d0, %ACR1
/* initialize general use internal ram */
move.l #0, %d0
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a2
move.l %d0, (%a1)
move.l %d0, (%a2)
/* set stackpointer to end of internal ram to get some stackspace for the
first c-code */
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET), %sp
clr.l %sp@-
move.l #__got_start, %a5 /* put relocation table address to a5 */
bsr cpu_init_f /* run low-level CPU init code (from flash) */
bsr board_init_f /* run low-level board init code (from flash) */
/* board_init_f() does not return */
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* r3 = dest
* r4 = src
* r5 = length in bytes
* r6 = cachelinesize
*/
.globl relocate_code
relocate_code:
link.w %a6,#0
move.l 8(%a6), %sp /* set new stack pointer */
move.l 12(%a6), %d0 /* Save copy of Global Data pointer */
move.l 16(%a6), %a0 /* Save copy of Destination Address */
move.l #CFG_MONITOR_BASE, %a1
move.l #__init_end, %a2
move.l %a0, %a3
/* copy the code to RAM */
1:
move.l (%a1)+, (%a3)+
cmp.l %a1,%a2
bgt.s 1b
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
move.l %a0, %a1
add.l #(in_ram - CFG_MONITOR_BASE), %a1
jmp (%a1)
in_ram:
clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CFG_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CFG_MONITOR_BASE),%d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
bgt.s 6b
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CFG_MONITOR_BASE),%a1
move.l %a1,%a5 /* * fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CFG_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CFG_MONITOR_BASE), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */
move.l %d0,-(%sp) /* gd */
jsr (%a1)
/*------------------------------------------------------------------------------*/
/* exception code */
.globl _fault
_fault:
jmp _fault
.globl _exc_handler
_exc_handler:
SAVE_ALL
movel %sp,%sp@-
bsr exc_handler
addql #4,%sp
RESTORE_ALL
.globl _int_handler
_int_handler:
SAVE_ALL
movel %sp,%sp@-
bsr int_handler
addql #4,%sp
RESTORE_ALL
/*------------------------------------------------------------------------------*/
/* cache functions */
.globl icache_enable
icache_enable:
move.l #0x01000000, %d0 /* Invalidate cache cmd */
movec %d0, %CACR /* Invalidate cache */
move.l #(CFG_SDRAM_BASE + 0xc000 + ((CFG_SDRAM_SIZE & 0x1fe0) << 11)), %d0
movec %d0, %ACR0 /* Enable cache */
move.l #0x80000200, %d0 /* Setup cache mask */
movec %d0, %CACR /* Enable cache */
nop
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
.globl icache_disable
icache_disable:
move.l #0x01000000, %d0 /* Setup cache mask */
movec %d0, %CACR /* Disable cache */
clr.l %d0 /* Setup cache mask */
movec %d0, %ACR0
movec %d0, %ACR1
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
moveq #0, %d0
move.l %d0, (%a1)
rts
.globl icache_status
icache_status:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-8), %a1
move.l (%a1), %d0
rts
.globl icache_invalid
icache_invalid:
move.l #0x81000200, %d0 /* Setup cache mask */
movec %d0, %CACR /* Enable cache */
rts
.globl dcache_enable
dcache_enable:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
/* No dcache, just a dummy function */
.globl dcache_disable
dcache_disable:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a1
moveq #0, %d0
move.l %d0, (%a1)
rts
.globl dcache_status
dcache_status:
move.l #(CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-4), %a1
move.l (%a1), %d0
rts
/*------------------------------------------------------------------------------*/
.globl version_string
version_string:
.ascii U_BOOT_VERSION
.ascii " (", __DATE__, " - ", __TIME__, ")"
.ascii CONFIG_IDENT_STRING, "\0"

48
cpu/mcf5445x/Makefile Normal file
View File

@@ -0,0 +1,48 @@
#
# (C) Copyright 2000-2004
# 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
# CFLAGS += -DET_DEBUG
LIB = lib$(CPU).a
START = start.o
COBJS = cpu.o speed.o cpu_init.o interrupts.o pci.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
START := $(addprefix $(obj),$(START))
all: $(obj).depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

27
cpu/mcf5445x/config.mk Normal file
View File

@@ -0,0 +1,27 @@
#
# (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
#
# (C) Copyright 2000-2004
# 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
#
PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
PLATFORM_CPPFLAGS += -m5407 -fPIC

97
cpu/mcf5445x/cpu.c Normal file
View File

@@ -0,0 +1,97 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <watchdog.h>
#include <command.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
int do_reset(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
{
volatile rcm_t *rcm = (rcm_t *) (MMAP_RCM);
udelay(1000);
rcm->rcr |= RCM_RCR_SOFTRST;
/* we don't return! */
return 0;
};
int checkcpu(void)
{
volatile ccm_t *ccm = (ccm_t *) MMAP_CCM;
u16 msk;
u16 id = 0;
u8 ver;
puts("CPU: ");
msk = (ccm->cir >> 6);
ver = (ccm->cir & 0x003f);
switch (msk) {
case 0x48:
id = 54455;
break;
case 0x49:
id = 54454;
break;
case 0x4a:
id = 54453;
break;
case 0x4b:
id = 54452;
break;
case 0x4d:
id = 54451;
break;
case 0x4f:
id = 54450;
break;
}
if (id) {
printf("Freescale MCF%d (Mask:%01x Version:%x)\n", id, msk,
ver);
printf(" CPU CLK %d Mhz BUS CLK %d Mhz FLB CLK %d Mhz\n",
(int)(gd->cpu_clk / 1000000),
(int)(gd->bus_clk / 1000000),
(int)(gd->flb_clk / 1000000));
#ifdef CONFIG_PCI
printf(" PCI CLK %d Mhz INP CLK %d Mhz VCO CLK %d Mhz\n",
(int)(gd->pci_clk / 1000000),
(int)(gd->inp_clk / 1000000),
(int)(gd->vco_clk / 1000000));
#else
printf(" INP CLK %d Mhz VCO CLK %d Mhz\n",
(int)(gd->inp_clk / 1000000),
(int)(gd->vco_clk / 1000000));
#endif
}
return 0;
}

140
cpu/mcf5445x/cpu_init.c Normal file
View File

@@ -0,0 +1,140 @@
/*
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* (C) Copyright 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <watchdog.h>
#include <asm/immap.h>
#include <asm/rtc.h>
/*
* Breath some life into the CPU...
*
* Set up the memory map,
* initialize a bunch of registers,
* initialize the UPM's
*/
void cpu_init_f(void)
{
volatile scm1_t *scm1 = (scm1_t *) MMAP_SCM1;
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
volatile fbcs_t *fbcs = (fbcs_t *) MMAP_FBCS;
scm1->mpr = 0x77777777;
scm1->pacra = 0;
scm1->pacrb = 0;
scm1->pacrc = 0;
scm1->pacrd = 0;
scm1->pacre = 0;
scm1->pacrf = 0;
scm1->pacrg = 0;
/* FlexBus */
gpio->par_be =
GPIO_PAR_BE_BE3_BE3 | GPIO_PAR_BE_BE2_BE2 | GPIO_PAR_BE_BE1_BE1 |
GPIO_PAR_BE_BE0_BE0;
gpio->par_fbctl =
GPIO_PAR_FBCTL_OE | GPIO_PAR_FBCTL_TA_TA | GPIO_PAR_FBCTL_RW_RW |
GPIO_PAR_FBCTL_TS_TS;
#if (defined(CFG_CS0_BASE) && defined(CFG_CS0_MASK) && defined(CFG_CS0_CTRL))
fbcs->csar0 = CFG_CS0_BASE;
fbcs->cscr0 = CFG_CS0_CTRL;
fbcs->csmr0 = CFG_CS0_MASK;
#endif
#if (defined(CFG_CS1_BASE) && defined(CFG_CS1_MASK) && defined(CFG_CS1_CTRL))
/* Latch chipselect */
fbcs->csar1 = CFG_CS1_BASE;
fbcs->cscr1 = CFG_CS1_CTRL;
fbcs->csmr1 = CFG_CS1_MASK;
#endif
#if (defined(CFG_CS2_BASE) && defined(CFG_CS2_MASK) && defined(CFG_CS2_CTRL))
fbcs->csar2 = CFG_CS2_BASE;
fbcs->cscr2 = CFG_CS2_CTRL;
fbcs->csmr2 = CFG_CS2_MASK;
#endif
#if (defined(CFG_CS3_BASE) && defined(CFG_CS3_MASK) && defined(CFG_CS3_CTRL))
fbcs->csar3 = CFG_CS3_BASE;
fbcs->cscr3 = CFG_CS3_CTRL;
fbcs->csmr3 = CFG_CS3_MASK;
#endif
#if (defined(CFG_CS4_BASE) && defined(CFG_CS4_MASK) && defined(CFG_CS4_CTRL))
fbcs->csar4 = CFG_CS4_BASE;
fbcs->cscr4 = CFG_CS4_CTRL;
fbcs->csmr4 = CFG_CS4_MASK;
#endif
#if (defined(CFG_CS5_BASE) && defined(CFG_CS5_MASK) && defined(CFG_CS5_CTRL))
fbcs->csar5 = CFG_CS5_BASE;
fbcs->cscr5 = CFG_CS5_CTRL;
fbcs->csmr5 = CFG_CS5_MASK;
#endif
#ifdef CONFIG_FSL_I2C
gpio->par_feci2c = GPIO_PAR_FECI2C_SCL_SCL | GPIO_PAR_FECI2C_SDA_SDA;
#endif
icache_enable();
}
/*
* initialize higher level parts of CPU like timers
*/
int cpu_init_r(void)
{
#ifdef CONFIG_MCFTMR
volatile rtc_t *rtc = (volatile rtc_t *)(CFG_MCFRTC_BASE);
volatile rtcex_t *rtcex = (volatile rtcex_t *)&rtc->extended;
u32 oscillator = CFG_RTC_OSCILLATOR;
rtcex->gocu = (CFG_RTC_OSCILLATOR >> 16) & 0xFFFF;
rtcex->gocl = CFG_RTC_OSCILLATOR & 0xFFFF;
#endif
return (0);
}
void uart_port_conf(void)
{
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
/* Setup Ports: */
switch (CFG_UART_PORT) {
case 0:
gpio->par_uart =
(GPIO_PAR_UART_U0TXD_U0TXD | GPIO_PAR_UART_U0RXD_U0RXD);
break;
case 1:
gpio->par_uart =
(GPIO_PAR_UART_U1TXD_U1TXD | GPIO_PAR_UART_U1RXD_U1RXD);
break;
}
}

52
cpu/mcf5445x/interrupts.c Normal file
View File

@@ -0,0 +1,52 @@
/*
*
* (C) Copyright 2000-2004
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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
*/
/* CPU specific interrupt routine */
#include <common.h>
#include <asm/immap.h>
int interrupt_init(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
/* Make sure all interrupts are disabled */
intp->imrh0 |= 0xFFFFFFFF;
intp->imrl0 |= 0xFFFFFFFF;
enable_interrupts();
return 0;
}
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
volatile int0_t *intp = (int0_t *) (CFG_INTR_BASE);
intp->icr0[CFG_TMRINTR_NO] = CFG_TMRINTR_PRI;
intp->imrh0 &= ~CFG_TMRINTR_MASK;
}
#endif

189
cpu/mcf5445x/pci.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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
*/
/*
* PCI Configuration space access support
*/
#include <common.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/immap.h>
#if defined(CONFIG_PCI)
/* System RAM mapped over PCI */
#define CFG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE
#define CFG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE
#define CFG_PCI_SYS_MEM_SIZE (1024 * 1024 * 1024)
#define cfg_read(val, addr, type, op) *val = op((type)(addr));
#define cfg_write(val, addr, type, op) op((type *)(addr), (val));
#define PCI_OP(rw, size, type, op, mask) \
int pci_##rw##_cfg_##size(struct pci_controller *hose, \
pci_dev_t dev, int offset, type val) \
{ \
u32 addr = 0; \
u16 cfg_type = 0; \
addr = ((offset & 0xfc) | cfg_type | (dev) | 0x80000000); \
out_be32(hose->cfg_addr, addr); \
__asm__ __volatile__("nop"); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
out_be32(hose->cfg_addr, addr & 0x7fffffff); \
__asm__ __volatile__("nop"); \
return 0; \
}
PCI_OP(read, byte, u8 *, in_8, 3)
PCI_OP(read, word, u16 *, in_le16, 2)
PCI_OP(write, byte, u8, out_8, 3)
PCI_OP(write, word, u16, out_le16, 2)
PCI_OP(write, dword, u32, out_le32, 0)
int pci_read_cfg_dword(struct pci_controller *hose, pci_dev_t dev,
int offset, u32 * val)
{
u32 addr;
u32 tmpv;
u32 mask = 2; /* word access */
/* Read lower 16 bits */
addr = ((offset & 0xfc) | (dev) | 0x80000000);
out_be32(hose->cfg_addr, addr);
__asm__ __volatile__("nop");
*val = (u32) in_le16((u16 *) (hose->cfg_data + (offset & mask)));
out_be32(hose->cfg_addr, addr & 0x7fffffff);
__asm__ __volatile__("nop");
/* Read upper 16 bits */
offset += 2;
addr = ((offset & 0xfc) | 1 | (dev) | 0x80000000);
out_be32(hose->cfg_addr, addr);
__asm__ __volatile__("nop");
tmpv = (u32) in_le16((u16 *) (hose->cfg_data + (offset & mask)));
out_be32(hose->cfg_addr, addr & 0x7fffffff);
__asm__ __volatile__("nop");
/* combine results into dword value */
*val = (tmpv << 16) | *val;
return 0;
}
void pci_mcf5445x_init(struct pci_controller *hose)
{
volatile pci_t *pci = (volatile pci_t *)MMAP_PCI;
volatile pciarb_t *pciarb = (volatile pciarb_t *)MMAP_PCIARB;
volatile gpio_t *gpio = (gpio_t *) MMAP_GPIO;
u32 barEn = 0;
pciarb->acr = 0x001f001f;
/* Set PCIGNT1, PCIREQ1, PCIREQ0/PCIGNTIN, PCIGNT0/PCIREQOUT,
PCIREQ2, PCIGNT2 */
gpio->par_pci =
GPIO_PAR_PCI_GNT3_GNT3 | GPIO_PAR_PCI_GNT2 | GPIO_PAR_PCI_GNT1 |
GPIO_PAR_PCI_GNT0 | GPIO_PAR_PCI_REQ3_REQ3 | GPIO_PAR_PCI_REQ2 |
GPIO_PAR_PCI_REQ1 | GPIO_PAR_PCI_REQ0;
pci->tcr1 |= PCI_TCR1_P;
/* Initiator windows */
pci->iw0btar = CFG_PCI_MEM_PHYS;
pci->iw1btar = CFG_PCI_IO_PHYS;
pci->iw2btar = CFG_PCI_CFG_PHYS;
pci->iwcr =
PCI_IWCR_W0C_EN | PCI_IWCR_W1C_EN | PCI_IWCR_W1C_IO |
PCI_IWCR_W2C_EN | PCI_IWCR_W2C_IO;
/* Enable bus master and mem access */
pci->scr = PCI_SCR_MW | PCI_SCR_B | PCI_SCR_M;
/* Cache line size and master latency */
pci->cr1 = PCI_CR1_CLS(8) | PCI_CR1_LTMR(0xFF);
pci->cr2 = 0;
#ifdef CFG_PCI_BAR0
pci->bar0 = PCI_BAR_BAR0(CFG_PCI_BAR0);
pci->tbatr0 = CFG_PCI_TBATR0 | PCI_TBATR_EN;
barEn |= PCI_TCR1_B0E;
#endif
#ifdef CFG_PCI_BAR1
pci->bar1 = PCI_BAR_BAR1(CFG_PCI_BAR1);
pci->tbatr1 = CFG_PCI_TBATR1 | PCI_TBATR_EN;
barEn |= PCI_TCR1_B1E;
#endif
#ifdef CFG_PCI_BAR2
pci->bar2 = PCI_BAR_BAR2(CFG_PCI_BAR2);
pci->tbatr2 = CFG_PCI_TBATR2 | PCI_TBATR_EN;
barEn |= PCI_TCR1_B2E;
#endif
#ifdef CFG_PCI_BAR3
pci->bar3 = PCI_BAR_BAR3(CFG_PCI_BAR3);
pci->tbatr3 = CFG_PCI_TBATR3 | PCI_TBATR_EN;
barEn |= PCI_TCR1_B3E;
#endif
#ifdef CFG_PCI_BAR4
pci->bar4 = PCI_BAR_BAR4(CFG_PCI_BAR4);
pci->tbatr4 = CFG_PCI_TBATR4 | PCI_TBATR_EN;
barEn |= PCI_TCR1_B4E;
#endif
#ifdef CFG_PCI_BAR5
pci->bar5 = PCI_BAR_BAR5(CFG_PCI_BAR5);
pci->tbatr5 = CFG_PCI_TBATR5 | PCI_TBATR_EN;
barEn |= PCI_TCR1_B5E;
#endif
pci->tcr2 = barEn;
/* Deassert reset bit */
pci->gscr &= ~PCI_GSCR_PR;
udelay(1000);
/* Enable PCI bus master support */
hose->first_busno = 0;
hose->last_busno = 0xff;
pci_set_region(hose->regions + 0, CFG_PCI_MEM_BUS, CFG_PCI_MEM_PHYS,
CFG_PCI_MEM_SIZE, PCI_REGION_MEM);
pci_set_region(hose->regions + 1, CFG_PCI_IO_BUS, CFG_PCI_IO_PHYS,
CFG_PCI_IO_SIZE, PCI_REGION_IO);
pci_set_region(hose->regions + 2, CFG_PCI_SYS_MEM_BUS,
CFG_PCI_SYS_MEM_PHYS, CFG_PCI_SYS_MEM_SIZE,
PCI_REGION_MEM | PCI_REGION_MEMORY);
hose->region_count = 3;
hose->cfg_addr = &(pci->car);
hose->cfg_data = (volatile unsigned char *)CFG_PCI_CFG_BUS;
pci_set_ops(hose, pci_read_cfg_byte, pci_read_cfg_word,
pci_read_cfg_dword, pci_write_cfg_byte, pci_write_cfg_word,
pci_write_cfg_dword);
/* Hose scan */
pci_register_hose(hose);
hose->last_busno = pci_hose_scan(hose);
}
#endif /* CONFIG_PCI */

186
cpu/mcf5445x/speed.c Normal file
View File

@@ -0,0 +1,186 @@
/*
*
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.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 <asm/processor.h>
#include <asm/immap.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* Low Power Divider specifications
*/
#define CLOCK_LPD_MIN (1 << 0) /* Divider (decoded) */
#define CLOCK_LPD_MAX (1 << 15) /* Divider (decoded) */
#define CLOCK_PLL_FVCO_MAX 540000000
#define CLOCK_PLL_FVCO_MIN 300000000
#define CLOCK_PLL_FSYS_MAX 266666666
#define CLOCK_PLL_FSYS_MIN 100000000
#define MHZ 1000000
void clock_enter_limp(int lpdiv)
{
volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
int i, j;
/* Check bounds of divider */
if (lpdiv < CLOCK_LPD_MIN)
lpdiv = CLOCK_LPD_MIN;
if (lpdiv > CLOCK_LPD_MAX)
lpdiv = CLOCK_LPD_MAX;
/* Round divider down to nearest power of two */
for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;
/* Apply the divider to the system clock */
ccm->cdr = (ccm->cdr & 0xF0FF) | CCM_CDR_LPDIV(i);
/* Enable Limp Mode */
ccm->misccr |= CCM_MISCCR_LIMP;
}
/*
* brief Exit Limp mode
* warning The PLL should be set and locked prior to exiting Limp mode
*/
void clock_exit_limp(void)
{
volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;
/* Exit Limp mode */
ccm->misccr &= ~CCM_MISCCR_LIMP;
/* Wait for the PLL to lock */
while (!(pll->psr & PLL_PSR_LOCK)) ;
}
/*
* get_clocks() fills in gd->cpu_clock and gd->bus_clk
*/
int get_clocks(void)
{
volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;
volatile u8 *cpld = (volatile u8 *)(CFG_CS2_BASE + 3);
volatile u8 *fpga = (volatile u8 *)(CFG_CS3_BASE + 14);
int pllmult_nopci[] = { 20, 10, 24, 18, 12, 6, 16, 8 };
int pllmult_pci[] = { 12, 6, 16, 8 };
int vco, bPci, temp, fbtemp, pcrvalue;
int *pPllmult = NULL;
u16 fbpll_mask;
u8 cpldmode;
/* To determine PCI is present or not */
if (((ccm->ccr & CCM_CCR_360_FBCONFIG_MASK) == 0x00e0) ||
((ccm->ccr & CCM_CCR_360_FBCONFIG_MASK) == 0x0060)) {
pPllmult = &pllmult_pci[0];
fbpll_mask = 3;
bPci = 1;
} else {
pPllmult = &pllmult_nopci[0];
fbpll_mask = 7;
#ifdef CONFIG_PCI
gd->pci_clk = 0;
#endif
bPci = 0;
}
#ifdef CONFIG_M54455EVB
/* Temporary place here, belongs in board/freescale/... */
/* Temporary read from CCR- fixed fb issue, must be the same clock
as pci or input clock, causing cpld/fpga read inconsistancy */
fbtemp = pPllmult[ccm->ccr & fbpll_mask];
/* Break down into small pieces, code still in flex bus */
pcrvalue = pll->pcr & 0xFFFFF0FF;
temp = fbtemp - 1;
pcrvalue |= PLL_PCR_OUTDIV3(temp);
pll->pcr = pcrvalue;
cpldmode = *cpld & 0x03;
if (cpldmode == 0) {
/* RCON mode */
vco = pPllmult[ccm->rcon & fbpll_mask] * CFG_INPUT_CLKSRC;
if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {
/* invaild range, re-set in PCR */
int temp = ((pll->pcr & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;
int i, j, bus;
j = (pll->pcr & 0xFF000000) >> 24;
for (i = j; i < 0xFF; i++) {
vco = i * CFG_INPUT_CLKSRC;
if (vco >= CLOCK_PLL_FVCO_MIN) {
bus = vco / temp;
if (bus <= CLOCK_PLL_FSYS_MIN - MHZ)
continue;
else
break;
}
}
pcrvalue = pll->pcr & 0x00FF00FF;
fbtemp = ((i - 1) << 8) | ((i - 1) << 12);
pcrvalue |= ((i << 24) | fbtemp);
pll->pcr = pcrvalue;
}
gd->vco_clk = vco; /* Vco clock */
} else if (cpldmode == 2) {
/* Normal mode */
vco = pPllmult[ccm->ccr & fbpll_mask] * CFG_INPUT_CLKSRC;
gd->vco_clk = vco; /* Vco clock */
} else if (cpldmode == 3) {
/* serial mode */
}
#endif /* CONFIG_M54455EVB */
if ((ccm->ccr & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) {
/* Limp mode */
} else {
gd->inp_clk = CFG_INPUT_CLKSRC; /* Input clock */
temp = (pll->pcr & PLL_PCR_OUTDIV1_MASK) + 1;
gd->cpu_clk = vco / temp; /* cpu clock */
temp = ((pll->pcr & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;
gd->bus_clk = vco / temp; /* bus clock */
temp = ((pll->pcr & PLL_PCR_OUTDIV3_MASK) >> 8) + 1;
gd->flb_clk = vco / temp; /* FlexBus clock */
#ifdef CONFIG_PCI
if (bPci) {
temp = ((pll->pcr & PLL_PCR_OUTDIV4_MASK) >> 12) + 1;
gd->pci_clk = vco / temp; /* PCI clock */
}
#endif
}
return (0);
}

388
cpu/mcf5445x/start.S Normal file
View File

@@ -0,0 +1,388 @@
/*
* Copyright (C) 2003 Josef Baumgartner <josef.baumgartner@telex.de>
* Based on code from Bernhard Kuhn <bkuhn@metrowerks.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 <config.h>
#include "version.h"
#ifndef CONFIG_IDENT_STRING
#define CONFIG_IDENT_STRING ""
#endif
/* last three long word reserved for cache status */
#define CACR_STATUS (CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END-12)
#define ICACHE_STATUS (CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END- 8)
#define DCACHE_STATUS (CFG_INIT_RAM_ADDR+CFG_INIT_RAM_END- 4)
#define _START _start
#define _FAULT _fault
#define SAVE_ALL \
move.w #0x2700,%sr; /* disable intrs */ \
subl #60,%sp; /* space for 15 regs */ \
moveml %d0-%d7/%a0-%a6,%sp@;
#define RESTORE_ALL \
moveml %sp@,%d0-%d7/%a0-%a6; \
addl #60,%sp; /* space for 15 regs */ \
rte;
.text
/*
* Vector table. This is used for initial platform startup.
* These vectors are to catch any un-intended traps.
*/
_vectors:
INITSP: .long 0x00000000 /* Initial SP */
INITPC: .long _START /* Initial PC */
vector02: .long _FAULT /* Access Error */
vector03: .long _FAULT /* Address Error */
vector04: .long _FAULT /* Illegal Instruction */
vector05: .long _FAULT /* Reserved */
vector06: .long _FAULT /* Reserved */
vector07: .long _FAULT /* Reserved */
vector08: .long _FAULT /* Privilege Violation */
vector09: .long _FAULT /* Trace */
vector0A: .long _FAULT /* Unimplemented A-Line */
vector0B: .long _FAULT /* Unimplemented F-Line */
vector0C: .long _FAULT /* Debug Interrupt */
vector0D: .long _FAULT /* Reserved */
vector0E: .long _FAULT /* Format Error */
vector0F: .long _FAULT /* Unitialized Int. */
/* Reserved */
vector10_17:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector18: .long _FAULT /* Spurious Interrupt */
vector19: .long _FAULT /* Autovector Level 1 */
vector1A: .long _FAULT /* Autovector Level 2 */
vector1B: .long _FAULT /* Autovector Level 3 */
vector1C: .long _FAULT /* Autovector Level 4 */
vector1D: .long _FAULT /* Autovector Level 5 */
vector1E: .long _FAULT /* Autovector Level 6 */
vector1F: .long _FAULT /* Autovector Level 7 */
/* TRAP #0 - #15 */
vector20_2F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
/* Reserved */
vector30_3F:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector64_127:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector128_191:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
vector192_255:
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.long _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT, _FAULT
.text
.globl _start
_start:
nop
nop
move.w #0x2700,%sr /* Mask off Interrupt */
/* Set vector base register at the beginning of the Flash */
move.l #CFG_FLASH_BASE, %d0
movec %d0, %VBR
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_RAM_CTRL), %d0
movec %d0, %RAMBAR0
/* initialize general use internal ram */
move.l #0, %d0
move.l #(CACR_STATUS), %a1 /* CACR */
move.l #(ICACHE_STATUS), %a2 /* icache */
move.l #(DCACHE_STATUS), %a3 /* dcache */
move.l %d0, (%a1)
move.l %d0, (%a2)
move.l %d0, (%a3)
/* invalidate and disable cache */
move.l #0x01004100, %d0 /* Invalidate cache cmd */
movec %d0, %CACR /* Invalidate cache */
move.l #0, %d0
movec %d0, %ACR0
movec %d0, %ACR1
movec %d0, %ACR2
movec %d0, %ACR3
/* set stackpointer to end of internal ram to get some stackspace for
the first c-code */
move.l #(CFG_INIT_RAM_ADDR + CFG_INIT_SP_OFFSET), %sp
clr.l %sp@-
move.l #__got_start, %a5 /* put relocation table address to a5 */
bsr cpu_init_f /* run low-level CPU init code (from flash) */
bsr board_init_f /* run low-level board init code (from flash) */
/* board_init_f() does not return */
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* r3 = dest
* r4 = src
* r5 = length in bytes
* r6 = cachelinesize
*/
.globl relocate_code
relocate_code:
link.w %a6,#0
move.l 8(%a6), %sp /* set new stack pointer */
move.l 12(%a6), %d0 /* Save copy of Global Data pointer */
move.l 16(%a6), %a0 /* Save copy of Destination Address */
move.l #CFG_MONITOR_BASE, %a1
move.l #__init_end, %a2
move.l %a0, %a3
/* copy the code to RAM */
1:
move.l (%a1)+, (%a3)+
cmp.l %a1,%a2
bgt.s 1b
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
move.l %a0, %a1
add.l #(in_ram - CFG_MONITOR_BASE), %a1
jmp (%a1)
in_ram:
clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CFG_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CFG_MONITOR_BASE),%d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
bgt.s 6b
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CFG_MONITOR_BASE),%a1
move.l %a1,%a5 /* * fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CFG_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CFG_MONITOR_BASE), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */
move.l %d0,-(%sp) /* gd */
jsr (%a1)
/*------------------------------------------------------------------------------*/
/* exception code */
.globl _fault
_fault:
jmp _fault
.globl _exc_handler
_exc_handler:
SAVE_ALL
movel %sp,%sp@-
bsr exc_handler
addql #4,%sp
RESTORE_ALL
.globl _int_handler
_int_handler:
SAVE_ALL
movel %sp,%sp@-
bsr int_handler
addql #4,%sp
RESTORE_ALL
/*------------------------------------------------------------------------------*/
/* cache functions */
.globl icache_enable
icache_enable:
move.l #(CACR_STATUS), %a1 /* read CACR Status */
move.l (%a1), %d1
move.l #0x00040100, %d0 /* Invalidate icache */
or.l %d1, %d0
movec %d0, %CACR
move.l #(CFG_SDRAM_BASE + 0xc000), %d0 /* Setup icache */
movec %d0, %ACR2
or.l #0x00088400, %d1 /* Enable bcache and icache */
movec %d1, %CACR
move.l #(ICACHE_STATUS), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
.globl icache_disable
icache_disable:
move.l #(CACR_STATUS), %a1 /* read CACR Status */
move.l (%a1), %d0
and.l #0xFFF77BFF, %d0
or.l #0x00040100, %d0 /* Setup cache mask */
movec %d0, %CACR /* Invalidate icache */
clr.l %d0
movec %d0, %ACR2
movec %d0, %ACR3
move.l #(ICACHE_STATUS), %a1
moveq #0, %d0
move.l %d0, (%a1)
rts
.globl icache_status
icache_status:
move.l #(ICACHE_STATUS), %a1
move.l (%a1), %d0
rts
.globl icache_invalid
icache_invalid:
move.l #(CACR_STATUS), %a1 /* read CACR Status */
move.l (%a1), %d0
or.l #0x00040100, %d0 /* Invalidate icache */
movec %d0, %CACR /* Enable and invalidate cache */
rts
.globl dcache_enable
dcache_enable:
move.l #(CACR_STATUS), %a1 /* read CACR Status */
move.l (%a1), %d1
move.l #0x01000000, %d0
or.l %d1, %d0
movec %d0, %CACR /* Invalidate dcache */
move.l #(CFG_SDRAM_BASE + 0xc000), %d0
movec %d0, %ACR0
move.l #0, %d0
movec %d0, %ACR1
or.l #0x80000000, %d1 /* Enable bcache and icache */
movec %d1, %CACR
move.l #(DCACHE_STATUS), %a1
moveq #1, %d0
move.l %d0, (%a1)
rts
.globl dcache_disable
dcache_disable:
move.l #(CACR_STATUS), %a1 /* read CACR Status */
move.l (%a1), %d0
and.l #0x7FFFFFFF, %d0
or.l #0x01000000, %d0 /* Setup cache mask */
movec %d0, %CACR /* Disable dcache */
clr.l %d0
movec %d0, %ACR0
movec %d0, %ACR1
move.l #(DCACHE_STATUS), %a1
moveq #0, %d0
move.l %d0, (%a1)
rts
.globl dcache_invalid
dcache_invalid:
move.l #(CACR_STATUS), %a1 /* read CACR Status */
move.l (%a1), %d0
or.l #0x01000000, %d0 /* Setup cache mask */
movec %d0, %CACR /* Enable and invalidate cache */
rts
.globl dcache_status
dcache_status:
move.l #(DCACHE_STATUS), %a1
move.l (%a1), %d0
rts
/*------------------------------------------------------------------------------*/
.globl version_string
version_string:
.ascii U_BOOT_VERSION
.ascii " (", __DATE__, " - ", __TIME__, ")"
.ascii CONFIG_IDENT_STRING, "\0"

View File

@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).a
START = start.o
SOBJS = dcache.o icache.o irq.o disable_int.o enable_int.o
SOBJS = irq.o
COBJS = cpu.o interrupts.o cache.o exception.o timer.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)

View File

@@ -23,8 +23,9 @@
*/
#include <common.h>
#include <asm/asm.h>
#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
#if defined(CONFIG_CMD_CACHE)
int dcache_status (void)
{
@@ -45,4 +46,20 @@ int icache_status (void)
__asm__ __volatile__ ("and %0,%0,%1"::"r" (i), "r" (mask):"memory");
return i;
}
void icache_enable (void) {
MSRSET(0x20);
}
void icache_disable(void) {
MSRCLR(0x20);
}
void dcache_enable (void) {
MSRSET(0x80);
}
void dcache_disable(void) {
MSRCLR(0x80);
}
#endif

View File

@@ -1,68 +0,0 @@
/*
* (C) Copyright 2007 Michal Simek
*
* Michal SIMEK <monstr@monstr.eu>
*
* 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
*/
.text
.globl dcache_enable
.ent dcache_enable
.align 2
dcache_enable:
/* Make space on stack for a temporary */
addi r1, r1, -4
/* Save register r12 */
swi r12, r1, 0
/* Read the MSR register */
mfs r12, rmsr
/* Set the instruction enable bit */
ori r12, r12, 0x80
/* Save the MSR register */
mts rmsr, r12
/* Load register r12 */
lwi r12, r1, 0
/* Return */
rtsd r15, 8
/* Update stack in the delay slot */
addi r1, r1, 4
.end dcache_enable
.text
.globl dcache_disable
.ent dcache_disable
.align 2
dcache_disable:
/* Make space on stack for a temporary */
addi r1, r1, -4
/* Save register r12 */
swi r12, r1, 0
/* Read the MSR register */
mfs r12, rmsr
/* Clear the data cache enable bit */
andi r12, r12, ~0x80
/* Save the MSR register */
mts rmsr, r12
/* Load register r12 */
lwi r12, r1, 0
/* Return */
rtsd r15, 8
/* Update stack in the delay slot */
addi r1, r1, 4
.end dcache_disable

View File

@@ -23,15 +23,16 @@
*/
#include <common.h>
#include <asm/asm.h>
void _hw_exception_handler (void)
{
int address = 0;
int state = 0;
/* loading address of exception EAR */
__asm__ __volatile ("mfs %0,rear"::"r" (address):"memory");
MFS (address, rear);
/* loading excetpion state register ESR */
__asm__ __volatile ("mfs %0,resr"::"r" (state):"memory");
MFS (state, resr);
printf ("Hardware exception at 0x%x address\n", address);
switch (state & 0x1f) { /* mask on exception cause */
case 0x1:
@@ -49,6 +50,11 @@ void _hw_exception_handler (void)
case 0x5:
puts ("Divide by zero exception\n");
break;
#ifdef MICROBLAZE_V5
case 0x1000:
puts ("Exception in delay slot\n");
break;
#endif
default:
puts ("Undefined cause\n");
break;

View File

@@ -1,69 +0,0 @@
/*
* (C) Copyright 2007 Michal Simek
*
* Michal SIMEK <monstr@monstr.eu>
*
* 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
*/
.text
.globl icache_enable
.ent icache_enable
.align 2
icache_enable:
/* Make space on stack for a temporary */
addi r1, r1, -4
/* Save register r12 */
swi r12, r1, 0
/* Read the MSR register */
mfs r12, rmsr
/* Set the instruction enable bit */
ori r12, r12, 0x20
/* Save the MSR register */
mts rmsr, r12
/* Load register r12 */
lwi r12, r1, 0
/* Return */
rtsd r15, 8
/* Update stack in the delay slot */
addi r1, r1, 4
.end icache_enable
.text
.globl icache_disable
.ent icache_disable
.align 2
icache_disable:
/* Make space on stack for a temporary */
addi r1, r1, -4
/* Save register r12 */
swi r12, r1, 0
/* Read the MSR register */
mfs r12, rmsr
/* Clear the instruction enable bit */
andi r12, r12, ~0x20
/* Save the MSR register */
mts rmsr, r12
/* Load register r12 */
lwi r12, r1, 0
/* Return */
rtsd r15, 8
/* Update stack in the delay slot */
addi r1, r1, 4
.end icache_disable

View File

@@ -27,6 +27,7 @@
#include <common.h>
#include <command.h>
#include <asm/microblaze_intc.h>
#include <asm/asm.h>
#undef DEBUG_INT
@@ -35,12 +36,12 @@ extern void microblaze_enable_interrupts (void);
void enable_interrupts (void)
{
microblaze_enable_interrupts ();
MSRSET(0x2);
}
int disable_interrupts (void)
{
microblaze_disable_interrupts ();
MSRCLR(0x2);
return 0;
}
@@ -48,6 +49,10 @@ int disable_interrupts (void)
#ifdef CFG_TIMER_0
extern void timer_init (void);
#endif
#ifdef CFG_FSL_2
extern void fsl_init2 (void);
#endif
static struct irq_action vecs[CFG_INTC_0_NUM];
@@ -106,7 +111,6 @@ void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
act->count = 0;
enable_one_interrupt (irq);
} else { /* disable */
act->handler = (interrupt_handler_t *) def_hdlr;
act->arg = (void *)irq;
disable_one_interrupt (irq);
@@ -140,6 +144,9 @@ int interrupts_init (void)
intc_init ();
#ifdef CFG_TIMER_0
timer_init ();
#endif
#ifdef CFG_FSL_2
fsl_init2 ();
#endif
enable_interrupts ();
return 0;
@@ -147,12 +154,13 @@ int interrupts_init (void)
void interrupt_handler (void)
{
int irqs;
irqs = (intc->isr & intc->ier); /* find active interrupt */
int irqs = (intc->isr & intc->ier); /* find active interrupt */
int i = 1;
#ifdef DEBUG_INT
int value;
printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
intc->iar, intc->mer);
R14(value);
printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
#endif
struct irq_action *act = vecs;
@@ -165,20 +173,24 @@ void interrupt_handler (void)
#endif
act->handler (act->arg);
act->count++;
intc->iar = i;
return;
}
irqs >>= 1;
act++;
i <<= 1;
}
intc->iar = 0xFFFFFFFF; /* erase all events */
#ifdef DEBUG
#ifdef DEBUG_INT
printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
intc->ier, intc->iar, intc->mer);
printf ("Interrupt handler on %x line, r14\n", irqs);
R14(value);
printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
#endif
}
#endif
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
#if defined(CONFIG_CMD_IRQ)
#ifdef CFG_INTC_0
int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
@@ -205,4 +217,4 @@ int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
puts ("Undefined interrupt controller\n");
}
#endif
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
#endif

View File

@@ -23,6 +23,7 @@
*/
#include <config.h>
#include <asm/asm.h>
.text
.global _interrupt_handler
_interrupt_handler:
@@ -151,6 +152,11 @@ _interrupt_handler:
addi r1, r1, 4
/* enable_interrupt */
#ifdef XILINX_USE_MSR_INSTR
msrset r0, 2
#else
/* FIXME unstable in stressed mode - two irqs */
nop
addi r1, r1, -4
swi r12, r1, 0
mfs r12, rmsr
@@ -159,6 +165,7 @@ _interrupt_handler:
lwi r12, r1, 0
addi r1, r1, 4
nop
#endif
bra r14
nop
nop

View File

@@ -117,3 +117,36 @@ clear_bss:
3: /* jumping to board_init */
brai board_init
1: bri 1b
/*
* Read 16bit little endian
*/
.text
.global in16
.ent in16
.align 2
in16: lhu r3, r0, r5
bslli r4, r3, 8
bsrli r3, r3, 8
andi r4, r4, 0xffff
or r3, r3, r4
rtsd r15, 8
sext16 r3, r3
.end in16
/*
* Write 16bit little endian
* first parameter(r5) - address, second(r6) - short value
*/
.text
.global out16
.ent out16
.align 2
out16: bslli r3, r6, 8
bsrli r6, r6, 8
andi r3, r3, 0xffff
or r3, r3, r6
sh r3, r0, r5
rtsd r15, 8
or r0, r0, r0
.end out16

View File

@@ -24,6 +24,7 @@
#include <common.h>
#include <asm/microblaze_timer.h>
#include <asm/microblaze_intc.h>
volatile int timestamp = 0;
@@ -44,9 +45,6 @@ void set_timer (ulong t)
#ifdef CFG_INTC_0
#ifdef CFG_TIMER_0
extern void install_interrupt_handler (int irq, interrupt_handler_t * hdlr,
void *arg);
microblaze_timer_t *tmr = (microblaze_timer_t *) (CFG_TIMER_0_ADDR);
void timer_isr (void *arg)

View File

@@ -63,7 +63,7 @@
#include <asm/io.h>
#include <asm/au1x00.h>
#if (CONFIG_COMMANDS & CFG_CMD_MII)
#if defined(CONFIG_CMD_MII)
#include <miiphy.h>
#endif
@@ -241,7 +241,7 @@ int au1x00_enet_initialize(bd_t *bis){
eth_register(dev);
#if (CONFIG_COMMANDS & CFG_CMD_MII)
#if defined(CONFIG_CMD_MII)
miiphy_register(dev->name,
au1x00_miiphy_read, au1x00_miiphy_write);
#endif
@@ -249,7 +249,7 @@ int au1x00_enet_initialize(bd_t *bis){
return 1;
}
#if (CONFIG_COMMANDS & CFG_CMD_MII)
#if defined(CONFIG_CMD_MII)
int au1x00_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short * value)
{
@@ -306,6 +306,6 @@ int au1x00_miiphy_write(char *devname, unsigned char addr,
*mii_control_reg = mii_control;
return 0;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_MII */
#endif
#endif /* CONFIG_AU1X00 */

46
cpu/mpc512x/Makefile Normal file
View File

@@ -0,0 +1,46 @@
#
# (C) Copyright 2007 DENX Software Engineering
#
# 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$(CPU).a
START = start.o
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o fec.o i2c.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
START := $(addprefix $(obj),$(START))
all: $(obj).depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

25
cpu/mpc512x/config.mk Normal file
View File

@@ -0,0 +1,25 @@
#
# (C) Copyright 2007 DENX Software Engineering
#
# 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
#
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_MPC512X -DCONFIG_E300 \
-ffixed-r2 -ffixed-r29 -msoft-float -mcpu=603e

127
cpu/mpc512x/cpu.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
* (C) Copyright 2007 DENX Software Engineering
*
* 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
*/
/*
* CPU specific code for the MPC512x family.
*
* Derived from the MPC83xx code.
*/
#include <common.h>
#include <command.h>
#include <mpc512x.h>
#include <asm/processor.h>
DECLARE_GLOBAL_DATA_PTR;
int checkcpu (void)
{
volatile immap_t *immr = (immap_t *) CFG_IMMR;
ulong clock = gd->cpu_clk;
u32 pvr = get_pvr ();
u32 spridr = immr->sysconf.spridr;
char buf[32];
puts ("CPU: ");
switch (spridr & 0xffff0000) {
case SPR_5121E:
puts ("MPC5121e ");
break;
default:
printf ("Unknown part ID %08x ", spridr & 0xffff0000);
}
printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr));
switch (pvr & 0xffff0000) {
case PVR_E300C4:
puts ("e300c4 ");
break;
default:
puts ("unknown ");
}
printf ("at %s MHz, CSB at %3d MHz\n", strmhz(buf, clock),
gd->csb_clk / 1000000);
return 0;
}
int
do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
ulong msr;
volatile immap_t *immap = (immap_t *) CFG_IMMR;
/* Interrupts and MMU off */
__asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
msr &= ~( MSR_EE | MSR_IR | MSR_DR);
__asm__ __volatile__ ("mtmsr %0"::"r" (msr));
/*
* Enable Reset Control Reg - "RSTE" is the magic word that let us go
*/
immap->reset.rpr = 0x52535445;
/* Verify Reset Control Reg is enabled */
while (!((immap->reset.rcer) & RCER_CRE))
;
printf ("Resetting the board.\n");
udelay(200);
/* Perform reset */
immap->reset.rcr = RCR_SWHR;
/* Unreached... */
return 1;
}
/*
* Get timebase clock frequency (like cpu_clk in Hz)
*/
unsigned long get_tbclk (void)
{
ulong tbclk;
tbclk = (gd->bus_clk + 3L) / 4L;
return tbclk;
}
#if defined(CONFIG_WATCHDOG)
void watchdog_reset (void)
{
int re_enable = disable_interrupts ();
/* Reset watchdog */
volatile immap_t *immr = (immap_t *) CFG_IMMR;
immr->wdt.swsrr = 0x556c;
immr->wdt.swsrr = 0xaa39;
if (re_enable)
enable_interrupts ();
}
#endif

87
cpu/mpc512x/cpu_init.c Normal file
View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
* (C) Copyright 2007 DENX Software Engineering
*
* 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
*
* Derived from the MPC83xx code.
*
*/
#include <common.h>
#include <mpc512x.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* Set up the memory map, initialize registers,
*/
void cpu_init_f (volatile immap_t * im)
{
u32 ips_div;
/* Pointer is writable since we allocated a register for it */
gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
/* Clear initial global data */
memset ((void *) gd, 0, sizeof (gd_t));
/* system performance tweaking */
#ifdef CFG_ACR_PIPE_DEP
/* Arbiter pipeline depth */
im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
(CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
#endif
#ifdef CFG_ACR_RPTCNT
/* Arbiter repeat count */
im->arbiter.acr = ((im->arbiter.acr & ~(ACR_RPTCNT)) |
(CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT));
#endif
/* RSR - Reset Status Register - clear all status */
gd->reset_status = im->reset.rsr;
im->reset.rsr = ~(RSR_RES);
/*
* RMR - Reset Mode Register - enable checkstop reset
*/
im->reset.rmr = (RMR_CSRE & (1 << RMR_CSRE_SHIFT));
/* Set IPS-CSB divider: IPS = 1/2 CSB */
ips_div = im->clk.scfr[0];
ips_div &= ~(SCFR1_IPS_DIV_MASK);
ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT;
im->clk.scfr[0] = ips_div;
/*
* Enable Time Base/Decrementer
*
* NOTICE: TB needs to be enabled as early as possible in order to
* have udelay() working; if not enabled, usually leads to a hang, like
* during FLASH chip identification etc.
*/
im->sysconf.spcr |= SPCR_TBEN;
}
int cpu_init_r (void)
{
return 0;
}

809
cpu/mpc512x/fec.c Normal file
View File

@@ -0,0 +1,809 @@
/*
* (C) Copyright 2003-2007
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Derived from the MPC8xx FEC driver.
* Adapted for MPC512x by Grzegorz Bernacki <gjb@semihalf.com>
*/
#include <common.h>
#include <mpc512x.h>
#include <malloc.h>
#include <net.h>
#include <miiphy.h>
#include "fec.h"
DECLARE_GLOBAL_DATA_PTR;
#define DEBUG 0
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_MPC512x_FEC)
#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif
#if (DEBUG & 0x40)
static uint32 local_crc32(char *string, unsigned int crc_value, int len);
#endif
int fec512x_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
int fec512x_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
static uchar rx_buff[FEC_BUFFER_SIZE];
static int rx_buff_idx = 0;
/********************************************************************/
#if (DEBUG & 0x2)
static void mpc512x_fec_phydump (char *devname)
{
uint16 phyStatus, i;
uint8 phyAddr = CONFIG_PHY_ADDR;
uint8 reg_mask[] = {
/* regs to print: 0...8, 21,27,31 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
};
for (i = 0; i < 32; i++) {
if (reg_mask[i]) {
miiphy_read (devname, phyAddr, i, &phyStatus);
printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
}
}
}
#endif
/********************************************************************/
static int mpc512x_fec_bd_init (mpc512x_fec_priv *fec)
{
int ix;
/*
* Receive BDs init
*/
for (ix = 0; ix < FEC_RBD_NUM; ix++) {
fec->bdBase->rbd[ix].dataPointer = (uint32)&fec->bdBase->recv_frames[ix];
fec->bdBase->rbd[ix].status = FEC_RBD_EMPTY;
fec->bdBase->rbd[ix].dataLength = 0;
}
/*
* have the last RBD to close the ring
*/
fec->bdBase->rbd[ix - 1].status |= FEC_RBD_WRAP;
fec->rbdIndex = 0;
/*
* Trasmit BDs init
*/
for (ix = 0; ix < FEC_TBD_NUM; ix++) {
fec->bdBase->tbd[ix].status = 0;
}
/*
* Have the last TBD to close the ring
*/
fec->bdBase->tbd[ix - 1].status |= FEC_TBD_WRAP;
/*
* Initialize some indices
*/
fec->tbdIndex = 0;
fec->usedTbdIndex = 0;
fec->cleanTbdNum = FEC_TBD_NUM;
return 0;
}
/********************************************************************/
static void mpc512x_fec_rbd_clean (mpc512x_fec_priv *fec, volatile FEC_RBD * pRbd)
{
/*
* Reset buffer descriptor as empty
*/
if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
else
pRbd->status = FEC_RBD_EMPTY;
pRbd->dataLength = 0;
/*
* Increment BD count
*/
fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
/*
* Now, we have an empty RxBD, notify FEC
*/
fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
}
/********************************************************************/
static void mpc512x_fec_tbd_scrub (mpc512x_fec_priv *fec)
{
volatile FEC_TBD *pUsedTbd;
#if (DEBUG & 0x1)
printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
fec->cleanTbdNum, fec->usedTbdIndex);
#endif
/*
* process all the consumed TBDs
*/
while (fec->cleanTbdNum < FEC_TBD_NUM) {
pUsedTbd = &fec->bdBase->tbd[fec->usedTbdIndex];
if (pUsedTbd->status & FEC_TBD_READY) {
#if (DEBUG & 0x20)
printf ("Cannot clean TBD %d, in use\n", fec->usedTbdIndex);
#endif
return;
}
/*
* clean this buffer descriptor
*/
if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
pUsedTbd->status = FEC_TBD_WRAP;
else
pUsedTbd->status = 0;
/*
* update some indeces for a correct handling of the TBD ring
*/
fec->cleanTbdNum++;
fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
}
}
/********************************************************************/
static void mpc512x_fec_set_hwaddr (mpc512x_fec_priv *fec, char *mac)
{
uint8 currByte; /* byte for which to compute the CRC */
int byte; /* loop - counter */
int bit; /* loop - counter */
uint32 crc = 0xffffffff; /* initial value */
/*
* The algorithm used is the following:
* we loop on each of the six bytes of the provided address,
* and we compute the CRC by left-shifting the previous
* value by one position, so that each bit in the current
* byte of the address may contribute the calculation. If
* the latter and the MSB in the CRC are different, then
* the CRC value so computed is also ex-ored with the
* "polynomium generator". The current byte of the address
* is also shifted right by one bit at each iteration.
* This is because the CRC generatore in hardware is implemented
* as a shift-register with as many ex-ores as the radixes
* in the polynomium. This suggests that we represent the
* polynomiumm itself as a 32-bit constant.
*/
for (byte = 0; byte < 6; byte++) {
currByte = mac[byte];
for (bit = 0; bit < 8; bit++) {
if ((currByte & 0x01) ^ (crc & 0x01)) {
crc >>= 1;
crc = crc ^ 0xedb88320;
} else {
crc >>= 1;
}
currByte >>= 1;
}
}
crc = crc >> 26;
/*
* Set individual hash table register
*/
if (crc >= 32) {
fec->eth->iaddr1 = (1 << (crc - 32));
fec->eth->iaddr2 = 0;
} else {
fec->eth->iaddr1 = 0;
fec->eth->iaddr2 = (1 << crc);
}
/*
* Set physical address
*/
fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
}
/********************************************************************/
static int mpc512x_fec_init (struct eth_device *dev, bd_t * bis)
{
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
#if (DEBUG & 0x1)
printf ("mpc512x_fec_init... Begin\n");
#endif
/* Set interrupt mask register */
fec->eth->imask = 0x00000000;
/* Clear FEC-Lite interrupt event register(IEVENT) */
fec->eth->ievent = 0xffffffff;
/* Set transmit fifo watermark register(X_WMRK), default = 64 */
fec->eth->x_wmrk = 0x0;
/* Set Opcode/Pause Duration Register */
fec->eth->op_pause = 0x00010020;
/* Frame length=1522; MII mode */
fec->eth->r_cntrl = (FEC_MAX_FRAME_LEN << 16) | 0x24;
/* Half-duplex, heartbeat disabled */
fec->eth->x_cntrl = 0x00000000;
/* Enable MIB counters */
fec->eth->mib_control = 0x0;
/* Setup recv fifo start and buff size */
fec->eth->r_fstart = 0x500;
fec->eth->r_buff_size = FEC_BUFFER_SIZE;
/* Setup BD base addresses */
fec->eth->r_des_start = (uint32)fec->bdBase->rbd;
fec->eth->x_des_start = (uint32)fec->bdBase->tbd;
/* DMA Control */
fec->eth->dma_control = 0xc0000000;
/* Enable FEC */
fec->eth->ecntrl |= 0x00000006;
/* Initilize addresses and status words of BDs */
mpc512x_fec_bd_init (fec);
/* Descriptor polling active */
fec->eth->r_des_active = 0x01000000;
#if (DEBUG & 0x1)
printf("mpc512x_fec_init... Done \n");
#endif
return 1;
}
/********************************************************************/
int mpc512x_fec_init_phy (struct eth_device *dev, bd_t * bis)
{
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
const uint8 phyAddr = CONFIG_PHY_ADDR; /* Only one PHY */
int timeout = 1;
uint16 phyStatus;
#if (DEBUG & 0x1)
printf ("mpc512x_fec_init_phy... Begin\n");
#endif
/*
* Clear FEC-Lite interrupt event register(IEVENT)
*/
fec->eth->ievent = 0xffffffff;
/*
* Set interrupt mask register
*/
fec->eth->imask = 0x00000000;
if (fec->xcv_type != SEVENWIRE) {
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
fec->eth->mii_speed = (((gd->ipb_clk / 1000000) / 5) + 1) << 1;
/*
* Reset PHY, then delay 300ns
*/
miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
udelay (1000);
if (fec->xcv_type == MII10) {
/*
* Force 10Base-T, FDX operation
*/
#if (DEBUG & 0x2)
printf ("Forcing 10 Mbps ethernet link... ");
#endif
miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
timeout = 20;
do { /* wait for link status to go down */
udelay (10000);
if ((timeout--) == 0) {
#if (DEBUG & 0x2)
printf ("hmmm, should not have waited...");
#endif
break;
}
miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
#if (DEBUG & 0x2)
printf ("=");
#endif
} while ((phyStatus & 0x0004)); /* !link up */
timeout = 1000;
do { /* wait for link status to come back up */
udelay (10000);
if ((timeout--) == 0) {
printf ("failed. Link is down.\n");
break;
}
miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
#if (DEBUG & 0x2)
printf ("+");
#endif
} while (!(phyStatus & 0x0004)); /* !link up */
#if (DEBUG & 0x2)
printf ("done.\n");
#endif
} else { /* MII100 */
/*
* Set the auto-negotiation advertisement register bits
*/
miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
/*
* Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
*/
miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
/*
* Wait for AN completion
*/
timeout = 50000;
do {
udelay (1000);
if ((timeout--) == 0) {
#if (DEBUG & 0x2)
printf ("PHY auto neg 0 failed...\n");
#endif
return -1;
}
if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) != 0) {
#if (DEBUG & 0x2)
printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
#endif
return -1;
}
} while (!(phyStatus & 0x0004));
#if (DEBUG & 0x2)
printf ("PHY auto neg complete! \n");
#endif
}
}
#if (DEBUG & 0x2)
if (fec->xcv_type != SEVENWIRE)
mpc512x_fec_phydump (dev->name);
#endif
#if (DEBUG & 0x1)
printf ("mpc512x_fec_init_phy... Done \n");
#endif
return 1;
}
/********************************************************************/
static void mpc512x_fec_halt (struct eth_device *dev)
{
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
int counter = 0xffff;
#if (DEBUG & 0x2)
if (fec->xcv_type != SEVENWIRE)
mpc512x_fec_phydump (dev->name);
#endif
/*
* mask FEC chip interrupts
*/
fec->eth->imask = 0;
/*
* issue graceful stop command to the FEC transmitter if necessary
*/
fec->eth->x_cntrl |= 0x00000001;
/*
* wait for graceful stop to register
*/
while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
/*
* Disable the Ethernet Controller
*/
fec->eth->ecntrl &= 0xfffffffd;
/*
* Issue a reset command to the FEC chip
*/
fec->eth->ecntrl |= 0x1;
/*
* wait at least 16 clock cycles
*/
udelay (10);
#if (DEBUG & 0x3)
printf ("Ethernet task stopped\n");
#endif
}
/********************************************************************/
static int mpc512x_fec_send (struct eth_device *dev, volatile void *eth_data,
int data_length)
{
/*
* This routine transmits one frame. This routine only accepts
* 6-byte Ethernet addresses.
*/
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
volatile FEC_TBD *pTbd;
#if (DEBUG & 0x20)
printf("tbd status: 0x%04x\n", fec->tbdBase[fec->tbdIndex].status);
#endif
/*
* Clear Tx BD ring at first
*/
mpc512x_fec_tbd_scrub (fec);
/*
* Check for valid length of data.
*/
if ((data_length > 1500) || (data_length <= 0)) {
return -1;
}
/*
* Check the number of vacant TxBDs.
*/
if (fec->cleanTbdNum < 1) {
#if (DEBUG & 0x20)
printf ("No available TxBDs ...\n");
#endif
return -1;
}
/*
* Get the first TxBD to send the mac header
*/
pTbd = &fec->bdBase->tbd[fec->tbdIndex];
pTbd->dataLength = data_length;
pTbd->dataPointer = (uint32)eth_data;
pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
/* Activate transmit Buffer Descriptor polling */
fec->eth->x_des_active = 0x01000000; /* Descriptor polling active */
#if (DEBUG & 0x8)
printf ( "+" );
#endif
fec->cleanTbdNum -= 1;
/*
* wait until frame is sent .
*/
while (pTbd->status & FEC_TBD_READY) {
udelay (10);
#if (DEBUG & 0x8)
printf ("TDB status = %04x\n", pTbd->status);
#endif
}
return 0;
}
/********************************************************************/
static int mpc512x_fec_recv (struct eth_device *dev)
{
/*
* This command pulls one frame from the card
*/
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
volatile FEC_RBD *pRbd = &fec->bdBase->rbd[fec->rbdIndex];
unsigned long ievent;
int frame_length = 0;
#if (DEBUG & 0x1)
printf ("mpc512x_fec_recv %d Start...\n", fec->rbdIndex);
#endif
#if (DEBUG & 0x8)
printf( "-" );
#endif
/*
* Check if any critical events have happened
*/
ievent = fec->eth->ievent;
fec->eth->ievent = ievent;
if (ievent & 0x20060000) {
/* BABT, Rx/Tx FIFO errors */
mpc512x_fec_halt (dev);
mpc512x_fec_init (dev, NULL);
return 0;
}
if (ievent & 0x80000000) {
/* Heartbeat error */
fec->eth->x_cntrl |= 0x00000001;
}
if (ievent & 0x10000000) {
/* Graceful stop complete */
if (fec->eth->x_cntrl & 0x00000001) {
mpc512x_fec_halt (dev);
fec->eth->x_cntrl &= ~0x00000001;
mpc512x_fec_init (dev, NULL);
}
}
if (!(pRbd->status & FEC_RBD_EMPTY)) {
if (!(pRbd->status & FEC_RBD_ERR) &&
((pRbd->dataLength - 4) > 14)) {
/*
* Get buffer size
*/
if (pRbd->status & FEC_RBD_LAST)
frame_length = pRbd->dataLength - 4;
else
frame_length = pRbd->dataLength;
#if (DEBUG & 0x20)
{
int i;
printf ("recv data length 0x%08x data hdr: ",
pRbd->dataLength);
for (i = 0; i < 14; i++)
printf ("%x ", *((uint8*)pRbd->dataPointer + i));
printf("\n");
}
#endif
/*
* Fill the buffer and pass it to upper layers
*/
memcpy (&rx_buff[rx_buff_idx], (void*)pRbd->dataPointer,
frame_length - rx_buff_idx);
rx_buff_idx = frame_length;
if (pRbd->status & FEC_RBD_LAST) {
NetReceive ((uchar*)rx_buff, frame_length);
rx_buff_idx = 0;
}
}
/*
* Reset buffer descriptor as empty
*/
mpc512x_fec_rbd_clean (fec, pRbd);
}
/* Try to fill Buffer Descriptors */
fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
return frame_length;
}
/********************************************************************/
int mpc512x_fec_initialize (bd_t * bis)
{
immap_t *im = (immap_t*) CFG_IMMR;
mpc512x_fec_priv *fec;
struct eth_device *dev;
int i;
char *tmp, *end, env_enetaddr[6];
uint32 *reg;
void * bd;
fec = (mpc512x_fec_priv *) malloc (sizeof(*fec));
dev = (struct eth_device *) malloc (sizeof(*dev));
memset (dev, 0, sizeof *dev);
fec->eth = (ethernet_regs *) MPC512X_FEC;
# ifndef CONFIG_FEC_10MBIT
fec->xcv_type = MII100;
# else
fec->xcv_type = MII10;
# endif
dev->priv = (void *)fec;
dev->iobase = MPC512X_FEC;
dev->init = mpc512x_fec_init;
dev->halt = mpc512x_fec_halt;
dev->send = mpc512x_fec_send;
dev->recv = mpc512x_fec_recv;
sprintf (dev->name, "FEC ETHERNET");
eth_register (dev);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register (dev->name,
fec512x_miiphy_read, fec512x_miiphy_write);
#endif
/*
* Initialize I\O pins
*/
reg = (uint32 *) &(im->io_ctrl.regs[PSC0_0_IDX]);
for (i = 0; i < 15; i++)
reg[i] = IOCTRL_MUX_FEC | 0x00000001;
im->io_ctrl.regs[SPDIF_TXCLOCK_IDX] = IOCTRL_MUX_FEC | 0x00000001;
im->io_ctrl.regs[SPDIF_TX_IDX] = IOCTRL_MUX_FEC | 0x00000001;
im->io_ctrl.regs[SPDIF_RX_IDX] = IOCTRL_MUX_FEC | 0x00000001;
/* Clean up space FEC's MIB and FIFO RAM ...*/
memset ((void *) MPC512X_FEC + 0x200, 0x00, 0x400);
/*
* Malloc space for BDs (must be quad word-aligned)
* this pointer is lost, so cannot be freed
*/
bd = malloc (sizeof(mpc512x_buff_descs) + 0x1f);
fec->bdBase = (mpc512x_buff_descs*)((uint32)bd & 0xfffffff0);
memset ((void *) bd, 0x00, sizeof(mpc512x_buff_descs) + 0x1f);
/*
* Set interrupt mask register
*/
fec->eth->imask = 0x00000000;
/*
* Clear FEC-Lite interrupt event register(IEVENT)
*/
fec->eth->ievent = 0xffffffff;
/*
* Try to set the mac address now. The fec mac address is
* a garbage after reset. When not using fec for booting
* the Linux fec driver will try to work with this garbage.
*/
tmp = getenv ("ethaddr");
if (tmp) {
for (i=0; i<6; i++) {
env_enetaddr[i] = tmp ? simple_strtoul (tmp, &end, 16) : 0;
if (tmp)
tmp = (*end) ? end+1 : end;
}
mpc512x_fec_set_hwaddr (fec, env_enetaddr);
fec->eth->gaddr1 = 0x00000000;
fec->eth->gaddr2 = 0x00000000;
}
mpc512x_fec_init_phy (dev, bis);
return 1;
}
/* MII-interface related functions */
/********************************************************************/
int fec512x_miiphy_read (char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
{
ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC;
uint32 reg; /* convenient holder for the PHY register */
uint32 phy; /* convenient holder for the PHY */
int timeout = 0xffff;
/*
* reading from any PHY's register is done by properly
* programming the FEC's MII data register.
*/
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
/*
* wait for the related interrupt
*/
while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
if (timeout == 0) {
#if (DEBUG & 0x2)
printf ("Read MDIO failed...\n");
#endif
return -1;
}
/*
* clear mii interrupt bit
*/
eth->ievent = 0x00800000;
/*
* it's now safe to read the PHY's register
*/
*retVal = (uint16) eth->mii_data;
return 0;
}
/********************************************************************/
int fec512x_miiphy_write (char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
{
ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC;
uint32 reg; /* convenient holder for the PHY register */
uint32 phy; /* convenient holder for the PHY */
int timeout = 0xffff;
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
FEC_MII_DATA_TA | phy | reg | data);
/*
* wait for the MII interrupt
*/
while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
if (timeout == 0) {
#if (DEBUG & 0x2)
printf ("Write MDIO failed...\n");
#endif
return -1;
}
/*
* clear MII interrupt bit
*/
eth->ievent = 0x00800000;
return 0;
}
#if (DEBUG & 0x40)
static uint32 local_crc32 (char *string, unsigned int crc_value, int len)
{
int i;
char c;
unsigned int crc, count;
/*
* crc32 algorithm
*/
/*
* crc = 0xffffffff; * The initialized value should be 0xffffffff
*/
crc = crc_value;
for (i = len; --i >= 0;) {
c = *string++;
for (count = 0; count < 8; count++) {
if ((c & 0x01) ^ (crc & 0x01)) {
crc >>= 1;
crc = crc ^ 0xedb88320;
} else {
crc >>= 1;
}
c >>= 1;
}
}
/*
* In big endian system, do byte swaping for crc value
*/
/**/ return crc;
}
#endif /* DEBUG */
#endif /* CONFIG_MPC512x_FEC */

227
cpu/mpc512x/fec.h Normal file
View File

@@ -0,0 +1,227 @@
/*
* (C) Copyright 2003 - 2007
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Derived from the MPC8xx driver's header file.
*/
#ifndef __MPC512X_FEC_H
#define __MPC512X_FEC_H
#include <common.h>
#include <mpc512x.h>
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef struct ethernet_register_set {
/* [10:2]addr = 00 */
/* Control and status Registers (offset 000-1FF) */
volatile uint32 fec_id; /* MBAR_ETH + 0x000 */
volatile uint32 ievent; /* MBAR_ETH + 0x004 */
volatile uint32 imask; /* MBAR_ETH + 0x008 */
volatile uint32 RES0[1]; /* MBAR_ETH + 0x00C */
volatile uint32 r_des_active; /* MBAR_ETH + 0x010 */
volatile uint32 x_des_active; /* MBAR_ETH + 0x014 */
volatile uint32 RES1[3]; /* MBAR_ETH + 0x018-020 */
volatile uint32 ecntrl; /* MBAR_ETH + 0x024 */
volatile uint32 RES2[6]; /* MBAR_ETH + 0x028-03C */
volatile uint32 mii_data; /* MBAR_ETH + 0x040 */
volatile uint32 mii_speed; /* MBAR_ETH + 0x044 */
volatile uint32 RES3[7]; /* MBAR_ETH + 0x048-060 */
volatile uint32 mib_control; /* MBAR_ETH + 0x064 */
volatile uint32 RES4[7]; /* MBAR_ETH + 0x068-80 */
volatile uint32 r_cntrl; /* MBAR_ETH + 0x084 */
volatile uint32 r_hash; /* MBAR_ETH + 0x088 */
volatile uint32 RES5[14]; /* MBAR_ETH + 0x08c-0C0 */
volatile uint32 x_cntrl; /* MBAR_ETH + 0x0C4 */
volatile uint32 RES6[7]; /* MBAR_ETH + 0x0C8-0E0 */
volatile uint32 paddr1; /* MBAR_ETH + 0x0E4 */
volatile uint32 paddr2; /* MBAR_ETH + 0x0E8 */
volatile uint32 op_pause; /* MBAR_ETH + 0x0EC */
volatile uint32 RES7[10]; /* MBAR_ETH + 0x0F0-114 */
volatile uint32 iaddr1; /* MBAR_ETH + 0x118 */
volatile uint32 iaddr2; /* MBAR_ETH + 0x11C */
volatile uint32 gaddr1; /* MBAR_ETH + 0x120 */
volatile uint32 gaddr2; /* MBAR_ETH + 0x124 */
volatile uint32 RES8[6]; /* MBAR_ETH + 0x128-13C */
volatile uint32 fifo_id; /* MBAR_ETH + 0x140 */
volatile uint32 x_wmrk; /* MBAR_ETH + 0x144 */
volatile uint32 RES9[1]; /* MBAR_ETH + 0x148 */
volatile uint32 r_bound; /* MBAR_ETH + 0x14C */
volatile uint32 r_fstart; /* MBAR_ETH + 0x150 */
volatile uint32 RES10[11]; /* MBAR_ETH + 0x154-17C */
volatile uint32 r_des_start; /* MBAR_ETH + 0x180 */
volatile uint32 x_des_start; /* MBAR_ETH + 0x184 */
volatile uint32 r_buff_size; /* MBAR_ETH + 0x188 */
volatile uint32 RES11[26]; /* MBAR_ETH + 0x18C-1F0 */
volatile uint32 dma_control; /* MBAR_ETH + 0x1F4 */
volatile uint32 RES12[2]; /* MBAR_ETH + 0x1F8-1FC */
/* MIB COUNTERS (Offset 200-2FF) */
volatile uint32 rmon_t_drop; /* MBAR_ETH + 0x200 */
volatile uint32 rmon_t_packets; /* MBAR_ETH + 0x204 */
volatile uint32 rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
volatile uint32 rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
volatile uint32 rmon_t_crc_align; /* MBAR_ETH + 0x210 */
volatile uint32 rmon_t_undersize; /* MBAR_ETH + 0x214 */
volatile uint32 rmon_t_oversize; /* MBAR_ETH + 0x218 */
volatile uint32 rmon_t_frag; /* MBAR_ETH + 0x21C */
volatile uint32 rmon_t_jab; /* MBAR_ETH + 0x220 */
volatile uint32 rmon_t_col; /* MBAR_ETH + 0x224 */
volatile uint32 rmon_t_p64; /* MBAR_ETH + 0x228 */
volatile uint32 rmon_t_p65to127; /* MBAR_ETH + 0x22C */
volatile uint32 rmon_t_p128to255; /* MBAR_ETH + 0x230 */
volatile uint32 rmon_t_p256to511; /* MBAR_ETH + 0x234 */
volatile uint32 rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
volatile uint32 rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
volatile uint32 rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
volatile uint32 rmon_t_octets; /* MBAR_ETH + 0x244 */
volatile uint32 ieee_t_drop; /* MBAR_ETH + 0x248 */
volatile uint32 ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
volatile uint32 ieee_t_1col; /* MBAR_ETH + 0x250 */
volatile uint32 ieee_t_mcol; /* MBAR_ETH + 0x254 */
volatile uint32 ieee_t_def; /* MBAR_ETH + 0x258 */
volatile uint32 ieee_t_lcol; /* MBAR_ETH + 0x25C */
volatile uint32 ieee_t_excol; /* MBAR_ETH + 0x260 */
volatile uint32 ieee_t_macerr; /* MBAR_ETH + 0x264 */
volatile uint32 ieee_t_cserr; /* MBAR_ETH + 0x268 */
volatile uint32 ieee_t_sqe; /* MBAR_ETH + 0x26C */
volatile uint32 t_fdxfc; /* MBAR_ETH + 0x270 */
volatile uint32 ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
volatile uint32 RES13[2]; /* MBAR_ETH + 0x278-27C */
volatile uint32 rmon_r_drop; /* MBAR_ETH + 0x280 */
volatile uint32 rmon_r_packets; /* MBAR_ETH + 0x284 */
volatile uint32 rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
volatile uint32 rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
volatile uint32 rmon_r_crc_align; /* MBAR_ETH + 0x290 */
volatile uint32 rmon_r_undersize; /* MBAR_ETH + 0x294 */
volatile uint32 rmon_r_oversize; /* MBAR_ETH + 0x298 */
volatile uint32 rmon_r_frag; /* MBAR_ETH + 0x29C */
volatile uint32 rmon_r_jab; /* MBAR_ETH + 0x2A0 */
volatile uint32 rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
volatile uint32 rmon_r_p64; /* MBAR_ETH + 0x2A8 */
volatile uint32 rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
volatile uint32 rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
volatile uint32 rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
volatile uint32 rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
volatile uint32 rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
volatile uint32 rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
volatile uint32 rmon_r_octets; /* MBAR_ETH + 0x2C4 */
volatile uint32 ieee_r_drop; /* MBAR_ETH + 0x2C8 */
volatile uint32 ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
volatile uint32 ieee_r_crc; /* MBAR_ETH + 0x2D0 */
volatile uint32 ieee_r_align; /* MBAR_ETH + 0x2D4 */
volatile uint32 r_macerr; /* MBAR_ETH + 0x2D8 */
volatile uint32 r_fdxfc; /* MBAR_ETH + 0x2DC */
volatile uint32 ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
volatile uint32 RES14[6]; /* MBAR_ETH + 0x2E4-2FC */
volatile uint32 RES15[64]; /* MBAR_ETH + 0x300-3FF */
} ethernet_regs;
/* Receive & Transmit Buffer Descriptor definitions */
typedef struct BufferDescriptor {
uint16 status;
uint16 dataLength;
uint32 dataPointer;
} FEC_RBD;
typedef struct {
uint16 status;
uint16 dataLength;
uint32 dataPointer;
} FEC_TBD;
/* private structure */
typedef enum {
SEVENWIRE, /* 7-wire */
MII10, /* MII 10Mbps */
MII100 /* MII 100Mbps */
} xceiver_type;
/* BD Numer definitions */
#define FEC_TBD_NUM 48 /* The user can adjust this value */
#define FEC_RBD_NUM 32 /* The user can adjust this value */
/* packet size limit */
#define FEC_MAX_FRAME_LEN 1522 /* recommended default value */
/* Buffer size must be evenly divisible by 16 */
#define FEC_BUFFER_SIZE ((FEC_MAX_FRAME_LEN + 0x10) & (~0xf))
typedef struct {
uint8 frame[FEC_BUFFER_SIZE];
} mpc512x_frame;
typedef struct {
FEC_RBD rbd[FEC_RBD_NUM]; /* RBD ring */
FEC_TBD tbd[FEC_TBD_NUM]; /* TBD ring */
mpc512x_frame recv_frames[FEC_RBD_NUM]; /* receive buff */
} mpc512x_buff_descs;
typedef struct {
ethernet_regs *eth;
xceiver_type xcv_type; /* transceiver type */
mpc512x_buff_descs *bdBase; /* BD rings and recv buffer */
uint16 rbdIndex; /* next receive BD to read */
uint16 tbdIndex; /* next transmit BD to send */
uint16 usedTbdIndex; /* next transmit BD to clean */
uint16 cleanTbdNum; /* the number of available transmit BDs */
} mpc512x_fec_priv;
/* RBD bits definitions */
#define FEC_RBD_EMPTY 0x8000 /* Buffer is empty */
#define FEC_RBD_WRAP 0x2000 /* Last BD in ring */
#define FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */
#define FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */
#define FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */
#define FEC_RBD_MC 0x0040 /* The received frame is multicast frame */
#define FEC_RBD_LG 0x0020 /* Frame length violation */
#define FEC_RBD_NO 0x0010 /* Nonoctet align frame */
#define FEC_RBD_SH 0x0008 /* Short frame */
#define FEC_RBD_CR 0x0004 /* CRC error */
#define FEC_RBD_OV 0x0002 /* Receive FIFO overrun */
#define FEC_RBD_TR 0x0001 /* Frame is truncated */
#define FEC_RBD_ERR (FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
FEC_RBD_OV | FEC_RBD_TR)
/* TBD bits definitions */
#define FEC_TBD_READY 0x8000 /* Buffer is ready */
#define FEC_TBD_WRAP 0x2000 /* Last BD in ring */
#define FEC_TBD_LAST 0x0800 /* Buffer is last in frame */
#define FEC_TBD_TC 0x0400 /* Transmit the CRC */
#define FEC_TBD_ABC 0x0200 /* Append bad CRC */
/* MII-related definitios */
#define FEC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */
#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */
#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */
#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */
#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */
#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */
#define FEC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */
#define FEC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
#endif /* __MPC512X_FEC_H */

431
cpu/mpc512x/i2c.c Normal file
View File

@@ -0,0 +1,431 @@
/*
* (C) Copyright 2003 - 2007
* 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
*
* Based on the MPC5xxx code.
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_HARD_I2C
#include <mpc512x.h>
#include <i2c.h>
#define immr ((immap_t *)CFG_IMMR)
/* by default set I2C bus 0 active */
static unsigned int bus_num = 0;
#define I2C_TIMEOUT 100
#define I2C_RETRIES 3
struct mpc512x_i2c_tap {
int scl2tap;
int tap2tap;
};
static int mpc_reg_in(volatile u32 *reg);
static void mpc_reg_out(volatile u32 *reg, int val, int mask);
static int wait_for_bb(void);
static int wait_for_pin(int *status);
static int do_address(uchar chip, char rdwr_flag);
static int send_bytes(uchar chip, char *buf, int len);
static int receive_bytes(uchar chip, char *buf, int len);
static int mpc_get_fdr(int);
static int mpc_reg_in (volatile u32 *reg)
{
int ret = *reg >> 24;
__asm__ __volatile__ ("eieio");
return ret;
}
static void mpc_reg_out (volatile u32 *reg, int val, int mask)
{
int tmp;
if (!mask) {
*reg = val << 24;
} else {
tmp = mpc_reg_in (reg);
*reg = ((tmp & ~mask) | (val & mask)) << 24;
}
__asm__ __volatile__ ("eieio");
return;
}
static int wait_for_bb (void)
{
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int timeout = I2C_TIMEOUT;
int status;
status = mpc_reg_in (&regs->msr);
while (timeout-- && (status & I2C_BB)) {
volatile int temp;
mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
temp = mpc_reg_in (&regs->mdr);
mpc_reg_out (&regs->mcr, 0, I2C_STA);
mpc_reg_out (&regs->mcr, 0, 0);
mpc_reg_out (&regs->mcr, I2C_EN, 0);
udelay (1000);
status = mpc_reg_in (&regs->msr);
}
return (status & I2C_BB);
}
static int wait_for_pin (int *status)
{
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int timeout = I2C_TIMEOUT;
*status = mpc_reg_in (&regs->msr);
while (timeout-- && !(*status & I2C_IF)) {
udelay (1000);
*status = mpc_reg_in (&regs->msr);
}
if (!(*status & I2C_IF)) {
return -1;
}
mpc_reg_out (&regs->msr, 0, I2C_IF);
return 0;
}
static int do_address (uchar chip, char rdwr_flag)
{
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int status;
chip <<= 1;
if (rdwr_flag) {
chip |= 1;
}
mpc_reg_out (&regs->mcr, I2C_TX, I2C_TX);
mpc_reg_out (&regs->mdr, chip, 0);
if (wait_for_pin (&status)) {
return -2;
}
if (status & I2C_RXAK) {
return -3;
}
return 0;
}
static int send_bytes (uchar chip, char *buf, int len)
{
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int wrcount;
int status;
for (wrcount = 0; wrcount < len; ++wrcount) {
mpc_reg_out (&regs->mdr, buf[wrcount], 0);
if (wait_for_pin (&status)) {
break;
}
if (status & I2C_RXAK) {
break;
}
}
return !(wrcount == len);
}
static int receive_bytes (uchar chip, char *buf, int len)
{
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int dummy = 1;
int rdcount = 0;
int status;
int i;
mpc_reg_out (&regs->mcr, 0, I2C_TX);
for (i = 0; i < len; ++i) {
buf[rdcount] = mpc_reg_in (&regs->mdr);
if (dummy) {
dummy = 0;
} else {
rdcount++;
}
if (wait_for_pin (&status)) {
return -4;
}
}
mpc_reg_out (&regs->mcr, I2C_TXAK, I2C_TXAK);
buf[rdcount++] = mpc_reg_in (&regs->mdr);
if (wait_for_pin (&status)) {
return -5;
}
mpc_reg_out (&regs->mcr, 0, I2C_TXAK);
return 0;
}
/**************** I2C API ****************/
void i2c_init (int speed, int saddr)
{
int i;
for(i = 0; i < I2C_BUS_CNT; i++){
i2c512x_dev_t *regs = &immr->i2c.dev[i];
mpc_reg_out (&regs->mcr, 0, 0);
/* Set clock */
mpc_reg_out (&regs->mfdr, mpc_get_fdr (speed), 0);
mpc_reg_out (&regs->madr, saddr << 1, 0);
/* Enable module */
mpc_reg_out (&regs->mcr, I2C_EN, I2C_INIT_MASK);
mpc_reg_out (&regs->msr, 0, I2C_IF);
}
/* Disable interrupts */
immr->i2c.icr = 0;
/* Turn off filters */
immr->i2c.mifr = 0;
return;
}
static int mpc_get_fdr (int speed)
{
static int fdr = -1;
if (fdr == -1) {
ulong best_speed = 0;
ulong divider;
ulong ipb, scl;
ulong bestmatch = 0xffffffffUL;
int best_i = 0, best_j = 0, i, j;
int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
struct mpc512x_i2c_tap scltap[] = {
{4, 1},
{4, 2},
{6, 4},
{6, 8},
{14, 16},
{30, 32},
{62, 64},
{126, 128}
};
ipb = gd->ipb_clk;
for (i = 7; i >= 0; i--) {
for (j = 7; j >= 0; j--) {
scl = 2 * (scltap[j].scl2tap +
(SCL_Tap[i] - 1) * scltap[j].tap2tap
+ 2);
if (ipb <= speed*scl) {
if ((speed*scl - ipb) < bestmatch) {
bestmatch = speed*scl - ipb;
best_i = i;
best_j = j;
best_speed = ipb/scl;
}
}
}
}
divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
if (gd->flags & GD_FLG_RELOC) {
fdr = divider;
} else {
debug("%ld kHz, \n", best_speed / 1000);
return divider;
}
}
return fdr;
}
int i2c_probe (uchar chip)
{
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int i;
for (i = 0; i < I2C_RETRIES; i++) {
mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
if (! do_address (chip, 0)) {
mpc_reg_out (&regs->mcr, 0, I2C_STA);
udelay (500);
break;
}
mpc_reg_out (&regs->mcr, 0, I2C_STA);
udelay (500);
}
return (i == I2C_RETRIES);
}
int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len)
{
char xaddr[4];
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int ret = -1;
xaddr[0] = (addr >> 24) & 0xFF;
xaddr[1] = (addr >> 16) & 0xFF;
xaddr[2] = (addr >> 8) & 0xFF;
xaddr[3] = addr & 0xFF;
if (wait_for_bb ()) {
printf ("i2c_read: bus is busy\n");
goto Done;
}
mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
if (do_address (chip, 0)) {
printf ("i2c_read: failed to address chip\n");
goto Done;
}
if (send_bytes (chip, &xaddr[4-alen], alen)) {
printf ("i2c_read: send_bytes failed\n");
goto Done;
}
mpc_reg_out (&regs->mcr, I2C_RSTA, I2C_RSTA);
if (do_address (chip, 1)) {
printf ("i2c_read: failed to address chip\n");
goto Done;
}
if (receive_bytes (chip, (char *)buf, len)) {
printf ("i2c_read: receive_bytes failed\n");
goto Done;
}
ret = 0;
Done:
mpc_reg_out (&regs->mcr, 0, I2C_STA);
return ret;
}
int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len)
{
char xaddr[4];
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
int ret = -1;
xaddr[0] = (addr >> 24) & 0xFF;
xaddr[1] = (addr >> 16) & 0xFF;
xaddr[2] = (addr >> 8) & 0xFF;
xaddr[3] = addr & 0xFF;
if (wait_for_bb ()) {
printf ("i2c_write: bus is busy\n");
goto Done;
}
mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
if (do_address (chip, 0)) {
printf ("i2c_write: failed to address chip\n");
goto Done;
}
if (send_bytes (chip, &xaddr[4-alen], alen)) {
printf ("i2c_write: send_bytes failed\n");
goto Done;
}
if (send_bytes (chip, (char *)buf, len)) {
printf ("i2c_write: send_bytes failed\n");
goto Done;
}
ret = 0;
Done:
mpc_reg_out (&regs->mcr, 0, I2C_STA);
return ret;
}
uchar i2c_reg_read (uchar chip, uchar reg)
{
uchar buf;
i2c_read (chip, reg, 1, &buf, 1);
return buf;
}
void i2c_reg_write (uchar chip, uchar reg, uchar val)
{
i2c_write (chip, reg, 1, &val, 1);
return;
}
int i2c_set_bus_num (unsigned int bus)
{
if (bus >= I2C_BUS_CNT) {
return -1;
}
bus_num = bus;
return 0;
}
unsigned int i2c_get_bus_num (void)
{
return bus_num;
}
/* TODO */
unsigned int i2c_get_bus_speed (void)
{
return -1;
}
int i2c_set_bus_speed (unsigned int speed)
{
if (speed != CFG_I2C_SPEED)
return -1;
return 0;
}
#endif /* CONFIG_HARD_I2C */

61
cpu/mpc512x/interrupts.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* (C) Copyright 2000-2007
* 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
*
* Derived from the MPC83xx code.
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
struct irq_action {
interrupt_handler_t *handler;
void *arg;
ulong count;
};
int interrupt_init_cpu (unsigned *decrementer_count)
{
*decrementer_count = get_tbclk () / CFG_HZ;
return 0;
}
/*
* Install and free an interrupt handler.
*/
void
irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
{
}
void irq_free_handler (int irq)
{
}
void timer_interrupt_cpu (struct pt_regs *regs)
{
/* nothing to do here */
return;
}

197
cpu/mpc512x/serial.c Normal file
View File

@@ -0,0 +1,197 @@
/*
* (C) Copyright 2000 - 2007
* 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
*
* Based ont the MPC5200 PSC driver.
* Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
*/
/*
* Minimal serial functions needed to use one of the PSC ports
* as serial console interface.
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_PSC_CONSOLE)
static void fifo_init (volatile psc512x_t *psc)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
/* reset Rx & Tx fifo slice */
psc->rfcmd = PSC_FIFO_RESET_SLICE;
psc->tfcmd = PSC_FIFO_RESET_SLICE;
/* disable Tx & Rx FIFO interrupts */
psc->rfintmask = 0;
psc->tfintmask = 0;
psc->tfsize = CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16);
psc->rfsize = CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16);
/* enable Tx & Rx FIFO slice */
psc->rfcmd = PSC_FIFO_ENABLE_SLICE;
psc->tfcmd = PSC_FIFO_ENABLE_SLICE;
im->fifoc.fifoc_cmd = FIFOC_DISABLE_CLOCK_GATE;
__asm__ volatile ("sync");
}
int serial_init(void)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
unsigned long baseclk;
int div;
fifo_init (psc);
/* set MR register to point to MR1 */
psc->command = PSC_SEL_MODE_REG_1;
/* disable Tx/Rx */
psc->command = PSC_TX_DISABLE | PSC_RX_DISABLE;
/* choose the prescaler by 16 for the Tx/Rx clock generation */
psc->psc_clock_select = 0xdd00;
/* switch to UART mode */
psc->sicr = 0;
/* mode register points to mr1 */
/* configure parity, bit length and so on in mode register 1*/
psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
/* now, mode register points to mr2 */
psc->mode = PSC_MODE_1_STOPBIT;
/* calculate dividor for setting PSC CTUR and CTLR registers */
baseclk = (gd->ipb_clk + 8) / 16;
div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
psc->ctur = (div >> 8) & 0xff;
/* set baudrate */
psc->ctlr = div & 0xff;
/* disable all interrupts */
psc->psc_imr = 0;
/* reset and enable Rx/Tx */
psc->command = PSC_RST_RX;
psc->command = PSC_RST_TX;
psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
return 0;
}
void serial_putc (const char c)
{
volatile immap_t *im = (immap_t *)CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
if (c == '\n')
serial_putc ('\r');
/* Wait for last character to go. */
while (!(psc->psc_status & PSC_SR_TXEMP))
;
psc->tfdata_8 = c;
}
void serial_putc_raw (const char c)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
/* Wait for last character to go. */
while (!(psc->psc_status & PSC_SR_TXEMP))
;
psc->tfdata_8 = c;
}
void serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
int serial_getc (void)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
/* Wait for a character to arrive. */
while (psc->rfstat & PSC_FIFO_EMPTY)
;
return psc->rfdata_8;
}
int serial_tstc (void)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
return !(psc->rfstat & PSC_FIFO_EMPTY);
}
void serial_setbrg (void)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
unsigned long baseclk, div;
baseclk = (gd->csb_clk + 8) / 16;
div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
psc->ctur = (div >> 8) & 0xFF;
psc->ctlr = div & 0xff; /* set baudrate */
}
void serial_setrts(int s)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
if (s) {
/* Assert RTS (become LOW) */
psc->op1 = 0x1;
}
else {
/* Negate RTS (become HIGH) */
psc->op0 = 0x1;
}
}
int serial_getcts(void)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
return (psc->ip & 0x1) ? 0 : 1;
}
#endif /* CONFIG_PSC_CONSOLE */

135
cpu/mpc512x/speed.c Normal file
View File

@@ -0,0 +1,135 @@
/*
* (C) Copyright 2000-2007
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2004-2006 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
*
* Based on the MPC83xx code.
*/
#include <common.h>
#include <mpc512x.h>
#include <command.h>
#include <asm/processor.h>
DECLARE_GLOBAL_DATA_PTR;
static int spmf_mult[] = {
68, 1, 12, 16,
20, 24, 28, 32,
36, 40, 44, 48,
52, 56, 60, 64
};
static int cpmf_mult[][2] = {
{0, 1}, {0, 1}, /* 0 and 1 are not valid */
{1, 1}, {3, 2},
{2, 1}, {5, 2},
{3, 1}, {7, 2},
{0, 1}, {0, 1}, /* and all above 7 are not valid too */
{0, 1}, {0, 1},
{0, 1}, {0, 1},
{0, 1}, {0, 1}
};
static int sys_dividors[][2] = {
{2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1},
{9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1},
{9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1},
{15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1},
{18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1},
{24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1},
{29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1}
};
int get_clocks (void)
{
volatile immap_t *im = (immap_t *) CFG_IMMR;
u8 spmf;
u8 cpmf;
u8 sys_div;
u8 ips_div;
u32 ref_clk = CFG_MPC512X_CLKIN;
u32 spll;
u32 sys_clk;
u32 core_clk;
u32 csb_clk;
u32 ips_clk;
if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
return -1;
spmf = (im->clk.spmr & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
spll = ref_clk * spmf_mult[spmf];
sys_div = (im->clk.scfr[1] & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT;
sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0];
csb_clk = sys_clk / 2;
cpmf = (im->clk.spmr & SPMR_CPMF) >> SPMR_CPMF_SHIFT;
core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1];
ips_div = (im->clk.scfr[0] & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT;
if (ips_div != 0) {
ips_clk = csb_clk / ips_div;
} else {
/* in case we cannot get a sane IPS divisor, fail gracefully */
ips_clk = 0;
}
gd->ipb_clk = ips_clk;
gd->csb_clk = csb_clk;
gd->cpu_clk = core_clk;
gd->bus_clk = csb_clk;
return 0;
}
/********************************************
* get_bus_freq
* return system bus freq in Hz
*********************************************/
ulong get_bus_freq (ulong dummy)
{
return gd->csb_clk;
}
int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
printf ("Clock configuration:\n");
printf (" CPU: %4d MHz\n", gd->cpu_clk / 1000000);
printf (" Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000);
printf (" IPS Bus: %4d MHz\n", gd->ipb_clk / 1000000);
printf (" DDR: %4d MHz\n", 2 * gd->csb_clk / 1000000);
return 0;
}
U_BOOT_CMD(clocks, 1, 0, do_clocks,
"clocks - print clock configuration\n",
" clocks\n"
);
int prt_mpc512x_clks (void)
{
do_clocks (NULL, 0, 0, NULL);
return (0);
}

780
cpu/mpc512x/start.S Normal file
View File

@@ -0,0 +1,780 @@
/*
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
* Copyright (C) 2000, 2001, 2002, 2007 Wolfgang Denk <wd@denx.de>
* Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
*
* 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
*
* Based on the MPC83xx code.
*/
/*
* U-Boot - Startup Code for MPC512x based Embedded Boards
*/
#include <config.h>
#include <mpc512x.h>
#include <version.h>
#define CONFIG_521X 1 /* needed for Linux kernel header files*/
#include <ppc_asm.tmpl>
#include <ppc_defs.h>
#include <asm/cache.h>
#include <asm/mmu.h>
#ifndef CONFIG_IDENT_STRING
#define CONFIG_IDENT_STRING "MPC512X"
#endif
/*
* Floating Point enable, Machine Check and Recoverable Interr.
*/
#undef MSR_KERNEL
#ifdef DEBUG
#define MSR_KERNEL (MSR_FP|MSR_RI)
#else
#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
#endif
/* Macros for manipulating CSx_START/STOP */
#define START_REG(start) ((start) >> 16)
#define STOP_REG(start, size) (((start) + (size) - 1) >> 16)
/*
* Set up GOT: Global Offset Table
*
* Use r14 to access the GOT
*/
START_GOT
GOT_ENTRY(_GOT2_TABLE_)
GOT_ENTRY(_FIXUP_TABLE_)
GOT_ENTRY(_start)
GOT_ENTRY(_start_of_vectors)
GOT_ENTRY(_end_of_vectors)
GOT_ENTRY(transfer_to_handler)
GOT_ENTRY(__init_end)
GOT_ENTRY(_end)
GOT_ENTRY(__bss_start)
END_GOT
/*
* Magic number and version string
*/
.long 0x27051956 /* U-Boot Magic Number */
.globl version_string
version_string:
.ascii U_BOOT_VERSION
.ascii " (", __DATE__, " - ", __TIME__, ")"
.ascii " ", CONFIG_IDENT_STRING, "\0"
/*
* Vector Table
*/
.text
. = EXC_OFF_SYS_RESET
.globl _start
/* Start from here after reset/power on */
_start:
li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
b boot_cold
.globl _start_of_vectors
_start_of_vectors:
/* Machine check */
STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
/* Data Storage exception. */
STD_EXCEPTION(0x300, DataStorage, UnknownException)
/* Instruction Storage exception. */
STD_EXCEPTION(0x400, InstStorage, UnknownException)
/* External Interrupt exception. */
STD_EXCEPTION(0x500, ExtInterrupt, UnknownException)
/* Alignment exception. */
. = 0x600
Alignment:
EXCEPTION_PROLOG(SRR0, SRR1)
mfspr r4,DAR
stw r4,_DAR(r21)
mfspr r5,DSISR
stw r5,_DSISR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
lwz r6,GOT(transfer_to_handler)
mtlr r6
blrl
.L_Alignment:
.long AlignmentException - _start + EXC_OFF_SYS_RESET
.long int_return - _start + EXC_OFF_SYS_RESET
/* Program check exception */
. = 0x700
ProgramCheck:
EXCEPTION_PROLOG(SRR0, SRR1)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
lwz r6,GOT(transfer_to_handler)
mtlr r6
blrl
.L_ProgramCheck:
.long ProgramCheckException - _start + EXC_OFF_SYS_RESET
.long int_return - _start + EXC_OFF_SYS_RESET
/* Floating Point Unit unavailable exception */
STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
/* Decrementer */
STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
/* Critical interrupt */
STD_EXCEPTION(0xa00, Critical, UnknownException)
/* System Call */
STD_EXCEPTION(0xc00, SystemCall, UnknownException)
/* Trace interrupt */
STD_EXCEPTION(0xd00, Trace, UnknownException)
/* Performance Monitor interrupt */
STD_EXCEPTION(0xf00, PerfMon, UnknownException)
/* Intruction Translation Miss */
STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
/* Data Load Translation Miss */
STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
/* Data Store Translation Miss */
STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
/* Instruction Address Breakpoint */
STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException)
/* System Management interrupt */
STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException)
.globl _end_of_vectors
_end_of_vectors:
. = 0x3000
boot_cold:
/* Save msr contents */
mfmsr r5
/* Set IMMR area to our preferred location */
lis r4, CONFIG_DEFAULT_IMMR@h
lis r3, CFG_IMMR@h
ori r3, r3, CFG_IMMR@l
stw r3, IMMRBAR(r4)
mtspr MBAR, r3 /* IMMRBAR is mirrored into the MBAR SPR (311) */
/* Initialise the machine */
bl cpu_early_init
/*
* Set up Local Access Windows:
*
* 1) Boot/CS0 (boot FLASH)
* 2) On-chip SRAM (initial stack purposes)
*/
/* Boot CS/CS0 window range */
lis r3, CFG_IMMR@h
ori r3, r3, CFG_IMMR@l
lis r4, START_REG(CFG_FLASH_BASE)
ori r4, r4, STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE)
stw r4, LPCS0AW(r3)
/*
* The SRAM window has a fixed size (256K), so only the start address
* is necessary
*/
lis r4, START_REG(CFG_SRAM_BASE) & 0xff00
stw r4, SRAMBAR(r3)
/*
* According to MPC5121e RM, configuring local access windows should
* be followed by a dummy read of the config register that was
* modified last and an isync
*/
lwz r4, SRAMBAR(r3)
isync
/*
* Set configuration of the Boot/CS0, the SRAM window does not have a
* config register so no params can be set for it
*/
lis r3, (CFG_IMMR + LPC_OFFSET)@h
ori r3, r3, (CFG_IMMR + LPC_OFFSET)@l
lis r4, CFG_CS0_CFG@h
ori r4, r4, CFG_CS0_CFG@l
stw r4, CS0_CONFIG(r3)
/* Master enable all CS's */
lis r4, CS_CTRL_ME@h
ori r4, r4, CS_CTRL_ME@l
stw r4, CS_CTRL(r3)
lis r4, (CFG_MONITOR_BASE)@h
ori r4, r4, (CFG_MONITOR_BASE)@l
addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
mtlr r5
blr
in_flash:
lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
li r0, 0 /* Make room for stack frame header and */
stwu r0, -4(r1) /* clear final stack frame so that */
stwu r0, -4(r1) /* stack backtraces terminate cleanly */
/* let the C-code set up the rest */
/* */
/* Be careful to keep code relocatable & stack humble */
/*------------------------------------------------------*/
GET_GOT /* initialize GOT access */
/* r3: IMMR */
lis r3, CFG_IMMR@h
/* run low-level CPU init code (in Flash) */
bl cpu_init_f
/* r3: BOOTFLAG */
mr r3, r21
/* run 1st part of board init code (in Flash) */
bl board_init_f
/* NOTREACHED - board_init_f() does not return */
/*
* This code finishes saving the registers to the exception frame
* and jumps to the appropriate handler for the exception.
* Register r21 is pointer into trap frame, r1 has new stack pointer.
*/
.globl transfer_to_handler
transfer_to_handler:
stw r22,_NIP(r21)
lis r22,MSR_POW@h
andc r23,r23,r22
stw r23,_MSR(r21)
SAVE_GPR(7, r21)
SAVE_4GPRS(8, r21)
SAVE_8GPRS(12, r21)
SAVE_8GPRS(24, r21)
mflr r23
andi. r24,r23,0x3f00 /* get vector offset */
stw r24,TRAP(r21)
li r22,0
stw r22,RESULT(r21)
lwz r24,0(r23) /* virtual address of handler */
lwz r23,4(r23) /* where to go when done */
mtspr SRR0,r24
mtspr SRR1,r20
mtlr r23
SYNC
rfi /* jump to handler, enable MMU */
int_return:
mfmsr r28 /* Disable interrupts */
li r4,0
ori r4,r4,MSR_EE
andc r28,r28,r4
SYNC /* Some chip revs need this... */
mtmsr r28
SYNC
lwz r2,_CTR(r1)
lwz r0,_LINK(r1)
mtctr r2
mtlr r0
lwz r2,_XER(r1)
lwz r0,_CCR(r1)
mtspr XER,r2
mtcrf 0xFF,r0
REST_10GPRS(3, r1)
REST_10GPRS(13, r1)
REST_8GPRS(23, r1)
REST_GPR(31, r1)
lwz r2,_NIP(r1) /* Restore environment */
lwz r0,_MSR(r1)
mtspr SRR0,r2
mtspr SRR1,r0
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
SYNC
rfi
/*
* This code initialises the machine, it expects original MSR contents to be in r5.
*/
cpu_early_init:
/* Initialize machine status; enable machine check interrupt */
/*-----------------------------------------------------------*/
li r3, MSR_KERNEL /* Set ME and RI flags */
rlwimi r3, r5, 0, 25, 25 /* preserve IP bit */
#ifdef DEBUG
rlwimi r3, r5, 0, 21, 22 /* debugger might set SE, BE bits */
#endif
mtmsr r3
SYNC
mtspr SRR1, r3 /* Mirror current MSR state in SRR1 */
lis r3, CFG_IMMR@h
#if defined(CONFIG_WATCHDOG)
/* Initialise the watchdog and reset it */
/*--------------------------------------*/
lis r4, CFG_WATCHDOG_VALUE
ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
stw r4, SWCRR(r3)
/* reset */
li r4, 0x556C
sth r4, SWSRR@l(r3)
li r4, 0x0
ori r4, r4, 0xAA39
sth r4, SWSRR@l(r3)
#else
/* Disable the watchdog */
/*----------------------*/
lwz r4, SWCRR(r3)
/*
* Check to see if it's enabled for disabling: once disabled by s/w
* it's not possible to re-enable it
*/
andi. r4, r4, 0x4
beq 1f
xor r4, r4, r4
stw r4, SWCRR(r3)
1:
#endif /* CONFIG_WATCHDOG */
/* Initialize the Hardware Implementation-dependent Registers */
/* HID0 also contains cache control */
/*------------------------------------------------------*/
lis r3, CFG_HID0_INIT@h
ori r3, r3, CFG_HID0_INIT@l
SYNC
mtspr HID0, r3
lis r3, CFG_HID0_FINAL@h
ori r3, r3, CFG_HID0_FINAL@l
SYNC
mtspr HID0, r3
lis r3, CFG_HID2@h
ori r3, r3, CFG_HID2@l
SYNC
mtspr HID2, r3
sync
blr
/* Cache functions.
*
* Note: requires that all cache bits in
* HID0 are in the low half word.
*/
.globl icache_enable
icache_enable:
mfspr r3, HID0
ori r3, r3, HID0_ICE
lis r4, 0
ori r4, r4, HID0_ILOCK
andc r3, r3, r4
ori r4, r3, HID0_ICFI
isync
mtspr HID0, r4 /* sets enable and invalidate, clears lock */
isync
mtspr HID0, r3 /* clears invalidate */
blr
.globl icache_disable
icache_disable:
mfspr r3, HID0
lis r4, 0
ori r4, r4, HID0_ICE|HID0_ILOCK
andc r3, r3, r4
ori r4, r3, HID0_ICFI
isync
mtspr HID0, r4 /* sets invalidate, clears enable and lock*/
isync
mtspr HID0, r3 /* clears invalidate */
blr
.globl icache_status
icache_status:
mfspr r3, HID0
rlwinm r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
blr
.globl dcache_enable
dcache_enable:
mfspr r3, HID0
li r5, HID0_DCFI|HID0_DLOCK
andc r3, r3, r5
mtspr HID0, r3 /* no invalidate, unlock */
ori r3, r3, HID0_DCE
ori r5, r3, HID0_DCFI
mtspr HID0, r5 /* enable + invalidate */
mtspr HID0, r3 /* enable */
sync
blr
.globl dcache_disable
dcache_disable:
mfspr r3, HID0
lis r4, 0
ori r4, r4, HID0_DCE|HID0_DLOCK
andc r3, r3, r4
ori r4, r3, HID0_DCI
sync
mtspr HID0, r4 /* sets invalidate, clears enable and lock */
sync
mtspr HID0, r3 /* clears invalidate */
blr
.globl dcache_status
dcache_status:
mfspr r3, HID0
rlwinm r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
blr
.globl get_pvr
get_pvr:
mfspr r3, PVR
blr
/*------------------------------------------------------------------------------- */
/* Function: ppcDcbf */
/* Description: Data Cache block flush */
/* Input: r3 = effective address */
/* Output: none. */
/*------------------------------------------------------------------------------- */
.globl ppcDcbf
ppcDcbf:
dcbf r0,r3
blr
/*------------------------------------------------------------------------------- */
/* Function: ppcDcbi */
/* Description: Data Cache block Invalidate */
/* Input: r3 = effective address */
/* Output: none. */
/*------------------------------------------------------------------------------- */
.globl ppcDcbi
ppcDcbi:
dcbi r0,r3
blr
/*--------------------------------------------------------------------------
* Function: ppcDcbz
* Description: Data Cache block zero.
* Input: r3 = effective address
* Output: none.
*-------------------------------------------------------------------------- */
.globl ppcDcbz
ppcDcbz:
dcbz r0,r3
blr
.globl ppcDWstore
ppcDWstore:
lfd 1, 0(r4)
stfd 1, 0(r3)
blr
.globl ppcDWload
ppcDWload:
lfd 1, 0(r3)
stfd 1, 0(r4)
blr
/*-------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* r3 = dest
* r4 = src
* r5 = length in bytes
* r6 = cachelinesize
*/
.globl relocate_code
relocate_code:
mr r1, r3 /* Set new stack pointer */
mr r9, r4 /* Save copy of Global Data pointer */
mr r10, r5 /* Save copy of Destination Address */
mr r3, r5 /* Destination Address */
lis r4, CFG_MONITOR_BASE@h /* Source Address */
ori r4, r4, CFG_MONITOR_BASE@l
lwz r5, GOT(__init_end)
sub r5, r5, r4
li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
/*
* Fix GOT pointer:
*
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
* + Destination Address
*
* Offset:
*/
sub r15, r10, r4
/* First our own GOT */
add r14, r14, r15
/* then the one used by the C code */
add r30, r30, r15
/*
* Now relocate code
*/
cmplw cr1,r3,r4
addi r0,r5,3
srwi. r0,r0,2
beq cr1,4f /* In place copy is not necessary */
beq 7f /* Protect against 0 count */
mtctr r0
bge cr1,2f
la r8,-4(r4)
la r7,-4(r3)
/* copy */
1: lwzu r0,4(r8)
stwu r0,4(r7)
bdnz 1b
addi r0,r5,3
srwi. r0,r0,2
mtctr r0
la r8,-4(r4)
la r7,-4(r3)
/* and compare */
20: lwzu r20,4(r8)
lwzu r21,4(r7)
xor. r22, r20, r21
bne 30f
bdnz 20b
b 4f
/* compare failed */
30: li r3, 0
blr
2: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
add r8,r4,r0
add r7,r3,r0
3: lwzu r0,-4(r8)
stwu r0,-4(r7)
bdnz 3b
/*
* Now flush the cache: note that we must start from a cache aligned
* address. Otherwise we might miss one cache line.
*/
4: cmpwi r6,0
add r5,r3,r5
beq 7f /* Always flush prefetch queue in any case */
subi r0,r6,1
andc r3,r3,r0
mr r4,r3
5: dcbst 0,r4
add r4,r4,r6
cmplw r4,r5
blt 5b
sync /* Wait for all dcbst to complete on bus */
mr r4,r3
6: icbi 0,r4
add r4,r4,r6
cmplw r4,r5
blt 6b
7: sync /* Wait for all icbi to complete on bus */
isync
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
mtlr r0
blr
in_ram:
/*
* Relocation Function, r14 point to got2+0x8000
*
* Adjust got2 pointers, no need to check for 0, this code
* already puts a few entries in the table.
*/
li r0,__got2_entries@sectoff@l
la r3,GOT(_GOT2_TABLE_)
lwz r11,GOT(_GOT2_TABLE_)
mtctr r0
sub r11,r3,r11
addi r3,r3,-4
1: lwzu r0,4(r3)
add r0,r0,r11
stw r0,0(r3)
bdnz 1b
/*
* Now adjust the fixups and the pointers to the fixups
* in case we need to move ourselves again.
*/
2: li r0,__fixup_entries@sectoff@l
lwz r3,GOT(_FIXUP_TABLE_)
cmpwi r0,0
mtctr r0
addi r3,r3,-4
beq 4f
3: lwzu r4,4(r3)
lwzux r0,r4,r11
add r0,r0,r11
stw r10,0(r3)
stw r0,0(r4)
bdnz 3b
4:
clear_bss:
/*
* Now clear BSS segment
*/
lwz r3,GOT(__bss_start)
lwz r4,GOT(_end)
cmplw 0, r3, r4
beq 6f
li r0, 0
5:
stw r0, 0(r3)
addi r3, r3, 4
cmplw 0, r3, r4
bne 5b
6:
mr r3, r9 /* Global Data pointer */
mr r4, r10 /* Destination Address */
bl board_init_r
/*
* Copy exception vector code to low memory
*
* r3: dest_addr
* r7: source address, r8: end address, r9: target address
*/
.globl trap_init
trap_init:
lwz r7, GOT(_start)
lwz r8, GOT(_end_of_vectors)
li r9, 0x100 /* reset vector at 0x100 */
cmplw 0, r7, r8
bgelr /* return if r7>=r8 - just in case */
mflr r4 /* save link register */
1:
lwz r0, 0(r7)
stw r0, 0(r9)
addi r7, r7, 4
addi r9, r9, 4
cmplw 0, r7, r8
bne 1b
/*
* relocate `hdlr' and `int_return' entries
*/
li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
li r8, Alignment - _start + EXC_OFF_SYS_RESET
2:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 2b
li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
bl trap_reloc
li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
bl trap_reloc
li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
li r8, SystemCall - _start + EXC_OFF_SYS_RESET
3:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 3b
li r7, .L_Trace - _start + EXC_OFF_SYS_RESET
li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
4:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 4b
mfmsr r3 /* now that the vectors have */
lis r7, MSR_IP@h /* relocated into low memory */
ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
andc r3, r3, r7 /* (if it was on) */
SYNC /* Some chip revs need this... */
mtmsr r3
SYNC
mtlr r4 /* restore link register */
blr
/*
* Function: relocate entries for one exception vector
*/
trap_reloc:
lwz r0, 0(r7) /* hdlr ... */
add r0, r0, r3 /* ... += dest_addr */
stw r0, 0(r7)
lwz r0, 4(r7) /* int_return ... */
add r0, r0, r3 /* ... += dest_addr */
stw r0, 4(r7)
blr

205
cpu/mpc512x/traps.c Normal file
View File

@@ -0,0 +1,205 @@
/*
* (C) Copyright 2000 - 2007
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* 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
*
* Derived from the MPC83xx code.
*/
/*
* This file handles the architecture-dependent parts of hardware
* exceptions
*/
#include <common.h>
#include <asm/processor.h>
DECLARE_GLOBAL_DATA_PTR;
extern unsigned long search_exception_table(unsigned long);
#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
/*
* Trap & Exception support
*/
void
print_backtrace (unsigned long *sp)
{
int cnt = 0;
unsigned long i;
puts ("Call backtrace: ");
while (sp) {
if ((uint)sp > END_OF_MEM)
break;
i = sp[1];
if (cnt++ % 7 == 0)
putc ('\n');
printf ("%08lX ", i);
if (cnt > 32) break;
sp = (unsigned long *) *sp;
}
putc ('\n');
}
void show_regs (struct pt_regs * regs)
{
int i;
printf ("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
printf ("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0,
regs->msr & MSR_IR ? 1 : 0,
regs->msr & MSR_DR ? 1 : 0);
putc ('\n');
for (i = 0; i < 32; i++) {
if ((i % 8) == 0) {
printf ("GPR%02d: ", i);
}
printf ("%08lX ", regs->gpr[i]);
if ((i % 8) == 7) {
putc ('\n');
}
}
}
void
_exception (int signr, struct pt_regs *regs)
{
show_regs (regs);
print_backtrace ((unsigned long *)regs->gpr[1]);
panic ("Exception at pc %lx signal %d", regs->nip,signr);
}
void
MachineCheckException (struct pt_regs *regs)
{
unsigned long fixup;
if ((fixup = search_exception_table (regs->nip)) != 0) {
regs->nip = fixup;
return;
}
#ifdef CONFIG_CMD_KGDB
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
puts ("Machine check.\nCaused by (from msr): ");
printf ("regs %p ",regs);
switch (regs->msr & 0x00FF0000) {
case (0x80000000 >> 10):
puts ("Instruction cache parity signal\n");
break;
case (0x80000000 >> 11):
puts ("Data cache parity signal\n");
break;
case (0x80000000 >> 12):
puts ("Machine check signal\n");
break;
case (0x80000000 >> 13):
puts ("Transfer error ack signal\n");
break;
case (0x80000000 >> 14):
puts ("Data parity signal\n");
break;
case (0x80000000 >> 15):
puts ("Address parity signal\n");
break;
default:
puts ("Unknown values in msr\n");
}
show_regs (regs);
print_backtrace ((unsigned long *)regs->gpr[1]);
panic ("machine check");
}
void
AlignmentException (struct pt_regs *regs)
{
#ifdef CONFIG_CMD_KGDB
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs (regs);
print_backtrace ((unsigned long *)regs->gpr[1]);
panic ("Alignment Exception");
}
void
ProgramCheckException (struct pt_regs *regs)
{
#ifdef CONFIG_CMD_KGDB
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs (regs);
print_backtrace ((unsigned long *)regs->gpr[1]);
panic ("Program Check Exception");
}
void
SoftEmuException (struct pt_regs *regs)
{
#ifdef CONFIG_CMD_KGDB
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs (regs);
print_backtrace ((unsigned long *)regs->gpr[1]);
panic ("Software Emulation Exception");
}
void
UnknownException (struct pt_regs *regs)
{
#ifdef CONFIG_CMD_KGDB
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
printf ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
regs->nip, regs->msr, regs->trap);
_exception (0, regs);
}
#ifdef CONFIG_CMD_BEDBUG
extern void do_bedbug_breakpoint (struct pt_regs *);
#endif
void
DebugException (struct pt_regs *regs)
{
printf ("Debugger trap at @ %lx\n", regs->nip );
show_regs (regs);
#ifdef CONFIG_CMD_BEDBUG
do_bedbug_breakpoint (regs);
#endif
}

View File

@@ -28,6 +28,9 @@
#
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
PLATFORM_CPPFLAGS += -DCONFIG_5xx -ffixed-r2 -ffixed-r29 -mpowerpc -msoft-float
# Use default linker script. Board port can override in board/*/config.mk
LDSCRIPT := $(SRCTREE)/cpu/mpc5xx/u-boot.lds

View File

@@ -178,7 +178,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
return;
}
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
#if defined(CONFIG_CMD_IRQ)
/*******************************************************************************
*
* irqinfo - print information about IRQs
@@ -204,4 +204,4 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
}
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
#endif

View File

@@ -155,7 +155,7 @@ in_flash:
/* Initialize some SPRs that are hard to access from C */
/*----------------------------------------------------------------------*/
lis r3, CFG_IMMR@h /* Pass IMMR as arg1 to C routine */
lis r3, CFG_IMMR@h /* Pass IMMR as arg1 to C routine */
lis r2, CFG_INIT_SP_ADDR@h
ori r1, r2, CFG_INIT_SP_ADDR@l /* Set up the stack in internal SRAM */
/* Note: R0 is still 0 here */
@@ -210,7 +210,7 @@ _start_of_vectors:
/* Alignment exception. */
. = 0x600
Alignment:
EXCEPTION_PROLOG
EXCEPTION_PROLOG(SRR0, SRR1)
mfspr r4,DAR
stw r4,_DAR(r21)
mfspr r5,DSISR
@@ -228,7 +228,7 @@ Alignment:
/* Program check exception */
. = 0x700
ProgramCheck:
EXCEPTION_PROLOG
EXCEPTION_PROLOG(SRR0, SRR1)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */

View File

@@ -36,11 +36,11 @@
#include <command.h>
#include <asm/processor.h>
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
#if defined(CONFIG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
@@ -131,7 +131,7 @@ void MachineCheckException(struct pt_regs *regs)
return;
}
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -165,7 +165,7 @@ void MachineCheckException(struct pt_regs *regs)
*/
void AlignmentException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -179,7 +179,7 @@ void AlignmentException(struct pt_regs *regs)
*/
void ProgramCheckException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -193,7 +193,7 @@ void ProgramCheckException(struct pt_regs *regs)
*/
void SoftEmuException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -208,7 +208,7 @@ void SoftEmuException(struct pt_regs *regs)
*/
void UnknownException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
@@ -224,7 +224,7 @@ void DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
#if defined(CONFIG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}

Some files were not shown because too many files have changed in this diff Show More