drm/radeon/atpx: hybrid platforms use d3cold
[deliverable/linux.git] / drivers / irqchip / irq-gic-v2m.c
index 28f047c61baae62ffed6a07c9ef2f55cbd4de05b..ad0d2960b6644d0f71df271e81802d647e7905b7 100644 (file)
@@ -49,6 +49,9 @@
 /* APM X-Gene with GICv2m MSI_IIDR register value */
 #define XGENE_GICV2M_MSI_IIDR          0x06000170
 
+/* Broadcom NS2 GICv2m MSI_IIDR register value */
+#define BCM_NS2_GICV2M_MSI_IIDR                0x0000013f
+
 /* List of flags for specific v2m implementation */
 #define GICV2M_NEEDS_SPI_OFFSET                0x00000001
 
@@ -62,6 +65,7 @@ struct v2m_data {
        void __iomem *base;     /* GICv2m virt address */
        u32 spi_start;          /* The SPI number that MSIs start */
        u32 nr_spis;            /* The number of SPIs for MSIs */
+       u32 spi_offset;         /* offset to be subtracted from SPI number */
        unsigned long *bm;      /* MSI vector bitmap */
        u32 flags;              /* v2m flags for specific implementation */
 };
@@ -102,7 +106,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
        msg->data = data->hwirq;
 
        if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
-               msg->data -= v2m->spi_start;
+               msg->data -= v2m->spi_offset;
 }
 
 static struct irq_chip gicv2m_irq_chip = {
@@ -340,9 +344,20 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
         * different from the standard GICv2m implementation where
         * the MSI data is the absolute value within the range from
         * spi_start to (spi_start + num_spis).
+        *
+        * Broadom NS2 GICv2m implementation has an erratum where the MSI data
+        * is 'spi_number - 32'
         */
-       if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
+       switch (readl_relaxed(v2m->base + V2M_MSI_IIDR)) {
+       case XGENE_GICV2M_MSI_IIDR:
+               v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+               v2m->spi_offset = v2m->spi_start;
+               break;
+       case BCM_NS2_GICV2M_MSI_IIDR:
                v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+               v2m->spi_offset = 32;
+               break;
+       }
 
        v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
                          GFP_KERNEL);
This page took 0.035843 seconds and 5 git commands to generate.