Viewing file: setup_cqreek.c (5.84 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* $Id: setup_cqreek.c,v 1.9 2001/07/30 12:43:28 gniibe Exp $ * * arch/sh/kernel/setup_cqreek.c * * Copyright (C) 2000 Niibe Yutaka * * CqREEK IDE/ISA Bridge Support. * */
#include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/irq.h>
#include <asm/io.h> #include <asm/io_generic.h> #include <asm/irq.h> #include <asm/machvec.h> #include <asm/machvec_init.h> #include <asm/rtc.h>
#define BRIDGE_FEATURE 0x0002
#define BRIDGE_IDE_CTRL 0x0018 #define BRIDGE_IDE_INTR_LVL 0x001A #define BRIDGE_IDE_INTR_MASK 0x001C #define BRIDGE_IDE_INTR_STAT 0x001E
#define BRIDGE_ISA_CTRL 0x0028 #define BRIDGE_ISA_INTR_LVL 0x002A #define BRIDGE_ISA_INTR_MASK 0x002C #define BRIDGE_ISA_INTR_STAT 0x002E
#define IDE_OFFSET 0xA4000000UL #define ISA_OFFSET 0xA4A00000UL
static unsigned long cqreek_port2addr(unsigned long port) { if (0x0000<=port && port<=0x0040) return IDE_OFFSET + port; if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6) return IDE_OFFSET + port;
return ISA_OFFSET + port; }
struct cqreek_irq_data { unsigned short mask_port; /* Port of Interrupt Mask Register */ unsigned short stat_port; /* Port of Interrupt Status Register */ unsigned short bit; /* Value of the bit */ }; static struct cqreek_irq_data cqreek_irq_data[NR_IRQS];
static void disable_cqreek_irq(unsigned int irq) { unsigned long flags; unsigned short mask; unsigned short mask_port = cqreek_irq_data[irq].mask_port; unsigned short bit = cqreek_irq_data[irq].bit;
save_and_cli(flags); /* Disable IRQ */ mask = inw(mask_port) & ~bit; outw_p(mask, mask_port); restore_flags(flags); }
static void enable_cqreek_irq(unsigned int irq) { unsigned long flags; unsigned short mask; unsigned short mask_port = cqreek_irq_data[irq].mask_port; unsigned short bit = cqreek_irq_data[irq].bit;
save_and_cli(flags); /* Enable IRQ */ mask = inw(mask_port) | bit; outw_p(mask, mask_port); restore_flags(flags); }
static void mask_and_ack_cqreek(unsigned int irq) { unsigned short stat_port = cqreek_irq_data[irq].stat_port; unsigned short bit = cqreek_irq_data[irq].bit;
disable_cqreek_irq(irq); /* Clear IRQ (it might be edge IRQ) */ inw(stat_port); outw_p(bit, stat_port); }
static void end_cqreek_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_cqreek_irq(irq); }
static unsigned int startup_cqreek_irq(unsigned int irq) { enable_cqreek_irq(irq); return 0; }
static void shutdown_cqreek_irq(unsigned int irq) { disable_cqreek_irq(irq); }
static struct hw_interrupt_type cqreek_irq_type = { "CqREEK-IRQ", startup_cqreek_irq, shutdown_cqreek_irq, enable_cqreek_irq, disable_cqreek_irq, mask_and_ack_cqreek, end_cqreek_irq };
static int has_ide, has_isa;
/* XXX: This is just for test for my NE2000 ISA board What we really need is virtualized IRQ and demultiplexer like HP600 port */ void __init init_cqreek_IRQ(void) { if (has_ide) { cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK; cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT; cqreek_irq_data[14].bit = 1;
irq_desc[14].handler = &cqreek_irq_type; irq_desc[14].status = IRQ_DISABLED; irq_desc[14].action = 0; irq_desc[14].depth = 1;
disable_cqreek_irq(14); }
if (has_isa) { cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK; cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT; cqreek_irq_data[10].bit = (1 << 10);
/* XXX: Err... we may need demultiplexer for ISA irq... */ irq_desc[10].handler = &cqreek_irq_type; irq_desc[10].status = IRQ_DISABLED; irq_desc[10].action = 0; irq_desc[10].depth = 1;
disable_cqreek_irq(10); } }
/* * Initialize the board */ void __init setup_cqreek(void) { int i; /* udelay is not available at setup time yet... */ #define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */ outw_p(0, BRIDGE_IDE_INTR_LVL); outw_p(0, BRIDGE_IDE_INTR_MASK);
outw_p(0, BRIDGE_IDE_CTRL); DELAY();
outw_p(0x8000, BRIDGE_IDE_CTRL); DELAY();
outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */ outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */ outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */ has_ide=1; }
if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */ outw_p(0, BRIDGE_ISA_INTR_LVL); outw_p(0, BRIDGE_ISA_INTR_MASK);
outw_p(0, BRIDGE_ISA_CTRL); DELAY(); outw_p(0x8000, BRIDGE_ISA_CTRL); DELAY();
outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */ outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */ outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */ has_isa=1; }
printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", has_ide, has_isa); }
/* * The Machine Vector */
struct sh_machine_vector mv_cqreek __initmv = { mv_name: "CqREEK",
#if defined(__SH4__) mv_nr_irqs: 48, #elif defined(CONFIG_CPU_SUBTYPE_SH7708) mv_nr_irqs: 32, #elif defined(CONFIG_CPU_SUBTYPE_SH7709) mv_nr_irqs: 61, #endif
mv_inb: generic_inb, mv_inw: generic_inw, mv_inl: generic_inl, mv_outb: generic_outb, mv_outw: generic_outw, mv_outl: generic_outl,
mv_inb_p: generic_inb_p, mv_inw_p: generic_inw_p, mv_inl_p: generic_inl_p, mv_outb_p: generic_outb_p, mv_outw_p: generic_outw_p, mv_outl_p: generic_outl_p,
mv_insb: generic_insb, mv_insw: generic_insw, mv_insl: generic_insl, mv_outsb: generic_outsb, mv_outsw: generic_outsw, mv_outsl: generic_outsl,
mv_readb: generic_readb, mv_readw: generic_readw, mv_readl: generic_readl, mv_writeb: generic_writeb, mv_writew: generic_writew, mv_writel: generic_writel,
mv_init_arch: setup_cqreek, mv_init_irq: init_cqreek_IRQ,
mv_isa_port2addr: cqreek_port2addr,
mv_ioremap: generic_ioremap, mv_iounmap: generic_iounmap,
mv_rtc_gettimeofday: sh_rtc_gettimeofday, mv_rtc_settimeofday: sh_rtc_settimeofday, }; ALIAS_MV(cqreek)
|