diff options
Diffstat (limited to 'arch/sh/boards/adx')
-rw-r--r-- | arch/sh/boards/adx/Makefile | 6 | ||||
-rw-r--r-- | arch/sh/boards/adx/irq.c | 31 | ||||
-rw-r--r-- | arch/sh/boards/adx/irq_maskreg.c | 107 | ||||
-rw-r--r-- | arch/sh/boards/adx/setup.c | 56 |
4 files changed, 200 insertions, 0 deletions
diff --git a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile new file mode 100644 index 00000000000..5b1c531b399 --- /dev/null +++ b/arch/sh/boards/adx/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for ADX boards +# + +obj-y := setup.o irq.o irq_maskreq.o + diff --git a/arch/sh/boards/adx/irq.c b/arch/sh/boards/adx/irq.c new file mode 100644 index 00000000000..c6ca409dff9 --- /dev/null +++ b/arch/sh/boards/adx/irq.c @@ -0,0 +1,31 @@ +/* + * linux/arch/sh/boards/adx/irq.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * 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. + * + */ + +#include <asm/irq.h> + +void init_adx_IRQ(void) +{ + int i; + +/* printk("init_adx_IRQ()\n");*/ + /* setup irq_mask_register */ + irq_mask_register = (unsigned short *)0xa6000008; + + /* cover all external interrupt area by maskreg_irq_type + * (Actually, irq15 doesn't exist) + */ + for (i = 0; i < 16; i++) { + make_maskreg_irq(i); + disable_irq(i); + } +} diff --git a/arch/sh/boards/adx/irq_maskreg.c b/arch/sh/boards/adx/irq_maskreg.c new file mode 100644 index 00000000000..ca91bb0f1f5 --- /dev/null +++ b/arch/sh/boards/adx/irq_maskreg.c @@ -0,0 +1,107 @@ +/* + * linux/arch/sh/kernel/irq_maskreg.c + * + * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp> + * + * This file may be copied or modified under the terms of the GNU + * General Public License. See linux/COPYING for more information. + * + * Interrupt handling for Simple external interrupt mask register + * + * This is for the machine which have single 16 bit register + * for masking external IRQ individually. + * Each bit of the register is for masking each interrupt. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/machvec.h> + +/* address of external interrupt mask register + * address must be set prior to use these (maybe in init_XXX_irq()) + * XXX : is it better to use .config than specifying it in code? */ +unsigned short *irq_mask_register = 0; + +/* forward declaration */ +static unsigned int startup_maskreg_irq(unsigned int irq); +static void shutdown_maskreg_irq(unsigned int irq); +static void enable_maskreg_irq(unsigned int irq); +static void disable_maskreg_irq(unsigned int irq); +static void mask_and_ack_maskreg(unsigned int); +static void end_maskreg_irq(unsigned int irq); + +/* hw_interrupt_type */ +static struct hw_interrupt_type maskreg_irq_type = { + " Mask Register", + startup_maskreg_irq, + shutdown_maskreg_irq, + enable_maskreg_irq, + disable_maskreg_irq, + mask_and_ack_maskreg, + end_maskreg_irq +}; + +/* actual implementatin */ +static unsigned int startup_maskreg_irq(unsigned int irq) +{ + enable_maskreg_irq(irq); + return 0; /* never anything pending */ +} + +static void shutdown_maskreg_irq(unsigned int irq) +{ + disable_maskreg_irq(irq); +} + +static void disable_maskreg_irq(unsigned int irq) +{ + if (irq_mask_register) { + unsigned long flags; + unsigned short val, mask = 0x01 << irq; + + /* Set "irq"th bit */ + local_irq_save(flags); + val = ctrl_inw((unsigned long)irq_mask_register); + val |= mask; + ctrl_outw(val, (unsigned long)irq_mask_register); + local_irq_restore(flags); + } +} + +static void enable_maskreg_irq(unsigned int irq) +{ + if (irq_mask_register) { + unsigned long flags; + unsigned short val, mask = ~(0x01 << irq); + + /* Clear "irq"th bit */ + local_irq_save(flags); + val = ctrl_inw((unsigned long)irq_mask_register); + val &= mask; + ctrl_outw(val, (unsigned long)irq_mask_register); + local_irq_restore(flags); + } +} + +static void mask_and_ack_maskreg(unsigned int irq) +{ + disable_maskreg_irq(irq); +} + +static void end_maskreg_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_maskreg_irq(irq); +} + +void make_maskreg_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &maskreg_irq_type; + disable_maskreg_irq(irq); +} diff --git a/arch/sh/boards/adx/setup.c b/arch/sh/boards/adx/setup.c new file mode 100644 index 00000000000..4938d959234 --- /dev/null +++ b/arch/sh/boards/adx/setup.c @@ -0,0 +1,56 @@ +/* + * linux/arch/sh/board/adx/setup.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * 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. + * + */ + +#include <asm/machvec.h> +#include <linux/module.h> + +extern void init_adx_IRQ(void); +extern void *cf_io_base; + +const char *get_system_type(void) +{ + return "A&D ADX"; +} + +unsigned long adx_isa_port2addr(unsigned long offset) +{ + /* CompactFlash (IDE) */ + if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) { + return (unsigned long)cf_io_base + offset; + } + + /* eth0 */ + if ((offset >= 0x300) && (offset <= 0x30f)) { + return 0xa5000000 + offset; /* COMM BOARD (AREA1) */ + } + + return offset + 0xb0000000; /* IOBUS (AREA 4)*/ +} + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_adx __initmv = { + .mv_nr_irqs = 48, + .mv_isa_port2addr = adx_isa_port2addr, + .mv_init_irq = init_adx_IRQ, +}; +ALIAS_MV(adx) + +int __init platform_setup(void) +{ + /* Nothing to see here .. */ + return 0; +} + |