diff options
Diffstat (limited to 'arch/cris/arch-v10/kernel')
-rw-r--r-- | arch/cris/arch-v10/kernel/Makefile | 18 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/crisksyms.c | 17 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/debugport.c | 560 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/dma.c | 288 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/entry.S | 978 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/fasttimer.c | 835 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/head.S | 620 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/io_interface_mux.c | 1183 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/irq.c | 236 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/kgdb.c | 1128 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/process.c | 180 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/ptrace.c | 204 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/setup.c | 107 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/shadows.c | 37 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/signal.c | 440 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/time.c | 268 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/traps.c | 134 |
17 files changed, 0 insertions, 7233 deletions
diff --git a/arch/cris/arch-v10/kernel/Makefile b/arch/cris/arch-v10/kernel/Makefile deleted file mode 100644 index 7ec04b4a285e..000000000000 --- a/arch/cris/arch-v10/kernel/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the linux kernel. -# - -extra-y := head.o - - -obj-y := entry.o traps.o shadows.o debugport.o irq.o \ - process.o setup.o signal.o traps.o time.o ptrace.o \ - dma.o io_interface_mux.o - -obj-$(CONFIG_ETRAX_KGDB) += kgdb.o -obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o -obj-$(CONFIG_MODULES) += crisksyms.o - -clean: - diff --git a/arch/cris/arch-v10/kernel/crisksyms.c b/arch/cris/arch-v10/kernel/crisksyms.c deleted file mode 100644 index e1d897ed5b37..000000000000 --- a/arch/cris/arch-v10/kernel/crisksyms.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/module.h> -#include <asm/io.h> -#include <arch/svinto.h> - -/* Export shadow registers for the CPU I/O pins */ -EXPORT_SYMBOL(genconfig_shadow); -EXPORT_SYMBOL(port_pa_data_shadow); -EXPORT_SYMBOL(port_pa_dir_shadow); -EXPORT_SYMBOL(port_pb_data_shadow); -EXPORT_SYMBOL(port_pb_dir_shadow); -EXPORT_SYMBOL(port_pb_config_shadow); -EXPORT_SYMBOL(port_g_data_shadow); - -/* Cache flush functions */ -EXPORT_SYMBOL(flush_etrax_cache); -EXPORT_SYMBOL(prepare_rx_descriptor); diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c deleted file mode 100644 index d30834d4dd7e..000000000000 --- a/arch/cris/arch-v10/kernel/debugport.c +++ /dev/null @@ -1,560 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Serialport functions for debugging - * - * Copyright (c) 2000-2007 Axis Communications AB - * - * Authors: Bjorn Wesen - * - * Exports: - * console_print_etrax(char *buf) - * int getDebugChar() - * putDebugChar(int) - * enableDebugIRQ() - * init_etrax_debug() - * - */ - -#include <linux/console.h> -#include <linux/init.h> -#include <linux/major.h> -#include <linux/delay.h> -#include <linux/tty.h> -#include <arch/svinto.h> - -extern void reset_watchdog(void); - -struct dbg_port -{ - unsigned int index; - const volatile unsigned* read; - volatile char* write; - volatile unsigned* xoff; - volatile char* baud; - volatile char* tr_ctrl; - volatile char* rec_ctrl; - unsigned long irq; - unsigned int started; - unsigned long baudrate; - unsigned char parity; - unsigned int bits; -}; - -struct dbg_port ports[]= -{ - { - 0, - R_SERIAL0_READ, - R_SERIAL0_TR_DATA, - R_SERIAL0_XOFF, - R_SERIAL0_BAUD, - R_SERIAL0_TR_CTRL, - R_SERIAL0_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser0_data, set), - 0, - 115200, - 'N', - 8 - }, - { - 1, - R_SERIAL1_READ, - R_SERIAL1_TR_DATA, - R_SERIAL1_XOFF, - R_SERIAL1_BAUD, - R_SERIAL1_TR_CTRL, - R_SERIAL1_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser1_data, set), - 0, - 115200, - 'N', - 8 - }, - { - 2, - R_SERIAL2_READ, - R_SERIAL2_TR_DATA, - R_SERIAL2_XOFF, - R_SERIAL2_BAUD, - R_SERIAL2_TR_CTRL, - R_SERIAL2_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser2_data, set), - 0, - 115200, - 'N', - 8 - }, - { - 3, - R_SERIAL3_READ, - R_SERIAL3_TR_DATA, - R_SERIAL3_XOFF, - R_SERIAL3_BAUD, - R_SERIAL3_TR_CTRL, - R_SERIAL3_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser3_data, set), - 0, - 115200, - 'N', - 8 - } -}; - -#ifdef CONFIG_ETRAX_SERIAL -extern struct tty_driver *serial_driver; -#endif - -struct dbg_port* port = -#if defined(CONFIG_ETRAX_DEBUG_PORT0) - &ports[0]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT1) - &ports[1]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT2) - &ports[2]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT3) - &ports[3]; -#else - NULL; -#endif - -static struct dbg_port* kgdb_port = -#if defined(CONFIG_ETRAX_KGDB_PORT0) - &ports[0]; -#elif defined(CONFIG_ETRAX_KGDB_PORT1) - &ports[1]; -#elif defined(CONFIG_ETRAX_KGDB_PORT2) - &ports[2]; -#elif defined(CONFIG_ETRAX_KGDB_PORT3) - &ports[3]; -#else - NULL; -#endif - -static void -start_port(struct dbg_port* p) -{ - unsigned long rec_ctrl = 0; - unsigned long tr_ctrl = 0; - - if (!p) - return; - - if (p->started) - return; - p->started = 1; - - if (p->index == 0) - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); - } - else if (p->index == 1) - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); - } - else if (p->index == 2) - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, ser2, select); - } - else - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, ser3, select); - } - - *R_GEN_CONFIG = genconfig_shadow; - - *p->xoff = - IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) | - IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) | - IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0); - - switch (p->baudrate) - { - case 0: - case 115200: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); - break; - case 1200: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz); - break; - case 2400: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz); - break; - case 4800: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz); - break; - case 9600: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz); - break; - case 19200: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz); - break; - case 38400: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz); - break; - case 57600: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz); - break; - default: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); - break; - } - - if (p->parity == 'E') { - rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); - tr_ctrl = - IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); - } else if (p->parity == 'O') { - rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); - tr_ctrl = - IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); - } else { - rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, disable); - tr_ctrl = - IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable); - } - if (p->bits == 7) - { - rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit); - tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit); - } - else - { - rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_8bit); - tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit); - } - - *p->rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) | - IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) | - IO_STATE(R_SERIAL0_REC_CTRL, sampling, middle) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) | - rec_ctrl; - - *p->tr_ctrl = - IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) | - IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) | - IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, one_bit) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, normal) | - tr_ctrl; -} - -static void -console_write_direct(struct console *co, const char *buf, unsigned int len) -{ - int i; - unsigned long flags; - - if (!port) - return; - - local_irq_save(flags); - - /* Send data */ - for (i = 0; i < len; i++) { - /* LF -> CRLF */ - if (buf[i] == '\n') { - while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) - ; - *port->write = '\r'; - } - /* Wait until transmitter is ready and send.*/ - while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) - ; - *port->write = buf[i]; - } - - /* - * Feed the watchdog, otherwise it will reset the chip during boot. - * The time to send an ordinary boot message line (10-90 chars) - * varies between 1-8ms at 115200. What makes up for the additional - * 90ms that allows the watchdog to bite? - */ - reset_watchdog(); - - local_irq_restore(flags); -} - -static void -console_write(struct console *co, const char *buf, unsigned int len) -{ - if (!port) - return; - - console_write_direct(co, buf, len); -} - -/* legacy function */ - -void -console_print_etrax(const char *buf) -{ - console_write(NULL, buf, strlen(buf)); -} - -/* Use polling to get a single character FROM the debug port */ - -int -getDebugChar(void) -{ - unsigned long readval; - - if (!kgdb_port) - return 0; - - do { - readval = *kgdb_port->read; - } while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail))); - - return (readval & IO_MASK(R_SERIAL0_READ, data_in)); -} - -/* Use polling to put a single character to the debug port */ - -void -putDebugChar(int val) -{ - if (!kgdb_port) - return; - - while (!(*kgdb_port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) - ; - *kgdb_port->write = val; -} - -/* Enable irq for receiving chars on the debug port, used by kgdb */ - -void -enableDebugIRQ(void) -{ - if (!kgdb_port) - return; - - *R_IRQ_MASK1_SET = kgdb_port->irq; - /* use R_VECT_MASK directly, since we really bypass Linux normal - * IRQ handling in kgdb anyway, we don't need to use enable_irq - */ - *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); - - *kgdb_port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); -} - -static int __init -console_setup(struct console *co, char *options) -{ - char* s; - - if (options) { - port = &ports[co->index]; - port->baudrate = 115200; - port->parity = 'N'; - port->bits = 8; - port->baudrate = simple_strtoul(options, NULL, 10); - s = options; - while(*s >= '0' && *s <= '9') - s++; - if (*s) port->parity = *s++; - if (*s) port->bits = *s++ - '0'; - port->started = 0; - start_port(0); - } - return 0; -} - - -/* This is a dummy serial device that throws away anything written to it. - * This is used when no debug output is wanted. - */ -static struct tty_driver dummy_driver; - -static int dummy_open(struct tty_struct *tty, struct file * filp) -{ - return 0; -} - -static void dummy_close(struct tty_struct *tty, struct file * filp) -{ -} - -static int dummy_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - return count; -} - -static int dummy_write_room(struct tty_struct *tty) -{ - return 8192; -} - -static const struct tty_operations dummy_ops = { - .open = dummy_open, - .close = dummy_close, - .write = dummy_write, - .write_room = dummy_write_room, -}; - -void __init -init_dummy_console(void) -{ - memset(&dummy_driver, 0, sizeof(struct tty_driver)); - dummy_driver.driver_name = "serial"; - dummy_driver.name = "ttyS"; - dummy_driver.major = TTY_MAJOR; - dummy_driver.minor_start = 68; - dummy_driver.num = 1; /* etrax100 has 4 serial ports */ - dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; - dummy_driver.subtype = SERIAL_TYPE_NORMAL; - dummy_driver.init_termios = tty_std_termios; - /* Normally B9600 default... */ - dummy_driver.init_termios.c_cflag = - B115200 | CS8 | CREAD | HUPCL | CLOCAL; - dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - dummy_driver.init_termios.c_ispeed = 115200; - dummy_driver.init_termios.c_ospeed = 115200; - - dummy_driver.ops = &dummy_ops; - if (tty_register_driver(&dummy_driver)) - panic("Couldn't register dummy serial driver\n"); -} - -static struct tty_driver* -etrax_console_device(struct console* co, int *index) -{ - if (port) - *index = port->index; - else - *index = 0; -#ifdef CONFIG_ETRAX_SERIAL - return port ? serial_driver : &dummy_driver; -#else - return &dummy_driver; -#endif -} - -static struct console ser_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : -1, - cflag : 0, - next : NULL -}; -static struct console ser0_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 0, - cflag : 0, - next : NULL -}; - -static struct console ser1_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 1, - cflag : 0, - next : NULL -}; -static struct console ser2_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 2, - cflag : 0, - next : NULL -}; -static struct console ser3_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 3, - cflag : 0, - next : NULL -}; -/* - * Register console (for printk's etc) - */ - -int __init -init_etrax_debug(void) -{ - static int first = 1; - - if (!first) { - unregister_console(&ser_console); - register_console(&ser0_console); - register_console(&ser1_console); - register_console(&ser2_console); - register_console(&ser3_console); - init_dummy_console(); - return 0; - } - - first = 0; - register_console(&ser_console); - start_port(port); -#ifdef CONFIG_ETRAX_KGDB - start_port(kgdb_port); -#endif - return 0; -} -__initcall(init_etrax_debug); diff --git a/arch/cris/arch-v10/kernel/dma.c b/arch/cris/arch-v10/kernel/dma.c deleted file mode 100644 index c68e978def05..000000000000 --- a/arch/cris/arch-v10/kernel/dma.c +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Wrapper for DMA channel allocator that updates DMA client muxing. - * Copyright 2004-2007, Axis Communications AB - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> - -#include <asm/dma.h> -#include <arch/svinto.h> -#include <arch/system.h> - -/* Macro to access ETRAX 100 registers */ -#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_STATE_(reg##_, field##_, _##val) - - -static char used_dma_channels[MAX_DMA_CHANNELS]; -static const char * used_dma_channels_users[MAX_DMA_CHANNELS]; - -int cris_request_dma(unsigned int dmanr, const char * device_id, - unsigned options, enum dma_owner owner) -{ - unsigned long flags; - unsigned long int gens; - int fail = -EINVAL; - - if (dmanr >= MAX_DMA_CHANNELS) { - printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr); - return -EINVAL; - } - - local_irq_save(flags); - if (used_dma_channels[dmanr]) { - local_irq_restore(flags); - if (options & DMA_VERBOSE_ON_ERROR) { - printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]); - } - if (options & DMA_PANIC_ON_ERROR) { - panic("request_dma error!"); - } - return -EBUSY; - } - - gens = genconfig_shadow; - - switch(owner) - { - case dma_eth: - if ((dmanr != NETWORK_TX_DMA_NBR) && - (dmanr != NETWORK_RX_DMA_NBR)) { - printk(KERN_CRIT "Invalid DMA channel for eth\n"); - goto bail; - } - break; - case dma_ser0: - if (dmanr == SER0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma6, serial0); - } else if (dmanr == SER0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma7, serial0); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser0\n"); - goto bail; - } - break; - case dma_ser1: - if (dmanr == SER1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma8, serial1); - } else if (dmanr == SER1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma9, serial1); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser1\n"); - goto bail; - } - break; - case dma_ser2: - if (dmanr == SER2_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, serial2); - } else if (dmanr == SER2_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, serial2); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser2\n"); - goto bail; - } - break; - case dma_ser3: - if (dmanr == SER3_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, serial3); - } else if (dmanr == SER3_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, serial3); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser3\n"); - goto bail; - } - break; - case dma_ata: - if (dmanr == ATA_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, ata); - } else if (dmanr == ATA_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, ata); - } else { - printk(KERN_CRIT "Invalid DMA channel for ata\n"); - goto bail; - } - break; - case dma_ext0: - if (dmanr == EXTDMA0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, extdma0); - } else if (dmanr == EXTDMA0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, extdma0); - } else { - printk(KERN_CRIT "Invalid DMA channel for ext0\n"); - goto bail; - } - break; - case dma_ext1: - if (dmanr == EXTDMA1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma6, extdma1); - } else if (dmanr == EXTDMA1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma7, extdma1); - } else { - printk(KERN_CRIT "Invalid DMA channel for ext1\n"); - goto bail; - } - break; - case dma_int6: - if (dmanr == MEM2MEM_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma7, intdma6); - } else { - printk(KERN_CRIT "Invalid DMA channel for int6\n"); - goto bail; - } - break; - case dma_int7: - if (dmanr == MEM2MEM_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma6, intdma7); - } else { - printk(KERN_CRIT "Invalid DMA channel for int7\n"); - goto bail; - } - break; - case dma_usb: - if (dmanr == USB_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma8, usb); - } else if (dmanr == USB_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma9, usb); - } else { - printk(KERN_CRIT "Invalid DMA channel for usb\n"); - goto bail; - } - break; - case dma_scsi0: - if (dmanr == SCSI0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, scsi0); - } else if (dmanr == SCSI0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, scsi0); - } else { - printk(KERN_CRIT "Invalid DMA channel for scsi0\n"); - goto bail; - } - break; - case dma_scsi1: - if (dmanr == SCSI1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, scsi1); - } else if (dmanr == SCSI1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, scsi1); - } else { - printk(KERN_CRIT "Invalid DMA channel for scsi1\n"); - goto bail; - } - break; - case dma_par0: - if (dmanr == PAR0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, par0); - } else if (dmanr == PAR0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, par0); - } else { - printk(KERN_CRIT "Invalid DMA channel for par0\n"); - goto bail; - } - break; - case dma_par1: - if (dmanr == PAR1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, par1); - } else if (dmanr == PAR1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, par1); - } else { - printk(KERN_CRIT "Invalid DMA channel for par1\n"); - goto bail; - } - break; - default: - printk(KERN_CRIT "Invalid DMA owner.\n"); - goto bail; - } - - used_dma_channels[dmanr] = 1; - used_dma_channels_users[dmanr] = device_id; - - { - volatile int i; - genconfig_shadow = gens; - *R_GEN_CONFIG = genconfig_shadow; - /* Wait 12 cycles before doing any DMA command */ - for(i = 6; i > 0; i--) - nop(); - } - fail = 0; - bail: - local_irq_restore(flags); - return fail; -} - -void cris_free_dma(unsigned int dmanr, const char * device_id) -{ - unsigned long flags; - if (dmanr >= MAX_DMA_CHANNELS) { - printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr); - return; - } - - local_irq_save(flags); - if (!used_dma_channels[dmanr]) { - printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr); - } else if (device_id != used_dma_channels_users[dmanr]) { - printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr); - } else { - switch(dmanr) - { - case 0: - *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) == - IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset)); - break; - case 1: - *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) == - IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset)); - break; - case 2: - *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) == - IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset)); - break; - case 3: - *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) == - IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset)); - break; - case 4: - *R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) == - IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset)); - break; - case 5: - *R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) == - IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset)); - break; - case 6: - *R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); - break; - case 7: - *R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) == - IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset)); - break; - case 8: - *R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) == - IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset)); - break; - case 9: - *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) == - IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset)); - break; - } - used_dma_channels[dmanr] = 0; - } - local_irq_restore(flags); -} - -EXPORT_SYMBOL(cris_request_dma); -EXPORT_SYMBOL(cris_free_dma); diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S deleted file mode 100644 index 1f066eebbd2b..000000000000 --- a/arch/cris/arch-v10/kernel/entry.S +++ /dev/null @@ -1,978 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * linux/arch/cris/entry.S - * - * Copyright (C) 2000, 2001, 2002 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - */ - -/* - * entry.S contains the system-call and fault low-level handling routines. - * - * NOTE: This code handles signal-recognition, which happens every time - * after a timer-interrupt and after each system call. - * - * Stack layout in 'ret_from_system_call': - * ptrace needs to have all regs on the stack. - * if the order here is changed, it needs to be - * updated in fork.c:copy_process, signal.c:do_signal, - * ptrace.c and ptrace.h - * - */ - -#include <linux/linkage.h> -#include <linux/sys.h> -#include <asm/unistd.h> -#include <arch/sv_addr_ag.h> -#include <asm/errno.h> -#include <asm/thread_info.h> -#include <asm/asm-offsets.h> -#include <asm/page.h> -#include <asm/pgtable.h> - - ;; functions exported from this file - - .globl system_call - .globl ret_from_intr - .globl ret_from_fork - .globl ret_from_kernel_thread - .globl resume - .globl multiple_interrupt - .globl hwbreakpoint - .globl IRQ1_interrupt - .globl spurious_interrupt - .globl hw_bp_trigs - .globl mmu_bus_fault - .globl do_sigtrap - .globl gdb_handle_breakpoint - .globl sys_call_table - - ;; below are various parts of system_call which are not in the fast-path - -#ifdef CONFIG_PREEMPT - ; Check if preemptive kernel scheduling should be done -_resume_kernel: - di - ; Load current task struct - movs.w -8192, $r0 ; THREAD_SIZE = 8192 - and.d $sp, $r0 - move.d [$r0+TI_preempt_count], $r10 ; Preemption disabled? - bne _Rexit - nop -_need_resched: - move.d [$r0+TI_flags], $r10 - btstq TIF_NEED_RESCHED, $r10 ; Check if need_resched is set - bpl _Rexit - nop - ; Ok, lets's do some preemptive kernel scheduling - jsr preempt_schedule_irq - ; Load new task struct - movs.w -8192, $r0 ; THREAD_SIZE = 8192 - and.d $sp, $r0 - ; One more time (with new task) - ba _need_resched - nop -#else -#define _resume_kernel _Rexit -#endif - - ; Called at exit from fork. schedule_tail must be called to drop - ; spinlock if CONFIG_PREEMPT -ret_from_fork: - jsr schedule_tail - ba ret_from_sys_call - nop - -ret_from_kernel_thread: - jsr schedule_tail - move.d $r2, $r10 ; argument is here - jsr $r1 ; call the payload - moveq 0, $r9 ; no syscall restarts, TYVM... - ba ret_from_sys_call - -ret_from_intr: - ;; check for resched if preemptive kernel or if we're going back to user-mode - ;; this test matches the user_regs(regs) macro - ;; we cannot simply test $dccr, because that does not necessarily - ;; reflect what mode we'll return into. - - move.d [$sp + PT_dccr], $r0; regs->dccr - btstq 8, $r0 ; U-flag - bpl _resume_kernel - ; Note that di below is in delay slot - -_resume_userspace: - di ; so need_resched and sigpending don't change - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - move.d [$r0+TI_flags], $r10 ; current->work - and.d _TIF_WORK_MASK, $r10 ; is there any work to be done on return - bne _work_pending - nop - ba _Rexit - nop - - ;; The system_call is called by a BREAK instruction, which works like - ;; an interrupt call but it stores the return PC in BRP instead of IRP. - ;; Since we dont really want to have two epilogues (one for system calls - ;; and one for interrupts) we push the contents of BRP instead of IRP in the - ;; system call prologue, to make it look like an ordinary interrupt on the - ;; stackframe. - ;; - ;; Since we can't have system calls inside interrupts, it should not matter - ;; that we don't stack IRP. - ;; - ;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,mof,srp - ;; - ;; This function looks on the _surface_ like spaghetti programming, but it's - ;; really designed so that the fast-path does not force cache-loading of non-used - ;; instructions. Only the non-common cases cause the outlined code to run.. - -system_call: - ;; stack-frame similar to the irq heads, which is reversed in ret_from_sys_call - move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame - push $srp - push $dccr - push $mof - subq 14*4, $sp ; make room for r0-r13 - movem $r13, [$sp] ; push r0-r13 - push $r10 ; push orig_r10 - clear.d [$sp=$sp-4] ; frametype == 0, normal stackframe - - movs.w -ENOSYS, $r0 - move.d $r0, [$sp+PT_r10] ; put the default return value in r10 in the frame - - ;; check if this process is syscall-traced - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - move.d [$r0+TI_flags], $r0 - btstq TIF_SYSCALL_TRACE, $r0 - bmi _syscall_trace_entry - nop - -_syscall_traced: - - ;; check for sanity in the requested syscall number - - cmpu.w NR_syscalls, $r9 - bcc ret_from_sys_call - lslq 2, $r9 ; multiply by 4, in the delay slot - - ;; as a bonus 7th parameter, we give the location on the stack - ;; of the register structure itself. some syscalls need this. - - push $sp - - ;; the parameter carrying registers r10, r11, r12 and 13 are intact. - ;; the fifth and sixth parameters (if any) was in mof and srp - ;; respectively, and we need to put them on the stack. - - push $srp - push $mof - - jsr [$r9+sys_call_table] ; actually do the system call - addq 3*4, $sp ; pop the mof, srp and regs parameters - move.d $r10, [$sp+PT_r10] ; save the return value - - moveq 1, $r9 ; "parameter" to ret_from_sys_call to show it was a sys call - - ;; fall through into ret_from_sys_call to return - -ret_from_sys_call: - ;; r9 is a parameter - if >=1 we came from a syscall, if 0, from an irq - - ;; get the current task-struct pointer (see top for defs) - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - di ; make sure need_resched and sigpending don't change - move.d [$r0+TI_flags],$r1 - and.d _TIF_ALLWORK_MASK, $r1 - bne _syscall_exit_work - nop - -_Rexit: - ;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h - pop $r10 ; frametype - bne _RBFexit ; was not CRIS_FRAME_NORMAL, handle otherwise - addq 4, $sp ; skip orig_r10, in delayslot - movem [$sp+], $r13 ; registers r0-r13 - pop $mof ; multiply overflow register - pop $dccr ; condition codes - pop $srp ; subroutine return pointer - ;; now we have a 4-word SBFS frame which we do not want to restore - ;; using RBF since it was not stacked with SBFS. instead we would like to - ;; just get the PC value to restart it with, and skip the rest of - ;; the frame. - ;; Also notice that it's important to use instructions here that - ;; keep the interrupts disabled (since we've already popped DCCR) - move [$sp=$sp+16], $p8; pop the SBFS frame from the sp - jmpu [$sp-16] ; return through the irp field in the sbfs frame - -_RBFexit: - movem [$sp+], $r13 ; registers r0-r13, in delay slot - pop $mof ; multiply overflow register - pop $dccr ; condition codes - pop $srp ; subroutine return pointer - rbf [$sp+] ; return by popping the CPU status - - ;; We get here after doing a syscall if extra work might need to be done - ;; perform syscall exit tracing if needed - -_syscall_exit_work: - ;; $r0 contains current at this point and irq's are disabled - - move.d [$r0+TI_flags], $r1 - btstq TIF_SYSCALL_TRACE, $r1 - bpl _work_pending - nop - - ei - - move.d $r9, $r1 ; preserve r9 - jsr do_syscall_trace - move.d $r1, $r9 - - ba _resume_userspace - nop - -_work_pending: - move.d [$r0+TI_flags], $r1 - btstq TIF_NEED_RESCHED, $r1 - bpl _work_notifysig ; was neither trace nor sched, must be signal/notify - nop - -_work_resched: - move.d $r9, $r1 ; preserve r9 - jsr schedule - move.d $r1, $r9 - di - - move.d [$r0+TI_flags], $r1 - and.d _TIF_WORK_MASK, $r1; ignore the syscall trace counter - beq _Rexit - nop - btstq TIF_NEED_RESCHED, $r1 - bmi _work_resched ; current->work.need_resched - nop - -_work_notifysig: - ;; deal with pending signals and notify-resume requests - - move.d $r9, $r10 ; do_notify_resume syscall/irq param - move.d $sp, $r11 ; the regs param - move.d $r1, $r12 ; the thread_info_flags parameter - jsr do_notify_resume - - ba _Rexit - nop - - ;; We get here as a sidetrack when we've entered a syscall with the - ;; trace-bit set. We need to call do_syscall_trace and then continue - ;; with the call. - -_syscall_trace_entry: - ;; PT_r10 in the frame contains -ENOSYS as required, at this point - - jsr do_syscall_trace - - ;; now re-enter the syscall code to do the syscall itself - ;; we need to restore $r9 here to contain the wanted syscall, and - ;; the other parameter-bearing registers - - move.d [$sp+PT_r9], $r9 - move.d [$sp+PT_orig_r10], $r10 ; PT_r10 is already filled with -ENOSYS. - move.d [$sp+PT_r11], $r11 - move.d [$sp+PT_r12], $r12 - move.d [$sp+PT_r13], $r13 - move [$sp+PT_mof], $mof - move [$sp+PT_srp], $srp - - ba _syscall_traced - nop - - ;; resume performs the actual task-switching, by switching stack pointers - ;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct - ;; returns old current in r10 - ;; - ;; TODO: see the i386 version. The switch_to which calls resume in our version - ;; could really be an inline asm of this. - -resume: - push $srp ; we keep the old/new PC on the stack - add.d $r12, $r10 ; r10 = current tasks tss - move $dccr, [$r10+THREAD_dccr]; save irq enable state - di - - move $usp, [$r10+ THREAD_usp] ; save user-mode stackpointer - - ;; See copy_thread for the reason why register R9 is saved. - subq 10*4, $sp - movem $r9, [$sp] ; save non-scratch registers and R9. - - move.d $sp, [$r10+THREAD_ksp] ; save the kernel stack pointer for the old task - move.d $sp, $r10 ; return last running task in r10 - and.d -8192, $r10 ; get thread_info from stackpointer - move.d [$r10+TI_task], $r10 ; get task - add.d $r12, $r11 ; find the new tasks tss - move.d [$r11+THREAD_ksp], $sp ; switch into the new stackframe by restoring kernel sp - - movem [$sp+], $r9 ; restore non-scratch registers and R9. - - move [$r11+THREAD_usp], $usp ; restore user-mode stackpointer - - move [$r11+THREAD_dccr], $dccr ; restore irq enable status - jump [$sp+] ; restore PC - - ;; This is the MMU bus fault handler. - ;; It needs to stack the CPU status and overall is different - ;; from the other interrupt handlers. - -mmu_bus_fault: - ;; For refills we try to do a quick page table lookup. If it is - ;; a real fault we let the mm subsystem handle it. - - ;; the first longword in the sbfs frame was the interrupted PC - ;; which fits nicely with the "IRP" slot in pt_regs normally used to - ;; contain the return address. used by Oops to print kernel errors. - sbfs [$sp=$sp-16] ; push the internal CPU status - push $dccr - di - subq 2*4, $sp - movem $r1, [$sp] - move.d [R_MMU_CAUSE], $r1 - ;; ETRAX 100LX TR89 bugfix: if the second half of an unaligned - ;; write causes a MMU-fault, it will not be restarted correctly. - ;; This could happen if a write crosses a page-boundary and the - ;; second page is not yet COW'ed or even loaded. The workaround - ;; is to clear the unaligned bit in the CPU status record, so - ;; that the CPU will rerun both the first and second halves of - ;; the instruction. This will not have any sideeffects unless - ;; the first half goes to any device or memory that can't be - ;; written twice, and which is mapped through the MMU. - ;; - ;; We only need to do this for writes. - btstq 8, $r1 ; Write access? - bpl 1f - nop - move.d [$sp+16], $r0 ; Clear unaligned bit in csrinstr - and.d ~(1<<5), $r0 - move.d $r0, [$sp+16] -1: btstq 12, $r1 ; Refill? - bpl 2f - lsrq 24, $r1 ; Get PGD index (bit 24-31) - move.d [current_pgd], $r0 ; PGD for the current process - move.d [$r0+$r1.d], $r0 ; Get PMD - beq 2f - nop - and.w PAGE_MASK, $r0 ; Remove PMD flags - move.d [R_MMU_CAUSE], $r1 - lsrq PAGE_SHIFT, $r1 - and.d 0x7ff, $r1 ; Get PTE index into PGD (bit 13-23) - move.d [$r0+$r1.d], $r1 ; Get PTE - beq 2f - nop - ;; Store in TLB - move.d $r1, [R_TLB_LO] - ;; Return - movem [$sp+], $r1 - pop $dccr - rbf [$sp+] ; return by popping the CPU status - -2: ; PMD or PTE missing, let the mm subsystem fix it up. - movem [$sp+], $r1 - pop $dccr - - ; Ok, not that easy, pass it on to the mm subsystem - ; The MMU status record is now on the stack - push $srp ; make a stackframe similar to pt_regs - push $dccr - push $mof - di - subq 14*4, $sp - movem $r13, [$sp] - push $r10 ; dummy orig_r10 - moveq 1, $r10 - push $r10 ; frametype == 1, BUSFAULT frame type - - move.d $sp, $r10 ; pt_regs argument to handle_mmu_bus_fault - - jsr handle_mmu_bus_fault ; in arch/cris/arch-v10/mm/fault.c - - ;; now we need to return through the normal path, we cannot just - ;; do the RBFexit since we might have killed off the running - ;; process due to a SEGV, scheduled due to a page blocking or - ;; whatever. - - moveq 0, $r9 ; busfault is equivalent to an irq - - ba ret_from_intr - nop - - ;; special handlers for breakpoint and NMI -hwbreakpoint: - push $dccr - di - push $r10 - push $r11 - move.d [hw_bp_trig_ptr],$r10 - move $brp,$r11 - move.d $r11,[$r10+] - move.d $r10,[hw_bp_trig_ptr] -1: pop $r11 - pop $r10 - pop $dccr - retb - nop - -IRQ1_interrupt: - ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! - move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame - push $srp - push $dccr - push $mof - di - subq 14*4, $sp - movem $r13, [$sp] - push $r10 ; push orig_r10 - clear.d [$sp=$sp-4] ; frametype == 0, normal frame - - ;; If there is a glitch on the NMI pin shorter than ~100ns - ;; (i.e. non-active by the time we get here) then the nmi_pin bit - ;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit - ;; is cleared by us however (when feeding the watchdog), which is why - ;; we use that bit to determine what brought us here. - - move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog? - and.d (1<<30), $r1 - bne wdog - move.d $sp, $r10 - jsr handle_nmi - setf m ; Enable NMI again - ba _Rexit ; Return the standard way - nop -wdog: -#if defined(CONFIG_ETRAX_WATCHDOG) -;; Check if we're waiting for reset to happen, as signalled by -;; hard_reset_now setting cause_of_death to a magic value. If so, just -;; get stuck until reset happens. - .comm cause_of_death, 4 ;; Don't declare this anywhere. - move.d [cause_of_death], $r10 - cmp.d 0xbedead, $r10 -_killed_by_death: - beq _killed_by_death - nop - -;; We'll see this in ksymoops dumps. -Watchdog_bite: - -#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY - ;; We just restart the watchdog here to be sure we dont get - ;; hit while printing the watchdogmsg below - ;; This restart is compatible with the rest of the C-code, so - ;; the C-code can keep restarting the watchdog after this point. - ;; The non-NICE_DOGGY code below though, disables the possibility - ;; to restart since it changes the watchdog key, to avoid any - ;; buggy loops etc. keeping the watchdog alive after this. - jsr reset_watchdog -#else - -;; We need to extend the 3.3ms after the NMI at watchdog bite, so we have -;; time for an oops-dump over a 115k2 serial wire. Another 100ms should do. - -;; Change the watchdog key to an arbitrary 3-bit value and restart the -;; watchdog. -#define WD_INIT 2 - moveq IO_FIELD (R_WATCHDOG, key, WD_INIT), $r10 - move.d R_WATCHDOG, $r11 - - move.d $r10, [$r11] - moveq IO_FIELD (R_WATCHDOG, key, \ - IO_EXTRACT (R_WATCHDOG, key, \ - IO_MASK (R_WATCHDOG, key)) \ - ^ WD_INIT) \ - | IO_STATE (R_WATCHDOG, enable, start), $r10 - move.d $r10, [$r11] - -#endif - -;; Note that we don't do "setf m" here (or after two necessary NOPs), -;; since *not* doing that saves us from re-entrancy checks. We don't want -;; to get here again due to possible subsequent NMIs; we want the watchdog -;; to reset us. - - move.d _watchdogmsg,$r10 - jsr printk - - move.d $sp, $r10 - jsr watchdog_bite_hook - -;; This nop is here so we see the "Watchdog_bite" label in ksymoops dumps -;; rather than "spurious_interrupt". - nop -;; At this point we drop down into spurious_interrupt, which will do a -;; hard reset. - - .section .rodata,"a" -_watchdogmsg: - .ascii "Oops: bitten by watchdog\n\0" - .previous - -#endif /* CONFIG_ETRAX_WATCHDOG */ - -spurious_interrupt: - di - jump hard_reset_now - - ;; this handles the case when multiple interrupts arrive at the same time - ;; we jump to the first set interrupt bit in a priority fashion - ;; the hardware will call the unserved interrupts after the handler finishes - -multiple_interrupt: - ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! - move $irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame - push $srp - push $dccr - push $mof - di - subq 14*4, $sp - movem $r13, [$sp] - push $r10 ; push orig_r10 - clear.d [$sp=$sp-4] ; frametype == 0, normal frame - - move.d $sp, $r10 - jsr do_multiple_IRQ - - jump ret_from_intr - -do_sigtrap: - ;; - ;; SIGTRAP the process that executed the break instruction. - ;; Make a frame that Rexit in entry.S expects. - ;; - move $brp, [$sp=$sp-16] ; Push BRP while faking a cpu status record. - push $srp ; Push subroutine return pointer. - push $dccr ; Push condition codes. - push $mof ; Push multiply overflow reg. - di ; Need to disable irq's at this point. - subq 14*4, $sp ; Make room for r0-r13. - movem $r13, [$sp] ; Push the r0-r13 registers. - push $r10 ; Push orig_r10. - clear.d [$sp=$sp-4] ; Frametype - this is a normal stackframe. - - movs.w -8192,$r9 ; THREAD_SIZE == 8192 - and.d $sp, $r9 - move.d [$r9+TI_task], $r10 - move.d [$r10+TASK_pid], $r10 ; current->pid as arg1. - moveq 5, $r11 ; SIGTRAP as arg2. - jsr sys_kill - jump ret_from_intr ; Use the return routine for interrupts. - -gdb_handle_breakpoint: - push $dccr - push $r0 -#ifdef CONFIG_ETRAX_KGDB - move $dccr, $r0 ; U-flag not affected by previous insns. - btstq 8, $r0 ; Test the U-flag. - bmi _ugdb_handle_breakpoint ; Go to user mode debugging. - nop ; Empty delay slot (cannot pop r0 here). - pop $r0 ; Restore r0. - ba kgdb_handle_breakpoint ; Go to kernel debugging. - pop $dccr ; Restore dccr in delay slot. -#endif - -_ugdb_handle_breakpoint: - move $brp, $r0 ; Use r0 temporarily for calculation. - subq 2, $r0 ; Set to address of previous instruction. - move $r0, $brp - pop $r0 ; Restore r0. - ba do_sigtrap ; SIGTRAP the offending process. - pop $dccr ; Restore dccr in delay slot. - - .data - -hw_bp_trigs: - .space 64*4 -hw_bp_trig_ptr: - .dword hw_bp_trigs - - .section .rodata,"a" -sys_call_table: - .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ - .long sys_exit - .long sys_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown16 - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid16 - .long sys_getuid16 - .long sys_stime /* 25 */ - .long sys_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid16 - .long sys_getgid16 - .long sys_signal - .long sys_geteuid16 - .long sys_getegid16 /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys( */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_ni_syscall /* old sys_olduname holder */ - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid16 /* 70 */ - .long sys_setregid16 - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups16 /* 80 */ - .long sys_setgroups16 - .long sys_select /* was old_select in Linux/E100 */ - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long sys_old_readdir - .long sys_old_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown16 /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ni_syscall /* sys_ioperm in i386 */ - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_ni_syscall /* old sys_uname holder */ - .long sys_ni_syscall /* 110 */ /* sys_iopl in i386 */ - .long sys_vhangup - .long sys_ni_syscall /* old "idle" system call */ - .long sys_ni_syscall /* vm86old in i386 */ - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc - .long sys_fsync - .long sys_sigreturn - .long sys_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall /* sys_modify_ldt */ - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old "create_module" */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* 130: old "get_kernel_syms" */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 - .long sys_llseek /* 140 */ - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .long sys_mlock /* 150 */ - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam - .long sys_sched_getparam /* 155 */ - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid16 - .long sys_getresuid16 /* 165 */ - .long sys_ni_syscall /* sys_vm86 */ - .long sys_ni_syscall /* Old sys_query_module */ - .long sys_poll - .long sys_ni_syscall /* old nfsservctl */ - .long sys_setresgid16 /* 170 */ - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask /* 175 */ - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread64 /* 180 */ - .long sys_pwrite64 - .long sys_chown16 - .long sys_getcwd - .long sys_capget - .long sys_capset /* 185 */ - .long sys_sigaltstack - .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ - .long sys_vfork /* 190 */ - .long sys_getrlimit - .long sys_mmap2 /* mmap_pgoff */ - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_lchown - .long sys_getuid - .long sys_getgid /* 200 */ - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid - .long sys_getgroups /* 205 */ - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid - .long sys_setresgid /* 210 */ - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - .long sys_getdents64 /* 220 */ - .long sys_fcntl64 - .long sys_ni_syscall /* reserved for TUX */ - .long sys_ni_syscall - .long sys_gettid - .long sys_readahead /* 225 */ - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr /* 230 */ - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr /* 235 */ - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 - .long sys_futex /* 240 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_ni_syscall /* sys_set_thread_area */ - .long sys_ni_syscall /* sys_get_thread_area */ - .long sys_io_setup /* 245 */ - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 /* 250 */ - .long sys_ni_syscall - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl /* 255 */ - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime /* 260 */ - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime /* 265 */ - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill /* 270 */ - .long sys_utimes - .long sys_fadvise64_64 - .long sys_ni_syscall /* sys_vserver */ - .long sys_ni_syscall /* sys_mbind */ - .long sys_ni_syscall /* 275 sys_get_mempolicy */ - .long sys_ni_syscall /* sys_set_mempolicy */ - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 280 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_ni_syscall - .long sys_waitid - .long sys_ni_syscall /* 285 */ /* available */ - .long sys_add_key - .long sys_request_key - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get /* 290 */ - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_migrate_pages - .long sys_openat /* 295 */ - .long sys_mkdirat - .long sys_mknodat - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 /* 300 */ - .long sys_unlinkat - .long sys_renameat - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat /* 305 */ - .long sys_fchmodat - .long sys_faccessat - .long sys_pselect6 - .long sys_ppoll - .long sys_unshare /* 310 */ - .long sys_set_robust_list - .long sys_get_robust_list - .long sys_splice - .long sys_sync_file_range - .long sys_tee /* 315 */ - .long sys_vmsplice - .long sys_move_pages - .long sys_getcpu - .long sys_epoll_pwait - .long sys_utimensat /* 320 */ - .long sys_signalfd - .long sys_timerfd_create - .long sys_eventfd - .long sys_fallocate - .long sys_timerfd_settime /* 325 */ - .long sys_timerfd_gettime - .long sys_signalfd4 - .long sys_eventfd2 - .long sys_epoll_create1 - .long sys_dup3 /* 330 */ - .long sys_pipe2 - .long sys_inotify_init1 - .long sys_preadv - .long sys_pwritev - .long sys_setns /* 335 */ - .long sys_name_to_handle_at - .long sys_open_by_handle_at - .long sys_rt_tgsigqueueinfo - .long sys_perf_event_open - .long sys_recvmmsg /* 340 */ - .long sys_accept4 - .long sys_fanotify_init - .long sys_fanotify_mark - .long sys_prlimit64 - .long sys_clock_adjtime /* 345 */ - .long sys_syncfs - .long sys_sendmmsg - .long sys_process_vm_readv - .long sys_process_vm_writev - .long sys_kcmp /* 350 */ - .long sys_finit_module - .long sys_sched_setattr - .long sys_sched_getattr - .long sys_renameat2 - .long sys_seccomp /* 355 */ - .long sys_getrandom - .long sys_memfd_create - .long sys_bpf - .long sys_execveat - - /* - * NOTE!! This doesn't have to be exact - we just have - * to make sure we have _enough_ of the "sys_ni_syscall" - * entries. Don't panic if you notice that this hasn't - * been shrunk every time we add a new system call. - */ - - .rept NR_syscalls-(.-sys_call_table)/4 - .long sys_ni_syscall - .endr - diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c deleted file mode 100644 index 94abbff557ff..000000000000 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ /dev/null @@ -1,835 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/fasttimer.c - * - * Fast timers for ETRAX100/ETRAX100LX - * - * Copyright (C) 2000-2007 Axis Communications AB, Lund, Sweden - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/delay.h> - -#include <asm/segment.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/delay.h> - -#include <arch/svinto.h> -#include <asm/fasttimer.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - - -#define DEBUG_LOG_INCLUDED -#define FAST_TIMER_LOG -/* #define FAST_TIMER_TEST */ - -#define FAST_TIMER_SANITY_CHECKS - -#ifdef FAST_TIMER_SANITY_CHECKS -static int sanity_failed; -#endif - -#define D1(x) -#define D2(x) -#define DP(x) - -static unsigned int fast_timer_running; -static unsigned int fast_timers_added; -static unsigned int fast_timers_started; -static unsigned int fast_timers_expired; -static unsigned int fast_timers_deleted; -static unsigned int fast_timer_is_init; -static unsigned int fast_timer_ints; - -struct fast_timer *fast_timer_list = NULL; - -#ifdef DEBUG_LOG_INCLUDED -#define DEBUG_LOG_MAX 128 -static const char * debug_log_string[DEBUG_LOG_MAX]; -static unsigned long debug_log_value[DEBUG_LOG_MAX]; -static unsigned int debug_log_cnt; -static unsigned int debug_log_cnt_wrapped; - -#define DEBUG_LOG(string, value) \ -{ \ - unsigned long log_flags; \ - local_irq_save(log_flags); \ - debug_log_string[debug_log_cnt] = (string); \ - debug_log_value[debug_log_cnt] = (unsigned long)(value); \ - if (++debug_log_cnt >= DEBUG_LOG_MAX) \ - { \ - debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ - debug_log_cnt_wrapped = 1; \ - } \ - local_irq_restore(log_flags); \ -} -#else -#define DEBUG_LOG(string, value) -#endif - - -/* The frequencies for index = clkselx number in R_TIMER_CTRL */ -#define NUM_TIMER_FREQ 15 -#define MAX_USABLE_TIMER_FREQ 7 -#define MAX_DELAY_US 853333L -const unsigned long timer_freq_100[NUM_TIMER_FREQ] = -{ - 3, /* 0 3333 - 853333 us */ - 6, /* 1 1666 - 426666 us */ - 12, /* 2 833 - 213333 us */ - 24, /* 3 416 - 106666 us */ - 48, /* 4 208 - 53333 us */ - 96, /* 5 104 - 26666 us */ - 192, /* 6 52 - 13333 us */ - 384, /* 7 26 - 6666 us */ - 576, - 1152, - 2304, - 4608, - 9216, - 18432, - 62500, - /* 15 = cascade */ -}; -#define NUM_TIMER_STATS 16 -#ifdef FAST_TIMER_LOG -struct fast_timer timer_added_log[NUM_TIMER_STATS]; -struct fast_timer timer_started_log[NUM_TIMER_STATS]; -struct fast_timer timer_expired_log[NUM_TIMER_STATS]; -#endif - -int timer_div_settings[NUM_TIMER_STATS]; -int timer_freq_settings[NUM_TIMER_STATS]; -int timer_delay_settings[NUM_TIMER_STATS]; - -/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ -inline void do_gettimeofday_fast(struct fasttime_t *tv) -{ - tv->tv_jiff = jiffies; - tv->tv_usec = GET_JIFFIES_USEC(); -} - -inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1) -{ - /* Compare jiffies. Takes care of wrapping */ - if (time_before(t0->tv_jiff, t1->tv_jiff)) - return -1; - else if (time_after(t0->tv_jiff, t1->tv_jiff)) - return 1; - - /* Compare us */ - if (t0->tv_usec < t1->tv_usec) - return -1; - else if (t0->tv_usec > t1->tv_usec) - return 1; - return 0; -} - -inline void start_timer1(unsigned long delay_us) -{ - int freq_index = 0; /* This is the lowest resolution */ - unsigned long upper_limit = MAX_DELAY_US; - - unsigned long div; - /* Start/Restart the timer to the new shorter value */ - /* t = 1/freq = 1/19200 = 53us - * T=div*t, div = T/t = delay_us*freq/1000000 - */ -#if 1 /* Adaptive timer settings */ - while (delay_us < upper_limit && freq_index < MAX_USABLE_TIMER_FREQ) - { - freq_index++; - upper_limit >>= 1; /* Divide by 2 using shift */ - } - if (freq_index > 0) - { - freq_index--; - } -#else - freq_index = 6; -#endif - div = delay_us * timer_freq_100[freq_index]/10000; - if (div < 2) - { - /* Maybe increase timer freq? */ - div = 2; - } - if (div > 255) - { - div = 0; /* This means 256, the max the timer takes */ - /* If a longer timeout than the timer can handle is used, - * then we must restart it when it goes off. - */ - } - - timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = div; - timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index; - timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; - - D1(printk(KERN_DEBUG "start_timer1 : %d us freq: %i div: %i\n", - delay_us, freq_index, div)); - /* Clear timer1 irq */ - *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); - - /* Set timer values */ - *R_TIMER_CTRL = r_timer_ctrl_shadow = - (r_timer_ctrl_shadow & - ~IO_MASK(R_TIMER_CTRL, timerdiv1) & - ~IO_MASK(R_TIMER_CTRL, tm1) & - ~IO_MASK(R_TIMER_CTRL, clksel1)) | - IO_FIELD(R_TIMER_CTRL, timerdiv1, div) | - IO_STATE(R_TIMER_CTRL, tm1, stop_ld) | - IO_FIELD(R_TIMER_CTRL, clksel1, freq_index ); /* 6=c19k2Hz */ - - /* Ack interrupt */ - *R_TIMER_CTRL = r_timer_ctrl_shadow | - IO_STATE(R_TIMER_CTRL, i1, clr); - - /* Start timer */ - *R_TIMER_CTRL = r_timer_ctrl_shadow = - (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) | - IO_STATE(R_TIMER_CTRL, tm1, run); - - /* Enable timer1 irq */ - *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set); - fast_timers_started++; - fast_timer_running = 1; -} - -/* In version 1.4 this function takes 27 - 50 us */ -void start_one_shot_timer(struct fast_timer *t, - fast_timer_function_type *function, - unsigned long data, - unsigned long delay_us, - const char *name) -{ - unsigned long flags; - struct fast_timer *tmp; - - D1(printk("sft %s %d us\n", name, delay_us)); - - local_irq_save(flags); - - do_gettimeofday_fast(&t->tv_set); - tmp = fast_timer_list; - -#ifdef FAST_TIMER_SANITY_CHECKS - /* Check so this is not in the list already... */ - while (tmp != NULL) { - if (tmp == t) { - printk(KERN_WARNING "timer name: %s data: " - "0x%08lX already in list!\n", name, data); - sanity_failed++; - goto done; - } else - tmp = tmp->next; - } - tmp = fast_timer_list; -#endif - - t->delay_us = delay_us; - t->function = function; - t->data = data; - t->name = name; - - t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; - t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ; - if (t->tv_expires.tv_usec > 1000000) - { - t->tv_expires.tv_usec -= 1000000; - t->tv_expires.tv_jiff += HZ; - } -#ifdef FAST_TIMER_LOG - timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; -#endif - fast_timers_added++; - - /* Check if this should timeout before anything else */ - if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) - { - /* Put first in list and modify the timer value */ - t->prev = NULL; - t->next = fast_timer_list; - if (fast_timer_list) - { - fast_timer_list->prev = t; - } - fast_timer_list = t; -#ifdef FAST_TIMER_LOG - timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; -#endif - start_timer1(delay_us); - } else { - /* Put in correct place in list */ - while (tmp->next && fasttime_cmp(&t->tv_expires, - &tmp->next->tv_expires) > 0) - { - tmp = tmp->next; - } - /* Insert t after tmp */ - t->prev = tmp; - t->next = tmp->next; - if (tmp->next) - { - tmp->next->prev = t; - } - tmp->next = t; - } - - D2(printk("start_one_shot_timer: %d us done\n", delay_us)); - -done: - local_irq_restore(flags); -} /* start_one_shot_timer */ - -static inline int fast_timer_pending (const struct fast_timer * t) -{ - return (t->next != NULL) || (t->prev != NULL) || (t == fast_timer_list); -} - -static inline int detach_fast_timer (struct fast_timer *t) -{ - struct fast_timer *next, *prev; - if (!fast_timer_pending(t)) - return 0; - next = t->next; - prev = t->prev; - if (next) - next->prev = prev; - if (prev) - prev->next = next; - else - fast_timer_list = next; - fast_timers_deleted++; - return 1; -} - -int del_fast_timer(struct fast_timer * t) -{ - unsigned long flags; - int ret; - - local_irq_save(flags); - ret = detach_fast_timer(t); - t->next = t->prev = NULL; - local_irq_restore(flags); - return ret; -} /* del_fast_timer */ - - -/* Interrupt routines or functions called in interrupt context */ - -/* Timer 1 interrupt handler */ - -static irqreturn_t -timer1_handler(int irq, void *dev_id) -{ - struct fast_timer *t; - unsigned long flags; - - /* We keep interrupts disabled not only when we modify the - * fast timer list, but any time we hold a reference to a - * timer in the list, since del_fast_timer may be called - * from (another) interrupt context. Thus, the only time - * when interrupts are enabled is when calling the timer - * callback function. - */ - local_irq_save(flags); - - /* Clear timer1 irq */ - *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); - - /* First stop timer, then ack interrupt */ - /* Stop timer */ - *R_TIMER_CTRL = r_timer_ctrl_shadow = - (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) | - IO_STATE(R_TIMER_CTRL, tm1, stop_ld); - - /* Ack interrupt */ - *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr); - - fast_timer_running = 0; - fast_timer_ints++; - - t = fast_timer_list; - while (t) - { - struct fasttime_t tv; - fast_timer_function_type *f; - unsigned long d; - - /* Has it really expired? */ - do_gettimeofday_fast(&tv); - D1(printk(KERN_DEBUG "t: %is %06ius\n", - tv.tv_jiff, tv.tv_usec)); - - if (fasttime_cmp(&t->tv_expires, &tv) <= 0) - { - /* Yes it has expired */ -#ifdef FAST_TIMER_LOG - timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; -#endif - fast_timers_expired++; - - /* Remove this timer before call, since it may reuse the timer */ - if (t->prev) - { - t->prev->next = t->next; - } - else - { - fast_timer_list = t->next; - } - if (t->next) - { - t->next->prev = t->prev; - } - t->prev = NULL; - t->next = NULL; - - /* Save function callback data before enabling - * interrupts, since the timer may be removed and - * we don't know how it was allocated - * (e.g. ->function and ->data may become overwritten - * after deletion if the timer was stack-allocated). - */ - f = t->function; - d = t->data; - - if (f != NULL) { - /* Run callback with interrupts enabled. */ - local_irq_restore(flags); - f(d); - local_irq_save(flags); - } else - DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints); - } - else - { - /* Timer is to early, let's set it again using the normal routines */ - D1(printk(".\n")); - } - - if ((t = fast_timer_list) != NULL) - { - /* Start next timer.. */ - long us = 0; - struct fasttime_t tv; - - do_gettimeofday_fast(&tv); - - /* time_after_eq takes care of wrapping */ - if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff)) - us = ((t->tv_expires.tv_jiff - tv.tv_jiff) * - 1000000 / HZ + t->tv_expires.tv_usec - - tv.tv_usec); - - if (us > 0) - { - if (!fast_timer_running) - { -#ifdef FAST_TIMER_LOG - timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; -#endif - start_timer1(us); - } - break; - } - else - { - /* Timer already expired, let's handle it better late than never. - * The normal loop handles it - */ - D1(printk("e! %d\n", us)); - } - } - } - - local_irq_restore(flags); - - if (!t) - { - D1(printk("t1 stop!\n")); - } - - return IRQ_HANDLED; -} - -static void wake_up_func(unsigned long data) -{ - wait_queue_head_t *sleep_wait_p = (wait_queue_head_t *)data; - wake_up(sleep_wait_p); -} - - -/* Useful API */ - -void schedule_usleep(unsigned long us) -{ - struct fast_timer t; - wait_queue_head_t sleep_wait; - init_waitqueue_head(&sleep_wait); - - D1(printk("schedule_usleep(%d)\n", us)); - start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, - "usleep"); - /* Uninterruptible sleep on the fast timer. (The condition is somewhat - * redundant since the timer is what wakes us up.) */ - wait_event(sleep_wait, !fast_timer_pending(&t)); - - D1(printk("done schedule_usleep(%d)\n", us)); -} - -#ifdef CONFIG_PROC_FS -/* This value is very much based on testing */ -#define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300) - -static int proc_fasttimer_show(struct seq_file *m, void *v) -{ - unsigned long flags; - int i = 0; - int num_to_show; - struct fasttime_t tv; - struct fast_timer *t, *nextt; - - do_gettimeofday_fast(&tv); - - seq_printf(m, "Fast timers added: %i\n", fast_timers_added); - seq_printf(m, "Fast timers started: %i\n", fast_timers_started); - seq_printf(m, "Fast timer interrupts: %i\n", fast_timer_ints); - seq_printf(m, "Fast timers expired: %i\n", fast_timers_expired); - seq_printf(m, "Fast timers deleted: %i\n", fast_timers_deleted); - seq_printf(m, "Fast timer running: %s\n", - fast_timer_running ? "yes" : "no"); - seq_printf(m, "Current time: %lu.%06lu\n", - (unsigned long)tv.tv_jiff, - (unsigned long)tv.tv_usec); -#ifdef FAST_TIMER_SANITY_CHECKS - seq_printf(m, "Sanity failed: %i\n", sanity_failed); -#endif - seq_putc(m, '\n'); - -#ifdef DEBUG_LOG_INCLUDED - { - int end_i = debug_log_cnt; - i = 0; - - if (debug_log_cnt_wrapped) - i = debug_log_cnt; - - while (i != end_i || debug_log_cnt_wrapped) { - seq_printf(m, debug_log_string[i], debug_log_value[i]); - if (seq_has_overflowed(m)) - return 0; - i = (i+1) % DEBUG_LOG_MAX; - } - } - seq_putc(m, '\n'); -#endif - - num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started: - NUM_TIMER_STATS); - seq_printf(m, "Timers started: %i\n", fast_timers_started); - for (i = 0; i < num_to_show; i++) { - int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS; - -#if 1 //ndef FAST_TIMER_LOG - seq_printf(m, "div: %i freq: %i delay: %i\n", - timer_div_settings[cur], - timer_freq_settings[cur], - timer_delay_settings[cur]); -#endif -#ifdef FAST_TIMER_LOG - t = &timer_started_log[cur]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; -#endif - } - seq_putc(m, '\n'); - -#ifdef FAST_TIMER_LOG - num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added: - NUM_TIMER_STATS); - seq_printf(m, "Timers added: %i\n", fast_timers_added); - for (i = 0; i < num_to_show; i++) { - t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - } - seq_putc(m, '\n'); - - num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired: - NUM_TIMER_STATS); - seq_printf(m, "Timers expired: %i\n", fast_timers_expired); - for (i = 0; i < num_to_show; i++) { - t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - } - seq_putc(m, '\n'); -#endif - - seq_puts(m, "Active timers:\n"); - local_irq_save(flags); - t = fast_timer_list; - while (t) { - nextt = t->next; - local_irq_restore(flags); - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - local_irq_save(flags); - if (t->next != nextt) - printk(KERN_WARNING "timer removed!\n"); - t = nextt; - } - local_irq_restore(flags); - - return 0; -} - -static int proc_fasttimer_open(struct inode *inode, struct file *file) -{ - return single_open_size(file, proc_fasttimer_show, PDE_DATA(inode), BIG_BUF_SIZE); -} - -static const struct file_operations proc_fasttimer_fops = { - .open = proc_fasttimer_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* PROC_FS */ - -#ifdef FAST_TIMER_TEST -static volatile unsigned long i = 0; -static volatile int num_test_timeout = 0; -static struct fast_timer tr[10]; -static int exp_num[10]; - -static struct fasttime_t tv_exp[100]; - -static void test_timeout(unsigned long data) -{ - do_gettimeofday_fast(&tv_exp[data]); - exp_num[data] = num_test_timeout; - - num_test_timeout++; -} - -static void test_timeout1(unsigned long data) -{ - do_gettimeofday_fast(&tv_exp[data]); - exp_num[data] = num_test_timeout; - if (data < 7) - { - start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1"); - i++; - } - num_test_timeout++; -} - -DP( -static char buf0[2000]; -static char buf1[2000]; -static char buf2[2000]; -static char buf3[2000]; -static char buf4[2000]; -); - -static char buf5[6000]; -static int j_u[1000]; - -static void fast_timer_test(void) -{ - int prev_num; - int j; - - struct fasttime_t tv, tv0, tv1, tv2; - - printk("fast_timer_test() start\n"); - do_gettimeofday_fast(&tv); - - for (j = 0; j < 1000; j++) - { - j_u[j] = GET_JIFFIES_USEC(); - } - for (j = 0; j < 100; j++) - { - do_gettimeofday_fast(&tv_exp[j]); - } - printk(KERN_DEBUG "fast_timer_test() %is %06i\n", - tv.tv_jiff, tv.tv_usec); - - for (j = 0; j < 1000; j++) - { - printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); - j += 4; - } - for (j = 0; j < 100; j++) - { - printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n", - tv_exp[j].tv_jiff, tv_exp[j].tv_usec, - tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec, - tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec, - tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec, - tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec); - j += 4; - } - do_gettimeofday_fast(&tv0); - start_one_shot_timer(&tr[i], test_timeout, i, 50000, "test0"); - DP(proc_fasttimer_read(buf0, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 70000, "test1"); - DP(proc_fasttimer_read(buf1, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 40000, "test2"); - DP(proc_fasttimer_read(buf2, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 60000, "test3"); - DP(proc_fasttimer_read(buf3, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout1, i, 55000, "test4xx"); - DP(proc_fasttimer_read(buf4, NULL, 0, 0, 0)); - i++; - do_gettimeofday_fast(&tv1); - - proc_fasttimer_read(buf5, NULL, 0, 0, 0); - - prev_num = num_test_timeout; - while (num_test_timeout < i) - { - if (num_test_timeout != prev_num) - { - prev_num = num_test_timeout; - } - } - do_gettimeofday_fast(&tv2); - printk(KERN_DEBUG "Timers started %is %06i\n", - tv0.tv_jiff, tv0.tv_usec); - printk(KERN_DEBUG "Timers started at %is %06i\n", - tv1.tv_jiff, tv1.tv_usec); - printk(KERN_DEBUG "Timers done %is %06i\n", - tv2.tv_jiff, tv2.tv_usec); - DP(printk("buf0:\n"); - printk(buf0); - printk("buf1:\n"); - printk(buf1); - printk("buf2:\n"); - printk(buf2); - printk("buf3:\n"); - printk(buf3); - printk("buf4:\n"); - printk(buf4); - ); - printk("buf5:\n"); - printk(buf5); - - printk("timers set:\n"); - for(j = 0; j<i; j++) - { - struct fast_timer *t = &tr[j]; - printk("%-10s set: %6is %06ius exp: %6is %06ius " - "data: 0x%08X func: 0x%08X\n", - t->name, - t->tv_set.tv_jiff, - t->tv_set.tv_usec, - t->tv_expires.tv_jiff, - t->tv_expires.tv_usec, - t->data, - t->function - ); - - printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", - t->delay_us, - tv_exp[j].tv_jiff, - tv_exp[j].tv_usec, - exp_num[j], - (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) * - 1000000 + tv_exp[j].tv_usec - - t->tv_expires.tv_usec); - } - proc_fasttimer_read(buf5, NULL, 0, 0, 0); - printk("buf5 after all done:\n"); - printk(buf5); - printk("fast_timer_test() done\n"); -} -#endif - - -int fast_timer_init(void) -{ - /* For some reason, request_irq() hangs when called froom time_init() */ - if (!fast_timer_is_init) - { -#if 0 && defined(FAST_TIMER_TEST) - int i; -#endif - - printk(KERN_INFO "fast_timer_init()\n"); - -#if 0 && defined(FAST_TIMER_TEST) - for (i = 0; i <= TIMER0_DIV; i++) - { - /* We must be careful not to get overflow... */ - printk("%3i %6u\n", i, timer0_value_us[i]); - } -#endif -#ifdef CONFIG_PROC_FS - proc_create("fasttimer", 0, NULL, &proc_fasttimer_fops); -#endif /* PROC_FS */ - if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0, - "fast timer int", NULL)) - { - printk("err: timer1 irq\n"); - } - fast_timer_is_init = 1; -#ifdef FAST_TIMER_TEST - printk("do test\n"); - fast_timer_test(); -#endif - } - return 0; -} -__initcall(fast_timer_init); diff --git a/arch/cris/arch-v10/kernel/head.S b/arch/cris/arch-v10/kernel/head.S deleted file mode 100644 index b260a8833903..000000000000 --- a/arch/cris/arch-v10/kernel/head.S +++ /dev/null @@ -1,620 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Head of the kernel - alter with care - * - * Copyright (C) 2000, 2001, 2010 Axis Communications AB - * - */ - -#include <linux/init.h> - -#define ASSEMBLER_MACROS_ONLY -/* The IO_* macros use the ## token concatenation operator, so - -traditional must not be used when assembling this file. */ -#include <arch/sv_addr_ag.h> - -#define CRAMFS_MAGIC 0x28cd3d45 -#define RAM_INIT_MAGIC 0x56902387 -#define COMMAND_LINE_MAGIC 0x87109563 - -#define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\ - IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) - - ;; exported symbols - - .globl etrax_irv - .globl romfs_start - .globl romfs_length - .globl romfs_in_flash - .globl swapper_pg_dir - - __HEAD - - ;; This is the entry point of the kernel. We are in supervisor mode. - ;; 0x00000000 if Flash, 0x40004000 if DRAM - ;; since etrax actually starts at address 2 when booting from flash, we - ;; put a nop (2 bytes) here first so we dont accidentally skip the di - ;; - ;; NOTICE! The registers r8 and r9 are used as parameters carrying - ;; information from the decompressor (if the kernel was compressed). - ;; They should not be used in the code below until read. - - nop - di - - ;; First setup the kseg_c mapping from where the kernel is linked - ;; to 0x40000000 (where the actual DRAM resides) otherwise - ;; we cannot do very much! See arch/cris/README.mm - ;; - ;; Notice that since we're potentially running at 0x00 or 0x40 right now, - ;; we will get a fault as soon as we enable the MMU if we dont - ;; temporarily map those segments linearily. - ;; - ;; Due to a bug in Etrax-100 LX version 1 we need to map the memory - ;; slightly different. The bug is that you can't remap bit 31 of - ;; an address. Though we can check the version register for - ;; whether the bug is present, some constants would then have to - ;; be variables, so we don't. The drawback is that you can "only" map - ;; 1G per process with CONFIG_CRIS_LOW_MAP. - -#ifdef CONFIG_CRIS_LOW_MAP - ; kseg mappings, temporary map of 0xc0->0x40 - move.d IO_FIELD (R_MMU_KBASE_HI, base_c, 4) \ - | IO_FIELD (R_MMU_KBASE_HI, base_b, 0xb) \ - | IO_FIELD (R_MMU_KBASE_HI, base_9, 9) \ - | IO_FIELD (R_MMU_KBASE_HI, base_8, 8), $r0 - move.d $r0, [R_MMU_KBASE_HI] - - ; temporary map of 0x40->0x40 and 0x60->0x40 - move.d IO_FIELD (R_MMU_KBASE_LO, base_6, 4) \ - | IO_FIELD (R_MMU_KBASE_LO, base_4, 4), $r0 - move.d $r0, [R_MMU_KBASE_LO] - - ; mmu enable, segs e,c,b,a,6,5,4,0 segment mapped - move.d IO_STATE (R_MMU_CONFIG, mmu_enable, enable) \ - | IO_STATE (R_MMU_CONFIG, inv_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, acc_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, we_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, seg_f, page) \ - | IO_STATE (R_MMU_CONFIG, seg_e, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_d, page) \ - | IO_STATE (R_MMU_CONFIG, seg_c, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_b, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_a, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_9, page) \ - | IO_STATE (R_MMU_CONFIG, seg_8, page) \ - | IO_STATE (R_MMU_CONFIG, seg_7, page) \ - | IO_STATE (R_MMU_CONFIG, seg_6, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_5, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_4, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_3, page) \ - | IO_STATE (R_MMU_CONFIG, seg_2, page) \ - | IO_STATE (R_MMU_CONFIG, seg_1, page) \ - | IO_STATE (R_MMU_CONFIG, seg_0, seg), $r0 - move.d $r0, [R_MMU_CONFIG] -#else - ; kseg mappings - move.d IO_FIELD (R_MMU_KBASE_HI, base_e, 8) \ - | IO_FIELD (R_MMU_KBASE_HI, base_c, 4) \ - | IO_FIELD (R_MMU_KBASE_HI, base_b, 0xb), $r0 - move.d $r0, [R_MMU_KBASE_HI] - - ; temporary map of 0x40->0x40 and 0x00->0x00 - move.d IO_FIELD (R_MMU_KBASE_LO, base_4, 4), $r0 - move.d $r0, [R_MMU_KBASE_LO] - - ; mmu enable, segs f,e,c,b,4,0 segment mapped - move.d IO_STATE (R_MMU_CONFIG, mmu_enable, enable) \ - | IO_STATE (R_MMU_CONFIG, inv_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, acc_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, we_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, seg_f, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_e, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_d, page) \ - | IO_STATE (R_MMU_CONFIG, seg_c, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_b, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_a, page) \ - | IO_STATE (R_MMU_CONFIG, seg_9, page) \ - | IO_STATE (R_MMU_CONFIG, seg_8, page) \ - | IO_STATE (R_MMU_CONFIG, seg_7, page) \ - | IO_STATE (R_MMU_CONFIG, seg_6, page) \ - | IO_STATE (R_MMU_CONFIG, seg_5, page) \ - | IO_STATE (R_MMU_CONFIG, seg_4, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_3, page) \ - | IO_STATE (R_MMU_CONFIG, seg_2, page) \ - | IO_STATE (R_MMU_CONFIG, seg_1, page) \ - | IO_STATE (R_MMU_CONFIG, seg_0, seg), $r0 - move.d $r0, [R_MMU_CONFIG] -#endif - - ;; Now we need to sort out the segments and their locations in RAM or - ;; Flash. The image in the Flash (or in DRAM) consists of 3 pieces: - ;; 1) kernel text, 2) kernel data, 3) ROM filesystem image - ;; But the linker has linked the kernel to expect this layout in - ;; DRAM memory: - ;; 1) kernel text, 2) kernel data, 3) kernel BSS - ;; (the location of the ROM filesystem is determined by the krom driver) - ;; If we boot this from Flash, we want to keep the ROM filesystem in - ;; the flash, we want to copy the text and need to copy the data to DRAM. - ;; But if we boot from DRAM, we need to move the ROMFS image - ;; from its position after kernel data, to after kernel BSS, BEFORE the - ;; kernel starts using the BSS area (since its "overlayed" with the ROMFS) - ;; - ;; In both cases, we start in un-cached mode, and need to jump into a - ;; cached PC after we're done fiddling around with the segments. - ;; - ;; arch/etrax100/etrax100.ld sets some symbols that define the start - ;; and end of each segment. - - ;; Check if we start from DRAM or FLASH by testing PC - - move.d $pc,$r0 - and.d 0x7fffffff,$r0 ; get rid of the non-cache bit - cmp.d 0x10000,$r0 ; arbitrary... just something above this code - blo _inflash0 - nop - - jump _inram ; enter cached ram - - ;; Jumpgate for branches. -_inflash0: - jump _inflash - - ;; Put this in a suitable section where we can reclaim storage - ;; after init. - __INIT -_inflash: -#ifdef CONFIG_ETRAX_ETHERNET - ;; Start MII clock to make sure it is running when tranceiver is reset - move.d START_ETHERNET_CLOCK, $r0 - move.d $r0, [R_NETWORK_GEN_CONFIG] -#endif - - ;; Set up waitstates etc according to kernel configuration. - move.d CONFIG_ETRAX_DEF_R_WAITSTATES, $r0 - move.d $r0, [R_WAITSTATES] - - move.d CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0 - move.d $r0, [R_BUS_CONFIG] - - ;; We need to initialze DRAM registers before we start using the DRAM - - cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? - beq _dram_init_finished - nop - -#include "../lib/dram_init.S" - -_dram_init_finished: - ;; Copy text+data to DRAM - ;; This is fragile - the calculation of r4 as the image size depends - ;; on that the labels below actually are the first and last positions - ;; in the linker-script. - ;; - ;; Then the locating of the cramfs image depends on the aforementioned - ;; image being located in the flash at 0. This is most often not true, - ;; thus the following does not work (normally there is a rescue-block - ;; between the physical start of the flash and the flash-image start, - ;; and when run with compression, the kernel is actually unpacked to - ;; DRAM and we never get here in the first place :)) - - moveq 0, $r0 ; source - move.d text_start, $r1 ; destination - move.d __vmlinux_end, $r2 ; end destination - move.d $r2, $r4 - sub.d $r1, $r4 ; r4=__vmlinux_end in flash, used below -1: move.w [$r0+], $r3 - move.w $r3, [$r1+] - cmp.d $r2, $r1 - blo 1b - nop - - ;; We keep the cramfs in the flash. - ;; There might be none, but that does not matter because - ;; we don't do anything than read some bytes here. - - moveq 0, $r0 - move.d $r0, [romfs_length] ; default if there is no cramfs - - move.d [$r4], $r0 ; cramfs_super.magic - cmp.d CRAMFS_MAGIC, $r0 - bne 1f - nop - move.d [$r4 + 4], $r0 ; cramfs_super.size - move.d $r0, [romfs_length] -#ifdef CONFIG_CRIS_LOW_MAP - add.d 0x50000000, $r4 ; add flash start in virtual memory (cached) -#else - add.d 0xf0000000, $r4 ; add flash start in virtual memory (cached) -#endif - move.d $r4, [romfs_start] -1: - moveq 1, $r0 - move.d $r0, [romfs_in_flash] - - jump _start_it ; enter code, cached this time - -_inram: - ;; Move the ROM fs to after BSS end. This assumes that the cramfs - ;; second longword contains the length of the cramfs - - moveq 0, $r0 - move.d $r0, [romfs_length] ; default if there is no cramfs - - ;; The kernel could have been unpacked to DRAM by the loader, but - ;; the cramfs image could still be in the Flash directly after the - ;; compressed kernel image. The loader passes the address of the - ;; byte succeeding the last compressed byte in the flash in the - ;; register r9 when starting the kernel. Check if r9 points to a - ;; decent cramfs image! - ;; (Notice that if this is not booted from the loader, r9 will be - ;; garbage but we do sanity checks on it, the chance that it points - ;; to a cramfs magic is small.. ) - - cmp.d 0x0ffffff8, $r9 - bhs _no_romfs_in_flash ; r9 points outside the flash area - nop - move.d [$r9], $r0 ; cramfs_super.magic - cmp.d CRAMFS_MAGIC, $r0 - bne _no_romfs_in_flash - nop - move.d [$r9+4], $r0 ; cramfs_super.length - move.d $r0, [romfs_length] -#ifdef CONFIG_CRIS_LOW_MAP - add.d 0x50000000, $r9 ; add flash start in virtual memory (cached) -#else - add.d 0xf0000000, $r9 ; add flash start in virtual memory (cached) -#endif - move.d $r9, [romfs_start] - - moveq 1, $r0 - move.d $r0, [romfs_in_flash] - - jump _start_it ; enter code, cached this time - -_no_romfs_in_flash: - - ;; Check if there is a cramfs (magic value). - ;; Notice that we check for cramfs magic value - which is - ;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does - ;; not need this mechanism anyway) - - move.d __init_end, $r0; the image will be after the end of init - move.d [$r0], $r1 ; cramfs assumes same endian on host/target - cmp.d CRAMFS_MAGIC, $r1; magic value in cramfs superblock - bne 2f - nop - - ;; Ok. What is its size ? - - move.d [$r0 + 4], $r2 ; cramfs_super.size (again, no need to swapwb) - - ;; We want to copy it to the end of the BSS - - move.d _end, $r1 - - ;; Remember values so cramfs and setup can find this info - - move.d $r1, [romfs_start] ; new romfs location - move.d $r2, [romfs_length] - - ;; We need to copy it backwards, since they can be overlapping - - add.d $r2, $r0 - add.d $r2, $r1 - - ;; Go ahead. Make my loop. - - lsrq 1, $r2 ; size is in bytes, we copy words - -1: move.w [$r0=$r0-2],$r3 - move.w $r3,[$r1=$r1-2] - subq 1, $r2 - bne 1b - nop - -2: - ;; Dont worry that the BSS is tainted. It will be cleared later. - - moveq 0, $r0 - move.d $r0, [romfs_in_flash] - - jump _start_it ; better skip the additional cramfs check below - -_start_it: - - ;; Check if kernel command line is supplied - cmp.d COMMAND_LINE_MAGIC, $r10 - bne no_command_line - nop - - move.d 256, $r13 - move.d cris_command_line, $r10 - or.d 0x80000000, $r11 ; Make it virtual -1: - move.b [$r11+], $r12 - move.b $r12, [$r10+] - subq 1, $r13 - bne 1b - nop - -no_command_line: - - ;; the kernel stack is overlayed with the task structure for each - ;; task. thus the initial kernel stack is in the same page as the - ;; init_task (but starts in the top of the page, size 8192) - move.d init_thread_union + 8192, $sp - move.d ibr_start,$r0 ; this symbol is set by the linker script - move $r0,$ibr - move.d $r0,[etrax_irv] ; set the interrupt base register and pointer - - ;; Clear BSS region, from _bss_start to _end - - move.d __bss_start, $r0 - move.d _end, $r1 -1: clear.d [$r0+] - cmp.d $r1, $r0 - blo 1b - nop - - ;; Etrax product HW genconfig setup - - moveq 0,$r0 - - ;; Select or disable serial port 2 -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - or.d IO_STATE (R_GEN_CONFIG, ser2, select),$r0 -#else - or.d IO_STATE (R_GEN_CONFIG, ser2, disable),$r0 -#endif - - ;; Init interfaces (disable them). - or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \ - | IO_STATE (R_GEN_CONFIG, ata, disable) \ - | IO_STATE (R_GEN_CONFIG, par0, disable) \ - | IO_STATE (R_GEN_CONFIG, mio, disable) \ - | IO_STATE (R_GEN_CONFIG, scsi1, disable) \ - | IO_STATE (R_GEN_CONFIG, scsi0w, disable) \ - | IO_STATE (R_GEN_CONFIG, par1, disable) \ - | IO_STATE (R_GEN_CONFIG, ser3, disable) \ - | IO_STATE (R_GEN_CONFIG, mio_w, disable) \ - | IO_STATE (R_GEN_CONFIG, usb1, disable) \ - | IO_STATE (R_GEN_CONFIG, usb2, disable) \ - | IO_STATE (R_GEN_CONFIG, par_w, disable),$r0 - - ;; Init DMA channel muxing (set to unused clients). - or.d IO_STATE (R_GEN_CONFIG, dma2, ata) \ - | IO_STATE (R_GEN_CONFIG, dma3, ata) \ - | IO_STATE (R_GEN_CONFIG, dma4, scsi1) \ - | IO_STATE (R_GEN_CONFIG, dma5, scsi1) \ - | IO_STATE (R_GEN_CONFIG, dma6, unused) \ - | IO_STATE (R_GEN_CONFIG, dma7, unused) \ - | IO_STATE (R_GEN_CONFIG, dma8, usb) \ - | IO_STATE (R_GEN_CONFIG, dma9, usb),$r0 - - - move.d $r0,[genconfig_shadow] ; init a shadow register of R_GEN_CONFIG - - move.d $r0,[R_GEN_CONFIG] - -#if 0 - moveq 4,$r0 - move.b $r0,[R_DMA_CH6_CMD] ; reset (ser0 dma out) - move.b $r0,[R_DMA_CH7_CMD] ; reset (ser0 dma in) -1: move.b [R_DMA_CH6_CMD],$r0 ; wait for reset cycle to finish - and.b 7,$r0 - cmp.b 4,$r0 - beq 1b - nop -1: move.b [R_DMA_CH7_CMD],$r0 ; wait for reset cycle to finish - and.b 7,$r0 - cmp.b 4,$r0 - beq 1b - nop -#endif - - moveq IO_STATE (R_DMA_CH8_CMD, cmd, reset),$r0 - move.b $r0,[R_DMA_CH8_CMD] ; reset (ser1 dma out) - move.b $r0,[R_DMA_CH9_CMD] ; reset (ser1 dma in) -1: move.b [R_DMA_CH8_CMD],$r0 ; wait for reset cycle to finish - andq IO_MASK (R_DMA_CH8_CMD, cmd),$r0 - cmpq IO_STATE (R_DMA_CH8_CMD, cmd, reset),$r0 - beq 1b - nop -1: move.b [R_DMA_CH9_CMD],$r0 ; wait for reset cycle to finish - andq IO_MASK (R_DMA_CH9_CMD, cmd),$r0 - cmpq IO_STATE (R_DMA_CH9_CMD, cmd, reset),$r0 - beq 1b - nop - - ;; setup port PA and PB default initial directions and data - ;; including their shadow registers - - move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR,$r0 - move.b $r0,[port_pa_dir_shadow] - move.b $r0,[R_PORT_PA_DIR] - move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA,$r0 - move.b $r0,[port_pa_data_shadow] - move.b $r0,[R_PORT_PA_DATA] - - move.b CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG,$r0 - move.b $r0,[port_pb_config_shadow] - move.b $r0,[R_PORT_PB_CONFIG] - move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR,$r0 - move.b $r0,[port_pb_dir_shadow] - move.b $r0,[R_PORT_PB_DIR] - move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA,$r0 - move.b $r0,[port_pb_data_shadow] - move.b $r0,[R_PORT_PB_DATA] - - moveq 0, $r0 - move.d $r0,[port_pb_i2c_shadow] - move.d $r0, [R_PORT_PB_I2C] - - moveq 0,$r0 - move.d $r0,[port_g_data_shadow] - move.d $r0,[R_PORT_G_DATA] - - ;; setup the serial port 0 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL0_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL0_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL0_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL0_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL0_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL0_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL0_BAUD] - - ; Set up and enable the serial0 receiver. - move.b IO_STATE (R_SERIAL0_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL0_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL0_REC_CTRL] - - ; Set up and enable the serial0 transmitter. - move.b IO_FIELD (R_SERIAL0_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL0_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL0_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL0_TR_CTRL] - - ;; setup the serial port 1 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL1_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL1_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL1_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL1_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL1_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL1_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL1_BAUD] - - ; Set up and enable the serial1 receiver. - move.b IO_STATE (R_SERIAL1_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL1_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL1_REC_CTRL] - - ; Set up and enable the serial1 transmitter. - move.b IO_FIELD (R_SERIAL1_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL1_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL1_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL1_TR_CTRL] - -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - ;; setup the serial port 2 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL2_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL2_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL2_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL2_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL2_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL2_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL2_BAUD] - - ; Set up and enable the serial2 receiver. - move.b IO_STATE (R_SERIAL2_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL2_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL2_REC_CTRL] - - ; Set up and enable the serial2 transmitter. - move.b IO_FIELD (R_SERIAL2_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL2_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL2_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL2_TR_CTRL] -#endif - -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - ;; setup the serial port 3 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL3_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL3_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL3_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL3_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL3_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL3_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL3_BAUD] - - ; Set up and enable the serial3 receiver. - move.b IO_STATE (R_SERIAL3_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL3_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL3_REC_CTRL] - - ; Set up and enable the serial3 transmitter. - move.b IO_FIELD (R_SERIAL3_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL3_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL3_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL3_TR_CTRL] -#endif - - jump start_kernel ; jump into the C-function start_kernel in init/main.c - - .data -etrax_irv: - .dword 0 -romfs_start: - .dword 0 -romfs_length: - .dword 0 -romfs_in_flash: - .dword 0 - - ;; put some special pages at the beginning of the kernel aligned - ;; to page boundaries - the kernel cannot start until after this - -#ifdef CONFIG_CRIS_LOW_MAP -swapper_pg_dir = 0x60002000 -#else -swapper_pg_dir = 0xc0002000 -#endif - - .section ".init.data", "aw" -#include "../lib/hw_settings.S" diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c deleted file mode 100644 index 13a887ce115a..000000000000 --- a/arch/cris/arch-v10/kernel/io_interface_mux.c +++ /dev/null @@ -1,1183 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* IO interface mux allocator for ETRAX100LX. - * Copyright 2004-2007, Axis Communications AB - */ - - -/* C.f. ETRAX100LX Designer's Reference chapter 19.9 */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/init.h> - -#include <arch/svinto.h> -#include <asm/io.h> -#include <arch/io_interface_mux.h> -#include <arch/system.h> - - -#define DBG(s) - -/* Macro to access ETRAX 100 registers */ -#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_STATE_(reg##_, field##_, _##val) - -enum io_if_group { - group_a = (1<<0), - group_b = (1<<1), - group_c = (1<<2), - group_d = (1<<3), - group_e = (1<<4), - group_f = (1<<5) -}; - -struct watcher -{ - void (*notify)(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available); - struct watcher *next; -}; - - -struct if_group -{ - enum io_if_group group; - /* name - the name of the group 'A' to 'F' */ - char *name; - /* used - a bit mask of all pins in the group in the order listed - * in the tables in 19.9.1 to 19.9.6. Note that no - * distinction is made between in, out and in/out pins. */ - unsigned int used; -}; - - -struct interface -{ - enum cris_io_interface ioif; - /* name - the name of the interface */ - char *name; - /* groups - OR'ed together io_if_group flags describing what pin groups - * the interface uses pins in. */ - unsigned char groups; - /* used - set when the interface is allocated. */ - unsigned char used; - char *owner; - /* group_a through group_f - bit masks describing what pins in the - * pin groups the interface uses. */ - unsigned int group_a; - unsigned int group_b; - unsigned int group_c; - unsigned int group_d; - unsigned int group_e; - unsigned int group_f; - - /* gpio_g_in, gpio_g_out, gpio_b - bit masks telling what pins in the - * GPIO ports the interface uses. This could be reconstucted using - * the group_X masks and a table of what pins the GPIO ports use, - * but that would be messy. */ - unsigned int gpio_g_in; - unsigned int gpio_g_out; - unsigned char gpio_b; -}; - -static struct if_group if_groups[6] = { - { - .group = group_a, - .name = "A", - .used = 0, - }, - { - .group = group_b, - .name = "B", - .used = 0, - }, - { - .group = group_c, - .name = "C", - .used = 0, - }, - { - .group = group_d, - .name = "D", - .used = 0, - }, - { - .group = group_e, - .name = "E", - .used = 0, - }, - { - .group = group_f, - .name = "F", - .used = 0, - } -}; - -/* The order in the array must match the order of enum - * cris_io_interface in io_interface_mux.h */ -static struct interface interfaces[] = { - /* Begin Non-multiplexed interfaces */ - { - .ioif = if_eth, - .name = "ethernet", - .groups = 0, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0, - .gpio_g_out = 0, - .gpio_b = 0 - }, - { - .ioif = if_serial_0, - .name = "serial_0", - .groups = 0, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0, - .gpio_g_out = 0, - .gpio_b = 0 - }, - /* End Non-multiplexed interfaces */ - { - .ioif = if_serial_1, - .name = "serial_1", - .groups = group_e, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x0f, - .group_f = 0, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x00 - }, - { - .ioif = if_serial_2, - .name = "serial_2", - .groups = group_b, - - .group_a = 0, - .group_b = 0x0f, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x000000c0, - .gpio_g_out = 0x000000c0, - .gpio_b = 0x00 - }, - { - .ioif = if_serial_3, - .name = "serial_3", - .groups = group_c, - - .group_a = 0, - .group_b = 0, - .group_c = 0x0f, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0xc0000000, - .gpio_g_out = 0xc0000000, - .gpio_b = 0x00 - }, - { - .ioif = if_sync_serial_1, - .name = "sync_serial_1", - .groups = group_e | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x0f, - .group_f = 0x10, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x10 - }, - { - .ioif = if_sync_serial_3, - .name = "sync_serial_3", - .groups = group_c | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0x0f, - .group_d = 0, - .group_e = 0, - .group_f = 0x80, - - .gpio_g_in = 0xc0000000, - .gpio_g_out = 0xc0000000, - .gpio_b = 0x80 - }, - { - .ioif = if_shared_ram, - .name = "shared_ram", - .groups = group_a, - - .group_a = 0x7f8ff, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x0000ff3e, - .gpio_g_out = 0x0000ff38, - .gpio_b = 0x00 - }, - { - .ioif = if_shared_ram_w, - .name = "shared_ram_w", - .groups = group_a | group_d, - - .group_a = 0x7f8ff, - .group_b = 0, - .group_c = 0, - .group_d = 0xff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00ffff3e, - .gpio_g_out = 0x00ffff38, - .gpio_b = 0x00 - }, - { - .ioif = if_par_0, - .name = "par_0", - .groups = group_a, - - .group_a = 0x7fbff, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x0000ff3e, - .gpio_g_out = 0x0000ff3e, - .gpio_b = 0x00 - }, - { - .ioif = if_par_1, - .name = "par_1", - .groups = group_d, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0x7feff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x3eff0000, - .gpio_g_out = 0x3eff0000, - .gpio_b = 0x00 - }, - { - .ioif = if_par_w, - .name = "par_w", - .groups = group_a | group_d, - - .group_a = 0x7fbff, - .group_b = 0, - .group_c = 0, - .group_d = 0xff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00ffff3e, - .gpio_g_out = 0x00ffff3e, - .gpio_b = 0x00 - }, - { - .ioif = if_scsi8_0, - .name = "scsi8_0", - .groups = group_a | group_b | group_f, - - .group_a = 0x7ffff, - .group_b = 0x0f, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0x10, - - .gpio_g_in = 0x0000ffff, - .gpio_g_out = 0x0000ffff, - .gpio_b = 0x10 - }, - { - .ioif = if_scsi8_1, - .name = "scsi8_1", - .groups = group_c | group_d | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0x0f, - .group_d = 0x7ffff, - .group_e = 0, - .group_f = 0x80, - - .gpio_g_in = 0xffff0000, - .gpio_g_out = 0xffff0000, - .gpio_b = 0x80 - }, - { - .ioif = if_scsi_w, - .name = "scsi_w", - .groups = group_a | group_b | group_d | group_f, - - .group_a = 0x7ffff, - .group_b = 0x0f, - .group_c = 0, - .group_d = 0x601ff, - .group_e = 0, - .group_f = 0x90, - - .gpio_g_in = 0x01ffffff, - .gpio_g_out = 0x07ffffff, - .gpio_b = 0x80 - }, - { - .ioif = if_ata, - .name = "ata", - .groups = group_a | group_b | group_c | group_d, - - .group_a = 0x7ffff, - .group_b = 0x0f, - .group_c = 0x0f, - .group_d = 0x7cfff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0xf9ffffff, - .gpio_g_out = 0xffffffff, - .gpio_b = 0x80 - }, - { - .ioif = if_csp, - .name = "csp", - .groups = group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0xfc, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0xfc - }, - { - .ioif = if_i2c, - .name = "i2c", - .groups = group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0x03, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x03 - }, - { - .ioif = if_usb_1, - .name = "usb_1", - .groups = group_e | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x0f, - .group_f = 0x2c, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x2c - }, - { - .ioif = if_usb_2, - .name = "usb_2", - .groups = group_d, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x33e00, - .group_f = 0, - - .gpio_g_in = 0x3e000000, - .gpio_g_out = 0x0c000000, - .gpio_b = 0x00 - }, - /* GPIO pins */ - { - .ioif = if_gpio_grp_a, - .name = "gpio_a", - .groups = group_a, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x0000ff3f, - .gpio_g_out = 0x0000ff3f, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_b, - .name = "gpio_b", - .groups = group_b, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x000000c0, - .gpio_g_out = 0x000000c0, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_c, - .name = "gpio_c", - .groups = group_c, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0xc0000000, - .gpio_g_out = 0xc0000000, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_d, - .name = "gpio_d", - .groups = group_d, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x3fff0000, - .gpio_g_out = 0x3fff0000, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_e, - .name = "gpio_e", - .groups = group_e, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_f, - .name = "gpio_f", - .groups = group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0xff - } - /* Array end */ -}; - -static struct watcher *watchers = NULL; - -/* The pins that are free to use in the GPIO ports. */ -static unsigned int gpio_in_pins = 0xffffffff; -static unsigned int gpio_out_pins = 0xffffffff; -static unsigned char gpio_pb_pins = 0xff; -static unsigned char gpio_pa_pins = 0xff; - -/* Identifiers for the owners of the GPIO pins. */ -static enum cris_io_interface gpio_pa_owners[8]; -static enum cris_io_interface gpio_pb_owners[8]; -static enum cris_io_interface gpio_pg_owners[32]; - -static int cris_io_interface_init(void); - -static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group) -{ - return (groups & ~group->group); -} - - -static struct if_group *get_group(const unsigned char groups) -{ - int i; - for (i = 0; i < ARRAY_SIZE(if_groups); i++) { - if (groups & if_groups[i].group) { - return &if_groups[i]; - } - } - return NULL; -} - - -static void notify_watchers(void) -{ - struct watcher *w = watchers; - - DBG(printk("io_interface_mux: notifying watchers\n")); - - while (NULL != w) { - w->notify((const unsigned int)gpio_in_pins, - (const unsigned int)gpio_out_pins, - (const unsigned char)gpio_pa_pins, - (const unsigned char)gpio_pb_pins); - w = w->next; - } -} - - -int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id) -{ - int set_gen_config = 0; - int set_gen_config_ii = 0; - unsigned long int gens; - unsigned long int gens_ii; - struct if_group *grp; - unsigned char group_set; - unsigned long flags; - int res = 0; - - (void)cris_io_interface_init(); - - DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id)); - - if ((ioif >= if_max_interfaces) || (ioif < 0)) { - printk(KERN_CRIT "cris_request_io_interface: Bad interface " - "%u submitted for %s\n", - ioif, - device_id); - return -EINVAL; - } - - local_irq_save(flags); - - if (interfaces[ioif].used) { - printk(KERN_CRIT "cris_io_interface: Cannot allocate interface " - "%s for %s, in use by %s\n", - interfaces[ioif].name, - device_id, - interfaces[ioif].owner); - res = -EBUSY; - goto exit; - } - - /* Check that all required pins in the used groups are free - * before allocating. */ - group_set = interfaces[ioif].groups; - while (NULL != (grp = get_group(group_set))) { - unsigned int if_group_use = 0; - - switch (grp->group) { - case group_a: - if_group_use = interfaces[ioif].group_a; - break; - case group_b: - if_group_use = interfaces[ioif].group_b; - break; - case group_c: - if_group_use = interfaces[ioif].group_c; - break; - case group_d: - if_group_use = interfaces[ioif].group_d; - break; - case group_e: - if_group_use = interfaces[ioif].group_e; - break; - case group_f: - if_group_use = interfaces[ioif].group_f; - break; - default: - BUG_ON(1); - } - - if (if_group_use & grp->used) { - printk(KERN_INFO "cris_request_io_interface: group " - "%s needed by %s not available\n", - grp->name, interfaces[ioif].name); - res = -EBUSY; - goto exit; - } - - group_set = clear_group_from_set(group_set, grp); - } - - /* Are the required GPIO pins available too? */ - if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != - interfaces[ioif].gpio_g_in) || - ((interfaces[ioif].gpio_g_out & gpio_out_pins) != - interfaces[ioif].gpio_g_out) || - ((interfaces[ioif].gpio_b & gpio_pb_pins) != - interfaces[ioif].gpio_b)) { - printk(KERN_CRIT "cris_request_io_interface: Could not get " - "required pins for interface %u\n", ioif); - res = -EBUSY; - goto exit; - } - - /* Check which registers need to be reconfigured. */ - gens = genconfig_shadow; - gens_ii = gen_config_ii_shadow; - - set_gen_config = 1; - switch (ioif) - { - /* Begin Non-multiplexed interfaces */ - case if_eth: - /* fall through */ - case if_serial_0: - set_gen_config = 0; - break; - /* End Non-multiplexed interfaces */ - case if_serial_1: - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async); - break; - case if_serial_2: - SETS(gens, R_GEN_CONFIG, ser2, select); - break; - case if_serial_3: - SETS(gens, R_GEN_CONFIG, ser3, select); - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async); - break; - case if_sync_serial_1: - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync); - break; - case if_sync_serial_3: - SETS(gens, R_GEN_CONFIG, ser3, select); - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync); - break; - case if_shared_ram: - SETS(gens, R_GEN_CONFIG, mio, select); - break; - case if_shared_ram_w: - SETS(gens, R_GEN_CONFIG, mio_w, select); - break; - case if_par_0: - SETS(gens, R_GEN_CONFIG, par0, select); - break; - case if_par_1: - SETS(gens, R_GEN_CONFIG, par1, select); - break; - case if_par_w: - SETS(gens, R_GEN_CONFIG, par0, select); - SETS(gens, R_GEN_CONFIG, par_w, select); - break; - case if_scsi8_0: - SETS(gens, R_GEN_CONFIG, scsi0, select); - break; - case if_scsi8_1: - SETS(gens, R_GEN_CONFIG, scsi1, select); - break; - case if_scsi_w: - SETS(gens, R_GEN_CONFIG, scsi0, select); - SETS(gens, R_GEN_CONFIG, scsi0w, select); - break; - case if_ata: - SETS(gens, R_GEN_CONFIG, ata, select); - break; - case if_csp: - /* fall through */ - case if_i2c: - set_gen_config = 0; - break; - case if_usb_1: - SETS(gens, R_GEN_CONFIG, usb1, select); - break; - case if_usb_2: - SETS(gens, R_GEN_CONFIG, usb2, select); - break; - case if_gpio_grp_a: - /* GPIO groups are only accounted, don't do configuration changes. */ - /* fall through */ - case if_gpio_grp_b: - /* fall through */ - case if_gpio_grp_c: - /* fall through */ - case if_gpio_grp_d: - /* fall through */ - case if_gpio_grp_e: - /* fall through */ - case if_gpio_grp_f: - set_gen_config = 0; - break; - default: - printk(KERN_INFO "cris_request_io_interface: Bad interface " - "%u submitted for %s\n", - ioif, device_id); - res = -EBUSY; - goto exit; - } - - /* All needed I/O pins and pin groups are free, allocate. */ - group_set = interfaces[ioif].groups; - while (NULL != (grp = get_group(group_set))) { - unsigned int if_group_use = 0; - - switch (grp->group) { - case group_a: - if_group_use = interfaces[ioif].group_a; - break; - case group_b: - if_group_use = interfaces[ioif].group_b; - break; - case group_c: - if_group_use = interfaces[ioif].group_c; - break; - case group_d: - if_group_use = interfaces[ioif].group_d; - break; - case group_e: - if_group_use = interfaces[ioif].group_e; - break; - case group_f: - if_group_use = interfaces[ioif].group_f; - break; - default: - BUG_ON(1); - } - grp->used |= if_group_use; - - group_set = clear_group_from_set(group_set, grp); - } - - interfaces[ioif].used = 1; - interfaces[ioif].owner = (char*)device_id; - - if (set_gen_config) { - volatile int i; - genconfig_shadow = gens; - *R_GEN_CONFIG = genconfig_shadow; - /* Wait 12 cycles before doing any DMA command */ - for(i = 6; i > 0; i--) - nop(); - } - if (set_gen_config_ii) { - gen_config_ii_shadow = gens_ii; - *R_GEN_CONFIG_II = gen_config_ii_shadow; - } - - DBG(printk(KERN_DEBUG "GPIO pins: available before: " - "g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - DBG(printk(KERN_DEBUG - "grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - interfaces[ioif].gpio_g_in, - interfaces[ioif].gpio_g_out, - interfaces[ioif].gpio_b)); - - gpio_in_pins &= ~interfaces[ioif].gpio_g_in; - gpio_out_pins &= ~interfaces[ioif].gpio_g_out; - gpio_pb_pins &= ~interfaces[ioif].gpio_b; - - DBG(printk(KERN_DEBUG "GPIO pins: available after: " - "g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - -exit: - local_irq_restore(flags); - if (res == 0) - notify_watchers(); - return res; -} - - -void cris_free_io_interface(enum cris_io_interface ioif) -{ - struct if_group *grp; - unsigned char group_set; - unsigned long flags; - - (void)cris_io_interface_init(); - - if ((ioif >= if_max_interfaces) || (ioif < 0)) { - printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n", - ioif); - return; - } - local_irq_save(flags); - if (!interfaces[ioif].used) { - printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n", - ioif); - local_irq_restore(flags); - return; - } - group_set = interfaces[ioif].groups; - while (NULL != (grp = get_group(group_set))) { - unsigned int if_group_use = 0; - - switch (grp->group) { - case group_a: - if_group_use = interfaces[ioif].group_a; - break; - case group_b: - if_group_use = interfaces[ioif].group_b; - break; - case group_c: - if_group_use = interfaces[ioif].group_c; - break; - case group_d: - if_group_use = interfaces[ioif].group_d; - break; - case group_e: - if_group_use = interfaces[ioif].group_e; - break; - case group_f: - if_group_use = interfaces[ioif].group_f; - break; - default: - BUG_ON(1); - } - - if ((grp->used & if_group_use) != if_group_use) - BUG_ON(1); - grp->used = grp->used & ~if_group_use; - - group_set = clear_group_from_set(group_set, grp); - } - interfaces[ioif].used = 0; - interfaces[ioif].owner = NULL; - - DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - interfaces[ioif].gpio_g_in, - interfaces[ioif].gpio_g_out, - interfaces[ioif].gpio_b)); - - gpio_in_pins |= interfaces[ioif].gpio_g_in; - gpio_out_pins |= interfaces[ioif].gpio_g_out; - gpio_pb_pins |= interfaces[ioif].gpio_b; - - DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - - local_irq_restore(flags); - - notify_watchers(); -} - -/* Create a bitmask from bit 0 (inclusive) to bit stop_bit - (non-inclusive). stop_bit == 0 returns 0x0 */ -static inline unsigned int create_mask(const unsigned stop_bit) -{ - /* Avoid overflow */ - if (stop_bit >= 32) { - return 0xffffffff; - } - return (1<<stop_bit)-1; -} - - -/* port can be 'a', 'b' or 'g' */ -int cris_io_interface_allocate_pins(const enum cris_io_interface ioif, - const char port, - const unsigned start_bit, - const unsigned stop_bit) -{ - unsigned int i; - unsigned int mask = 0; - unsigned int tmp_mask; - unsigned long int flags; - enum cris_io_interface *owners; - - (void)cris_io_interface_init(); - - DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n", - ioif, port, start_bit, stop_bit)); - - if (!((start_bit <= stop_bit) && - ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) || - ((port == 'g') && (stop_bit < 32))))) { - return -EINVAL; - } - - mask = create_mask(stop_bit + 1); - tmp_mask = create_mask(start_bit); - mask &= ~tmp_mask; - - DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n", - port, start_bit, stop_bit, mask)); - - local_irq_save(flags); - - switch (port) { - case 'a': - if ((gpio_pa_pins & mask) != mask) { - local_irq_restore(flags); - return -EBUSY; - } - owners = gpio_pa_owners; - gpio_pa_pins &= ~mask; - break; - case 'b': - if ((gpio_pb_pins & mask) != mask) { - local_irq_restore(flags); - return -EBUSY; - } - owners = gpio_pb_owners; - gpio_pb_pins &= ~mask; - break; - case 'g': - if (((gpio_in_pins & mask) != mask) || - ((gpio_out_pins & mask) != mask)) { - local_irq_restore(flags); - return -EBUSY; - } - owners = gpio_pg_owners; - gpio_in_pins &= ~mask; - gpio_out_pins &= ~mask; - break; - default: - local_irq_restore(flags); - return -EINVAL; - } - - for (i = start_bit; i <= stop_bit; i++) { - owners[i] = ioif; - } - local_irq_restore(flags); - - notify_watchers(); - return 0; -} - - -/* port can be 'a', 'b' or 'g' */ -int cris_io_interface_free_pins(const enum cris_io_interface ioif, - const char port, - const unsigned start_bit, - const unsigned stop_bit) -{ - unsigned int i; - unsigned int mask = 0; - unsigned int tmp_mask; - unsigned long int flags; - enum cris_io_interface *owners; - - (void)cris_io_interface_init(); - - if (!((start_bit <= stop_bit) && - ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) || - ((port == 'g') && (stop_bit < 32))))) { - return -EINVAL; - } - - mask = create_mask(stop_bit + 1); - tmp_mask = create_mask(start_bit); - mask &= ~tmp_mask; - - DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n", - port, start_bit, stop_bit, mask)); - - local_irq_save(flags); - - switch (port) { - case 'a': - if ((~gpio_pa_pins & mask) != mask) { - local_irq_restore(flags); - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); - } - owners = gpio_pa_owners; - break; - case 'b': - if ((~gpio_pb_pins & mask) != mask) { - local_irq_restore(flags); - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); - } - owners = gpio_pb_owners; - break; - case 'g': - if (((~gpio_in_pins & mask) != mask) || - ((~gpio_out_pins & mask) != mask)) { - local_irq_restore(flags); - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); - } - owners = gpio_pg_owners; - break; - default: - owners = NULL; /* Cannot happen. Shut up, gcc! */ - } - - for (i = start_bit; i <= stop_bit; i++) { - if (owners[i] != ioif) { - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins"); - } - } - - /* All was ok, change data. */ - switch (port) { - case 'a': - gpio_pa_pins |= mask; - break; - case 'b': - gpio_pb_pins |= mask; - break; - case 'g': - gpio_in_pins |= mask; - gpio_out_pins |= mask; - break; - } - - for (i = start_bit; i <= stop_bit; i++) { - owners[i] = if_unclaimed; - } - local_irq_restore(flags); - notify_watchers(); - - return 0; -} - - -int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available)) -{ - struct watcher *w; - - (void)cris_io_interface_init(); - - if (NULL == notify) { - return -EINVAL; - } - w = kmalloc(sizeof(*w), GFP_KERNEL); - if (!w) { - return -ENOMEM; - } - w->notify = notify; - w->next = watchers; - watchers = w; - - w->notify((const unsigned int)gpio_in_pins, - (const unsigned int)gpio_out_pins, - (const unsigned char)gpio_pa_pins, - (const unsigned char)gpio_pb_pins); - - return 0; -} - -void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available)) -{ - struct watcher *w = watchers, *prev = NULL; - - (void)cris_io_interface_init(); - - while ((NULL != w) && (w->notify != notify)){ - prev = w; - w = w->next; - } - if (NULL != w) { - if (NULL != prev) { - prev->next = w->next; - } else { - watchers = w->next; - } - kfree(w); - return; - } - printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify); -} - - -static int cris_io_interface_init(void) -{ - static int first = 1; - int i; - - if (!first) { - return 0; - } - first = 0; - - for (i = 0; i<8; i++) { - gpio_pa_owners[i] = if_unclaimed; - gpio_pb_owners[i] = if_unclaimed; - gpio_pg_owners[i] = if_unclaimed; - } - for (; i<32; i++) { - gpio_pg_owners[i] = if_unclaimed; - } - return 0; -} - - -module_init(cris_io_interface_init); - - -EXPORT_SYMBOL(cris_request_io_interface); -EXPORT_SYMBOL(cris_free_io_interface); -EXPORT_SYMBOL(cris_io_interface_allocate_pins); -EXPORT_SYMBOL(cris_io_interface_free_pins); -EXPORT_SYMBOL(cris_io_interface_register_watcher); -EXPORT_SYMBOL(cris_io_interface_delete_watcher); diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c deleted file mode 100644 index df11e383acdd..000000000000 --- a/arch/cris/arch-v10/kernel/irq.c +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/irq.c - * - * Copyright (c) 2000-2002 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * - * This file contains the interrupt vectors and some - * helper functions - * - */ - -#include <asm/irq.h> -#include <asm/current.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/init.h> - -#define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); -#define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); - -extern void kgdb_init(void); -extern void breakpoint(void); - -/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is - * global just so that the kernel gdb can use it. - */ - -void -set_int_vector(int n, irqvectptr addr) -{ - etrax_irv->v[n + 0x20] = (irqvectptr)addr; -} - -/* the breakpoint vector is obviously not made just like the normal irq handlers - * but needs to contain _code_ to jump to addr. - * - * the BREAK n instruction jumps to IBR + n * 8 - */ - -void -set_break_vector(int n, irqvectptr addr) -{ - unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2]; - unsigned long *jaddr = (unsigned long *)(jinstr + 1); - - /* if you don't know what this does, do not touch it! */ - - *jinstr = 0x0d3f; - *jaddr = (unsigned long)addr; - - /* 00000026 <clrlop+1a> 3f0d82000000 jump 0x82 */ -} - -/* - * This builds up the IRQ handler stubs using some ugly macros in irq.h - * - * These macros create the low-level assembly IRQ routines that do all - * the operations that are needed. They are also written to be fast - and to - * disable interrupts as little as humanly possible. - * - */ - -/* IRQ0 and 1 are special traps */ -void hwbreakpoint(void); -void IRQ1_interrupt(void); -BUILD_TIMER_IRQ(2, 0x04) /* the timer interrupt is somewhat special */ -BUILD_IRQ(3, 0x08) -BUILD_IRQ(4, 0x10) -BUILD_IRQ(5, 0x20) -BUILD_IRQ(6, 0x40) -BUILD_IRQ(7, 0x80) -BUILD_IRQ(8, 0x100) -BUILD_IRQ(9, 0x200) -BUILD_IRQ(10, 0x400) -BUILD_IRQ(11, 0x800) -BUILD_IRQ(12, 0x1000) -BUILD_IRQ(13, 0x2000) -void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ -void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ -BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */ -BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */ -BUILD_IRQ(18, 0x40000) -BUILD_IRQ(19, 0x80000) -BUILD_IRQ(20, 0x100000) -BUILD_IRQ(21, 0x200000) -BUILD_IRQ(22, 0x400000) -BUILD_IRQ(23, 0x800000) -BUILD_IRQ(24, 0x1000000) -BUILD_IRQ(25, 0x2000000) -/* IRQ 26-30 are reserved */ -BUILD_IRQ(31, 0x80000000) - -/* - * Pointers to the low-level handlers - */ - -static void (*interrupt[NR_IRQS])(void) = { - NULL, NULL, IRQ2_interrupt, IRQ3_interrupt, - IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt, - IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt, - IRQ12_interrupt, IRQ13_interrupt, NULL, NULL, - IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt, - IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt, - IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL, - IRQ31_interrupt -}; - -static void enable_crisv10_irq(struct irq_data *data) -{ - crisv10_unmask_irq(data->irq); -} - -static void disable_crisv10_irq(struct irq_data *data) -{ - crisv10_mask_irq(data->irq); -} - -static struct irq_chip crisv10_irq_type = { - .name = "CRISv10", - .irq_shutdown = disable_crisv10_irq, - .irq_enable = enable_crisv10_irq, - .irq_disable = disable_crisv10_irq, -}; - -void weird_irq(void); -void system_call(void); /* from entry.S */ -void do_sigtrap(void); /* from entry.S */ -void gdb_handle_breakpoint(void); /* from entry.S */ - -extern void do_IRQ(int irq, struct pt_regs * regs); - -/* Handle multiple IRQs */ -void do_multiple_IRQ(struct pt_regs* regs) -{ - int bit; - unsigned masked; - unsigned mask; - unsigned ethmask = 0; - - /* Get interrupts to mask and handle */ - mask = masked = *R_VECT_MASK_RD; - - /* Never mask timer IRQ */ - mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0)); - - /* - * If either ethernet interrupt (rx or tx) is active then block - * the other one too. Unblock afterwards also. - */ - if (mask & - (IO_STATE(R_VECT_MASK_RD, dma0, active) | - IO_STATE(R_VECT_MASK_RD, dma1, active))) { - ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) | - IO_MASK(R_VECT_MASK_RD, dma1)); - } - - /* Block them */ - *R_VECT_MASK_CLR = (mask | ethmask); - - /* An extra irq_enter here to prevent softIRQs to run after - * each do_IRQ. This will decrease the interrupt latency. - */ - irq_enter(); - - /* Handle all IRQs */ - for (bit = 2; bit < 32; bit++) { - if (masked & (1 << bit)) { - do_IRQ(bit, regs); - } - } - - /* This irq_exit() will trigger the soft IRQs. */ - irq_exit(); - - /* Unblock the IRQs again */ - *R_VECT_MASK_SET = (masked | ethmask); -} - -/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and - setting the irq vector table. -*/ - -void __init init_IRQ(void) -{ - int i; - - /* clear all interrupt masks */ - *R_IRQ_MASK0_CLR = 0xffffffff; - *R_IRQ_MASK1_CLR = 0xffffffff; - *R_IRQ_MASK2_CLR = 0xffffffff; - *R_VECT_MASK_CLR = 0xffffffff; - - for (i = 0; i < 256; i++) - etrax_irv->v[i] = weird_irq; - - /* Initialize IRQ handler descriptors. */ - for(i = 2; i < NR_IRQS; i++) { - irq_set_chip_and_handler(i, &crisv10_irq_type, - handle_simple_irq); - set_int_vector(i, interrupt[i]); - } - - /* the entries in the break vector contain actual code to be - executed by the associated break handler, rather than just a jump - address. therefore we need to setup a default breakpoint handler - for all breakpoints */ - for (i = 0; i < 16; i++) - set_break_vector(i, do_sigtrap); - - /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ - set_int_vector(15, multiple_interrupt); - - /* 0 and 1 which are special breakpoint/NMI traps */ - set_int_vector(0, hwbreakpoint); - set_int_vector(1, IRQ1_interrupt); - - /* and irq 14 which is the mmu bus fault handler */ - set_int_vector(14, mmu_bus_fault); - - /* setup the system-call trap, which is reached by BREAK 13 */ - set_break_vector(13, system_call); - - /* setup a breakpoint handler for debugging used for both user and - kernel mode debugging (which is why it is not inside an ifdef - CONFIG_ETRAX_KGDB) */ - set_break_vector(8, gdb_handle_breakpoint); - -#ifdef CONFIG_ETRAX_KGDB - /* setup kgdb if its enabled, and break into the debugger */ - kgdb_init(); - breakpoint(); -#endif -} diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c deleted file mode 100644 index 79b13564d15c..000000000000 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ /dev/null @@ -1,1128 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*!************************************************************************** -*! -*! FILE NAME : kgdb.c -*! -*! DESCRIPTION: Implementation of the gdb stub with respect to ETRAX 100. -*! It is a mix of arch/m68k/kernel/kgdb.c and cris_stub.c. -*! -*!--------------------------------------------------------------------------- -*! HISTORY -*! -*! DATE NAME CHANGES -*! ---- ---- ------- -*! Apr 26 1999 Hendrik Ruijter Initial version. -*! May 6 1999 Hendrik Ruijter Removed call to strlen in libc and removed -*! struct assignment as it generates calls to -*! memcpy in libc. -*! Jun 17 1999 Hendrik Ruijter Added gdb 4.18 support. 'X', 'qC' and 'qL'. -*! Jul 21 1999 Bjorn Wesen eLinux port -*! -*!--------------------------------------------------------------------------- -*! -*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN -*! -*!**************************************************************************/ -/* @(#) cris_stub.c 1.3 06/17/99 */ - -/* - * kgdb usage notes: - * ----------------- - * - * If you select CONFIG_ETRAX_KGDB in the configuration, the kernel will be - * built with different gcc flags: "-g" is added to get debug infos, and - * "-fomit-frame-pointer" is omitted to make debugging easier. Since the - * resulting kernel will be quite big (approx. > 7 MB), it will be stripped - * before compresion. Such a kernel will behave just as usually, except if - * given a "debug=<device>" command line option. (Only serial devices are - * allowed for <device>, i.e. no printers or the like; possible values are - * machine depedend and are the same as for the usual debug device, the one - * for logging kernel messages.) If that option is given and the device can be - * initialized, the kernel will connect to the remote gdb in trap_init(). The - * serial parameters are fixed to 8N1 and 115200 bps, for easyness of - * implementation. - * - * To start a debugging session, start that gdb with the debugging kernel - * image (the one with the symbols, vmlinux.debug) named on the command line. - * This file will be used by gdb to get symbol and debugging infos about the - * kernel. Next, select remote debug mode by - * target remote <device> - * where <device> is the name of the serial device over which the debugged - * machine is connected. Maybe you have to adjust the baud rate by - * set remotebaud <rate> - * or also other parameters with stty: - * shell stty ... </dev/... - * If the kernel to debug has already booted, it waited for gdb and now - * connects, and you'll see a breakpoint being reported. If the kernel isn't - * running yet, start it now. The order of gdb and the kernel doesn't matter. - * Another thing worth knowing about in the getting-started phase is how to - * debug the remote protocol itself. This is activated with - * set remotedebug 1 - * gdb will then print out each packet sent or received. You'll also get some - * messages about the gdb stub on the console of the debugged machine. - * - * If all that works, you can use lots of the usual debugging techniques on - * the kernel, e.g. inspecting and changing variables/memory, setting - * breakpoints, single stepping and so on. It's also possible to interrupt the - * debugged kernel by pressing C-c in gdb. Have fun! :-) - * - * The gdb stub is entered (and thus the remote gdb gets control) in the - * following situations: - * - * - If breakpoint() is called. This is just after kgdb initialization, or if - * a breakpoint() call has been put somewhere into the kernel source. - * (Breakpoints can of course also be set the usual way in gdb.) - * In eLinux, we call breakpoint() in init/main.c after IRQ initialization. - * - * - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel() - * are entered. All the CPU exceptions are mapped to (more or less..., see - * the hard_trap_info array below) appropriate signal, which are reported - * to gdb. die_if_kernel() is usually called after some kind of access - * error and thus is reported as SIGSEGV. - * - * - When panic() is called. This is reported as SIGABRT. - * - * - If C-c is received over the serial line, which is treated as - * SIGINT. - * - * Of course, all these signals are just faked for gdb, since there is no - * signal concept as such for the kernel. It also isn't possible --obviously-- - * to set signal handlers from inside gdb, or restart the kernel with a - * signal. - * - * Current limitations: - * - * - While the kernel is stopped, interrupts are disabled for safety reasons - * (i.e., variables not changing magically or the like). But this also - * means that the clock isn't running anymore, and that interrupts from the - * hardware may get lost/not be served in time. This can cause some device - * errors... - * - * - When single-stepping, only one instruction of the current thread is - * executed, but interrupts are allowed for that time and will be serviced - * if pending. Be prepared for that. - * - * - All debugging happens in kernel virtual address space. There's no way to - * access physical memory not mapped in kernel space, or to access user - * space. A way to work around this is using get_user_long & Co. in gdb - * expressions, but only for the current process. - * - * - Interrupting the kernel only works if interrupts are currently allowed, - * and the interrupt of the serial line isn't blocked by some other means - * (IPL too high, disabled, ...) - * - * - The gdb stub is currently not reentrant, i.e. errors that happen therein - * (e.g. accessing invalid memory) may not be caught correctly. This could - * be removed in future by introducing a stack of struct registers. - * - */ - -/* - * To enable debugger support, two things need to happen. One, a - * call to kgdb_init() is necessary in order to allow any breakpoints - * or error conditions to be properly intercepted and reported to gdb. - * Two, a breakpoint needs to be generated to begin communication. This - * is most easily accomplished by a call to breakpoint(). - * - * The following gdb commands are supported: - * - * command function Return value - * - * g return the value of the CPU registers hex data or ENN - * G set the value of the CPU registers OK or ENN - * - * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN - * - * c Resume at current address SNN ( signal NN) - * cAA..AA Continue at address AA..AA SNN - * - * s Step one instruction SNN - * sAA..AA Step one instruction from AA..AA SNN - * - * k kill - * - * ? What was the last sigval ? SNN (signal NN) - * - * bBB..BB Set baud rate to BB..BB OK or BNN, then sets - * baud rate - * - * All commands and responses are sent with a packet which includes a - * checksum. A packet consists of - * - * $<packet info>#<checksum>. - * - * where - * <packet info> :: <characters representing the command or response> - * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> - * - * When a packet is received, it is first acknowledged with either '+' or '-'. - * '+' indicates a successful transfer. '-' indicates a failed transfer. - * - * Example: - * - * Host: Reply: - * $m0,10#2a +$00010203040506070809101112131415#42 - * - */ - - -#include <linux/string.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/linkage.h> -#include <linux/reboot.h> - -#include <asm/setup.h> -#include <asm/ptrace.h> - -#include <arch/svinto.h> -#include <asm/irq.h> - -static int kgdb_started = 0; - -/********************************* Register image ****************************/ -/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's - Reference", p. 1-1, with the additional register definitions of the - ETRAX 100LX in cris-opc.h. - There are 16 general 32-bit registers, R0-R15, where R14 is the stack - pointer, SP, and R15 is the program counter, PC. - There are 16 special registers, P0-P15, where three of the unimplemented - registers, P0, P4 and P8, are reserved as zero-registers. A read from - any of these registers returns zero and a write has no effect. */ - -typedef -struct register_image -{ - /* Offset */ - unsigned int r0; /* 0x00 */ - unsigned int r1; /* 0x04 */ - unsigned int r2; /* 0x08 */ - unsigned int r3; /* 0x0C */ - unsigned int r4; /* 0x10 */ - unsigned int r5; /* 0x14 */ - unsigned int r6; /* 0x18 */ - unsigned int r7; /* 0x1C */ - unsigned int r8; /* 0x20 Frame pointer */ - unsigned int r9; /* 0x24 */ - unsigned int r10; /* 0x28 */ - unsigned int r11; /* 0x2C */ - unsigned int r12; /* 0x30 */ - unsigned int r13; /* 0x34 */ - unsigned int sp; /* 0x38 Stack pointer */ - unsigned int pc; /* 0x3C Program counter */ - - unsigned char p0; /* 0x40 8-bit zero-register */ - unsigned char vr; /* 0x41 Version register */ - - unsigned short p4; /* 0x42 16-bit zero-register */ - unsigned short ccr; /* 0x44 Condition code register */ - - unsigned int mof; /* 0x46 Multiply overflow register */ - - unsigned int p8; /* 0x4A 32-bit zero-register */ - unsigned int ibr; /* 0x4E Interrupt base register */ - unsigned int irp; /* 0x52 Interrupt return pointer */ - unsigned int srp; /* 0x56 Subroutine return pointer */ - unsigned int bar; /* 0x5A Breakpoint address register */ - unsigned int dccr; /* 0x5E Double condition code register */ - unsigned int brp; /* 0x62 Breakpoint return pointer (pc in caller) */ - unsigned int usp; /* 0x66 User mode stack pointer */ -} registers; - -/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */ -int getDebugChar (void); - -/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ -void putDebugChar (int val); - -void enableDebugIRQ (void); - -/******************** Prototypes for global functions. ***********************/ - -/* The string str is prepended with the GDB printout token and sent. */ -void putDebugString (const unsigned char *str, int length); /* used by etrax100ser.c */ - -/* The hook for both static (compiled) and dynamic breakpoints set by GDB. - ETRAX 100 specific. */ -void handle_breakpoint (void); /* used by irq.c */ - -/* The hook for an interrupt generated by GDB. ETRAX 100 specific. */ -void handle_interrupt (void); /* used by irq.c */ - -/* A static breakpoint to be used at startup. */ -void breakpoint (void); /* called by init/main.c */ - -/* From osys_int.c, executing_task contains the number of the current - executing task in osys. Does not know of object-oriented threads. */ -extern unsigned char executing_task; - -/* The number of characters used for a 64 bit thread identifier. */ -#define HEXCHARS_IN_THREAD_ID 16 - -/********************************** Packet I/O ******************************/ -/* BUFMAX defines the maximum number of characters in - inbound/outbound buffers */ -#define BUFMAX 512 - -/* Run-length encoding maximum length. Send 64 at most. */ -#define RUNLENMAX 64 - -/* The inbound/outbound buffers used in packet I/O */ -static char remcomInBuffer[BUFMAX]; -static char remcomOutBuffer[BUFMAX]; - -/* Error and warning messages. */ -enum error_type -{ - SUCCESS, E01, E02, E03, E04, E05, E06, E07, E08 -}; -static char *error_message[] = -{ - "", - "E01 Set current or general thread - H[c,g] - internal error.", - "E02 Change register content - P - cannot change read-only register.", - "E03 Thread is not alive.", /* T, not used. */ - "E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.", - "E05 Change register content - P - the register is not implemented..", - "E06 Change memory content - M - internal error.", - "E07 Change register content - P - the register is not stored on the stack", - "E08 Invalid parameter" -}; -/********************************* Register image ****************************/ -/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's - Reference", p. 1-1, with the additional register definitions of the - ETRAX 100LX in cris-opc.h. - There are 16 general 32-bit registers, R0-R15, where R14 is the stack - pointer, SP, and R15 is the program counter, PC. - There are 16 special registers, P0-P15, where three of the unimplemented - registers, P0, P4 and P8, are reserved as zero-registers. A read from - any of these registers returns zero and a write has no effect. */ -enum register_name -{ - R0, R1, R2, R3, - R4, R5, R6, R7, - R8, R9, R10, R11, - R12, R13, SP, PC, - P0, VR, P2, P3, - P4, CCR, P6, MOF, - P8, IBR, IRP, SRP, - BAR, DCCR, BRP, USP -}; - -/* The register sizes of the registers in register_name. An unimplemented register - is designated by size 0 in this array. */ -static int register_size[] = -{ - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 1, 1, 0, 0, - 2, 2, 0, 4, - 4, 4, 4, 4, - 4, 4, 4, 4 -}; - -/* Contains the register image of the executing thread in the assembler - part of the code in order to avoid horrible addressing modes. */ -registers cris_reg; - -/* FIXME: Should this be used? Delete otherwise. */ -/* Contains the assumed consistency state of the register image. Uses the - enum error_type for state information. */ -static int consistency_status = SUCCESS; - -/********************************** Handle exceptions ************************/ -/* The variable cris_reg contains the register image associated with the - current_thread_c variable. It is a complete register image created at - entry. The reg_g contains a register image of a task where the general - registers are taken from the stack and all special registers are taken - from the executing task. It is associated with current_thread_g and used - in order to provide access mainly for 'g', 'G' and 'P'. -*/ - -/********************************** Breakpoint *******************************/ -/* Use an internal stack in the breakpoint and interrupt response routines */ -#define INTERNAL_STACK_SIZE 1024 -char internal_stack[INTERNAL_STACK_SIZE]; - -/* Due to the breakpoint return pointer, a state variable is needed to keep - track of whether it is a static (compiled) or dynamic (gdb-invoked) - breakpoint to be handled. A static breakpoint uses the content of register - BRP as it is whereas a dynamic breakpoint requires subtraction with 2 - in order to execute the instruction. The first breakpoint is static. */ -static unsigned char __used is_dyn_brkp; - -/********************************* String library ****************************/ -/* Single-step over library functions creates trap loops. */ - -/* Copy char s2[] to s1[]. */ -static char* -gdb_cris_strcpy (char *s1, const char *s2) -{ - char *s = s1; - - for (s = s1; (*s++ = *s2++) != '\0'; ) - ; - return (s1); -} - -/* Find length of s[]. */ -static int -gdb_cris_strlen (const char *s) -{ - const char *sc; - - for (sc = s; *sc != '\0'; sc++) - ; - return (sc - s); -} - -/* Find first occurrence of c in s[n]. */ -static void* -gdb_cris_memchr (const void *s, int c, int n) -{ - const unsigned char uc = c; - const unsigned char *su; - - for (su = s; 0 < n; ++su, --n) - if (*su == uc) - return ((void *)su); - return (NULL); -} -/******************************* Standard library ****************************/ -/* Single-step over library functions creates trap loops. */ -/* Convert string to long. */ -static int -gdb_cris_strtol (const char *s, char **endptr, int base) -{ - char *s1; - char *sd; - int x = 0; - - for (s1 = (char*)s; (sd = gdb_cris_memchr(hex_asc, *s1, base)) != NULL; ++s1) - x = x * base + (sd - hex_asc); - - if (endptr) - { - /* Unconverted suffix is stored in endptr unless endptr is NULL. */ - *endptr = s1; - } - - return x; -} - -/********************************** Packet I/O ******************************/ - -/* Convert the memory, pointed to by mem into hexadecimal representation. - Put the result in buf, and return a pointer to the last character - in buf (null). */ - -static char * -mem2hex(char *buf, unsigned char *mem, int count) -{ - int i; - int ch; - - if (mem == NULL) { - /* Bogus read from m0. FIXME: What constitutes a valid address? */ - for (i = 0; i < count; i++) { - *buf++ = '0'; - *buf++ = '0'; - } - } else { - /* Valid mem address. */ - for (i = 0; i < count; i++) { - ch = *mem++; - buf = hex_byte_pack(buf, ch); - } - } - - /* Terminate properly. */ - *buf = '\0'; - return (buf); -} - -/* Put the content of the array, in binary representation, pointed to by buf - into memory pointed to by mem, and return a pointer to the character after - the last byte written. - Gdb will escape $, #, and the escape char (0x7d). */ -static unsigned char* -bin2mem (unsigned char *mem, unsigned char *buf, int count) -{ - int i; - unsigned char *next; - for (i = 0; i < count; i++) { - /* Check for any escaped characters. Be paranoid and - only unescape chars that should be escaped. */ - if (*buf == 0x7d) { - next = buf + 1; - if (*next == 0x3 || *next == 0x4 || *next == 0x5D) /* #, $, ESC */ - { - buf++; - *buf += 0x20; - } - } - *mem++ = *buf++; - } - return (mem); -} - -/* Await the sequence $<data>#<checksum> and store <data> in the array buffer - returned. */ -static void -getpacket (char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - char ch; - do { - while ((ch = getDebugChar ()) != '$') - /* Wait for the start character $ and ignore all other characters */; - checksum = 0; - xmitcsum = -1; - count = 0; - /* Read until a # or the end of the buffer is reached */ - while (count < BUFMAX - 1) { - ch = getDebugChar (); - if (ch == '#') - break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - buffer[count] = '\0'; - - if (ch == '#') { - xmitcsum = hex_to_bin(getDebugChar()) << 4; - xmitcsum += hex_to_bin(getDebugChar()); - if (checksum != xmitcsum) { - /* Wrong checksum */ - putDebugChar ('-'); - } - else { - /* Correct checksum */ - putDebugChar ('+'); - /* If sequence characters are received, reply with them */ - if (buffer[2] == ':') { - putDebugChar (buffer[0]); - putDebugChar (buffer[1]); - /* Remove the sequence characters from the buffer */ - count = gdb_cris_strlen (buffer); - for (i = 3; i <= count; i++) - buffer[i - 3] = buffer[i]; - } - } - } - } while (checksum != xmitcsum); -} - -/* Send $<data>#<checksum> from the <data> in the array buffer. */ - -static void -putpacket(char *buffer) -{ - int checksum; - int runlen; - int encode; - - do { - char *src = buffer; - putDebugChar ('$'); - checksum = 0; - while (*src) { - /* Do run length encoding */ - putDebugChar (*src); - checksum += *src; - runlen = 0; - while (runlen < RUNLENMAX && *src == src[runlen]) { - runlen++; - } - if (runlen > 3) { - /* Got a useful amount */ - putDebugChar ('*'); - checksum += '*'; - encode = runlen + ' ' - 4; - putDebugChar (encode); - checksum += encode; - src += runlen; - } - else { - src++; - } - } - putDebugChar('#'); - putDebugChar(hex_asc_hi(checksum)); - putDebugChar(hex_asc_lo(checksum)); - } while(kgdb_started && (getDebugChar() != '+')); -} - -/* The string str is prepended with the GDB printout token and sent. Required - in traditional implementations. */ -void -putDebugString (const unsigned char *str, int length) -{ - remcomOutBuffer[0] = 'O'; - mem2hex(&remcomOutBuffer[1], (unsigned char *)str, length); - putpacket(remcomOutBuffer); -} - -/********************************* Register image ****************************/ -/* Write a value to a specified register in the register image of the current - thread. Returns status code SUCCESS, E02, E05 or E08. */ -static int -write_register (int regno, char *val) -{ - int status = SUCCESS; - registers *current_reg = &cris_reg; - - if (regno >= R0 && regno <= PC) { - /* 32-bit register with simple offset. */ - if (hex2bin((unsigned char *)current_reg + regno * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - } - else if (regno == P0 || regno == VR || regno == P4 || regno == P8) { - /* Do not support read-only registers. */ - status = E02; - } - else if (regno == CCR) { - /* 16 bit register with complex offset. (P4 is read-only, P6 is not implemented, - and P7 (MOF) is 32 bits in ETRAX 100LX. */ - if (hex2bin((unsigned char *)&(current_reg->ccr) + (regno-CCR) * sizeof(unsigned short), - val, sizeof(unsigned short))) - status = E08; - } - else if (regno >= MOF && regno <= USP) { - /* 32 bit register with complex offset. (P8 has been taken care of.) */ - if (hex2bin((unsigned char *)&(current_reg->ibr) + (regno-IBR) * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - } - else { - /* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */ - status = E05; - } - return status; -} - -/* Read a value from a specified register in the register image. Returns the - value in the register or -1 for non-implemented registers. - Should check consistency_status after a call which may be E05 after changes - in the implementation. */ -static int -read_register (char regno, unsigned int *valptr) -{ - registers *current_reg = &cris_reg; - - if (regno >= R0 && regno <= PC) { - /* 32-bit register with simple offset. */ - *valptr = *(unsigned int *)((char *)current_reg + regno * sizeof(unsigned int)); - return SUCCESS; - } - else if (regno == P0 || regno == VR) { - /* 8 bit register with complex offset. */ - *valptr = (unsigned int)(*(unsigned char *) - ((char *)&(current_reg->p0) + (regno-P0) * sizeof(char))); - return SUCCESS; - } - else if (regno == P4 || regno == CCR) { - /* 16 bit register with complex offset. */ - *valptr = (unsigned int)(*(unsigned short *) - ((char *)&(current_reg->p4) + (regno-P4) * sizeof(unsigned short))); - return SUCCESS; - } - else if (regno >= MOF && regno <= USP) { - /* 32 bit register with complex offset. */ - *valptr = *(unsigned int *)((char *)&(current_reg->p8) - + (regno-P8) * sizeof(unsigned int)); - return SUCCESS; - } - else { - /* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */ - consistency_status = E05; - return E05; - } -} - -/********************************** Handle exceptions ************************/ -/* Build and send a response packet in order to inform the host the - stub is stopped. TAAn...:r...;n...:r...;n...:r...; - AA = signal number - n... = register number (hex) - r... = register contents - n... = `thread' - r... = thread process ID. This is a hex integer. - n... = other string not starting with valid hex digit. - gdb should ignore this n,r pair and go on to the next. - This way we can extend the protocol. */ -static void -stub_is_stopped(int sigval) -{ - char *ptr = remcomOutBuffer; - int regno; - - unsigned int reg_cont; - int status; - - /* Send trap type (converted to signal) */ - - *ptr++ = 'T'; - ptr = hex_byte_pack(ptr, sigval); - - /* Send register contents. We probably only need to send the - * PC, frame pointer and stack pointer here. Other registers will be - * explicitly asked for. But for now, send all. - */ - - for (regno = R0; regno <= USP; regno++) { - /* Store n...:r...; for the registers in the buffer. */ - - status = read_register (regno, ®_cont); - - if (status == SUCCESS) { - ptr = hex_byte_pack(ptr, regno); - *ptr++ = ':'; - - ptr = mem2hex(ptr, (unsigned char *)®_cont, - register_size[regno]); - *ptr++ = ';'; - } - - } - - /* null-terminate and send it off */ - - *ptr = 0; - - putpacket (remcomOutBuffer); -} - -/* Performs a complete re-start from scratch. */ -static void -kill_restart (void) -{ - machine_restart(""); -} - -/* All expected commands are sent from remote.c. Send a response according - to the description in remote.c. */ -void -handle_exception (int sigval) -{ - /* Send response. */ - - stub_is_stopped (sigval); - - for (;;) { - remcomOutBuffer[0] = '\0'; - getpacket (remcomInBuffer); - switch (remcomInBuffer[0]) { - case 'g': - /* Read registers: g - Success: Each byte of register data is described by two hex digits. - Registers are in the internal order for GDB, and the bytes - in a register are in the same order the machine uses. - Failure: void. */ - - mem2hex(remcomOutBuffer, (char *)&cris_reg, sizeof(registers)); - break; - - case 'G': - /* Write registers. GXX..XX - Each byte of register data is described by two hex digits. - Success: OK - Failure: E08. */ - if (hex2bin((char *)&cris_reg, &remcomInBuffer[1], sizeof(registers))) - gdb_cris_strcpy (remcomOutBuffer, error_message[E08]); - else - gdb_cris_strcpy (remcomOutBuffer, "OK"); - break; - - case 'P': - /* Write register. Pn...=r... - Write register n..., hex value without 0x, with value r..., - which contains a hex value without 0x and two hex digits - for each byte in the register (target byte order). P1f=11223344 means - set register 31 to 44332211. - Success: OK - Failure: E02, E05, E08 */ - { - char *suffix; - int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16); - int status; - status = write_register (regno, suffix+1); - - switch (status) { - case E02: - /* Do not support read-only registers. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E02]); - break; - case E05: - /* Do not support non-existing registers. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E05]); - break; - case E07: - /* Do not support non-existing registers on the stack. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E07]); - break; - case E08: - /* Invalid parameter. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E08]); - break; - default: - /* Valid register number. */ - gdb_cris_strcpy (remcomOutBuffer, "OK"); - break; - } - } - break; - - case 'm': - /* Read from memory. mAA..AA,LLLL - AA..AA is the address and LLLL is the length. - Success: XX..XX is the memory content. Can be fewer bytes than - requested if only part of the data may be read. m6000120a,6c means - retrieve 108 byte from base address 6000120a. - Failure: void. */ - { - char *suffix; - unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1], - &suffix, 16); int length = gdb_cris_strtol(suffix+1, 0, 16); - - mem2hex(remcomOutBuffer, addr, length); - } - break; - - case 'X': - /* Write to memory. XAA..AA,LLLL:XX..XX - AA..AA is the start address, LLLL is the number of bytes, and - XX..XX is the binary data. - Success: OK - Failure: void. */ - case 'M': - /* Write to memory. MAA..AA,LLLL:XX..XX - AA..AA is the start address, LLLL is the number of bytes, and - XX..XX is the hexadecimal data. - Success: OK - Failure: E08. */ - { - char *lenptr; - char *dataptr; - unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1], - &lenptr, 16); - int length = gdb_cris_strtol(lenptr+1, &dataptr, 16); - if (*lenptr == ',' && *dataptr == ':') { - if (remcomInBuffer[0] == 'M') { - if (hex2bin(addr, dataptr + 1, length)) - gdb_cris_strcpy (remcomOutBuffer, error_message[E08]); - else - gdb_cris_strcpy (remcomOutBuffer, "OK"); - } else /* X */ { - bin2mem(addr, dataptr + 1, length); - gdb_cris_strcpy (remcomOutBuffer, "OK"); - } - } else { - gdb_cris_strcpy (remcomOutBuffer, error_message[E06]); - } - } - break; - - case 'c': - /* Continue execution. cAA..AA - AA..AA is the address where execution is resumed. If AA..AA is - omitted, resume at the present address. - Success: return to the executing thread. - Failure: will never know. */ - if (remcomInBuffer[1] != '\0') { - cris_reg.pc = gdb_cris_strtol (&remcomInBuffer[1], 0, 16); - } - enableDebugIRQ(); - return; - - case 's': - /* Step. sAA..AA - AA..AA is the address where execution is resumed. If AA..AA is - omitted, resume at the present address. Success: return to the - executing thread. Failure: will never know. - - Should never be invoked. The single-step is implemented on - the host side. If ever invoked, it is an internal error E04. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E04]); - putpacket (remcomOutBuffer); - return; - - case '?': - /* The last signal which caused a stop. ? - Success: SAA, where AA is the signal number. - Failure: void. */ - remcomOutBuffer[0] = 'S'; - remcomOutBuffer[1] = hex_asc_hi(sigval); - remcomOutBuffer[2] = hex_asc_lo(sigval); - remcomOutBuffer[3] = 0; - break; - - case 'D': - /* Detach from host. D - Success: OK, and return to the executing thread. - Failure: will never know */ - putpacket ("OK"); - return; - - case 'k': - case 'r': - /* kill request or reset request. - Success: restart of target. - Failure: will never know. */ - kill_restart (); - break; - - case 'C': - case 'S': - case '!': - case 'R': - case 'd': - /* Continue with signal sig. Csig;AA..AA - Step with signal sig. Ssig;AA..AA - Use the extended remote protocol. ! - Restart the target system. R0 - Toggle debug flag. d - Search backwards. tAA:PP,MM - Not supported: E04 */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E04]); - break; - - default: - /* The stub should ignore other request and send an empty - response ($#<checksum>). This way we can extend the protocol and GDB - can tell whether the stub it is talking to uses the old or the new. */ - remcomOutBuffer[0] = 0; - break; - } - putpacket(remcomOutBuffer); - } -} - -/********************************** Breakpoint *******************************/ -/* The hook for both a static (compiled) and a dynamic breakpoint set by GDB. - An internal stack is used by the stub. The register image of the caller is - stored in the structure register_image. - Interactive communication with the host is handled by handle_exception and - finally the register image is restored. */ - -void kgdb_handle_breakpoint(void); - -asm ("\n" -" .global kgdb_handle_breakpoint\n" -"kgdb_handle_breakpoint:\n" -";;\n" -";; Response to the break-instruction\n" -";;\n" -";; Create a register image of the caller\n" -";;\n" -" move $dccr,[cris_reg+0x5E] ; Save the flags in DCCR before disable interrupts\n" -" di ; Disable interrupts\n" -" move.d $r0,[cris_reg] ; Save R0\n" -" move.d $r1,[cris_reg+0x04] ; Save R1\n" -" move.d $r2,[cris_reg+0x08] ; Save R2\n" -" move.d $r3,[cris_reg+0x0C] ; Save R3\n" -" move.d $r4,[cris_reg+0x10] ; Save R4\n" -" move.d $r5,[cris_reg+0x14] ; Save R5\n" -" move.d $r6,[cris_reg+0x18] ; Save R6\n" -" move.d $r7,[cris_reg+0x1C] ; Save R7\n" -" move.d $r8,[cris_reg+0x20] ; Save R8\n" -" move.d $r9,[cris_reg+0x24] ; Save R9\n" -" move.d $r10,[cris_reg+0x28] ; Save R10\n" -" move.d $r11,[cris_reg+0x2C] ; Save R11\n" -" move.d $r12,[cris_reg+0x30] ; Save R12\n" -" move.d $r13,[cris_reg+0x34] ; Save R13\n" -" move.d $sp,[cris_reg+0x38] ; Save SP (R14)\n" -";; Due to the old assembler-versions BRP might not be recognized\n" -" .word 0xE670 ; move brp,$r0\n" -" subq 2,$r0 ; Set to address of previous instruction.\n" -" move.d $r0,[cris_reg+0x3c] ; Save the address in PC (R15)\n" -" clear.b [cris_reg+0x40] ; Clear P0\n" -" move $vr,[cris_reg+0x41] ; Save special register P1\n" -" clear.w [cris_reg+0x42] ; Clear P4\n" -" move $ccr,[cris_reg+0x44] ; Save special register CCR\n" -" move $mof,[cris_reg+0x46] ; P7\n" -" clear.d [cris_reg+0x4A] ; Clear P8\n" -" move $ibr,[cris_reg+0x4E] ; P9,\n" -" move $irp,[cris_reg+0x52] ; P10,\n" -" move $srp,[cris_reg+0x56] ; P11,\n" -" move $bar,[cris_reg+0x5A] ; P12,\n" -" ; P13, register DCCR already saved\n" -";; Due to the old assembler-versions BRP might not be recognized\n" -" .word 0xE670 ; move brp,r0\n" -";; Static (compiled) breakpoints must return to the next instruction in order\n" -";; to avoid infinite loops. Dynamic (gdb-invoked) must restore the instruction\n" -";; in order to execute it when execution is continued.\n" -" test.b [is_dyn_brkp] ; Is this a dynamic breakpoint?\n" -" beq is_static ; No, a static breakpoint\n" -" nop\n" -" subq 2,$r0 ; rerun the instruction the break replaced\n" -"is_static:\n" -" moveq 1,$r1\n" -" move.b $r1,[is_dyn_brkp] ; Set the state variable to dynamic breakpoint\n" -" move.d $r0,[cris_reg+0x62] ; Save the return address in BRP\n" -" move $usp,[cris_reg+0x66] ; USP\n" -";;\n" -";; Handle the communication\n" -";;\n" -" move.d internal_stack+1020,$sp ; Use the internal stack which grows upward\n" -" moveq 5,$r10 ; SIGTRAP\n" -" jsr handle_exception ; Interactive routine\n" -";;\n" -";; Return to the caller\n" -";;\n" -" move.d [cris_reg],$r0 ; Restore R0\n" -" move.d [cris_reg+0x04],$r1 ; Restore R1\n" -" move.d [cris_reg+0x08],$r2 ; Restore R2\n" -" move.d [cris_reg+0x0C],$r3 ; Restore R3\n" -" move.d [cris_reg+0x10],$r4 ; Restore R4\n" -" move.d [cris_reg+0x14],$r5 ; Restore R5\n" -" move.d [cris_reg+0x18],$r6 ; Restore R6\n" -" move.d [cris_reg+0x1C],$r7 ; Restore R7\n" -" move.d [cris_reg+0x20],$r8 ; Restore R8\n" -" move.d [cris_reg+0x24],$r9 ; Restore R9\n" -" move.d [cris_reg+0x28],$r10 ; Restore R10\n" -" move.d [cris_reg+0x2C],$r11 ; Restore R11\n" -" move.d [cris_reg+0x30],$r12 ; Restore R12\n" -" move.d [cris_reg+0x34],$r13 ; Restore R13\n" -";;\n" -";; FIXME: Which registers should be restored?\n" -";;\n" -" move.d [cris_reg+0x38],$sp ; Restore SP (R14)\n" -" move [cris_reg+0x56],$srp ; Restore the subroutine return pointer.\n" -" move [cris_reg+0x5E],$dccr ; Restore DCCR\n" -" move [cris_reg+0x66],$usp ; Restore USP\n" -" jump [cris_reg+0x62] ; A jump to the content in register BRP works.\n" -" nop ;\n" -"\n"); - -/* The hook for an interrupt generated by GDB. An internal stack is used - by the stub. The register image of the caller is stored in the structure - register_image. Interactive communication with the host is handled by - handle_exception and finally the register image is restored. Due to the - old assembler which does not recognise the break instruction and the - breakpoint return pointer hex-code is used. */ - -void kgdb_handle_serial(void); - -asm ("\n" -" .global kgdb_handle_serial\n" -"kgdb_handle_serial:\n" -";;\n" -";; Response to a serial interrupt\n" -";;\n" -"\n" -" move $dccr,[cris_reg+0x5E] ; Save the flags in DCCR\n" -" di ; Disable interrupts\n" -" move.d $r0,[cris_reg] ; Save R0\n" -" move.d $r1,[cris_reg+0x04] ; Save R1\n" -" move.d $r2,[cris_reg+0x08] ; Save R2\n" -" move.d $r3,[cris_reg+0x0C] ; Save R3\n" -" move.d $r4,[cris_reg+0x10] ; Save R4\n" -" move.d $r5,[cris_reg+0x14] ; Save R5\n" -" move.d $r6,[cris_reg+0x18] ; Save R6\n" -" move.d $r7,[cris_reg+0x1C] ; Save R7\n" -" move.d $r8,[cris_reg+0x20] ; Save R8\n" -" move.d $r9,[cris_reg+0x24] ; Save R9\n" -" move.d $r10,[cris_reg+0x28] ; Save R10\n" -" move.d $r11,[cris_reg+0x2C] ; Save R11\n" -" move.d $r12,[cris_reg+0x30] ; Save R12\n" -" move.d $r13,[cris_reg+0x34] ; Save R13\n" -" move.d $sp,[cris_reg+0x38] ; Save SP (R14)\n" -" move $irp,[cris_reg+0x3c] ; Save the address in PC (R15)\n" -" clear.b [cris_reg+0x40] ; Clear P0\n" -" move $vr,[cris_reg+0x41] ; Save special register P1,\n" -" clear.w [cris_reg+0x42] ; Clear P4\n" -" move $ccr,[cris_reg+0x44] ; Save special register CCR\n" -" move $mof,[cris_reg+0x46] ; P7\n" -" clear.d [cris_reg+0x4A] ; Clear P8\n" -" move $ibr,[cris_reg+0x4E] ; P9,\n" -" move $irp,[cris_reg+0x52] ; P10,\n" -" move $srp,[cris_reg+0x56] ; P11,\n" -" move $bar,[cris_reg+0x5A] ; P12,\n" -" ; P13, register DCCR already saved\n" -";; Due to the old assembler-versions BRP might not be recognized\n" -" .word 0xE670 ; move brp,r0\n" -" move.d $r0,[cris_reg+0x62] ; Save the return address in BRP\n" -" move $usp,[cris_reg+0x66] ; USP\n" -"\n" -";; get the serial character (from debugport.c) and check if it is a ctrl-c\n" -"\n" -" jsr getDebugChar\n" -" cmp.b 3, $r10\n" -" bne goback\n" -" nop\n" -"\n" -" move.d [cris_reg+0x5E], $r10 ; Get DCCR\n" -" btstq 8, $r10 ; Test the U-flag.\n" -" bmi goback\n" -" nop\n" -"\n" -";;\n" -";; Handle the communication\n" -";;\n" -" move.d internal_stack+1020,$sp ; Use the internal stack\n" -" moveq 2,$r10 ; SIGINT\n" -" jsr handle_exception ; Interactive routine\n" -"\n" -"goback:\n" -";;\n" -";; Return to the caller\n" -";;\n" -" move.d [cris_reg],$r0 ; Restore R0\n" -" move.d [cris_reg+0x04],$r1 ; Restore R1\n" -" move.d [cris_reg+0x08],$r2 ; Restore R2\n" -" move.d [cris_reg+0x0C],$r3 ; Restore R3\n" -" move.d [cris_reg+0x10],$r4 ; Restore R4\n" -" move.d [cris_reg+0x14],$r5 ; Restore R5\n" -" move.d [cris_reg+0x18],$r6 ; Restore R6\n" -" move.d [cris_reg+0x1C],$r7 ; Restore R7\n" -" move.d [cris_reg+0x20],$r8 ; Restore R8\n" -" move.d [cris_reg+0x24],$r9 ; Restore R9\n" -" move.d [cris_reg+0x28],$r10 ; Restore R10\n" -" move.d [cris_reg+0x2C],$r11 ; Restore R11\n" -" move.d [cris_reg+0x30],$r12 ; Restore R12\n" -" move.d [cris_reg+0x34],$r13 ; Restore R13\n" -";;\n" -";; FIXME: Which registers should be restored?\n" -";;\n" -" move.d [cris_reg+0x38],$sp ; Restore SP (R14)\n" -" move [cris_reg+0x56],$srp ; Restore the subroutine return pointer.\n" -" move [cris_reg+0x5E],$dccr ; Restore DCCR\n" -" move [cris_reg+0x66],$usp ; Restore USP\n" -" reti ; Return from the interrupt routine\n" -" nop\n" -"\n"); - -/* Use this static breakpoint in the start-up only. */ - -void -breakpoint(void) -{ - kgdb_started = 1; - is_dyn_brkp = 0; /* This is a static, not a dynamic breakpoint. */ - __asm__ volatile ("break 8"); /* Jump to handle_breakpoint. */ -} - -/* initialize kgdb. doesn't break into the debugger, but sets up irq and ports */ - -void -kgdb_init(void) -{ - /* could initialize debug port as well but it's done in head.S already... */ - - /* breakpoint handler is now set in irq.c */ - set_int_vector(8, kgdb_handle_serial); - - enableDebugIRQ(); -} - -/****************************** End of file **********************************/ diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c deleted file mode 100644 index 16848b2c61c8..000000000000 --- a/arch/cris/arch-v10/kernel/process.c +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/process.c - * - * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 2000-2002 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * Mikael Starvik (starvik@axis.com) - * - * This file handles the architecture-dependent parts of process handling.. - */ - -#include <linux/sched.h> -#include <linux/sched/debug.h> -#include <linux/sched/task.h> -#include <linux/sched/task_stack.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/fs.h> -#include <arch/svinto.h> -#include <linux/init.h> -#include <arch/system.h> -#include <linux/ptrace.h> - -#ifdef CONFIG_ETRAX_GPIO -void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ -#endif - -/* - * We use this if we don't have any better - * idle routine.. - */ -void default_idle(void) -{ -#ifdef CONFIG_ETRAX_GPIO - etrax_gpio_wake_up_check(); -#endif - local_irq_enable(); -} - -/* if the watchdog is enabled, we can simply disable interrupts and go - * into an eternal loop, and the watchdog will reset the CPU after 0.1s - * if on the other hand the watchdog wasn't enabled, we just enable it and wait - */ - -void hard_reset_now (void) -{ - /* - * Don't declare this variable elsewhere. We don't want any other - * code to know about it than the watchdog handler in entry.S and - * this code, implementing hard reset through the watchdog. - */ -#if defined(CONFIG_ETRAX_WATCHDOG) - extern int cause_of_death; -#endif - - printk("*** HARD RESET ***\n"); - local_irq_disable(); - -#if defined(CONFIG_ETRAX_WATCHDOG) - cause_of_death = 0xbedead; -#else - /* Since we dont plan to keep on resetting the watchdog, - the key can be arbitrary hence three */ - *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, 3) | - IO_STATE(R_WATCHDOG, enable, start); -#endif - - while(1) /* waiting for RETRIBUTION! */ ; -} - -/* setup the child's kernel stack with a pt_regs and switch_stack on it. - * it will be un-nested during _resume and _ret_from_sys_call when the - * new thread is scheduled. - * - * also setup the thread switching structure which is used to keep - * thread-specific data during _resumes. - * - */ -asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); - -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) -{ - struct pt_regs *childregs = task_pt_regs(p); - struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; - - /* put the pt_regs structure at the end of the new kernel stack page and fix it up - * remember that the task_struct doubles as the kernel stack for the task - */ - - if (unlikely(p->flags & PF_KTHREAD)) { - memset(swstack, 0, - sizeof(struct switch_stack) + sizeof(struct pt_regs)); - swstack->r1 = usp; - swstack->r2 = arg; - childregs->dccr = 1 << I_DCCR_BITNR; - swstack->return_ip = (unsigned long) ret_from_kernel_thread; - p->thread.ksp = (unsigned long) swstack; - p->thread.usp = 0; - return 0; - } - *childregs = *current_pt_regs(); /* struct copy of pt_regs */ - - childregs->r10 = 0; /* child returns 0 after a fork/clone */ - - /* put the switch stack right below the pt_regs */ - - swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ - - /* we want to return into ret_from_sys_call after the _resume */ - - swstack->return_ip = (unsigned long) ret_from_fork; /* Will call ret_from_sys_call */ - - /* fix the user-mode stackpointer */ - - p->thread.usp = usp ?: rdusp(); - - /* and the kernel-mode one */ - - p->thread.ksp = (unsigned long) swstack; - -#ifdef DEBUG - printk("copy_thread: new regs at 0x%p, as shown below:\n", childregs); - show_registers(childregs); -#endif - - return 0; -} - -unsigned long get_wchan(struct task_struct *p) -{ -#if 0 - /* YURGH. TODO. */ - - unsigned long ebp, esp, eip; - unsigned long stack_page; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - stack_page = (unsigned long)p; - esp = p->thread.esp; - if (!stack_page || esp < stack_page || esp > 8188+stack_page) - return 0; - /* include/asm-i386/system.h:switch_to() pushes ebp last. */ - ebp = *(unsigned long *) esp; - do { - if (ebp < stack_page || ebp > 8184+stack_page) - return 0; - eip = *(unsigned long *) (ebp+4); - if (!in_sched_functions(eip)) - return eip; - ebp = *(unsigned long *) ebp; - } while (count++ < 16); -#endif - return 0; -} -#undef last_sched -#undef first_sched - -void show_regs(struct pt_regs * regs) -{ - unsigned long usp = rdusp(); - - show_regs_print_info(KERN_DEFAULT); - - printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", - regs->irp, regs->srp, regs->dccr, usp, regs->mof ); - printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", - regs->r8, regs->r9, regs->r10, regs->r11); - printk("r12: %08lx r13: %08lx oR10: %08lx\n", - regs->r12, regs->r13, regs->orig_r10); -} - diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c deleted file mode 100644 index b89f57ae096e..000000000000 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2000-2003, Axis Communications AB. - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/signal.h> -#include <linux/security.h> - -#include <linux/uaccess.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/processor.h> - -/* - * Determines which bits in DCCR the user has access to. - * 1 = access, 0 = no access. - */ -#define DCCR_MASK 0x0000001f /* XNZVC */ - -/* - * Get contents of register REGNO in task TASK. - */ -inline long get_reg(struct task_struct *task, unsigned int regno) -{ - /* USP is a special case, it's not in the pt_regs struct but - * in the tasks thread struct - */ - - if (regno == PT_USP) - return task->thread.usp; - else if (regno < PT_MAX) - return ((unsigned long *)task_pt_regs(task))[regno]; - else - return 0; -} - -/* - * Write contents of register REGNO in task TASK. - */ -inline int put_reg(struct task_struct *task, unsigned int regno, - unsigned long data) -{ - if (regno == PT_USP) - task->thread.usp = data; - else if (regno < PT_MAX) - ((unsigned long *)task_pt_regs(task))[regno] = data; - else - return -1; - return 0; -} - -/* - * Called by kernel/ptrace.c when detaching. - * - * Make sure the single step bit is not set. - */ -void -ptrace_disable(struct task_struct *child) -{ - /* Todo - pending singlesteps? */ - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -} - -/* - * Note that this implementation of ptrace behaves differently from vanilla - * ptrace. Contrary to what the man page says, in the PTRACE_PEEKTEXT, - * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not - * ignored. Instead, the data variable is expected to point at a location - * (in user space) where the result of the ptrace call is written (instead of - * being returned). - */ -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - unsigned int regno = addr >> 2; - unsigned long __user *datap = (unsigned long __user *)data; - - switch (request) { - /* Read word at location address. */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - - /* Read the word at location address in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - ret = -EIO; - if ((addr & 3) || regno > PT_MAX) - break; - - tmp = get_reg(child, regno); - ret = put_user(tmp, datap); - break; - } - - /* Write the word at location address. */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - - /* Write the word at location address in the USER area. */ - case PTRACE_POKEUSR: - ret = -EIO; - if ((addr & 3) || regno > PT_MAX) - break; - - if (regno == PT_DCCR) { - /* don't allow the tracing process to change stuff like - * interrupt enable, kernel/user bit, dma enables etc. - */ - data &= DCCR_MASK; - data |= get_reg(child, PT_DCCR) & ~DCCR_MASK; - } - if (put_reg(child, regno, data)) - break; - ret = 0; - break; - - /* Get all GP registers from the child. */ - case PTRACE_GETREGS: { - int i; - unsigned long tmp; - - ret = 0; - for (i = 0; i <= PT_MAX; i++) { - tmp = get_reg(child, i); - - if (put_user(tmp, datap)) { - ret = -EFAULT; - break; - } - - datap++; - } - - break; - } - - /* Set all GP registers in the child. */ - case PTRACE_SETREGS: { - int i; - unsigned long tmp; - - ret = 0; - for (i = 0; i <= PT_MAX; i++) { - if (get_user(tmp, datap)) { - ret = -EFAULT; - break; - } - - if (i == PT_DCCR) { - tmp &= DCCR_MASK; - tmp |= get_reg(child, PT_DCCR) & ~DCCR_MASK; - } - - put_reg(child, i, tmp); - datap++; - } - - break; - } - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} - -void do_syscall_trace(void) -{ - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - - if (!(current->ptrace & PT_PTRACED)) - return; - - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - - /* - * This isn't the same as continuing with a signal, but it will do for - * normal use. - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} diff --git a/arch/cris/arch-v10/kernel/setup.c b/arch/cris/arch-v10/kernel/setup.c deleted file mode 100644 index 8e4fc248f96f..000000000000 --- a/arch/cris/arch-v10/kernel/setup.c +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * - * linux/arch/cris/arch-v10/kernel/setup.c - * - * Copyright (C) 1995 Linus Torvalds - * Copyright (c) 2001-2002 Axis Communications AB - */ - -/* - * This file handles the architecture-dependent parts of initialization - */ - -#include <linux/seq_file.h> -#include <linux/proc_fs.h> -#include <linux/delay.h> -#include <linux/param.h> -#include <arch/system.h> - -#ifdef CONFIG_PROC_FS -#define HAS_FPU 0x0001 -#define HAS_MMU 0x0002 -#define HAS_ETHERNET100 0x0004 -#define HAS_TOKENRING 0x0008 -#define HAS_SCSI 0x0010 -#define HAS_ATA 0x0020 -#define HAS_USB 0x0040 -#define HAS_IRQ_BUG 0x0080 -#define HAS_MMU_BUG 0x0100 - -static struct cpu_info { - char *model; - unsigned short cache; - unsigned short flags; -} cpu_info[] = { - /* The first four models will never ever run this code and are - only here for display. */ - { "ETRAX 1", 0, 0 }, - { "ETRAX 2", 0, 0 }, - { "ETRAX 3", 0, HAS_TOKENRING }, - { "ETRAX 4", 0, HAS_TOKENRING | HAS_SCSI }, - { "Unknown", 0, 0 }, - { "Unknown", 0, 0 }, - { "Unknown", 0, 0 }, - { "Simulator", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA }, - { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG }, - { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA }, - { "ETRAX 100LX", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG }, - { "ETRAX 100LX v2", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU }, - { "Unknown", 0, 0 } /* This entry MUST be the last */ -}; - -int show_cpuinfo(struct seq_file *m, void *v) -{ - unsigned long revision; - struct cpu_info *info; - - /* read the version register in the CPU and print some stuff */ - - revision = rdvr(); - - if (revision >= ARRAY_SIZE(cpu_info)) - info = &cpu_info[ARRAY_SIZE(cpu_info) - 1]; - else - info = &cpu_info[revision]; - - seq_printf(m, - "processor\t: 0\n" - "cpu\t\t: CRIS\n" - "cpu revision\t: %lu\n" - "cpu model\t: %s\n" - "cache size\t: %d kB\n" - "fpu\t\t: %s\n" - "mmu\t\t: %s\n" - "mmu DMA bug\t: %s\n" - "ethernet\t: %s Mbps\n" - "token ring\t: %s\n" - "scsi\t\t: %s\n" - "ata\t\t: %s\n" - "usb\t\t: %s\n" - "bogomips\t: %lu.%02lu\n", - - revision, - info->model, - info->cache, - info->flags & HAS_FPU ? "yes" : "no", - info->flags & HAS_MMU ? "yes" : "no", - info->flags & HAS_MMU_BUG ? "yes" : "no", - info->flags & HAS_ETHERNET100 ? "10/100" : "10", - info->flags & HAS_TOKENRING ? "4/16 Mbps" : "no", - info->flags & HAS_SCSI ? "yes" : "no", - info->flags & HAS_ATA ? "yes" : "no", - info->flags & HAS_USB ? "yes" : "no", - (loops_per_jiffy * HZ + 500) / 500000, - ((loops_per_jiffy * HZ + 500) / 5000) % 100); - - return 0; -} - -#endif /* CONFIG_PROC_FS */ - -void -show_etrax_copyright(void) -{ - printk(KERN_INFO - "Linux/CRIS port on ETRAX 100LX (c) 2001 Axis Communications AB\n"); -} diff --git a/arch/cris/arch-v10/kernel/shadows.c b/arch/cris/arch-v10/kernel/shadows.c deleted file mode 100644 index 2e9565e868f2..000000000000 --- a/arch/cris/arch-v10/kernel/shadows.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Various shadow registers. Defines for these are in include/asm-etrax100/io.h - */ - -/* Shadows for internal Etrax-registers */ - -unsigned long genconfig_shadow; -unsigned long gen_config_ii_shadow; -unsigned long port_g_data_shadow; -unsigned char port_pa_dir_shadow; -unsigned char port_pa_data_shadow; -unsigned char port_pb_i2c_shadow; -unsigned char port_pb_config_shadow; -unsigned char port_pb_dir_shadow; -unsigned char port_pb_data_shadow; -unsigned long r_timer_ctrl_shadow; - -/* Shadows for external I/O port registers. - * These are only usable if there actually IS a latch connected - * to the corresponding external chip-select pin. - * - * A common usage is that CSP0 controls LEDs and CSP4 video chips. - */ - -unsigned long port_cse1_shadow; -unsigned long port_csp0_shadow; -unsigned long port_csp4_shadow; - -/* Corresponding addresses for the ports. - * These are initialized in arch/cris/mm/init.c using ioremap. - */ - -volatile unsigned long *port_cse1_addr; -volatile unsigned long *port_csp0_addr; -volatile unsigned long *port_csp4_addr; - diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c deleted file mode 100644 index 2beffc37faf8..000000000000 --- a/arch/cris/arch-v10/kernel/signal.c +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/signal.c - * - * Based on arch/i386/kernel/signal.c by - * Copyright (C) 1991, 1992 Linus Torvalds - * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * - * - * Ideas also taken from arch/arm. - * - * Copyright (C) 2000-2007 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * - */ - -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/stddef.h> - -#include <asm/processor.h> -#include <asm/ucontext.h> -#include <linux/uaccess.h> -#include <arch/system.h> - -#define DEBUG_SIG 0 - -/* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */ -/* manipulate regs so that upon return, it will be re-executed */ - -/* We rely on that pc points to the instruction after "break 13", so the - * library must never do strange things like putting it in a delay slot. - */ -#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2; - -void do_signal(int canrestart, struct pt_regs *regs); - -/* - * Do a signal return; undo the signal stack. - */ - -struct sigframe { - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS-1]; - unsigned char retcode[8]; /* trampoline code */ -}; - -struct rt_sigframe { - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - unsigned char retcode[8]; /* trampoline code */ -}; - - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) -{ - unsigned int err = 0; - unsigned long old_usp; - - /* Always make any pending restarted system calls return -EINTR */ - current->restart_block.fn = do_no_restart_syscall; - - /* restore the regs from &sc->regs (same as sc, since regs is first) - * (sc is already checked for VERIFY_READ since the sigframe was - * checked in sys_sigreturn previously) - */ - - if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) - goto badframe; - - /* make sure the U-flag is set so user-mode cannot fool us */ - - regs->dccr |= 1 << 8; - - /* restore the old USP as it was before we stacked the sc etc. - * (we cannot just pop the sigcontext since we aligned the sp and - * stuff after pushing it) - */ - - err |= __get_user(old_usp, &sc->usp); - - wrusp(old_usp); - - /* TODO: the other ports use regs->orig_XX to disable syscall checks - * after this completes, but we don't use that mechanism. maybe we can - * use it now ? - */ - - return err; - -badframe: - return 1; -} - -asmlinkage int sys_sigreturn(void) -{ - struct pt_regs *regs = current_pt_regs(); - struct sigframe __user *frame = (struct sigframe *)rdusp(); - sigset_t set; - - /* - * Since we stacked the signal on a dword boundary, - * then frame should be dword aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (((long)frame) & 3) - goto badframe; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->sc)) - goto badframe; - - /* TODO: SIGTRAP when single-stepping as in arm ? */ - - return regs->r10; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(void) -{ - struct pt_regs *regs = current_pt_regs(); - struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp(); - sigset_t set; - - /* - * Since we stacked the signal on a dword boundary, - * then frame should be dword aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (((long)frame) & 3) - goto badframe; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) - goto badframe; - - if (restore_altstack(&frame->uc.uc_stack)) - goto badframe; - - return regs->r10; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* - * Set up a signal frame. - */ - -static int setup_sigcontext(struct sigcontext __user *sc, - struct pt_regs *regs, unsigned long mask) -{ - int err = 0; - unsigned long usp = rdusp(); - - /* copy the regs. they are first in sc so we can use sc directly */ - - err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); - - /* Set the frametype to CRIS_FRAME_NORMAL for the execution of - the signal handler. The frametype will be restored to its previous - value in restore_sigcontext. */ - regs->frametype = CRIS_FRAME_NORMAL; - - /* then some other stuff */ - - err |= __put_user(mask, &sc->oldmask); - - err |= __put_user(usp, &sc->usp); - - return err; -} - -/* Figure out where we want to put the new signal frame - * - usually on the stack. */ - -static inline void __user * -get_sigframe(struct ksignal *ksig, size_t frame_size) -{ - unsigned long sp = sigsp(rdusp(), ksig); - - /* make sure the frame is dword-aligned */ - - sp &= ~3; - - return (void __user*)(sp - frame_size); -} - -/* grab and setup a signal frame. - * - * basically we stack a lot of state info, and arrange for the - * user-mode program to return to the kernel using either a - * trampoline which performs the syscall sigreturn, or a provided - * user-mode trampoline. - */ - -static int setup_frame(struct ksignal *ksig, sigset_t *set, - struct pt_regs *regs) -{ - struct sigframe __user *frame; - unsigned long return_ip; - int err = 0; - - frame = get_sigframe(ksig, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - if (err) - return -EFAULT; - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - } - if (err) - return -EFAULT; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ksig->ka.sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long)ksig->ka.sa.sa_restorer; - } else { - /* trampoline - the desired return ip is the retcode itself */ - return_ip = (unsigned long)&frame->retcode; - /* This is movu.w __NR_sigreturn, r9; break 13; */ - err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2)); - err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); - } - - if (err) - return -EFAULT; - - /* Set up registers for signal handler */ - - regs->irp = (unsigned long) ksig->ka.sa.sa_handler; /* what we enter NOW */ - regs->srp = return_ip; /* what we enter LATER */ - regs->r10 = ksig->sig; /* first argument is signo */ - - /* actually move the usp to reflect the stacked frame */ - - wrusp((unsigned long)frame); - - return 0; -} - -static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, - struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - unsigned long return_ip; - int err = 0; - - frame = get_sigframe(ksig, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, &ksig->info); - if (err) - return -EFAULT; - - /* Clear all the bits of the ucontext we don't use. */ - err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); - - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - err |= __save_altstack(&frame->uc.uc_stack, rdusp()); - - if (err) - return -EFAULT; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ksig->ka.sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long)ksig->ka.sa.sa_restorer; - } else { - /* trampoline - the desired return ip is the retcode itself */ - return_ip = (unsigned long)&frame->retcode; - /* This is movu.w __NR_rt_sigreturn, r9; break 13; */ - err |= __put_user(0x9c5f, (short __user *)(frame->retcode+0)); - err |= __put_user(__NR_rt_sigreturn, - (short __user *)(frame->retcode+2)); - err |= __put_user(0xe93d, (short __user *)(frame->retcode+4)); - } - - if (err) - return -EFAULT; - - /* Set up registers for signal handler */ - - /* What we enter NOW */ - regs->irp = (unsigned long) ksig->ka.sa.sa_handler; - /* What we enter LATER */ - regs->srp = return_ip; - /* First argument is signo */ - regs->r10 = ksig->sig; - /* Second argument is (siginfo_t *) */ - regs->r11 = (unsigned long)&frame->info; - /* Third argument is unused */ - regs->r12 = 0; - - /* Actually move the usp to reflect the stacked frame */ - wrusp((unsigned long)frame); - - return 0; -} - -/* - * OK, we're invoking a handler - */ - -static inline void handle_signal(int canrestart, struct ksignal *ksig, - struct pt_regs *regs) -{ - sigset_t *oldset = sigmask_to_save(); - int ret; - - /* Are we from a system call? */ - if (canrestart) { - /* If so, check system call restarting.. */ - switch (regs->r10) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - /* ERESTARTNOHAND means that the syscall should - * only be restarted if there was no handler for - * the signal, and since we only get here if there - * is a handler, we don't restart */ - regs->r10 = -EINTR; - break; - case -ERESTARTSYS: - /* ERESTARTSYS means to restart the syscall if - * there is no handler or the handler was - * registered with SA_RESTART */ - if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { - regs->r10 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - /* ERESTARTNOINTR means that the syscall should - * be called again after the signal handler returns. */ - RESTART_CRIS_SYS(regs); - } - } - - /* Set up the stack frame */ - if (ksig->ka.sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(ksig, oldset, regs); - else - ret = setup_frame(ksig, oldset, regs); - - signal_setup_done(ret, ksig, 0); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Also note that the regs structure given here as an argument, is the latest - * pushed pt_regs. It may or may not be the same as the first pushed registers - * when the initial usermode->kernelmode transition took place. Therefore - * we can use user_mode(regs) to see if we came directly from kernel or user - * mode below. - */ - -void do_signal(int canrestart, struct pt_regs *regs) -{ - struct ksignal ksig; - - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return; - - if (get_signal(&ksig)) { - /* Whee! Actually deliver the signal. */ - handle_signal(canrestart, &ksig, regs); - return; - } - - /* Did we come from a system call? */ - if (canrestart) { - /* Restart the system call - no handlers present */ - if (regs->r10 == -ERESTARTNOHAND || - regs->r10 == -ERESTARTSYS || - regs->r10 == -ERESTARTNOINTR) { - RESTART_CRIS_SYS(regs); - } - if (regs->r10 == -ERESTART_RESTARTBLOCK) { - regs->r9 = __NR_restart_syscall; - regs->irp -= 2; - } - } - - /* if there's no signal to deliver, we just put the saved sigmask - * back */ - restore_saved_sigmask(); -} diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c deleted file mode 100644 index 3d78373db254..000000000000 --- a/arch/cris/arch-v10/kernel/time.c +++ /dev/null @@ -1,268 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/arch-v10/kernel/time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Copyright (C) 1999-2002 Axis Communications AB - * - */ - -#include <linux/timex.h> -#include <linux/time.h> -#include <linux/jiffies.h> -#include <linux/interrupt.h> -#include <linux/swap.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <asm/types.h> -#include <asm/signal.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/irq_regs.h> - -/* define this if you need to use print_timestamp */ -/* it will make jiffies at 96 hz instead of 100 hz though */ -#undef USE_CASCADE_TIMERS - -unsigned long get_ns_in_jiffie(void) -{ - unsigned char timer_count, t1; - unsigned short presc_count; - unsigned long ns; - unsigned long flags; - - local_irq_save(flags); - timer_count = *R_TIMER0_DATA; - presc_count = *R_TIM_PRESC_STATUS; - /* presc_count might be wrapped */ - t1 = *R_TIMER0_DATA; - - if (timer_count != t1){ - /* it wrapped, read prescaler again... */ - presc_count = *R_TIM_PRESC_STATUS; - timer_count = t1; - } - local_irq_restore(flags); - if (presc_count >= PRESCALE_VALUE/2 ){ - presc_count = PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2; - } else { - presc_count = PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2; - } - - ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) + - ( (presc_count) * (1000000000/PRESCALE_FREQ)); - return ns; -} - -static u32 cris_v10_gettimeoffset(void) -{ - u32 count; - - /* The timer interrupt comes from Etrax timer 0. In order to get - * better precision, we check the current value. It might have - * underflowed already though. - */ - count = *R_TIMER0_DATA; - - /* Convert timer value to nsec */ - return (TIMER0_DIV - count) * (NSEC_PER_SEC/HZ)/TIMER0_DIV; -} - -/* Excerpt from the Etrax100 HSDD about the built-in watchdog: - * - * 3.10.4 Watchdog timer - - * When the watchdog timer is started, it generates an NMI if the watchdog - * isn't restarted or stopped within 0.1 s. If it still isn't restarted or - * stopped after an additional 3.3 ms, the watchdog resets the chip. - * The watchdog timer is stopped after reset. The watchdog timer is controlled - * by the R_WATCHDOG register. The R_WATCHDOG register contains an enable bit - * and a 3-bit key value. The effect of writing to the R_WATCHDOG register is - * described in the table below: - * - * Watchdog Value written: - * state: To enable: To key: Operation: - * -------- ---------- ------- ---------- - * stopped 0 X No effect. - * stopped 1 key_val Start watchdog with key = key_val. - * started 0 ~key Stop watchdog - * started 1 ~key Restart watchdog with key = ~key. - * started X new_key_val Change key to new_key_val. - * - * Note: '~' is the bitwise NOT operator. - * - */ - -/* right now, starting the watchdog is the same as resetting it */ -#define start_watchdog reset_watchdog - -#ifdef CONFIG_ETRAX_WATCHDOG -static int watchdog_key = 0; /* arbitrary number */ -#endif - -/* number of pages to consider "out of memory". it is normal that the memory - * is used though, so put this really low. - */ - -#define WATCHDOG_MIN_FREE_PAGES 8 - -void reset_watchdog(void) -{ -#if defined(CONFIG_ETRAX_WATCHDOG) - /* only keep watchdog happy as long as we have memory left! */ - if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { - /* reset the watchdog with the inverse of the old key */ - watchdog_key ^= 0x7; /* invert key, which is 3 bits */ - *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) | - IO_STATE(R_WATCHDOG, enable, start); - } -#endif -} - -/* stop the watchdog - we still need the correct key */ - -void stop_watchdog(void) -{ -#ifdef CONFIG_ETRAX_WATCHDOG - watchdog_key ^= 0x7; /* invert key, which is 3 bits */ - *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) | - IO_STATE(R_WATCHDOG, enable, stop); -#endif -} - - -extern void cris_do_profile(struct pt_regs *regs); - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "xtime_update()" routine every clocktick - */ -static inline irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - struct pt_regs *regs = get_irq_regs(); - /* acknowledge the timer irq */ - -#ifdef USE_CASCADE_TIMERS - *R_TIMER_CTRL = - IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) | - IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) | - IO_STATE( R_TIMER_CTRL, i1, clr) | - IO_STATE( R_TIMER_CTRL, tm1, run) | - IO_STATE( R_TIMER_CTRL, clksel1, cascade0) | - IO_STATE( R_TIMER_CTRL, i0, clr) | - IO_STATE( R_TIMER_CTRL, tm0, run) | - IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz); -#else - *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i0, clr); -#endif - - /* reset watchdog otherwise it resets us! */ - reset_watchdog(); - - /* Update statistics. */ - update_process_times(user_mode(regs)); - - /* call the real timer interrupt handler */ - xtime_update(1); - - cris_do_profile(regs); /* Save profiling information */ - return IRQ_HANDLED; -} - -/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain */ - -static struct irqaction irq2 = { - .handler = timer_interrupt, - .flags = IRQF_SHARED, - .name = "timer", -}; - -void __init time_init(void) -{ - arch_gettimeoffset = cris_v10_gettimeoffset; - - /* probe for the RTC and read it if it exists - * Before the RTC can be probed the loops_per_usec variable needs - * to be initialized to make usleep work. A better value for - * loops_per_usec is calculated by the kernel later once the - * clock has started. - */ - loops_per_usec = 50; - - /* Setup the etrax timers - * Base frequency is 25000 hz, divider 250 -> 100 HZ - * In normal mode, we use timer0, so timer1 is free. In cascade - * mode (which we sometimes use for debugging) both timers are used. - * Remember that linux/timex.h contains #defines that rely on the - * timer settings below (hz and divide factor) !!! - */ - -#ifdef USE_CASCADE_TIMERS - *R_TIMER_CTRL = - IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) | - IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) | - IO_STATE( R_TIMER_CTRL, i1, nop) | - IO_STATE( R_TIMER_CTRL, tm1, stop_ld) | - IO_STATE( R_TIMER_CTRL, clksel1, cascade0) | - IO_STATE( R_TIMER_CTRL, i0, nop) | - IO_STATE( R_TIMER_CTRL, tm0, stop_ld) | - IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz); - - *R_TIMER_CTRL = r_timer_ctrl_shadow = - IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) | - IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) | - IO_STATE( R_TIMER_CTRL, i1, nop) | - IO_STATE( R_TIMER_CTRL, tm1, run) | - IO_STATE( R_TIMER_CTRL, clksel1, cascade0) | - IO_STATE( R_TIMER_CTRL, i0, nop) | - IO_STATE( R_TIMER_CTRL, tm0, run) | - IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz); -#else - *R_TIMER_CTRL = - IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) | - IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) | - IO_STATE(R_TIMER_CTRL, i1, nop) | - IO_STATE(R_TIMER_CTRL, tm1, stop_ld) | - IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) | - IO_STATE(R_TIMER_CTRL, i0, nop) | - IO_STATE(R_TIMER_CTRL, tm0, stop_ld) | - IO_STATE(R_TIMER_CTRL, clksel0, flexible); - - *R_TIMER_CTRL = r_timer_ctrl_shadow = - IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) | - IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) | - IO_STATE(R_TIMER_CTRL, i1, nop) | - IO_STATE(R_TIMER_CTRL, tm1, run) | - IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) | - IO_STATE(R_TIMER_CTRL, i0, nop) | - IO_STATE(R_TIMER_CTRL, tm0, run) | - IO_STATE(R_TIMER_CTRL, clksel0, flexible); - - *R_TIMER_PRESCALE = PRESCALE_VALUE; -#endif - - /* unmask the timer irq */ - *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer0, set); - - /* now actually register the irq handler that calls timer_interrupt() */ - setup_irq(2, &irq2); /* irq 2 is the timer0 irq in etrax */ - - /* enable watchdog if we should use one */ -#if defined(CONFIG_ETRAX_WATCHDOG) - printk("Enabling watchdog...\n"); - start_watchdog(); - - /* If we use the hardware watchdog, we want to trap it as an NMI - and dump registers before it resets us. For this to happen, we - must set the "m" NMI enable flag (which once set, is unset only - when an NMI is taken). - - The same goes for the external NMI, but that doesn't have any - driver or infrastructure support yet. */ - asm ("setf m"); - - *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set); - *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, nmi, set); -#endif -} diff --git a/arch/cris/arch-v10/kernel/traps.c b/arch/cris/arch-v10/kernel/traps.c deleted file mode 100644 index 876d45b957f4..000000000000 --- a/arch/cris/arch-v10/kernel/traps.c +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Helper functions for trap handlers - * - * Copyright (C) 2000-2007, Axis Communications AB. - * - * Authors: Bjorn Wesen - * Hans-Peter Nilsson - * - */ - -#include <linux/ptrace.h> -#include <linux/uaccess.h> -#include <linux/sched/debug.h> - -#include <arch/sv_addr_ag.h> -#include <arch/system.h> - -void -show_registers(struct pt_regs *regs) -{ - /* - * It's possible to use either the USP register or current->thread.usp. - * USP might not correspond to the current process for all cases this - * function is called, and current->thread.usp isn't up to date for the - * current process. Experience shows that using USP is the way to go. - */ - unsigned long usp = rdusp(); - - printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", - regs->irp, regs->srp, regs->dccr, usp, regs->mof); - - printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - - printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - - printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", - regs->r8, regs->r9, regs->r10, regs->r11); - - printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n", - regs->r12, regs->r13, regs->orig_r10, (long unsigned)regs); - - printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, (unsigned long)current); - - /* - * When in-kernel, we also print out the stack and code at the - * time of the fault.. - */ - if (!user_mode(regs)) { - int i; - - show_stack(NULL, (unsigned long *)usp); - - /* - * If the previous stack-dump wasn't a kernel one, dump the - * kernel stack now. - */ - if (usp != 0) - show_stack(NULL, NULL); - - printk("\nCode: "); - - if (regs->irp < PAGE_OFFSET) - goto bad_value; - - /* - * Quite often the value at regs->irp doesn't point to the - * interesting instruction, which often is the previous - * instruction. So dump at an offset large enough that the - * instruction decoding should be in sync at the interesting - * point, but small enough to fit on a row. The regs->irp - * location is pointed out in a ksymoops-friendly way by - * wrapping the byte for that address in parenthesises. - */ - for (i = -12; i < 12; i++) { - unsigned char c; - - if (__get_user(c, &((unsigned char *)regs->irp)[i])) { -bad_value: - printk(" Bad IP value."); - break; - } - - if (i == 0) - printk("(%02x) ", c); - else - printk("%02x ", c); - } - printk("\n"); - } -} - -void -arch_enable_nmi(void) -{ - asm volatile ("setf m"); -} - -extern void (*nmi_handler)(struct pt_regs *); -void handle_nmi(struct pt_regs *regs) -{ - if (nmi_handler) - nmi_handler(regs); - - /* Wait until nmi is no longer active. (We enable NMI immediately after - returning from this function, and we don't want it happening while - exiting from the NMI interrupt handler.) */ - while (*R_IRQ_MASK0_RD & IO_STATE(R_IRQ_MASK0_RD, nmi_pin, active)) - ; -} - -#ifdef CONFIG_DEBUG_BUGVERBOSE -void -handle_BUG(struct pt_regs *regs) -{ - struct bug_frame f; - unsigned char c; - unsigned long irp = regs->irp; - - if (__copy_from_user(&f, (const void __user *)(irp - 8), sizeof f)) - return; - if (f.prefix != BUG_PREFIX || f.magic != BUG_MAGIC) - return; - if (__get_user(c, f.filename)) - f.filename = "<bad filename>"; - - printk("kernel BUG at %s:%d!\n", f.filename, f.line); -} -#endif |