Commit 17017b3a authored by Ralf Bächle's avatar Ralf Bächle Committed by Linus Torvalds

[PATCH] Update Cobalt support

This adds back support for the MIPS-based Cobalt Raq 1/2 and Qube 1/2
systems.
parent 60409e5c
#
# Makefile for the Cobalt micro systems family specific parts of the kernel
#
obj-y := irq.o int-handler.o reset.o setup.o via.o promcon.o
EXTRA_AFLAGS := $(CFLAGS)
/*
* Cobalt interrupt handler
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1995, 1996, 1997 by Ralf Baechle
* Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/cobalt/cobalt.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* cobalt_handle_int: Interrupt handler for Cobalt boards
*/
.text
.set noreorder
.set noat
.align 5
NESTED(cobalt_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
/*
* Get pending Interrupts
*/
mfc0 s0,CP0_CAUSE # get raw irq status
mfc0 a0,CP0_STATUS # get irq mask
and s0,s0,a0 # compute masked irq status
andi a0,s0,CAUSEF_IP2 /* Check for Galileo timer */
beq a0,zero,1f
andi a0,s0,CAUSEF_IP6 /* Check for Via chip */
/* Galileo interrupt */
jal galileo_irq
move a0,sp
j ret_from_irq
nop
1:
beq a0,zero,1f /* Check IP6 */
andi a0,s0,CAUSEF_IP3
/* Via interrupt */
jal via_irq
move a0,sp
j ret_from_irq
nop
1:
beq a0,zero,1f /* Check IP3 */
andi a0,s0,CAUSEF_IP4
/* Ethernet 0 interrupt */
li a0,COBALT_ETH0_IRQ
jal do_IRQ
move a1,sp
j ret_from_irq
nop
1:
beq a0,zero,1f /* Check IP4 */
andi a0,s0,CAUSEF_IP5
/* Ethernet 1 interrupt */
li a0,COBALT_ETH1_IRQ
jal do_IRQ
move a1,sp
j ret_from_irq
nop
1:
beq a0,zero,1f /* Check IP5 */
andi a0,s0,CAUSEF_IP7
/* Serial interrupt */
li a0,COBALT_SERIAL_IRQ
jal do_IRQ
move a1,sp
j ret_from_irq
nop
1:
beq a0,zero,1f /* Check IP7 */
nop
/* PCI interrupt */
li a0,COBALT_QUBE_SLOT_IRQ
jal do_IRQ
move a1,sp
1:
j ret_from_irq
nop
END(cobalt_handle_int)
/*
* IRQ vector handles
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1995, 1996, 1997 by Ralf Baechle
* Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/bootinfo.h>
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/cobalt/cobalt.h>
/* Cobalt Exception handler */
extern void cobalt_handle_int(void);
/* Via masking routines */
extern void unmask_irq(unsigned int irqr);
extern void mask_irq(unsigned int irq);
/*
* We have two types of interrupts that we handle, ones that come
* in through the CPU interrupt lines, and ones that come in on
* the via chip. The CPU mappings are:
* 0,1 - S/W (ignored)
* 2 - Galileo chip (timer)
* 3 - Tulip 0 + NCR SCSI
* 4 - Tulip 1
* 5 - 16550 UART
* 6 - VIA southbridge PIC
* 7 - unused
*
* The VIA chip is a master/slave 8259 setup and has the
* following interrupts
* 8 - RTC
* 9 - PCI
* 14 - IDE0
* 15 - IDE1
*
* In the table we use a 1 to indicate that we use a VIA interrupt
* line, and IE_IRQx to indicate that we use a CPU interrupt line
*
* We map all of these onto linux IRQ #s 0-15 and forget the rest
*/
#define NOINT_LINE 0
#define CPUINT_LINE(x) IE_IRQ##x
#define VIAINT_LINE 1
#define COBALT_IRQS 16
static unsigned short irqnr_to_type[COBALT_IRQS] =
{ CPUINT_LINE(0), NOINT_LINE, VIAINT_LINE, NOINT_LINE,
CPUINT_LINE(1), NOINT_LINE, NOINT_LINE, CPUINT_LINE(3),
VIAINT_LINE, VIAINT_LINE, NOINT_LINE, NOINT_LINE,
NOINT_LINE, CPUINT_LINE(2), VIAINT_LINE, VIAINT_LINE };
/*
* Cobalt CPU irq
*/
static void enable_cpu_irq(unsigned int irq)
{
unsigned long flags;
local_irq_save(flags);
change_c0_status(irqnr_to_type[irq], irqnr_to_type[irq]);
local_irq_restore(flags);
}
static unsigned startup_cpu_irq(unsigned int irq)
{
enable_cpu_irq(irq);
return 0;
}
static void disable_cpu_irq(unsigned int irq)
{
unsigned long flags;
local_irq_save(flags);
change_c0_status(irqnr_to_type[irq], ~(irqnr_to_type[irq]));
local_irq_restore(flags);
}
#define shutdown_cpu_irq disable_cpu_irq
#define mask_and_ack_cpu_irq disable_cpu_irq
static void end_cpu_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_cpu_irq(irq);
}
static struct hw_interrupt_type cobalt_cpu_irq_type = {
"Cobalt CPU",
startup_cpu_irq,
shutdown_cpu_irq,
enable_cpu_irq,
disable_cpu_irq,
mask_and_ack_cpu_irq,
end_cpu_irq,
NULL
};
void __init init_IRQ(void)
{
int i;
/* Initialise all of the IRQ descriptors */
init_i8259_irqs();
/* Map the irqnr to the type int we have */
for (i=0; i < COBALT_IRQS; i++) {
if (irqnr_to_type[i] >= CPUINT_LINE(0))
/* cobalt_cpu_irq_type */
irq_desc[i].handler = &cobalt_cpu_irq_type;
}
/* Mask all cpu interrupts
(except IE4, we already masked those at VIA level) */
clear_c0_status(ST0_IM);
set_c0_status(IE_IRQ4);
cli();
set_except_vector(0, cobalt_handle_int);
}
/*
* PROM console for Cobalt Raq2
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1995, 1996, 1997 by Ralf Baechle
* Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
*
*/
#include <linux/init.h>
#include <linux/console.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
#include <linux/serial_reg.h>
#include <asm/delay.h>
#include <asm/serial.h>
#include <asm/io.h>
static unsigned long port = 0xc800000;
static __inline__ void ns16550_cons_put_char(char ch, unsigned long ioaddr)
{
char lsr;
do {
lsr = inb(ioaddr + UART_LSR);
} while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
outb(ch, ioaddr + UART_TX);
}
static __inline__ char ns16550_cons_get_char(unsigned long ioaddr)
{
while ((inb(ioaddr + UART_LSR) & UART_LSR_DR) == 0)
udelay(1);
return inb(ioaddr + UART_RX);
}
void ns16550_console_write(struct console *co, const char *s, unsigned count)
{
char lsr, ier;
unsigned i;
ier = inb(port + UART_IER);
outb(0x00, port + UART_IER);
for (i=0; i < count; i++, s++) {
if(*s == '\n')
ns16550_cons_put_char('\r', port);
ns16550_cons_put_char(*s, port);
}
do {
lsr = inb(port + UART_LSR);
} while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
outb(ier, port + UART_IER);
}
char getDebugChar(void)
{
return ns16550_cons_get_char(port);
}
void putDebugChar(char kgdb_char)
{
ns16550_cons_put_char(kgdb_char, port);
}
static kdev_t
ns16550_console_dev(struct console *c)
{
return mk_kdev(TTY_MAJOR, 64 + c->index);
}
static struct console ns16550_console = {
.name = "prom",
.setup = NULL,
.write = ns16550_console_write,
.device = ns16550_console_dev,
.flags = CON_PRINTBUFFER,
.index = -1,
};
void __init ns16550_setup_console(void)
{
register_console(&ns16550_console);
}
/*
* Cobalt Reset operations
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1995, 1996, 1997 by Ralf Baechle
* Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <asm/mipsregs.h>
void cobalt_machine_restart(char *command)
{
*(volatile char *)0xbc000000 = 0x0f;
/*
* Ouch, we're still alive ... This time we take the silver bullet ...
* ... and find that we leave the hardware in a state in which the
* kernel in the flush locks up somewhen during of after the PCI
* detection stuff.
*/
set_c0_status(ST0_BEV | ST0_ERL);
change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
flush_cache_all();
write_c0_wired(0);
__asm__ __volatile__(
"jr\t%0"
:
: "r" (0xbfc00000));
}
extern int led_state;
#define kLED 0xBC000000
#define LEDSet(x) (*(volatile unsigned char *) kLED) = (( unsigned char)x)
void cobalt_machine_halt(void)
{
int mark;
/* Blink our cute? little LED (number 3)... */
while (1) {
led_state = led_state | ( 1 << 3 );
LEDSet(led_state);
mark = jiffies;
while (jiffies<(mark+HZ));
led_state = led_state & ~( 1 << 3 );
LEDSet(led_state);
mark = jiffies;
while (jiffies<(mark+HZ));
}
}
/*
* This triggers the luser mode device driver for the power switch ;-)
*/
void cobalt_machine_power_off(void)
{
printk("You can switch the machine off now.\n");
cobalt_machine_halt();
}
/*
* Setup pointers to hardware dependent routines.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1996, 1997 by Ralf Baechle
* Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
*
*/
#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/mc146818rtc.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/gt64120.h>
#include <asm/cobalt/cobalt.h>
extern void cobalt_machine_restart(char *command);
extern void cobalt_machine_halt(void);
extern void cobalt_machine_power_off(void);
extern struct rtc_ops std_rtc_ops;
extern struct ide_ops std_ide_ops;
char arcs_cmdline[CL_SIZE] = {
"console=ttyS0,115200 "
#ifdef CONFIG_IP_PNP
"ip=on "
#endif
#ifdef CONFIG_ROOT_NFS
"root=/dev/nfs "
#else
"root=/dev/hda1 "
#endif
};
const char *get_system_type(void)
{
return "MIPS Cobalt";
}
static void __init cobalt_time_init(void)
{
rtc_ops = &std_rtc_ops;
}
static void __init cobalt_timer_setup(struct irqaction *irq)
{
/* Load timer value for 150 Hz */
GALILEO_OUTL(500000, GT_TC0_OFS);
/* Register our timer interrupt */
setup_irq(COBALT_TIMER_IRQ, irq);
/* Enable timer ints */
GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS);
/* Unmask timer int */
GALILEO_OUTL(0x100, GT_INTRMASK_OFS);
}
void __init cobalt_setup(void)
{
_machine_restart = cobalt_machine_restart;
_machine_halt = cobalt_machine_halt;
_machine_power_off = cobalt_machine_power_off;
board_time_init = cobalt_time_init;
board_timer_setup = cobalt_timer_setup;
#ifdef CONFIG_BLK_DEV_IDE
ide_ops = &std_ide_ops;
#endif
set_io_port_base(KSEG1ADDR(0x10000000));
/*
* This is a prom style console. We just poke at the
* UART to make it talk.
* Only use this console if you really screw up and can't
* get to the stage of setting up a real serial console.
*/
/*ns16550_setup_console();*/
}
/* Prom init. We read our one and only communication with the
firmware. Grab the amount of installed memory */
void __init prom_init(int argc)
{
mips_machgroup = MACH_GROUP_COBALT;
add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
{
/* Nothing to do! */
}
/*
* VIA chipset irq handling
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1996, 1997 by Ralf Baechle
* Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
*
*/
#include <linux/irq.h>
#include <linux/kernel.h>
#include <asm/gt64120.h>
#include <asm/ptrace.h>
#include <asm/io.h>
#include <asm/cobalt/cobalt.h>
asmlinkage void via_irq(struct pt_regs *regs)
{
char mstat, sstat;
/* Read Master Status */
outb(0x0C, 0x20);
mstat = inb(0x20);
if (mstat < 0) {
mstat &= 0x7f;
if (mstat != 2) {
do_IRQ(mstat, regs);
outb(mstat | 0x20, 0x20);
} else {
sstat = inb(0xA0);
/* Slave interrupt */
outb(0x0C, 0xA0);
sstat = inb(0xA0);
if (sstat < 0) {
do_IRQ((sstat + 8) & 0x7f, regs);
outb(0x22, 0x20);
outb((sstat & 0x7f) | 0x20, 0xA0);
} else {
printk("Spurious slave interrupt...\n");
}
}
} else
printk("Spurious master interrupt...");
}
asmlinkage void galileo_irq(struct pt_regs *regs)
{
unsigned long irq_src;
irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
/* Check for timer irq ... */
if (irq_src & GALILEO_T0EXP) {
/* Clear the int line */
GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
do_IRQ(COBALT_TIMER_IRQ, regs);
} else
printk("Spurious Galileo interrupt...\n");
}
This diff is collapsed.
This diff is collapsed.
/*
* Lowlevel hardware stuff for the MIPS based Cobalt microservers.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1997 Cobalt Microserver
* Copyright (C) 1997 Ralf Baechle
* Copyright (C) 2001, 2002, 2003 Liam Davies (ldavies@agile.tv)
*
*/
#ifndef __ASM_MIPS_COBALT_H
#define __ASM_MIPS_COBALT_H
/*
* COBALT interrupt enable bits
*/
#define COBALT_IE_PCI (1 << 0)
#define COBALT_IE_FLOPPY (1 << 1)
#define COBALT_IE_KEYBOARD (1 << 2)
#define COBALT_IE_SERIAL1 (1 << 3)
#define COBALT_IE_SERIAL2 (1 << 4)
#define COBALT_IE_PARALLEL (1 << 5)
#define COBALT_IE_GPIO (1 << 6)
#define COBALT_IE_RTC (1 << 7)
/*
* PCI defines
*/
#define COBALT_IE_ETHERNET (1 << 7)
#define COBALT_IE_SCSI (1 << 7)
/*
* COBALT Interrupt Level definitions.
* These should match the request IRQ id's.
*/
#define COBALT_TIMER_IRQ 0
#define COBALT_KEYBOARD_IRQ 1
#define COBALT_QUBE_SLOT_IRQ 9
#define COBALT_ETH0_IRQ 4
#define COBALT_ETH1_IRQ 13
#define COBALT_SCC_IRQ 4
#define COBALT_SERIAL2_IRQ 4
#define COBALT_PARALLEL_IRQ 5
#define COBALT_FLOPPY_IRQ 6 /* needs to be consistent with floppy driver! */
#define COBALT_SCSI_IRQ 7
#define COBALT_SERIAL_IRQ 7
#define COBALT_RAQ_SCSI_IRQ 4
/*
* PCI configuration space manifest constants. These are wired into
* the board layout according to the PCI spec to enable the software
* to probe the hardware configuration space in a well defined manner.
*
* The PCI_DEVSHFT() macro transforms these values into numbers
* suitable for passing as the dev parameter to the various
* pcibios_read/write_config routines.
*/
#define COBALT_PCICONF_CPU 0x06
#define COBALT_PCICONF_ETH0 0x07
#define COBALT_PCICONF_RAQSCSI 0x08
#define COBALT_PCICONF_VIA 0x09
#define COBALT_PCICONF_PCISLOT 0x0A
#define COBALT_PCICONF_ETH1 0x0C
/*
* The Cobalt board id information. The boards have an ID number wired
* into the VIA that is available in the high nibble of register 94.
* This register is available in the VIA configuration space through the
* interface routines qube_pcibios_read/write_config. See cobalt/pci.c
*/
#define VIA_COBALT_BRD_ID_REG 0x94
#define VIA_COBALT_BRD_REG_to_ID(reg) ((unsigned char) (reg) >> 4)
#define COBALT_BRD_ID_QUBE1 0x3
#define COBALT_BRD_ID_RAQ1 0x4
#define COBALT_BRD_ID_QUBE2 0x5
#define COBALT_BRD_ID_RAQ2 0x6
/*
* Galileo chipset access macros for the Cobalt. The base address for
* the GT64111 chip is 0x14000000
*/
#define GT64111_BASE 0x04000000
#define GALILEO_REG(ofs) (GT64111_BASE + (ofs))
#define GALILEO_INL(port) (inl(GALILEO_REG(port)))
#define GALILEO_OUTL(val, port) outl(val, GALILEO_REG(port))
#define GALILEO_T0EXP 0x0100
#define GALILEO_ENTC0 0x01
#define GALILEO_SELTC0 0x02
#endif /* __ASM_MIPS_COBALT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment