|
@@ -1,27 +1,27 @@
|
|
|
-/************************************************************************/
|
|
|
-/* This module supports the iSeries PCI bus interrupt handling */
|
|
|
-/* Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> */
|
|
|
-/* */
|
|
|
-/* This program is free software; you can redistribute it and/or modify */
|
|
|
-/* it under the terms of the GNU General Public License as published by */
|
|
|
-/* the Free Software Foundation; either version 2 of the License, or */
|
|
|
-/* (at your option) any later version. */
|
|
|
-/* */
|
|
|
-/* This program is distributed in the hope that it will be useful, */
|
|
|
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
|
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
|
-/* GNU General Public License for more details. */
|
|
|
-/* */
|
|
|
-/* You should have received a copy of the GNU General Public License */
|
|
|
-/* along with this program; if not, write to the: */
|
|
|
-/* Free Software Foundation, Inc., */
|
|
|
-/* 59 Temple Place, Suite 330, */
|
|
|
-/* Boston, MA 02111-1307 USA */
|
|
|
-/************************************************************************/
|
|
|
-/* Change Activity: */
|
|
|
-/* Created, December 13, 2000 by Wayne Holm */
|
|
|
-/* End Change Activity */
|
|
|
-/************************************************************************/
|
|
|
+/*
|
|
|
+ * This module supports the iSeries PCI bus interrupt handling
|
|
|
+ * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
|
|
|
+ *
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
+ * (at your option) any later version.
|
|
|
+ *
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
+ * along with this program; if not, write to the:
|
|
|
+ * Free Software Foundation, Inc.,
|
|
|
+ * 59 Temple Place, Suite 330,
|
|
|
+ * Boston, MA 02111-1307 USA
|
|
|
+ *
|
|
|
+ * Change Activity:
|
|
|
+ * Created, December 13, 2000 by Wayne Holm
|
|
|
+ * End Change Activity
|
|
|
+ */
|
|
|
#include <linux/pci.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/threads.h>
|
|
@@ -38,22 +38,6 @@
|
|
|
#include <asm/iSeries/HvCallPci.h>
|
|
|
#include <asm/iSeries/HvCallXm.h>
|
|
|
#include <asm/iSeries/iSeries_irq.h>
|
|
|
-#include <asm/iSeries/XmPciLpEvent.h>
|
|
|
-
|
|
|
-static unsigned int iSeries_startup_IRQ(unsigned int irq);
|
|
|
-static void iSeries_shutdown_IRQ(unsigned int irq);
|
|
|
-static void iSeries_enable_IRQ(unsigned int irq);
|
|
|
-static void iSeries_disable_IRQ(unsigned int irq);
|
|
|
-static void iSeries_end_IRQ(unsigned int irq);
|
|
|
-
|
|
|
-static hw_irq_controller iSeries_IRQ_handler = {
|
|
|
- .typename = "iSeries irq controller",
|
|
|
- .startup = iSeries_startup_IRQ,
|
|
|
- .shutdown = iSeries_shutdown_IRQ,
|
|
|
- .enable = iSeries_enable_IRQ,
|
|
|
- .disable = iSeries_disable_IRQ,
|
|
|
- .end = iSeries_end_IRQ
|
|
|
-};
|
|
|
|
|
|
/* This maps virtual irq numbers to real irqs */
|
|
|
unsigned int virt_irq_to_real_map[NR_IRQS];
|
|
@@ -69,30 +53,32 @@ void __init iSeries_init_IRQ(void)
|
|
|
XmPciLpEvent_init();
|
|
|
}
|
|
|
|
|
|
+#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
|
|
|
+#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
|
|
|
+#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
|
|
|
+
|
|
|
/*
|
|
|
- * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
|
|
|
- * It calculates the irq value for the slot.
|
|
|
- * Note that subBusNumber is always 0 (at the moment at least).
|
|
|
+ * This will be called by device drivers (via enable_IRQ)
|
|
|
+ * to enable INTA in the bridge interrupt status register.
|
|
|
*/
|
|
|
-int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
|
|
|
- HvSubBusNumber subBusNumber, HvAgentId deviceId)
|
|
|
+static void iSeries_enable_IRQ(unsigned int irq)
|
|
|
{
|
|
|
- unsigned int realirq, virtirq;
|
|
|
- u8 idsel = (deviceId >> 4);
|
|
|
- u8 function = deviceId & 7;
|
|
|
+ u32 bus, deviceId, function, mask;
|
|
|
+ const u32 subBus = 0;
|
|
|
+ unsigned int rirq = virt_irq_to_real_map[irq];
|
|
|
|
|
|
- virtirq = next_virtual_irq++;
|
|
|
- realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
|
|
|
- virt_irq_to_real_map[virtirq] = realirq;
|
|
|
+ /* The IRQ has already been locked by the caller */
|
|
|
+ bus = REAL_IRQ_TO_BUS(rirq);
|
|
|
+ function = REAL_IRQ_TO_FUNC(rirq);
|
|
|
+ deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
|
|
|
|
|
- irq_desc[virtirq].handler = &iSeries_IRQ_handler;
|
|
|
- return virtirq;
|
|
|
+ /* Unmask secondary INTA */
|
|
|
+ mask = 0x80000000;
|
|
|
+ HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
|
|
|
+ PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
|
|
|
+ bus, subBus, deviceId, irq);
|
|
|
}
|
|
|
|
|
|
-#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
|
|
|
-#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
|
|
|
-#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
|
|
|
-
|
|
|
/* This is called by iSeries_activate_IRQs */
|
|
|
static unsigned int iSeries_startup_IRQ(unsigned int irq)
|
|
|
{
|
|
@@ -131,7 +117,7 @@ void __init iSeries_activate_IRQs()
|
|
|
desc->handler->startup(irq);
|
|
|
spin_unlock_irqrestore(&desc->lock, flags);
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* this is not called anywhere currently */
|
|
@@ -173,29 +159,7 @@ static void iSeries_disable_IRQ(unsigned int irq)
|
|
|
mask = 0x80000000;
|
|
|
HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
|
|
|
PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
|
|
|
- bus, subBus, deviceId, irq);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * This will be called by device drivers (via enable_IRQ)
|
|
|
- * to enable INTA in the bridge interrupt status register.
|
|
|
- */
|
|
|
-static void iSeries_enable_IRQ(unsigned int irq)
|
|
|
-{
|
|
|
- u32 bus, deviceId, function, mask;
|
|
|
- const u32 subBus = 0;
|
|
|
- unsigned int rirq = virt_irq_to_real_map[irq];
|
|
|
-
|
|
|
- /* The IRQ has already been locked by the caller */
|
|
|
- bus = REAL_IRQ_TO_BUS(rirq);
|
|
|
- function = REAL_IRQ_TO_FUNC(rirq);
|
|
|
- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
|
|
-
|
|
|
- /* Unmask secondary INTA */
|
|
|
- mask = 0x80000000;
|
|
|
- HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
|
|
|
- PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
|
|
|
- bus, subBus, deviceId, irq);
|
|
|
+ bus, subBus, deviceId, irq);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -207,3 +171,32 @@ static void iSeries_enable_IRQ(unsigned int irq)
|
|
|
static void iSeries_end_IRQ(unsigned int irq)
|
|
|
{
|
|
|
}
|
|
|
+
|
|
|
+static hw_irq_controller iSeries_IRQ_handler = {
|
|
|
+ .typename = "iSeries irq controller",
|
|
|
+ .startup = iSeries_startup_IRQ,
|
|
|
+ .shutdown = iSeries_shutdown_IRQ,
|
|
|
+ .enable = iSeries_enable_IRQ,
|
|
|
+ .disable = iSeries_disable_IRQ,
|
|
|
+ .end = iSeries_end_IRQ
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
|
|
|
+ * It calculates the irq value for the slot.
|
|
|
+ * Note that subBusNumber is always 0 (at the moment at least).
|
|
|
+ */
|
|
|
+int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
|
|
|
+ HvSubBusNumber subBusNumber, HvAgentId deviceId)
|
|
|
+{
|
|
|
+ unsigned int realirq, virtirq;
|
|
|
+ u8 idsel = (deviceId >> 4);
|
|
|
+ u8 function = deviceId & 7;
|
|
|
+
|
|
|
+ virtirq = next_virtual_irq++;
|
|
|
+ realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
|
|
|
+ virt_irq_to_real_map[virtirq] = realirq;
|
|
|
+
|
|
|
+ irq_desc[virtirq].handler = &iSeries_IRQ_handler;
|
|
|
+ return virtirq;
|
|
|
+}
|