#include <asm/byteorder.h> /* get in-line asm for swab */
#include <asm/pdc.h>
+#include <asm/pdcpat.h>
#include <asm/page.h>
#include <asm/segment.h>
#include <asm/system.h>
-#include <asm/io.h> /* gsc_read/write functions */
+#include <asm/io.h> /* read/write functions */
#ifdef CONFIG_SUPERIO
#include <asm/superio.h>
#endif
#endif
-#define READ_U8(addr) gsc_readb(addr)
-#define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
-#define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
-#define READ_REG16(addr) gsc_readw((u16 *) (addr))
-#define READ_REG32(addr) gsc_readl((u32 *) (addr))
-#define WRITE_U8(value, addr) gsc_writeb(value, addr)
-#define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
-#define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
-#define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
-#define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
-
-
-#define IOSAPIC_REG_SELECT 0
+#define IOSAPIC_REG_SELECT 0x00
#define IOSAPIC_REG_WINDOW 0x10
#define IOSAPIC_REG_EOI 0x40
#define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
#define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
+static inline unsigned int iosapic_read(unsigned long iosapic, unsigned int reg)
+{
+ writel(reg, iosapic + IOSAPIC_REG_SELECT);
+ return readl(iosapic + IOSAPIC_REG_WINDOW);
+}
+
+static inline void iosapic_write(unsigned long iosapic, unsigned int reg, u32 val)
+{
+ writel(reg, iosapic + IOSAPIC_REG_SELECT);
+ writel(val, iosapic + IOSAPIC_REG_WINDOW);
+}
+
/*
-** FIXME: revisit which GFP flags we should really be using.
** GFP_KERNEL includes __GFP_WAIT flag and that may not
** be acceptable. Since this is boot time, we shouldn't have
** to wait ever and this code should (will?) never get called
#define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags)
-#define IOSAPIC_VERSION_MASK 0x000000ff
-#define IOSAPIC_VERSION_SHIFT 0x0
-#define IOSAPIC_VERSION(ver) \
- (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
+#define IOSAPIC_VERSION_MASK 0x000000ff
+#define IOSAPIC_VERSION(ver) ((int) (ver & IOSAPIC_VERSION_MASK))
#define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
-
#define IOSAPIC_MAX_ENTRY_SHIFT 0x10
-#define IOSAPIC_IRDT_MAX_ENTRY(ver) \
- (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
+#define IOSAPIC_IRDT_MAX_ENTRY(ver) \
+ (int) (((ver) & IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
/* bits in the "low" I/O Sapic IRdT entry */
#define IOSAPIC_IRDT_ENABLE 0x10000
#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
-
-#define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
-
static struct iosapic_info *iosapic_list;
static spinlock_t iosapic_lock;
static int iosapic_count;
struct irt_entry *p = table;
int i;
- printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
- printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
+ printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
+ printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
table,
num_entries,
(int) sizeof(struct irt_entry));
for (i = 0 ; i < num_entries ; i++, p++) {
- printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
+ printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
p->entry_type, p->entry_length, p->interrupt_type,
p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
p->src_seg_id, p->dest_iosapic_intin,
static irqreturn_t
iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
- struct vector_info *vi = (struct vector_info *)dev_id;
+ struct vector_info *vi = (struct vector_info *) dev_id;
extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
int irq_num = vi->iosapic->isi_region->data.irqbase + vi->irqline;
- DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
- irq, vi->irqline, vi->eoi_addr);
+ DBG("iosapic_interrupt(): irq %d line %d eoi 0x%p 0x%x\n",
+ irq, vi->irqline, vi->eoi_addr, vi->eoi_data);
+
+ /* Do NOT need to mask/unmask IRQ. processor is already masked. */
-/* FIXME: Need to mask/unmask? processor IRQ is already masked... */
do_irq(&vi->iosapic->isi_region->action[vi->irqline], irq_num, regs);
/*
+ ** PARISC only supports PCI devices below I/O SAPIC.
** PCI only supports level triggered in order to share IRQ lines.
- ** I/O SAPIC must always issue EOI.
+ ** ergo I/O SAPIC must always issue EOI on parisc.
+ **
+ ** i386/ia64 support ISA devices and have to deal with
+ ** edge-triggered interrupts too.
*/
- IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
-
+ __raw_writel(vi->eoi_data, vi->eoi_addr);
return IRQ_HANDLED;
}
ASSERT(tmp == 0);
vi->eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
- vi->eoi_data = cpu_to_le32(vi->irqline);
-
+ vi->eoi_data = cpu_to_le32(vi->txn_data);
ASSERT(NULL != isi->isi_region);
DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
struct iosapic_info *isp = vi->iosapic;
u8 idx = vi->irqline;
- /* point the window register to the lower word */
- WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
- *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
-
- /* point the window register to the higher word */
- WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
- *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ *dp0 = iosapic_read(isp->isi_hpa, IOSAPIC_IRDT_ENTRY(idx));
+ *dp1 = iosapic_read(isp->isi_hpa, IOSAPIC_IRDT_ENTRY_HI(idx));
}
ASSERT(NULL != isp);
ASSERT(0 != isp->isi_hpa);
- DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n",
+ DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p 0x%x 0x%x\n",
vi->irqline,
- isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
+ isp->isi_hpa,
dp0, dp1);
- /* point the window register to the lower word */
- WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
- WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ iosapic_write(isp->isi_hpa, IOSAPIC_IRDT_ENTRY(vi->irqline), dp0);
/* Read the window register to flush the writes down to HW */
- dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ dp0 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
- /* point the window register to the higher word */
- WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
- WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ iosapic_write(isp->isi_hpa, IOSAPIC_IRDT_ENTRY_HI(vi->irqline), dp1);
/* Read the window register to flush the writes down to HW */
- dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ dp1 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
}
iosapic_set_irt_data(vi, &d0, &d1);
iosapic_wr_irt_entry(vi, d0, d1);
-
#ifdef DEBUG_IOSAPIC_IRT
{
u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
- while (t < vi->eoi_addr) printk(" %x", READ_U32(t++));
+ for ( ; t < vi->eoi_addr; t++)
+ printk(" %x", readl(t));
printk("\n");
}
struct iosapic_info *isp = vi->iosapic;
for (d0=0x10; d0<0x1e; d0++) {
- /* point the window register to the lower word */
- WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
-
- /* read the word */
- d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ d1 = iosapic_read(isp->isi_hpa, d0);
printk(" %x", d1);
}
}
#endif
/*
- ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
- ** PCI supports level triggered in order to share IRQ lines.
- **
- ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
- ** asserted.
+ ** Issueing I/O SAPIC an EOI causes an interrupt IFF IRQ line is
+ ** asserted. IRQ generally should not be asserted when a driver
+ ** enables their IRQ. It can lead to "interesting" race conditions
+ ** in the driver initialization sequence.
*/
- IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
+ __raw_writel(vi->eoi_data, vi->eoi_addr);
}
ASSERT(isi);
ASSERT(isi->isi_hpa);
- /* point window to the version register */
- WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
-
- /* now read the version register */
- return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
+ return iosapic_read(isi->isi_hpa, IOSAPIC_REG_VERSION);
}