#include <asm/platform.h>
#include <xen/stdbool.h>
#include <xen/vmap.h>
+#include <xen/device_tree.h>
#include <asm/io.h>
#include <asm/gic.h>
static u32 reset_mask;
static bool reset_vals_valid = false;
+#define XGENE_SEC_GICV2_DIST_ADDR 0x78010000
+static u32 __read_mostly xgene_quirks = PLATFORM_QUIRK_GIC_64K_STRIDE;
+
+static void __init xgene_check_pirq_eoi(void)
+{
+ const struct dt_device_node *node;
+ int res;
+ paddr_t dbase;
+ const struct dt_device_match xgene_dt_int_ctrl_match[] =
+ {
+ DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"),
+ { /*sentinel*/ },
+ };
+
+ node = dt_find_interrupt_controller(xgene_dt_int_ctrl_match);
+ if ( !node )
+ panic("%s: Can not find interrupt controller node", __func__);
+
+ res = dt_device_get_address(node, 0, &dbase, NULL);
+ if ( !dbase )
+ panic("%s: Cannot find a valid address for the distributor", __func__);
+
+ /*
+ * In old X-Gene Storm firmware and DT, secure mode addresses have
+ * been mentioned in GICv2 node. We have to use maintenance interrupt
+ * instead of EOI HW in this case. We check the GIC Distributor Base
+ * Address to maintain compatibility with older firmware.
+ */
+ if ( dbase == XGENE_SEC_GICV2_DIST_ADDR )
+ {
+ xgene_quirks |= PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI;
+ printk("Xen: WARNING: OLD X-Gene Firmware, disabling PIRQ EOI mode\n");
+ }
+}
+
static uint32_t xgene_storm_quirks(void)
{
- return PLATFORM_QUIRK_GIC_64K_STRIDE|PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI;
+ return xgene_quirks;
}
static int map_one_mmio(struct domain *d, const char *what,
reset_mask = XGENE_RESET_MASK;
reset_vals_valid = true;
+ xgene_check_pirq_eoi();
+
return 0;
}