diff options
Diffstat (limited to 'arch/arm/mach-shark')
-rw-r--r-- | arch/arm/mach-shark/Makefile | 12 | ||||
-rw-r--r-- | arch/arm/mach-shark/Makefile.boot | 2 | ||||
-rw-r--r-- | arch/arm/mach-shark/core.c | 114 | ||||
-rw-r--r-- | arch/arm/mach-shark/dma.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-shark/irq.c | 109 | ||||
-rw-r--r-- | arch/arm/mach-shark/leds.c | 163 | ||||
-rw-r--r-- | arch/arm/mach-shark/pci.c | 42 |
7 files changed, 464 insertions, 0 deletions
diff --git a/arch/arm/mach-shark/Makefile b/arch/arm/mach-shark/Makefile new file mode 100644 index 00000000000..45be9b04e7b --- /dev/null +++ b/arch/arm/mach-shark/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := core.o dma.o irq.o pci.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_LEDS) += leds.o diff --git a/arch/arm/mach-shark/Makefile.boot b/arch/arm/mach-shark/Makefile.boot new file mode 100644 index 00000000000..4320f8b9277 --- /dev/null +++ b/arch/arm/mach-shark/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x08008000 + diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c new file mode 100644 index 00000000000..a9bc5d0dbd8 --- /dev/null +++ b/arch/arm/mach-shark/core.c @@ -0,0 +1,114 @@ +/* + * linux/arch/arm/mach-shark/arch.c + * + * Architecture specific stuff. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/serial_8250.h> + +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/io.h> +#include <asm/leds.h> +#include <asm/param.h> + +#include <asm/mach/map.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> + +static struct plat_serial8250_port serial_platform_data[] = { + { + .iobase = 0x3f8, + .irq = 4, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .iobase = 0x2f8, + .irq = 3, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +static int __init shark_init(void) +{ + int ret; + + if (machine_is_shark()) + ret = platform_device_register(&serial_device); + + return ret; +} + +arch_initcall(shark_init); + +extern void shark_init_irq(void); + +static struct map_desc shark_io_desc[] __initdata = { + { IO_BASE , IO_START , IO_SIZE , MT_DEVICE } +}; + +static void __init shark_map_io(void) +{ + iotable_init(shark_io_desc, ARRAY_SIZE(shark_io_desc)); +} + +#define IRQ_TIMER 0 +#define HZ_TIME ((1193180 + HZ/2) / HZ) + +static irqreturn_t +shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + write_seqlock(&xtime_lock); + timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; +} + +static struct irqaction shark_timer_irq = { + .name = "Shark Timer Tick", + .flags = SA_INTERRUPT, + .handler = shark_timer_interrupt +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +static void __init shark_timer_init(void) +{ + outb(0x34, 0x43); /* binary, mode 0, LSB/MSB, Ch 0 */ + outb(HZ_TIME & 0xff, 0x40); /* LSB of count */ + outb(HZ_TIME >> 8, 0x40); + + setup_irq(IRQ_TIMER, &shark_timer_irq); +} + +static struct sys_timer shark_timer = { + .init = shark_timer_init, +}; + +MACHINE_START(SHARK, "Shark") + MAINTAINER("Alexander Schulz") + BOOT_MEM(0x08000000, 0x40000000, 0xe0000000) + BOOT_PARAMS(0x08003000) + MAPIO(shark_map_io) + INITIRQ(shark_init_irq) + .timer = &shark_timer, +MACHINE_END diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c new file mode 100644 index 00000000000..835989a0291 --- /dev/null +++ b/arch/arm/mach-shark/dma.c @@ -0,0 +1,22 @@ +/* + * linux/arch/arm/mach-shark/dma.c + * + * by Alexander Schulz + * + * derived from: + * arch/arm/kernel/dma-ebsa285.c + * Copyright (C) 1998 Phil Blundell + */ + +#include <linux/config.h> +#include <linux/init.h> + +#include <asm/dma.h> +#include <asm/mach/dma.h> + +void __init arch_dma_init(dma_t *dma) +{ +#ifdef CONFIG_ISA_DMA + isa_init_dma(dma); +#endif +} diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c new file mode 100644 index 00000000000..6cb67bd3dfd --- /dev/null +++ b/arch/arm/mach-shark/irq.c @@ -0,0 +1,109 @@ +/* + * linux/arch/arm/mach-shark/irq.c + * + * by Alexander Schulz + * + * derived from linux/arch/ppc/kernel/i8259.c and: + * include/asm-arm/arch-ebsa110/irq.h + * Copyright (C) 1996-1998 Russell King + */ + +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/ptrace.h> +#include <linux/interrupt.h> + +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/mach/irq.h> + +/* + * 8259A PIC functions to handle ISA devices: + */ + +/* + * This contains the irq mask for both 8259A irq controllers, + * Let through the cascade-interrupt no. 2 (ff-(1<<2)==fb) + */ +static unsigned char cached_irq_mask[2] = { 0xfb, 0xff }; + +/* + * These have to be protected by the irq controller spinlock + * before being called. + */ +static void shark_disable_8259A_irq(unsigned int irq) +{ + unsigned int mask; + if (irq<8) { + mask = 1 << irq; + cached_irq_mask[0] |= mask; + outb(cached_irq_mask[1],0xA1); + } else { + mask = 1 << (irq-8); + cached_irq_mask[1] |= mask; + outb(cached_irq_mask[0],0x21); + } +} + +static void shark_enable_8259A_irq(unsigned int irq) +{ + unsigned int mask; + if (irq<8) { + mask = ~(1 << irq); + cached_irq_mask[0] &= mask; + outb(cached_irq_mask[0],0x21); + } else { + mask = ~(1 << (irq-8)); + cached_irq_mask[1] &= mask; + outb(cached_irq_mask[1],0xA1); + } +} + +static void shark_ack_8259A_irq(unsigned int irq){} + +static irqreturn_t bogus_int(int irq, void *dev_id, struct pt_regs *regs) +{ + printk("Got interrupt %i!\n",irq); + return IRQ_NONE; +} + +static struct irqaction cascade; + +static struct irqchip fb_chip = { + .ack = shark_ack_8259A_irq, + .mask = shark_disable_8259A_irq, + .unmask = shark_enable_8259A_irq, +}; + +void __init shark_init_irq(void) +{ + int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + set_irq_chip(irq, &fb_chip); + set_irq_handler(irq, do_edge_IRQ); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + /* init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence, edge triggered (level: 0x19)*/ + outb(0x00, 0x21); /* Vector base */ + outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */ + outb(0x03, 0x21); /* Select 8086 mode , auto eoi*/ + outb(0x0A, 0x20); + /* init slave interrupt controller */ + outb(0x11, 0xA0); /* Start init sequence, edge triggered */ + outb(0x08, 0xA1); /* Vector base */ + outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */ + outb(0x03, 0xA1); /* Select 8086 mode, auto eoi */ + outb(0x0A, 0xA0); + outb(cached_irq_mask[1],0xA1); + outb(cached_irq_mask[0],0x21); + //request_region(0x20,0x2,"pic1"); + //request_region(0xA0,0x2,"pic2"); + + cascade.handler = bogus_int; + cascade.name = "cascade"; + setup_irq(2,&cascade); +} + diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c new file mode 100644 index 00000000000..7bdeb70a0c1 --- /dev/null +++ b/arch/arm/mach-shark/leds.c @@ -0,0 +1,163 @@ +/* + * arch/arm/kernel/leds-shark.c + * by Alexander Schulz + * + * derived from: + * arch/arm/kernel/leds-footbridge.c + * Copyright (C) 1998-1999 Russell King + * + * DIGITAL Shark LED control routines. + * + * The leds use is as follows: + * - Green front - toggles state every 50 timer interrupts + * - Amber front - Unused, this is a dual color led (Amber/Green) + * - Amber back - On if system is not idle + * + * Changelog: + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/ioport.h> + +#include <asm/hardware.h> +#include <asm/leds.h> +#include <asm/io.h> +#include <asm/system.h> + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 +static char led_state; +static short hw_led_state; +static short saved_state; + +static DEFINE_SPINLOCK(leds_lock); + +short sequoia_read(int addr) { + outw(addr,0x24); + return inw(0x26); +} + +void sequoia_write(short value,short addr) { + outw(addr,0x24); + outw(value,0x26); +} + +static void sequoia_leds_event(led_event_t evt) +{ + unsigned long flags; + + spin_lock_irqsave(&leds_lock, flags); + + hw_led_state = sequoia_read(0x09); + + switch (evt) { + case led_start: + hw_led_state |= SEQUOIA_LED_GREEN; + hw_led_state |= SEQUOIA_LED_AMBER; +#ifdef CONFIG_LEDS_CPU + hw_led_state |= SEQUOIA_LED_BACK; +#else + hw_led_state &= ~SEQUOIA_LED_BACK; +#endif + led_state |= LED_STATE_ENABLED; + break; + + case led_stop: + hw_led_state &= ~SEQUOIA_LED_BACK; + hw_led_state |= SEQUOIA_LED_GREEN; + hw_led_state |= SEQUOIA_LED_AMBER; + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + saved_state = hw_led_state; + hw_led_state &= ~SEQUOIA_LED_BACK; + hw_led_state |= SEQUOIA_LED_GREEN; + hw_led_state |= SEQUOIA_LED_AMBER; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = saved_state; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= SEQUOIA_LED_GREEN; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~SEQUOIA_LED_BACK; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= SEQUOIA_LED_BACK; + break; +#endif + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~SEQUOIA_LED_GREEN; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= SEQUOIA_LED_GREEN; + break; + + case led_amber_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~SEQUOIA_LED_AMBER; + break; + + case led_amber_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= SEQUOIA_LED_AMBER; + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= SEQUOIA_LED_BACK; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~SEQUOIA_LED_BACK; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + sequoia_write(hw_led_state,0x09); + + spin_unlock_irqrestore(&leds_lock, flags); +} + +static int __init leds_init(void) +{ + extern void (*leds_event)(led_event_t); + short temp; + + leds_event = sequoia_leds_event; + + /* Make LEDs independent of power-state */ + request_region(0x24,4,"sequoia"); + temp = sequoia_read(0x09); + temp |= 1<<10; + sequoia_write(temp,0x09); + leds_event(led_start); + return 0; +} + +__initcall(leds_init); diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c new file mode 100644 index 00000000000..37a7112d411 --- /dev/null +++ b/arch/arm/mach-shark/pci.c @@ -0,0 +1,42 @@ +/* + * linux/arch/arm/mach-shark/pci.c + * + * PCI bios-type initialisation for PCI machines + * + * Bits taken from various places. + */ +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/init.h> + +#include <asm/irq.h> +#include <asm/mach/pci.h> +#include <asm/mach-types.h> + +static int __init shark_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (dev->bus->number == 0) + if (dev->devfn == 0) return 255; + else return 11; + else return 255; +} + +extern void __init via82c505_preinit(void); + +static struct hw_pci shark_pci __initdata = { + .setup = via82c505_setup, + .swizzle = pci_std_swizzle, + .map_irq = shark_map_irq, + .nr_controllers = 1, + .scan = via82c505_scan_bus, + .preinit = via82c505_preinit, +}; + +static int __init shark_pci_init(void) +{ + if (machine_is_shark()) + pci_common_init(&shark_pci); + return 0; +} + +subsys_initcall(shark_pci_init); |