diff options
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 42 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic-v3.h | 12 |
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); | |||
104 | enum gic_intid_range { | 104 | enum 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 | ||
138 | static inline int gic_irq_in_rdist(struct irq_data *d) | 141 | static 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 | ||
143 | static inline void __iomem *gic_dist_base(struct irq_data *d) | 147 | static 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 | ||
508 | static int gic_set_type(struct irq_data *d, unsigned int type) | 523 | static 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 | ||