diff options
Diffstat (limited to 'arch/mips/vr4181')
-rw-r--r-- | arch/mips/vr4181/common/Makefile | 7 | ||||
-rw-r--r-- | arch/mips/vr4181/common/int_handler.S | 206 | ||||
-rw-r--r-- | arch/mips/vr4181/common/irq.c | 239 | ||||
-rw-r--r-- | arch/mips/vr4181/common/serial.c | 51 | ||||
-rw-r--r-- | arch/mips/vr4181/common/time.c | 145 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/Makefile | 7 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/dbg_io.c | 136 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/prom.c | 49 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/reset.c | 40 | ||||
-rw-r--r-- | arch/mips/vr4181/osprey/setup.c | 68 |
10 files changed, 948 insertions, 0 deletions
diff --git a/arch/mips/vr4181/common/Makefile b/arch/mips/vr4181/common/Makefile new file mode 100644 index 000000000000..f7587ca64ead --- /dev/null +++ b/arch/mips/vr4181/common/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for common code of NEC vr4181 based boards +# + +obj-y := irq.o int_handler.o serial.o time.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/vr4181/common/int_handler.S b/arch/mips/vr4181/common/int_handler.S new file mode 100644 index 000000000000..2c041b8ee52b --- /dev/null +++ b/arch/mips/vr4181/common/int_handler.S @@ -0,0 +1,206 @@ +/* + * arch/mips/vr4181/common/int_handler.S + * + * Adapted to the VR4181 and almost entirely rewritten: + * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar + * + * Clean up to conform to the new IRQ + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/stackframe.h> + +#include <asm/vr4181/vr4181.h> + +/* + * [jsun] + * See include/asm/vr4181/irq.h for IRQ assignment and strategy. + */ + + .text + .set noreorder + + .align 5 + NESTED(vr4181_handle_irq, PT_SIZE, ra) + + .set noat + SAVE_ALL + CLI + + .set at + .set noreorder + + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + /* we check IP3 first; it happens most frequently */ + andi t1, t0, STATUSF_IP3 + bnez t1, ll_cpu_ip3 + andi t1, t0, STATUSF_IP2 + bnez t1, ll_cpu_ip2 + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + andi t1, t0, STATUSF_IP4 + bnez t1, ll_cpu_ip4 + andi t1, t0, STATUSF_IP5 + bnez t1, ll_cpu_ip5 + andi t1, t0, STATUSF_IP6 + bnez t1, ll_cpu_ip6 + andi t1, t0, STATUSF_IP0 /* software int 0 */ + bnez t1, ll_cpu_ip0 + andi t1, t0, STATUSF_IP1 /* software int 1 */ + bnez t1, ll_cpu_ip1 + nop + + .set reorder +do_spurious: + j spurious_interrupt + +/* + * regular CPU irqs + */ +ll_cputimer_irq: + li a0, VR4181_IRQ_TIMER + move a1, sp + jal do_IRQ + j ret_from_irq + + +ll_cpu_ip0: + li a0, VR4181_IRQ_SW1 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip1: + li a0, VR4181_IRQ_SW2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip3: + li a0, VR4181_IRQ_INT1 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip4: + li a0, VR4181_IRQ_INT2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip5: + li a0, VR4181_IRQ_INT3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip6: + li a0, VR4181_IRQ_INT4 + move a1, sp + jal do_IRQ + j ret_from_irq + +/* + * One of the sys irq has happend. + * + * In the interest of speed, we first determine in the following order + * which 16-irq block have pending interrupts: + * sysint1 (16 sources, including cascading intrs from GPIO) + * sysint2 + * gpio (16 intr sources) + * + * Then we do binary search to find the exact interrupt source. + */ +ll_cpu_ip2: + + lui t3,%hi(VR4181_SYSINT1REG) + lhu t0,%lo(VR4181_SYSINT1REG)(t3) + lhu t2,%lo(VR4181_MSYSINT1REG)(t3) + and t0, 0xfffb /* hack - remove RTC Long 1 intr */ + and t0, t2 + beqz t0, check_sysint2 + + /* check for GPIO interrupts */ + andi t1, t0, 0x0100 + bnez t1, check_gpio_int + + /* so we have an interrupt in sysint1 which is not gpio int */ + li a0, VR4181_SYS_IRQ_BASE - 1 + j check_16 + +check_sysint2: + + lhu t0,%lo(VR4181_SYSINT2REG)(t3) + lhu t2,%lo(VR4181_MSYSINT2REG)(t3) + and t0, 0xfffe /* hack - remove RTC Long 2 intr */ + and t0, t2 + li a0, VR4181_SYS_IRQ_BASE + 16 - 1 + j check_16 + +check_gpio_int: + lui t3,%hi(VR4181_GPINTMSK) + lhu t0,%lo(VR4181_GPINTMSK)(t3) + lhu t2,%lo(VR4181_GPINTSTAT)(t3) + xori t0, 0xffff /* why? reverse logic? */ + and t0, t2 + li a0, VR4181_GPIO_IRQ_BASE - 1 + j check_16 + +/* + * When we reach check_16, we have 16-bit status in t0 and base irq number + * in a0. + */ +check_16: + andi t1, t0, 0xff + bnez t1, check_8 + + srl t0, 8 + addi a0, 8 + j check_8 + +/* + * When we reach check_8, we have 8-bit status in t0 and base irq number + * in a0. + */ +check_8: + andi t1, t0, 0xf + bnez t1, check_4 + + srl t0, 4 + addi a0, 4 + j check_4 + +/* + * When we reach check_4, we have 4-bit status in t0 and base irq number + * in a0. + */ +check_4: + andi t0, t0, 0xf + beqz t0, do_spurious + +loop: + andi t2, t0, 0x1 + srl t0, 1 + addi a0, 1 + beqz t2, loop + +found_it: + move a1, sp + jal do_IRQ + + j ret_from_irq + + END(vr4181_handle_irq) diff --git a/arch/mips/vr4181/common/irq.c b/arch/mips/vr4181/common/irq.c new file mode 100644 index 000000000000..2cdf77c5cb3e --- /dev/null +++ b/arch/mips/vr4181/common/irq.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + * + * linux/arch/mips/vr4181/common/irq.c + * Completely re-written to use the new irq.c + * + * Credits to Bradley D. LaRonde and Michael Klar for writing the original + * irq.c file which was derived from the common irq.c file. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/types.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/random.h> + +#include <asm/irq.h> +#include <asm/mipsregs.h> +#include <asm/gdb-stub.h> + +#include <asm/vr4181/vr4181.h> + +/* + * Strategy: + * + * We essentially have three irq controllers, CPU, system, and gpio. + * + * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and + * CONFIG_IRQ_CPU config option. + * + * We here provide sys_irq and gpio_irq controller code. + */ + +static int sys_irq_base; +static int gpio_irq_base; + +/* ---------------------- sys irq ------------------------ */ +static void +sys_irq_enable(unsigned int irq) +{ + irq -= sys_irq_base; + if (irq < 16) { + *VR4181_MSYSINT1REG |= (u16)(1 << irq); + } else { + irq -= 16; + *VR4181_MSYSINT2REG |= (u16)(1 << irq); + } +} + +static void +sys_irq_disable(unsigned int irq) +{ + irq -= sys_irq_base; + if (irq < 16) { + *VR4181_MSYSINT1REG &= ~((u16)(1 << irq)); + } else { + irq -= 16; + *VR4181_MSYSINT2REG &= ~((u16)(1 << irq)); + } + +} + +static unsigned int +sys_irq_startup(unsigned int irq) +{ + sys_irq_enable(irq); + return 0; +} + +#define sys_irq_shutdown sys_irq_disable +#define sys_irq_ack sys_irq_disable + +static void +sys_irq_end(unsigned int irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + sys_irq_enable(irq); +} + +static hw_irq_controller sys_irq_controller = { + "vr4181_sys_irq", + sys_irq_startup, + sys_irq_shutdown, + sys_irq_enable, + sys_irq_disable, + sys_irq_ack, + sys_irq_end, + NULL /* no affinity stuff for UP */ +}; + +/* ---------------------- gpio irq ------------------------ */ +/* gpio irq lines use reverse logic */ +static void +gpio_irq_enable(unsigned int irq) +{ + irq -= gpio_irq_base; + *VR4181_GPINTMSK &= ~((u16)(1 << irq)); +} + +static void +gpio_irq_disable(unsigned int irq) +{ + irq -= gpio_irq_base; + *VR4181_GPINTMSK |= (u16)(1 << irq); +} + +static unsigned int +gpio_irq_startup(unsigned int irq) +{ + gpio_irq_enable(irq); + + irq -= gpio_irq_base; + *VR4181_GPINTEN |= (u16)(1 << irq ); + + return 0; +} + +static void +gpio_irq_shutdown(unsigned int irq) +{ + gpio_irq_disable(irq); + + irq -= gpio_irq_base; + *VR4181_GPINTEN &= ~((u16)(1 << irq )); +} + +static void +gpio_irq_ack(unsigned int irq) +{ + u16 irqtype; + u16 irqshift; + + gpio_irq_disable(irq); + + /* we clear interrupt if it is edge triggered */ + irq -= gpio_irq_base; + if (irq < 8) { + irqtype = *VR4181_GPINTTYPL; + irqshift = 2 << (irq*2); + } else { + irqtype = *VR4181_GPINTTYPH; + irqshift = 2 << ((irq-8)*2); + } + if ( ! (irqtype & irqshift) ) { + *VR4181_GPINTSTAT = (u16) (1 << irq); + } +} + +static void +gpio_irq_end(unsigned int irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + gpio_irq_enable(irq); +} + +static hw_irq_controller gpio_irq_controller = { + "vr4181_gpio_irq", + gpio_irq_startup, + gpio_irq_shutdown, + gpio_irq_enable, + gpio_irq_disable, + gpio_irq_ack, + gpio_irq_end, + NULL /* no affinity stuff for UP */ +}; + +/* --------------------- IRQ init stuff ---------------------- */ + +extern asmlinkage void vr4181_handle_irq(void); +extern void breakpoint(void); +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +extern void mips_cpu_irq_init(u32 irq_base); + +static struct irqaction cascade = + { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL }; +static struct irqaction reserved = + { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL }; + +void __init arch_init_irq(void) +{ + int i; + + set_except_vector(0, vr4181_handle_irq); + + /* init CPU irqs */ + mips_cpu_irq_init(VR4181_CPU_IRQ_BASE); + + /* init sys irqs */ + sys_irq_base = VR4181_SYS_IRQ_BASE; + for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &sys_irq_controller; + } + + /* init gpio irqs */ + gpio_irq_base = VR4181_GPIO_IRQ_BASE; + for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &gpio_irq_controller; + } + + /* Default all ICU IRQs to off ... */ + *VR4181_MSYSINT1REG = 0; + *VR4181_MSYSINT2REG = 0; + + /* We initialize the level 2 ICU registers to all bits disabled. */ + *VR4181_MPIUINTREG = 0; + *VR4181_MAIUINTREG = 0; + *VR4181_MKIUINTREG = 0; + + /* disable all GPIO intrs */ + *VR4181_GPINTMSK = 0xffff; + + /* vector handler. What these do is register the IRQ as non-sharable */ + setup_irq(VR4181_IRQ_INT0, &cascade); + setup_irq(VR4181_IRQ_GIU, &cascade); + + /* + * RTC interrupts are interesting. They have two destinations. + * One is at sys irq controller, and the other is at CPU IP3 and IP4. + * RTC timer is used as system timer. + * We enable them here, but timer routine will register later + * with CPU IP3/IP4. + */ + setup_irq(VR4181_IRQ_RTCL1, &reserved); + setup_irq(VR4181_IRQ_RTCL2, &reserved); +} diff --git a/arch/mips/vr4181/common/serial.c b/arch/mips/vr4181/common/serial.c new file mode 100644 index 000000000000..3f62c62b107f --- /dev/null +++ b/arch/mips/vr4181/common/serial.c @@ -0,0 +1,51 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/vr4181/common/serial.c + * initialize serial port on vr4181. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/* + * [jsun, 010925] + * You need to make sure rs_table has at least one element in + * drivers/char/serial.c file. There is no good way to do it right + * now. A workaround is to include CONFIG_SERIAL_MANY_PORTS in your + * configure file, which would gives you 64 ports and wastes 11K ram. + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/serial.h> + +#include <asm/vr4181/vr4181.h> + +void __init vr4181_init_serial(void) +{ + struct serial_struct s; + + /* turn on UART clock */ + *VR4181_CMUCLKMSK |= VR4181_CMUCLKMSK_MSKSIU; + + /* clear memory */ + memset(&s, 0, sizeof(s)); + + s.line = 0; /* we set the first one */ + s.baud_base = 1152000; + s.irq = VR4181_IRQ_SIU; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; /* STD_COM_FLAGS */ + s.iomem_base = (u8*)VR4181_SIURB; + s.iomem_reg_shift = 0; + s.io_type = SERIAL_IO_MEM; + if (early_serial_setup(&s) != 0) { + panic("vr4181_init_serial() failed!"); + } +} + diff --git a/arch/mips/vr4181/common/time.c b/arch/mips/vr4181/common/time.c new file mode 100644 index 000000000000..17814076b6f4 --- /dev/null +++ b/arch/mips/vr4181/common/time.c @@ -0,0 +1,145 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * rtc and time ops for vr4181. Part of code is drived from + * linux-vr, originally written by Bradley D. LaRonde & Michael Klar. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/param.h> /* for HZ */ +#include <linux/time.h> +#include <linux/interrupt.h> + +#include <asm/system.h> +#include <asm/time.h> + +#include <asm/vr4181/vr4181.h> + +#define COUNTS_PER_JIFFY ((32768 + HZ/2) / HZ) + +/* + * RTC ops + */ + +DEFINE_SPINLOCK(rtc_lock); + +/* per VR41xx docs, bad data can be read if between 2 counts */ +static inline unsigned short +read_time_reg(volatile unsigned short *reg) +{ + unsigned short value; + do { + value = *reg; + barrier(); + } while (value != *reg); + return value; +} + +static unsigned long +vr4181_rtc_get_time(void) +{ + unsigned short regh, regm, regl; + + // why this crazy order, you ask? to guarantee that neither m + // nor l wrap before all 3 read + do { + regm = read_time_reg(VR4181_ETIMEMREG); + barrier(); + regh = read_time_reg(VR4181_ETIMEHREG); + barrier(); + regl = read_time_reg(VR4181_ETIMELREG); + } while (regm != read_time_reg(VR4181_ETIMEMREG)); + return ((regh << 17) | (regm << 1) | (regl >> 15)); +} + +static int +vr4181_rtc_set_time(unsigned long timeval) +{ + unsigned short intreg; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + intreg = *VR4181_RTCINTREG & 0x05; + barrier(); + *VR4181_ETIMELREG = timeval << 15; + *VR4181_ETIMEMREG = timeval >> 1; + *VR4181_ETIMEHREG = timeval >> 17; + barrier(); + // assume that any ints that just triggered are invalid, since the + // time value is written non-atomically in 3 separate regs + *VR4181_RTCINTREG = 0x05 ^ intreg; + spin_unlock_irqrestore(&rtc_lock, flags); + + return 0; +} + + +/* + * timer interrupt routine (wrapper) + * + * we need our own interrupt routine because we need to clear + * RTC1 interrupt. + */ +static void +vr4181_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* Clear the interrupt. */ + *VR4181_RTCINTREG = 0x2; + + /* call the generic one */ + timer_interrupt(irq, dev_id, regs); +} + + +/* + * vr4181_time_init: + * + * We pick the following choices: + * . we use elapsed timer as the RTC. We set some reasonable init data since + * it does not persist across reset + * . we use RTC1 as the system timer interrupt source. + * . we use CPU counter for fast_gettimeoffset and we calivrate the cpu + * frequency. In other words, we use calibrate_div64_gettimeoffset(). + * . we use our own timer interrupt routine which clears the interrupt + * and then calls the generic high-level timer interrupt routine. + * + */ + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); + +static void +vr4181_timer_setup(struct irqaction *irq) +{ + /* over-write the handler to be our own one */ + irq->handler = vr4181_timer_interrupt; + + /* sets up the frequency */ + *VR4181_RTCL1LREG = COUNTS_PER_JIFFY; + *VR4181_RTCL1HREG = 0; + + /* and ack any pending ints */ + *VR4181_RTCINTREG = 0x2; + + /* setup irqaction */ + setup_irq(VR4181_IRQ_INT1, irq); + +} + +void +vr4181_init_time(void) +{ + /* setup hookup functions */ + rtc_get_time = vr4181_rtc_get_time; + rtc_set_time = vr4181_rtc_set_time; + + board_timer_setup = vr4181_timer_setup; +} + diff --git a/arch/mips/vr4181/osprey/Makefile b/arch/mips/vr4181/osprey/Makefile new file mode 100644 index 000000000000..34be05790883 --- /dev/null +++ b/arch/mips/vr4181/osprey/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for common code of NEC Osprey board +# + +obj-y := setup.o prom.o reset.o + +obj-$(CONFIG_KGDB) += dbg_io.o diff --git a/arch/mips/vr4181/osprey/dbg_io.c b/arch/mips/vr4181/osprey/dbg_io.c new file mode 100644 index 000000000000..5e8a84072d5b --- /dev/null +++ b/arch/mips/vr4181/osprey/dbg_io.c @@ -0,0 +1,136 @@ +/* + * kgdb io functions for osprey. We use the serial port on debug board. + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/* ======================= CONFIG ======================== */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE 0xb7fffff0 +#define MAX_BAUD 115200 + +/* distance in bytes between two serial registers */ +#define REG_OFFSET 1 + +/* + * 0 - kgdb does serial init + * 1 - kgdb skip serial init + */ +static int remoteDebugInitialized = 1; + +/* + * the default baud rate *if* kgdb does serial init + */ +#define BAUD_DEFAULT UART16550_BAUD_38400 + +/* ======================= END OF CONFIG ======================== */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} diff --git a/arch/mips/vr4181/osprey/prom.c b/arch/mips/vr4181/osprey/prom.c new file mode 100644 index 000000000000..af0d14561619 --- /dev/null +++ b/arch/mips/vr4181/osprey/prom.c @@ -0,0 +1,49 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * arch/mips/vr4181/osprey/prom.c + * prom code for osprey. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <asm/bootinfo.h> +#include <asm/addrspace.h> + +const char *get_system_type(void) +{ + return "NEC_Vr41xx Osprey"; +} + +/* + * [jsun] right now we assume it is the nec debug monitor, which does + * not pass any arguments. + */ +void __init prom_init(void) +{ + // cmdline is now set in default config + // strcpy(arcs_cmdline, "ip=bootp "); + // strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 "); + // strcpy(arcs_cmdline, "ether=0,0x0300,eth0 " + // strcat(arcs_cmdline, "video=vr4181fb:xres:240,yres:320,bpp:8 "); + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_NEC_OSPREY; + + /* 16MB fixed */ + add_memory_region(0, 16 << 20, BOOT_MEM_RAM); +} + +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} diff --git a/arch/mips/vr4181/osprey/reset.c b/arch/mips/vr4181/osprey/reset.c new file mode 100644 index 000000000000..036ae83d89d6 --- /dev/null +++ b/arch/mips/vr4181/osprey/reset.c @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <asm/io.h> +#include <asm/cacheflush.h> +#include <asm/processor.h> +#include <asm/reboot.h> +#include <asm/system.h> + +void nec_osprey_restart(char *command) +{ + set_c0_status(ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void nec_osprey_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void nec_osprey_power_off(void) +{ + nec_osprey_halt(); +} diff --git a/arch/mips/vr4181/osprey/setup.c b/arch/mips/vr4181/osprey/setup.c new file mode 100644 index 000000000000..2ff7140e7ed7 --- /dev/null +++ b/arch/mips/vr4181/osprey/setup.c @@ -0,0 +1,68 @@ +/* + * linux/arch/mips/vr4181/setup.c + * + * VR41xx setup routines + * + * Copyright (C) 1999 Bradley D. LaRonde + * Copyright (C) 1999, 2000 Michael Klar + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include <linux/ide.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <asm/reboot.h> +#include <asm/vr4181/vr4181.h> +#include <asm/io.h> + + +extern void nec_osprey_restart(char* c); +extern void nec_osprey_halt(void); +extern void nec_osprey_power_off(void); + +extern void vr4181_init_serial(void); +extern void vr4181_init_time(void); + +static void __init nec_osprey_setup(void) +{ + set_io_port_base(VR4181_PORT_BASE); + isa_slot_offset = VR4181_ISAMEM_BASE; + + vr4181_init_serial(); + vr4181_init_time(); + + _machine_restart = nec_osprey_restart; + _machine_halt = nec_osprey_halt; + _machine_power_off = nec_osprey_power_off; + + /* setup resource limit */ + ioport_resource.end = 0xffffffff; + iomem_resource.end = 0xffffffff; + + /* [jsun] hack */ + /* + printk("[jsun] hack to change external ISA control register, %x -> %x\n", + (*VR4181_XISACTL), + (*VR4181_XISACTL) | 0x2); + *VR4181_XISACTL |= 0x2; + */ + + // *VR4181_GPHIBSTH = 0x2000; + // *VR4181_GPMD0REG = 0x00c0; + // *VR4181_GPINTEN = 1<<6; + + /* [jsun] I believe this will get the interrupt type right + * for the ether port. + */ + *VR4181_GPINTTYPL = 0x3000; +} + +early_initcall(nec_osprey_setup); |