diff options
Diffstat (limited to 'cpu/mips')
-rw-r--r-- | cpu/mips/Makefile | 3 | ||||
-rw-r--r-- | cpu/mips/asc_serial.c (renamed from cpu/mips/serial.c) | 5 | ||||
-rw-r--r-- | cpu/mips/asc_serial.h (renamed from cpu/mips/serial.h) | 0 | ||||
-rw-r--r-- | cpu/mips/au1x00_eth.c | 216 | ||||
-rw-r--r-- | cpu/mips/au1x00_serial.c | 123 | ||||
-rw-r--r-- | cpu/mips/cache.S | 6 | ||||
-rw-r--r-- | cpu/mips/cpu.c | 10 |
7 files changed, 358 insertions, 5 deletions
diff --git a/cpu/mips/Makefile b/cpu/mips/Makefile index 91008bf..1182266 100644 --- a/cpu/mips/Makefile +++ b/cpu/mips/Makefile @@ -26,7 +26,8 @@ include $(TOPDIR)/config.mk LIB = lib$(CPU).a START = start.o -OBJS = interrupts.o cpu.o incaip_clock.o serial.o +OBJS = asc_serial.o au1x00_serial.o au1x00_eth.o \ + cpu.o interrupts.o incaip_clock.o SOBJS = incaip_wdt.o cache.o all: .depend $(START) $(LIB) diff --git a/cpu/mips/serial.c b/cpu/mips/asc_serial.c index 585227a..d95ec3f 100644 --- a/cpu/mips/serial.c +++ b/cpu/mips/asc_serial.c @@ -4,6 +4,8 @@ #include <config.h> +#if defined(CONFIG_PURPLE) || defined(CONFIG_INCA_IP) + #ifdef CONFIG_PURPLE #define serial_init asc_serial_init #define serial_putc asc_serial_putc @@ -15,7 +17,7 @@ #include <common.h> #include <asm/inca-ip.h> -#include "serial.h" +#include "asc_serial.h" #ifdef CONFIG_PURPLE @@ -366,3 +368,4 @@ int serial_tstc (void) return res; } +#endif /* CONFIG_PURPLE || CONFIG_INCA_IP */ diff --git a/cpu/mips/serial.h b/cpu/mips/asc_serial.h index 7ffdcfa..7ffdcfa 100644 --- a/cpu/mips/serial.h +++ b/cpu/mips/asc_serial.h diff --git a/cpu/mips/au1x00_eth.c b/cpu/mips/au1x00_eth.c new file mode 100644 index 0000000..c23712b --- /dev/null +++ b/cpu/mips/au1x00_eth.c @@ -0,0 +1,216 @@ +/* Only eth0 supported for now + * + * (C) Copyright 2003 + * Thomas.Lange@corelatus.se + * + * 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> + +#ifdef CONFIG_AU1X00 + +#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII) +#error "PHY and MII not supported yet" +/* We just assume that we are running 100FD for now */ +/* We all use switches, right? ;-) */ +#endif + +#ifdef CONFIG_AU1000 +/* Base address differ between cpu:s */ +#define ETH0_BASE AU1000_ETH0_BASE +#define MAC0_ENABLE AU1000_MAC0_ENABLE +#else +#error "Au1100 and Au1500 not supported" +#endif + +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <command.h> +#include <asm/io.h> +#include <asm/au1x00.h> + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH 1520 +#define PKT_MAXBUF_SIZE 1518 + +static char txbuf[DBUF_LENGTH]; + +static int next_tx; +static int next_rx; + +/* 4 rx and 4 tx fifos */ +#define NO_OF_FIFOS 4 + +typedef struct{ + u32 status; + u32 addr; + u32 len; /* Only used for tx */ + u32 not_used; +} mac_fifo_t; + +mac_fifo_t mac_fifo[NO_OF_FIFOS]; + +#define MAX_WAIT 1000 + +static int au1x00_send(struct eth_device* dev, volatile void *packet, int length){ + volatile mac_fifo_t *fifo_tx = + (volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS); + int i; + int res; + + /* tx fifo should always be idle */ + fifo_tx[next_tx].len = length; + fifo_tx[next_tx].addr = (virt_to_phys(packet))|TX_DMA_ENABLE; + au_sync(); + + udelay(1); + i=0; + while(!(fifo_tx[next_tx].addr&TX_T_DONE)){ + if(i>MAX_WAIT){ + printf("TX timeout\n"); + break; + } + udelay(1); + i++; + } + + /* Clear done bit */ + fifo_tx[next_tx].addr = 0; + fifo_tx[next_tx].len = 0; + au_sync(); + + res = fifo_tx[next_tx].status; + + next_tx++; + if(next_tx>=NO_OF_FIFOS){ + next_tx=0; + } + return(res); +} + +static int au1x00_recv(struct eth_device* dev){ + volatile mac_fifo_t *fifo_rx = + (volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS); + + int length; + u32 status; + + for(;;){ + if(!(fifo_rx[next_rx].addr&RX_T_DONE)){ + /* Nothing has been received */ + return(-1); + } + + status = fifo_rx[next_rx].status; + + length = status&0x3FFF; + + if(status&RX_ERROR){ + printf("Rx error 0x%x\n", status); + } + else{ + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[next_rx], length - 4); + } + + fifo_rx[next_rx].addr = (virt_to_phys(NetRxPackets[next_rx]))|RX_DMA_ENABLE; + + next_rx++; + if(next_rx>=NO_OF_FIFOS){ + next_rx=0; + } + } /* for */ + + return(0); /* Does anyone use this? */ +} + +static int au1x00_init(struct eth_device* dev, bd_t * bd){ + + volatile u32 *macen = (volatile u32*)MAC0_ENABLE; + volatile u32 *mac_ctrl = (volatile u32*)(ETH0_BASE+MAC_CONTROL); + volatile u32 *mac_addr_high = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_HIGH); + volatile u32 *mac_addr_low = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_LOW); + volatile u32 *mac_mcast_high = (volatile u32*)(ETH0_BASE+MAC_MCAST_HIGH); + volatile u32 *mac_mcast_low = (volatile u32*)(ETH0_BASE+MAC_MCAST_LOW); + volatile mac_fifo_t *fifo_tx = + (volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS); + volatile mac_fifo_t *fifo_rx = + (volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS); + int i; + + next_tx = 0; + next_rx = 0; + + /* We have to enable clocks before releasing reset */ + *macen = MAC_EN_CLOCK_ENABLE; + udelay(10); + + /* Enable MAC0 */ + /* We have to release reset before accessing registers */ + *macen = MAC_EN_CLOCK_ENABLE|MAC_EN_RESET0| + MAC_EN_RESET1|MAC_EN_RESET2; + udelay(10); + + for(i=0;i<NO_OF_FIFOS;i++){ + fifo_tx[i].len = 0; + fifo_tx[i].addr = virt_to_phys(&txbuf[0]); + fifo_rx[i].addr = (virt_to_phys(NetRxPackets[i]))|RX_DMA_ENABLE; + } + + /* Put mac addr in little endian */ +#define ea eth_get_dev()->enetaddr + *mac_addr_high = (ea[5] << 8) | (ea[4] ) ; + *mac_addr_low = (ea[3] << 24) | (ea[2] << 16) | + (ea[1] << 8) | (ea[0] ) ; +#undef ea + + *mac_mcast_low = 0; + *mac_mcast_high = 0; + + *mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX; + udelay(1); + *mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE; + + return(1); +} + +static void au1x00_halt(struct eth_device* dev){ +} + +int au1x00_enet_initialize(bd_t *bis){ + struct eth_device* dev; + + dev = (struct eth_device*) malloc(sizeof *dev); + memset(dev, 0, sizeof *dev); + + sprintf(dev->name, "Au1X00 ETHERNET"); + dev->iobase = 0; + dev->priv = 0; + dev->init = au1x00_init; + dev->halt = au1x00_halt; + dev->send = au1x00_send; + dev->recv = au1x00_recv; + + eth_register(dev); + + return 1; +} + +#endif /* CONFIG_AU1X00 */ diff --git a/cpu/mips/au1x00_serial.c b/cpu/mips/au1x00_serial.c new file mode 100644 index 0000000..99e2489 --- /dev/null +++ b/cpu/mips/au1x00_serial.c @@ -0,0 +1,123 @@ +/* + * AU1X00 UART support + * + * Hardcoded to UART 0 for now + * Speed and options also hardcoded to 115200 8N1 + * + * Copyright (c) 2003 Thomas.Lange@corelatus.se + * + * 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> + +#ifdef CONFIG_AU1X00 + +#include <common.h> +#include <asm/au1x00.h> + +/****************************************************************************** +* +* serial_init - initialize a 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) +{ + volatile u32 *uart_fifoctl = (volatile u32*)(UART0_ADDR+UART_FCR); + volatile u32 *uart_enable = (volatile u32*)(UART0_ADDR+UART_ENABLE); + + /* Enable clocks first */ + *uart_enable = UART_EN_CE; + + /* Then release reset */ + /* Must release reset before setting other regs */ + *uart_enable = UART_EN_CE|UART_EN_E; + + /* Activate fifos, reset tx and rx */ + /* Set tx trigger level to 12 */ + *uart_fifoctl = UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR| + UART_FCR_CLEAR_XMIT|UART_FCR_T_TRIGGER_12; + + serial_setbrg(); + + return 0; +} + + +void serial_setbrg (void) +{ + volatile u32 *uart_clk = (volatile u32*)(UART0_ADDR+UART_CLK); + volatile u32 *uart_lcr = (volatile u32*)(UART0_ADDR+UART_LCR); + + /* Set baudrate to 115200 */ + *uart_clk = 0x36; + + /* Set parity, stop bits and word length to 8N1 */ + *uart_lcr = UART_LCR_WLEN8; +} + +void serial_putc (const char c) +{ + volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR); + volatile u32 *uart_tx = (volatile u32*)(UART0_ADDR+UART_TX); + + if (c == '\n') serial_putc ('\r'); + + /* Wait for fifo to shift out some bytes */ + while((*uart_lsr&UART_LSR_THRE)==0); + + *uart_tx = (u32)c; +} + +void serial_puts (const char *s) +{ + while (*s) + { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + volatile u32 *uart_rx = (volatile u32*)(UART0_ADDR+UART_RX); + char c; + + while (!serial_tstc()); + + c = (*uart_rx&0xFF); + return c; +} + +int serial_tstc (void) +{ + volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR); + + if(*uart_lsr&UART_LSR_DR){ + /* Data in rfifo */ + return(1); + } + return 0; +} +#endif /* CONFIG_SERIAL_AU1X00 */ diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S index 01fbb2f..aad76e0 100644 --- a/cpu/mips/cache.S +++ b/cpu/mips/cache.S @@ -250,10 +250,10 @@ dcache_disable: * RETURNS: N/A * */ -#if defined(CONFIG_INCA_IP) -# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE) -#elif defined(CONFIG_PURPLE) +#if defined(CONFIG_PURPLE) # define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2) +#else +# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE) #endif .globl mips_cache_lock .ent mips_cache_lock diff --git a/cpu/mips/cpu.c b/cpu/mips/cpu.c index c27abbd..e73d138 100644 --- a/cpu/mips/cpu.c +++ b/cpu/mips/cpu.c @@ -24,6 +24,7 @@ #include <common.h> #include <command.h> #include <asm/inca-ip.h> +#include <asm/mipsregs.h> int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { @@ -42,3 +43,12 @@ void flush_cache (ulong start_addr, ulong size) { } + +void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 ){ + write_32bit_cp0_register(CP0_ENTRYLO0, low0); + write_32bit_cp0_register(CP0_PAGEMASK, pagemask); + write_32bit_cp0_register(CP0_ENTRYLO1, low1); + write_32bit_cp0_register(CP0_ENTRYHI, hi); + write_32bit_cp0_register(CP0_INDEX, index); + tlb_write_indexed(); +} |