Skip to content

Commit 76fe06c

Browse files
committed
Merge tag 'irqchip-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates from Marc Zyngier: - A few new drivers for the Loongson MIPS platform (HTVEC, PIC, MSI) - A cleanup of the __irq_domain_add() API - A cleanup of the IRQ simulator to actually use some of the irq infrastructure - Some fixes for the Sifive PLIC when used in a multi-controller context - Fixes for the GICv3 ITS to spread interrupts according to the load of each CPU, and to honor managed interrupts - Numerous cleanups and documentation fixes
2 parents 1d0326f + da10a4b commit 76fe06c

File tree

20 files changed

+1336
-220
lines changed

20 files changed

+1336
-220
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: "http://devicetree.org/schemas/interrupt-controller/loongson,htvec.yaml#"
5+
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
6+
7+
title: Loongson-3 HyperTransport Interrupt Vector Controller
8+
9+
maintainers:
10+
- Jiaxun Yang <[email protected]>
11+
12+
description:
13+
This interrupt controller is found in the Loongson-3 family of chips for
14+
receiving vectorized interrupts from PCH's interrupt controller.
15+
16+
properties:
17+
compatible:
18+
const: loongson,htvec-1.0
19+
20+
reg:
21+
maxItems: 1
22+
23+
interrupts:
24+
minItems: 1
25+
maxItems: 4
26+
description: Four parent interrupts that receive chained interrupts.
27+
28+
interrupt-controller: true
29+
30+
'#interrupt-cells':
31+
const: 1
32+
33+
required:
34+
- compatible
35+
- reg
36+
- interrupts
37+
- interrupt-controller
38+
- '#interrupt-cells'
39+
40+
additionalProperties: false
41+
42+
examples:
43+
- |
44+
#include <dt-bindings/interrupt-controller/irq.h>
45+
htvec: interrupt-controller@fb000080 {
46+
compatible = "loongson,htvec-1.0";
47+
reg = <0xfb000080 0x40>;
48+
interrupt-controller;
49+
#interrupt-cells = <1>;
50+
51+
interrupt-parent = <&liointc>;
52+
interrupts = <24 IRQ_TYPE_LEVEL_HIGH>,
53+
<25 IRQ_TYPE_LEVEL_HIGH>,
54+
<26 IRQ_TYPE_LEVEL_HIGH>,
55+
<27 IRQ_TYPE_LEVEL_HIGH>;
56+
};
57+
...
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: "http://devicetree.org/schemas/interrupt-controller/loongson,pch-msi.yaml#"
5+
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
6+
7+
title: Loongson PCH MSI Controller
8+
9+
maintainers:
10+
- Jiaxun Yang <[email protected]>
11+
12+
description:
13+
This interrupt controller is found in the Loongson LS7A family of PCH for
14+
transforming interrupts from PCIe MSI into HyperTransport vectorized
15+
interrupts.
16+
17+
properties:
18+
compatible:
19+
const: loongson,pch-msi-1.0
20+
21+
reg:
22+
maxItems: 1
23+
24+
loongson,msi-base-vec:
25+
description:
26+
u32 value of the base of parent HyperTransport vector allocated
27+
to PCH MSI.
28+
allOf:
29+
- $ref: "/schemas/types.yaml#/definitions/uint32"
30+
- minimum: 0
31+
maximum: 255
32+
33+
loongson,msi-num-vecs:
34+
description:
35+
u32 value of the number of parent HyperTransport vectors allocated
36+
to PCH MSI.
37+
allOf:
38+
- $ref: "/schemas/types.yaml#/definitions/uint32"
39+
- minimum: 1
40+
maximum: 256
41+
42+
msi-controller: true
43+
44+
required:
45+
- compatible
46+
- reg
47+
- msi-controller
48+
- loongson,msi-base-vec
49+
- loongson,msi-num-vecs
50+
51+
examples:
52+
- |
53+
#include <dt-bindings/interrupt-controller/irq.h>
54+
msi: msi-controller@2ff00000 {
55+
compatible = "loongson,pch-msi-1.0";
56+
reg = <0x2ff00000 0x4>;
57+
msi-controller;
58+
loongson,msi-base-vec = <64>;
59+
loongson,msi-num-vecs = <64>;
60+
interrupt-parent = <&htvec>;
61+
};
62+
...
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: "http://devicetree.org/schemas/interrupt-controller/loongson,pch-pic.yaml#"
5+
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
6+
7+
title: Loongson PCH PIC Controller
8+
9+
maintainers:
10+
- Jiaxun Yang <[email protected]>
11+
12+
description:
13+
This interrupt controller is found in the Loongson LS7A family of PCH for
14+
transforming interrupts from on-chip devices into HyperTransport vectorized
15+
interrupts.
16+
17+
properties:
18+
compatible:
19+
const: loongson,pch-pic-1.0
20+
21+
reg:
22+
maxItems: 1
23+
24+
loongson,pic-base-vec:
25+
description:
26+
u32 value of the base of parent HyperTransport vector allocated
27+
to PCH PIC.
28+
allOf:
29+
- $ref: "/schemas/types.yaml#/definitions/uint32"
30+
- minimum: 0
31+
maximum: 192
32+
33+
interrupt-controller: true
34+
35+
'#interrupt-cells':
36+
const: 2
37+
38+
required:
39+
- compatible
40+
- reg
41+
- loongson,pic-base-vec
42+
- interrupt-controller
43+
- '#interrupt-cells'
44+
45+
examples:
46+
- |
47+
#include <dt-bindings/interrupt-controller/irq.h>
48+
pic: interrupt-controller@10000000 {
49+
compatible = "loongson,pch-pic-1.0";
50+
reg = <0x10000000 0x400>;
51+
interrupt-controller;
52+
#interrupt-cells = <2>;
53+
loongson,pic-base-vec = <64>;
54+
interrupt-parent = <&htvec>;
55+
};
56+
...

