summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2019-07-18 08:19:25 -0400
committerMarc Zyngier <maz@kernel.org>2019-08-20 05:23:35 -0400
commit5f51f803826e4f4aedff415ddaf14efa707be5a7 (patch)
tree0687c293d66d687124ea8c0555ccaec9e233278a
parent4b049063e0bcbfd302f6bf867de9d55a965d622e (diff)
irqchip/gic-v3: Add EPPI range support
Expand the pre-existing PPI support to be able to deal with the Extended PPI range (EPPI). This includes obtaining the number of PPIs from each individual redistributor, and compute the minimum set (just in case someone builds something really clever...). Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--drivers/irqchip/irq-gic-v3.c42
-rw-r--r--include/linux/irqchip/arm-gic-v3.h12
2 files changed, 47 insertions, 7 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index f5dbdbf3e98d..d3727e877872 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -104,6 +104,7 @@ static DEFINE_PER_CPU(bool, has_rss);
104enum gic_intid_range { 104enum gic_intid_range {
105 PPI_RANGE, 105 PPI_RANGE,
106 SPI_RANGE, 106 SPI_RANGE,
107 EPPI_RANGE,
107 ESPI_RANGE, 108 ESPI_RANGE,
108 LPI_RANGE, 109 LPI_RANGE,
109 __INVALID_RANGE__ 110 __INVALID_RANGE__
@@ -116,6 +117,8 @@ static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
116 return PPI_RANGE; 117 return PPI_RANGE;
117 case 32 ... 1019: 118 case 32 ... 1019:
118 return SPI_RANGE; 119 return SPI_RANGE;
120 case EPPI_BASE_INTID ... (EPPI_BASE_INTID + 63):
121 return EPPI_RANGE;
119 case ESPI_BASE_INTID ... (ESPI_BASE_INTID + 1023): 122 case ESPI_BASE_INTID ... (ESPI_BASE_INTID + 1023):
120 return ESPI_RANGE; 123 return ESPI_RANGE;
121 case 8192 ... GENMASK(23, 0): 124 case 8192 ... GENMASK(23, 0):
@@ -137,13 +140,15 @@ static inline unsigned int gic_irq(struct irq_data *d)
137 140
138static inline int gic_irq_in_rdist(struct irq_data *d) 141static inline int gic_irq_in_rdist(struct irq_data *d)
139{ 142{
140 return get_intid_range(d) == PPI_RANGE; 143 enum gic_intid_range range = get_intid_range(d);
144 return range == PPI_RANGE || range == EPPI_RANGE;
141} 145}
142 146
143static inline void __iomem *gic_dist_base(struct irq_data *d) 147static inline void __iomem *gic_dist_base(struct irq_data *d)
144{ 148{
145 switch (get_intid_range(d)) { 149 switch (get_intid_range(d)) {
146 case PPI_RANGE: 150 case PPI_RANGE:
151 case EPPI_RANGE:
147 /* SGI+PPI -> SGI_base for this CPU */ 152 /* SGI+PPI -> SGI_base for this CPU */
148 return gic_data_rdist_sgi_base(); 153 return gic_data_rdist_sgi_base();
149 154
@@ -242,6 +247,14 @@ static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
242 case SPI_RANGE: 247 case SPI_RANGE:
243 *index = d->hwirq; 248 *index = d->hwirq;
244 return offset; 249 return offset;
250 case EPPI_RANGE:
251 /*
252 * Contrary to the ESPI range, the EPPI range is contiguous
253 * to the PPI range in the registers, so let's adjust the
254 * displacement accordingly. Consistency is overrated.
255 */
256 *index = d->hwirq - EPPI_BASE_INTID + 32;
257 return offset;
245 case ESPI_RANGE: 258 case ESPI_RANGE:
246 *index = d->hwirq - ESPI_BASE_INTID; 259 *index = d->hwirq - ESPI_BASE_INTID;
247 switch (offset) { 260 switch (offset) {
@@ -414,6 +427,8 @@ static u32 gic_get_ppi_index(struct irq_data *d)
414 switch (get_intid_range(d)) { 427 switch (get_intid_range(d)) {
415 case PPI_RANGE: 428 case PPI_RANGE:
416 return d->hwirq - 16; 429 return d->hwirq - 16;
430 case EPPI_RANGE:
431 return d->hwirq - EPPI_BASE_INTID + 16;
417 default: 432 default:
418 unreachable(); 433 unreachable();
419 } 434 }
@@ -507,6 +522,7 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
507 522
508static int gic_set_type(struct irq_data *d, unsigned int type) 523static int gic_set_type(struct irq_data *d, unsigned int type)
509{ 524{
525 enum gic_intid_range range;
510 unsigned int irq = gic_irq(d); 526 unsigned int irq = gic_irq(d);
511 void (*rwp_wait)(void); 527 void (*rwp_wait)(void);
512 void __iomem *base; 528 void __iomem *base;
@@ -517,9 +533,11 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
517 if (irq < 16) 533 if (irq < 16)
518 return -EINVAL; 534 return -EINVAL;
519 535
536 range = get_intid_range(d);
537
520 /* SPIs have restrictions on the supported types */ 538 /* SPIs have restrictions on the supported types */
521 if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && 539 if ((range == SPI_RANGE || range == ESPI_RANGE) &&
522 type != IRQ_TYPE_EDGE_RISING) 540 type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
523 return -EINVAL; 541 return -EINVAL;
524 542
525 if (gic_irq_in_rdist(d)) { 543 if (gic_irq_in_rdist(d)) {
@@ -533,9 +551,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
533 offset = convert_offset_index(d, GICD_ICFGR, &index); 551 offset = convert_offset_index(d, GICD_ICFGR, &index);
534 552
535 ret = gic_configure_irq(index, type, base + offset, rwp_wait); 553 ret = gic_configure_irq(index, type, base + offset, rwp_wait);
536 if (ret && irq < 32) { 554 if (ret && (range == PPI_RANGE || range == EPPI_RANGE)) {
537 /* Misconfigured PPIs are usually not fatal */ 555 /* Misconfigured PPIs are usually not fatal */
538 pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16); 556 pr_warn("GIC: PPI INTID%d is secure or misconfigured\n", irq);
539 ret = 0; 557 ret = 0;
540 } 558 }
541 559
@@ -833,7 +851,7 @@ static int __gic_update_rdist_properties(struct redist_region *region,
833 u64 typer = gic_read_typer(ptr + GICR_TYPER); 851 u64 typer = gic_read_typer(ptr + GICR_TYPER);
834 gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS); 852 gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
835 gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS); 853 gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
836 gic_data.ppi_nr = 16; 854 gic_data.ppi_nr = min(GICR_TYPER_NR_PPIS(typer), gic_data.ppi_nr);
837 855
838 return 1; 856 return 1;
839} 857}
@@ -1222,6 +1240,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
1222 1240
1223 switch (__get_intid_range(hw)) { 1241 switch (__get_intid_range(hw)) {
1224 case PPI_RANGE: 1242 case PPI_RANGE:
1243 case EPPI_RANGE:
1225 irq_set_percpu_devid(irq); 1244 irq_set_percpu_devid(irq);
1226 irq_domain_set_info(d, irq, hw, chip, d->host_data, 1245 irq_domain_set_info(d, irq, hw, chip, d->host_data,
1227 handle_percpu_devid_irq, NULL, NULL); 1246 handle_percpu_devid_irq, NULL, NULL);
@@ -1266,15 +1285,24 @@ static int gic_irq_domain_translate(struct irq_domain *d,
1266 *hwirq = fwspec->param[1] + 32; 1285 *hwirq = fwspec->param[1] + 32;
1267 break; 1286 break;
1268 case 1: /* PPI */ 1287 case 1: /* PPI */
1269 case GIC_IRQ_TYPE_PARTITION:
1270 *hwirq = fwspec->param[1] + 16; 1288 *hwirq = fwspec->param[1] + 16;
1271 break; 1289 break;
1272 case 2: /* ESPI */ 1290 case 2: /* ESPI */
1273 *hwirq = fwspec->param[1] + ESPI_BASE_INTID; 1291 *hwirq = fwspec->param[1] + ESPI_BASE_INTID;
1274 break; 1292 break;
1293 case 3: /* EPPI */
1294 *hwirq = fwspec->param[1] + EPPI_BASE_INTID;
1295 break;
1275 case GIC_IRQ_TYPE_LPI: /* LPI */ 1296 case GIC_IRQ_TYPE_LPI: /* LPI */
1276 *hwirq = fwspec->param[1]; 1297 *hwirq = fwspec->param[1];
1277 break; 1298 break;
1299 case GIC_IRQ_TYPE_PARTITION:
1300 *hwirq = fwspec->param[1];
1301 if (fwspec->param[1] >= 16)
1302 *hwirq += EPPI_BASE_INTID - 16;
1303 else
1304 *hwirq += 16;
1305 break;
1278 default: 1306 default:
1279 return -EINVAL; 1307 return -EINVAL;
1280 } 1308 }
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c523bf1faa55..9ec3349dee04 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -124,6 +124,18 @@
124 124
125#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff) 125#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
126 126
127#define EPPI_BASE_INTID 1056
128
129#define GICR_TYPER_NR_PPIS(r) \
130 ({ \
131 unsigned int __ppinum = ((r) >> 27) & 0x1f; \
132 unsigned int __nr_ppis = 16; \
133 if (__ppinum == 1 || __ppinum == 2) \
134 __nr_ppis += __ppinum * 32; \
135 \
136 __nr_ppis; \
137 })
138
127#define GICR_WAKER_ProcessorSleep (1U << 1) 139#define GICR_WAKER_ProcessorSleep (1U << 1)
128#define GICR_WAKER_ChildrenAsleep (1U << 2) 140#define GICR_WAKER_ChildrenAsleep (1U << 2)
129 141