Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
#
# Makefile for the common code of NEC DDB-Vrc5xxx board
#
obj-y += nile4.o prom.o rtc_ds1386.o

View File

@@ -0,0 +1,130 @@
/*
*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* arch/mips/ddb5xxx/common/nile4.c
* misc low-level routines for vrc-5xxx controllers.
*
* derived from original code by Geert Uytterhoeven <geert@sonycom.com>
*
* 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/types.h>
#include <linux/kernel.h>
#include <asm/ddb5xxx/ddb5xxx.h>
u32
ddb_calc_pdar(u32 phys, u32 size, int width,
int on_memory_bus, int pci_visible)
{
u32 maskbits;
u32 widthbits;
switch (size) {
#if 0 /* We don't support 4 GB yet */
case 0x100000000: /* 4 GB */
maskbits = 4;
break;
#endif
case 0x80000000: /* 2 GB */
maskbits = 5;
break;
case 0x40000000: /* 1 GB */
maskbits = 6;
break;
case 0x20000000: /* 512 MB */
maskbits = 7;
break;
case 0x10000000: /* 256 MB */
maskbits = 8;
break;
case 0x08000000: /* 128 MB */
maskbits = 9;
break;
case 0x04000000: /* 64 MB */
maskbits = 10;
break;
case 0x02000000: /* 32 MB */
maskbits = 11;
break;
case 0x01000000: /* 16 MB */
maskbits = 12;
break;
case 0x00800000: /* 8 MB */
maskbits = 13;
break;
case 0x00400000: /* 4 MB */
maskbits = 14;
break;
case 0x00200000: /* 2 MB */
maskbits = 15;
break;
case 0: /* OFF */
maskbits = 0;
break;
default:
panic("nile4_set_pdar: unsupported size %p", (void *) size);
}
switch (width) {
case 8:
widthbits = 0;
break;
case 16:
widthbits = 1;
break;
case 32:
widthbits = 2;
break;
case 64:
widthbits = 3;
break;
default:
panic("nile4_set_pdar: unsupported width %d", width);
}
return maskbits | (on_memory_bus ? 0x10 : 0) |
(pci_visible ? 0x20 : 0) | (widthbits << 6) |
(phys & 0xffe00000);
}
void
ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
int on_memory_bus, int pci_visible)
{
u32 temp= ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible);
ddb_out32(pdar, temp);
ddb_out32(pdar + 4, 0);
/*
* When programming a PDAR, the register should be read immediately
* after writing it. This ensures that address decoders are properly
* configured.
* [jsun] is this really necessary?
*/
ddb_in32(pdar);
ddb_in32(pdar + 4);
}
/*
* routines that mess with PCIINITx registers
*/
void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options)
{
switch (type) {
case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */
case DDB_PCICMD_IO: /* PCI I/O Space */
case DDB_PCICMD_MEM: /* PCI Memory Space */
case DDB_PCICMD_CFG: /* PCI Configuration Space */
break;
default:
panic("nile4_set_pmr: invalid type %d", type);
}
ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options );
ddb_out32(pmr + 4, 0);
}

View File

@@ -0,0 +1,142 @@
/*
* 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.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/ddb5xxx/ddb5xxx.h>
#include <asm/debug.h>
const char *get_system_type(void)
{
switch (mips_machtype) {
case MACH_NEC_DDB5074: return "NEC DDB Vrc-5074";
case MACH_NEC_DDB5476: return "NEC DDB Vrc-5476";
case MACH_NEC_DDB5477: return "NEC DDB Vrc-5477";
case MACH_NEC_ROCKHOPPER: return "NEC Rockhopper";
case MACH_NEC_ROCKHOPPERII: return "NEC RockhopperII";
default: return "Unknown NEC board";
}
}
#if defined(CONFIG_DDB5477)
void ddb5477_runtime_detection(void);
#endif
/* [jsun@junsun.net] PMON passes arguments in C main() style */
void __init prom_init(void)
{
int argc = fw_arg0;
char **arg = (char**) fw_arg1;
int i;
/* if user passes kernel args, ignore the default one */
if (argc > 1)
arcs_cmdline[0] = '\0';
/* arg[0] is "g", the rest is boot parameters */
for (i = 1; i < argc; i++) {
if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
>= sizeof(arcs_cmdline))
break;
strcat(arcs_cmdline, arg[i]);
strcat(arcs_cmdline, " ");
}
mips_machgroup = MACH_GROUP_NEC_DDB;
#if defined(CONFIG_DDB5074)
mips_machtype = MACH_NEC_DDB5074;
add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
#elif defined(CONFIG_DDB5476)
mips_machtype = MACH_NEC_DDB5476;
add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
#elif defined(CONFIG_DDB5477)
ddb5477_runtime_detection();
add_memory_region(0, board_ram_size, BOOT_MEM_RAM);
#endif
}
unsigned long __init prom_free_prom_memory(void)
{
return 0;
}
#if defined(CONFIG_DDB5477)
#define DEFAULT_LCS1_BASE 0x19000000
#define TESTVAL1 'K'
#define TESTVAL2 'S'
int board_ram_size;
void ddb5477_runtime_detection(void)
{
volatile char *test_offset;
char saved_test_byte;
/* Determine if this is a DDB5477 board, or a BSB-VR0300
base board. We can tell by checking for the location of
the NVRAM. It lives at the beginning of LCS1 on the DDB5477,
and the beginning of LCS1 on the BSB-VR0300 is flash memory.
The first 2K of the NVRAM are reserved, so don't we'll poke
around just after that.
*/
/* We can only use the PCI bus to distinquish between
the Rockhopper and RockhopperII backplanes and this must
wait until ddb5477_board_init() in setup.c after the 5477
is initialized. So, until then handle
both Rockhopper and RockhopperII backplanes as Rockhopper 1
*/
test_offset = (char *)KSEG1ADDR(DEFAULT_LCS1_BASE + 0x800);
saved_test_byte = *test_offset;
*test_offset = TESTVAL1;
if (*test_offset != TESTVAL1) {
/* We couldn't set our test value, so it must not be NVRAM,
so it's a BSB_VR0300 */
mips_machtype = MACH_NEC_ROCKHOPPER;
} else {
/* We may have gotten lucky, and the TESTVAL1 was already
stored at the test location, so we must check a second
test value */
*test_offset = TESTVAL2;
if (*test_offset != TESTVAL2) {
/* OK, we couldn't set this value either, so it must
definately be a BSB_VR0300 */
mips_machtype = MACH_NEC_ROCKHOPPER;
} else {
/* We could change the value twice, so it must be
NVRAM, so it's a DDB_VRC5477 */
mips_machtype = MACH_NEC_DDB5477;
}
}
/* Restore the original byte */
*test_offset = saved_test_byte;
/* before we know a better way, we will trust PMON for getting
* RAM size
*/
board_ram_size = 1 << (36 - (ddb_in32(DDB_SDRAM0) & 0xf));
db_run(printk("DDB run-time detection : %s, %d MB RAM\n",
mips_machtype == MACH_NEC_DDB5477 ?
"DDB5477" : "Rockhopper",
board_ram_size >> 20));
/* we can't handle ram size > 128 MB */
db_assert(board_ram_size <= (128 << 20));
}
#endif

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* arch/mips/ddb5xxx/common/rtc_ds1386.c
* low-level RTC hookups for s for Dallas 1396 chip.
*
* 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 a function, rtc_ds1386_init(), which expects an
* uncached base address as the argument. It will set the two function
* pointers expected by the MIPS generic timer code.
*/
#include <linux/types.h>
#include <linux/time.h>
#include <linux/bcd.h>
#include <asm/time.h>
#include <asm/addrspace.h>
#include <asm/mc146818rtc.h>
#include <asm/debug.h>
#define EPOCH 2000
#define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x)
#define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y
static unsigned long rtc_base;
static unsigned long
rtc_ds1386_get_time(void)
{
u8 byte;
u8 temp;
unsigned int year, month, day, hour, minute, second;
/* let us freeze external registers */
byte = READ_RTC(0xB);
byte &= 0x3f;
WRITE_RTC(0xB, byte);
/* read time data */
year = BCD2BIN(READ_RTC(0xA)) + EPOCH;
month = BCD2BIN(READ_RTC(0x9) & 0x1f);
day = BCD2BIN(READ_RTC(0x8));
minute = BCD2BIN(READ_RTC(0x2));
second = BCD2BIN(READ_RTC(0x1));
/* hour is special - deal with it later */
temp = READ_RTC(0x4);
/* enable time transfer */
byte |= 0x80;
WRITE_RTC(0xB, byte);
/* calc hour */
if (temp & 0x40) {
/* 12 hour format */
hour = BCD2BIN(temp & 0x1f);
if (temp & 0x20) hour += 12; /* PM */
} else {
/* 24 hour format */
hour = BCD2BIN(temp & 0x3f);
}
return mktime(year, month, day, hour, minute, second);
}
static int
rtc_ds1386_set_time(unsigned long t)
{
struct rtc_time tm;
u8 byte;
u8 temp;
u8 year, month, day, hour, minute, second;
/* let us freeze external registers */
byte = READ_RTC(0xB);
byte &= 0x3f;
WRITE_RTC(0xB, byte);
/* convert */
to_tm(t, &tm);
/* check each field one by one */
year = BIN2BCD(tm.tm_year - EPOCH);
if (year != READ_RTC(0xA)) {
WRITE_RTC(0xA, year);
}
temp = READ_RTC(0x9);
month = BIN2BCD(tm.tm_mon+1); /* tm_mon starts from 0 to 11 */
if (month != (temp & 0x1f)) {
WRITE_RTC( 0x9,
(month & 0x1f) | (temp & ~0x1f) );
}
day = BIN2BCD(tm.tm_mday);
if (day != READ_RTC(0x8)) {
WRITE_RTC(0x8, day);
}
temp = READ_RTC(0x4);
if (temp & 0x40) {
/* 12 hour format */
hour = 0x40;
if (tm.tm_hour > 12) {
hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
} else {
hour |= BIN2BCD(tm.tm_hour);
}
} else {
/* 24 hour format */
hour = BIN2BCD(tm.tm_hour) & 0x3f;
}
if (hour != temp) WRITE_RTC(0x4, hour);
minute = BIN2BCD(tm.tm_min);
if (minute != READ_RTC(0x2)) {
WRITE_RTC(0x2, minute);
}
second = BIN2BCD(tm.tm_sec);
if (second != READ_RTC(0x1)) {
WRITE_RTC(0x1, second);
}
return 0;
}
void
rtc_ds1386_init(unsigned long base)
{
unsigned char byte;
/* remember the base */
rtc_base = base;
db_assert((rtc_base & 0xe0000000) == KSEG1);
/* turn on RTC if it is not on */
byte = READ_RTC(0x9);
if (byte & 0x80) {
byte &= 0x7f;
WRITE_RTC(0x9, byte);
}
/* enable time transfer */
byte = READ_RTC(0xB);
byte |= 0x80;
WRITE_RTC(0xB, byte);
/* set the function pointers */
rtc_get_time = rtc_ds1386_get_time;
rtc_set_time = rtc_ds1386_set_time;
}

