diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/dbg_io.c linux.2.6.17.comcat/arch/mips/godson/ev64240/dbg_io.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/dbg_io.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/dbg_io.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,124 @@ +#include + + +#include /* For the serial port location and base baud */ + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#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 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE (0xffffffffbd000020) +#define MAX_BAUD EV64240_BASE_BAUD + +/* === END OF CONFIG === */ + +#define REG_OFFSET 4 + +/* 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); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + 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(UART16550_BAUD_115200, + 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 -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/gt-irq.c linux.2.6.17.comcat/arch/mips/godson/ev64240/gt-irq.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/gt-irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/gt-irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,172 @@ +/* + * Copyright 2003 ICT CAS + * Author: guoyi@ict.ac.cn + * + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/godson2a/gt-irq.c + * Interrupt routines for gt64240. Interrupt numbers are assigned from + * GT64240_IRQ_BASE to GT64240_IRQ_BASE+64. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GT64240_IRQ_BASE 64 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_gt64240_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (GT64240_IRQ_BASE + 32)) { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &value); + value &= ~(1 << (irq - GT64240_IRQ_BASE)); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, value); + } else { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &value); + value &= ~(1 << (irq - (GT64240_IRQ_BASE - 32))); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, value); + } +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_gt64240_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (GT64240_IRQ_BASE + 32)) { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &value); + value |= 1 << (irq - GT64240_IRQ_BASE); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, value); + } else { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &value); + value |= 1 << (irq - (GT64240_IRQ_BASE - 32)); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, value); + } +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_gt64240_irq(unsigned int irq) +{ + unmask_gt64240_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_gt64240_irq(unsigned int irq) +{ + unmask_gt64240_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_gt64240_irq(unsigned int irq) +{ + mask_gt64240_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_gt64240_irq(unsigned int irq) +{ + mask_gt64240_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_gt64240_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_gt64240_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_gt64240_irq(struct pt_regs *regs) +{ + unsigned int irq_src_low, irq_src_high; + unsigned int irq_mask_low, irq_mask_high; + + /* read the interrupt status registers */ + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &irq_mask_low); + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &irq_mask_high); + GT_READ(LOW_INTERRUPT_CAUSE_REGISTER, &irq_src_low); + GT_READ(HIGH_INTERRUPT_CAUSE_REGISTER, &irq_src_high); + /* mask for just the interrupts we want */ + irq_src_low &= irq_mask_low; + irq_src_high &= irq_mask_high; + + if (irq_src_low) + do_IRQ(ls1bit32(irq_src_low) + GT64240_IRQ_BASE, regs); + else + do_IRQ(ls1bit32(irq_src_high) + GT64240_IRQ_BASE + 32, regs); +} + +#define shutdown_gt64240_irq disable_gt64240_irq + +struct hw_interrupt_type gt64240_irq_type = { + "GT64240-decoder", + startup_gt64240_irq, + shutdown_gt64240_irq, + enable_gt64240_irq, + disable_gt64240_irq, + mask_and_ack_gt64240_irq, + end_gt64240_irq, + NULL +}; + +void gt64240_irq_init(void) +{ + int i; + + /* Reset irq handlers pointers to NULL */ + /*for (i = GT64240_IRQ_BASE; i < (GT64240_IRQ_BASE + 64); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = >64240_irq_type; + }*/ + + /* Mask out all PCI_0 interrupts so PCI_Int should only asserted by + * PCI slot + */ + GT_WRITE(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x0); + GT_WRITE(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0x0); +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/int-handler.S linux.2.6.17.comcat/arch/mips/godson/ev64240/int-handler.S --- linux.2.6.17.orig/arch/mips/godson/ev64240/int-handler.S 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/int-handler.S 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * 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. + * + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse + * + * Jazz family specific interrupt stuff + * + * To do: On Jazz machines we remap some non-ISA interrupts to ISA + * interrupts. These interrupts should use their own vectors. + * Squeeze the last cycles out of the handlers. Only a dead + * cycle is a good cycle. + */ +#include +#include +#include +#include +#include + +/* + * ev64240_handle_int: + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .set noreorder + .align 5 + NESTED(ev64240_handle_int, PT_SIZE, sp) + .set noat + SAVE_ALL + CLI + .set at + + /* + * Get pending interrupts + */ + mfc0 t0,CP0_CAUSE # get pending interrupts + mfc0 t2,CP0_STATUS # get enabled interrupts + and t0,t2 # isolate allowed ones + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + +#ifdef CONFIG_PERFCTR + andi t1, t0, STATUSF_IP6 /* cpu performance ov*/ + bnez t1, ll_perfctr_irq +#endif + andi t1, t0, STATUSF_IP5 + bnez t1, ll_8259_irq + + andi t1, t0, STATUSF_IP2 /*int0 hardware line*/ + bnez t1, ll_galileo_p0_irq + + andi t1, t0, STATUSF_IP3 /* int1 hardware line */ + bnez t1, ll_pci_1_7_irq + + andi t1, t0, STATUSF_IP4 /* int2 hardware line */ + bnez t1, ll_eth_irq + +#if 0 + andi t1, t0, STATUSF_IP6 /* int3 hardware line */ + bnez t1, ll_uart_irq +#endif + .set reorder +ll_spurious_irq: + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(ev64240_handle_int) + + .align 5 +ll_uart_irq: + li a0, 26 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cputimer_irq: + li a0, 27 + move a1, sp + jal do_IRQ + j ret_from_irq +#ifdef CONFIG_PERFCTR +ll_perfctr_irq: + li a0, 26 + move a1, sp + jal do_IRQ + j ret_from_irq +#endif + +ll_pci_1_7_irq: + li a0, 23 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_galileo_p0_irq: + li a0, 22 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_8259_irq: + li t0, 0xb4000000 + lw t1, 0xcb4(t0) + and a0, t1, 0x0f + move a1, sp + jal do_IRQ + nop + j ret_from_irq + +ll_eth_irq: + li a0, 50 + move a1, sp + jal do_IRQ + j ret_from_irq + + + li t0, 0xb4000000 + lw t1, 0xc68(t0) + andi t0, t1, 0x1 + bnez t0, ll_eth0_irq + andi t0, t1, 0x2 + bnez t0, ll_eth1_irq + andi t0, t1, 0x4 + bnez t0, ll_eth2_irq + li a0, 50 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_eth0_irq: + li a0, 17 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_eth1_irq: + li a0, 18 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_eth2_irq: + li a0, 19 + move a1, sp + jal do_IRQ + j ret_from_irq diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/irq.c linux.2.6.17.comcat/arch/mips/godson/ev64240/irq.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2003 ICT CAS (guoyi@ict.ac.cn) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef EV64240_IRQ_DEBUG +#ifdef EV64240_IRQ_DEBUG +#define DPRINTK(fmt, args...) printk(fmt, ##args) +#else +#define DPRINTK(fmt, args...) +#endif + +static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED; + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) +{ + unsigned long status; + unsigned clr_mask; + unsigned set_mask; + /* do the low 8 bits first */ + clr_mask = 0xff & clr_mask_in; + set_mask = 0xff & set_mask_in; + status = read_c0_status(); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_c0_status(status); +#if 0 + /* do the high 8 bits */ + clr_mask = 0xff & (clr_mask_in >> 8); + set_mask = 0xff & (set_mask_in >> 8); + status = read_c0_intcontrol(); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_c0_intcontrol(status); +#endif +} + +static inline void mask_irq(unsigned int irq) +{ + modify_cp0_intmask(irq, 0); +} + +static inline void unmask_irq(unsigned int irq) +{ + modify_cp0_intmask(0, irq); +} + +static void enable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&rm7000_irq_lock, flags); + unmask_irq(1 << (irq-20)); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +static unsigned int startup_cp7000_irq(unsigned int irq) +{ + enable_cp7000_irq(irq); + + return 0; /* never anything pending */ +} + +static void disable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&rm7000_irq_lock, flags); + mask_irq(1 << (irq-20)); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +#define shutdown_cp7000_irq disable_cp7000_irq + +static void mask_and_ack_cp7000_irq(unsigned int irq) +{ + mask_irq(1 << (irq-20)); +} + +static void end_cp7000_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_irq(1 << (irq-20)); +} + +static struct hw_interrupt_type cp7000_irq_type = { + .typename = "CP7000", + .startup = startup_cp7000_irq, + .shutdown = shutdown_cp7000_irq, + .enable = enable_cp7000_irq, + .disable = disable_cp7000_irq, + .ack = mask_and_ack_cp7000_irq, + .end = end_cp7000_irq, + .set_affinity = NULL +}; + +extern asmlinkage void ev64240_handle_int(void); +extern void gt64240_irq_init(void); + + +static struct irqaction cascade_i8259 = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE,//0, + .name = "cascade_i8259", + .dev_id = NULL, + .next = NULL +}; + +static struct irqaction cascade_gt64240 = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE,//0, + .name = "cascade_gt64240", + .dev_id = NULL, + .next = NULL +}; +static struct irqaction cascade_gt64240_mpp = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE,//0, + .name = "cascade_gt64240_mpp", + .dev_id = NULL, + .next = NULL +}; + +#define CPU_IRQ_MAX 27 + +void __init arch_init_irq(void) +{ + int i; + + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM | ST0_BEV); + modify_cp0_intmask(0xff, 0); + cli(); + + /* Sets the first-level interrupt dispatcher. */ + set_except_vector(0, ev64240_handle_int); + +/* for (i = 20; i <= CPU_IRQ_MAX; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &cp7000_irq_type; + }*/ + + mips_cpu_irq_init(20); + gt64240_irq_init(); //???lixy? + init_i8259_irqs(); + + setup_irq(24, &cascade_i8259); + setup_irq(25, &cascade_gt64240); + +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); +#endif + +#ifdef CONFIG_KGDB + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/Makefile linux.2.6.17.comcat/arch/mips/godson/ev64240/Makefile --- linux.2.6.17.orig/arch/mips/godson/ev64240/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/Makefile 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,10 @@ +# +# Makefile for ICT CAS godsonev2a board. +# + +obj-y += int-handler.o irq.o gt-irq.o prom.o reset.o setup.o pci.o rtc.o +obj-$(CONFIG_EXTERNAL_CACHE) += tc-godson2a.o +#obj-$(CONFIG_KGDB) += dbg_io.o +obj-y += dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/pci.c linux.2.6.17.comcat/arch/mips/godson/ev64240/pci.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/pci.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/pci.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * pci.c + * + * Copyright (C) 2004 ICT CAS + * Author: Lin Wei, ICT CAS + * wlin@ict.ac.cn + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include + +#include + +extern struct pci_ops godson2a_pci0_pci_ops; +extern struct pci_ops godson2a_pci1_pci_ops; + + +static struct resource godson2a_pci0_mem_resource = { + .name = "GODSON2A PCI0 MEM", + .start = 0x12000000UL, + .end = 0x137fffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource godson2a_pci0_io_resource = { + .name = "GODSON2A PCI0 IO MEM", + .start = 0x00100000UL, + .end = 0x001fffffUL, + .flags = IORESOURCE_IO, +}; + +static struct resource godson2a_pci1_mem_resource = { + .name = "GODSON2A PCI1 MEM", + .start = 0x10800000UL, + .end = 0x11ffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource godson2a_pci1_io_resource = { + .name = "GODSON2A PCI1 IO MEM", + .start = 0x00001000UL, + .end = 0x0000ffffUL, + .flags = IORESOURCE_IO, +}; + +static struct pci_controller godson2a_pci0_controller = { + .pci_ops = &godson2a_pci0_pci_ops, + .io_resource = &godson2a_pci0_io_resource, + .mem_resource = &godson2a_pci0_mem_resource, + .mem_offset = 0x00000000UL, + .io_offset = 0x00000000UL, +}; + +static struct pci_controller godson2a_pci1_controller = { + .pci_ops = &godson2a_pci1_pci_ops, + .io_resource = &godson2a_pci1_io_resource, + .mem_resource = &godson2a_pci1_mem_resource, + .mem_offset = 0x00000000UL, + .io_offset = 0x00000000UL, +}; + +static int __init pcibios_init(void) +{ + extern int pci_probe_only; + + pci_probe_only = 1; + +#ifdef CONFIG_TRACE_BOOT + prom_printf("arch_initcall:pcibios_init\n"); + prom_printf("register_pci_controller : %x\n",&godson2a_pci0_controller); + prom_printf("register_pci_controller : %x\n",&godson2a_pci1_controller); +#endif + register_pci_controller(&godson2a_pci0_controller); + register_pci_controller(&godson2a_pci1_controller); + return 0; +} + +arch_initcall(pcibios_init); + + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/prom.c linux.2.6.17.comcat/arch/mips/godson/ev64240/prom.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/prom.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/prom.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,108 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * Copyright 2003 ICT CAS + * Author: Michael Guo + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include + +extern char arcs_cmdline[CL_SIZE]; + +extern unsigned long bus_clock; +extern unsigned long cpu_clock; +extern int putDebugChar(unsigned char byte); +extern void prom_printf(char *fmt, ...); + +int argc; +char **arg; +char **env; + +const char *get_system_type(void) +{ + return "ICT CAS GodsonEV2a"; +} + +void __init prom_init_cmdline(void) +{ + int i; + /* some 64bit toolchain can't convert int to a pointer correctly */ + long l; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + l = arg[i]; + if (strlen(arcs_cmdline) + strlen(((char*)l) + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ((char*)l)); + strcat(arcs_cmdline, " "); + } +} + +void __init prom_init(void) +{ + long l; + argc=fw_arg0; + arg=(char **)fw_arg1; + env=(char **)fw_arg2; + + prom_printf("Booting Linux kernel...\n"); + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64240A; + + prom_init_cmdline(); + if((strstr(arcs_cmdline, "console=")) == NULL) + strcat(arcs_cmdline, "console=ttyS0,115200"); + + l = *env; + while (l!=0) { + if (strncmp("gtbase", (char*)l, strlen("gtbase")) == 0) { + gt64240_base = simple_strtol((char*)l + strlen("gtbase="), + NULL, 16); + } + if (strncmp("busclock", (char*)l, strlen("busclock")) == 0) { + bus_clock = simple_strtol((char*)l + strlen("busclock="), + NULL, 10); + } + if (strncmp("cpuclock", (char*)l, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol((char*)l + strlen("cpuclock="), + NULL, 10); + } + env++; + l=*env; + } + + prom_printf("Booting Linux kernel...\n"); + prom_printf("gtbase=%x, busclock=%x, cpuclock=%x\n",gt64240_base, bus_clock, cpu_clock); +} + +void __init prom_free_prom_memory(void) +{ + return 0; +} + +void prom_putchar(char c) +{ + putDebugChar(c); +} + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/reset.c linux.2.6.17.comcat/arch/mips/godson/ev64240/reset.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/reset.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/reset.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * 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. + * Copyright 2003 ICT CAS + * Author: jsun@mvista.com or jsun@junsun.net + * guoyi@ict.ac.cn + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void ev64240_restart(char *command) +{ + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void ev64240_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); +#ifndef CONFIG_CPU_GODSON2 + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +#else + while(1); +#endif +} + +void ev64240_power_off(void) +{ + ev64240_halt(); +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/rtc.c linux.2.6.17.comcat/arch/mips/godson/ev64240/rtc.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/rtc.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/rtc.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright 2003 ICT CAS. + * Author: Michael Guo, guoyi@ict.ac.cn + * + * EV64240 DS1501 RTC routines. + * + * 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 +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_RTC +#include +#endif +#include +//#ifdef CONFIG_RTC +#include +//#endif +#include + +unsigned long rtc_base; + +#define RTC_WRITE(ofs, data) \ + *(volatile u8 *)(rtc_base+(ofs)) = data +#define RTC_READ(ofs) \ + (*(volatile u8 *)(rtc_base+(ofs))) + + +#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf)) +#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10)) + + +unsigned long ev64240_get_time(void); +int ev64240_set_time(unsigned long time); + +unsigned long ev64240_get_time(void) +{ + int ctrlbsave; + int year, mon, day, hour, min, sec; + /* Freeze readout data regs */ + ctrlbsave = RTC_READ(DS_REG_CTLB); + RTC_WRITE(DS_REG_CTLB, ctrlbsave & ~DS_CTLB_TE); + + sec = FROMBCD(RTC_READ(DS_REG_SEC)); + min = FROMBCD(RTC_READ(DS_REG_MIN)); + hour = FROMBCD(RTC_READ(DS_REG_HOUR)); + day = FROMBCD(RTC_READ(DS_REG_DATE)); + mon = FROMBCD(RTC_READ(DS_REG_MONTH) & 0x1f); + year = FROMBCD(RTC_READ(DS_REG_YEAR)); + year += 100 * (FROMBCD(RTC_READ(DS_REG_CENT))); + + RTC_WRITE(DS_REG_CTLB, ctrlbsave | DS_CTLB_TE); + return mktime(year, mon, day, hour, min, sec); +} + +int ev64240_set_time(unsigned long t) +{ + struct rtc_time tm; + int ctrlbsave; + to_tm(t, &tm); + + /* Enable register writing */ + ctrlbsave = RTC_READ(DS_REG_CTLB); + RTC_WRITE(DS_REG_CTLB, ctrlbsave & ~DS_CTLB_TE); + + RTC_WRITE(DS_REG_CENT, TOBCD(tm.tm_year / 100)); + RTC_WRITE(DS_REG_YEAR, TOBCD(tm.tm_year % 100)); + RTC_WRITE(DS_REG_MONTH,TOBCD(tm.tm_mon + 1)); + RTC_WRITE(DS_REG_DATE, TOBCD(tm.tm_mday)); + RTC_WRITE(DS_REG_WDAY, TOBCD(tm.tm_wday)); + RTC_WRITE(DS_REG_HOUR, TOBCD(tm.tm_hour)); + RTC_WRITE(DS_REG_MIN, TOBCD(tm.tm_min)); + RTC_WRITE(DS_REG_SEC, TOBCD(tm.tm_sec)); + + /* Transfer new time to counters */ + RTC_WRITE(DS_REG_CTLB, ctrlbsave | DS_CTLB_TE); + return 0; +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/setup.c linux.2.6.17.comcat/arch/mips/godson/ev64240/setup.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/setup.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/setup.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,245 @@ +/* + * BRIEF MODULE DESCRIPTION + * GodsonEV2a - board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 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. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_IDE +#include +#endif +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_BLK_DEV_FD +#include +#endif +#include +#ifdef CONFIG_VT +#include +#endif +#ifdef CONFIG_PC_KEYB +#include +#endif +#include +#include +#include + +extern void prom_printf(char *fmt, ...); + + +#ifdef CONFIG_64BIT +#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p))) +#else +#define PTR_PAD(p) (p) +#endif + +#ifdef CONFIG_VT +extern struct screen_info screen_info; +#endif + +extern unsigned long rtc_base; +unsigned long gt64240_base; +unsigned long cpu_clock; +unsigned long bus_clock; + +struct { + struct resource ram; + struct resource pci_mem; + struct resource pci_io; + struct resource flash; + struct resource boot; +}ev64240_resources = { + { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */ + { "PCI Mem", 0x10800000, 0x137FFFFF, IORESOURCE_MEM }, + { "PCI I/O", 0x00000000, 0x001FFFFF }, + { "Flash", 0x08000000, 0x0CFFFFFF }, + { "Boot ROM", 0x1FC00000, 0x1FFFFFFF } +}; + + +unsigned long gt64240_scs[4][2]={{SCS_0_LOW_DECODE_ADDRESS, + SCS_0_HIGH_DECODE_ADDRESS}, + {SCS_1_LOW_DECODE_ADDRESS, + SCS_1_HIGH_DECODE_ADDRESS}, + {SCS_2_LOW_DECODE_ADDRESS, + SCS_2_HIGH_DECODE_ADDRESS}, + {SCS_3_LOW_DECODE_ADDRESS, + SCS_3_HIGH_DECODE_ADDRESS}}; + +/* These functions are used for rebooting or halting the machine*/ +extern void ev64240_restart(char *command); +extern void ev64240_halt(void); +extern void ev64240_power_off(void); +extern void __init setup_l3cache(unsigned long size); +extern unsigned long ev64240_get_time(void); +extern int ev64240_set_time(unsigned long); + + +void ev64240_timer_setup(struct irqaction *irq) +{ + setup_irq(27, irq); +} + +void ev64240_time_init(void) +{ + /* setup mips r4k timer */ + mips_hpt_frequency = cpu_clock / 2; + + /* setup low-lever RTC functionality */ + rtc_base=PTR_PAD(0xbc800000); + rtc_get_time=ev64240_get_time; + rtc_set_time=ev64240_set_time; +} +static void wbflush_godson2(void) +{ +#if 1 + *(volatile unsigned long *)KSEG1; + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "sync\n\t" + "nop\n\t" + ".set\tpop"); +#endif +} + +void (*__wbflush) (void); + +static int __init ev64240_setup(void) +{ +#if defined (CONFIG_CPU_RM7000) || defined (CONFIG_EXTERNAL_CACHE) + void (*l3func)(unsigned long)=(void (*)(unsigned long))KSEG1ADDR(&setup_l3cache); +#endif + + unsigned int i; + unsigned int scs,baselo,basehi; + prom_printf("Marvell Ev64240-board\n"); + + /* Reset PCI I/O and PCI MEM values */ + set_io_port_base(PTR_PAD(0xb0100000)); + + ioport_resource.start = ev64240_resources.pci_io.start; + ioport_resource.end = ev64240_resources.pci_io.end; + iomem_resource.start = ev64240_resources.pci_mem.start; + iomem_resource.end = ev64240_resources.pci_mem.end; + + /* + * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge. + */ + enable_dma(4); + + + board_time_init = ev64240_time_init; + board_timer_setup = ev64240_timer_setup; + + _machine_restart = ev64240_restart; + _machine_halt = ev64240_halt; + _machine_power_off = ev64240_power_off; + + __wbflush=wbflush_godson2; + + /* Set the memory size based on SCS decode registers set by PMON */ + for(scs = 0; scs < 3; scs++) { + GT_READ(gt64240_scs[scs][0], &baselo); + GT_READ(gt64240_scs[scs][1], &basehi); + if (basehi > baselo) { + baselo = baselo<<20; + basehi = (basehi + 1)<<20; + prom_printf(" - SCS%d: %dMB\n", scs, (basehi - baselo)>>20); + add_memory_region(baselo, (basehi - baselo), BOOT_MEM_RAM); + } + } + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + gt64240_base = PTR_PAD(0xb4000000); + +#ifdef CONFIG_EXTERNAL_CACHE + prom_printf(" - L3 Cache size: %d MiB\n", L3_CACHE_SIZE>>20); + l3func(L3_CACHE_SIZE); +#endif + +#ifdef CONFIG_CPU_RM7000 + prom_printf(" - L3 Cache size: %d MiB\n", L3_CACHE_SIZE>>20); + prom_printf("L3 cache not enabled\n"); + //l3func(L3_CACHE_SIZE); +#endif + +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; + + screen_info = (struct screen_info) { + 0, 25, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0,0,0, /* ega_ax, ega_bx, ega_cx */ + 25, /* orig-video-lines */ + VIDEO_TYPE_VGAC, /* orig-video-isVGA */ + 16 /* orig-video-points */ + }; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +#endif + + + return 0; +} + +early_initcall(ev64240_setup); diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64240/tc-godson2a.c linux.2.6.17.comcat/arch/mips/godson/ev64240/tc-godson2a.c --- linux.2.6.17.orig/arch/mips/godson/ev64240/tc-godson2a.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64240/tc-godson2a.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,213 @@ +/* + * BRIEF MODULE DESCRIPTION + * GodsonEV2a - board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 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. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void prom_printf(char *fmt, ...); + + + +/* sd to physical address ffffffff8 will cause a page invalidate + * sd to physical address ffffffff0 will cause a clear. + * We use unmapped uncached address space 0x9000000000000000- + * 0x9000000fffffffff to produce needed physical address + */ +void godson2_invalidate_external_cache_page(unsigned long addr) +{ + unsigned long paddr; + paddr = virt_to_phys(addr); +#ifdef CONFIG_64BIT + __asm__ volatile ( + ".set mips3\n\t" + "li $2,0x90000010\n\t" + "dsll32 $2,$2,0\n\t" + "dsubu $2,$2,8\n\t" + "sd %0,0($2)\n\t" + ".set mips0\n\t" + ::"r"(paddr):"$2"); +#else + __asm__ volatile ( + ".set mips3\n\t" + "li $2,0x90000010\n\t" + "dsll32 $2,$2,0\n\t" + "dsubu $2,$2,8\n\t" + "daddiu $3, $0, 0xffff\n\t" + "dsrl32 $3, $3, 0\n\t" + "and $3, $3, %0\n\t" + "sd $3,0($2)\n\t" + ".set mips0\n\t" + ::"r"(paddr):"$2", "$3"); +#endif +} + +/* + * Writeback and invalidate the primary cache dcache before DMA. + */ +static void godson2_tc_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + +#ifdef DEBUG_CACHE + printk("godson2_tc_wback_inv[%08lx,%08lx]", addr, size); +#endif + a = addr & ~(tc_pagesize - 1); + end = (addr + size - 1) & ~(tc_pagesize - 1); + while (1) { + godson2_invalidate_external_cache_page(a); + if (a == end) + break; + a += tc_pagesize; + } +} + +static void godson2_tc_inv(unsigned long addr, unsigned long size) +{ + godson2_tc_wback_inv(addr,size); +} + +static __init void godson2_tc_enable(void) +{ + unsigned long tmp; +#ifdef CONFIG_GODSON2_SRAM_TYPE_SCD + /* extend DCE interface signal by one cycle in the CPU */ + set_c0_config(1 << 13); +#else + clear_c0_config(1<<13); +#endif + set_c0_config(1<<12); + + GT_READ(CPU_CONFIGURATION, &tmp); + GT_WRITE(CPU_CONFIGURATION, tmp | (1<<14)); + + for (tmp=0;tmp> 10), tc_lsize); + + return 1; +} + +struct bcache_ops godson2_tc_ops = { + .bc_enable = godson2_tc_enable, + .bc_disable = godson2_tc_disable, + .bc_wback_inv = godson2_tc_wback_inv, + .bc_inv = godson2_tc_inv +}; + +void __init godson2_tc_init(void) +{ + if (godson2_tc_probe()) { + //godson2_tc_enable(); + prom_printf("set L2 cache funcs\n"); + bcops = &godson2_tc_ops; + } +} + +/* + * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() + */ +#define Page_Invalidate_T 0x16 +void __init setup_l3cache(unsigned long size) +{ + unsigned int tmp; + int register i; + + printk("Enabling L3 cache..."); + +#ifdef CONFIG_SPLIT_READ + /* Enable the split read support in the GT64240A's CPU Configuration register */ + GT_READ(CPU_CONFIGURATION, &tmp); + GT_WRITE(CPU_CONFIGURATION, tmp | (1<<13)); + + prom_printf("Split read enabled\n"); +#endif + +#ifdef CONFIG_GODSON2_SRAM_TYPE_SCD + /* extend DCE interface signal by one cycle in the CPU */ + set_c0_config(1<<13); +#else /* DCD */ + clear_c0_config(1<<13); +#endif + + /* Enable the L3 cache in the CPU */ + set_c0_config(1<<12 /* CONF_TE */); + + __asm__ __volatile__ (".set\tnoat\n" + "lui\t$1, 0xb400\n" + "lw\t%0, 0x0($1)\n" + "ori\t%0, %0, 0x4000\n" + "sw\t%0, 0x0($1)\n" + ".set\tat\n" + :"=&r"(tmp)); + + for (i=0; i < L3_CACHE_SIZE; i+= 4096) { + godson2_invalidate_external_cache_page(KSEG0+i); + } + + read_c0_prid(); + printk("external cache flushed\n"); +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/dbg_io.c linux.2.6.17.comcat/arch/mips/godson/ev64420/dbg_io.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/dbg_io.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/dbg_io.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,147 @@ +#include + + +#include /* For the serial port location and base baud */ + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#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 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE (0xffffffffb01003f8) +#define MAX_BAUD BASE_BAUD + +/* === END OF CONFIG === */ + +#define REG_OFFSET 1 + +/* 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) + +#if 0 +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); +} + +static int remoteDebugInitialized = 0; + + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + 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(UART16550_BAUD_115200, + 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; +} + +#else + +extern char mpsc_getchar_debug(void); +extern int mpsc_putchar_early(char ch); +uint8 getDebugChar(void) +{ + uint8 byte; + //printk("getchar"); + byte = mpsc_getchar_debug(); + //printk("%x",byte); + return byte; +} + +int putDebugChar(uint8 byte) +{ + //printk("putchar %x\n",byte); + mpsc_putchar_early(byte); +} + +#endif + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/gt-irq.c linux.2.6.17.comcat/arch/mips/godson/ev64420/gt-irq.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/gt-irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/gt-irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,186 @@ +/* + * Copyright 2003 ICT CAS + * Author: guoyi@ict.ac.cn + * + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/ev64420/gt-irq.c + * Interrupt routines for gt64420. Interrupt numbers are assigned from + * GT64420_IRQ_BASE to GT64420_IRQ_BASE+64. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GT64420_IRQ_BASE 64 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_gt64420_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (GT64420_IRQ_BASE + 32)) { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &value); + value &= ~(1 << (irq - GT64420_IRQ_BASE)); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, value); + } else { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &value); + value &= ~(1 << (irq - (GT64420_IRQ_BASE - 32))); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, value); + } +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_gt64420_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (GT64420_IRQ_BASE + 32)) { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &value); + value |= 1 << (irq - GT64420_IRQ_BASE); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, value); + } else { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &value); + value |= 1 << (irq - (GT64420_IRQ_BASE - 32)); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, value); + } +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_gt64420_irq(unsigned int irq) +{ + unmask_gt64420_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_gt64420_irq(unsigned int irq) +{ + unmask_gt64420_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_gt64420_irq(unsigned int irq) +{ + mask_gt64420_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_gt64420_irq(unsigned int irq) +{ + mask_gt64420_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_gt64420_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_gt64420_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_gt64420_irq(struct pt_regs *regs) +{ + unsigned int irq_src_low, irq_src_high; + unsigned int irq_mask_low, irq_mask_high; + + /* read the interrupt status registers */ + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &irq_mask_low); + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &irq_mask_high); + GT_READ(LOW_INTERRUPT_CAUSE_REGISTER, &irq_src_low); + GT_READ(HIGH_INTERRUPT_CAUSE_REGISTER, &irq_src_high); + /* mask for just the interrupts we want */ + irq_src_low &= irq_mask_low; + irq_src_high &= irq_mask_high; + + if (irq_src_low) + do_IRQ(ls1bit32(irq_src_low) + GT64420_IRQ_BASE, regs); + else + do_IRQ(ls1bit32(irq_src_high) + GT64420_IRQ_BASE + 32, regs); +} + +#define shutdown_gt64420_irq disable_gt64420_irq + +struct hw_interrupt_type gt64420_irq_type = { + "GT64420-decoder", + startup_gt64420_irq, + shutdown_gt64420_irq, + enable_gt64420_irq, + disable_gt64420_irq, + mask_and_ack_gt64420_irq, + end_gt64420_irq, + NULL +}; + +static struct irqaction cascade_gt64420_mpp = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE,//0, + .name = "cascade_gt64420_mpp", + .dev_id = NULL, + .next = NULL +}; + +void gt64420_irq_init(void) +{ + int i; + + /* Reset irq handlers pointers to NULL */ + for (i = GT64420_IRQ_BASE; i < (GT64420_IRQ_BASE + 64); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = >64420_irq_type; + } + + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH,0x0); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, 0x0); + GT_WRITE(LOW_INTERRUPT_CAUSE_REGISTER, 0); + GT_WRITE(HIGH_INTERRUPT_CAUSE_REGISTER, 0); + + /* mpsc0 and MPP28-31(MPP28~31 are connected to PCI int) + * high register, bit8,27 + */ + /* we use via686b interrupt controller */ + //setup_irq(64 + 32 + 27, &cascade_gt64420_mpp); +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/gt-mpp-irq.c linux.2.6.17.comcat/arch/mips/godson/ev64420/gt-mpp-irq.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/gt-mpp-irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/gt-mpp-irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,170 @@ +/* + * Copyright 2003 ICT CAS + * Author: guoyi@ict.ac.cn + * + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/ev64420/gt-mpp-irq.c + * Interrupt routines for gt64420 MPP. Interrupt numbers are assigned from + * GT64420_MPP_IRQ_BASE to GT64420_MPP_IRQ_BASE+32. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GT64420_MPP_IRQ_BASE 32 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +static inline void ack_gt64420_mpp_irq(unsigned int irq) +{ + uint32_t value; + //write cause reg + GT_READ(GPP_INTERRUPT_CAUSE, &value); + value &= ~(1 << (irq - GT64420_MPP_IRQ_BASE)); + GT_WRITE(GPP_INTERRUPT_CAUSE, value); + +} +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_gt64420_mpp_irq(unsigned int irq) +{ + uint32_t value; + + GT_READ(GPP_INTERRUPT_MASK, &value); + value &= ~(1 << (irq - GT64420_MPP_IRQ_BASE)); + GT_WRITE(GPP_INTERRUPT_MASK, value); +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_gt64420_mpp_irq(unsigned int irq) +{ + uint32_t value; + + GT_READ(GPP_INTERRUPT_MASK, &value); + value |= 1 << (irq - GT64420_MPP_IRQ_BASE); + GT_WRITE(GPP_INTERRUPT_MASK, value); +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_gt64420_mpp_irq(unsigned int irq) +{ + unmask_gt64420_mpp_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_gt64420_mpp_irq(unsigned int irq) +{ + unmask_gt64420_mpp_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_gt64420_mpp_irq(unsigned int irq) +{ + mask_gt64420_mpp_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_gt64420_mpp_irq(unsigned int irq) +{ + mask_gt64420_mpp_irq(irq); + ack_gt64420_mpp_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_gt64420_mpp_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_gt64420_mpp_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_gt64420_mpp_irq(struct pt_regs *regs) +{ + unsigned int irq_src; + unsigned int irq_mask; + + /* read the interrupt status registers */ + GT_READ(GPP_INTERRUPT_MASK, &irq_mask); + GT_READ(GPP_INTERRUPT_CAUSE, &irq_src); + + /* mask for just the interrupts we want */ + irq_src &= irq_mask; + + if (irq_src) + do_IRQ(ls1bit32(irq_src) + GT64420_MPP_IRQ_BASE, regs); +} + +#define shutdown_gt64420_mpp_irq disable_gt64420_mpp_irq + +struct hw_interrupt_type gt64420_mpp_irq_type = { + "GT64420-MPP", + startup_gt64420_mpp_irq, + shutdown_gt64420_mpp_irq, + enable_gt64420_mpp_irq, + disable_gt64420_mpp_irq, + mask_and_ack_gt64420_mpp_irq, + end_gt64420_mpp_irq, + NULL +}; + +void gt64420_mpp_irq_init(void) +{ + int i; + uint32_t value; + + /* Reset irq handlers pointers to NULL */ + for (i = GT64420_MPP_IRQ_BASE; i < (GT64420_MPP_IRQ_BASE + 32); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = >64420_mpp_irq_type; + } + + /* Set MPP interrupt to level-sensitive */ + GT_READ(COMM_UNIT_ARBITER_CONTROL, &value); + value |= (1 << 10); + GT_WRITE(COMM_UNIT_ARBITER_CONTROL, value); + + GT_WRITE(GPP_INTERRUPT_CAUSE,0); + GT_WRITE(GPP_INTERRUPT_MASK, 0x0); + +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/int-handler.S linux.2.6.17.comcat/arch/mips/godson/ev64420/int-handler.S --- linux.2.6.17.orig/arch/mips/godson/ev64420/int-handler.S 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/int-handler.S 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * 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. + * + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse + * + * Jazz family specific interrupt stuff + * + * To do: On Jazz machines we remap some non-ISA interrupts to ISA + * interrupts. These interrupts should use their own vectors. + * Squeeze the last cycles out of the handlers. Only a dead + * cycle is a good cycle. + */ +#include +#include +#include +#include +#include +#include + +/* + * ev64420_handle_int: + * We check for the timer first, then check 8259 interrupts + * Then fall through. + * interrupt routing: + * 8259(via686b) wired to hw int0 + * CPU_INTn(64420) wired to hw int1 + * SMI(via686b) wired to hw int3 + */ +.set noreorder + .align 5 +NESTED(ev64420_handle_int, PT_SIZE, sp) + .set noat + SAVE_ALL + CLI + .set at + + /* + * Get pending interrupts + */ + mfc0 t0,CP0_CAUSE # get pending interrupts + mfc0 t2,CP0_STATUS # get enabled interrupts + and t0,t2 # isolate allowed ones + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq +#ifdef CONFIG_PERFCTR + andi t1, t0, STATUSF_IP6 /* cpu performance ov*/ + bnez t1, ll_perfctr_irq +#endif + + andi t1, t0, STATUSF_IP2 /*int0 hardware line*/ + bnez t1, ll_8259_irq + + + andi t1, t0, STATUSF_IP3 /* int1 hardware line */ + bnez t1, ll_gt64420_decode_irq + nop + + .set reorder + ll_spurious_irq: + /* wrong alarm or masked ... */ + j spurious_interrupt + nop +END(ev64420_handle_int) + +ll_cputimer_irq: + li a0, 27 + move a1, sp + jal do_IRQ + j ret_from_irq + +#ifdef CONFIG_PERFCTR +ll_perfctr_irq: + li a0, 26 + move a1, sp + jal do_IRQ + j ret_from_irq +#endif + +ll_8259_irq: + li t0, GT_BASE_ADDR + lw t1, 0xc34(t0) + and a0, t1, 0x0f + move a1, sp + jal do_IRQ + nop + j ret_from_irq + +ll_gt64420_decode_irq: + move a0, sp + jal ll_gt64420_irq + j ret_from_irq + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/irq.c linux.2.6.17.comcat/arch/mips/godson/ev64420/irq.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2003 ICT CAS (guoyi@ict.ac.cn) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#undef EV64420_IRQ_DEBUG +#ifdef EV64420_IRQ_DEBUG +#define DPRINTK(fmt, args...) printk(fmt, ##args) +#else +#define DPRINTK(fmt, args...) +#endif + +static struct irqaction cascade_i8259 = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE,//0, + .name = "cascade_i8259", + .dev_id = NULL, + .next = NULL +}; + +static struct irqaction cascade_gt64420 = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE,//0, + .name = "cascade_gt64420", + .dev_id = NULL, + .next = NULL +}; + +extern asmlinkage void ev64420_handle_int(void); +extern void gt64420_irq_init(void); + +void __init arch_init_irq(void) +{ + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM | ST0_BEV); + local_irq_disable(); + + /* Sets the first-level interrupt dispatcher. */ + set_except_vector(0, ev64420_handle_int); + + /* irq allocation scheme: + * 0-15: 8259 irqs, via686b int output wired to hw int0 + * pci interrupts is wired to 686b. + * 20-27: mips cpu irqs. For now we use IP7(27) as timer interrupts + * 32-64: 64420 irqs. For now we may use mpsc interrupts and MPP28-31(PCIA-D),all located in + * high cause/mask + */ + init_i8259_irqs(); + mips_cpu_irq_init(20); + gt64420_irq_init(); + + setup_irq(22,&cascade_i8259); + setup_irq(23,&cascade_gt64420); + +#ifdef CONFIG_KGDB + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif + + printk("arch_init_irq done\n"); +} + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/Makefile linux.2.6.17.comcat/arch/mips/godson/ev64420/Makefile --- linux.2.6.17.orig/arch/mips/godson/ev64420/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/Makefile 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,10 @@ +# +# Makefile for ICT CAS godsonev2a board. +# + +obj-y += int-handler.o irq.o gt-irq.o gt-mpp-irq.o prom.o reset.o setup.o pci.o mipsdha.o mpsc.o +#obj-$(CONFIG_KGDB) += dbg_io.o +obj-$(CONFIG_EXTERNAL_CACHE) += tc-godson2a.o +obj-y += dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/mipsdha.c linux.2.6.17.comcat/arch/mips/godson/ev64420/mipsdha.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/mipsdha.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/mipsdha.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t mipsdha_proc_read(struct file *file, char *buf, size_t len, loff_t *ppos); + +static ssize_t mipsdha_proc_write(struct file *file, const char *buf, size_t len, loff_t *ppos); + + +static struct proc_dir_entry *mipsdha_proc_entry; + +#define INFO_SIZE 4096 +static char info_buf[INFO_SIZE]; + +static struct file_operations mipsdha_fops = +{ + owner: THIS_MODULE, + read: mipsdha_proc_read, + write: mipsdha_proc_write, +}; + +static enum {CMD_ERR, CMD_GIB, CMD_GPI} cmd; + +typedef struct pciinfo_s +{ + int bus,card,func; + unsigned short command; + unsigned short vendor,device; + unsigned base0,base1,base2,baserom; +} pciinfo_t; + + +static int __init mipsdha_proc_init(void) +{ + mipsdha_proc_entry = create_proc_entry("mipsdha", S_IWUSR | S_IRUGO, &proc_root); + if (mipsdha_proc_entry == NULL) { + printk("MIPSDHA: register /proc/mipsdha failed!\n"); + return 0; + } + + mipsdha_proc_entry->owner = THIS_MODULE; + mipsdha_proc_entry->proc_fops = &mipsdha_fops; + + cmd=CMD_ERR; + return 0; +} + +static ssize_t mipsdha_proc_write (struct file *file, const char *buf, size_t len, loff_t *ppos) +{ + char cmd_gib[]="GET IO BASE"; + char cmd_gpi[]="GET PCI INFO"; + + if (len >= INFO_SIZE) return -ENOMEM; + + if (copy_from_user(info_buf, buf, len)) return -EFAULT; + info_buf[len] = '\0'; + + if (strncmp(info_buf, cmd_gib, sizeof(cmd_gib)-1)==0) { + cmd = CMD_GIB; + return len; + } else if (strncmp(info_buf, cmd_gpi, sizeof(cmd_gpi)-1)==0) { + cmd = CMD_GPI; + return len; + } else { + return -EINVAL; + } +} + +static ssize_t mipsdha_proc_read (struct file *file, char *buf, size_t len, loff_t *ppos) +{ + int info_cnt; + pciinfo_t *pciinfo; + struct pci_dev *dev = NULL; + + switch (cmd) { + default: + printk("MIPSDHA: BUG found in function %s!(cmd=%d)\n", + __FUNCTION__, cmd); + return -EINVAL; + + + case CMD_ERR: + return -EINVAL; + + + case CMD_GIB: + *(unsigned long *)info_buf = + virt_to_phys((void *) mips_io_port_base); + info_cnt=sizeof(unsigned long); + break; + + + case CMD_GPI: + pciinfo = (pciinfo_t *) info_buf; + info_cnt = 0; + for_each_pci_dev(dev) { + + if (info_cnt+sizeof(pciinfo_t)>INFO_SIZE) return -ENOMEM; + + pciinfo->bus = dev->bus->number; + pciinfo->card = PCI_SLOT(dev->devfn); + pciinfo->func = PCI_FUNC(dev->devfn); + + if (pci_read_config_word(dev, PCI_COMMAND, &pciinfo->command) + != PCIBIOS_SUCCESSFUL) { + printk("MIPSDHA: BUG found in function %s!\n", + __FUNCTION__); + pciinfo->command=0; + } + + pciinfo->vendor = dev->vendor; + pciinfo->device = dev->device; + + pciinfo->base0 = (dev->resource[0]).start; + pciinfo->base1 = (dev->resource[1]).start; + pciinfo->base2 = (dev->resource[2]).start; + pciinfo->baserom = (dev->resource[PCI_ROM_RESOURCE]).start; + + pciinfo++; + info_cnt += sizeof(pciinfo_t); + } + break; + } + + if (len < info_cnt) return -ENOMEM; + if (copy_to_user(buf, info_buf, info_cnt)) return -EFAULT; + + return info_cnt; +} + +__initcall(mipsdha_proc_init); diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/mpsc.c linux.2.6.17.comcat/arch/mips/godson/ev64420/mpsc.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/mpsc.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/mpsc.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,548 @@ +/* + * (C) Copyright 2001 + * John Clemens , Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +/* + * mpsc.c - driver for console over the MPSC. + */ +#include +#include + +#include "asm/ict/gt64420.h" + +#define MVREGREAD(offset) \ + (*((volatile unsigned int *) \ + (GT_BASE_ADDR | (offset)))) + +#define MV_REG_WRITE(offset, data) \ + ((*((volatile unsigned int *) \ + (GT_BASE_ADDR | (offset)))) = (data)) + +#include "mpsc.h" + + +/* Define this if you wish to use the MPSC as a register based UART. + * This will force the serial port to not use the SDMA engine at all. + */ +#define CONFIG_MPSC_DEBUG_PORT + +static int gd_baudrate; + +/* local function declarations */ +static int galmpsc_connect(int channel, int connect); +static int galmpsc_route_rx_clock(int channel, int brg); +static int galmpsc_route_tx_clock(int channel, int brg); +static int galmpsc_write_config_regs(int mpsc, int mode); +static int galmpsc_config_channel_regs(int mpsc); +static int galmpsc_set_char_length(int mpsc, int value); +static int galmpsc_set_stop_bit_length(int mpsc, int value); +static int galmpsc_set_parity(int mpsc, int value); +static int galmpsc_enter_hunt(int mpsc); +static int galmpsc_set_brkcnt(int mpsc, int value); +static int galmpsc_set_tcschar(int mpsc, int value); +static int galmpsc_shutdown(int mpsc); + + +static int galbrg_set_CDV(int channel, int value); +static int galbrg_enable(int channel); +static int galbrg_disable(int channel); +static int galbrg_set_clksrc(int channel, int value); +static int galbrg_set_CUV(int channel, int value); + + + +#ifdef CONFIG_MPSC_DEBUG_PORT + +#define NO_BIT 0x00000000 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + + +static void +mpsc_debug_init(void) { + + volatile unsigned int temp; + + /* Clear the CFR (CHR4) */ + /* Write random 'Z' bit (bit 29) of CHR4 to enable debug uart *UNDOCUMENTED FEATURE* */ + temp = MVREGREAD(GALMPSC_CHANNELREG_4+(CHANNEL*GALMPSC_REG_GAP)); + temp &= 0xffffff00; + temp |= BIT29; + MV_REG_WRITE(GALMPSC_CHANNELREG_4+(CHANNEL*GALMPSC_REG_GAP), temp); + + /* Set the Valid bit 'V' (bit 12) and int generation bit 'INT' (bit 15) */ + temp = MVREGREAD(GALMPSC_CHANNELREG_5+(CHANNEL*GALMPSC_REG_GAP)); + temp |= (BIT12 | BIT15); + MV_REG_WRITE(GALMPSC_CHANNELREG_5+(CHANNEL*GALMPSC_REG_GAP), temp); + + /* Set int mask */ + temp = MVREGREAD(GALMPSC_0_INT_MASK); + temp |= BIT6; + MV_REG_WRITE(GALMPSC_0_INT_MASK, temp); +} +#endif + +char +mpsc_getchar_debug(void) +{ + volatile int temp; + volatile unsigned int cause; + + cause = MVREGREAD(GALMPSC_0_INT_CAUSE); + while ((cause & BIT6) == 0) { + cause = MVREGREAD(GALMPSC_0_INT_CAUSE); + } + + temp = MVREGREAD(GALMPSC_CHANNELREG_10+(CHANNEL*GALMPSC_REG_GAP)); + /* By writing 1's to the set bits, the register is cleared */ + MV_REG_WRITE(GALMPSC_CHANNELREG_10+(CHANNEL*GALMPSC_REG_GAP), temp ); + MV_REG_WRITE(GALMPSC_0_INT_CAUSE, cause & ~BIT6); + return (temp >> 16) & 0xff; +} + +void +mydelay(int microseconds) +{ + volatile int total; + int start; + start = read_c0_count(); + total = microseconds * 300; + + while(total > (read_c0_count() - start)); +} + +/* special function for running out of flash. doesn't modify any + * global variables [josh] */ +int +mpsc_putchar_early(char ch) +{ + int mpsc=CHANNEL; + int temp=MVREGREAD(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP)); + galmpsc_set_tcschar(mpsc,ch); + MV_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), temp|0x200); + + mydelay(1000); + return 0; +} + +int +mpsc_test_char_debug(void) +{ + if ((MVREGREAD(GALMPSC_0_INT_CAUSE) & BIT6) == 0 ) + return 0; + else{ + return 1; + } +} + +int +mpsc_init(int baud) +{ + /* BRG CONFIG */ + galbrg_set_baudrate(CHANNEL, baud); + galbrg_set_clksrc(CHANNEL,0); /* set source=bclk_in */ + galbrg_set_CUV(CHANNEL, 0); /* set up CountUpValue */ + galbrg_enable(CHANNEL); /* Enable BRG */ + + /* Set up clock routing */ + galmpsc_connect(CHANNEL, GALMPSC_CONNECT); /* connect it */ + + galmpsc_route_rx_clock(CHANNEL, CHANNEL); /* chosse BRG0 for Rx */ + galmpsc_route_tx_clock(CHANNEL, CHANNEL); /* chose BRG0 for Tx */ + + /* reset MPSC state */ + //galmpsc_shutdown(CHANNEL); + + + /* MPSC CONFIG */ + galmpsc_write_config_regs(CHANNEL, GALMPSC_UART); + galmpsc_config_channel_regs(CHANNEL); + galmpsc_set_char_length(CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */ + galmpsc_set_parity(CHANNEL, GALMPSC_PARITY_NONE); /* N */ + galmpsc_set_stop_bit_length(CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */ + +#ifdef CONFIG_MPSC_DEBUG_PORT + mpsc_debug_init(); +#endif + return 0; +} + + +int +galbrg_set_baudrate(int channel, int rate) +{ + int clock; + + galbrg_disable(channel); /*ok*/ + +#ifdef ZUMA_NTL + /* from tclk */ + clock = (CFG_TCLK/(16*rate)) - 1; +#else + clock = (CFG_TCLK/(16*rate)) - 1; +#endif + + galbrg_set_CDV(channel, clock); /* set timer Reg. for BRG*/ + + galbrg_enable(channel); + + gd_baudrate = rate; + + return 0; +} + +/* ------------------------------------------------------------------ */ + +/* Below are all the private functions that no one else needs */ + +static int +galbrg_set_CDV(int channel, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP)); + temp &= 0xFFFF0000; + temp |= (value & 0x0000FFFF); + MV_REG_WRITE(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP), temp); + + return 0; +} + +static int +galbrg_enable(int channel) +{ + unsigned int temp; + + temp = MVREGREAD(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP)); + temp |= 0x00010000; + MV_REG_WRITE(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP), temp); + + return 0; +} + +static int +galbrg_disable(int channel) +{ + unsigned int temp; + + temp = MVREGREAD(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP)); + temp &= 0xFFFEFFFF; + MV_REG_WRITE(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP), temp); + + return 0; +} + +static int +galbrg_set_clksrc(int channel, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP)); + temp &= 0xFFC3FFFF; /* Bit 18 - 21 (MV 64260 18-22)*/ + temp |= (value << 18); + MV_REG_WRITE(GALBRG_0_CONFREG+(channel*GALBRG_REG_GAP), temp); + return 0; +} + +static int +galbrg_set_CUV(int channel, int value) +{ + /* set CountUpValue*/ + /* MV_REG_WRITE(GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); read-only register. */ + + return 0; +} + +#if 0 +static int +galbrg_reset(int channel) +{ + unsigned int temp; + + temp = MVREGREAD(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x20000; + MV_REG_WRITE(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} +#endif + +static int +galmpsc_connect(int channel, int connect) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_ROUTING_REGISTER); + + if ((channel == 0) && connect) + temp &= ~0x00000007; + else if ((channel == 1) && connect) + temp &= ~(0x00000007 << 6); + else if ((channel == 0) && !connect) + temp |= 0x00000007; + else + temp |= (0x00000007 << 6); + + /* Just in case... */ + temp &= 0x3fffffff; + + MV_REG_WRITE(GALMPSC_ROUTING_REGISTER, temp); + + return 0; +} + +static int +galmpsc_route_rx_clock(int channel, int brg) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_RxC_ROUTE); + + if (channel == 0) { + temp &= ~0x0000000F; + temp |= brg; } + else { + temp &= ~0x00000F00; + temp |= (brg << 8); } + + MV_REG_WRITE(GALMPSC_RxC_ROUTE,temp); + + return 0; +} + +static int +galmpsc_route_tx_clock(int channel, int brg) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_TxC_ROUTE); + + if (channel == 0) { + temp &= ~0x0000000F; + temp |= brg; } + else { + temp &= ~0x00000F00; + temp |= (brg << 8); } + + MV_REG_WRITE(GALMPSC_TxC_ROUTE,temp); + + return 0; +} + +static int +galmpsc_write_config_regs(int mpsc, int mode) +{ + if (mode == GALMPSC_UART) { + /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ + MV_REG_WRITE(GALMPSC_MCONF_LOW + (mpsc*GALMPSC_REG_GAP), + 0x000004c4); + + /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ + MV_REG_WRITE(GALMPSC_MCONF_HIGH +(mpsc*GALMPSC_REG_GAP), + 0x02400200 /*0x024003f8*/); + /* 22 2222 1111*/ + /* 54 3210 9876*/ + /* 0000 0010 0000 0000*/ + /* 1*/ + /* 098 7654 3210*/ + /* 0000 0011 1111 1000*/ + } else + return -1; + + return 0; +} + +static int +galmpsc_config_channel_regs(int mpsc) +{ + MV_REG_WRITE(GALMPSC_CHANNELREG_1+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_3+(mpsc*GALMPSC_REG_GAP), 1); + MV_REG_WRITE(GALMPSC_CHANNELREG_4+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_5+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_6+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_7+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_8+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_9+(mpsc*GALMPSC_REG_GAP), 0); + MV_REG_WRITE(GALMPSC_CHANNELREG_10+(mpsc*GALMPSC_REG_GAP), 0); + + galmpsc_set_brkcnt(mpsc, 0x3); + galmpsc_set_tcschar(mpsc, 0xab); + + return 0; +} + +static int +galmpsc_set_brkcnt(int mpsc, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_CHANNELREG_1+(mpsc*GALMPSC_REG_GAP)); + temp &= 0x0000FFFF; + temp |= (value << 16); + MV_REG_WRITE(GALMPSC_CHANNELREG_1+(mpsc*GALMPSC_REG_GAP), temp); + + return 0; +} + +static int +galmpsc_set_tcschar(int mpsc, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_CHANNELREG_1+(mpsc*GALMPSC_REG_GAP)); + temp &= 0xFFFF0000; + temp |= value; + MV_REG_WRITE(GALMPSC_CHANNELREG_1+(mpsc*GALMPSC_REG_GAP), temp); + + return 0; +} + +static int +galmpsc_set_char_length(int mpsc, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_PROTOCONF_REG+(mpsc*GALMPSC_REG_GAP)); + temp &= 0xFFFFCFFF; + temp |= (value << 12); + MV_REG_WRITE(GALMPSC_PROTOCONF_REG+(mpsc*GALMPSC_REG_GAP), temp); + + return 0; +} + +static int +galmpsc_set_stop_bit_length(int mpsc, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_PROTOCONF_REG+(mpsc*GALMPSC_REG_GAP)); + temp &= 0xFFFFBFFF; + temp |= (value << 14); + MV_REG_WRITE(GALMPSC_PROTOCONF_REG+(mpsc*GALMPSC_REG_GAP),temp); + + return 0; +} + +static int +galmpsc_set_parity(int mpsc, int value) +{ + unsigned int temp; + + temp = MVREGREAD(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP)); + if (value != -1) { + temp &= 0xFFF3FFF3; + temp |= ((value << 18) | (value << 2)); + temp |= ((value << 17) | (value << 1)); + } else { + temp &= 0xFFF1FFF1; + } + + MV_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), temp); + + return 0; +} + +static int +galmpsc_enter_hunt(int mpsc) +{ + int temp; + + temp = MVREGREAD(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP)); + temp |= 0x80000000; + MV_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), temp); + + while(MVREGREAD(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP)) & MPSC_ENTER_HUNT) { + mydelay(1); + } + return 0; +} + + +static int +galmpsc_shutdown(int mpsc) +{ + unsigned int temp; + + /* cause RX abort (clears RX) */ + temp = MVREGREAD(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP)); + temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; + temp &= ~MPSC_ENTER_HUNT; + MV_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP),temp); + + MV_REG_WRITE(GALSDMA_0_COM_REG, 0); + MV_REG_WRITE(GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); + + /* shut down the MPSC */ + MV_REG_WRITE(GALMPSC_MCONF_LOW, 0); + MV_REG_WRITE(GALMPSC_MCONF_HIGH, 0); + MV_REG_WRITE(GALMPSC_PROTOCONF_REG+(mpsc*GALMPSC_REG_GAP),0); + + mydelay(100); + + /* shut down the sdma engines. */ + /* reset config to default */ + MV_REG_WRITE(GALSDMA_0_CONF_REG, 0x000000fc); + + mydelay(100); + + /* clear the SDMA current and first TX and RX pointers */ + MV_REG_WRITE(GALSDMA_0_CUR_RX_PTR, 0); + MV_REG_WRITE(GALSDMA_0_CUR_TX_PTR, 0); + MV_REG_WRITE(GALSDMA_0_FIR_TX_PTR, 0); + + mydelay(100); + + return 0; +} + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/mpsc.h linux.2.6.17.comcat/arch/mips/godson/ev64420/mpsc.h --- linux.2.6.17.orig/arch/mips/godson/ev64420/mpsc.h 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/mpsc.h 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,196 @@ +/* + * (C) Copyright 2001 + * John Clemens , Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +/* + * mpsc.h - header file for MPSC in uart mode (console driver) + */ + +#ifndef __MPSC_H__ +#define __MPSC_H__ + +/* include actual Galileo defines */ +/* driver related defines */ +#ifndef __ASM__ +int mpsc_init(int baud); +void mpsc_sdma_init(void); +void mpsc_init2(void); +int galbrg_set_baudrate(int channel, int rate); + +int mpsc_putchar_early(char ch); +char mpsc_getchar_debug(void); +int mpsc_test_char_debug(void); + +int mpsc_test_char_sdma(void); + +extern int (*mpsc_putchar)(char ch); +extern char (*mpsc_getchar)(void); +extern int (*mpsc_test_char)(void); +#endif +#define CFG_TCLK 133*(1<<20) +#define CFG_BCLK_IN (14318000) +#define CFG_TSCLK1_IN (24000000) +#define CHANNEL 0 + +#define TX_DESC 5 +#define RX_DESC 20 + +#define DESC_FIRST 0x00010000 +#define DESC_LAST 0x00020000 +#define DESC_OWNER_BIT 0x80000000 + +#define TX_DEMAND 0x00800000 +#define TX_STOP 0x00010000 +#define RX_ENABLE 0x00000080 + +#define SDMA_RX_ABORT (1 << 15) +#define SDMA_TX_ABORT (1 << 31) +#define MPSC_TX_ABORT (1 << 7) +#define MPSC_RX_ABORT (1 << 23) +#define MPSC_ENTER_HUNT (1 << 31) + +/* MPSC defines */ + +#define GALMPSC_CONNECT 0x1 +#define GALMPSC_DISCONNECT 0x0 + +#define GALMPSC_UART 0x1 + +#define GALMPSC_STOP_BITS_1 0x0 +#define GALMPSC_STOP_BITS_2 0x1 +#define GALMPSC_CHAR_LENGTH_8 0x3 +#define GALMPSC_CHAR_LENGTH_7 0x2 + +#define GALMPSC_PARITY_ODD 0x0 +#define GALMPSC_PARITY_EVEN 0x2 +#define GALMPSC_PARITY_MARK 0x3 +#define GALMPSC_PARITY_SPACE 0x1 +#define GALMPSC_PARITY_NONE -1 + +#define GALMPSC_SERIAL_MULTIPLEX SERIAL_PORT_MULTIPLEX /* 0xf010 */ +#define GALMPSC_ROUTING_REGISTER MPSC_ROUTING_REG /* 0xb400 */ +#define GALMPSC_RxC_ROUTE MPSC_RX_CLOCK_ROUTING_REG /* 0xb404 */ +#define GALMPSC_TxC_ROUTE MPSC_TX_CLOCK_ROUTING_REG /* 0xb408 */ +#define GALMPSC_MCONF_LOW MPSC_MAIN_CONFIG_LOW(0) /* 0x8000 */ +#define GALMPSC_MCONF_HIGH MPSC_MAIN_CONFIG_HIGH(0) /* 0x8004 */ +#define GALMPSC_PROTOCONF_REG MPSC_PROTOCOL_CONFIG(0) /* 0x8008 */ + +#define GALMPSC_REG_GAP 0x1000 + +#define GALMPSC_MCONF_CHREG_BASE MPSC_CHANNEL_REG1(0) /* 0x800c */ +#define GALMPSC_CHANNELREG_1 MPSC_CHANNEL_REG1(0) /* 0x800c */ +#define GALMPSC_CHANNELREG_2 MPSC_CHANNEL_REG2(0) /* 0x8010 */ +#define GALMPSC_CHANNELREG_3 MPSC_CHANNEL_REG3(0) /* 0x8014 */ +#define GALMPSC_CHANNELREG_4 MPSC_CHANNEL_REG4(0) /* 0x8018 */ +#define GALMPSC_CHANNELREG_5 MPSC_CHANNEL_REG5(0) /* 0x801c */ +#define GALMPSC_CHANNELREG_6 MPSC_CHANNEL_REG6(0) /* 0x8020 */ +#define GALMPSC_CHANNELREG_7 MPSC_CHANNEL_REG7(0) /* 0x8024 */ +#define GALMPSC_CHANNELREG_8 MPSC_CHANNEL_REG8(0) /* 0x8028 */ +#define GALMPSC_CHANNELREG_9 MPSC_CHANNEL_REG9(0) /* 0x802c */ +#define GALMPSC_CHANNELREG_10 MPSC_CHANNEL_REG10(0) /* 0x8030 */ +#define GALMPSC_CHANNELREG_11 MPSC_CHANNEL_REG11(0) /* 0x8034 */ + +#define GALSDMA_COMMAND_FIRST (1 << 16) +#define GALSDMA_COMMAND_LAST (1 << 17) +#define GALSDMA_COMMAND_ENABLEINT (1 << 23) +#define GALSDMA_COMMAND_AUTO (1 << 30) +#define GALSDMA_COMMAND_OWNER (1 << 31) + +#define GALSDMA_RX 0 +#define GALSDMA_TX 1 + +/* CHANNEL2 should be CHANNEL1, according to documentation, + * but to work with the current MVREGS file... + */ +#define GALSDMA_0_CONF_REG SDMA_CONFIG_REG(0) /* 0x4000 */ +#define GALSDMA_1_CONF_REG SDMA_CONFIG_REG(2) /* 0x6000 */ +#define GALSDMA_0_COM_REG SDMA_COMMAND_REG(0) /* 0x4008 */ +#define GALSDMA_1_COM_REG SDMA_COMMAND_REG(2) /* 0x6008 */ +#define GALSDMA_0_CUR_RX_PTR SDMA_CURRENT_RX_DESCRIPTOR_POINTER(0) /* 0x4810 */ +#define GALSDMA_0_CUR_TX_PTR SDMA_CURRENT_TX_DESCRIPTOR_POINTER(0) /* 0x4c10 */ +#define GALSDMA_0_FIR_TX_PTR SDMA_FIRST_TX_DESCRIPTOR_POINTER(0) /* 0x4c14 */ +#define GALSDMA_1_CUR_RX_PTR CHANNEL2_CURRENT_RX_DESCRIPTOR_POINTER /* 0x6810 */ +#define GALSDMA_1_CUR_TX_PTR SDMA_CURRENT_TX_DESCRIPTOR_POINTER(2) /* 0x6c10 */ +#define GALSDMA_1_FIR_TX_PTR SDMA_FIRST_TX_DESCRIPTOR_POINTER(2) /* 0x6c14 */ +#define GALSDMA_REG_DIFF 0x2000 + +/* WRONG in gt64260R.h */ +#define GALSDMA_INT_CAUSE 0xb800 /* SDMA_CAUSE */ +#define GALSDMA_INT_MASK 0xb880 /* SDMA_MASK */ +#define GALMPSC_0_INT_CAUSE 0xb804 +#define GALMPSC_0_INT_MASK 0xb884 + +#define GALSDMA_MODE_UART 0 +#define GALSDMA_MODE_BISYNC 1 +#define GALSDMA_MODE_HDLC 2 +#define GALSDMA_MODE_TRANSPARENT 3 + +#define GALBRG_0_CONFREG BRG_CONFIG_REG(0) /* 0xb200 */ +#define GALBRG_REG_GAP 0x0008 +#define GALBRG_0_BTREG BRG_BAUDE_TUNING_REG(0) /* 0xb204 */ + + /* Cunit Base Address Enable Window Bits*/ +#define CUNIT_BASE_ADDR_WIN_0_BIT 0x0 +#define CUNIT_BASE_ADDR_WIN_1_BIT 0x1 +#define CUNIT_BASE_ADDR_WIN_2_BIT 0x2 +#define CUNIT_BASE_ADDR_WIN_3_BIT 0x3 + +/* SDMA Window access protection */ +#define SDMA_WIN_ACCESS_NOT_ALLOWED 0 +#define SDMA_WIN_ACCESS_READ_ONLY 1 +#define SDMA_WIN_ACCESS_FULL 3 + +/****************************************/ +/* SDMA Address Space Targets */ +/****************************************/ + +#define SDMA_DRAM_CS_0_TARGET 0x0e00 +#define SDMA_DRAM_CS_1_TARGET 0x0d00 +#define SDMA_DRAM_CS_2_TARGET 0x0b00 +#define SDMA_DRAM_CS_3_TARGET 0x0700 + +#define SDMA_DEV_CS_0_TARGET 0x1e01 +#define SDMA_DEV_CS_1_TARGET 0x1d01 +#define SDMA_DEV_CS_2_TARGET 0x1b01 +#define SDMA_DEV_CS_3_TARGET 0x1701 + +/* SERIALIF Base Address Register bits */ +#define CBAR_TARGET_DRAM 0x00000000 +#define CBAR_TARGET_DEVICE 0x00000001 +#define CBAR_TARGET_SRAM 0x00000002 +#define CBAR_TARGET_PCI0 0x00000003 +#define CBAR_TARGET_PCI1 0x00000004 + +/* Window attributes */ +#define CBAR_ATTR_DRAM_CS0 0x00000E00 +#define CBAR_ATTR_DRAM_CS1 0x00000D00 +#define CBAR_ATTR_DRAM_CS2 0x00000B00 +#define CBAR_ATTR_DRAM_CS3 0x00000700 + +/* DRAM Target interface */ +#define CBAR_ATTR_DRAM_NO_CACHE_COHERENCY 0x00000000 +#define CBAR_ATTR_DRAM_CACHE_COHERENCY_WT 0x00001000 +#define CBAR_ATTR_DRAM_CACHE_COHERENCY_WB 0x00002000 + + +#endif /* __MPSC_H__ */ diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/pci.c linux.2.6.17.comcat/arch/mips/godson/ev64420/pci.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/pci.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/pci.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * pci.c + * + * Copyright (C) 2004 ICT CAS + * Author: Lin Wei, ICT CAS + * wlin@ict.ac.cn + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include + +#include +#include + +extern struct pci_ops ev64420_pci_ops; +extern void prom_printf(char *fmt, ...); + +static struct resource ev64420_mem_resource = { + .name = "EV64420 PCI MEM", + .start = 0x10000000UL, + .end = 0x1dffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource ev64420_io_resource = { + .name = "EV64420 PCI IO MEM", + .start = 0x0008000, + .end = 0x000ffffUL, + .flags = IORESOURCE_IO, +}; + +static struct pci_controller ev64420_pci_controller = { + .pci_ops = &ev64420_pci_ops, + .io_resource = &ev64420_io_resource, + .mem_resource = &ev64420_mem_resource, + .mem_offset = 0x00000000UL, + .io_offset = 0x00000000UL, +}; + +static int __init pcibios_init(void) +{ + extern int pci_probe_only; + + pci_probe_only = 1; + + register_pci_controller(&ev64420_pci_controller); + return 0; +} + +arch_initcall(pcibios_init); + + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/prom.c linux.2.6.17.comcat/arch/mips/godson/ev64420/prom.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/prom.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/prom.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * Copyright 2003 ICT CAS + * Author: Michael Guo + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include + +extern char arcs_cmdline[CL_SIZE]; + +extern unsigned long bus_clock; +extern unsigned long cpu_clock; +extern int putDebugChar(unsigned char byte); +extern void prom_printf(char *fmt, ...); + +int argc; +char **arg; +char **env; + +const char *get_system_type(void) +{ + return "ICT CAS GodsonEV2a"; +} + +void __init prom_init_cmdline(void) +{ +#if 1 + int i; + /* some 64bit toolchain can't convert int to a pointer correctly */ + long l; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + l = (long)arg[i]; + if (strlen(arcs_cmdline) + strlen(((char*)l) + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ((char*)l)); + strcat(arcs_cmdline, " "); + } +#endif +} + +void __init prom_init(void) +{ + long l; + + argc=fw_arg0; + arg=(char **)fw_arg1; + env=(char **)fw_arg2; + + prom_printf("arg0=%x,arg1=%x,arg2=%x,arg3=%x\n",fw_arg0, fw_arg1,fw_arg2,fw_arg3); + + mips_machgroup = MACH_GROUP_ICT; + mips_machtype = MACH_GODSONEV2A; + + prom_init_cmdline(); + +#if 1 + if((strstr(arcs_cmdline, "console=")) == NULL) + strcat(arcs_cmdline, "console=ttyS0,115200"); + + l = (long)*env; + while (l!=0) { + if (strncmp("busclock", (char*)l, strlen("busclock")) == 0) { + bus_clock = simple_strtol((char*)l + strlen("busclock="), + NULL, 10); + } + if (strncmp("cpuclock", (char*)l, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol((char*)l + strlen("cpuclock="), + NULL, 10); + } + env++; + l=(long)*env; + } + +#endif + prom_printf("Booting Linux kernel...\n"); + prom_printf("busclock=%x, cpuclock=%x\n",bus_clock, cpu_clock); + +} + +void __init prom_free_prom_memory(void) +{ + return; +} + +void prom_putchar(char c) +{ + putDebugChar(c); +} + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/reset.c linux.2.6.17.comcat/arch/mips/godson/ev64420/reset.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/reset.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/reset.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * 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. + * Copyright 2003 ICT CAS + * Author: jsun@mvista.com or jsun@junsun.net + * guoyi@ict.ac.cn + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void ev64420_restart(char *command) +{ + write_c0_config(((read_c0_config() >> 2) << 2) | 0x2); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void ev64420_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); +#ifndef CONFIG_CPU_GODSON2 + write_c0_config(((read_c0_config() >> 2) << 2) | 0x2); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +#else + while(1); +#endif +} + +void ev64420_power_off(void) +{ + ev64420_halt(); +} diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/setup.c linux.2.6.17.comcat/arch/mips/godson/ev64420/setup.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/setup.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/setup.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,363 @@ +/* + * BRIEF MODULE DESCRIPTION + * GodsonEV2a - board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 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. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_IDE +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_BLK_DEV_FD +#include +#endif +#include +#ifdef CONFIG_VT +#include +#endif +#ifdef CONFIG_PC_KEYB +#include +#endif +#include +#include +#include + +extern void prom_printf(char *fmt, ...); + + +#ifdef CONFIG_64BIT +#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p))) +#else +#define PTR_PAD(p) (p) +#endif + +#ifdef CONFIG_VT +extern struct screen_info screen_info; +#endif + +unsigned long cpu_clock; +unsigned long bus_clock; + +struct resource standard_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, +}; + +unsigned long gt64420_cs[4][2]={{CS_0_BASE_ADDRESS, CS_0_SIZE }, + {CS_1_BASE_ADDRESS, CS_1_SIZE }, + {CS_2_BASE_ADDRESS, CS_2_SIZE }, + {CS_3_BASE_ADDRESS, CS_3_SIZE }}; + +/* These functions are used for rebooting or halting the machine*/ +extern void ev64420_restart(char *command); +extern void ev64420_halt(void); +extern void ev64420_power_off(void); +extern void __init setup_l3cache(unsigned long size); + +unsigned long __init mips_rtc_get_time(void) +{ + return mc146818_get_cmos_time(); +} + + +void ev64420_timer_setup(struct irqaction *irq) +{ + setup_irq(27, irq); +} + +void ev64420_time_init(void) +{ + /* setup mips r4k timer */ + mips_hpt_frequency = cpu_clock / 2; +} + +#if 1 +static unsigned char CR(unsigned char reg) +{ + outb_p(reg, 0x70); + return inb_p(0x71); +} + +static void CW(unsigned char addr, unsigned char val) +{ + outb_p(addr, 0x70); + outb_p(val, 0x71); +} +static int rtc_fix(void) +{ + printk("Fix RTC\n"); + printk("STATUSA=%x\n",CR(RTC_REG_A)); + printk("STATUSB=%x\n",CR(RTC_REG_B)); + printk("STATUSC=%x\n",CR(RTC_REG_C)); + printk("STATUSD=%x\n",CR(RTC_REG_D)); + CW(RTC_REG_A, RTC_REF_CLCK_32KHZ); + CW(RTC_REG_B, RTC_DM_BINARY | RTC_24H); + CW(RTC_REG_C, 0x00); + printk("Fixed RTC\n"); + printk("STATUSA=%x\n",CR(RTC_REG_A)); + printk("STATUSB=%x\n",CR(RTC_REG_B)); + printk("STATUSC=%x\n",CR(RTC_REG_C)); + printk("STATUSD=%x\n",CR(RTC_REG_D)); + printk("%02x-%02x-%02x %02x:%02x:%02x\n",CR(0x09),CR(0x08),CR(0x07), + CR(0x04),CR(0x02),CR(0x00)); + + return 0; +} +#endif + +void __init plat_setup(void) +{ +#if defined (CONFIG_CPU_RM7000) || defined (CONFIG_EXTERNAL_CACHE) + void (*l3func)(unsigned long)=(void (*)(unsigned long))KSEG1ADDR(&setup_l3cache); +#endif + + unsigned int i; + unsigned int cs,base,size; + prom_printf("EV64420 board\n"); + + /* Request I/O space for devices used on the Malta board. */ + for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) + request_resource(&ioport_resource, standard_io_resources+i); + + /* Reset PCI I/O and PCI MEM values */ + set_io_port_base(PTR_PAD(PCI_IO_SPACE_BASE)); + + /* + * Enable DMA channel 4 (cascade channel) in the south bridge. + */ + //enable_dma(4); + + + board_time_init = ev64420_time_init; + rtc_get_time = mips_rtc_get_time; + board_timer_setup = ev64420_timer_setup; + + _machine_restart = ev64420_restart; + _machine_halt = ev64420_halt; + _machine_power_off = ev64420_power_off; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + +#ifdef CONFIG_EXTERNAL_CACHE + prom_printf(" - L3 Cache size: %d MiB\n", L3_CACHE_SIZE>>20); + l3func(L3_CACHE_SIZE); +#endif + +#ifdef CONFIG_CPU_RM7000 + prom_printf(" - L3 Cache size: %d MiB\n", L3_CACHE_SIZE>>20); + prom_printf("L3 cache not enabled\n"); + //l3func(L3_CACHE_SIZE); +#endif +/* Set the memory size based on CS decode registers set by PMON */ + for(cs = 0; cs < 4; cs++) { + GT_READ(gt64420_cs[cs][0], &base); + GT_READ(gt64420_cs[cs][1], &size); + if (size!=0) { + base = base<<16; + prom_printf(" - CS%d: %dMB\n", cs, (size>>4) + 1); + if (base == 0) { + add_memory_region(0, 0x100000, BOOT_MEM_RESERVED); + add_memory_region(0x100000, ((size+1) << 16) - 0x100000, BOOT_MEM_RAM); + } else { + //add_memory_region(base, (size+1) << 16, BOOT_MEM_RAM); + /* debug: reserved last 1M memory */ + //add_memory_region(base, ((size+1) << 16) - 0x1000000, BOOT_MEM_RAM); + add_memory_region(base, ((size+1) << 16), BOOT_MEM_RAM); + } + } + } + //add_memory_region(0x10000000, 0x40000000, BOOT_MEM_RESERVED); + +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; + + screen_info = (struct screen_info) { + 0, 25, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0,0,0, /* ega_ax, ega_bx, ega_cx */ + 25, /* orig-video-lines */ + VIDEO_TYPE_VGAC, /* orig-video-isVGA */ + 16 /* orig-video-points */ + }; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +#endif + /* for EV64420 GAINT mem, cpu address space is: + * 0 - 10000000: memory + * 10000000 - 1e000000: pci space with identical addr + * 1e000000 - 1e010000: gt internal registers + * 1ea00000 - 1eb00000: pci io + * 1ee00000 - 1ef00000: pci space [0-100000] + * 1f000000 - 1fc00000: flash : not used + * 1fc00000 - 1fd00000: boot rom + * all other region should not be accessed + */ +#if 1 + /* no access to 1e100000-1ea00000 */ + GT_WRITE(CPU_PROTECT_BASE_ADDRESS_0, (1<<31) | (7<<20) | (0x1e01)); + GT_WRITE(CPU_PROTECT_SIZE_0,0x90); /* ?? change to 8f die */ + + /* no access to 1f000000-1fc00000 */ + GT_WRITE(CPU_PROTECT_BASE_ADDRESS_1, (1<<31) | (7<<20) | (0x1f00)); + GT_WRITE(CPU_PROTECT_SIZE_1,0xbf); +#endif + +#if 1 + /* no access to 1fd00000-20000000 */ + GT_WRITE(CPU_PROTECT_BASE_ADDRESS_2, (1<<31) | (7<<20) | (0x1fd0)); + GT_WRITE(CPU_PROTECT_SIZE_2,0x2f); + + /* no access to 20000000 - top */ + GT_WRITE(CPU_PROTECT_BASE_ADDRESS_3, (1<<31) | (7<<20) | (0x02000)); + GT_WRITE(CPU_PROTECT_SIZE_3,0xdfff); +#endif + + //rtc_fix(); + + printk("setup_arch done!\n"); + + { + unsigned int val; + /* enable all barrier */ + GT_WRITE(CPU_SYNC_BARIER_CONTROL, 0x6d0); + +#if 0 + /* enable pci order */ + GT_READ(PCI_MEMORY0_BASE_ADDRESS,&val); + GT_WRITE(PCI_MEMORY0_BASE_ADDRESS, val | (1<<28)); + prom_printf("mem0 base = %x\n",val); + + /* enable pci order */ + GT_READ(PCI_MEMORY1_BASE_ADDRESS,&val); + GT_WRITE(PCI_MEMORY1_BASE_ADDRESS, val | (1<<28)); + prom_printf("mem0 base = %x\n",val); +#endif + } + /* from u-boot */ + //GT_WRITE(0xc28, 0xF77FF7); + GT_WRITE(GT_PCI_COMMAND, 0x510100c1); /* default 0107e371 */ + +#if 1 + /* disable unused access to pci interface */ + GT_WRITE(PCI_CROSS_BAR_CONTROL_LOW,0x33333332); + GT_WRITE(PCI_CROSS_BAR_CONTROL_HIGH,0x33333332); + + /* sdram */ + GT_WRITE(SDRAM_CROSS_BAR_CONTROL_LOW, 0x00000023); + GT_WRITE(SDRAM_CROSS_BAR_CONTROL_HIGH,0x00000023); + + /* device */ + GT_WRITE(DEVICE_CROSS_BAR_CONTROL_LOW, 0x11111112); + GT_WRITE(DEVICE_CROSS_BAR_CONTROL_HIGH,0x11111112); +#endif + + /* stop queues */ + GT_WRITE(0x2680, 0xff00); + /* power down ether */ + GT_WRITE(0x20b0, 0x20000); + + /* set sdram pad driving strength*/ + GT_WRITE(0x14c0, 0x8000000a); + GT_WRITE(0x14c0, 0x8000000a); + GT_WRITE(0x14c4, 0x8000000a); + GT_WRITE(0x14c4, 0x8000000a); + +#if 1 + /* pci retry */ + GT_WRITE(0xc04, 0xff0000); + + /* discard timer */ + GT_WRITE(0xd04, 0x00ffff); +#endif + + //GT_WRITE(MPP_CONTROL2, 0x00111111); //MPP16~23 as PCI REQ or GNT. + //GT_WRITE(MPP_CONTROL2, 0x11000011); //MPP16~23 as PCI REQ or GNT. + +#if 0 +#define PCI_ORDING (1<<28) +#define CHANGE_SIZE(x) \ + GT_READ(PCI_ACCESS_CONTROL_SIZE_##x,&val); \ + GT_WRITE(PCI_ACCESS_CONTROL_SIZE_##x,val | (1<<11)); + + { unsigned int val; + CHANGE_SIZE(0); + CHANGE_SIZE(1); + CHANGE_SIZE(2); + CHANGE_SIZE(3); + CHANGE_SIZE(4); + CHANGE_SIZE(5); + + GT_READ(PCI_I_O_BASE_ADDRESS,&val); + GT_WRITE(PCI_I_O_BASE_ADDRESS,val | PCI_ORDING); + GT_READ(PCI_MEMORY0_BASE_ADDRESS,&val); + GT_WRITE(PCI_MEMORY0_BASE_ADDRESS,val | PCI_ORDING); + } +#endif +} + diff -uNr linux.2.6.17.orig/arch/mips/godson/ev64420/tc-godson2a.c linux.2.6.17.comcat/arch/mips/godson/ev64420/tc-godson2a.c --- linux.2.6.17.orig/arch/mips/godson/ev64420/tc-godson2a.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/ev64420/tc-godson2a.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,234 @@ +/* + * BRIEF MODULE DESCRIPTION + * GodsonEV2a - board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 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. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void prom_printf(char *fmt, ...); + + + +/* sd to physical address ffffffff8 will cause a page invalidate + * sd to physical address ffffffff0 will cause a clear. + * We use unmapped uncached address space 0x9000000000000000- + * 0x9000000fffffffff to produce needed physical address + */ +void godson2_invalidate_external_cache_page(unsigned long addr) +{ + unsigned long paddr; + spinlock_t lock; + unsigned long flags; + + paddr = virt_to_phys(addr); + + spin_lock_irqsave(&lock,flags); +#ifdef CONFIG_64BIT + __asm__ volatile ( + ".set mips3\n\t" + "li $2,0x90000010\n\t" + "dsll32 $2,$2,0\n\t" + "dsubu $2,$2,8\n\t" + "sd %0,0($2)\n\t" + ".set mips0\n\t" + ::"r"(paddr):"$2"); +#else + __asm__ volatile ( + ".set mips3\n\t" + "li $2,0x90000010\n\t" + "dsll32 $2,$2,0\n\t" + "dsubu $2,$2,8\n\t" + "daddiu $3, $0, 0xffff\n\t" + "dsrl32 $3, $3, 0\n\t" + "and $3, $3, %0\n\t" + "sd $3,0($2)\n\t" + ".set mips0\n\t" + ::"r"(paddr):"$2", "$3"); +#endif + spin_unlock_irqrestore(&lock,flags); +} + +/* + * Writeback and invalidate the primary cache dcache before DMA. + */ +static void godson2_tc_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + +#ifdef DEBUG_CACHE + printk("godson2_tc_wback_inv[%08lx,%08lx]", addr, size); +#endif + a = addr & ~(tc_pagesize - 1); + end = (addr + size - 1) & ~(tc_pagesize - 1); + while (1) { + godson2_invalidate_external_cache_page(a); + if (a == end) + break; + a += tc_pagesize; + } +} + +static void godson2_tc_inv(unsigned long addr, unsigned long size) +{ + godson2_tc_wback_inv(addr,size); +} + +static __init void godson2_tc_enable(void) +{ + unsigned long tmp; +#if 0 + +#ifdef CONFIG_GODSON2_SRAM_TYPE_SCD + /* extend DCE interface signal by one cycle in the CPU */ + set_c0_config(1 << 13); +#else + clear_c0_config(1<<13); +#endif + set_c0_config(1<<12); + + GT_READ(CPU_CONFIGURATION, &tmp); + GT_WRITE(CPU_CONFIGURATION, tmp | (1<<14)); +#endif + + for (tmp=0;tmp> 10), tc_lsize); + + return 1; +} + +struct bcache_ops godson2_tc_ops = { + .bc_enable = godson2_tc_enable, + .bc_disable = godson2_tc_disable, + .bc_wback_inv = godson2_tc_wback_inv, + .bc_inv = godson2_tc_inv +}; + +void __init godson2_tc_init(void) +{ + if (godson2_tc_probe()) { + //godson2_tc_enable(); + prom_printf("set L2 cache funcs\n"); + bcops = &godson2_tc_ops; + } +} + +/* + * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() + */ +#define Page_Invalidate_T 0x16 +void __init setup_l3cache(unsigned long size) +{ + unsigned int tmp; + int register i; +#ifdef CONFIG_DEBUG_LIXY + prom_printf("Enabling L3 cache..."); +#else + printk("Enabling L3 cache..."); +#endif + +#if 0 /* we don't really have external cache,for debug */ + +#ifdef CONFIG_SPLIT_READ + /* Enable the split read support in the GT6420A's CPU Configuration register */ + GT_READ(CPU_CONFIGURATION, &tmp); + GT_WRITE(CPU_CONFIGURATION, tmp | (1<<13)); + + prom_printf("Split read enabled\n"); +#endif + +#ifdef CONFIG_GODSON2_SRAM_TYPE_SCD + /* extend DCE interface signal by one cycle in the CPU */ + set_c0_config(1<<13); +#else /* DCD */ + clear_c0_config(1<<13); +#endif + + /* Enable the L3 cache in the CPU */ + set_c0_config(1<<12 /* CONF_TE */); + + __asm__ __volatile__ (".set\tnoat\n" + "lui\t$1, 0xb400\n" + "lw\t%0, 0x0($1)\n" + "ori\t%0, %0, 0x4000\n" + "sw\t%0, 0x0($1)\n" + ".set\tat\n" + :"=&r"(tmp)); +#endif + + for (i=0; i < L3_CACHE_SIZE; i+= 4096) { + godson2_invalidate_external_cache_page(KSEG0+i); + } + + read_c0_prid(); +#ifdef CONFIG_DEBUG_LIXY + prom_printf("external cache flushed\n"); +#else + printk("external cache flushed\n"); +#endif +} diff -uNr linux.2.6.17.orig/arch/mips/godson/godson2a/dbg_io.c linux.2.6.17.comcat/arch/mips/godson/godson2a/dbg_io.c --- linux.2.6.17.orig/arch/mips/godson/godson2a/dbg_io.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/godson2a/dbg_io.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,124 @@ +#include + + +#include /* For the serial port location and base baud */ + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#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 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE (0xffffffffb01003f8) +#define MAX_BAUD BASE_BAUD + +/* === END OF CONFIG === */ + +#define REG_OFFSET 1 + +/* 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); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + 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(UART16550_BAUD_115200, + 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 -uNr linux.2.6.17.orig/arch/mips/godson/godson2a/gt-irq.c linux.2.6.17.comcat/arch/mips/godson/godson2a/gt-irq.c --- linux.2.6.17.orig/arch/mips/godson/godson2a/gt-irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/godson2a/gt-irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,171 @@ +/* + * Copyright 2003 ICT CAS + * Author: guoyi@ict.ac.cn + * + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/godson2a/gt-irq.c + * Interrupt routines for gt64240. Interrupt numbers are assigned from + * GT64240_IRQ_BASE to GT64240_IRQ_BASE+64. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GT64240_IRQ_BASE 64 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_gt64240_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (GT64240_IRQ_BASE + 32)) { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &value); + value &= ~(1 << (irq - GT64240_IRQ_BASE)); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, value); + } else { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &value); + value &= ~(1 << (irq - (GT64240_IRQ_BASE - 32))); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, value); + } +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_gt64240_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (GT64240_IRQ_BASE + 32)) { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &value); + value |= 1 << (irq - GT64240_IRQ_BASE); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, value); + } else { + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &value); + value |= 1 << (irq - (GT64240_IRQ_BASE - 32)); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH, value); + } +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_gt64240_irq(unsigned int irq) +{ + unmask_gt64240_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_gt64240_irq(unsigned int irq) +{ + unmask_gt64240_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_gt64240_irq(unsigned int irq) +{ + mask_gt64240_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_gt64240_irq(unsigned int irq) +{ + mask_gt64240_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_gt64240_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_gt64240_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_gt64240_irq(struct pt_regs *regs) +{ + unsigned int irq_src_low, irq_src_high; + unsigned int irq_mask_low, irq_mask_high; + + /* read the interrupt status registers */ + GT_READ(CPU_INTERRUPT_MASK_REGISTER_LOW, &irq_mask_low); + GT_READ(CPU_INTERRUPT_MASK_REGISTER_HIGH, &irq_mask_high); + GT_READ(LOW_INTERRUPT_CAUSE_REGISTER, &irq_src_low); + GT_READ(HIGH_INTERRUPT_CAUSE_REGISTER, &irq_src_high); + /* mask for just the interrupts we want */ + irq_src_low &= irq_mask_low; + irq_src_high &= irq_mask_high; + + if (irq_src_low) + do_IRQ(ls1bit32(irq_src_low) + GT64240_IRQ_BASE, regs); + else + do_IRQ(ls1bit32(irq_src_high) + GT64240_IRQ_BASE + 32, regs); +} + +#define shutdown_gt64240_irq disable_gt64240_irq + +struct hw_interrupt_type gt64240_irq_type = { + "GT64240-decoder", + startup_gt64240_irq, + shutdown_gt64240_irq, + enable_gt64240_irq, + disable_gt64240_irq, + mask_and_ack_gt64240_irq, + end_gt64240_irq, + NULL +}; + +void gt64240_irq_init(void) +{ + int i; + + /* Reset irq handlers pointers to NULL */ + for (i = GT64240_IRQ_BASE; i < (GT64240_IRQ_BASE + 64); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = >64240_irq_type; + } + /* Only eth0 enabled on linuxpc */ + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_HIGH,0x1); + GT_WRITE(CPU_INTERRUPT_MASK_REGISTER_LOW, 0x0); + GT_WRITE(LOW_INTERRUPT_CAUSE_REGISTER, 0); + GT_WRITE(HIGH_INTERRUPT_CAUSE_REGISTER, 0); +} diff -uNr linux.2.6.17.orig/arch/mips/godson/godson2a/gt-mpp-irq.c linux.2.6.17.comcat/arch/mips/godson/godson2a/gt-mpp-irq.c --- linux.2.6.17.orig/arch/mips/godson/godson2a/gt-mpp-irq.c 1970-01-01 00:00:00.000000000 +0000 +++ linux.2.6.17.comcat/arch/mips/godson/godson2a/gt-mpp-irq.c 2006-12-15 14:27:39.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * Copyright 2003 ICT CAS + * Author: guoyi@ict.ac.cn + * + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/godson2a/gt-mpp-irq.c + * Interrupt routines for gt64240 MPP. Interrupt numbers are assigned from + * GT64240_MPP_IRQ_BASE to GT64240_MPP_IRQ_BASE+32. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GT64240_MPP_IRQ_BASE 32 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +static inline void ack_gt64240_mpp_irq(unsigned int irq) +{ + uint32_t value; + //write cause reg + GT_READ(GPP_INTERRUPT_CAUSE, &value); + value &= ~(1 << (irq - GT64240_MPP_IRQ_BASE)); + GT_WRITE(GPP_INTERRUPT_CAUSE, value); + +} +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_gt64240_mpp_irq(unsigned int irq) +{ + uint32_t value; + + GT_READ(GPP_INTERRUPT_MASK, &value); + value &= ~(1 << (irq - GT64240_MPP_IRQ_BASE)); + GT_WRITE(GPP_INTERRUPT_MASK, value); +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_gt64240_mpp_irq(unsigned int irq) +{ + uint32_t value; + + GT_READ(GPP_INTERRUPT_MASK, &value); + value |= 1 << (irq - GT64240_MPP_IRQ_BASE); + GT_WRITE(GPP_INTERRUPT_MASK, value); +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_gt64240_mpp_irq(unsigned int irq) +{ + unmask_gt64240_mpp_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_gt64240_mpp_irq(unsigned int irq) +{ + unmask_gt64240_mpp_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_gt64240_mpp_irq(unsigned int irq) +{ + mask_gt64240_mpp_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_gt64240_mpp_irq(unsigned int irq) +{ + mask_gt64240_mpp_irq(irq); + ack_gt64240_mpp_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_gt64240_mpp_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_gt64240_mpp_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_gt64240_mpp_irq(struct pt_regs *regs) +{ + unsigned int irq_src; + unsigned int irq_mask; + + /* read the interrupt status registers */ + GT_READ(GPP_INTERRUPT_MASK, &irq_mask); + GT_READ(GPP_INTERRUPT_CAUSE, &irq_src); + + /* mask for just the interrupts we want */ + irq_src &= irq_mask; + + if (irq_src) + do_IRQ(ls1bit32(irq_src) + GT64240_MPP_IRQ_BASE, regs); +} + +#define shutdown_gt64