drivers/base/platform-msi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
387387
*
388388
* @domain: The platform-msi domain
389389
* @virq: The base irq from which to perform the allocate operation
390-
* @nvec: How many interrupts to free from @virq
390+
* @nr_irqs: How many interrupts to free from @virq
391391
*
392392
* Return 0 on success, or an error code on failure. Must be called
393393
* with irq_domain_mutex held (which can only be done as part of a

drivers/gpio/gpio-mockup.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/interrupt.h>
1515
#include <linux/irq.h>
1616
#include <linux/irq_sim.h>
17+
#include <linux/irqdomain.h>
1718
#include <linux/module.h>
1819
#include <linux/platform_device.h>
1920
#include <linux/property.h>
@@ -48,7 +49,7 @@ struct gpio_mockup_line_status {
4849
struct gpio_mockup_chip {
4950
struct gpio_chip gc;
5051
struct gpio_mockup_line_status *lines;
51-
struct irq_sim irqsim;
52+
struct irq_domain *irq_sim_domain;
5253
struct dentry *dbg_dir;
5354
struct mutex lock;
5455
};
@@ -144,14 +145,12 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc,
144145
static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
145146
unsigned int offset, int value)
146147
{
148+
int curr, irq, irq_type, ret = 0;
147149
struct gpio_desc *desc;
148150
struct gpio_chip *gc;
149-
struct irq_sim *sim;
150-
int curr, irq, irq_type;
151151

152152
gc = &chip->gc;
153153
desc = &gc->gpiodev->descs[offset];
154-
sim = &chip->irqsim;
155154

156155
mutex_lock(&chip->lock);
157156

@@ -161,14 +160,28 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
161160
if (curr == value)
162161
goto out;
163162

164-
irq = irq_sim_irqnum(sim, offset);
163+
irq = irq_find_mapping(chip->irq_sim_domain, offset);
164+
if (!irq)
165+
/*
166+
* This is fine - it just means, nobody is listening
167+
* for interrupts on this line, otherwise
168+
* irq_create_mapping() would have been called from
169+
* the to_irq() callback.
170+
*/
171+
goto set_value;
172+
165173
irq_type = irq_get_trigger_type(irq);
166174

167175
if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
168-
(value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
169-
irq_sim_fire(sim, offset);
176+
(value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) {
177+
ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING,
178+
true);
179+
if (ret)
180+
goto out;
181+
}
170182
}
171183

184+
set_value:
172185
/* Change the value unless we're actively driving the line. */
173186
if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
174187
!test_bit(FLAG_IS_OUT, &desc->flags))
@@ -177,7 +190,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
177190
out:
178191
chip->lines[offset].pull = value;
179192
mutex_unlock(&chip->lock);
180-
return 0;
193+
return ret;
181194
}
182195

