Converting to new IRQ code
Rune Torgersen
runet at innovsys.com
Tue Aug 29 05:40:27 EST 2006
Hi.
Can anybody help me convert the following IRQ demux code to the new IRQ
setup?
I tried just changing irq_desc[irq].handler to irq_desc_[irq].chip, but
then it dumps in _do_IRQ()
This is on a MPC8280 with an ecternal (in FPGA) PCI IRQ mux
static volatile unsigned short * pci_status_reg;
static volatile unsigned short * pci_mask_reg;
static inline int
innsys_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char
pin)
{
//struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
//int temp;
if (!dev->bus->number) // PCI bus 0
{
static char pci_irq_table[][4] =
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{
{ PIRQ0, PIRQ0, PIRQ0, PIRQ0 }, /* IDSEL 16 -
CPU2 */
{ PIRQ5, PIRQ5, PIRQ5, PIRQ5 }, /* IDSEL 17 -
IDE controller */
{ PIRQ1, PIRQ2, PIRQ3, PIRQ4 }, /* IDSEL 18 -
Bridge */
};
const long min_idsel = 0x10, max_idsel = 0x12, irqs_per_slot
= 4;
//temp = PCI_IRQ_TABLE_LOOKUP;
//printk("<1>0: PCI map IRQ for bus %d, device %d; IDsel = %d,
pin %d, irq = %d\n",
// dev->bus->number, dev->bus->device, idsel, pin, temp);
return PCI_IRQ_TABLE_LOOKUP;
//return temp;
}
else // PCI bus 1
{
static char pci_irq_table[][4] =
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{
{ PIRQ1, PIRQ2, PIRQ3, PIRQ4 }, /* IDSEL 16 -
DSP 0 */
{ PIRQ2, PIRQ2, PIRQ2, PIRQ2 }, /* IDSEL 17 -
DSP 1 */
{ PIRQ3, PIRQ3, PIRQ3, PIRQ3 }, /* IDSEL 18 -
DSP 2 */
{ PIRQ4, PIRQ4, PIRQ4, PIRQ4 }, /* IDSEL 19 -
DSP 2 */
};
const long min_idsel = 18, max_idsel = 18, irqs_per_slot =
4;
return PCI_IRQ_TABLE_LOOKUP;
//temp = PCI_IRQ_TABLE_LOOKUP;
//printk("<1>1: PCI map IRQ for bus %d, device %d; IDsel = %d,
pin %d, irq = %d\n",
// dev->bus->number, dev->bus->device, idsel, pin, temp);
//return PCI_IRQ_TABLE_LOOKUP;
//return temp;
}
}
static void
innsys_mask_irq(unsigned int irq)
{
int bit = irq - PCI_INT_OFFSET;
// 0 is masked, 1 is enabled
//*(volatile unsigned short *) PCI_INT_MASK_REG &= ~(1 << bit);
*pci_mask_reg &= ~(1 << bit);
return;
}
static void
innsys_unmask_irq(unsigned int irq)
{
int bit = irq - PCI_INT_OFFSET;
//*(volatile unsigned short *) PCI_INT_MASK_REG |= (1 << bit);
*pci_mask_reg |= (1 << bit);
return;
}
static void
innsys_mask_and_ack(unsigned int irq)
{
int bit = irq - PCI_INT_OFFSET;
//*(volatile unsigned short *) PCI_INT_MASK_REG &= ~(1 << bit);
*pci_mask_reg &= ~(1 << bit);
//__asm("sync");
return;
}
static void
innsys_end_irq(unsigned int irq)
{
int bit = irq - PCI_INT_OFFSET;
//*(volatile unsigned short *) PCI_INT_MASK_REG |= (1 << bit);
*pci_mask_reg |= (1 << bit);
return;
}
struct hw_interrupt_type innsys_ic = {
" AP2PCI ",
NULL,
NULL,
innsys_unmask_irq,
innsys_mask_irq,
innsys_mask_and_ack,
innsys_end_irq,
0
};
static irqreturn_t
pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned short stat, mask, pend;
int bit;
for(;;) {
//stat = *(volatile unsigned short *) PCI_INT_STAT_REG;
//mask = *(volatile unsigned short *) PCI_INT_MASK_REG;
stat = *pci_status_reg;
mask = *pci_mask_reg;
pend = stat & mask & 0x3f;
//printk("<1>\tInt status = 0x%04x, mask = 0x%04x, pend =
0x%04x\n", stat, mask, pend);
if (!pend)
break;
for (bit = 0; pend != 0; ++bit, pend >>= 1) {
if (pend & 1)
{
//printk("<1> dispatch int %d\n", PCI_INT_OFFSET + bit);
//ppc_irq_dispatch_handler(regs,
PCI_INT_OFFSET + bit);
__do_IRQ((PCI_INT_OFFSET + bit), regs);
}
}
}
return IRQ_HANDLED;
}
static struct irqaction innsys_pci_action = {
.handler= pci_irq_demux,
.flags = SA_INTERRUPT,
.mask = CPU_MASK_NONE,
.name = "PCI IRQ demux",
};
void
innsys_init_irq(void)
{
int irq;
void * tmp;
volatile cpm2_map_t *immap = cpm2_immr;
uint32_t fpga_base;
tmp = innsys_map_irq;
// map mask and status registers
fpga_base = immap->im_memctl.memc_br5 & 0xffff8000;
pci_status_reg = (unsigned short *)(fpga_base + PCI_INT_STAT_REG);
pci_mask_reg = (unsigned short *)(fpga_base + PCI_INT_MASK_REG);
for (irq = PCI_INT_OFFSET; irq < PCI_INT_OFFSET + NUM_PCI_INTS;
irq++)
irq_desc[irq].handler = &innsys_ic;
/* make IRQ7 level sensitive */
((volatile cpm2_map_t *) CPM_MAP_ADDR)->im_intctl.ic_siexr &=
~(1 << (14 - (SIU_INT_IRQ7 - SIU_INT_IRQ1)));
/* mask all PCI interrupts */
//*(volatile unsigned short *) PCI_INT_MASK_REG = 0;
*pci_mask_reg = 0;
/* install the demultiplexer for the PCI cascade interrupt */
setup_irq(SIU_INT_IRQ7, &innsys_pci_action);
return;
}
More information about the Linuxppc-embedded
mailing list