View File

@@ -0,0 +1,8 @@
#
# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
# under Linux.
#
obj-y += setup.o irq.o int-handler.o nile4_pic.o
EXTRA_AFLAGS := $(CFLAGS)

View File

@@ -0,0 +1,120 @@
/*
* arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
*
* Based on arch/mips/sgi/kernel/indyIRQ.S
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/* A lot of complication here is taken away because:
*
* 1) We handle one interrupt and return, sitting in a loop and moving across
* all the pending IRQ bits in the cause register is _NOT_ the answer, the
* common case is one pending IRQ so optimize in that direction.
*
* 2) We need not check against bits in the status register IRQ mask, that
* would make this routine slow as hell.
*
* 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
* between like BSD spl() brain-damage.
*
* Furthermore, the IRQs on the INDY look basically (barring software IRQs
* which we don't use at all) like:
*
* MIPS IRQ Source
* -------- ------
* 0 Software (ignored)
* 1 Software (ignored)
* 2 Local IRQ level zero
* 3 Local IRQ level one
* 4 8254 Timer zero
* 5 8254 Timer one
* 6 Bus Error
* 7 R4k timer (what we use)
*
* We handle the IRQ according to _our_ priority which is:
*
* Highest ---- R4k Timer
* Local IRQ zero
* Local IRQ one
* Bus Error
* 8254 Timer zero
* Lowest ---- 8254 Timer one
*
* then we just return, if multiple IRQs are pending then we will just take
* another exception, big deal.
*/
.text
.set noreorder
.set noat
.align 5
NESTED(ddbIRQ, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 s0, CP0_CAUSE # get irq mask
#if 1
mfc0 t2,CP0_STATUS # get enabled interrupts
and s0,t2 # isolate allowed ones
#endif
/* First we check for r4k counter/timer IRQ. */
andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
beq a0, zero, 1f
andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
/* Wheee, local level zero interrupt. */
jal ddb_local0_irqdispatch
move a0, sp # delay slot
j ret_from_irq
nop # delay slot
1:
beq a0, zero, 1f
andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
/* Wheee, local level one interrupt. */
move a0, sp
jal ddb_local1_irqdispatch
nop
j ret_from_irq
nop
1:
beq a0, zero, 1f
nop
/* Wheee, an asynchronous bus error... */
move a0, sp
jal ddb_buserror_irq
nop
j ret_from_irq
nop
1:
/* Here by mistake? This is possible, what can happen
* is that by the time we take the exception the IRQ
* pin goes low, so just leave if this is the case.
*/
andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
beq a0, zero, 1f
/* Must be one of the 8254 timers... */
move a0, sp
jal ddb_8254timer_irq
nop
1:
j ret_from_irq
nop
END(ddbIRQ)

View File

@@ -0,0 +1,159 @@
/*
* arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/irq_cpu.h>
#include <asm/ptrace.h>
#include <asm/nile4.h>
#include <asm/ddb5xxx/ddb5xxx.h>
#include <asm/ddb5xxx/ddb5074.h>
extern asmlinkage void ddbIRQ(void);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
static void m1543_irq_setup(void)
{
/*
* The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
* the possible IO sources in the M1543 are in use by us. We will
* use the following mapping:
*
* IRQ1 - keyboard (default set by M1543)
* IRQ3 - reserved for UART B (default set by M1543) (note that
* the schematics for the DDB Vrc-5074 board seem to
* indicate that IRQ3 is connected to the DS1386
* watchdog timer interrupt output so we might have
* a conflict)
* IRQ4 - reserved for UART A (default set by M1543)
* IRQ5 - parallel (default set by M1543)
* IRQ8 - DS1386 time of day (RTC) interrupt
* IRQ12 - mouse
*/
/*
* Assing mouse interrupt to IRQ12
*/
/* Enter configuration mode */
outb(0x51, M1543_PNP_CONFIG);
outb(0x23, M1543_PNP_CONFIG);
/* Select logical device 7 (Keyboard) */
outb(0x07, M1543_PNP_INDEX);
outb(0x07, M1543_PNP_DATA);
/* Select IRQ12 */
outb(0x72, M1543_PNP_INDEX);
outb(0x0c, M1543_PNP_DATA);
outb(0x30, M1543_PNP_INDEX);
printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA));
outb(0x70, M1543_PNP_INDEX);
printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA));
/* Leave configration mode */
outb(0xbb, M1543_PNP_CONFIG);
}
void ddb_local0_irqdispatch(struct pt_regs *regs)
{
u32 mask;
int nile4_irq;
mask = nile4_get_irq_stat(0);
/* Handle the timer interrupt first */
#if 0
if (mask & (1 << NILE4_INT_GPT)) {
do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
mask &= ~(1 << NILE4_INT_GPT);
}
#endif
for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
if (mask & 1) {
if (nile4_irq == NILE4_INT_INTE) {
int i8259_irq;
nile4_clear_irq(NILE4_INT_INTE);
i8259_irq = nile4_i8259_iack();
do_IRQ(i8259_irq, regs);
} else
do_IRQ(nile4_to_irq(nile4_irq), regs);
}
}
void ddb_local1_irqdispatch(void)
{
printk("ddb_local1_irqdispatch called\n");
}
void ddb_buserror_irq(void)
{
printk("ddb_buserror_irq called\n");
}
void ddb_8254timer_irq(void)
{
printk("ddb_8254timer_irq called\n");
}
void __init arch_init_irq(void)
{
/* setup cascade interrupts */
setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
set_except_vector(0, ddbIRQ);
nile4_irq_setup(NILE4_IRQ_BASE);
m1543_irq_setup();
init_i8259_irqs();
printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE);
mips_cpu_irq_init(CPU_IRQ_BASE);
printk("enabling 8259 cascade\n");
ddb5074_led_hex(0);
/* Enable the interrupt cascade */
nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE);
}

View File

@@ -0,0 +1,287 @@
/*
* arch/mips/ddb5476/nile4.c --
* low-level PIC code for NEC Vrc-5476 (Nile 4)
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/addrspace.h>
#include <asm/ddb5xxx/ddb5xxx.h>
static int irq_base;
/*
* Interrupt Programming
*/
void nile4_map_irq(int nile4_irq, int cpu_irq)
{
u32 offset, t;
offset = DDB_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = ddb_in32(offset);
t &= ~(7 << (nile4_irq * 4));
t |= cpu_irq << (nile4_irq * 4);
ddb_out32(offset, t);
}
void nile4_map_irq_all(int cpu_irq)
{
u32 all, t;
all = cpu_irq;
all |= all << 4;
all |= all << 8;
all |= all << 16;
t = ddb_in32(DDB_INTCTRL);
t &= 0x88888888;
t |= all;
ddb_out32(DDB_INTCTRL, t);
t = ddb_in32(DDB_INTCTRL + 4);
t &= 0x88888888;
t |= all;
ddb_out32(DDB_INTCTRL + 4, t);
}
void nile4_enable_irq(unsigned int nile4_irq)
{
u32 offset, t;
nile4_irq-=irq_base;
ddb5074_led_hex(8);
offset = DDB_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
ddb5074_led_hex(9);
t = ddb_in32(offset);
ddb5074_led_hex(0xa);
t |= 8 << (nile4_irq * 4);
ddb_out32(offset, t);
ddb5074_led_hex(0xb);
}
void nile4_disable_irq(unsigned int nile4_irq)
{
u32 offset, t;
nile4_irq-=irq_base;
offset = DDB_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = ddb_in32(offset);
t &= ~(8 << (nile4_irq * 4));
ddb_out32(offset, t);
}
void nile4_disable_irq_all(void)
{
ddb_out32(DDB_INTCTRL, 0);
ddb_out32(DDB_INTCTRL + 4, 0);
}
u16 nile4_get_irq_stat(int cpu_irq)
{
return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
}
void nile4_enable_irq_output(int cpu_irq)
{
u32 t;
t = ddb_in32(DDB_INTSTAT1 + 4);
t |= 1 << (16 + cpu_irq);
ddb_out32(DDB_INTSTAT1, t);
}
void nile4_disable_irq_output(int cpu_irq)
{
u32 t;
t = ddb_in32(DDB_INTSTAT1 + 4);
t &= ~(1 << (16 + cpu_irq));
ddb_out32(DDB_INTSTAT1, t);
}
void nile4_set_pci_irq_polarity(int pci_irq, int high)
{
u32 t;
t = ddb_in32(DDB_INTPPES);
if (high)
t &= ~(1 << (pci_irq * 2));
else
t |= 1 << (pci_irq * 2);
ddb_out32(DDB_INTPPES, t);
}
void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
{
u32 t;
t = ddb_in32(DDB_INTPPES);
if (level)
t |= 2 << (pci_irq * 2);
else
t &= ~(2 << (pci_irq * 2));
ddb_out32(DDB_INTPPES, t);
}
void nile4_clear_irq(int nile4_irq)
{
nile4_irq-=irq_base;
ddb_out32(DDB_INTCLR, 1 << nile4_irq);
}
void nile4_clear_irq_mask(u32 mask)
{
ddb_out32(DDB_INTCLR, mask);
}
u8 nile4_i8259_iack(void)
{
u8 irq;
u32 reg;
/* Set window 0 for interrupt acknowledge */
reg = ddb_in32(DDB_PCIINIT0);
ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
/* restore window 0 for PCI I/O space */
// ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
ddb_out32(DDB_PCIINIT0, reg);
/* i8269.c set the base vector to be 0x0 */
return irq ;
}
static unsigned int nile4_irq_startup(unsigned int irq) {
nile4_enable_irq(irq);
return 0;
}
static void nile4_ack_irq(unsigned int irq) {
ddb5074_led_hex(4);
nile4_clear_irq(irq);
ddb5074_led_hex(2);
nile4_disable_irq(irq);
ddb5074_led_hex(0);
}
static void nile4_irq_end(unsigned int irq) {
ddb5074_led_hex(3);
if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
ddb5074_led_hex(5);
nile4_enable_irq(irq);
ddb5074_led_hex(7);
}
ddb5074_led_hex(1);
}
#define nile4_irq_shutdown nile4_disable_irq
static hw_irq_controller nile4_irq_controller = {
"nile4",
nile4_irq_startup,
nile4_irq_shutdown,
nile4_enable_irq,
nile4_disable_irq,
nile4_ack_irq,
nile4_irq_end,
NULL
};
void nile4_irq_setup(u32 base) {
int i;
irq_base=base;
/* Map all interrupts to CPU int #0 */
nile4_map_irq_all(0);
/* PCI INTA#-E# must be level triggered */
nile4_set_pci_irq_level_or_edge(0, 1);
nile4_set_pci_irq_level_or_edge(1, 1);
nile4_set_pci_irq_level_or_edge(2, 1);
nile4_set_pci_irq_level_or_edge(3, 1);
nile4_set_pci_irq_level_or_edge(4, 1);
/* PCI INTA#-D# must be active low, INTE# must be active high */
nile4_set_pci_irq_polarity(0, 0);
nile4_set_pci_irq_polarity(1, 0);
nile4_set_pci_irq_polarity(2, 0);
nile4_set_pci_irq_polarity(3, 0);
nile4_set_pci_irq_polarity(4, 1);
for (i = 0; i < 16; i++) {
nile4_clear_irq(i);
nile4_disable_irq(i);
}
/* Enable CPU int #0 */
nile4_enable_irq_output(0);
for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &nile4_irq_controller;
}
}
#if defined(CONFIG_RUNTIME_DEBUG)
void nile4_dump_irq_status(void)
{
printk(KERN_DEBUG "
CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
(void *) ddb_in32(DDB_CPUSTAT));
printk(KERN_DEBUG "
INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
(void *) ddb_in32(DDB_INTCTRL));
printk(KERN_DEBUG
"INTSTAT0 = %p:%p\n",
(void *) ddb_in32(DDB_INTSTAT0 + 4),
(void *) ddb_in32(DDB_INTSTAT0));
printk(KERN_DEBUG
"INTSTAT1 = %p:%p\n",
(void *) ddb_in32(DDB_INTSTAT1 + 4),
(void *) ddb_in32(DDB_INTSTAT1));
printk(KERN_DEBUG
"INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
(void *) ddb_in32(DDB_INTCLR));
printk(KERN_DEBUG
"INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
(void *) ddb_in32(DDB_INTPPES));
}
#endif

