diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/nios/Makefile | 48 | ||||
-rw-r--r-- | cpu/nios/asmi.c | 695 | ||||
-rw-r--r-- | cpu/nios/config.mk | 24 | ||||
-rw-r--r-- | cpu/nios/cpu.c | 78 | ||||
-rw-r--r-- | cpu/nios/interrupts.c | 196 | ||||
-rw-r--r-- | cpu/nios/serial.c | 135 | ||||
-rw-r--r-- | cpu/nios/spi.c | 195 | ||||
-rw-r--r-- | cpu/nios/start.S | 238 | ||||
-rw-r--r-- | cpu/nios/traps.S | 582 |
9 files changed, 0 insertions, 2191 deletions
diff --git a/cpu/nios/Makefile b/cpu/nios/Makefile deleted file mode 100644 index ad17456..0000000 --- a/cpu/nios/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# (C) Copyright 2000-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -include $(TOPDIR)/config.mk - -LIB = $(obj)lib$(CPU).a - -START = start.o -SOBJS = traps.o -COBJS = cpu.o interrupts.o serial.o asmi.o spi.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 - -######################################################################### diff --git a/cpu/nios/asmi.c b/cpu/nios/asmi.c deleted file mode 100644 index 33553b7..0000000 --- a/cpu/nios/asmi.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * (C) Copyright 2003, Psyent Corporation <www.psyent.com> - * Scott McNutt <smcnutt@psyent.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> - -#if defined(CONFIG_NIOS_ASMI) -#include <command.h> -#include <nios-io.h> - -#if !defined(CONFIG_SYS_NIOS_ASMIBASE) -#error "*** CONFIG_SYS_NIOS_ASMIBASE not defined ***" -#endif - -/*-----------------------------------------------------------------------*/ -#define SHORT_HELP\ - "asmi - read/write Cyclone ASMI configuration device.\n" - -#define LONG_HELP\ - "\n"\ - "asmi erase start [end]\n"\ - " - erase sector start or sectors start through end.\n"\ - "asmi info\n"\ - " - display ASMI device information.\n"\ - "asmi protect on | off\n"\ - " - turn device protection on or off.\n"\ - "asmi read addr offset count\n"\ - " - read count bytes from offset to addr.\n"\ - "asmi write addr offset count\n"\ - " - write count bytes to offset from addr.\n"\ - "asmi verify addr offset count\n"\ - " - verify count bytes at offset from addr." - - -/*-----------------------------------------------------------------------*/ -/* Operation codes for serial configuration devices - */ -#define ASMI_WRITE_ENA 0x06 /* Write enable */ -#define ASMI_WRITE_DIS 0x04 /* Write disable */ -#define ASMI_READ_STAT 0x05 /* Read status */ -#define ASMI_READ_BYTES 0x03 /* Read bytes */ -#define ASMI_READ_ID 0xab /* Read silicon id */ -#define ASMI_WRITE_STAT 0x01 /* Write status */ -#define ASMI_WRITE_BYTES 0x02 /* Write bytes */ -#define ASMI_ERASE_BULK 0xc7 /* Erase entire device */ -#define ASMI_ERASE_SECT 0xd8 /* Erase sector */ - -/* Device status register bits - */ -#define ASMI_STATUS_WIP (1<<0) /* Write in progress */ -#define ASMI_STATUS_WEL (1<<1) /* Write enable latch */ - -static nios_asmi_t *asmi = (nios_asmi_t *)CONFIG_SYS_NIOS_ASMIBASE; - -/*********************************************************************** - * Device access - ***********************************************************************/ -static void asmi_cs (int assert) -{ - if (assert) { - asmi->control |= NIOS_ASMI_SSO; - } else { - /* Let all bits shift out */ - while ((asmi->status & NIOS_ASMI_TMT) == 0) - ; - asmi->control &= ~NIOS_ASMI_SSO; - } -} - -static void asmi_tx (unsigned char c) -{ - while ((asmi->status & NIOS_ASMI_TRDY) == 0) - ; - asmi->txdata = c; -} - -static int asmi_rx (void) -{ - while ((asmi->status & NIOS_ASMI_RRDY) == 0) - ; - return (asmi->rxdata); -} - -static unsigned char bitrev[] = { - 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, - 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f -}; - -static unsigned char asmi_bitrev( unsigned char c ) -{ - unsigned char val; - - val = bitrev[c>>4]; - val |= bitrev[c & 0x0f]<<4; - return (val); -} - -static void asmi_rcv (unsigned char *dst, int len) -{ - while (len--) { - asmi_tx (0); - *dst++ = asmi_rx (); - } -} - -static void asmi_rrcv (unsigned char *dst, int len) -{ - while (len--) { - asmi_tx (0); - *dst++ = asmi_bitrev (asmi_rx ()); - } -} - -static void asmi_snd (unsigned char *src, int len) -{ - while (len--) { - asmi_tx (*src++); - asmi_rx (); - } -} - -static void asmi_rsnd (unsigned char *src, int len) -{ - while (len--) { - asmi_tx (asmi_bitrev (*src++)); - asmi_rx (); - } -} - -static void asmi_wr_enable (void) -{ - asmi_cs (1); - asmi_tx (ASMI_WRITE_ENA); - asmi_rx (); - asmi_cs (0); -} - -static unsigned char asmi_status_rd (void) -{ - unsigned char status; - - asmi_cs (1); - asmi_tx (ASMI_READ_STAT); - asmi_rx (); - asmi_tx (0); - status = asmi_rx (); - asmi_cs (0); - return (status); -} - -static void asmi_status_wr (unsigned char status) -{ - asmi_wr_enable (); - asmi_cs (1); - asmi_tx (ASMI_WRITE_STAT); - asmi_rx (); - asmi_tx (status); - asmi_rx (); - asmi_cs (0); - return; -} - -/*********************************************************************** - * Device information - ***********************************************************************/ -typedef struct asmi_devinfo_t { - const char *name; /* Device name */ - unsigned char id; /* Device silicon id */ - unsigned char size; /* Total size log2(bytes)*/ - unsigned char num_sects; /* Number of sectors */ - unsigned char sz_sect; /* Sector size log2(bytes) */ - unsigned char sz_page; /* Page size log2(bytes) */ - unsigned char prot_mask; /* Protection mask */ -}asmi_devinfo_t; - -static struct asmi_devinfo_t devinfo[] = { - { "EPCS1 ", 0x10, 17, 4, 15, 8, 0x0c }, - { "EPCS4 ", 0x12, 19, 8, 16, 8, 0x1c }, - { 0, 0, 0, 0, 0, 0 } -}; - -static asmi_devinfo_t *asmi_dev_find (void) -{ - unsigned char buf[4]; - unsigned char id; - int i; - struct asmi_devinfo_t *dev = NULL; - - /* Read silicon id requires 3 "dummy bytes" before it's put - * on the wire. - */ - buf[0] = ASMI_READ_ID; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - - asmi_cs (1); - asmi_snd (buf,4); - asmi_rcv (buf,1); - asmi_cs (0); - id = buf[0]; - - /* Find the info struct */ - i = 0; - while (devinfo[i].name) { - if (id == devinfo[i].id) { - dev = &devinfo[i]; - break; - } - i++; - } - - return (dev); -} - -/*********************************************************************** - * Misc Utilities - ***********************************************************************/ -static unsigned asmi_cfgsz (void) -{ - unsigned sz = 0; - unsigned char buf[128]; - unsigned char *p; - - /* Read in the first 128 bytes of the device */ - buf[0] = ASMI_READ_BYTES; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - - asmi_cs (1); - asmi_snd (buf,4); - asmi_rrcv (buf, sizeof(buf)); - asmi_cs (0); - - /* Search for the starting 0x6a which is followed by the - * 4-byte 'register' and 4-byte bit-count. - */ - p = buf; - while (p < buf + sizeof(buf)-8) { - if ( *p == 0x6a ) { - /* Point to bit count and extract */ - p += 5; - sz = *p++; - sz |= *p++ << 8; - sz |= *p++ << 16; - sz |= *p++ << 24; - /* Convert to byte count */ - sz += 7; - sz >>= 3; - } else if (*p == 0xff) { - /* 0xff is ok ... just skip */ - p++; - continue; - } else { - /* Not 0xff or 0x6a ... something's not - * right ... report 'unknown' (sz=0). - */ - break; - } - } - return (sz); -} - -static int asmi_erase (unsigned start, unsigned end) -{ - unsigned off, sectsz; - unsigned char buf[4]; - struct asmi_devinfo_t *dev = asmi_dev_find (); - - if (!dev || (start>end)) - return (-1); - - /* Erase the requested sectors. An address is required - * that lies within the requested sector -- we'll just - * use the first address in the sector. - */ - printf ("asmi erasing sector %d ", start); - if (start != end) - printf ("to %d ", end); - sectsz = (1 << dev->sz_sect); - while (start <= end) { - off = start * sectsz; - start++; - - buf[0] = ASMI_ERASE_SECT; - buf[1] = off >> 16; - buf[2] = off >> 8; - buf[3] = off; - - asmi_wr_enable (); - asmi_cs (1); - asmi_snd (buf,4); - asmi_cs (0); - - printf ("."); /* Some user feedback */ - - /* Wait for erase to complete */ - while (asmi_status_rd() & ASMI_STATUS_WIP) - ; - } - printf (" done.\n"); - return (0); -} - -static int asmi_read (ulong addr, ulong off, ulong cnt) -{ - unsigned char buf[4]; - - buf[0] = ASMI_READ_BYTES; - buf[1] = off >> 16; - buf[2] = off >> 8; - buf[3] = off; - - asmi_cs (1); - asmi_snd (buf,4); - asmi_rrcv ((unsigned char *)addr, cnt); - asmi_cs (0); - - return (0); -} - -static -int asmi_write (ulong addr, ulong off, ulong cnt) -{ - ulong wrcnt; - unsigned pgsz; - unsigned char buf[4]; - struct asmi_devinfo_t *dev = asmi_dev_find (); - - if (!dev) - return (-1); - - pgsz = (1<<dev->sz_page); - while (cnt) { - if (off % pgsz) - wrcnt = pgsz - (off % pgsz); - else - wrcnt = pgsz; - wrcnt = (wrcnt > cnt) ? cnt : wrcnt; - - buf[0] = ASMI_WRITE_BYTES; - buf[1] = off >> 16; - buf[2] = off >> 8; - buf[3] = off; - - asmi_wr_enable (); - asmi_cs (1); - asmi_snd (buf,4); - asmi_rsnd ((unsigned char *)addr, wrcnt); - asmi_cs (0); - - /* Wait for write to complete */ - while (asmi_status_rd() & ASMI_STATUS_WIP) - ; - - cnt -= wrcnt; - off += wrcnt; - addr += wrcnt; - } - - return (0); -} - -static -int asmi_verify (ulong addr, ulong off, ulong cnt, ulong *err) -{ - ulong rdcnt; - unsigned char buf[256]; - unsigned char *start,*end; - int i; - - start = end = (unsigned char *)addr; - while (cnt) { - rdcnt = (cnt>sizeof(buf)) ? sizeof(buf) : cnt; - asmi_read ((ulong)buf, off, rdcnt); - for (i=0; i<rdcnt; i++) { - if (*end != buf[i]) { - *err = end - start; - return(-1); - } - end++; - } - cnt -= rdcnt; - off += rdcnt; - } - return (0); -} - -static int asmi_sect_erased (int sect, unsigned *offset, - struct asmi_devinfo_t *dev) -{ - unsigned char buf[128]; - unsigned off, end; - unsigned sectsz; - int i; - - sectsz = (1 << dev->sz_sect); - off = sectsz * sect; - end = off + sectsz; - - while (off < end) { - asmi_read ((ulong)buf, off, sizeof(buf)); - for (i=0; i < sizeof(buf); i++) { - if (buf[i] != 0xff) { - *offset = off + i; - return (0); - } - } - off += sizeof(buf); - } - return (1); -} - - -/*********************************************************************** - * Commands - ***********************************************************************/ -static -void do_asmi_info (struct asmi_devinfo_t *dev, int argc, char *argv[]) -{ - int i; - unsigned char stat; - unsigned tmp; - int erased; - - /* Basic device info */ - printf ("%s: %d kbytes (%d sectors x %d kbytes," - " %d bytes/page)\n", - dev->name, 1 << (dev->size-10), - dev->num_sects, 1 << (dev->sz_sect-10), - 1 << dev->sz_page ); - - /* Status -- for now protection is all-or-nothing */ - stat = asmi_status_rd(); - printf ("status: 0x%02x (WIP:%d, WEL:%d, PROT:%s)\n", - stat, - (stat & ASMI_STATUS_WIP) ? 1 : 0, - (stat & ASMI_STATUS_WEL) ? 1 : 0, - (stat & dev->prot_mask) ? "on" : "off" ); - - /* Configuration */ - tmp = asmi_cfgsz (); - if (tmp) { - printf ("config: 0x%06x (%d) bytes\n", tmp, tmp ); - } else { - printf ("config: unknown\n" ); - } - - /* Sector info */ - for (i=0; i<dev->num_sects; i++) { - erased = asmi_sect_erased (i, &tmp, dev); - printf (" %d: %06x ", - i, i*(1<<dev->sz_sect) ); - if (erased) - printf ("erased\n"); - else - printf ("data @ 0x%06x\n", tmp); - } - - return; -} - -static -void do_asmi_erase (struct asmi_devinfo_t *dev, int argc, char *argv[]) -{ - unsigned start,end; - - if ((argc < 3) || (argc > 4)) { - printf ("USAGE: asmi erase sect [end]\n"); - return; - } - if ((asmi_status_rd() & dev->prot_mask) != 0) { - printf ( "asmi: device protected.\n"); - return; - } - - start = simple_strtoul (argv[2], NULL, 10); - if (argc > 3) - end = simple_strtoul (argv[3], NULL, 10); - else - end = start; - if ((start >= dev->num_sects) || (start > end)) { - printf ("asmi: invalid sector range: [%d:%d]\n", - start, end ); - return; - } - - asmi_erase (start, end); - - return; -} - -static -void do_asmi_protect (struct asmi_devinfo_t *dev, int argc, char *argv[]) -{ - unsigned char stat; - - /* For now protection is all-or-nothing to keep things - * simple. The protection bits don't map in a linear - * fashion ... and we would rather protect the bottom - * of the device since it contains the config data and - * leave the top unprotected for app use. But unfortunately - * protection works from top-to-bottom so it does - * really help very much from a software app point-of-view. - */ - if (argc < 3) { - printf ("USAGE: asmi protect on | off\n"); - return; - } - if (!dev) - return; - - /* Protection on/off is just a matter of setting/clearing - * all protection bits in the status register. - */ - stat = asmi_status_rd (); - if (strcmp ("on", argv[2]) == 0) { - stat |= dev->prot_mask; - } else if (strcmp ("off", argv[2]) == 0 ) { - stat &= ~dev->prot_mask; - } else { - printf ("asmi: unknown protection: %s\n", argv[2]); - return; - } - asmi_status_wr (stat); - return; -} - -static -void do_asmi_read (struct asmi_devinfo_t *dev, int argc, char *argv[]) -{ - ulong addr,off,cnt; - ulong sz; - - if (argc < 5) { - printf ("USAGE: asmi read addr offset count\n"); - return; - } - - sz = 1 << dev->size; - addr = simple_strtoul (argv[2], NULL, 16); - off = simple_strtoul (argv[3], NULL, 16); - cnt = simple_strtoul (argv[4], NULL, 16); - if (off > sz) { - printf ("offset is greater than device size" - "... aborting.\n"); - return; - } - if ((off + cnt) > sz) { - printf ("request exceeds device size" - "... truncating.\n"); - cnt = sz - off; - } - printf ("asmi: read %08lx <- %06lx (0x%lx bytes)\n", - addr, off, cnt); - asmi_read (addr, off, cnt); - - return; -} - -static -void do_asmi_write (struct asmi_devinfo_t *dev, int argc, char *argv[]) -{ - ulong addr,off,cnt; - ulong sz; - ulong err; - - if (argc < 5) { - printf ("USAGE: asmi write addr offset count\n"); - return; - } - if ((asmi_status_rd() & dev->prot_mask) != 0) { - printf ( "asmi: device protected.\n"); - return; - } - - sz = 1 << dev->size; - addr = simple_strtoul (argv[2], NULL, 16); - off = simple_strtoul (argv[3], NULL, 16); - cnt = simple_strtoul (argv[4], NULL, 16); - if (off > sz) { - printf ("offset is greater than device size" - "... aborting.\n"); - return; - } - if ((off + cnt) > sz) { - printf ("request exceeds device size" - "... truncating.\n"); - cnt = sz - off; - } - printf ("asmi: write %08lx -> %06lx (0x%lx bytes)\n", - addr, off, cnt); - asmi_write (addr, off, cnt); - if (asmi_verify (addr, off, cnt, &err) != 0) - printf ("asmi: write error at offset %06lx\n", err); - - return; -} - -static -void do_asmi_verify (struct asmi_devinfo_t *dev, int argc, char *argv[]) -{ - ulong addr,off,cnt; - ulong sz; - ulong err; - - if (argc < 5) { - printf ("USAGE: asmi verify addr offset count\n"); - return; - } - - sz = 1 << dev->size; - addr = simple_strtoul (argv[2], NULL, 16); - off = simple_strtoul (argv[3], NULL, 16); - cnt = simple_strtoul (argv[4], NULL, 16); - if (off > sz) { - printf ("offset is greater than device size" - "... aborting.\n"); - return; - } - if ((off + cnt) > sz) { - printf ("request exceeds device size" - "... truncating.\n"); - cnt = sz - off; - } - printf ("asmi: verify %08lx -> %06lx (0x%lx bytes)\n", - addr, off, cnt); - if (asmi_verify (addr, off, cnt, &err) != 0) - printf ("asmi: verify error at offset %06lx\n", err); - - return; -} - -/*-----------------------------------------------------------------------*/ -int do_asmi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int len; - struct asmi_devinfo_t *dev = asmi_dev_find (); - - if (argc < 2) { - printf ("Usage:%s", LONG_HELP); - return (0); - } - - if (!dev) { - printf ("asmi: device not found.\n"); - return (0); - } - - len = strlen (argv[1]); - if (strncmp ("info", argv[1], len) == 0) { - do_asmi_info ( dev, argc, argv); - } else if (strncmp ("erase", argv[1], len) == 0) { - do_asmi_erase (dev, argc, argv); - } else if (strncmp ("protect", argv[1], len) == 0) { - do_asmi_protect (dev, argc, argv); - } else if (strncmp ("read", argv[1], len) == 0) { - do_asmi_read (dev, argc, argv); - } else if (strncmp ("write", argv[1], len) == 0) { - do_asmi_write (dev, argc, argv); - } else if (strncmp ("verify", argv[1], len) == 0) { - do_asmi_verify (dev, argc, argv); - } else { - printf ("asmi: unknown operation: %s\n", argv[1]); - } - - return (0); -} - -/*-----------------------------------------------------------------------*/ - - -U_BOOT_CMD( asmi, 5, 0, do_asmi, SHORT_HELP, LONG_HELP ); - -#endif /* CONFIG_NIOS_ASMI */ diff --git a/cpu/nios/config.mk b/cpu/nios/config.mk deleted file mode 100644 index f228d72..0000000 --- a/cpu/nios/config.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# (C) Copyright 2000 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -PLATFORM_RELFLAGS += diff --git a/cpu/nios/cpu.c b/cpu/nios/cpu.c deleted file mode 100644 index 5519e82..0000000 --- a/cpu/nios/cpu.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * (C) Copyright 2003, Psyent Corporation <www.psyent.com> - * Scott McNutt <smcnutt@psyent.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 <nios.h> - - -int checkcpu (void) -{ - unsigned val; - unsigned rev_major; - unsigned rev_minor; - short nregs, hi_limit, lo_limit; - - /* Get cpu version info */ - val = rdctl (CTL_CPU_ID); - puts ("CPU: "); - printf ("%s", (val & 0x00008000) ? "Nios-16 " : "Nios-32 "); - rev_major = (val>>12) & 0x07; - rev_minor = (val>>4) & 0x0ff; - printf ("Rev. %d.%d (0x%04x)", rev_major, rev_minor, - val & 0xffff); - if (rev_major == 0x08) - printf (" [OpenCore (R) Plus]"); - printf ("\n"); - - /* Check register file */ - val = rdctl (CTL_WVALID); - lo_limit = val & 0x01f; - hi_limit = (val>>5) & 0x1f; - nregs = (hi_limit + 2) * 16; - printf ("Reg file size: %d LO_LIMIT/HI_LIMIT: %d/%d\n", - nregs, lo_limit, hi_limit); - - return (0); -} - - -int do_reset (void) -{ - /* trap 0 does the trick ... at least with the OCI debug - * present -- haven't tested without it yet (stm). - */ - disable_interrupts (); - ipri (1); - asm volatile ("trap 0\n"); - - /* No return ;-) */ - - return(0); -} - - -#if defined(CONFIG_WATCHDOG) -void watchdog_reset (void) -{ -} -#endif /* CONFIG_WATCHDOG */ diff --git a/cpu/nios/interrupts.c b/cpu/nios/interrupts.c deleted file mode 100644 index 55a5718..0000000 --- a/cpu/nios/interrupts.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2003, Psyent Corporation <www.psyent.com> - * Scott McNutt <smcnutt@psyent.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 <nios.h> -#include <nios-io.h> -#include <asm/ptrace.h> -#include <common.h> -#include <command.h> -#include <watchdog.h> -#ifdef CONFIG_STATUS_LED -#include <status_led.h> -#endif - -/****************************************************************************/ - -struct irq_action { - interrupt_handler_t *handler; - void *arg; - int count; -}; - -static struct irq_action irq_vecs[64]; - -/*************************************************************************/ -volatile ulong timestamp = 0; - -void reset_timer (void) -{ - timestamp = 0; -} - -ulong get_timer (ulong base) -{ - WATCHDOG_RESET (); - return (timestamp - base); -} - -void set_timer (ulong t) -{ - timestamp = t; -} - - -/* The board must handle this interrupt if a timer is not - * provided. - */ -#if defined(CONFIG_SYS_NIOS_TMRBASE) -void timer_interrupt (struct pt_regs *regs) -{ - /* Interrupt is cleared by writing anything to the - * status register. - */ - nios_timer_t *tmr = (nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE; - tmr->status = 0; - timestamp += CONFIG_SYS_NIOS_TMRMS; -#ifdef CONFIG_STATUS_LED - status_led_tick(timestamp); -#endif -} -#endif - -/*************************************************************************/ -int disable_interrupts (void) -{ - int val = 0; - - /* Writing anything to CLR_IE disables interrupts */ - val = rdctl (CTL_STATUS); - wrctl (CTL_CLR_IE, 0); - return (val & STATUS_IE); -} - -void enable_interrupts( void ) -{ - /* Writing anything SET_IE enables interrupts */ - wrctl (CTL_SET_IE, 0); -} - -void external_interrupt (struct pt_regs *regs) -{ - unsigned vec; - - vec = (regs->status & STATUS_IPRI) >> 9; /* ipri */ - - irq_vecs[vec].count++; - if (irq_vecs[vec].handler != NULL) { - (*irq_vecs[vec].handler)(irq_vecs[vec].arg); - } else { - /* A sad side-effect of masking a bogus interrupt is - * that lower priority interrupts will also be disabled. - * This is probably not what we want ... so hang insted. - */ - printf ("Unhandled interrupt: 0x%x\n", vec); - disable_interrupts (); - hang (); - } -} - -/*************************************************************************/ -int interrupt_init (void) -{ - int vec; - -#if defined(CONFIG_SYS_NIOS_TMRBASE) - nios_timer_t *tmr = (nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE; - - tmr->control &= ~NIOS_TIMER_ITO; - tmr->control |= NIOS_TIMER_STOP; -#if defined(CONFIG_SYS_NIOS_TMRCNT) - tmr->periodl = CONFIG_SYS_NIOS_TMRCNT & 0xffff; - tmr->periodh = (CONFIG_SYS_NIOS_TMRCNT >> 16) & 0xffff; -#endif -#endif - - for (vec=0; vec<64; vec++ ) { - irq_vecs[vec].handler = NULL; - irq_vecs[vec].arg = NULL; - irq_vecs[vec].count = 0; - } - - /* Need timus interruptus -- start the lopri timer */ -#if defined(CONFIG_SYS_NIOS_TMRBASE) - tmr->control |= ( NIOS_TIMER_ITO | - NIOS_TIMER_CONT | - NIOS_TIMER_START ); - ipri (CONFIG_SYS_NIOS_TMRIRQ + 1); -#endif - enable_interrupts (); - return (0); -} - -void irq_install_handler (int vec, interrupt_handler_t *handler, void *arg) -{ - struct irq_action *irqa = irq_vecs; - int i = vec; - int flag; - - if (irqa[i].handler != NULL) { - printf ("Interrupt vector %d: handler 0x%x " - "replacing 0x%x\n", - vec, (uint)handler, (uint)irqa[i].handler); - } - - flag = disable_interrupts (); - irqa[i].handler = handler; - irqa[i].arg = arg; - if (flag ) - enable_interrupts (); -} - -/*************************************************************************/ -#if defined(CONFIG_CMD_IRQ) -int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int vec; - - printf ("\nInterrupt-Information:\n"); - printf ("Nr Routine Arg Count\n"); - - for (vec=0; vec<64; vec++) { - if (irq_vecs[vec].handler != NULL) { - printf ("%02d %08lx %08lx %d\n", - vec, - (ulong)irq_vecs[vec].handler<<1, - (ulong)irq_vecs[vec].arg, - irq_vecs[vec].count); - } - } - - return (0); -} -#endif diff --git a/cpu/nios/serial.c b/cpu/nios/serial.c deleted file mode 100644 index 44aa600..0000000 --- a/cpu/nios/serial.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * (C) Copyright 2003, Psyent Corporation <www.psyent.com> - * Scott McNutt <smcnutt@psyent.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 <nios-io.h> - -DECLARE_GLOBAL_DATA_PTR; - -/*------------------------------------------------------------------ - * JTAG acts as the serial port - *-----------------------------------------------------------------*/ -#if defined(CONFIG_CONSOLE_JTAG) - -static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; - -void serial_setbrg( void ){ return; } -int serial_init( void ) { return(0);} - -void serial_putc (char c) -{ - while ((jtag->txcntl & NIOS_JTAG_TRDY) != 0) - WATCHDOG_RESET (); - jtag->txcntl = NIOS_JTAG_TRDY | (unsigned char)c; -} - -void serial_puts (const char *s) -{ - while (*s != 0) - serial_putc (*s++); -} - -int serial_tstc (void) -{ - return (jtag->rxcntl & NIOS_JTAG_RRDY); -} - -int serial_getc (void) -{ - int c; - while (serial_tstc() == 0) - WATCHDOG_RESET (); - c = jtag->rxcntl & 0x0ff; - jtag->rxcntl = 0; - return (c); -} - -/*------------------------------------------------------------------ - * UART the serial port - *-----------------------------------------------------------------*/ -#else - -static nios_uart_t *uart = (nios_uart_t *)CONFIG_SYS_NIOS_CONSOLE; - -#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) - -/* Everything's already setup for fixed-baud PTF - * assignment - */ -void serial_setbrg (void){ return; } -int serial_init (void) { return (0);} - -#else - -void serial_setbrg (void) -{ - unsigned div; - - div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1; - uart->divisor = div; - return; -} - -int serial_init (void) -{ - serial_setbrg (); - return (0); -} - -#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ - - -/*----------------------------------------------------------------------- - * UART CONSOLE - *---------------------------------------------------------------------*/ -void serial_putc (char c) -{ - if (c == '\n') - serial_putc ('\r'); - while ((uart->status & NIOS_UART_TRDY) == 0) - WATCHDOG_RESET (); - uart->txdata = (unsigned char)c; -} - -void serial_puts (const char *s) -{ - while (*s != 0) { - serial_putc (*s++); - } -} - -int serial_tstc (void) -{ - return (uart->status & NIOS_UART_RRDY); -} - -int serial_getc (void) -{ - while (serial_tstc () == 0) - WATCHDOG_RESET (); - return( uart->rxdata & 0x00ff ); -} - -#endif /* CONFIG_JTAG_CONSOLE */ diff --git a/cpu/nios/spi.c b/cpu/nios/spi.c deleted file mode 100644 index 89f9797..0000000 --- a/cpu/nios/spi.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * (C) Copyright 2004, Li-Pro.Net <www.li-pro.net> - * Stephan Linz <linz@li-pro.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 <linux/ctype.h> - -#if defined(CONFIG_NIOS_SPI) -#include <nios-io.h> -#include <spi.h> - -#if !defined(CONFIG_SYS_NIOS_SPIBASE) -#error "*** CONFIG_SYS_NIOS_SPIBASE not defined ***" -#endif - -#if !defined(CONFIG_SYS_NIOS_SPIBITS) -#error "*** CONFIG_SYS_NIOS_SPIBITS not defined ***" -#endif - -#if (CONFIG_SYS_NIOS_SPIBITS != 8) && (CONFIG_SYS_NIOS_SPIBITS != 16) -#error "*** CONFIG_SYS_NIOS_SPIBITS should be either 8 or 16 ***" -#endif - -static nios_spi_t *spi = (nios_spi_t *)CONFIG_SYS_NIOS_SPIBASE; - -/* Warning: - * You cannot enable DEBUG for early system initalization, i. e. when - * this driver is used to read environment parameters like "baudrate" - * from EEPROM which are used to initialize the serial port which is - * needed to print the debug messages... - */ -#undef DEBUG - -#ifdef DEBUG - -#define DPRINT(a) printf a; -/* ----------------------------------------------- - * Helper functions to peek into tx and rx buffers - * ----------------------------------------------- */ -static const char * const hex_digit = "0123456789ABCDEF"; - -static char quickhex (int i) -{ - return hex_digit[i]; -} - -static void memdump (const void *pv, int num) -{ - int i; - const unsigned char *pc = (const unsigned char *) pv; - - for (i = 0; i < num; i++) - printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f)); - printf ("\t"); - for (i = 0; i < num; i++) - printf ("%c", isprint (pc[i]) ? pc[i] : '.'); - printf ("\n"); -} -#else /* !DEBUG */ - -#define DPRINT(a) -#define memdump(p,n) - -#endif /* DEBUG */ - - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct spi_slave *slave; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - slave = malloc(sizeof(struct spi_slave)); - if (!slave) - return NULL; - - slave->bus = bus; - slave->cs = cs; - - /* TODO: Add support for different modes and speeds */ - - return slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - free(slave); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - -} - -/* - * SPI transfer: - * - * See include/spi.h and http://www.altera.com/literature/ds/ds_nios_spi.pdf - * for more informations. - */ -int spi_xfer(struct spi_slave *slave, int bitlen, const void *dout, - void *din, unsigned long flags) -{ - const u8 *txd = dout; - u8 *rxd = din; - int j; - - DPRINT(("spi_xfer: slave %u:%u dout %08X din %08X bitlen %d\n", - slave->bus, slave->cs, *(uint *)dout, *(uint *)din, bitlen)); - - memdump(dout, (bitlen + 7) / 8); - - if (flags & SPI_XFER_BEGIN) - spi_cs_activate(slave); - - if (!(flags & SPI_XFER_END) || bitlen > CONFIG_SYS_NIOS_SPIBITS) { - /* leave chip select active */ - spi->control |= NIOS_SPI_SSO; - } - - for ( j = 0; /* count each byte in */ - j < ((bitlen + 7) / 8); /* dout[] and din[] */ - -#if (CONFIG_SYS_NIOS_SPIBITS == 8) - j++) { - - while ((spi->status & NIOS_SPI_TRDY) == 0) - ; - spi->txdata = (unsigned)(txd[j]); - - while ((spi->status & NIOS_SPI_RRDY) == 0) - ; - rxd[j] = (unsigned char)(spi->rxdata & 0xff); - -#elif (CONFIG_SYS_NIOS_SPIBITS == 16) - j++, j++) { - - while ((spi->status & NIOS_SPI_TRDY) == 0) - ; - if ((j+1) < ((bitlen + 7) / 8)) - spi->txdata = (unsigned)((txd[j] << 8) | txd[j+1]); - else - spi->txdata = (unsigned)(txd[j] << 8); - - while ((spi->status & NIOS_SPI_RRDY) == 0) - ; - rxd[j] = (unsigned char)((spi->rxdata >> 8) & 0xff); - if ((j+1) < ((bitlen + 7) / 8)) - rxd[j+1] = (unsigned char)(spi->rxdata & 0xff); - -#else -#error "*** unsupported value of CONFIG_SYS_NIOS_SPIBITS ***" -#endif - - } - - if (bitlen > CONFIG_SYS_NIOS_SPIBITS && (flags & SPI_XFER_END)) { - spi->control &= ~NIOS_SPI_SSO; - } - - if (flags & SPI_XFER_END) - spi_cs_deactivate(slave); - - memdump(din, (bitlen + 7) / 8); - - return 0; -} - -#endif /* CONFIG_NIOS_SPI */ diff --git a/cpu/nios/start.S b/cpu/nios/start.S deleted file mode 100644 index 3578a04..0000000 --- a/cpu/nios/start.S +++ /dev/null @@ -1,238 +0,0 @@ -/* - * (C) Copyright 2003, Psyent Corporation <www.psyent.com> - * Scott McNutt <smcnutt@psyent.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 <timestamp.h> -#include <version.h> - -#if !defined(CONFIG_IDENT_STRING) -#define CONFIG_IDENT_STRING "" -#endif - -#define STATUS_INIT 0x8600 /* IE=1, IPRI=2 */ - -/************************************************************************* - * RESTART - ************************************************************************/ - - .text - .global _start - -_start: - bsr 0f - nop - .long _start - - /* GERMS -- The "standard-32" configuration GERMS monitor looks - * for the string "Nios" at flash_base + 0xc (actually it only - * tests for 'N', 'i'). You can leave support for this in place - * as it's only a few words. - */ - . = _start + 0x000c - .string "Nios" - - .align 4 -0: - /* - * Early setup -- set cwp = HI_LIMIT, IPRI = 2, IE = 1 to - * enable underflow exceptions. Disable cache. - * NOTE: %o7 has return addr -- save in %g7 use later. - */ - mov %g7, %o7 - - pfx 2 /* WVALID */ - rdctl %g0 - lsri %g0, 1 - pfx %hi(STATUS_INIT) - or %g0, %lo(STATUS_INIT) - wrctl %g0 /* update status */ - nop - - /* - * STACK - */ - pfx %hi(CONFIG_SYS_INIT_SP) - movi %sp, %lo(CONFIG_SYS_INIT_SP) - pfx %xhi(CONFIG_SYS_INIT_SP) - movhi %sp, %xlo(CONFIG_SYS_INIT_SP) - mov %fp, %sp - - pfx %hi(4*16) - subi %sp, %lo(4*16) /* Space for reg window mgmt */ - - /* - * RELOCATE -- %g7 has return addr from bsr at _start. - */ - pfx %hi(__u_boot_cmd_end) - movi %g5, %lo(__u_boot_cmd_end) - pfx %xhi(__u_boot_cmd_end) - movhi %g5, %xlo(__u_boot_cmd_end) /* %g5 <- end address */ - - lsli %g7, 1 /* mem = retaddr << 1 */ - mov %g6, %g7 - subi %g6, 4 /* %g6 <- src addr */ - ld %g7, [%g7] /* %g7 <- dst addr */ - - /* No need to move text sections if we're already located - * at the proper address. - */ - cmp %g7, %g6 - ifs cc_z - br reloc - nop /* delay slot */ - -1: cmp %g7, %g5 - skps cc_nz - br 2f - nop /* delay slot */ - - ld %g0, [%g6] - addi %g6, 4 /* src++ */ - st [%g7], %g0 - addi %g7, 4 /* dst++ */ - br 1b - nop /* delay slot */ -2: - - /* - * Jump to relocation address - */ - pfx %hi(reloc@h) - movi %g0, %lo(reloc@h) - pfx %xhi(reloc@h) - movhi %g0, %xlo(reloc@h) - jmp %g0 - nop /* delay slot */ -reloc: - - /* - * CLEAR BSS - */ - pfx %hi(__bss_end) - movi %g5, %lo(__bss_end) - pfx %xhi(__bss_end) - movhi %g5, %xlo(__bss_end) /* %g5 <- end address */ - pfx %hi(__bss_start) - movi %g7, %lo(__bss_start) - pfx %xhi(__bss_start) - movhi %g7, %xlo(__bss_start) /* %g7 <- end address */ - - movi %g0, 0 -3: cmp %g7, %g5 - skps cc_nz - br 4f - nop /* delay slot */ - - st [%g7], %g0 - addi %g7, 4 /* (delay slot) dst++ */ - br 3b - nop /* delay slot */ -4: - - /* - * INIT VECTOR TABLE - */ - pfx %hi(CONFIG_SYS_VECT_BASE) - movi %g0, %lo(CONFIG_SYS_VECT_BASE) - pfx %xhi(CONFIG_SYS_VECT_BASE) - movhi %g0, %xlo(CONFIG_SYS_VECT_BASE) /* dst */ - mov %l0, %g0 - - pfx %hi(_vectors) - movi %g1, %lo(_vectors) - pfx %xhi(_vectors) - movhi %g1, %xlo(_vectors) /* src */ - bgen %g2, 6 /* cnt = 64 */ - - ldp %g3, [%l0, 3] /* bkpt vector */ - ldp %g4, [%l0, 4] /* single step vector */ - -5: ld %g7, [%g1] - addi %g1, 4 /* src++ */ - st [%g0], %g7 - addi %g0, 4 /* dst++ */ - - subi %g2, 1 /* cnt-- */ - ifrnz %g2 - br 5b - nop /* delay slot */ - -#if defined(CONFIG_ROM_STUBS) - /* Restore the breakpoint and single step exception - * vectors to their original values. - */ - stp [%l0,3], %g3 /* breakpoint */ - stp [%l0,4], %g4 /* single step */ -#endif - - /* For debug startup convenience ... software breakpoints - * set prior to this point may not succeed ;-) - */ - .global __start -__start: - - /* - * Call board_init -- never returns - */ - pfx %hi(board_init@h) - movi %g1, %lo(board_init@h) - pfx %xhi(board_init@h) - movhi %g1, %xlo(board_init@h) - call %g1 - nop /* Delaly slot */ - /* NEVER RETURNS */ - -/* - * dly_clks -- Nios doesn't have a time/clk reference for simple - * delay loops, so we do our best by counting instruction cycles. - * A control register that counts system clock cycles would be - * a handy feature -- hint for Altera ;-) - */ - .globl dly_clks - /* Each loop is 4 instructions as delay slot is always - * executed. Each instruction is approximately 4 clocks - * (according to some lame info from Altera). So ... - * ... each loop is about 16 clocks. - */ - -dly_clks: - lsri %o0, 4 /* cnt/16 */ - -8: skprnz %o0 - br 9f - subi %o0, 1 /* cnt--, Delay slot */ - br 8b - nop - -9: lret - nop /* Delay slot */ - - - .data - .globl version_string - -version_string: - .ascii U_BOOT_VERSION - .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" - .ascii CONFIG_IDENT_STRING, "\0" diff --git a/cpu/nios/traps.S b/cpu/nios/traps.S deleted file mode 100644 index bc4d3f6..0000000 --- a/cpu/nios/traps.S +++ /dev/null @@ -1,582 +0,0 @@ -/* - * (C) Copyright 2003, Psyent Corporation <www.psyent.com> - * Scott McNutt <smcnutt@psyent.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> - -/************************************************************************* - * Register window underflow - * - * The register window underflow exception occurs whenever the lowest - * valid register window is in use (CWP=LO_LIMIT) and a save instruction - * is issued. The save moves CWP below LO_LIMIT, %sp is set as normal, - * then the exception is generated prior to executing the instruction - * after the save. - ************************************************************************/ - .text - .global _cwp_lolimit - .align 4 - -_cwp_lolimit: - - /* Sixteen words are always allocated by the compiler in every - * procedure's stack frame, always starting at %sp, for saving - * 'in' and 'local' registers on a window overflow. - * - * Save the 'global' and 'in' regs on stack. They are restored - * at cwp = HI_LIMIT. The 'local' regs aren't in-use at this point. - */ - sts [%sp,0], %g0 /* Save 'global' regs*/ - sts [%sp,1], %g1 - sts [%sp,2], %g2 - sts [%sp,3], %g3 - sts [%sp,4], %g4 - sts [%sp,5], %g5 - sts [%sp,6], %g6 - sts [%sp,7], %g7 - - sts [%sp,8], %i0 /* Save 'in' regs */ - sts [%sp,9], %i1 - sts [%sp,10], %i2 - sts [%sp,11], %i3 - sts [%sp,12], %i4 - sts [%sp,13], %i5 - sts [%sp,14], %i6 - sts [%sp,15], %i7 - - /* Save current %sp and return address in a global so they are - * available at cwp = HI_LIMIT ... where the 'global'/'in' regs - * are restored. NOTE: %sp changes with cwp. - */ - mov %g7, %o7 - mov %g6, %sp - - /* Get LO_LIMIT/HI_LIMIT to know where to start & stop. Note: in - * the underflow exception, cwp is __NOT__ guaranteed to be zero. - * If the OCI debug module is enabled the reset value for LO_LIMIT - * is 2, not 1 -- so cwp can be 1 or 0. - */ - pfx 2 /* WVALID */ - rdctl %g1 - mov %g2, %g1 - pfx 0 - and %g1, 0x1f /* g1 <- LO_LIMIT */ - lsri %g2, 5 - pfx 0 - and %g2,0x1f /* g2 <- HI_LIMIT */ - - /* Set istatus so cwp = HI_LIMIT after tret - */ - movi %g5, 0x1f - lsli %g5, 4 - not %g5 /* mask to clr cwp */ - pfx 1 /* istatus */ - rdctl %g0 - and %g0, %g5 /* clear cwp field */ - - mov %g4, %g2 - lsli %g4, 4 - or %g0, %g4 /* cwp = HI_LIMIT */ - pfx 1 - wrctl %g0 /* update istatus */ - - /* Now move up the register file, saving as we go. When loop - * is first entered, %g1 is at LO_LIMIT. - */ -0: - restore /* cwp++ */ - sts [%sp,0], %l0 /* Save "local" regs*/ - sts [%sp,1], %l1 - sts [%sp,2], %l2 - sts [%sp,3], %l3 - sts [%sp,4], %l4 - sts [%sp,5], %l5 - sts [%sp,6], %l6 - sts [%sp,7], %l7 - - sts [%sp,8], %i0 /* Save 'in' regs */ - sts [%sp,9], %i1 - sts [%sp,10], %i2 - sts [%sp,11], %i3 - sts [%sp,12], %i4 - sts [%sp,13], %i5 - sts [%sp,14], %i6 - sts [%sp,15], %i7 - - cmp %g1, %g2 /* cwp == HI_LIMIT ? */ - skps cc_ne /* if so, we're done */ - br 1f - nop /* delay slot */ - - inc %g1 /* g1 <- cwp++ */ - br 0b - nop /* delay slot */ - - /* At this point cwp = HI_LIMIT, so the global/in regs that were - * in place when the underflow occurred must be restored using - * the original stack pointer (saved in g6). - */ -1: - mov %o7, %g7 /* restore return addr */ - mov %sp, %g6 /* Restore original sp */ - - lds %g0, [%sp,0] /* Restore 'global' regs*/ - lds %g1, [%sp,1] - lds %g2, [%sp,2] - lds %g3, [%sp,3] - lds %g4, [%sp,4] - lds %g5, [%sp,5] - lds %g6, [%sp,6] - lds %g7, [%sp,7] - - lds %i0, [%sp,8] /* Restore 'in' regs*/ - lds %i1, [%sp,9] - lds %i2, [%sp,10] - lds %i3, [%sp,11] - lds %i4, [%sp,12] - lds %i5, [%sp,13] - lds %i6, [%sp,14] - lds %i7, [%sp,15] - - tret %o7 /* All done */ - -/************************************************************************* - * Register window overflow - * - * The register window overflow exception occurs whenever the highest - * valid register window is in use (cwp = HI_LIMIT) and a restore - * instruction is issued. Control is transferred to the overflow handler - * before the instruction following restore is executed. - * - * When a register window overflow exception is taken, the exception - * handler sees cwp at HI_LIMIT. - ************************************************************************/ - .text - .global _cwp_hilimit - .align 4 - -_cwp_hilimit: - - /* Save 'global'/'in' regs on the stack -- will restore when cwp - * is at LO_LIMIT. Locals don't need saving as they are going away. - */ - sts [%sp,0], %g0 /* Save "global" regs*/ - sts [%sp,1], %g1 - sts [%sp,2], %g2 - sts [%sp,3], %g3 - sts [%sp,4], %g4 - sts [%sp,5], %g5 - sts [%sp,6], %g6 - sts [%sp,7], %g7 - - sts [%sp,8], %i0 /* Save 'in' regs */ - sts [%sp,9], %i1 - sts [%sp,10], %i2 - sts [%sp,11], %i3 - sts [%sp,12], %i4 - sts [%sp,13], %i5 - sts [%sp,14], %i6 - sts [%sp,15], %i7 - - /* The current %sp must be available in global to restore regs - * saved on stack. Need return addr as well ;-) - */ - mov %g7, %o7 - mov %g6, %sp - - /* Get HI_LIMIT & LO_LIMIT - */ - pfx 2 /* WVALID */ - rdctl %g1 - mov %g2, %g1 - pfx 0 - and %g1, 0x1f /* g1 <- LO_LIMIT */ - lsri %g2, 5 - pfx 0 - and %g2,0x1f /* g2 <- HI_LIMIT */ - - /* Set istatus so cwp = LO_LIMIT after tret - */ - movi %g5, 0x1f - lsli %g5, 4 - not %g5 /* mask to clr cwp */ - pfx 1 /* istatus */ - rdctl %g0 - and %g0, %g5 /* clear cwp field */ - - mov %g4, %g1 /* g4 <- LO_LIMIT */ - lsli %g4, 4 - or %g0, %g4 /* cwp = LO_LIMIT */ - pfx 1 - wrctl %g0 /* update istatus */ - - /* Move to cwp = LO_LIMIT-1 and restore 'in' regs. - */ - subi %g4,(1 << 4) /* g4 <- LO_LIMIT - 1 */ - rdctl %g0 - and %g0, %g5 /* clear cwp field */ - or %g0, %g4 /* cwp = LO_LIMIT - 1 */ - wrctl %g0 /* update status */ - nop - - mov %sp, %g6 /* Restore sp */ - lds %i0, [%sp,8] /* Restore 'in' regs */ - lds %i1, [%sp,9] - lds %i2, [%sp,10] - lds %i3, [%sp,11] - lds %i4, [%sp,12] - lds %i5, [%sp,13] - lds %i6, [%sp,14] /* sp in next window */ - lds %i7, [%sp,15] - - /* Starting at LO_LIMIT-1, move up the register file, restoring - * along the way. - */ -0: - restore /* cwp++ */ - lds %l0, [%sp,0] /* Restore 'local' regs*/ - lds %l1, [%sp,1] - lds %l2, [%sp,2] - lds %l3, [%sp,3] - lds %l4, [%sp,4] - lds %l5, [%sp,5] - lds %l6, [%sp,6] - lds %l7, [%sp,7] - - lds %i0, [%sp,8] /* Restore 'in' regs */ - lds %i1, [%sp,9] - lds %i2, [%sp,10] - lds %i3, [%sp,11] - lds %i4, [%sp,12] - lds %i5, [%sp,13] - lds %i6, [%sp,14] /* sp in next window */ - lds %i7, [%sp,15] - - cmp %g1, %g2 /* cwp == HI_LIMIT ? */ - skps cc_ne /* if so, we're done */ - br 1f - nop /* delay slot */ - - inc %g1 /* cwp++ */ - br 0b - nop /* delay slot */ - - /* All windows have been updated at this point, but the globals - * still need to be restored. Go to cwp = LO_LIMIT-1 to get - * some registers to use. - */ -1: - rdctl %g0 - and %g0, %g5 /* clear cwp field */ - or %g0, %g4 /* cwp = LO_LIMIT - 1 */ - wrctl %g0 /* update status */ - nop - - /* Now there are some registers available to use in restoring - * the globals. - */ - mov %sp, %g6 - mov %o7, %g7 - - lds %g0, [%sp,0] /* Restore "global" regs*/ - lds %g1, [%sp,1] - lds %g2, [%sp,2] - lds %g3, [%sp,3] - lds %g4, [%sp,4] - lds %g5, [%sp,5] - lds %g6, [%sp,6] - lds %g7, [%sp,7] - - /* The tret moves istatus -> status. istatus was already set for - * cwp = LO_LIMIT. - */ - - tret %o7 /* done */ - -/************************************************************************* - * Default exception handler - * - * The default handler passes control to external_interrupt(). So trap - * or hardware interrupt hanlders can be installed using the familiar - * irq_install_handler(). - * - * Here, the stack is fixed-up and cwp is incremented prior to calling - * external_interrupt(). This lets the underflow and overflow handlers - * operate normally during the exception. - ************************************************************************/ - .text - .global _def_xhandler - .align 4 - -_def_xhandler: - - /* Allocate some stack space: 16 words at %sp to accomodate - * a reg window underflow, 8 words to save interrupted task's - * 'out' regs (which are now the 'in' regs), 8 words to preserve - * the 'global' regs and 3 words to save the return address, - * status and istatus. istatus must be saved in the event an - * underflow occurs in a dispatched handler. status is saved so - * a handler can access it on stack. - */ - pfx %hi((16+16+3) * 4) - subi %fp, %lo((16+16+3) * 4) - mov %sp, %fp - - /* Save the 'global' regs and the interrupted task's 'out' regs - * (our 'in' regs) along with the return addr, status & istatus. - * First 16 words are for underflow exception. - */ - rdctl %l0 /* status */ - pfx 1 /* istatus */ - rdctl %l1 - - sts [%sp,16+0], %g0 /* Save 'global' regs*/ - sts [%sp,16+1], %g1 - sts [%sp,16+2], %g2 - sts [%sp,16+3], %g3 - sts [%sp,16+4], %g4 - sts [%sp,16+5], %g5 - sts [%sp,16+6], %g6 - sts [%sp,16+7], %g7 - - sts [%sp,16+8], %i0 /* Save 'in' regs */ - sts [%sp,16+9], %i1 - sts [%sp,16+10], %i2 - sts [%sp,16+11], %i3 - sts [%sp,16+12], %i4 - sts [%sp,16+13], %i5 - sts [%sp,16+14], %i6 - sts [%sp,16+15], %i7 - - sts [%sp,16+16], %l0 /* status */ - sts [%sp,16+17], %l1 /* istatus */ - sts [%sp,16+18], %o7 /* return addr */ - - /* Move to cwp+1 ... this guarantees cwp is at or above LO_LIMIT. - * Need to set IPRI=3 and IE=1 to enable underflow exceptions. - * NOTE: only the 'out' regs have been saved ... can't touch - * the 'in' or 'local' here. - */ - restore /* cwp++ */ - rdctl %o0 /* o0 <- status */ - - pfx %hi(0x7e00) - movi %o1, %lo(0x7e00) - not %o1 - and %o0, %o1 /* clear IPRI */ - - pfx %hi(0x8600) - movi %o1, %lo(0x8600) - or %o0, %o1 /* IPRI=3, IE=1 */ - - wrctl %o0 /* o0 -> status */ - nop - - /* It's ok to call a C routine now since cwp >= LO_LIMIT, - * interrupt task's registers are/will be preserved, and - * underflow exceptions can be handled. - */ - pfx %hi(external_interrupt@h) - movi %o1, %lo(external_interrupt@h) - pfx %xhi(external_interrupt@h) - movhi %o1, %xlo(external_interrupt@h) - bgen %o0, 4+2 /* 16 * 4 */ - add %o0, %sp /* Ptr to regs */ - call %o1 - nop - - /* Move back to the exception register window, restore the 'out' - * registers, then return from exception. - */ - rdctl %o0 /* o0 <- status */ - subi %o0, 16 - wrctl %o0 /* cwp-- */ - nop - - mov %sp, %fp - lds %g0, [%sp,16+0] /* Restore 'global' regs*/ - lds %g1, [%sp,16+1] - lds %g2, [%sp,16+2] - lds %g3, [%sp,16+3] - lds %g4, [%sp,16+4] - lds %g5, [%sp,16+5] - lds %g6, [%sp,16+6] - lds %g7, [%sp,16+7] - - lds %i0, [%sp,16+8] /* Restore 'in' regs*/ - lds %i1, [%sp,16+9] - lds %i2, [%sp,16+10] - lds %i3, [%sp,16+11] - lds %i4, [%sp,16+12] - lds %i5, [%sp,16+13] - lds %i6, [%sp,16+14] - lds %i7, [%sp,16+15] - - lds %l0, [%sp,16+16] /* status */ - lds %l1, [%sp,16+17] /* istatus */ - lds %o7, [%sp,16+18] /* return addr */ - - pfx 1 - wrctl %l1 /* restore istatus */ - - pfx %hi((16+16+3) * 4) - addi %sp, %lo((16+16+3) * 4) - mov %fp, %sp - - tret %o7 /* Done */ - - -/************************************************************************* - * Timebase Timer Interrupt -- This has identical structure to above, - * but calls timer_interrupt(). Doing it this way keeps things similar - * to other architectures (e.g. ppc). - ************************************************************************/ - .text - .global _timebase_int - .align 4 - -_timebase_int: - - /* Allocate stack space. - */ - pfx %hi((16+16+3) * 4) - subi %fp, %lo((16+16+3) * 4) - mov %sp, %fp - - /* Save the 'global' regs & 'out' regs (our 'in' regs) - */ - rdctl %l0 /* status */ - pfx 1 /* istatus */ - rdctl %l1 - - sts [%sp,16+0], %g0 /* Save 'global' regs*/ - sts [%sp,16+1], %g1 - sts [%sp,16+2], %g2 - sts [%sp,16+3], %g3 - sts [%sp,16+4], %g4 - sts [%sp,16+5], %g5 - sts [%sp,16+6], %g6 - sts [%sp,16+7], %g7 - - sts [%sp,16+8], %i0 /* Save 'in' regs */ - sts [%sp,16+9], %i1 - sts [%sp,16+10], %i2 - sts [%sp,16+11], %i3 - sts [%sp,16+12], %i4 - sts [%sp,16+13], %i5 - sts [%sp,16+14], %i6 - sts [%sp,16+15], %i7 - - sts [%sp,16+16], %l0 /* status */ - sts [%sp,16+17], %l1 /* istatus */ - sts [%sp,16+18], %o7 /* return addr */ - - /* Move to cwp+1. - */ - restore /* cwp++ */ - rdctl %o0 /* o0 <- status */ - - pfx %hi(0x7e00) - movi %o1, %lo(0x7e00) - not %o1 - and %o0, %o1 /* clear IPRI */ - - pfx %hi(0x8600) - movi %o1, %lo(0x8600) - or %o0, %o1 /* IPRI=3, IE=1 */ - - wrctl %o0 /* o0 -> status */ - nop - - /* Call timer_interrupt() - */ - pfx %hi(timer_interrupt@h) - movi %o1, %lo(timer_interrupt@h) - pfx %xhi(timer_interrupt@h) - movhi %o1, %xlo(timer_interrupt@h) - bgen %o0, 4+2 /* 16 * 4 */ - add %o0, %sp /* Ptr to regs */ - call %o1 - nop - - /* Move back to the exception register window, restore the 'out' - * registers, then return from exception. - */ - rdctl %o0 /* o0 <- status */ - subi %o0, 16 - wrctl %o0 /* cwp-- */ - nop - - mov %sp, %fp - lds %g0, [%sp,16+0] /* Restore 'global' regs*/ - lds %g1, [%sp,16+1] - lds %g2, [%sp,16+2] - lds %g3, [%sp,16+3] - lds %g4, [%sp,16+4] - lds %g5, [%sp,16+5] - lds %g6, [%sp,16+6] - lds %g7, [%sp,16+7] - - lds %i0, [%sp,16+8] /* Restore 'in' regs*/ - lds %i1, [%sp,16+9] - lds %i2, [%sp,16+10] - lds %i3, [%sp,16+11] - lds %i4, [%sp,16+12] - lds %i5, [%sp,16+13] - lds %i6, [%sp,16+14] - lds %i7, [%sp,16+15] - - lds %l0, [%sp,16+16] /* status */ - lds %l1, [%sp,16+17] /* istatus */ - lds %o7, [%sp,16+18] /* return addr */ - - pfx 1 - wrctl %l1 /* restore istatus */ - - pfx %hi((16+16+3) * 4) - addi %sp, %lo((16+16+3) * 4) - mov %fp, %sp - - tret %o7 /* Done */ - -/************************************************************************* - * GDB stubs - ************************************************************************/ - .text - .global _brkpt_hw_int, _brkpt_sw_int - .align 4 - -_brkpt_hw_int: - movi %l1, 9 - pfx 3 - wrctl %l1 - pfx 4 - wrctl %l1 - -_brkpt_sw_int: - movi %l1, 9 - pfx 3 - wrctl %l1 - pfx 4 - wrctl %l1 - - tret %o7 |