Merge git://www.denx.de/git/u-boot
Conflicts: CREDITS
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,))
|
||||
|
||||
50
cpu/arm720t/lpc2292/Makefile
Normal file
50
cpu/arm720t/lpc2292/Makefile
Normal 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
249
cpu/arm720t/lpc2292/flash.c
Normal 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;
|
||||
}
|
||||
7
cpu/arm720t/lpc2292/iap_entry.S
Normal file
7
cpu/arm720t/lpc2292/iap_entry.S
Normal 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
157
cpu/arm720t/lpc2292/mmc.c
Normal 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 */
|
||||
233
cpu/arm720t/lpc2292/mmc_hw.c
Normal file
233
cpu/arm720t/lpc2292/mmc_hw.c
Normal 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);
|
||||
}
|
||||
29
cpu/arm720t/lpc2292/mmc_hw.h
Normal file
29
cpu/arm720t/lpc2292/mmc_hw.h
Normal 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
40
cpu/arm720t/lpc2292/spi.c
Normal 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;
|
||||
}
|
||||
@@ -129,8 +129,6 @@ serial_puts (const char *s)
|
||||
|
||||
void serial_setbrg (void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
unsigned short divisor = 0;
|
||||
|
||||
switch (gd->baudrate) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
151
cpu/arm920t/at91rm9200/spi.c
Normal file
151
cpu/arm920t/at91rm9200/spi.c
Normal 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
|
||||
53
cpu/arm920t/at91rm9200/usb.c
Normal file
53
cpu/arm920t/at91rm9200/usb.c
Normal 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
@@ -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;
|
||||
}
|
||||
@@ -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
72
cpu/arm920t/s3c24x0/usb.c
Normal 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) */
|
||||
@@ -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 */
|
||||
|
||||
49
cpu/arm926ejs/davinci/Makefile
Normal file
49
cpu/arm926ejs/davinci/Makefile
Normal 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
|
||||
|
||||
#########################################################################
|
||||
156
cpu/arm926ejs/davinci/dp83848.c
Normal file
156
cpu/arm926ejs/davinci/dp83848.c
Normal 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 */
|
||||
650
cpu/arm926ejs/davinci/ether.c
Normal file
650
cpu/arm926ejs/davinci/ether.c
Normal 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
351
cpu/arm926ejs/davinci/i2c.c
Normal 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 */
|
||||
707
cpu/arm926ejs/davinci/lowlevel_init.S
Normal file
707
cpu/arm926ejs/davinci/lowlevel_init.S
Normal 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
|
||||
142
cpu/arm926ejs/davinci/lxt972.c
Normal file
142
cpu/arm926ejs/davinci/lxt972.c
Normal 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 */
|
||||
389
cpu/arm926ejs/davinci/nand.c
Normal file
389
cpu/arm926ejs/davinci/nand.c
Normal 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 */
|
||||
77
cpu/arm926ejs/davinci/reset.S
Normal file
77
cpu/arm926ejs/davinci/reset.S
Normal 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
|
||||
165
cpu/arm926ejs/davinci/timer.c
Normal file
165
cpu/arm926ejs/davinci/timer.c
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -76,7 +76,6 @@ void calc_baud(void)
|
||||
void serial_setbrg(void)
|
||||
{
|
||||
int i;
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
calc_baud();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
48
cpu/mcf523x/Makefile
Normal 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
27
cpu/mcf523x/config.mk
Normal 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
109
cpu/mcf523x/cpu.c
Normal 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
145
cpu/mcf523x/cpu_init.c
Normal 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
49
cpu/mcf523x/interrupts.c
Normal 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
|
||||
@@ -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
340
cpu/mcf523x/start.S
Normal 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"
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
48
cpu/mcf532x/Makefile
Normal 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
27
cpu/mcf532x/config.mk
Normal 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
119
cpu/mcf532x/cpu.c
Normal 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
141
cpu/mcf532x/cpu_init.c
Normal 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
49
cpu/mcf532x/interrupts.c
Normal 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
216
cpu/mcf532x/speed.c
Normal 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
335
cpu/mcf532x/start.S
Normal 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
48
cpu/mcf5445x/Makefile
Normal 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
27
cpu/mcf5445x/config.mk
Normal 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
97
cpu/mcf5445x/cpu.c
Normal 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
140
cpu/mcf5445x/cpu_init.c
Normal 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
52
cpu/mcf5445x/interrupts.c
Normal 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
189
cpu/mcf5445x/pci.c
Normal 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
186
cpu/mcf5445x/speed.c
Normal 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
388
cpu/mcf5445x/start.S
Normal 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"
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
46
cpu/mpc512x/Makefile
Normal 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
25
cpu/mpc512x/config.mk
Normal 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
127
cpu/mpc512x/cpu.c
Normal 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
87
cpu/mpc512x/cpu_init.c
Normal 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
809
cpu/mpc512x/fec.c
Normal 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
227
cpu/mpc512x/fec.h
Normal 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
431
cpu/mpc512x/i2c.c
Normal 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 (®s->msr);
|
||||
|
||||
while (timeout-- && (status & I2C_BB)) {
|
||||
volatile int temp;
|
||||
mpc_reg_out (®s->mcr, I2C_STA, I2C_STA);
|
||||
temp = mpc_reg_in (®s->mdr);
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
mpc_reg_out (®s->mcr, 0, 0);
|
||||
mpc_reg_out (®s->mcr, I2C_EN, 0);
|
||||
|
||||
udelay (1000);
|
||||
status = mpc_reg_in (®s->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 (®s->msr);
|
||||
|
||||
while (timeout-- && !(*status & I2C_IF)) {
|
||||
udelay (1000);
|
||||
*status = mpc_reg_in (®s->msr);
|
||||
}
|
||||
|
||||
if (!(*status & I2C_IF)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->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 (®s->mcr, I2C_TX, I2C_TX);
|
||||
mpc_reg_out (®s->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 (®s->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 (®s->mcr, 0, I2C_TX);
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
buf[rdcount] = mpc_reg_in (®s->mdr);
|
||||
|
||||
if (dummy) {
|
||||
dummy = 0;
|
||||
} else {
|
||||
rdcount++;
|
||||
}
|
||||
|
||||
if (wait_for_pin (&status)) {
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, I2C_TXAK, I2C_TXAK);
|
||||
buf[rdcount++] = mpc_reg_in (®s->mdr);
|
||||
|
||||
if (wait_for_pin (&status)) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->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 (®s->mcr, 0, 0);
|
||||
|
||||
/* Set clock */
|
||||
mpc_reg_out (®s->mfdr, mpc_get_fdr (speed), 0);
|
||||
mpc_reg_out (®s->madr, saddr << 1, 0);
|
||||
|
||||
/* Enable module */
|
||||
mpc_reg_out (®s->mcr, I2C_EN, I2C_INIT_MASK);
|
||||
mpc_reg_out (®s->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 (®s->mcr, I2C_STA, I2C_STA);
|
||||
|
||||
if (! do_address (chip, 0)) {
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
udelay (500);
|
||||
break;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->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 (®s->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 (®s->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 (®s->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 (®s->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 (®s->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
61
cpu/mpc512x/interrupts.c
Normal 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
197
cpu/mpc512x/serial.c
Normal 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
135
cpu/mpc512x/speed.c
Normal 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
780
cpu/mpc512x/start.S
Normal 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
205
cpu/mpc512x/traps.c
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user