View File

@@ -0,0 +1,235 @@
/*
* arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <linux/init.h>
#include <linux/kbd_ll.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <asm/addrspace.h>
#include <asm/bcache.h>
#include <asm/irq.h>
#include <asm/reboot.h>
#include <asm/gdb-stub.h>
#include <asm/time.h>
#include <asm/nile4.h>
#include <asm/ddb5xxx/ddb5074.h>
#include <asm/ddb5xxx/ddb5xxx.h>
static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
static void ddb_machine_restart(char *command)
{
u32 t;
/* PCI cold reset */
t = nile4_in32(NILE4_PCICTRL + 4);
t |= 0x40000000;
nile4_out32(NILE4_PCICTRL + 4, t);
/* CPU cold reset */
t = nile4_in32(NILE4_CPUSTAT);
t |= 1;
nile4_out32(NILE4_CPUSTAT, t);
/* Call the PROM */
back_to_prom();
}
static void ddb_machine_halt(void)
{
printk("DDB Vrc-5074 halted.\n");
do {
} while (1);
}
static void ddb_machine_power_off(void)
{
printk("DDB Vrc-5074 halted. Please turn off the power.\n");
do {
} while (1);
}
extern void rtc_ds1386_init(unsigned long base);
extern void (*board_timer_setup) (struct irqaction * irq);
static void __init ddb_timer_init(struct irqaction *irq)
{
/* set the clock to 1 Hz */
nile4_out32(NILE4_T2CTRL, 1000000);
/* enable the General-Purpose Timer */
nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
/* reset timer */
nile4_out32(NILE4_T2CNTR, 0);
/* enable interrupt */
setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT));
change_c0_status(ST0_IM,
IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
}
static void __init ddb_time_init(void)
{
/* we have ds1396 RTC chip */
rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
}
static void __init ddb5074_setup(void)
{
set_io_port_base(NILE4_PCI_IO_BASE);
isa_slot_offset = NILE4_PCI_MEM_BASE;
board_timer_setup = ddb_timer_init;
board_time_init = ddb_time_init;
_machine_restart = ddb_machine_restart;
_machine_halt = ddb_machine_halt;
_machine_power_off = ddb_machine_power_off;
ddb_out32(DDB_BAR0, 0);
ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10);
ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10);
/* Reboot on panic */
panic_timeout = 180;
}
early_initcall(ddb5074_setup);
#define USE_NILE4_SERIAL 0
#if USE_NILE4_SERIAL
#define ns16550_in(reg) nile4_in8((reg)*8)
#define ns16550_out(reg, val) nile4_out8((reg)*8, (val))
#else
#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8)
static inline u8 ns16550_in(u32 reg)
{
return *(volatile u8 *) (NS16550_BASE + reg);
}
static inline void ns16550_out(u32 reg, u8 val)
{
*(volatile u8 *) (NS16550_BASE + reg) = val;
}
#endif
#define NS16550_RBR 0
#define NS16550_THR 0
#define NS16550_DLL 0
#define NS16550_IER 1
#define NS16550_DLM 1
#define NS16550_FCR 2
#define NS16550_IIR 2
#define NS16550_LCR 3
#define NS16550_MCR 4
#define NS16550_LSR 5
#define NS16550_MSR 6
#define NS16550_SCR 7
#define NS16550_LSR_DR 0x01 /* Data ready */
#define NS16550_LSR_OE 0x02 /* Overrun */
#define NS16550_LSR_PE 0x04 /* Parity error */
#define NS16550_LSR_FE 0x08 /* Framing error */
#define NS16550_LSR_BI 0x10 /* Break */
#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */
#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */
#define NS16550_LSR_ERR 0x80 /* Error */
void _serinit(void)
{
#if USE_NILE4_SERIAL
ns16550_out(NS16550_LCR, 0x80);
ns16550_out(NS16550_DLM, 0x00);
ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
ns16550_out(NS16550_LCR, 0x00);
ns16550_out(NS16550_LCR, 0x03);
ns16550_out(NS16550_FCR, 0x47);
#else
/* done by PMON */
#endif
}
void _putc(char c)
{
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
ns16550_out(NS16550_THR, c);
if (c == '\n') {
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
ns16550_out(NS16550_THR, '\r');
}
}
void _puts(const char *s)
{
char c;
while ((c = *s++))
_putc(c);
}
char _getc(void)
{
while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
return ns16550_in(NS16550_RBR);
}
int _testc(void)
{
return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
}
/*
* Hexadecimal 7-segment LED
*/
void ddb5074_led_hex(int hex)
{
outb(hex, 0x80);
}
/*
* LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
*/
struct pci_dev *pci_pmu = NULL;
void ddb5074_led_d2(int on)
{
u8 t;
if (pci_pmu) {
pci_read_config_byte(pci_pmu, 0x7e, &t);
if (on)
t &= 0x7f;
else
t |= 0x80;
pci_write_config_byte(pci_pmu, 0x7e, t);
}
}
void ddb5074_led_d3(int on)
{
u8 t;
if (pci_pmu) {
pci_read_config_byte(pci_pmu, 0x7e, &t);
if (on)
t &= 0xbf;
else
t |= 0x40;
pci_write_config_byte(pci_pmu, 0x7e, t);
}
}

View File

@@ -0,0 +1,9 @@
#
# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines
# under Linux.
#
obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
obj-$(CONFIG_KGDB) += dbg_io.o
EXTRA_AFLAGS := $(CFLAGS)

View File