183196
static int gpio_mockup_set_config(struct gpio_chip *gc,
@@ -236,7 +249,7 @@ static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
236249
{
237250
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
238251

239-
return irq_sim_irqnum(&chip->irqsim, offset);
252+
return irq_create_mapping(chip->irq_sim_domain, offset);
240253
}
241254

242255
static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
@@ -389,6 +402,19 @@ static int gpio_mockup_name_lines(struct device *dev,
389402
return 0;
390403
}
391404

405+
static void gpio_mockup_dispose_mappings(void *data)
406+
{
407+
struct gpio_mockup_chip *chip = data;
408+
struct gpio_chip *gc = &chip->gc;
409+
int i, irq;
410+
411+
for (i = 0; i < gc->ngpio; i++) {
412+
irq = irq_find_mapping(chip->irq_sim_domain, i);
413+
if (irq)
414+
irq_dispose_mapping(irq);
415+
}
416+
}
417+
392418
static int gpio_mockup_probe(struct platform_device *pdev)
393419
{
394420
struct gpio_mockup_chip *chip;
@@ -456,8 +482,13 @@ static int gpio_mockup_probe(struct platform_device *pdev)
456482
return rv;
457483
}
458484

459-
rv = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio);
460-
if (rv < 0)
485+
chip->irq_sim_domain = devm_irq_domain_create_sim(dev, NULL,
486+
gc->ngpio);
487+
if (IS_ERR(chip->irq_sim_domain))
488+
return PTR_ERR(chip->irq_sim_domain);
489+
490+
rv = devm_add_action_or_reset(dev, gpio_mockup_dispose_mappings, chip);
491+
if (rv)
461492
return rv;
462493

463494
rv = devm_gpiochip_add_data(dev, &chip->gc, chip);

drivers/iio/dummy/iio_dummy_evgen.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ struct iio_dummy_eventgen {
3737
struct iio_dummy_regs regs[IIO_EVENTGEN_NO];
3838
struct mutex lock;
3939
bool inuse[IIO_EVENTGEN_NO];
40-
struct irq_sim irq_sim;
41-
int base;
40+
struct irq_domain *irq_sim_domain;
4241
};
4342

4443
/* We can only ever have one instance of this 'device' */
@@ -52,13 +51,14 @@ static int iio_dummy_evgen_create(void)
5251
if (!iio_evgen)
5352
return -ENOMEM;
5453

55-
ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
56-
if (ret < 0) {
54+
iio_evgen->irq_sim_domain = irq_domain_create_sim(NULL,
55+
IIO_EVENTGEN_NO);
56+
if (IS_ERR(iio_evgen->irq_sim_domain)) {
57+
ret = PTR_ERR(iio_evgen->irq_sim_domain);
5758
kfree(iio_evgen);
5859
return ret;
5960
}
6061

61-
iio_evgen->base = irq_sim_irqnum(&iio_evgen->irq_sim, 0);
6262
mutex_init(&iio_evgen->lock);
6363

6464
return 0;
@@ -80,7 +80,7 @@ int iio_dummy_evgen_get_irq(void)
8080
mutex_lock(&iio_evgen->lock);
8181
for (i = 0; i < IIO_EVENTGEN_NO; i++) {
8282
if (!iio_evgen->inuse[i]) {
83-
ret = irq_sim_irqnum(&iio_evgen->irq_sim, i);
83+
ret = irq_create_mapping(iio_evgen->irq_sim_domain, i);
8484
iio_evgen->inuse[i] = true;
8585
break;
8686
}
@@ -101,21 +101,27 @@ EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq);
101101
*/
102102
void iio_dummy_evgen_release_irq(int irq)
103103
{
104+
struct irq_data *irqd = irq_get_irq_data(irq);
105+
104106
mutex_lock(&iio_evgen->lock);
105-
iio_evgen->inuse[irq - iio_evgen->base] = false;
107+
iio_evgen->inuse[irqd_to_hwirq(irqd)] = false;
108+
irq_dispose_mapping(irq);
106109
mutex_unlock(&iio_evgen->lock);
107110
}
108111
EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq);
109112

110113
struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq)
111114
{
112-
return &iio_evgen->regs[irq - iio_evgen->base];
115+
struct irq_data *irqd = irq_get_irq_data(irq);
116+
117+
return &iio_evgen->regs[irqd_to_hwirq(irqd)];
118+
113119
}
114120
EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs);
115121

116122
static void iio_dummy_evgen_free(void)
117123
{
118-
irq_sim_fini(&iio_evgen->irq_sim);
124+
irq_domain_remove_sim(iio_evgen->irq_sim_domain);
119125
kfree(iio_evgen);
120126
}
121127

@@ -131,7 +137,7 @@ static ssize_t iio_evgen_poke(struct device *dev,
131137
{
132138
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
133139
unsigned long event;
134-
int ret;
140+
int ret, irq;
135141

136142
ret = kstrtoul(buf, 10, &event);
137143
if (ret)
@@ -140,7 +146,10 @@ static ssize_t iio_evgen_poke(struct device *dev,
140146
iio_evgen->regs[this_attr->address].reg_id = this_attr->address;
141147
iio_evgen->regs[this_attr->address].reg_data = event;
142148

143-
irq_sim_fire(&iio_evgen->irq_sim, this_attr->address);
149+
irq = irq_find_mapping(iio_evgen->irq_sim_domain, this_attr->address);
150+
ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true);
151+
if (ret)
152+
return ret;
144153

145154
return len;
146155
}

0 commit comments

Comments
 (0)