/* Our default, arbitrary priority value. Linux only uses one anyway. */
 #define DEFAULT_PMR_VALUE      0xf0
 
+enum gic_intid_range {
+       PPI_RANGE,
+       SPI_RANGE,
+       LPI_RANGE,
+       __INVALID_RANGE__
+};
+
+static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
+{
+       switch (hwirq) {
+       case 16 ... 31:
+               return PPI_RANGE;
+       case 32 ... 1019:
+               return SPI_RANGE;
+       case 8192 ... GENMASK(23, 0):
+               return LPI_RANGE;
+       default:
+               return __INVALID_RANGE__;
+       }
+}
+
+static enum gic_intid_range get_intid_range(struct irq_data *d)
+{
+       return __get_intid_range(d->hwirq);
+}
+
 static inline unsigned int gic_irq(struct irq_data *d)
 {
        return d->hwirq;
 
 static inline int gic_irq_in_rdist(struct irq_data *d)
 {
-       return gic_irq(d) < 32;
+       return get_intid_range(d) == PPI_RANGE;
 }
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
-       if (gic_irq_in_rdist(d))        /* SGI+PPI -> SGI_base for this CPU */
+       switch (get_intid_range(d)) {
+       case PPI_RANGE:
+               /* SGI+PPI -> SGI_base for this CPU */
                return gic_data_rdist_sgi_base();
 
-       if (d->hwirq <= 1023)           /* SPI -> dist_base */
+       case SPI_RANGE:
+               /* SPI -> dist_base */
                return gic_data.dist_base;
 
-       return NULL;
+       default:
+               return NULL;
+       }
 }
 
 static void gic_do_wait_for_rwp(void __iomem *base)
 /*
  * Routines to disable, enable, EOI and route interrupts
  */
+static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
+{
+       switch (get_intid_range(d)) {
+       case PPI_RANGE:
+       case SPI_RANGE:
+               *index = d->hwirq;
+               return offset;
+       default:
+               break;
+       }
+
+       WARN_ON(1);
+       *index = d->hwirq;
+       return offset;
+}
+
 static int gic_peek_irq(struct irq_data *d, u32 offset)
 {
-       u32 mask = 1 << (gic_irq(d) % 32);
        void __iomem *base;
+       u32 index, mask;
+
+       offset = convert_offset_index(d, offset, &index);
+       mask = 1 << (index % 32);
 
        if (gic_irq_in_rdist(d))
                base = gic_data_rdist_sgi_base();
        else
                base = gic_data.dist_base;
 
-       return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
+       return !!(readl_relaxed(base + offset + (index / 32) * 4) & mask);
 }
 
 static void gic_poke_irq(struct irq_data *d, u32 offset)
 {
-       u32 mask = 1 << (gic_irq(d) % 32);
        void (*rwp_wait)(void);
        void __iomem *base;
+       u32 index, mask;
+
+       offset = convert_offset_index(d, offset, &index);
+       mask = 1 << (index % 32);
 
        if (gic_irq_in_rdist(d)) {
                base = gic_data_rdist_sgi_base();
                rwp_wait = gic_dist_wait_for_rwp;
        }
 
-       writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
+       writel_relaxed(mask, base + offset + (index / 32) * 4);
        rwp_wait();
 }
 
 static void gic_irq_set_prio(struct irq_data *d, u8 prio)
 {
        void __iomem *base = gic_dist_base(d);
+       u32 offset, index;
 
-       writeb_relaxed(prio, base + GICD_IPRIORITYR + gic_irq(d));
+       offset = convert_offset_index(d, GICD_IPRIORITYR, &index);
+
+       writeb_relaxed(prio, base + offset + index);
 }
 
 static int gic_irq_nmi_setup(struct irq_data *d)
        unsigned int irq = gic_irq(d);
        void (*rwp_wait)(void);
        void __iomem *base;
+       u32 offset, index;
        int ret;
 
        /* Interrupt configuration for SGIs can't be changed */
                rwp_wait = gic_dist_wait_for_rwp;
        }
 
+       offset = convert_offset_index(d, GICD_ICFGR, &index);
 
-       ret = gic_configure_irq(irq, type, base + GICD_ICFGR, rwp_wait);
+       ret = gic_configure_irq(index, type, base + offset, rwp_wait);
        if (ret && irq < 32) {
                /* Misconfigured PPIs are usually not fatal */
                pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
                            bool force)
 {
        unsigned int cpu;
+       u32 offset, index;
        void __iomem *reg;
        int enabled;
        u64 val;
        if (enabled)
                gic_mask_irq(d);
 
-       reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
+       offset = convert_offset_index(d, GICD_IROUTER, &index);
+       reg = gic_dist_base(d) + offset + (index * 8);
        val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
 
        gic_write_irouter(val, reg);
        if (static_branch_likely(&supports_deactivate_key))
                chip = &gic_eoimode1_chip;
 
-       /* SGIs are private to the core kernel */
-       if (hw < 16)
-               return -EPERM;
-       /* Nothing here */
-       if (hw >= gic_data.irq_nr && hw < 8192)
-               return -EPERM;
-       /* Off limits */
-       if (hw >= GIC_ID_NR)
-               return -EPERM;
-
-       /* PPIs */
-       if (hw < 32) {
+       switch (__get_intid_range(hw)) {
+       case PPI_RANGE:
                irq_set_percpu_devid(irq);
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_percpu_devid_irq, NULL, NULL);
                irq_set_status_flags(irq, IRQ_NOAUTOEN);
-       }
-       /* SPIs */
-       if (hw >= 32 && hw < gic_data.irq_nr) {
+               break;
+
+       case SPI_RANGE:
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
                irq_set_probe(irq);
                irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
-       }
-       /* LPIs */
-       if (hw >= 8192 && hw < GIC_ID_NR) {
+               break;
+
+       case LPI_RANGE:
                if (!gic_dist_supports_lpis())
                        return -EPERM;
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
+               break;
+
+       default:
+               return -EPERM;
        }
 
        return 0;