@@ -0,0 +1,136 @@
/*
* kgdb io functions for DDB5476. We use the second serial port.
*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
/* ======================= CONFIG ======================== */
/* [jsun] we use the second serial port for kdb */
#define BASE 0xa60002f8
#define MAX_BAUD 115200
/* distance in bytes between two serial registers */
#define REG_OFFSET 1
/*
* 0 - kgdb does serial init
* 1 - kgdb skip serial init
*/
static int remoteDebugInitialized = 0;
/*
* the default baud rate *if* kgdb does serial init
*/
#define BAUD_DEFAULT UART16550_BAUD_38400
/* ======================= END OF CONFIG ======================== */
typedef unsigned char uint8;
typedef unsigned int uint32;
#define UART16550_BAUD_2400 2400
#define UART16550_BAUD_4800 4800
#define UART16550_BAUD_9600 9600
#define UART16550_BAUD_19200 19200
#define UART16550_BAUD_38400 38400
#define UART16550_BAUD_57600 57600
#define UART16550_BAUD_115200 115200
#define UART16550_PARITY_NONE 0
#define UART16550_PARITY_ODD 0x08
#define UART16550_PARITY_EVEN 0x18
#define UART16550_PARITY_MARK 0x28
#define UART16550_PARITY_SPACE 0x38
#define UART16550_DATA_5BIT 0x0
#define UART16550_DATA_6BIT 0x1
#define UART16550_DATA_7BIT 0x2
#define UART16550_DATA_8BIT 0x3
#define UART16550_STOP_1BIT 0x0
#define UART16550_STOP_2BIT 0x4
/* register offset */
#define OFS_RCV_BUFFER 0
#define OFS_TRANS_HOLD 0
#define OFS_SEND_BUFFER 0
#define OFS_INTR_ENABLE (1*REG_OFFSET)
#define OFS_INTR_ID (2*REG_OFFSET)
#define OFS_DATA_FORMAT (3*REG_OFFSET)
#define OFS_LINE_CONTROL (3*REG_OFFSET)
#define OFS_MODEM_CONTROL (4*REG_OFFSET)
#define OFS_RS232_OUTPUT (4*REG_OFFSET)
#define OFS_LINE_STATUS (5*REG_OFFSET)
#define OFS_MODEM_STATUS (6*REG_OFFSET)
#define OFS_RS232_INPUT (6*REG_OFFSET)
#define OFS_SCRATCH_PAD (7*REG_OFFSET)
#define OFS_DIVISOR_LSB (0*REG_OFFSET)
#define OFS_DIVISOR_MSB (1*REG_OFFSET)
/* memory-mapped read/write of the port */
#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
{
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
/* set up buad rate */
{
uint32 divisor;
/* set DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
/* set divisor */
divisor = MAX_BAUD / baud;
UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
/* clear DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
}
/* set data format */
UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
}
uint8 getDebugChar(void)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(BAUD_DEFAULT,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
return UART16550_READ(OFS_RCV_BUFFER);
}
int putDebugChar(uint8 byte)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(BAUD_DEFAULT,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
UART16550_WRITE(OFS_SEND_BUFFER, byte);
return 1;
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* First-level interrupt dispatcher for ddb5476
*
* 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 <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/ddb5xxx/ddb5476.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(ddb5476_handle_int, 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_cpu_ip7
andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */
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
move a0, sp
jal vrc5476_irq_dispatch
j ret_from_irq
nop
.align 5
ll_cpu_ip0:
li a0, CPU_IRQ_BASE + 0
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip1:
li a0, CPU_IRQ_BASE + 1
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip2: /* jump to second-level dispatching */
move a0, sp
jal vrc5476_irq_dispatch
j ret_from_irq
ll_cpu_ip3:
li a0, CPU_IRQ_BASE + 3
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip4:
li a0, CPU_IRQ_BASE + 4
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip5:
li a0, CPU_IRQ_BASE + 5
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip6:
li a0, CPU_IRQ_BASE + 6
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip7:
li a0, CPU_IRQ_BASE + 7
move a1, sp
jal do_IRQ
j ret_from_irq
END(ddb5476_handle_int)

View File

@@ -0,0 +1,143 @@
/*
* arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* Re-write the whole thing to use new irq.c file.
* Copyright (C) 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
*/
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/ptrace.h>
#include <asm/ddb5xxx/ddb5xxx.h>
#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
static void m1543_irq_setup(void)
{
/*
* The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
* the possible IO sources in the M1543 are in use by us. We will
* use the following mapping:
*
* IRQ1 - keyboard (default set by M1543)
* IRQ3 - reserved for UART B (default set by M1543) (note that
* the schematics for the DDB Vrc-5476 board seem to
* indicate that IRQ3 is connected to the DS1386
* watchdog timer interrupt output so we might have
* a conflict)
* IRQ4 - reserved for UART A (default set by M1543)
* IRQ5 - parallel (default set by M1543)
* IRQ8 - DS1386 time of day (RTC) interrupt
* IRQ9 - USB (hardwired in ddb_setup)
* IRQ10 - PMU (hardwired in ddb_setup)
* IRQ12 - mouse
* IRQ14,15 - IDE controller (need to be confirmed, jsun)
*/
/*
* Assing mouse interrupt to IRQ12
*/
/* Enter configuration mode */
outb(0x51, M1543_PNP_CONFIG);
outb(0x23, M1543_PNP_CONFIG);
/* Select logical device 7 (Keyboard) */
outb(0x07, M1543_PNP_INDEX);
outb(0x07, M1543_PNP_DATA);
/* Select IRQ12 */
outb(0x72, M1543_PNP_INDEX);
outb(0x0c, M1543_PNP_DATA);
/* Leave configration mode */
outb(0xbb, M1543_PNP_CONFIG);
}
static void nile4_irq_setup(void)
{
int i;
/* Map all interrupts to CPU int #0 (IP2) */
nile4_map_irq_all(0);
/* PCI INTA#-E# must be level triggered */
nile4_set_pci_irq_level_or_edge(0, 1);
nile4_set_pci_irq_level_or_edge(1, 1);
nile4_set_pci_irq_level_or_edge(2, 1);
nile4_set_pci_irq_level_or_edge(3, 1);
/* PCI INTA#, B#, D# must be active low, INTC# must be active high */
nile4_set_pci_irq_polarity(0, 0);
nile4_set_pci_irq_polarity(1, 0);
nile4_set_pci_irq_polarity(2, 1);
nile4_set_pci_irq_polarity(3, 0);
for (i = 0; i < 16; i++)
nile4_clear_irq(i);
/* Enable CPU int #0 */
nile4_enable_irq_output(0);
/* memory resource acquire in ddb_setup */
}
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
extern asmlinkage void ddb5476_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
extern void mips_cpu_irq_init(u32 irq_base);
extern void vrc5476_irq_init(u32 irq_base);
void __init arch_init_irq(void)
{
/* hardware initialization */
nile4_irq_setup();
m1543_irq_setup();
/* controller setup */
init_i8259_irqs();
vrc5476_irq_init(VRC5476_IRQ_BASE);
mips_cpu_irq_init(CPU_IRQ_BASE);
/* setup cascade interrupts */
setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade);
/* setup error interrupts for debugging */
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
/* setup the grandpa intr vector */
set_except_vector(0, ddb5476_handle_int);
}

View File

@@ -0,0 +1,190 @@
/*
* arch/mips/ddb5476/nile4.c --
* low-level PIC code for NEC Vrc-5476 (Nile 4)
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/addrspace.h>
#include <asm/ddb5xxx/ddb5xxx.h>
/*
* Interrupt Programming
*/
void nile4_map_irq(int nile4_irq, int cpu_irq)
{
u32 offset, t;
offset = DDB_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = ddb_in32(offset);
t &= ~(7 << (nile4_irq * 4));
t |= cpu_irq << (nile4_irq * 4);
ddb_out32(offset, t);
}
void nile4_map_irq_all(int cpu_irq)
{
u32 all, t;
all = cpu_irq;
all |= all << 4;
all |= all << 8;
all |= all << 16;
t = ddb_in32(DDB_INTCTRL);
t &= 0x88888888;
t |= all;
ddb_out32(DDB_INTCTRL, t);
t = ddb_in32(DDB_INTCTRL + 4);
t &= 0x88888888;
t |= all;
ddb_out32(DDB_INTCTRL + 4, t);
}
void nile4_enable_irq(int nile4_irq)
{
u32 offset, t;
offset = DDB_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = ddb_in32(offset);
t |= 8 << (nile4_irq * 4);
ddb_out32(offset, t);
}
void nile4_disable_irq(int nile4_irq)
{
u32 offset, t;
offset = DDB_INTCTRL;
if (nile4_irq >= 8) {
offset += 4;
nile4_irq -= 8;
}
t = ddb_in32(offset);
t &= ~(8 << (nile4_irq * 4));
ddb_out32(offset, t);
}
void nile4_disable_irq_all(void)
{
ddb_out32(DDB_INTCTRL, 0);
ddb_out32(DDB_INTCTRL + 4, 0);
}
u16 nile4_get_irq_stat(int cpu_irq)
{
return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
}
void nile4_enable_irq_output(int cpu_irq)
{
u32 t;
t = ddb_in32(DDB_INTSTAT1 + 4);
t |= 1 << (16 + cpu_irq);
ddb_out32(DDB_INTSTAT1, t);
}
void nile4_disable_irq_output(int cpu_irq)
{
u32 t;
t = ddb_in32(DDB_INTSTAT1 + 4);
t &= ~(1 << (16 + cpu_irq));
ddb_out32(DDB_INTSTAT1, t);
}
void nile4_set_pci_irq_polarity(int pci_irq, int high)
{
u32 t;
t = ddb_in32(DDB_INTPPES);
if (high)
t &= ~(1 << (pci_irq * 2));
else
t |= 1 << (pci_irq * 2);
ddb_out32(DDB_INTPPES, t);
}
void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
{
u32 t;
t = ddb_in32(DDB_INTPPES);
if (level)
t |= 2 << (pci_irq * 2);
else
t &= ~(2 << (pci_irq * 2));
ddb_out32(DDB_INTPPES, t);
}
void nile4_clear_irq(int nile4_irq)
{
ddb_out32(DDB_INTCLR, 1 << nile4_irq);
}
void nile4_clear_irq_mask(u32 mask)
{
ddb_out32(DDB_INTCLR, mask);
}
u8 nile4_i8259_iack(void)
{
u8 irq;
u32 reg;
/* Set window 0 for interrupt acknowledge */
reg = ddb_in32(DDB_PCIINIT0);
ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
/* restore window 0 for PCI I/O space */
// ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
ddb_out32(DDB_PCIINIT0, reg);
/* i8269.c set the base vector to be 0x0 */
return irq + I8259_IRQ_BASE;
}
#if defined(CONFIG_RUNTIME_DEBUG)
void nile4_dump_irq_status(void)
{
printk(KERN_DEBUG "
CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
(void *) ddb_in32(DDB_CPUSTAT));
printk(KERN_DEBUG "
INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
(void *) ddb_in32(DDB_INTCTRL));
printk(KERN_DEBUG
"INTSTAT0 = %p:%p\n",
(void *) ddb_in32(DDB_INTSTAT0 + 4),
(void *) ddb_in32(DDB_INTSTAT0));
printk(KERN_DEBUG
"INTSTAT1 = %p:%p\n",
(void *) ddb_in32(DDB_INTSTAT1 + 4),
(void *) ddb_in32(DDB_INTSTAT1));
printk(KERN_DEBUG
"INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
(void *) ddb_in32(DDB_INTCLR));
printk(KERN_DEBUG
"INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
(void *) ddb_in32(DDB_INTPPES));
}
#endif

View File

@@ -0,0 +1,297 @@
/*
* arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <linux/init.h>
#include <linux/kbd_ll.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <asm/addrspace.h>
#include <asm/bcache.h>
#include <asm/irq.h>
#include <asm/reboot.h>
#include <asm/gdb-stub.h>
#include <asm/time.h>
#include <asm/debug.h>
#include <asm/traps.h>
#include <asm/ddb5xxx/ddb5xxx.h>
// #define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */
#ifdef USE_CPU_COUNTER_TIMER
#define CPU_COUNTER_FREQUENCY 83000000
#else
/* otherwise we use general purpose timer */
#define TIMER_FREQUENCY 83000000
#define TIMER_BASE DDB_T2CTRL
#define TIMER_IRQ (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT)
#endif
static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
static void ddb_machine_restart(char *command)
{
u32 t;
/* PCI cold reset */
t = ddb_in32(DDB_PCICTRL + 4);
t |= 0x40000000;
ddb_out32(DDB_PCICTRL + 4, t);
/* CPU cold reset */
t = ddb_in32(DDB_CPUSTAT);
t |= 1;
ddb_out32(DDB_CPUSTAT, t);
/* Call the PROM */
back_to_prom();
}
static void ddb_machine_halt(void)
{
printk(KERN_NOTICE "DDB Vrc-5476 halted.\n");
while (1);
}
static void ddb_machine_power_off(void)
{
printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n");
while (1);
}
extern void rtc_ds1386_init(unsigned long base);
static void __init ddb_time_init(void)
{
#if defined(USE_CPU_COUNTER_TIMER)
mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
#endif
/* we have ds1396 RTC chip */
rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
}
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static void __init ddb_timer_setup(struct irqaction *irq)
{
#if defined(USE_CPU_COUNTER_TIMER)
unsigned int count;
/* we are using the cpu counter for timer interrupts */
setup_irq(CPU_IRQ_BASE + 7, irq);
/* to generate the first timer interrupt */
count = read_c0_count();
write_c0_compare(count + 1000);
#else
ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ);
ddb_out32(TIMER_BASE+4, 0x1); /* enable timer */
setup_irq(TIMER_IRQ, irq);
#endif
}
static struct {
struct resource dma1;
struct resource timer;
struct resource rtc;
struct resource dma_page_reg;
struct resource dma2;
} ddb5476_ioport = {
{
"dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
"timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
"rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
"dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
};
static struct {
struct resource nile4;
} ddb5476_iomem = {
{ "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY}
};
static void ddb5476_board_init(void);
static void __init ddb5476_setup(void)
{
set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
board_time_init = ddb_time_init;
board_timer_setup = ddb_timer_setup;
_machine_restart = ddb_machine_restart;
_machine_halt = ddb_machine_halt;
_machine_power_off = ddb_machine_power_off;
/* request io port/mem resources */
if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
request_resource(&ioport_resource,
&ddb5476_ioport.dma_page_reg)
|| request_resource(&ioport_resource, &ddb5476_ioport.dma2)
|| request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
printk
("ddb_setup - requesting oo port resources failed.\n");
for (;;);
}
/* Reboot on panic */
panic_timeout = 180;
/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
/* *(long*)0xbfa00218 = 0x8; */
/* board initialization stuff */
ddb5476_board_init();
}
early_initcall(ddb5476_setup);
/*
* We don't trust bios. We essentially does hardware re-initialization
* as complete as possible, as far as we know we can safely do.
*/
static void ddb5476_board_init(void)
{
/* ----------- setup PDARs ------------ */
/* check SDRAM0, whether we are on MEM bus does not matter */
db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) ==
ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1));
/* SDRAM1 should be turned off. What is this for anyway ? */
db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
/* flash 1&2, DDB status, DDB control */
ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0);
ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0);
ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0);
ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0);
/* shut off other pdar so they don't accidentally get into the way */
ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0);
ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0);
ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0);
/* verify VRC5477 base addr */
/* don't care about some details */
db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) ==
ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0));
/* verify BOOT ROM addr */
/* don't care about some details */
db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) ==
ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
/* setup PCI windows - window1 for MEM/config, window0 for IO */
ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1);
ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
/* ----------- setup PDARs ------------ */
/* this is problematic - it will reset Aladin which cause we loose
* serial port, and we don't know how to set up Aladin chip again.
*/
// ddb_pci_reset_bus();
ddb_out32(DDB_BAR0, 0x00000008);
ddb_out32(DDB_BARC, 0xffffffff);
ddb_out32(DDB_BARB, 0xffffffff);
ddb_out32(DDB_BAR1, 0xffffffff);
ddb_out32(DDB_BAR2, 0xffffffff);
ddb_out32(DDB_BAR3, 0xffffffff);
ddb_out32(DDB_BAR4, 0xffffffff);
ddb_out32(DDB_BAR5, 0xffffffff);
ddb_out32(DDB_BAR6, 0xffffffff);
ddb_out32(DDB_BAR7, 0xffffffff);
ddb_out32(DDB_BAR8, 0xffffffff);
/* ----------- switch PCI1 to PCI CONFIG space ------------ */
ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1);
ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32);
/* ----- M1543 PCI setup ------ */
/* we know M1543 PCI-ISA controller is at addr:18 */
/* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
*(volatile unsigned char *) 0xa8040072 &= 0xf0;
*(volatile unsigned char *) 0xa8040072 |= 0xa;
/* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
* no IOCHRDY signal, (bit 7 - 1)
* M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
* Make USB Master INTAJ level to edge conversion (bit 4 - 1)
*/
*(unsigned char *) 0xa8040074 = 0xd1;
/* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
* SCI routing to IRQ 13 disabled (bit 7 - 1)
* SCI interrupt level to edge conversion bypassed (bit 4 - 0)
*/
*(unsigned char *) 0xa8040076 = 0x83;
/* setup IDE controller
* enable IDE controller (bit 6 - 1)
* IDE IDSEL to be addr:24 (bit 4:5 - 11)
* no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
* no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
* primary IRQ is 14, secondary is 15 (bit 1:0 - 01
*/
// *(unsigned char*)0xa8040058 = 0x71;
// *(unsigned char*)0xa8040058 = 0x79;
// *(unsigned char*)0xa8040058 = 0x74; // use SIRQ, primary tri-state
*(unsigned char *) 0xa8040058 = 0x75; // primary tri-state
#if 0
/* this is not necessary if M5229 does not use SIRQ */
*(unsigned char *) 0xa8040044 = 0x0d; // primary to IRQ 14
*(unsigned char *) 0xa8040075 = 0x0d; // secondary to IRQ 14
#endif
/* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
/* M5229 IDSEL is addr:24; see above setting */
*(unsigned char *) 0xa9000050 |= 0x1;
/* enable bus master (bit 2) and IO decoding (bit 0) */
*(unsigned char *) 0xa9000004 |= 0x5;
/* enable native, copied from arch/ppc/k2boot/head.S */
/* TODO - need volatile, need to be portable */
*(unsigned char *) 0xa9000009 = 0xff;
/* ----- end of M1543 PCI setup ------ */
/* ----- reset on-board ether chip ------ */
*((volatile u32 *) 0xa8020004) |= 1; /* decode I/O */
*((volatile u32 *) 0xa8020010) = 0; /* set BAR address */
/* send reset command */
*((volatile u32 *) 0xa6000000) = 1; /* do a soft reset */
/* disable ether chip */
*((volatile u32 *) 0xa8020004) = 0; /* disable any decoding */
/* put it into sleep */
*((volatile u32 *) 0xa8020040) = 0x80000000;
/* ----- end of reset on-board ether chip ------ */
/* ----------- switch PCI1 back to PCI MEM space ------------ */
ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
}

