* Add support for MIPS32 4Kc CPUs

* Add support for INCA-IP Board
This commit is contained in:
wdenk
2003-03-27 12:09:35 +00:00
parent ac6dbb85b7
commit c021880ac5
25 changed files with 5874 additions and 3 deletions

44
cpu/mips/Makefile Normal file
View File

@@ -0,0 +1,44 @@
#
# (C) Copyright 2003
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = lib$(CPU).a
START = start.o
OBJS = interrupts.o cpu.o incaip_clock.o serial.o
SOBJS = incaip_wdt.o cache.o
all: .depend $(START) $(LIB)
$(LIB): $(OBJS) $(SOBJS)
$(AR) crv $@ $(OBJS) $(SOBJS)
#########################################################################
.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
sinclude .depend
#########################################################################

265
cpu/mips/cache.S Normal file
View File

@@ -0,0 +1,265 @@
/*
* Cache-handling routined for MIPS 4K CPUs
*
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
#include <version.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>
/* 16KB is the maximum size of instruction and data caches on
* MIPS 4K.
*/
#define MIPS_MAX_CACHE_SIZE 0x4000
/*
* cacheop macro to automate cache operations
* first some helpers...
*/
#define _mincache(size, maxsize) \
bltu size,maxsize,9f ; \
move size,maxsize ; \
9:
#define _align(minaddr, maxaddr, linesize) \
.set noat ; \
subu AT,linesize,1 ; \
not AT ; \
and minaddr,AT ; \
addu maxaddr,-1 ; \
and maxaddr,AT ; \
.set at
/* general operations */
#define doop1(op1) \
cache op1,0(a0)
#define doop2(op1, op2) \
cache op1,0(a0) ; \
nop ; \
cache op2,0(a0)
/* specials for cache initialisation */
#define doop1lw(op1) \
lw zero,0(a0)
#define doop1lw1(op1) \
cache op1,0(a0) ; \
lw zero,0(a0) ; \
cache op1,0(a0)
#define doop121(op1,op2) \
cache op1,0(a0) ; \
nop; \
cache op2,0(a0) ; \
nop; \
cache op1,0(a0)
#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
.set noreorder ; \
10: doop##tag##ops ; \
bne minaddr,maxaddr,10b ; \
add minaddr,linesize ; \
.set reorder
/* finally the cache operation macros */
#define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
blez n,11f ; \
addu n,kva ; \
_align(kva, n, cacheLineSize) ; \
_oploopn(kva, n, cacheLineSize, tag, ops) ; \
11:
#define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
_mincache(n, cacheSize); \
blez n,11f ; \
addu n,kva ; \
_align(kva, n, cacheLineSize) ; \
_oploopn(kva, n, cacheLineSize, tag, ops) ; \
11:
#define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
/*******************************************************************************
*
* mips_cache_reset - low level initialisation of the primary caches
*
* This routine initialises the primary caches to ensure that they
* have good parity. It must be called by the ROM before any cached locations
* are used to prevent the possibility of data with bad parity being written to
* memory.
* To initialise the instruction cache it is essential that a source of data
* with good parity is available. This routine
* will initialise an area of memory starting at location zero to be used as
* a source of parity.
*
* RETURNS: N/A
*
*/
.globl mips_cache_reset
.ent mips_cache_reset
mips_cache_reset:
li t2, CFG_ICACHE_SIZE
li t3, CFG_DCACHE_SIZE
li t4, CFG_CACHELINE_SIZE
move t5, t4
li v0, MIPS_MAX_CACHE_SIZE
/* Now clear that much memory starting from zero.
*/
li a0, KSEG1
addu a1, a0, v0
2: sw zero, 0(a0)
sw zero, 4(a0)
sw zero, 8(a0)
sw zero, 12(a0)
sw zero, 16(a0)
sw zero, 20(a0)
sw zero, 24(a0)
sw zero, 28(a0)
addu a0, 32
bltu a0, a1, 2b
/* Set invalid tag.
*/
mtc0 zero, CP0_TAGLO
/*
* The caches are probably in an indeterminate state,
* so we force good parity into them by doing an
* invalidate, load/fill, invalidate for each line.
*/
/* Assume bottom of RAM will generate good parity for the cache.
*/
li a0, K0BASE
move a2, t2 # icacheSize
move a3, t4 # icacheLineSize
move a1, a2
icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
/* To support Orion/R4600, we initialise the data cache in 3 passes.
*/
/* 1: initialise dcache tags.
*/
li a0, K0BASE
move a2, t3 # dcacheSize
move a3, t5 # dcacheLineSize
move a1, a2
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
/* 2: fill dcache.
*/
li a0, K0BASE
move a2, t3 # dcacheSize
move a3, t5 # dcacheLineSize
move a1, a2
icacheopn(a0,a1,a2,a3,1lw,(dummy))
/* 3: clear dcache tags.
*/
li a0, K0BASE
move a2, t3 # dcacheSize
move a3, t5 # dcacheLineSize
move a1, a2
icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
j ra
.end mips_cache_reset
/*******************************************************************************
*
* dcache_status - get cache status
*
* RETURNS: 0 - cache disabled; 1 - cache enabled
*
*/
.globl dcache_status
.ent dcache_status
dcache_status:
mfc0 v0, CP0_CONFIG
andi v0, v0, 1
j ra
.end dcache_status
/*******************************************************************************
*
* dcache_disable - disable cache
*
* RETURNS: N/A
*
*/
.globl dcache_disable
.ent dcache_disable
dcache_disable:
mfc0 t0, CP0_CONFIG
li t1, -8
and t0, t0, t1
ori t0, t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
j ra
.end dcache_disable
/*******************************************************************************
*
* mips_cache_lock - lock RAM area pointed to by a0 in cache.
*
* RETURNS: N/A
*
*/
.globl mips_cache_lock
.ent mips_cache_lock
mips_cache_lock:
li a1, K0BASE - CFG_DCACHE_SIZE
addu a0, a1
li a2, CFG_DCACHE_SIZE
li a3, CFG_CACHELINE_SIZE
move a1, a2
icacheop(a0,a1,a2,a3,0x1d)
j ra
.end mips_cache_lock

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

