Update of /cvsroot/linux-mips/linux/arch/mips/korva
In directory usw-pr-cvs1:/tmp/cvs-serv27423/arch/mips/korva
Added Files:
Makefile dbg_io.c int_handler.S irq.c irq_cpu.c irq_korva.c
prom.c reset.c setup.c
Log Message:
Support NEC Korva board (vr4120a based).
--- NEW FILE: Makefile ---
#
# Makefile for common code of NEC Korva board
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET:= korva.a
obj-y := setup.o prom.o reset.o int_handler.o irq.o irq_cpu.o irq_korva.o
obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o
obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
include $(TOPDIR)/Rules.make
--- NEW FILE: dbg_io.c ---
#include <linux/config.h>
#if defined(CONFIG_REMOTE_DEBUG)
/* --- 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 debug board serial port for kdb */
#define BASE 0xb0000080
#define MAX_BAUD 1152000
#define REG_OFFSET 4
static int remoteDebugInitialized = 0;
#define BAUD_DEFAULT UART16550_BAUD_115200
/* === END OF CONFIG === */
/* register offset */
#define OFS_RCV_BUFFER 0
#define OFS_TRANS_HOLD 0
#define OFS_SEND_BUFFER 0
#define OFS_INTR_ENABLE (1*REG_OFFSET)
#define OFS_INTR_ID (2*REG_OFFSET)
#define OFS_DATA_FORMAT (3*REG_OFFSET)
#define OFS_LINE_CONTROL (3*REG_OFFSET)
#define OFS_MODEM_CONTROL (4*REG_OFFSET)
#define OFS_RS232_OUTPUT (4*REG_OFFSET)
#define OFS_LINE_STATUS (5*REG_OFFSET)
#define OFS_MODEM_STATUS (6*REG_OFFSET)
#define OFS_RS232_INPUT (6*REG_OFFSET)
#define OFS_SCRATCH_PAD (7*REG_OFFSET)
#define OFS_DIVISOR_LSB (0*REG_OFFSET)
#define OFS_DIVISOR_MSB (1*REG_OFFSET)
/* memory-mapped read/write of the port */
#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
{
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
/* set up buad rate */
{
uint32 divisor;
/* set DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
/* set divisor */
divisor = MAX_BAUD / baud;
UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
/* clear DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
}
/* set data format */
UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
}
uint8 getDebugChar(void)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(BAUD_DEFAULT,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
return UART16550_READ(OFS_RCV_BUFFER);
}
int putDebugChar(uint8 byte)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(BAUD_DEFAULT,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
UART16550_WRITE(OFS_SEND_BUFFER, byte);
return 1;
}
#endif
--- NEW FILE: int_handler.S ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* First-level&2nd-level interrupt dispatcher for ddb5477
*
* 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.
*/
/*
* The second level IRQ has 5 interrupt sources. So we simply lump
* it together here with the first level.
*
* The IRQ levels are hardcoded. If you change them here, you better
* change the init_IRQ() as well.
*
* CPU IRQs :
* 0 - software intr 0
* 1 - software intr 1
* 2 - ATM Cell Processor
* 3 - USB Controller
* 4 - Ether Controller #1
* 5 - Ether Controller #2
* 6 - cascading to 2nd level (korva) interrupts
* 7 - cpu timer
*
* Korva IRQs :
* 8 - Timer ch0
* 9 - Timer ch1
* 10 - UART
* 11 - External interrupt
* 12 - Wakeup
*/
#include <linux/config.h>
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/korva.h>
/*
* first level interrupt dispatcher for ocelot board -
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
NESTED(korva_handle_irq, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
.set noreorder
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
andi t1, t0, STATUSF_IP7 /* cpu timer */
bnez t1, ll_cputimer_irq
andi t1, t0, STATUSF_IP2
bnez t1, ll_cpu_ip2
andi t1, t0, STATUSF_IP3
bnez t1, ll_cpu_ip3
andi t1, t0, STATUSF_IP4
bnez t1, ll_cpu_ip4
andi t1, t0, STATUSF_IP5
bnez t1, ll_cpu_ip5
andi t1, t0, STATUSF_IP6
bnez t1, ll_cpu_ip6
andi t1, t0, STATUSF_IP0 /* software int 0 */
bnez t1, ll_cpu_ip0
andi t1, t0, STATUSF_IP1 /* software int 1 */
bnez t1, ll_cpu_ip1
nop
.set reorder
/* wrong alarm or masked ... */
j spurious_interrupt
nop
END(korva_handle_irq)
.align 5
ll_cputimer_irq:
li a0, 7
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip0:
li a0, 0
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip1:
li a0, 1
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip2:
li a0, 2
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip3:
li a0, 3
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip4:
li a0, 4
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip5:
li a0, 5
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip6:
/* it is korva 2nd level interrupts */
/* reading ISR will clear it */
la t0, KORVA_BASE_VIRT + KORVA_S_ISR
lw s0, 0(t0)
/* and with the mask - just to be safe */
la t0, KORVA_BASE_VIRT + KORVA_S_IMR
lw t0, 0(t0)
and s0, s0, t0
/* do we need to deliver all the pending ones? */
li a0, 8
li a1, 13
li t0, 1
loop:
and t1, t0, s0
bnez t1, foundone
sll t0, t0, 1
addiu a0, a0, 1
/* check if we reach the end */
beq a0, a1, error
j loop
foundone:
move a1, sp
jal do_IRQ
j ret_from_irq
error:
j spurious_interrupt
--- NEW FILE: irq.c ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* init_IRQ for korva.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/pm.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/gdb-stub.h>
#include <asm/korva.h>
extern asmlinkage void korva_handle_irq(void);
extern void breakpoint(void);
extern void mips_cpu_irq_init(u32 irq_base);
extern void korva_irq_init(u32 irq_base);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
void __init init_IRQ(void)
{
set_except_vector(0, korva_handle_irq);
mips_cpu_irq_init(0);
korva_irq_init(8);
/* hack - enable uart */
/* korva_out32(KORVA_S_IMR, 1 << 2); */
/* setup cascade interrupt 6 */
setup_irq(6, &irq2);
#ifdef CONFIG_REMOTE_DEBUG
printk("Setting debug traps - please connect the remote debugger.\n");
set_debug_traps();
// you may move this line to whereever you want
breakpoint();
#endif
}
--- NEW FILE: irq_cpu.c ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* This file define the irq handler for MIPS CPU interrupts.
*
* 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.
*/
/*
* Almost all MIPS CPUs define 8 interrupt sources. They are typically
* level triggered (i.e., cannot be cleared from CPU; must be cleared from
* device). The first two are software interrupts. The last one is
* usually cpu timer interrupt if coutner register is present.
*
* This file exports one global function:
* mips_cpu_irq_init(u32 irq_base);
*/
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/mipsregs.h>
/* [jsun] sooner or later we should move this debug stuff to MIPS common */
#include <asm/ddb5xxx/debug.h>
static int mips_cpu_irq_base=-1;
static void
mips_cpu_irq_enable(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8));
set_cp0_status(1 << (irq - mips_cpu_irq_base + 8));
}
static void
mips_cpu_irq_disable(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
clear_cp0_status(1 << (irq - mips_cpu_irq_base + 8));
}
static unsigned int mips_cpu_irq_startup(unsigned int irq)
{
mips_cpu_irq_enable(irq);
return 0;
}
#define mips_cpu_irq_shutdown mips_cpu_irq_disable
static void
mips_cpu_irq_ack(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
/* although we attemp to clear the IP bit in cause reigster, I think
* usually it is cleared by device (irq source)
*/
clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8));
/* disable this interrupt - so that we safe proceed to the handler */
mips_cpu_irq_disable(irq);
}
static void
mips_cpu_irq_end(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
mips_cpu_irq_enable(irq);
}
static hw_irq_controller mips_cpu_irq_controller = {
"CPU_irq",
mips_cpu_irq_startup,
mips_cpu_irq_shutdown,
mips_cpu_irq_enable,
mips_cpu_irq_disable,
mips_cpu_irq_ack,
mips_cpu_irq_end,
NULL /* no affinity stuff for UP */
};
void
mips_cpu_irq_init(u32 irq_base)
{
extern irq_desc_t irq_desc[];
u32 i;
for (i= irq_base; i< irq_base+8; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &mips_cpu_irq_controller;
}
mips_cpu_irq_base = irq_base;
}
--- NEW FILE: irq_korva.c ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* This file define the irq handler for MIPS CPU interrupts.
*
* 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 file exports one global function:
* korva_irq_init(u32 irq_base);
*/
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/korva.h>
#include <asm/mipsregs.h>
/* [jsun] sooner or later we should move this debug stuff to MIPS common */
#include <asm/ddb5xxx/debug.h>
#define NUM_KORVA_IRQS 5
static int korva_irq_base=-1;
static void
korva_irq_enable(unsigned int irq)
{
MIPS_ASSERT(korva_irq_base != -1);
MIPS_ASSERT(irq >= korva_irq_base);
MIPS_ASSERT(irq < korva_irq_base+NUM_KORVA_IRQS);
irq -= korva_irq_base;
korva_out32(KORVA_S_IMR, korva_in32(KORVA_S_IMR) | (1 << irq) );
}
static void
korva_irq_disable(unsigned int irq)
{
MIPS_ASSERT(korva_irq_base != -1);
MIPS_ASSERT(irq >= korva_irq_base);
MIPS_ASSERT(irq < korva_irq_base+NUM_KORVA_IRQS);
irq -= korva_irq_base;
korva_out32(KORVA_S_IMR, korva_in32(KORVA_S_IMR) & ~(1 << irq) );
}
static unsigned int korva_irq_startup(unsigned int irq)
{
korva_irq_enable(irq);
return 0;
}
#define korva_irq_shutdown korva_irq_disable
/* the intr status register is already cleared when we read it */
#define korva_irq_ack korva_irq_disable
#define korva_irq_end korva_irq_enable
static hw_irq_controller korva_irq_controller = {
"KORVA_irq",
korva_irq_startup,
korva_irq_shutdown,
korva_irq_enable,
korva_irq_disable,
korva_irq_ack,
korva_irq_end,
NULL /* no affinity stuff for UP */
};
void
korva_irq_init(u32 irq_base)
{
extern irq_desc_t irq_desc[];
u32 i;
for (i= irq_base; i< irq_base+NUM_KORVA_IRQS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &korva_irq_controller;
}
korva_irq_base = irq_base;
}
--- NEW FILE: prom.c ---
/***********************************************************************
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* arch/mips/korva/prom.c
* prom setup file for korva
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
***********************************************************************
*/
#include <linux/init.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
#include <asm/korva.h>
char arcs_cmdline[COMMAND_LINE_SIZE];
void __init prom_init(void)
{
u32 sdtsr;
u32 ramsize;
strcpy(arcs_cmdline, "console=ttyS0,115200");
strcat(arcs_cmdline, " ip=bootp");
mips_machgroup = MACH_GROUP_NEC_VR41XX;
mips_machtype = MACH_NEC_KORVA;
/* bit 8:9 determines the RAM size */
sdtsr = korva_in32(KORVA_SDTSR);
ramsize = 2 << (1 + ((sdtsr >> 8) & 3));
printk("Korva board with %d MB system RAM\n", ramsize);
add_memory_region(0, ramsize << 20 , BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
{
}
void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
{
}
--- NEW FILE: reset.c ---
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Copyright (C) 1997, 2001 Ralf Baechle
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/system.h>
void nec_korva_restart(char *command)
{
set_cp0_status(ST0_BEV | ST0_ERL);
change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
flush_cache_all();
write_32bit_cp0_register(CP0_WIRED, 0);
__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}
void nec_korva_halt(void)
{
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
while (1);
}
void nec_korva_power_off(void)
{
nec_korva_halt();
}
--- NEW FILE: setup.c ---
/***********************************************************************
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* arch/mips/korva/setup.c
* The setup file for korva.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
***********************************************************************
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/serial.h>
#include <linux/types.h>
#include <linux/string.h> /* for memset */
#include <asm/reboot.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/korva.h>
#include <asm/ddb5xxx/debug.h>
// #define USE_CPU_TIMER 1 /* are we using cpu counter as timer */
extern void nec_korva_restart(char* c);
extern void nec_korva_halt(void);
extern void nec_korva_power_off(void);
static void __init init_serial_ports(void)
{
struct serial_struct s;
/* clear memory */
memset(&s, 0, sizeof(s));
s.line = 0; /* we set the first one */
s.baud_base = 1152000;
// s.irq = 6;
s.irq = 10;
s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
s.iomem_base = (u8*)(KORVA_BASE_VIRT + KORVA_UARTDLL);
s.iomem_reg_shift = 2;
s.io_type = SERIAL_IO_MEM;
MIPS_VERIFY(early_serial_setup(&s), == 0);
}
static void __init nec_korva_time_init(void)
{
/* 100 (CPU clock) MHz divided by 8 */
mips_counter_frequency = 100000000 / 8;
}
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static void __init nec_korva_timer_setup(struct irqaction *irq)
{
#if defined(USE_CPU_TIMER)
unsigned int count;
setup_irq(7, irq);
/* to generate the first CPU timer interrupt */
count = read_32bit_cp0_register(CP0_COUNT);
write_32bit_cp0_register(CP0_COMPARE, count + 1000);
#else
setup_irq(8,irq);
korva_out32(KORVA_TM0CSR, 100000000 / HZ); /* CPU clock / HZ */
korva_out32(KORVA_TMMR, 0x1); /* start the timer 0 */
#endif
}
#if defined(CONFIG_BLK_DEV_INITRD)
extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
#endif
#if defined(CONFIG_NEC_CANDY)
/* need to come up with a better way. FIXME */
static u_char ETHER_MAC_ADDR[][6] = {
{0x00, 0x00, 0x4c, 0x80, 0x92, 0xa1},
{0x00, 0x00, 0x4c, 0x80, 0x92, 0xa2}
};
extern int
nec_candy_setup_boot_param(uint irq, ulong base_addr, ulong pmd_addr, u_char *mac_addr);
#endif
void __init nec_korva_setup(void)
{
MIPS_DEBUG(printk("nec_korva_setup() starts.\n"));
#if defined(CONFIG_BLK_DEV_INITRD)
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
initrd_start = (unsigned long)&__rd_start;
initrd_end = (unsigned long)&__rd_end;
#endif
board_time_init = nec_korva_time_init;
board_timer_setup = nec_korva_timer_setup;
_machine_restart = nec_korva_restart;
_machine_halt = nec_korva_halt;
_machine_power_off = nec_korva_power_off;
init_serial_ports();
#if defined(CONFIG_NEC_CANDY)
/* setup ether driver */
nec_candy_setup_boot_param(4, 0xb0002000, 0x14, ETHER_MAC_ADDR[0]);
nec_candy_setup_boot_param(5, 0xb0003000, 0x16, ETHER_MAC_ADDR[1]);
#endif
/* ---------------- board hardware setup ---------------- */
/* reset all peripherials, except uart */
// korva_out32(KORVA_S_WRCR, 0x1f);
korva_out32(KORVA_S_WRCR, 0x0f);
/* enable IBUS arbitration for peripherals */
korva_set_bits(KORVA_S_GMR, 0x2);
}
|