View File

@@ -0,0 +1,112 @@
/*
* The irq controller for vrc5476.
*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <asm/system.h>
#include <asm/ddb5xxx/ddb5xxx.h>
static int irq_base;
static void vrc5476_irq_enable(uint irq)
{
nile4_enable_irq(irq - irq_base);
}
static void vrc5476_irq_disable(uint irq)
{
nile4_disable_irq(irq - irq_base);
}
static unsigned int vrc5476_irq_startup(uint irq)
{
nile4_enable_irq(irq - irq_base);
return 0;
}
#define vrc5476_irq_shutdown vrc5476_irq_disable
static void vrc5476_irq_ack(uint irq)
{
nile4_clear_irq(irq - irq_base);
nile4_disable_irq(irq - irq_base);
}
static void vrc5476_irq_end(uint irq)
{
if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
vrc5476_irq_enable(irq);
}
static hw_irq_controller vrc5476_irq_controller = {
"vrc5476",
vrc5476_irq_startup,
vrc5476_irq_shutdown,
vrc5476_irq_enable,
vrc5476_irq_disable,
vrc5476_irq_ack,
vrc5476_irq_end,
NULL /* no affinity stuff for UP */
};
void __init
vrc5476_irq_init(u32 base)
{
u32 i;
irq_base = base;
for (i= base; i< base + NUM_VRC5476_IRQ; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &vrc5476_irq_controller;
}
}
asmlinkage void
vrc5476_irq_dispatch(struct pt_regs *regs)
{
extern void spurious_interrupt(void);
u32 mask;
int nile4_irq;
mask = nile4_get_irq_stat(0);
/* quick check for possible time interrupt */
if (mask & (1 << VRC5476_IRQ_GPT)) {
do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs);
return;
}
/* check for i8259 interrupts */
if (mask & (1 << VRC5476_I8259_CASCADE)) {
int i8259_irq = nile4_i8259_iack();
do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
return;
}
/* regular nile4 interrupts (we should not really have any */
for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) {
if (mask & 1) {
do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs);
return;
}
}
spurious_interrupt();
}

View File

@@ -0,0 +1,10 @@
#
# Makefile for NEC DDB-Vrc5477 board
#
obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o
EXTRA_AFLAGS := $(CFLAGS)

View File

