diff options
Diffstat (limited to 'arch/sh/boards/harp')
-rw-r--r-- | arch/sh/boards/harp/Makefile | 8 | ||||
-rw-r--r-- | arch/sh/boards/harp/irq.c | 148 | ||||
-rw-r--r-- | arch/sh/boards/harp/led.c | 52 | ||||
-rw-r--r-- | arch/sh/boards/harp/mach.c | 62 | ||||
-rw-r--r-- | arch/sh/boards/harp/pcidma.c | 42 | ||||
-rw-r--r-- | arch/sh/boards/harp/setup.c | 91 |
6 files changed, 403 insertions, 0 deletions
diff --git a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile new file mode 100644 index 00000000000..eb753d31812 --- /dev/null +++ b/arch/sh/boards/harp/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for STMicroelectronics board specific parts of the kernel +# + +obj-y := irq.o setup.o mach.o led.o + +obj-$(CONFIG_PCI) += pcidma.o + diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c new file mode 100644 index 00000000000..acd58489970 --- /dev/null +++ b/arch/sh/boards/harp/irq.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Looks after interrupts on the HARP board. + * + * Bases on the IPR irq system + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/harp/harp.h> + + +#define NUM_EXTERNAL_IRQS 16 + +// Early versions of the STB1 Overdrive required this nasty frig +//#define INVERT_INTMASK_WRITES + +static void enable_harp_irq(unsigned int irq); +static void disable_harp_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_harp_irq disable_harp_irq + +static void mask_and_ack_harp(unsigned int); +static void end_harp_irq(unsigned int irq); + +static unsigned int startup_harp_irq(unsigned int irq) +{ + enable_harp_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type harp_irq_type = { + "Harp-IRQ", + startup_harp_irq, + shutdown_harp_irq, + enable_harp_irq, + disable_harp_irq, + mask_and_ack_harp, + end_harp_irq +}; + +static void disable_harp_irq(unsigned int irq) +{ + unsigned val, flags; + unsigned maskReg; + unsigned mask; + int pri; + + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + pri = 15 - irq; + + if (pri < 8) { + maskReg = EPLD_INTMASK0; + } else { + maskReg = EPLD_INTMASK1; + pri -= 8; + } + + local_irq_save(flags); + mask = ctrl_inl(maskReg); + mask &= (~(1 << pri)); +#if defined(INVERT_INTMASK_WRITES) + mask ^= 0xff; +#endif + ctrl_outl(mask, maskReg); + local_irq_restore(flags); +} + +static void enable_harp_irq(unsigned int irq) +{ + unsigned flags; + unsigned maskReg; + unsigned mask; + int pri; + + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + pri = 15 - irq; + + if (pri < 8) { + maskReg = EPLD_INTMASK0; + } else { + maskReg = EPLD_INTMASK1; + pri -= 8; + } + + local_irq_save(flags); + mask = ctrl_inl(maskReg); + + + mask |= (1 << pri); + +#if defined(INVERT_INTMASK_WRITES) + mask ^= 0xff; +#endif + ctrl_outl(mask, maskReg); + + local_irq_restore(flags); +} + +/* This functions sets the desired irq handler to be an overdrive type */ +static void __init make_harp_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &harp_irq_type; + disable_harp_irq(irq); +} + +static void mask_and_ack_harp(unsigned int irq) +{ + disable_harp_irq(irq); +} + +static void end_harp_irq(unsigned int irq) +{ + enable_harp_irq(irq); +} + +void __init init_harp_irq(void) +{ + int i; + +#if !defined(INVERT_INTMASK_WRITES) + // On the harp these are set to enable an interrupt + ctrl_outl(0x00, EPLD_INTMASK0); + ctrl_outl(0x00, EPLD_INTMASK1); +#else + // On the Overdrive the data is inverted before being stored in the reg + ctrl_outl(0xff, EPLD_INTMASK0); + ctrl_outl(0xff, EPLD_INTMASK1); +#endif + + for (i = 0; i < NUM_EXTERNAL_IRQS; i++) { + make_harp_irq(i); + } +} diff --git a/arch/sh/boards/harp/led.c b/arch/sh/boards/harp/led.c new file mode 100644 index 00000000000..76ca4ccac70 --- /dev/null +++ b/arch/sh/boards/harp/led.c @@ -0,0 +1,52 @@ +/* + * linux/arch/sh/stboards/led.c + * + * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com> + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains ST40STB1 HARP and compatible code. + */ + +#include <linux/config.h> +#include <asm/io.h> +#include <asm/harp/harp.h> + +/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */ +/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */ +/* Works for HARP and overdrive */ +static void mach_led(int position, int value) +{ + if (value) { + ctrl_outl(EPLD_LED_ON, EPLD_LED); + } else { + ctrl_outl(EPLD_LED_OFF, EPLD_LED); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include <linux/sched.h> + +/* acts like an actual heart beat -- ie thump-thump-pause... */ +void heartbeat_harp(void) +{ + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_led( -1, 1); + else if (cnt == 7 || cnt == dist+7) + mach_led( -1, 0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30; + dist = period / 4; + } +} +#endif diff --git a/arch/sh/boards/harp/mach.c b/arch/sh/boards/harp/mach.c new file mode 100644 index 00000000000..a946dd1674c --- /dev/null +++ b/arch/sh/boards/harp/mach.c @@ -0,0 +1,62 @@ +/* + * linux/arch/sh/boards/harp/mach.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the STMicroelectronics STB1 HARP and compatible boards + */ + +#include <linux/init.h> + +#include <asm/machvec.h> +#include <asm/rtc.h> +#include <asm/machvec_init.h> +#include <asm/hd64465/io.h> +#include <asm/hd64465/hd64465.h> + +void setup_harp(void); +void init_harp_irq(void); +void heartbeat_harp(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_harp __initmv = { + .mv_nr_irqs = 89 + HD64465_IRQ_NUM, + + .mv_inb = hd64465_inb, + .mv_inw = hd64465_inw, + .mv_inl = hd64465_inl, + .mv_outb = hd64465_outb, + .mv_outw = hd64465_outw, + .mv_outl = hd64465_outl, + + .mv_inb_p = hd64465_inb_p, + .mv_inw_p = hd64465_inw, + .mv_inl_p = hd64465_inl, + .mv_outb_p = hd64465_outb_p, + .mv_outw_p = hd64465_outw, + .mv_outl_p = hd64465_outl, + + .mv_insb = hd64465_insb, + .mv_insw = hd64465_insw, + .mv_insl = hd64465_insl, + .mv_outsb = hd64465_outsb, + .mv_outsw = hd64465_outsw, + .mv_outsl = hd64465_outsl, + + .mv_isa_port2addr = hd64465_isa_port2addr, + +#ifdef CONFIG_PCI + .mv_init_irq = init_harp_irq, +#endif +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_harp, +#endif +}; + +ALIAS_MV(harp) diff --git a/arch/sh/boards/harp/pcidma.c b/arch/sh/boards/harp/pcidma.c new file mode 100644 index 00000000000..475311390fd --- /dev/null +++ b/arch/sh/boards/harp/pcidma.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Dynamic DMA mapping support. + */ + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/pci.h> +#include <asm/io.h> +#include <asm/addrspace.h> + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + /* Is it neccessary to do the memset? */ + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + /* We must flush the cache before we pass it on to the device */ + flush_cache_all(); + return P2SEGADDR(ret); +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); + + free_pages(p1addr, get_order(size)); +} diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c new file mode 100644 index 00000000000..05b01b8f40a --- /dev/null +++ b/arch/sh/boards/harp/setup.c @@ -0,0 +1,91 @@ +/* + * arch/sh/stboard/setup.c + * + * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * STMicroelectronics ST40STB1 HARP and compatible support. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <asm/io.h> +#include <asm/harp/harp.h> + +const char *get_system_type(void) +{ + return "STB1 Harp"; +} + +/* + * Initialize the board + */ +int __init platform_setup(void) +{ +#ifdef CONFIG_SH_STB1_HARP + unsigned long ic8_version, ic36_version; + + ic8_version = ctrl_inl(EPLD_REVID2); + ic36_version = ctrl_inl(EPLD_REVID1); + + printk("STMicroelectronics STB1 HARP initialisaton\n"); + printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n", + (ic8_version >> 4) & 0xf, ic8_version & 0xf, + (ic36_version >> 4) & 0xf, ic36_version & 0xf); +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + unsigned long version; + + version = ctrl_inl(EPLD_REVID); + + printk("STMicroelectronics STB1 Overdrive initialisaton\n"); + printk("EPLD version: %d.%02d\n", + (version >> 4) & 0xf, version & 0xf); +#else +#error Undefined machine +#endif + + /* Currently all STB1 chips have problems with the sleep instruction, + * so disable it here. + */ + disable_hlt(); + + return 0; +} + +/* + * pcibios_map_platform_irq + * + * This is board specific and returns the IRQ for a given PCI device. + * It is used by the PCI code (arch/sh/kernel/st40_pci*) + * + */ + +#define HARP_PCI_IRQ 1 +#define HARP_BRIDGE_IRQ 2 +#define OVERDRIVE_SLOT0_IRQ 0 + + +int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + switch (slot) { +#ifdef CONFIG_SH_STB1_HARP + case 2: /*This is the PCI slot on the */ + return HARP_PCI_IRQ; + case 1: /* this is the bridge */ + return HARP_BRIDGE_IRQ; +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + case 1: + case 2: + case 3: + return slot - 1; +#else +#error Unknown board +#endif + default: + return -1; + } +} + |