bast-irq.c (2765B)
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// Copyright 2003-2005 Simtec Electronics 4// Ben Dooks <ben@simtec.co.uk> 5// 6// http://www.simtec.co.uk/products/EB2410ITX/ 7 8#include <linux/init.h> 9#include <linux/module.h> 10#include <linux/ioport.h> 11#include <linux/device.h> 12#include <linux/io.h> 13 14#include <asm/irq.h> 15#include <asm/mach-types.h> 16#include <asm/mach/irq.h> 17 18#include "regs-irq.h" 19#include "irqs.h" 20 21#include "bast.h" 22 23#define irqdbf(x...) 24#define irqdbf2(x...) 25 26/* handle PC104 ISA interrupts from the system CPLD */ 27 28/* table of ISA irq nos to the relevant mask... zero means 29 * the irq is not implemented 30*/ 31static const unsigned char bast_pc104_irqmasks[] = { 32 0, /* 0 */ 33 0, /* 1 */ 34 0, /* 2 */ 35 1, /* 3 */ 36 0, /* 4 */ 37 2, /* 5 */ 38 0, /* 6 */ 39 4, /* 7 */ 40 0, /* 8 */ 41 0, /* 9 */ 42 8, /* 10 */ 43 0, /* 11 */ 44 0, /* 12 */ 45 0, /* 13 */ 46 0, /* 14 */ 47 0, /* 15 */ 48}; 49 50static const unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 }; 51 52static void 53bast_pc104_mask(struct irq_data *data) 54{ 55 unsigned long temp; 56 57 temp = __raw_readb(BAST_VA_PC104_IRQMASK); 58 temp &= ~bast_pc104_irqmasks[data->irq]; 59 __raw_writeb(temp, BAST_VA_PC104_IRQMASK); 60} 61 62static void 63bast_pc104_maskack(struct irq_data *data) 64{ 65 struct irq_desc *desc = irq_to_desc(BAST_IRQ_ISA); 66 67 bast_pc104_mask(data); 68 desc->irq_data.chip->irq_ack(&desc->irq_data); 69} 70 71static void 72bast_pc104_unmask(struct irq_data *data) 73{ 74 unsigned long temp; 75 76 temp = __raw_readb(BAST_VA_PC104_IRQMASK); 77 temp |= bast_pc104_irqmasks[data->irq]; 78 __raw_writeb(temp, BAST_VA_PC104_IRQMASK); 79} 80 81static struct irq_chip bast_pc104_chip = { 82 .irq_mask = bast_pc104_mask, 83 .irq_unmask = bast_pc104_unmask, 84 .irq_ack = bast_pc104_maskack 85}; 86 87static void bast_irq_pc104_demux(struct irq_desc *desc) 88{ 89 unsigned int stat; 90 unsigned int irqno; 91 int i; 92 93 stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf; 94 95 if (unlikely(stat == 0)) { 96 /* ack if we get an irq with nothing (ie, startup) */ 97 desc->irq_data.chip->irq_ack(&desc->irq_data); 98 } else { 99 /* handle the IRQ */ 100 101 for (i = 0; stat != 0; i++, stat >>= 1) { 102 if (stat & 1) { 103 irqno = bast_pc104_irqs[i]; 104 generic_handle_irq(irqno); 105 } 106 } 107 } 108} 109 110static __init int bast_irq_init(void) 111{ 112 unsigned int i; 113 114 if (machine_is_bast()) { 115 printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n"); 116 117 /* zap all the IRQs */ 118 119 __raw_writeb(0x0, BAST_VA_PC104_IRQMASK); 120 121 irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux); 122 123 /* register our IRQs */ 124 125 for (i = 0; i < 4; i++) { 126 unsigned int irqno = bast_pc104_irqs[i]; 127 128 irq_set_chip_and_handler(irqno, &bast_pc104_chip, 129 handle_level_irq); 130 irq_clear_status_flags(irqno, IRQ_NOREQUEST); 131 } 132 } 133 134 return 0; 135} 136 137arch_initcall(bast_irq_init);