enum gic_intid_range {
        PPI_RANGE,
        SPI_RANGE,
+       EPPI_RANGE,
        ESPI_RANGE,
        LPI_RANGE,
        __INVALID_RANGE__
                return PPI_RANGE;
        case 32 ... 1019:
                return SPI_RANGE;
+       case EPPI_BASE_INTID ... (EPPI_BASE_INTID + 63):
+               return EPPI_RANGE;
        case ESPI_BASE_INTID ... (ESPI_BASE_INTID + 1023):
                return ESPI_RANGE;
        case 8192 ... GENMASK(23, 0):
 
 static inline int gic_irq_in_rdist(struct irq_data *d)
 {
-       return get_intid_range(d) == PPI_RANGE;
+       enum gic_intid_range range = get_intid_range(d);
+       return range == PPI_RANGE || range == EPPI_RANGE;
 }
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
        switch (get_intid_range(d)) {
        case PPI_RANGE:
+       case EPPI_RANGE:
                /* SGI+PPI -> SGI_base for this CPU */
                return gic_data_rdist_sgi_base();
 
        case SPI_RANGE:
                *index = d->hwirq;
                return offset;
+       case EPPI_RANGE:
+               /*
+                * Contrary to the ESPI range, the EPPI range is contiguous
+                * to the PPI range in the registers, so let's adjust the
+                * displacement accordingly. Consistency is overrated.
+                */
+               *index = d->hwirq - EPPI_BASE_INTID + 32;
+               return offset;
        case ESPI_RANGE:
                *index = d->hwirq - ESPI_BASE_INTID;
                switch (offset) {
        switch (get_intid_range(d)) {
        case PPI_RANGE:
                return d->hwirq - 16;
+       case EPPI_RANGE:
+               return d->hwirq - EPPI_BASE_INTID + 16;
        default:
                unreachable();
        }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
+       enum gic_intid_range range;
        unsigned int irq = gic_irq(d);
        void (*rwp_wait)(void);
        void __iomem *base;
        if (irq < 16)
                return -EINVAL;
 
+       range = get_intid_range(d);
+
        /* SPIs have restrictions on the supported types */
-       if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
-                        type != IRQ_TYPE_EDGE_RISING)
+       if ((range == SPI_RANGE || range == ESPI_RANGE) &&
+           type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
                return -EINVAL;
 
        if (gic_irq_in_rdist(d)) {
        offset = convert_offset_index(d, GICD_ICFGR, &index);
 
        ret = gic_configure_irq(index, type, base + offset, rwp_wait);
-       if (ret && irq < 32) {
+       if (ret && (range == PPI_RANGE || range == EPPI_RANGE)) {
                /* Misconfigured PPIs are usually not fatal */
-               pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
+               pr_warn("GIC: PPI INTID%d is secure or misconfigured\n", irq);
                ret = 0;
        }
 
        u64 typer = gic_read_typer(ptr + GICR_TYPER);
        gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
        gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
-       gic_data.ppi_nr = 16;
+       gic_data.ppi_nr = min(GICR_TYPER_NR_PPIS(typer), gic_data.ppi_nr);
 
        return 1;
 }
 
        switch (__get_intid_range(hw)) {
        case PPI_RANGE:
+       case EPPI_RANGE:
                irq_set_percpu_devid(irq);
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_percpu_devid_irq, NULL, NULL);
                        *hwirq = fwspec->param[1] + 32;
                        break;
                case 1:                 /* PPI */
-               case GIC_IRQ_TYPE_PARTITION:
                        *hwirq = fwspec->param[1] + 16;
                        break;
                case 2:                 /* ESPI */
                        *hwirq = fwspec->param[1] + ESPI_BASE_INTID;
                        break;
+               case 3:                 /* EPPI */
+                       *hwirq = fwspec->param[1] + EPPI_BASE_INTID;
+                       break;
                case GIC_IRQ_TYPE_LPI:  /* LPI */
                        *hwirq = fwspec->param[1];
                        break;
+               case GIC_IRQ_TYPE_PARTITION:
+                       *hwirq = fwspec->param[1];
+                       if (fwspec->param[1] >= 16)
+                               *hwirq += EPPI_BASE_INTID - 16;
+                       else
+                               *hwirq += 16;
+                       break;
                default:
                        return -EINVAL;
                }