@@ -0,0 +1,25 @@
#
# (C) Copyright 2003
# 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_CPPFLAGS += -mcpu=4kc -EB -mabicalls

41
cpu/mips/cpu.c Normal file
View File

@@ -0,0 +1,41 @@
/*
* (C) Copyright 2003
* 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 <asm/inca-ip.h>
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
#ifdef CONFIG_INCA_IP
*INCA_IP_WDT_RST_REQ = 0x3f;
#endif
fprintf(stderr, "*** reset failed ***\n");
return 0;
}
void flush_cache (ulong start_addr, ulong size)
{
}

107
cpu/mips/incaip_clock.c Normal file
View File

@@ -0,0 +1,107 @@
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/inca-ip.h>
/*******************************************************************************
*
* get_cpuclk - returns the frequency of the CPU.
*
* Gets the value directly from the INCA-IP hardware.
*
* RETURNS:
* 150.000.000 for 150 MHz
* 130.000.000. for 130 Mhz
* 100.000.000. for 100 Mhz
* NOTE:
* This functions should be used by the hardware driver to get the correct
* frequency of the CPU. Don't use the macros, which are set to init the CPU
* frequency in the ROM code.
*/
uint incaip_get_cpuclk(void)
{
/*-------------------------------------------------------------------------*/
/* CPU Clock Input Multiplexer (MUX I) */
/* Multiplexer MUX I selects the maximum input clock to the CPU. */
/*-------------------------------------------------------------------------*/
if (*((volatile ulong*)INCA_IP_CGU_CGU_MUXCR) & INCA_IP_CGU_CGU_MUXCR_MUXI)
{
/* MUX I set to 150 MHz clock */
return 150000000;
}
else
{
/* MUX I set to 100/133 MHz clock */
if (*((volatile ulong*)INCA_IP_CGU_CGU_DIVCR) & 0x40)
{
/* Division value is 1/3, maximum CPU operating */
/* frequency is 133.3 MHz */
return 130000000;
}
else
{
/* Division value is 1/4, maximum CPU operating */
/* frequency is 100 MHz */
return 100000000;
}
}
}
/*******************************************************************************
*
* get_fpiclk - returns the frequency of the FPI bus.
*
* Gets the value directly from the INCA-IP hardware.
*
* RETURNS: Frquency in Hz
*
* NOTE:
* This functions should be used by the hardware driver to get the correct
* frequency of the CPU. Don't use the macros, which are set to init the CPU
* frequency in the ROM code.
* The calculation for the
*/
uint incaip_get_fpiclk(void)
{
uint clkCPU;
clkCPU = incaip_get_cpuclk();
switch (*((volatile ulong*)INCA_IP_CGU_CGU_DIVCR) & 0xC)
{
case 0x4:
return clkCPU >> 1; /* devided by 2 */
break;
case 0x8:
return clkCPU >> 2; /* devided by 4 */
break;
default:
return clkCPU;
break;
}
}