@@ -0,0 +1,160 @@
/***********************************************************************
*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* arch/mips/ddb5xxx/ddb5477/debug.c
* vrc5477 specific debug 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 <linux/kernel.h>
#include <asm/mipsregs.h>
#include <asm/ddb5xxx/ddb5xxx.h>
typedef struct {
const char *regname;
unsigned regaddr;
} Register;
void jsun_show_regs(char *name, Register *regs)
{
int i;
printk("\nshow regs: %s\n", name);
for(i=0;regs[i].regname!= NULL; i++) {
printk("%-16s= %08x\t\t(@%08x)\n",
regs[i].regname,
*(unsigned *)(regs[i].regaddr),
regs[i].regaddr);
}
}
static Register int_regs[] = {
{"DDB_INTCTRL0", DDB_BASE + DDB_INTCTRL0},
{"DDB_INTCTRL1", DDB_BASE + DDB_INTCTRL1},
{"DDB_INTCTRL2", DDB_BASE + DDB_INTCTRL2},
{"DDB_INTCTRL3", DDB_BASE + DDB_INTCTRL3},
{"DDB_INT0STAT", DDB_BASE + DDB_INT0STAT},
{"DDB_INT1STAT", DDB_BASE + DDB_INT1STAT},
{"DDB_INT2STAT", DDB_BASE + DDB_INT2STAT},
{"DDB_INT3STAT", DDB_BASE + DDB_INT3STAT},
{"DDB_INT4STAT", DDB_BASE + DDB_INT4STAT},
{"DDB_NMISTAT", DDB_BASE + DDB_NMISTAT},
{"DDB_INTPPES0", DDB_BASE + DDB_INTPPES0},
{"DDB_INTPPES1", DDB_BASE + DDB_INTPPES1},
{NULL, 0x0}
};
void vrc5477_show_int_regs()
{
jsun_show_regs("interrupt registers", int_regs);
printk("CPU CAUSE = %08x\n", read_c0_cause());
printk("CPU STATUS = %08x\n", read_c0_status());
}
static Register pdar_regs[] = {
{"DDB_SDRAM0", DDB_BASE + DDB_SDRAM0},
{"DDB_SDRAM1", DDB_BASE + DDB_SDRAM1},
{"DDB_LCS0", DDB_BASE + DDB_LCS0},
{"DDB_LCS1", DDB_BASE + DDB_LCS1},
{"DDB_LCS2", DDB_BASE + DDB_LCS2},
{"DDB_INTCS", DDB_BASE + DDB_INTCS},
{"DDB_BOOTCS", DDB_BASE + DDB_BOOTCS},
{"DDB_PCIW0", DDB_BASE + DDB_PCIW0},
{"DDB_PCIW1", DDB_BASE + DDB_PCIW1},
{"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0},
{"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1},
{NULL, 0x0}
};
void vrc5477_show_pdar_regs(void)
{
jsun_show_regs("PDAR regs", pdar_regs);
}
static Register bar_regs[] = {
{"DDB_BARC0", DDB_BASE + DDB_BARC0},
{"DDB_BARM010", DDB_BASE + DDB_BARM010},
{"DDB_BARM230", DDB_BASE + DDB_BARM230},
{"DDB_BAR00", DDB_BASE + DDB_BAR00},
{"DDB_BAR10", DDB_BASE + DDB_BAR10},
{"DDB_BAR20", DDB_BASE + DDB_BAR20},
{"DDB_BAR30", DDB_BASE + DDB_BAR30},
{"DDB_BAR40", DDB_BASE + DDB_BAR40},
{"DDB_BAR50", DDB_BASE + DDB_BAR50},
{"DDB_BARB0", DDB_BASE + DDB_BARB0},
{"DDB_BARC1", DDB_BASE + DDB_BARC1},
{"DDB_BARM011", DDB_BASE + DDB_BARM011},
{"DDB_BARM231", DDB_BASE + DDB_BARM231},
{"DDB_BAR01", DDB_BASE + DDB_BAR01},
{"DDB_BAR11", DDB_BASE + DDB_BAR11},
{"DDB_BAR21", DDB_BASE + DDB_BAR21},
{"DDB_BAR31", DDB_BASE + DDB_BAR31},
{"DDB_BAR41", DDB_BASE + DDB_BAR41},
{"DDB_BAR51", DDB_BASE + DDB_BAR51},
{"DDB_BARB1", DDB_BASE + DDB_BARB1},
{NULL, 0x0}
};
void vrc5477_show_bar_regs(void)
{
jsun_show_regs("BAR regs", bar_regs);
}
static Register pci_regs[] = {
{"DDB_PCIW0", DDB_BASE + DDB_PCIW0},
{"DDB_PCIW1", DDB_BASE + DDB_PCIW1},
{"DDB_PCIINIT00", DDB_BASE + DDB_PCIINIT00},
{"DDB_PCIINIT10", DDB_BASE + DDB_PCIINIT10},
{"DDB_PCICTL0_L", DDB_BASE + DDB_PCICTL0_L},
{"DDB_PCICTL0_H", DDB_BASE + DDB_PCICTL0_H},
{"DDB_PCIARB0_L", DDB_BASE + DDB_PCIARB0_L},
{"DDB_PCIARB0_H", DDB_BASE + DDB_PCIARB0_H},
{"DDB_PCISWP0", DDB_BASE + DDB_PCISWP0},
{"DDB_PCIERR0", DDB_BASE + DDB_PCIERR0},
{"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0},
{"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1},
{"DDB_PCIINIT01", DDB_BASE + DDB_PCIINIT01},
{"DDB_PCIINIT11", DDB_BASE + DDB_PCIINIT11},
{"DDB_PCICTL1_L", DDB_BASE + DDB_PCICTL1_L},
{"DDB_PCICTL1_H", DDB_BASE + DDB_PCICTL1_H},
{"DDB_PCIARB1_L", DDB_BASE + DDB_PCIARB1_L},
{"DDB_PCIARB1_H", DDB_BASE + DDB_PCIARB1_H},
{"DDB_PCISWP1", DDB_BASE + DDB_PCISWP1},
{"DDB_PCIERR1", DDB_BASE + DDB_PCIERR1},
{NULL, 0x0}
};
void vrc5477_show_pci_regs(void)
{
jsun_show_regs("PCI regs", pci_regs);
}
static Register lb_regs[] = {
{"DDB_LCNFG", DDB_BASE + DDB_LCNFG},
{"DDB_LCST0", DDB_BASE + DDB_LCST0},
{"DDB_LCST1", DDB_BASE + DDB_LCST1},
{"DDB_LCST2", DDB_BASE + DDB_LCST2},
{"DDB_ERRADR", DDB_BASE + DDB_ERRADR},
{"DDB_ERRCS", DDB_BASE + DDB_ERRCS},
{"DDB_BTM", DDB_BASE + DDB_BTM},
{"DDB_BCST", DDB_BASE + DDB_BCST},
{NULL, 0x0}
};
void vrc5477_show_lb_regs(void)
{
jsun_show_regs("Local Bus regs", lb_regs);
}
void vrc5477_show_all_regs(void)
{
vrc5477_show_pdar_regs();
vrc5477_show_pci_regs();
vrc5477_show_bar_regs();
vrc5477_show_int_regs();
vrc5477_show_lb_regs();
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* First-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.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/ddb5xxx/ddb5477.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(ddb5477_handle_int, 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 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
bnez t1, ll_vrc5477_irq
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(ddb5477_handle_int)
.align 5
ll_vrc5477_irq:
move a0, sp
jal vrc5477_irq_dispatch
j ret_from_irq
ll_cputimer_irq:
li a0, CPU_IRQ_BASE + 7
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip0:
li a0, CPU_IRQ_BASE + 0
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip1:
li a0, CPU_IRQ_BASE + 1
move a1, sp
jal do_IRQ
j ret_from_irq

View File

@@ -0,0 +1,199 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* arch/mips/ddb5xxx/ddb5477/irq.c
* The irq setup and misc routines for DDB5476.
*
* 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/interrupt.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <asm/i8259.h>
#include <asm/system.h>
#include <asm/mipsregs.h>
#include <asm/debug.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/ddb5xxx/ddb5xxx.h>
/*
* IRQ mapping
*
* 0-7: 8 CPU interrupts
* 0 - software interrupt 0
* 1 - software interrupt 1
* 2 - most Vrc5477 interrupts are routed to this pin
* 3 - (optional) some other interrupts routed to this pin for debugg
* 4 - not used
* 5 - not used
* 6 - not used
* 7 - cpu timer (used by default)
*
* 8-39: 32 Vrc5477 interrupt sources
* (refer to the Vrc5477 manual)
*/
#define PCI0 DDB_INTPPES0
#define PCI1 DDB_INTPPES1
#define ACTIVE_LOW 1
#define ACTIVE_HIGH 0
#define LEVEL_SENSE 2
#define EDGE_TRIGGER 0
#define INTA 0
#define INTB 1
#define INTC 2
#define INTD 3
#define INTE 4
static inline void
set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
{
u32 reg_value;
u32 reg_bitmask;
reg_value = ddb_in32(pci);
reg_bitmask = 0x3 << (intn * 2);
reg_value &= ~reg_bitmask;
reg_value |= (active | trigger) << (intn * 2);
ddb_out32(pci, reg_value);
}
extern void vrc5477_irq_init(u32 base);
extern void mips_cpu_irq_init(u32 base);
extern asmlinkage void ddb5477_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
void __init arch_init_irq(void)
{
/* by default, we disable all interrupts and route all vrc5477
* interrupts to pin 0 (irq 2) */
ddb_out32(DDB_INTCTRL0, 0);
ddb_out32(DDB_INTCTRL1, 0);
ddb_out32(DDB_INTCTRL2, 0);
ddb_out32(DDB_INTCTRL3, 0);
clear_c0_status(0xff00);
set_c0_status(0x0400);
/* setup PCI interrupt attributes */
set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE);
if (mips_machtype == MACH_NEC_ROCKHOPPERII)
set_pci_int_attr(PCI0, INTC, ACTIVE_HIGH, LEVEL_SENSE);
else
set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI1, INTA, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI1, INTB, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI1, INTC, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE);
set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE);
/*
* for debugging purpose, we enable several error interrupts
* and route them to pin 1. (IP3)
*/
/* cpu parity check - 0 */
ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0);
/* cpu no-target decode - 1 */
ll_vrc5477_irq_route(1, 1); ll_vrc5477_irq_enable(1);
/* local bus read time-out - 7 */
ll_vrc5477_irq_route(7, 1); ll_vrc5477_irq_enable(7);
/* PCI SERR# - 14 */
ll_vrc5477_irq_route(14, 1); ll_vrc5477_irq_enable(14);
/* PCI internal error - 15 */
ll_vrc5477_irq_route(15, 1); ll_vrc5477_irq_enable(15);
/* IOPCI SERR# - 30 */
ll_vrc5477_irq_route(30, 1); ll_vrc5477_irq_enable(30);
/* IOPCI internal error - 31 */
ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31);
/* init all controllers */
init_i8259_irqs();
mips_cpu_irq_init(CPU_IRQ_BASE);
vrc5477_irq_init(VRC5477_IRQ_BASE);
/* setup cascade interrupts */
setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
/* hook up the first-level interrupt handler */
set_except_vector(0, ddb5477_handle_int);
}
u8 i8259_interrupt_ack(void)
{
u8 irq;
u32 reg;
/* Set window 0 for interrupt acknowledge */
reg = ddb_in32(DDB_PCIINIT10);
ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
ddb_out32(DDB_PCIINIT10, reg);
/* i8259.c set the base vector to be 0x0 */
return irq + I8259_IRQ_BASE;
}
/*
* the first level int-handler will jump here if it is a vrc5477 irq
*/
#define NUM_5477_IRQS 32
asmlinkage void
vrc5477_irq_dispatch(struct pt_regs *regs)
{
u32 intStatus;
u32 bitmask;
u32 i;
db_assert(ddb_in32(DDB_INT2STAT) == 0);
db_assert(ddb_in32(DDB_INT3STAT) == 0);
db_assert(ddb_in32(DDB_INT4STAT) == 0);
db_assert(ddb_in32(DDB_NMISTAT) == 0);
if (ddb_in32(DDB_INT1STAT) != 0) {
#if defined(CONFIG_RUNTIME_DEBUG)
vrc5477_show_int_regs();
#endif
panic("error interrupt has happened.");
}
intStatus = ddb_in32(DDB_INT0STAT);
if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
/* check for i8259 interrupts */
if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
int i8259_irq = i8259_interrupt_ack();
do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
return;
}
}
for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) {
/* do we need to "and" with the int mask? */
if (intStatus & bitmask) {
do_IRQ(VRC5477_IRQ_BASE + i, regs);
return;
}
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* arch/mips/ddb5xxx/ddb5477/irq_5477.c
* This file defines the irq handler for Vrc5477.
*
* 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.
*
*/
/*
* Vrc5477 defines 32 IRQs.
*
* This file exports one function:
* vrc5477_irq_init(u32 irq_base);
*/
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <asm/debug.h>
#include <asm/ddb5xxx/ddb5xxx.h>
/* number of total irqs supported by Vrc5477 */
#define NUM_5477_IRQ 32
static int vrc5477_irq_base = -1;
static void
vrc5477_irq_enable(unsigned int irq)
{
db_assert(vrc5477_irq_base != -1);
db_assert(irq >= vrc5477_irq_base);
db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ);
ll_vrc5477_irq_enable(irq - vrc5477_irq_base);
}
static void
vrc5477_irq_disable(unsigned int irq)
{
db_assert(vrc5477_irq_base != -1);
db_assert(irq >= vrc5477_irq_base);
db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ);
ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
}
static unsigned int vrc5477_irq_startup(unsigned int irq)
{
vrc5477_irq_enable(irq);
return 0;
}
#define vrc5477_irq_shutdown vrc5477_irq_disable
static void
vrc5477_irq_ack(unsigned int irq)
{
db_assert(vrc5477_irq_base != -1);
db_assert(irq >= vrc5477_irq_base);
db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ);
/* clear the interrupt bit */
/* some irqs require the driver to clear the sources */
ddb_out32(DDB_INTCLR32, 1 << (irq - vrc5477_irq_base));
/* disable interrupt - some handler will re-enable the irq
* and if the interrupt is leveled, we will have infinite loop
*/
ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
}
static void
vrc5477_irq_end(unsigned int irq)
{
db_assert(vrc5477_irq_base != -1);
db_assert(irq >= vrc5477_irq_base);
db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ);
if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
ll_vrc5477_irq_enable( irq - vrc5477_irq_base);
}
hw_irq_controller vrc5477_irq_controller = {
"vrc5477_irq",
vrc5477_irq_startup,
vrc5477_irq_shutdown,
vrc5477_irq_enable,
vrc5477_irq_disable,
vrc5477_irq_ack,
vrc5477_irq_end,
NULL /* no affinity stuff for UP */
};
void __init vrc5477_irq_init(u32 irq_base)
{
u32 i;
for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &vrc5477_irq_controller;
}
vrc5477_irq_base = irq_base;
}
void ll_vrc5477_irq_route(int vrc5477_irq, int ip)
{
u32 reg_value;
u32 reg_bitmask;
u32 reg_index;
db_assert(vrc5477_irq >= 0);
db_assert(vrc5477_irq < NUM_5477_IRQ);
db_assert(ip >= 0);
db_assert((ip < 5) || (ip == 6));
reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
reg_value = ddb_in32(reg_index);
reg_bitmask = 7 << (vrc5477_irq % 8 * 4);
reg_value &= ~reg_bitmask;
reg_value |= ip << (vrc5477_irq % 8 * 4);
ddb_out32(reg_index, reg_value);
}
void ll_vrc5477_irq_enable(int vrc5477_irq)
{
u32 reg_value;
u32 reg_bitmask;
u32 reg_index;
db_assert(vrc5477_irq >= 0);
db_assert(vrc5477_irq < NUM_5477_IRQ);
reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
reg_value = ddb_in32(reg_index);
reg_bitmask = 8 << (vrc5477_irq % 8 * 4);
db_assert((reg_value & reg_bitmask) == 0);
ddb_out32(reg_index, reg_value | reg_bitmask);
}
void ll_vrc5477_irq_disable(int vrc5477_irq)
{
u32 reg_value;
u32 reg_bitmask;
u32 reg_index;
db_assert(vrc5477_irq >= 0);
db_assert(vrc5477_irq < NUM_5477_IRQ);
reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
reg_value = ddb_in32(reg_index);
reg_bitmask = 8 << (vrc5477_irq % 8 * 4);
/* we assert that the interrupt is enabled (perhaps over-zealous) */
db_assert( (reg_value & reg_bitmask) != 0);
ddb_out32(reg_index, reg_value & ~reg_bitmask);
}

