DECLARE_GLOBAL_DATA_PTR;
+static bool isa_irq_occupied[16];
+
struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf)
{
- u32 mc;
+ ulong mc;
memcpy(mf->mpf_signature, MPF_SIGNATURE, 4);
- mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table);
+ mf->mpf_physptr = (ulong)mf + sizeof(struct mp_floating_table);
mf->mpf_length = 1;
mf->mpf_spec = MPSPEC_V14;
mf->mpf_checksum = 0;
mf->mpf_feature5 = 0;
mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16);
- mc = (u32)mf + sizeof(struct mp_floating_table);
+ mc = (ulong)mf + sizeof(struct mp_floating_table);
return (struct mp_config_table *)mc;
}
u32 mptable_finalize(struct mp_config_table *mc)
{
- u32 end;
+ ulong end;
mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc),
mc->mpe_length);
mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length);
end = mp_next_mpe_entry(mc);
- debug("Write the MP table at: %x - %x\n", (u32)mc, end);
+ debug("Write the MP table at: %lx - %lx\n", (ulong)mc, end);
return end;
}
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, apicid, 2);
- for (i = 3; i < 16; i++)
+ for (i = 3; i < 16; i++) {
+ /*
+ * Do not write ISA interrupt entry if it is already occupied
+ * by the platform devices.
+ */
+ if (isa_irq_occupied[i])
+ continue;
+
mp_write_intsrc(mc, MP_INT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, i, apicid, i);
+ }
}
/*
return (i == entry_num) ? false : true;
}
+/* TODO: move this to driver model */
+__weak int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
+{
+ /* PIRQ[A-H] are connected to I/O APIC INTPIN#16-23 */
+ return pirq + 16;
+}
+
static int mptable_add_intsrc(struct mp_config_table *mc,
int bus_isa, int apicid)
{
struct mpc_config_intsrc *intsrc_base;
int intsrc_entries = 0;
const void *blob = gd->fdt_blob;
- int node;
+ struct udevice *dev;
int len, count;
const u32 *cell;
- int i;
-
- /* Legacy Interrupts */
- debug("Writing ISA IRQs\n");
- mptable_add_isa_interrupts(mc, bus_isa, apicid, 0);
+ int i, ret;
- /* Get I/O interrupt information from device tree */
- node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER);
- if (node < 0) {
+ ret = uclass_first_device_err(UCLASS_IRQ, &dev);
+ if (ret && ret != -ENODEV) {
debug("%s: Cannot find irq router node\n", __func__);
- return -ENOENT;
+ return ret;
}
- cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
+ /* Get I/O interrupt information from device tree */
+ cell = fdt_getprop(blob, dev_of_offset(dev), "intel,pirq-routing",
+ &len);
if (!cell)
return -ENOENT;
for (i = 0; i < count; i++) {
struct pirq_routing pr;
+ int bus, dev, func;
+ int dstirq;
pr.bdf = fdt_addr_to_cpu(cell[0]);
pr.pin = fdt_addr_to_cpu(cell[1]);
pr.pirq = fdt_addr_to_cpu(cell[2]);
+ bus = PCI_BUS(pr.bdf);
+ dev = PCI_DEV(pr.bdf);
+ func = PCI_FUNC(pr.bdf);
if (check_dup_entry(intsrc_base, intsrc_entries,
- PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) {
+ bus, dev, pr.pin)) {
debug("found entry for bus %d device %d INT%c, skipping\n",
- PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
- 'A' + pr.pin - 1);
+ bus, dev, 'A' + pr.pin - 1);
cell += sizeof(struct pirq_routing) / sizeof(u32);
continue;
}
- /* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */
- mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf),
- PCI_DEV(pr.bdf), pr.pin, apicid,
- pr.pirq + 16);
+ dstirq = mp_determine_pci_dstirq(bus, dev, func, pr.pirq);
+ /*
+ * For PIRQ which is connected to I/O APIC interrupt pin#0-15,
+ * mark it as occupied so that we can skip it later.
+ */
+ if (dstirq < 16)
+ isa_irq_occupied[dstirq] = true;
+ mp_write_pci_intsrc(mc, MP_INT, bus, dev, pr.pin,
+ apicid, dstirq);
intsrc_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32);
}
+ /* Legacy Interrupts */
+ debug("Writing ISA IRQs\n");
+ mptable_add_isa_interrupts(mc, bus_isa, apicid, 0);
+
return 0;
}
bus_isa, 0, MP_APIC_ALL, 1);
}
-u32 write_mp_table(u32 addr)
+ulong write_mp_table(ulong addr)
{
struct mp_config_table *mc;
int ioapic_id, ioapic_ver;
int bus_isa = 0xff;
int ret;
- u32 end;
+ ulong end;
/* 16 byte align the table address */
addr = ALIGN(addr, 16);