73
cpu/mips/incaip_wdt.S Normal file
View File

@@ -0,0 +1,73 @@
/*
* INCA-IP Watchdog timer management code.
*
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
#include <version.h>
#include <asm/regdef.h>
#define WD_BASE 0xb8000000
#define WD_CON0(value) 0x0020(value)
#define WD_CON1(value) 0x0024(value)
#define WD_DISABLE 0x00000008
#define WD_ENABLE 0x00000000
#define WD_WRITE_PW 0xFFFC00F8
#define WD_WRITE_ENDINIT 0xFFFC00F3
#define WD_WRITE_INIT 0xFFFC00F2
.globl disable_incaip_wdt
disable_incaip_wdt:
li t0, WD_BASE
/* Calculate password.
*/
lw t2, WD_CON1(t0)
and t2, 0xC
lw t3, WD_CON0(t0)
and t3, 0xFFFFFF01
or t3, t2
or t3, 0xF0
sw t3, WD_CON0(t0) /* write password */
/* Clear ENDINIT.
*/
li t1, WD_WRITE_INIT
sw t1, WD_CON0(t0)
li t1, WD_DISABLE
sw t1, WD_CON1(t0) /* disable watchdog */
li t1, WD_WRITE_PW
sw t1, WD_CON0(t0) /* write password */
li t1, WD_WRITE_ENDINIT
sw t1, WD_CON0(t0) /* end command */
j ra
nop

34
cpu/mips/interrupts.c Normal file
View File