View File

@@ -0,0 +1,136 @@
/*
* kgdb io functions for DDB5477. We use the second serial port (upper one).
*
* Copyright (C) 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
/* ======================= CONFIG ======================== */
/* [jsun] we use the second serial port for kdb */
#define BASE 0xbfa04240
#define MAX_BAUD 115200
/* distance in bytes between two serial registers */
#define REG_OFFSET 8
/*
* 0 - kgdb does serial init
* 1 - kgdb skip serial init
*/
static int remoteDebugInitialized = 0;
/*
* the default baud rate *if* kgdb does serial init
*/
#define BAUD_DEFAULT UART16550_BAUD_38400
/* ======================= END OF CONFIG ======================== */
typedef unsigned char uint8;
typedef unsigned int uint32;
#define UART16550_BAUD_2400 2400
#define UART16550_BAUD_4800 4800
#define UART16550_BAUD_9600 9600
#define UART16550_BAUD_19200 19200
#define UART16550_BAUD_38400 38400
#define UART16550_BAUD_57600 57600
#define UART16550_BAUD_115200 115200
#define UART16550_PARITY_NONE 0
#define UART16550_PARITY_ODD 0x08
#define UART16550_PARITY_EVEN 0x18
#define UART16550_PARITY_MARK 0x28
#define UART16550_PARITY_SPACE 0x38
#define UART16550_DATA_5BIT 0x0
#define UART16550_DATA_6BIT 0x1
#define UART16550_DATA_7BIT 0x2
#define UART16550_DATA_8BIT 0x3
#define UART16550_STOP_1BIT 0x0
#define UART16550_STOP_2BIT 0x4
/* register offset */
#define OFS_RCV_BUFFER 0
#define OFS_TRANS_HOLD 0
#define OFS_SEND_BUFFER 0
#define OFS_INTR_ENABLE (1*REG_OFFSET)
#define OFS_INTR_ID (2*REG_OFFSET)
#define OFS_DATA_FORMAT (3*REG_OFFSET)
#define OFS_LINE_CONTROL (3*REG_OFFSET)
#define OFS_MODEM_CONTROL (4*REG_OFFSET)
#define OFS_RS232_OUTPUT (4*REG_OFFSET)
#define OFS_LINE_STATUS (5*REG_OFFSET)
#define OFS_MODEM_STATUS (6*REG_OFFSET)
#define OFS_RS232_INPUT (6*REG_OFFSET)
#define OFS_SCRATCH_PAD (7*REG_OFFSET)
#define OFS_DIVISOR_LSB (0*REG_OFFSET)
#define OFS_DIVISOR_MSB (1*REG_OFFSET)
/* memory-mapped read/write of the port */
#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
{
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
/* set up buad rate */
{
uint32 divisor;
/* set DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
/* set divisor */
divisor = MAX_BAUD / baud;
UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
/* clear DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
}
/* set data format */
UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
}
uint8 getDebugChar(void)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(BAUD_DEFAULT,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
return UART16550_READ(OFS_RCV_BUFFER);
}
int putDebugChar(uint8 byte)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(BAUD_DEFAULT,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
UART16550_WRITE(OFS_SEND_BUFFER, byte);
return 1;
}

View File

@@ -0,0 +1,92 @@
/*
* lcd44780.c
* Simple "driver" for a memory-mapped 44780-style LCD display.
*
* Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
*
* 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.
*
*/
#define LCD44780_COMMAND ((volatile unsigned char *)0xbe020000)
#define LCD44780_DATA ((volatile unsigned char *)0xbe020001)
#define LCD44780_4BIT_1LINE 0x20
#define LCD44780_4BIT_2LINE 0x28
#define LCD44780_8BIT_1LINE 0x30
#define LCD44780_8BIT_2LINE 0x38
#define LCD44780_MODE_DEC 0x04
#define LCD44780_MODE_DEC_SHIFT 0x05
#define LCD44780_MODE_INC 0x06
#define LCD44780_MODE_INC_SHIFT 0x07
#define LCD44780_SCROLL_LEFT 0x18
#define LCD44780_SCROLL_RIGHT 0x1e
#define LCD44780_CURSOR_UNDERLINE 0x0e
#define LCD44780_CURSOR_BLOCK 0x0f
#define LCD44780_CURSOR_OFF 0x0c
#define LCD44780_CLEAR 0x01
#define LCD44780_BLANK 0x08
#define LCD44780_RESTORE 0x0c // Same as CURSOR_OFF
#define LCD44780_HOME 0x02
#define LCD44780_LEFT 0x10
#define LCD44780_RIGHT 0x14
void lcd44780_wait(void)
{
int i, j;
for(i=0; i < 400; i++)
for(j=0; j < 10000; j++);
}
void lcd44780_command(unsigned char c)
{
*LCD44780_COMMAND = c;
lcd44780_wait();
}
void lcd44780_data(unsigned char c)
{
*LCD44780_DATA = c;
lcd44780_wait();
}
void lcd44780_puts(const char* s)
{
int i,j;
int pos = 0;
lcd44780_command(LCD44780_CLEAR);
while(*s) {
lcd44780_data(*s);
s++;
pos++;
if (pos == 8) {
/* We must write 32 of spaces to get cursor to 2nd line */
for (j=0; j<32; j++) {
lcd44780_data(' ');
}
}
if (pos == 16) {
/* We have filled all 16 character positions, so stop
outputing data */
break;
}
}
#ifdef LCD44780_PUTS_PAUSE
for(i = 1; i < 2000; i++)
lcd44780_wait();
#endif
}
void lcd44780_init(void)
{
// The display on the RockHopper is physically a single
// 16 char line (two 8 char lines concatenated). bdl
lcd44780_command(LCD44780_8BIT_2LINE);
lcd44780_command(LCD44780_MODE_INC);
lcd44780_command(LCD44780_CURSOR_BLOCK);
lcd44780_command(LCD44780_CLEAR);
}

View File

@@ -0,0 +1,15 @@
/*
* lcd44780.h
* Simple "driver" for a memory-mapped 44780-style LCD display.
*
* Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
*
* 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.
*
*/
void lcd44780_puts(const char* s);
void lcd44780_init(void);

View File

@@ -0,0 +1,405 @@
/*
*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
*
* arch/mips/ddb5xxx/ddb5477/setup.c
* Setup file 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.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/param.h> /* for HZ */
#include <linux/major.h>
#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <asm/cpu.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
#include <asm/time.h>
#include <asm/bcache.h>
#include <asm/irq.h>
#include <asm/reboot.h>
#include <asm/gdb-stub.h>
#include <asm/traps.h>
#include <asm/debug.h>
#include <asm/ddb5xxx/ddb5xxx.h>
#include "lcd44780.h"
#define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */
#define SP_TIMER_BASE DDB_SPT1CTRL_L
#define SP_TIMER_IRQ VRC5477_IRQ_SPT1
static int bus_frequency = CONFIG_DDB5477_BUS_FREQUENCY*1000;
static void ddb_machine_restart(char *command)
{
static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
u32 t;
/* PCI cold reset */
ddb_pci_reset_bus();
/* CPU cold reset */
t = ddb_in32(DDB_CPUSTAT);
db_assert((t&1));
ddb_out32(DDB_CPUSTAT, t);
/* Call the PROM */
back_to_prom();
}
static void ddb_machine_halt(void)
{
printk("DDB Vrc-5477 halted.\n");
while (1);
}
static void ddb_machine_power_off(void)
{
printk("DDB Vrc-5477 halted. Please turn off the power.\n");
while (1);
}
extern void rtc_ds1386_init(unsigned long base);
static unsigned int __init detect_bus_frequency(unsigned long rtc_base)
{
unsigned int freq;
unsigned char c;
unsigned int t1, t2;
unsigned i;
ddb_out32(SP_TIMER_BASE, 0xffffffff);
ddb_out32(SP_TIMER_BASE+4, 0x1);
ddb_out32(SP_TIMER_BASE+8, 0xffffffff);
/* check if rtc is running */
c= *(volatile unsigned char*)rtc_base;
for(i=0; (c == *(volatile unsigned char*)rtc_base) && (i<100000000); i++);
if (c == *(volatile unsigned char*)rtc_base) {
printk("Failed to detect bus frequency. Use default 83.3MHz.\n");
return 83333000;
}
c= *(volatile unsigned char*)rtc_base;
while (c == *(volatile unsigned char*)rtc_base);
/* we are now at the turn of 1/100th second, if no error. */
t1 = ddb_in32(SP_TIMER_BASE+8);
for (i=0; i< 10; i++) {
c= *(volatile unsigned char*)rtc_base;
while (c == *(volatile unsigned char*)rtc_base);
/* we are now at the turn of another 1/100th second */
t2 = ddb_in32(SP_TIMER_BASE+8);
}
ddb_out32(SP_TIMER_BASE+4, 0x0); /* disable it again */
freq = (t1 - t2)*10;
printk("DDB bus frequency detection : %u \n", freq);
return freq;
}
static void __init ddb_time_init(void)
{
unsigned long rtc_base;
unsigned int i;
/* we have ds1396 RTC chip */
if (mips_machtype == MACH_NEC_ROCKHOPPER
|| mips_machtype == MACH_NEC_ROCKHOPPERII) {
rtc_base = KSEG1ADDR(DDB_LCS2_BASE);
} else {
rtc_base = KSEG1ADDR(DDB_LCS1_BASE);
}
rtc_ds1386_init(rtc_base);
/* do we need to do run-time detection of bus speed? */
if (bus_frequency == 0) {
bus_frequency = detect_bus_frequency(rtc_base);
}
/* mips_hpt_frequency is 1/2 of the cpu core freq */
i = (read_c0_config() >> 28 ) & 7;
if ((current_cpu_data.cputype == CPU_R5432) && (i == 3))
i = 4;
mips_hpt_frequency = bus_frequency*(i+4)/4;
}
extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static void __init ddb_timer_setup(struct irqaction *irq)
{
#if defined(USE_CPU_COUNTER_TIMER)
/* we are using the cpu counter for timer interrupts */
setup_irq(CPU_IRQ_BASE + 7, irq);
#else
/* if we use Special purpose timer 1 */
ddb_out32(SP_TIMER_BASE, bus_frequency/HZ);
ddb_out32(SP_TIMER_BASE+4, 0x1);
setup_irq(SP_TIMER_IRQ, irq);
#endif
}
static void ddb5477_board_init(void);
extern struct pci_controller ddb5477_ext_controller;
extern struct pci_controller ddb5477_io_controller;
static int ddb5477_setup(void)
{
/* initialize board - we don't trust the loader */
ddb5477_board_init();
set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
board_time_init = ddb_time_init;
board_timer_setup = ddb_timer_setup;
_machine_restart = ddb_machine_restart;
_machine_halt = ddb_machine_halt;
_machine_power_off = ddb_machine_power_off;
/* setup resource limits */
ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1;
iomem_resource.end = 0xffffffff;
/* Reboot on panic */
panic_timeout = 180;
register_pci_controller (&ddb5477_ext_controller);
register_pci_controller (&ddb5477_io_controller);
return 0;
}
early_initcall(ddb5477_setup);
static void __init ddb5477_board_init(void)
{
/* ----------- setup PDARs ------------ */
/* SDRAM should have been set */
db_assert(ddb_in32(DDB_SDRAM0) ==
ddb_calc_pdar(DDB_SDRAM_BASE, board_ram_size, 32, 0, 1));
/* SDRAM1 should be turned off. What is this for anyway ? */
db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
/* Setup local bus. */
/* Flash U12 PDAR and timing. */
ddb_set_pdar(DDB_LCS0, DDB_LCS0_BASE, DDB_LCS0_SIZE, 16, 0, 0);
ddb_out32(DDB_LCST0, 0x00090842);
/* We need to setup LCS1 and LCS2 differently based on the
board_version */
if (mips_machtype == MACH_NEC_ROCKHOPPER) {
/* Flash U13 PDAR and timing. */
ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 16, 0, 0);
ddb_out32(DDB_LCST1, 0x00090842);
/* EPLD (NVRAM, switch, LCD, and mezzanie). */
ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 8, 0, 0);
} else {
/* misc */
ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 8, 0, 0);
/* mezzanie (?) */
ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 16, 0, 0);
}
/* verify VRC5477 base addr */
db_assert(ddb_in32(DDB_VRC5477) ==
ddb_calc_pdar(DDB_VRC5477_BASE, DDB_VRC5477_SIZE, 32, 0, 1));
/* verify BOOT ROM addr */
db_assert(ddb_in32(DDB_BOOTCS) ==
ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
/* setup PCI windows - window0 for MEM/config, window1 for IO */
ddb_set_pdar(DDB_PCIW0, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1);
ddb_set_pdar(DDB_PCIW1, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1);
ddb_set_pdar(DDB_IOPCIW0, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1);
ddb_set_pdar(DDB_IOPCIW1, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1);
/* ------------ reset PCI bus and BARs ----------------- */
ddb_pci_reset_bus();
ddb_out32(DDB_BARM010, 0x00000008);
ddb_out32(DDB_BARM011, 0x00000008);
ddb_out32(DDB_BARC0, 0xffffffff);
ddb_out32(DDB_BARM230, 0xffffffff);
ddb_out32(DDB_BAR00, 0xffffffff);
ddb_out32(DDB_BAR10, 0xffffffff);
ddb_out32(DDB_BAR20, 0xffffffff);
ddb_out32(DDB_BAR30, 0xffffffff);
ddb_out32(DDB_BAR40, 0xffffffff);
ddb_out32(DDB_BAR50, 0xffffffff);
ddb_out32(DDB_BARB0, 0xffffffff);
ddb_out32(DDB_BARC1, 0xffffffff);
ddb_out32(DDB_BARM231, 0xffffffff);
ddb_out32(DDB_BAR01, 0xffffffff);
ddb_out32(DDB_BAR11, 0xffffffff);
ddb_out32(DDB_BAR21, 0xffffffff);
ddb_out32(DDB_BAR31, 0xffffffff);
ddb_out32(DDB_BAR41, 0xffffffff);
ddb_out32(DDB_BAR51, 0xffffffff);
ddb_out32(DDB_BARB1, 0xffffffff);
/*
* We use pci master register 0 for memory space / config space
* And we use register 1 for IO space.
* Note that for memory space, we bump up the pci base address
* so that we have 1:1 mapping between PCI memory and cpu physical.
* For PCI IO space, it starts from 0 in PCI IO space but with
* DDB_xx_IO_BASE in CPU physical address space.
*/
ddb_set_pmr(DDB_PCIINIT00, DDB_PCICMD_MEM, DDB_PCI0_MEM_BASE,
DDB_PCI_ACCESS_32);
ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
ddb_set_pmr(DDB_PCIINIT01, DDB_PCICMD_MEM, DDB_PCI1_MEM_BASE,
DDB_PCI_ACCESS_32);
ddb_set_pmr(DDB_PCIINIT11, DDB_PCICMD_IO, DDB_PCI0_IO_SIZE,
DDB_PCI_ACCESS_32);
/* PCI cross window should be set properly */
ddb_set_pdar(DDB_BARP00, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1);
ddb_set_pdar(DDB_BARP10, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1);
ddb_set_pdar(DDB_BARP01, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1);
ddb_set_pdar(DDB_BARP11, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1);
if (mips_machtype == MACH_NEC_ROCKHOPPER
|| mips_machtype == MACH_NEC_ROCKHOPPERII) {
/* Disable bus diagnostics. */
ddb_out32(DDB_PCICTL0_L, 0);
ddb_out32(DDB_PCICTL0_H, 0);
ddb_out32(DDB_PCICTL1_L, 0);
ddb_out32(DDB_PCICTL1_H, 0);
}
if (mips_machtype == MACH_NEC_ROCKHOPPER) {
u16 vid;
struct pci_bus bus;
struct pci_dev dev_m1533;
extern struct pci_ops ddb5477_ext_pci_ops;
bus.parent = NULL; /* we scan the top level only */
bus.ops = &ddb5477_ext_pci_ops;
dev_m1533.bus = &bus;
dev_m1533.sysdata = NULL;
dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge.
pci_read_config_word(&dev_m1533, 0, &vid);
if (vid == PCI_VENDOR_ID_AL) {
printk("Changing mips_machtype to MACH_NEC_ROCKHOPPERII\n");
mips_machtype = MACH_NEC_ROCKHOPPERII;
}
}
/* enable USB input buffers */
ddb_out32(DDB_PIBMISC, 0x00000007);
/* For dual-function pins, make them all non-GPIO */
ddb_out32(DDB_GIUFUNSEL, 0x0);
// ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff); /* NEC recommanded value */
if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
/* enable IDE controller on Ali chip (south bridge) */
u8 temp8;
struct pci_bus bus;
struct pci_dev dev_m1533;
struct pci_dev dev_m5229;
extern struct pci_ops ddb5477_ext_pci_ops;
/* Setup M1535 registers */
bus.parent = NULL; /* we scan the top level only */
bus.ops = &ddb5477_ext_pci_ops;
dev_m1533.bus = &bus;
dev_m1533.sysdata = NULL;
dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge.
/* setup IDE controller
* enable IDE controller (bit 6 - 1)
* IDE IDSEL to be addr:A15 (bit 4:5 - 11)
* disable IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
* enable IDE ATA Primary Bus Signal Pad Control (bit 2 - 1)
*/
pci_write_config_byte(&dev_m1533, 0x58, 0x74);
/*
* positive decode (bit6 -0)
* enable IDE controler interrupt (bit 4 -1)
* setup SIRQ to point to IRQ 14 (bit 3:0 - 1101)
*/
pci_write_config_byte(&dev_m1533, 0x44, 0x1d);
/* Setup M5229 registers */
dev_m5229.bus = &bus;
dev_m5229.sysdata = NULL;
dev_m5229.devfn = 4*8; // slot 4 (AD15): M5229 IDE
/*
* enable IDE in the M5229 config register 0x50 (bit 0 - 1)
* M5229 IDSEL is addr:15; see above setting
*/
pci_read_config_byte(&dev_m5229, 0x50, &temp8);
pci_write_config_byte(&dev_m5229, 0x50, temp8 | 0x1);
/*
* enable bus master (bit 2) and IO decoding (bit 0)
*/
pci_read_config_byte(&dev_m5229, 0x04, &temp8);
pci_write_config_byte(&dev_m5229, 0x04, temp8 | 0x5);
/*
* enable native, copied from arch/ppc/k2boot/head.S
* TODO - need volatile, need to be portable
*/
pci_write_config_byte(&dev_m5229, 0x09, 0xef);
/* Set Primary Channel Command Block Timing */
pci_write_config_byte(&dev_m5229, 0x59, 0x31);
/*
* Enable primary channel 40-pin cable
* M5229 register 0x4a (bit 0)
*/
pci_read_config_byte(&dev_m5229, 0x4a, &temp8);
pci_write_config_byte(&dev_m5229, 0x4a, temp8 | 0x1);
}
if (mips_machtype == MACH_NEC_ROCKHOPPER
|| mips_machtype == MACH_NEC_ROCKHOPPERII) {
printk("lcd44780: initializing\n");
lcd44780_init();
lcd44780_puts("MontaVista Linux");
}
}