@@ -0,0 +1,34 @@
/*
* (C) Copyright 2003
* 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>
void enable_interrupts(void)
{
}
int disable_interrupts(void)
{
return 0;
}

282
cpu/mips/serial.c Normal file
View File

@@ -0,0 +1,282 @@
/*
* (INCA) ASC UART support
*/
#include <common.h>
#include <asm/inca-ip.h>
#include "serial.h"
#define SET_BIT(reg, mask) reg |= (mask)
#define CLEAR_BIT(reg, mask) reg &= (~mask)
#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
#define SET_BITS(reg, mask) SET_BIT(reg, mask)
#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
extern uint incaip_get_fpiclk(void);
static int serial_setopt (void);
/* pointer to ASC register base address */
static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
/******************************************************************************
*
* serial_init - initialize a INCAASC channel
*
* This routine initializes the number of data bits, parity
* and set the selected baud rate. Interrupts are disabled.
* Set the modem control signals if the option is selected.
*
* RETURNS: N/A
*/
int serial_init (void)
{
/* we have to set PMU.EN13 bit to enable an ASC device*/
INCAASC_PMU_ENABLE(13);
/* and we have to set CLC register*/
CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
/* initialy we are in async mode */
pAsc->asc_con = ASCCON_M_8ASYNC;
/* select input port */
pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
/* TXFIFO's filling level */
SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
/* enable TXFIFO */
SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
/* RXFIFO's filling level */
SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
/* enable RXFIFO */
SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
/* enable error signals */
SET_BIT(pAsc->asc_con, ASCCON_FEN);
SET_BIT(pAsc->asc_con, ASCCON_OEN);
/* acknowledge ASC interrupts */
ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
/* disable ASC interrupts */
ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
/* set FIFOs into the transparent mode */
SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
/* set baud rate */
serial_setbrg();
/* set the options */
serial_setopt();
return 0;
}
void serial_setbrg (void)
{
ulong uiReloadValue, fdv;
ulong f_ASC;
f_ASC = incaip_get_fpiclk();
#ifndef INCAASC_USE_FDV
fdv = 2;
uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
#else
fdv = INCAASC_FDV_HIGH_BAUDRATE;
uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
#endif /* INCAASC_USE_FDV */
if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
{
#ifndef INCAASC_USE_FDV
fdv = 3;
uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
#else
fdv = INCAASC_FDV_LOW_BAUDRATE;
uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
#endif /* INCAASC_USE_FDV */
if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
{
return; /* can't impossibly generate that baud rate */
}
}
/* Disable Baud Rate Generator; BG should only be written when R=0 */
CLEAR_BIT(pAsc->asc_con, ASCCON_R);
#ifndef INCAASC_USE_FDV
/*
* Disable Fractional Divider (FDE)
* Divide clock by reload-value + constant (BRS)
*/
/* FDE = 0 */
CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
if ( fdv == 2 )
CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
else
SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
#else /* INCAASC_USE_FDV */
/* Enable Fractional Divider */
SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
/* Set fractional divider value */
pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
#endif /* INCAASC_USE_FDV */
/* Set reload value in BG */
pAsc->asc_bg = uiReloadValue;
/* Enable Baud Rate Generator */
SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
}
/*******************************************************************************
*
* serial_setopt - set the serial options
*
* Set the channel operating mode to that specified. Following options
* are supported: CREAD, CSIZE, PARENB, and PARODD.
*
* Note, this routine disables the transmitter. The calling routine
* may have to re-enable it.
*
* RETURNS:
* Returns 0 to indicate success, otherwise -1 is returned
*/
static int serial_setopt (void)
{
ulong con;
switch ( ASC_OPTIONS & ASCOPT_CSIZE )
{
/* 7-bit-data */
case ASCOPT_CS7:
con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
break;
/* 8-bit-data */
case ASCOPT_CS8:
if ( ASC_OPTIONS & ASCOPT_PARENB )
con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
else
con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
break;
/*
* only 7 and 8-bit frames are supported
* if we don't use IOCTL extensions
*/
default:
return -1;
}
if ( ASC_OPTIONS & ASCOPT_STOPB )
SET_BIT(con, ASCCON_STP); /* 2 stop bits */
else
CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
if ( ASC_OPTIONS & ASCOPT_PARENB )
SET_BIT(con, ASCCON_PEN); /* enable parity checking */
else
CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
if ( ASC_OPTIONS & ASCOPT_PARODD )
SET_BIT(con, ASCCON_ODD); /* odd parity */
else
CLEAR_BIT(con, ASCCON_ODD); /* even parity */
if ( ASC_OPTIONS & ASCOPT_CREAD )
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
pAsc->asc_con |= con;
return 0;
}
void serial_putc (const char c)
{
uint txFl = 0;
if (c == '\n') serial_putc ('\r');
/* check do we have a free space in the TX FIFO */
/* get current filling level */
do
{
txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
}
while ( txFl == INCAASC_TXFIFO_FULL );
pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
/* check for errors */
if ( pAsc->asc_con & ASCCON_OE )
{
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
return;
}
}
void serial_puts (const char *s)
{
while (*s)
{
serial_putc (*s++);
}
}
int serial_getc (void)
{
ulong symbol_mask;
char c;
while (!serial_tstc());
symbol_mask =
((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
c = (char)(pAsc->asc_rbuf & symbol_mask);
return c;
}
int serial_tstc (void)
{
int res = 1;
if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
{
res = 0;
}
else if ( pAsc->asc_con & ASCCON_FE )
{
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
res = 0;
}
else if ( pAsc->asc_con & ASCCON_PE )
{
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
res = 0;
}
else if ( pAsc->asc_con & ASCCON_OE )
{
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
res = 0;
}
return res;
}

178
cpu/mips/serial.h Normal file
View File

@@ -0,0 +1,178 @@
/* incaAscSio.h - (INCA) ASC UART tty driver header */
#ifndef __INCincaAscSioh
#define __INCincaAscSioh
#include <asm/inca-ip.h>
/* channel operating modes */
#define ASCOPT_CSIZE 0x00000003
#define ASCOPT_CS7 0x00000001
#define ASCOPT_CS8 0x00000002
#define ASCOPT_PARENB 0x00000004
#define ASCOPT_STOPB 0x00000008
#define ASCOPT_PARODD 0x00000010
#define ASCOPT_CREAD 0x00000020
#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
/* ASC input select (0 or 1) */
#define CONSOLE_TTY 0
/* use fractional divider for baudrate settings */
#define INCAASC_USE_FDV
#ifdef INCAASC_USE_FDV
#define INCAASC_FDV_LOW_BAUDRATE 71
#define INCAASC_FDV_HIGH_BAUDRATE 453
#endif /*INCAASC_USE_FDV*/
#define INCAASC_TXFIFO_FL 1
#define INCAASC_RXFIFO_FL 1
#define INCAASC_TXFIFO_FULL 16
/* interrupt lines masks for the ASC device interrupts*/
/* change these macroses if it's necessary */
#define INCAASC_IRQ_LINE_ALL 0x000F0000 /* all IRQs */
#define INCAASC_IRQ_LINE_TIR 0x00010000 /* TIR - Tx */
#define INCAASC_IRQ_LINE_RIR 0x00020000 /* RIR - Rx */
#define INCAASC_IRQ_LINE_EIR 0x00040000 /* EIR - Err */
#define INCAASC_IRQ_LINE_TBIR 0x00080000 /* TBIR - Tx Buf*/
/* interrupt controller access macros */
#define ASC_INTERRUPTS_ENABLE(X) \
*((volatile unsigned int*) INCA_IP_ICU_IM2_IER) |= X;
#define ASC_INTERRUPTS_DISABLE(X) \
*((volatile unsigned int*) INCA_IP_ICU_IM2_IER) &= ~X;
#define ASC_INTERRUPTS_CLEAR(X) \
*((volatile unsigned int*) INCA_IP_ICU_IM2_ISR) = X;
/* CLC register's bits and bitfields */
#define ASCCLC_DISR 0x00000001
#define ASCCLC_DISS 0x00000002
#define ASCCLC_RMCMASK 0x0000FF00
#define ASCCLC_RMCOFFSET 8
/* CON register's bits and bitfields */
#define ASCCON_MODEMASK 0x0007
#define ASCCON_M_8SYNC 0x0
#define ASCCON_M_8ASYNC 0x1
#define ASCCON_M_8IRDAASYNC 0x2
#define ASCCON_M_7ASYNCPAR 0x3
#define ASCCON_M_9ASYNC 0x4
#define ASCCON_M_8WAKEUPASYNC 0x5
#define ASCCON_M_8ASYNCPAR 0x7
#define ASCCON_STP 0x0008
#define ASCCON_REN 0x0010
#define ASCCON_PEN 0x0020
#define ASCCON_FEN 0x0040
#define ASCCON_OEN 0x0080
#define ASCCON_PE 0x0100
#define ASCCON_FE 0x0200
#define ASCCON_OE 0x0400
#define ASCCON_FDE 0x0800
#define ASCCON_ODD 0x1000
#define ASCCON_BRS 0x2000
#define ASCCON_LB 0x4000
#define ASCCON_R 0x8000
/* WHBCON register's bits and bitfields */
#define ASCWHBCON_CLRREN 0x0010
#define ASCWHBCON_SETREN 0x0020
#define ASCWHBCON_CLRPE 0x0100
#define ASCWHBCON_CLRFE 0x0200
#define ASCWHBCON_CLROE 0x0400
#define ASCWHBCON_SETPE 0x0800
#define ASCWHBCON_SETFE 0x1000
#define ASCWHBCON_SETOE 0x2000
/* ABCON register's bits and bitfields */
#define ASCABCON_ABEN 0x0001
#define ASCABCON_AUREN 0x0002
#define ASCABCON_ABSTEN 0x0004
#define ASCABCON_ABDETEN 0x0008
#define ASCABCON_FCDETEN 0x0010
#define ASCABCON_EMMASK 0x0300
#define ASCABCON_EMOFF 8
#define ASCABCON_EM_DISAB 0x0
#define ASCABCON_EM_DURAB 0x1
#define ASCABCON_EM_ALWAYS 0x2
#define ASCABCON_TXINV 0x0400
#define ASCABCON_RXINV 0x0800
/* FDV register mask, offset and bitfields*/
#define ASCFDV_VALUE_MASK 0x000001FF
/* WHBABCON register's bits and bitfields */
#define ASCWHBABCON_SETABEN 0x0001
#define ASCWHBABCON_CLRABEN 0x0002
/* ABSTAT register's bits and bitfields */
#define ASCABSTAT_FCSDET 0x0001
#define ASCABSTAT_FCCDET 0x0002
#define ASCABSTAT_SCSDET 0x0004
#define ASCABSTAT_SCCDET 0x0008
#define ASCABSTAT_DETWAIT 0x0010
/* WHBABSTAT register's bits and bitfields */
#define ASCWHBABSTAT_CLRFCSDET 0x0001
#define ASCWHBABSTAT_SETFCSDET 0x0002
#define ASCWHBABSTAT_CLRFCCDET 0x0004
#define ASCWHBABSTAT_SETFCCDET 0x0008
#define ASCWHBABSTAT_CLRSCSDET 0x0010
#define ASCWHBABSTAT_SETSCSDET 0x0020
#define ASCWHBABSTAT_SETSCCDET 0x0040
#define ASCWHBABSTAT_CLRSCCDET 0x0080
#define ASCWHBABSTAT_CLRDETWAIT 0x0100
#define ASCWHBABSTAT_SETDETWAIT 0x0200
/* TXFCON register's bits and bitfields */
#define ASCTXFCON_TXFEN 0x0001
#define ASCTXFCON_TXFFLU 0x0002
#define ASCTXFCON_TXTMEN 0x0004
#define ASCTXFCON_TXFITLMASK 0x3F00
#define ASCTXFCON_TXFITLOFF 8
/* RXFCON register's bits and bitfields */
#define ASCRXFCON_RXFEN 0x0001
#define ASCRXFCON_RXFFLU 0x0002
#define ASCRXFCON_RXTMEN 0x0004
#define ASCRXFCON_RXFITLMASK 0x3F00
#define ASCRXFCON_RXFITLOFF 8
/* FSTAT register's bits and bitfields */
#define ASCFSTAT_RXFFLMASK 0x003F
#define ASCFSTAT_TXFFLMASK 0x3F00
#define ASCFSTAT_TXFFLOFF 8
#define INCAASC_PMU_ENABLE(BIT) *((volatile ulong*)0xBF102000) |= (0x1 << BIT);
typedef struct /* incaAsc_t */
{
volatile unsigned long asc_clc; /*0x0000*/
volatile unsigned long asc_pisel; /*0x0004*/
volatile unsigned long asc_rsvd1[2]; /* for mapping */ /*0x0008*/
volatile unsigned long asc_con; /*0x0010*/
volatile unsigned long asc_bg; /*0x0014*/
volatile unsigned long asc_fdv; /*0x0018*/
volatile unsigned long asc_pmw; /* not used */ /*0x001C*/
volatile unsigned long asc_tbuf; /*0x0020*/
volatile unsigned long asc_rbuf; /*0x0024*/
volatile unsigned long asc_rsvd2[2]; /* for mapping */ /*0x0028*/
volatile unsigned long asc_abcon; /*0x0030*/
volatile unsigned long asc_abstat; /* not used */ /*0x0034*/
volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0038*/
volatile unsigned long asc_rxfcon; /*0x0040*/
volatile unsigned long asc_txfcon; /*0x0044*/
volatile unsigned long asc_fstat; /*0x0048*/
volatile unsigned long asc_rsvd4; /* for mapping */ /*0x004C*/
volatile unsigned long asc_whbcon; /*0x0050*/
volatile unsigned long asc_whbabcon; /*0x0054*/
volatile unsigned long asc_whbabstat; /* not used */ /*0x0058*/
} incaAsc_t;
#endif /* __INCincaAscSioh */

350
cpu/mips/start.S Normal file
View File

@@ -0,0 +1,350 @@
/*
* Startup Code for MIPS32 CPU-core
*
* Copyright (c) 2003 Wolfgang Denk <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 <config.h>
#include <version.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#define RVECENT(f,n) \
b f; nop
#define XVECENT(f,bev) \
b f ; \
li k0,bev
.set noreorder
.globl _start
.text
_start:
RVECENT(reset,0) /* U-boot entry point */
RVECENT(reset,1) /* software reboot */
#ifdef CONFIG_INCA_IP
.word 0x000020C4 /* EBU init code, fetched during booting */
.word 0x00000000 /* phase of the flash */
#else
RVECENT(romReserved,2)
#endif
RVECENT(romReserved,3)
RVECENT(romReserved,4)
RVECENT(romReserved,5)
RVECENT(romReserved,6)
RVECENT(romReserved,7)
RVECENT(romReserved,8)
RVECENT(romReserved,9)
RVECENT(romReserved,10)
RVECENT(romReserved,11)
RVECENT(romReserved,12)
RVECENT(romReserved,13)
RVECENT(romReserved,14)
RVECENT(romReserved,15)
RVECENT(romReserved,16)
RVECENT(romReserved,17)
RVECENT(romReserved,18)
RVECENT(romReserved,19)
RVECENT(romReserved,20)
RVECENT(romReserved,21)
RVECENT(romReserved,22)
RVECENT(romReserved,23)
RVECENT(romReserved,24)
RVECENT(romReserved,25)
RVECENT(romReserved,26)
RVECENT(romReserved,27)
RVECENT(romReserved,28)
RVECENT(romReserved,29)
RVECENT(romReserved,30)
RVECENT(romReserved,31)
RVECENT(romReserved,32)
RVECENT(romReserved,33)
RVECENT(romReserved,34)
RVECENT(romReserved,35)
RVECENT(romReserved,36)
RVECENT(romReserved,37)
RVECENT(romReserved,38)
RVECENT(romReserved,39)
RVECENT(romReserved,40)
RVECENT(romReserved,41)
RVECENT(romReserved,42)
RVECENT(romReserved,43)
RVECENT(romReserved,44)
RVECENT(romReserved,45)
RVECENT(romReserved,46)
RVECENT(romReserved,47)
RVECENT(romReserved,48)
RVECENT(romReserved,49)
RVECENT(romReserved,50)
RVECENT(romReserved,51)
RVECENT(romReserved,52)
RVECENT(romReserved,53)
RVECENT(romReserved,54)
RVECENT(romReserved,55)
RVECENT(romReserved,56)
RVECENT(romReserved,57)
RVECENT(romReserved,58)
RVECENT(romReserved,59)
RVECENT(romReserved,60)
RVECENT(romReserved,61)
RVECENT(romReserved,62)
RVECENT(romReserved,63)
XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
RVECENT(romReserved,65)
RVECENT(romReserved,66)
RVECENT(romReserved,67)
RVECENT(romReserved,68)
RVECENT(romReserved,69)
RVECENT(romReserved,70)
RVECENT(romReserved,71)
RVECENT(romReserved,72)
RVECENT(romReserved,73)
RVECENT(romReserved,74)
RVECENT(romReserved,75)
RVECENT(romReserved,76)
RVECENT(romReserved,77)
RVECENT(romReserved,78)
RVECENT(romReserved,79)
XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
RVECENT(romReserved,81)
RVECENT(romReserved,82)
RVECENT(romReserved,83)
RVECENT(romReserved,84)
RVECENT(romReserved,85)
RVECENT(romReserved,86)
RVECENT(romReserved,87)
RVECENT(romReserved,88)
RVECENT(romReserved,89)
RVECENT(romReserved,90)
RVECENT(romReserved,91)
RVECENT(romReserved,92)
RVECENT(romReserved,93)
RVECENT(romReserved,94)
RVECENT(romReserved,95)
XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
RVECENT(romReserved,97)
RVECENT(romReserved,98)
RVECENT(romReserved,99)
RVECENT(romReserved,100)
RVECENT(romReserved,101)
RVECENT(romReserved,102)
RVECENT(romReserved,103)
RVECENT(romReserved,104)
RVECENT(romReserved,105)
RVECENT(romReserved,106)
RVECENT(romReserved,107)
RVECENT(romReserved,108)
RVECENT(romReserved,109)
RVECENT(romReserved,110)
RVECENT(romReserved,111)
XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
RVECENT(romReserved,113)
RVECENT(romReserved,114)
RVECENT(romReserved,115)
RVECENT(romReserved,116)
RVECENT(romReserved,116)
RVECENT(romReserved,118)
RVECENT(romReserved,119)
RVECENT(romReserved,120)
RVECENT(romReserved,121)
RVECENT(romReserved,122)
RVECENT(romReserved,123)
RVECENT(romReserved,124)
RVECENT(romReserved,125)
RVECENT(romReserved,126)
RVECENT(romReserved,127)
/* We hope there are no more reserved vectors!
* 128 * 8 == 1024 == 0x400
* so this is address R_VEC+0x400 == 0xbfc00400
*/
.align 4
reset:
/* Clear watch registers.
*/
mtc0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
/* STATUS register */
mfc0 k0, CP0_STATUS
li k1, ~ST0_IE
and k0, k1
mtc0 k0, CP0_STATUS
/* CAUSE register */
mtc0 zero, CP0_CAUSE
/* Init Timer */
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
/* CONFIG0 register */
li t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
#ifdef CONFIG_INCA_IP
/* Disable INCA-IP Watchdog.
*/
bal disable_incaip_wdt
nop
#endif
/* Initialize any external memory.
*/
bal memsetup
nop
/* Initialize caches...
*/
bal mips_cache_reset
nop
/* ... and enable them.
*/
li t0, CONF_CM_CACHABLE_NONCOHERENT
mtc0 t0, CP0_CONFIG
/* Set up temporary stack.
*/
li a0, CFG_INIT_SP_OFFSET
bal mips_cache_lock
nop
li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
la sp, 0(t0)
/* Initialize GOT pointer.
*/
bal 1f
nop
.word _GLOBAL_OFFSET_TABLE_ - 1f + 4
1:
move gp, ra
lw t1, 0(ra)
add gp, t1
la t9, board_init_f
j t9
nop
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* a0 = addr_sp
* a1 = gd
* a2 = destination address
*/
.globl relocate_code
.ent relocate_code
relocate_code:
move sp, a0 /* Set new stack pointer */
/*
* Fix GOT pointer:
*
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
*/
move t6, gp
sub gp, CFG_MONITOR_BASE
add gp, a2 /* gp now adjusted */
sub t6, gp, t6 /* t6 <-- relocation offset */
li t0, CFG_MONITOR_BASE
add t2, t0, CFG_MONITOR_LEN
move t1, a2
/*
* t0 = source address
* t1 = target address
* t2 = source end address
*/
1:
lw t3, 0(t0)
sw t3, 0(t1)
addu t0, 4
ble t0, t2, 1b
addu t1, 4 /* delay slot */
/* If caches were enabled, we would have to flush them here.
*/
/* Jump to where we've relocated ourselves.
*/
addi t0, a2, in_ram - _start
j t0
nop
.word uboot_end_data
.word uboot_end
.word num_got_entries
in_ram:
/* Now we want to update GOT.
*/
lw t3, -4(t0) /* t3 <-- num_got_entries */
addi t4, gp, 8 /* Skipping first two entries. */
li t2, 2
1:
lw t1, 0(t4)
beqz t1, 2f
add t1, t6
sw t1, 0(t4)
2:
addi t2, 1
blt t2, t3, 1b
addi t4, 4 /* delay slot */
/* Clear BSS.
*/
lw t1, -12(t0) /* t1 <-- uboot_end_data */
lw t2, -8(t0) /* t2 <-- uboot_end */
add t1, t6 /* adjust pointers */
add t2, t6
sub t1, 4
1: addi t1, 4
bltl t1, t2, 1b
sw zero, 0(t1) /* delay slot */
move a0, a1
la t9, board_init_r
j t9
move a1, a2 /* delay slot */
.end relocate_code
/* Exception handlers.
*/
romReserved:
b romReserved
romExcHandle:
b romExcHandle