Skip to content

Commit 0bdf062

Browse files
committed
Merge tag 'irq-core-2024-01-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq subsystem updates from Ingo Molnar: - Add support for the IA55 interrupt controller on RZ/G3S SoC's - Update/fix the Qualcom MPM Interrupt Controller driver's register enumeration within the somewhat exotic "RPM Message RAM" MMIO-mapped shared memory region that is used for other purposes as well - Clean up the Xtensa built-in Programmable Interrupt Controller driver (xtensa-pic) a bit * tag 'irq-core-2024-01-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/irq-xtensa-pic: Clean up irqchip/qcom-mpm: Support passing a slice of SRAM as reg space dt-bindings: interrupt-controller: mpm: Pass MSG RAM slice through phandle dt-bindings: interrupt-controller: renesas,rzg2l-irqc: Document RZ/G3S irqchip/renesas-rzg2l: Add support for suspend to RAM irqchip/renesas-rzg2l: Add macro to retrieve TITSR register offset based on register's index irqchip/renesas-rzg2l: Implement restriction when writing ISCR register irqchip/renesas-rzg2l: Document structure members irqchip/renesas-rzg2l: Align struct member names to tabs irqchip/renesas-rzg2l: Use tabs instead of spaces
2 parents f24dc33 + 69ffab9 commit 0bdf062

File tree

5 files changed

+158
-68
lines changed

5 files changed

+158
-68
lines changed

Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ properties:
2929
maxItems: 1
3030
description:
3131
Specifies the base address and size of vMPM registers in RPM MSG RAM.
32+
deprecated: true
33+
34+
qcom,rpm-msg-ram:
35+
$ref: /schemas/types.yaml#/definitions/phandle
36+
description:
37+
Phandle to the APSS MPM slice of the RPM Message RAM
3238

3339
interrupts:
3440
maxItems: 1
@@ -67,34 +73,46 @@ properties:
6773

6874
required:
6975
- compatible
70-
- reg
7176
- interrupts
7277
- mboxes
7378
- interrupt-controller
7479
- '#interrupt-cells'
7580
- qcom,mpm-pin-count
7681
- qcom,mpm-pin-map
82+
- qcom,rpm-msg-ram
7783

7884
additionalProperties: false
7985

8086
examples:
8187
- |
8288
#include <dt-bindings/interrupt-controller/arm-gic.h>
83-
mpm: interrupt-controller@45f01b8 {
84-
compatible = "qcom,mpm";
85-
interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
86-
reg = <0x45f01b8 0x1000>;
87-
mboxes = <&apcs_glb 1>;
88-
interrupt-controller;
89-
#interrupt-cells = <2>;
90-
interrupt-parent = <&intc>;
91-
qcom,mpm-pin-count = <96>;
92-
qcom,mpm-pin-map = <2 275>,
93-
<5 296>,
94-
<12 422>,
95-
<24 79>,
96-
<86 183>,
97-
<90 260>,
98-
<91 260>;
99-
#power-domain-cells = <0>;
89+
90+
remoteproc-rpm {
91+
compatible = "qcom,msm8998-rpm-proc", "qcom,rpm-proc";
92+
93+
glink-edge {
94+
compatible = "qcom,glink-rpm";
95+
96+
interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
97+
qcom,rpm-msg-ram = <&rpm_msg_ram>;
98+
mboxes = <&apcs_glb 0>;
99+
};
100+
101+
mpm: interrupt-controller {
102+
compatible = "qcom,mpm";
103+
qcom,rpm-msg-ram = <&apss_mpm>;
104+
interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
105+
mboxes = <&apcs_glb 1>;
106+
interrupt-controller;
107+
#interrupt-cells = <2>;
108+
interrupt-parent = <&intc>;
109+
qcom,mpm-pin-count = <96>;
110+
qcom,mpm-pin-map = <2 275>,
111+
<5 296>,
112+
<12 422>,
113+
<24 79>,
114+
<86 183>,
115+
<91 260>;
116+
#power-domain-cells = <0>;
117+
};
100118
};

Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ properties:
2626
- renesas,r9a07g043u-irqc # RZ/G2UL
2727
- renesas,r9a07g044-irqc # RZ/G2{L,LC}
2828
- renesas,r9a07g054-irqc # RZ/V2L
29+
- renesas,r9a08g045-irqc # RZ/G3S
2930
- const: renesas,rzg2l-irqc
3031

3132
'#interrupt-cells':
@@ -167,7 +168,9 @@ allOf:
167168
properties:
168169
compatible:
169170
contains:
170-
const: renesas,r9a07g043u-irqc
171+
enum:
172+
- renesas,r9a07g043u-irqc
173+
- renesas,r9a08g045-irqc
171174
then:
172175
properties:
173176
interrupts:

drivers/irqchip/irq-qcom-mpm.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/mailbox_client.h>
1515
#include <linux/module.h>
1616
#include <linux/of.h>
17+
#include <linux/of_address.h>
1718
#include <linux/of_platform.h>
1819
#include <linux/platform_device.h>
1920
#include <linux/pm_domain.h>
@@ -322,8 +323,10 @@ static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
322323
struct device *dev = &pdev->dev;
323324
struct irq_domain *parent_domain;
324325
struct generic_pm_domain *genpd;
326+
struct device_node *msgram_np;
325327
struct qcom_mpm_priv *priv;
326328
unsigned int pin_cnt;
329+
struct resource res;
327330
int i, irq;
328331
int ret;
329332

@@ -374,9 +377,26 @@ static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
374377

375378
raw_spin_lock_init(&priv->lock);
376379

377-
priv->base = devm_platform_ioremap_resource(pdev, 0);
378-
if (IS_ERR(priv->base))
379-
return PTR_ERR(priv->base);
380+
/* If we have a handle to an RPM message ram partition, use it. */
381+
msgram_np = of_parse_phandle(np, "qcom,rpm-msg-ram", 0);
382+
if (msgram_np) {
383+
ret = of_address_to_resource(msgram_np, 0, &res);
384+
if (ret) {
385+
of_node_put(msgram_np);
386+
return ret;
387+
}
388+
389+
/* Don't use devm_ioremap_resource, as we're accessing a shared region. */
390+
priv->base = devm_ioremap(dev, res.start, resource_size(&res));
391+
of_node_put(msgram_np);
392+
if (IS_ERR(priv->base))
393+
return PTR_ERR(priv->base);
394+
} else {
395+
/* Otherwise, fall back to simple MMIO. */
396+
priv->base = devm_platform_ioremap_resource(pdev, 0);
397+
if (IS_ERR(priv->base))
398+
return PTR_ERR(priv->base);
399+
}
380400

381401
for (i = 0; i < priv->reg_stride; i++) {
382402
qcom_mpm_write(priv, MPM_REG_ENABLE, i, 0);

drivers/irqchip/irq-renesas-rzg2l.c

Lines changed: 83 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/pm_runtime.h>
1919
#include <linux/reset.h>
2020
#include <linux/spinlock.h>
21+
#include <linux/syscore_ops.h>
2122

2223
#define IRQC_IRQ_START 1
2324
#define IRQC_IRQ_COUNT 8
@@ -28,8 +29,7 @@
2829
#define ISCR 0x10
2930
#define IITSR 0x14
3031
#define TSCR 0x20
31-
#define TITSR0 0x24
32-
#define TITSR1 0x28
32+
#define TITSR(n) (0x24 + (n) * 4)
3333
#define TITSR0_MAX_INT 16
3434
#define TITSEL_WIDTH 0x2
3535
#define TSSR(n) (0x30 + ((n) * 4))
@@ -53,15 +53,33 @@
5353
#define IITSR_IITSEL_EDGE_BOTH 3
5454
#define IITSR_IITSEL_MASK(n) IITSR_IITSEL((n), 3)
5555

56-
#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
57-
#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
56+
#define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
57+
#define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
5858

59-
struct rzg2l_irqc_priv {
60-
void __iomem *base;
61-
struct irq_fwspec fwspec[IRQC_NUM_IRQ];
62-
raw_spinlock_t lock;
59+
/**
60+
* struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume)
61+
* @iitsr: IITSR register
62+
* @titsr: TITSR registers
63+
*/
64+
struct rzg2l_irqc_reg_cache {
65+
u32 iitsr;
66+
u32 titsr[2];
6367
};
6468

69+
/**
70+
* struct rzg2l_irqc_priv - IRQ controller private data structure
71+
* @base: Controller's base address
72+
* @fwspec: IRQ firmware specific data
73+
* @lock: Lock to serialize access to hardware registers
74+
* @cache: Registers cache for suspend/resume
75+
*/
76+
static struct rzg2l_irqc_priv {
77+
void __iomem *base;
78+
struct irq_fwspec fwspec[IRQC_NUM_IRQ];
79+
raw_spinlock_t lock;
80+
struct rzg2l_irqc_reg_cache cache;
81+
} *rzg2l_irqc_data;
82+
6583
static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
6684
{
6785
return data->domain->host_data;
@@ -72,11 +90,17 @@ static void rzg2l_irq_eoi(struct irq_data *d)
7290
unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
7391
struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
7492
u32 bit = BIT(hw_irq);
75-
u32 reg;
93+
u32 iitsr, iscr;
7694

77-
reg = readl_relaxed(priv->base + ISCR);
78-
if (reg & bit)
79-
writel_relaxed(reg & ~bit, priv->base + ISCR);
95+
iscr = readl_relaxed(priv->base + ISCR);
96+
iitsr = readl_relaxed(priv->base + IITSR);
97+
98+
/*
99+
* ISCR can only be cleared if the type is falling-edge, rising-edge or
100+
* falling/rising-edge.
101+
*/
102+
if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq)))
103+
writel_relaxed(iscr & ~bit, priv->base + ISCR);
80104
}
81105

82106
static void rzg2l_tint_eoi(struct irq_data *d)
@@ -188,8 +212,7 @@ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
188212
struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
189213
unsigned int hwirq = irqd_to_hwirq(d);
190214
u32 titseln = hwirq - IRQC_TINT_START;
191-
u32 offset;
192-
u8 sense;
215+
u8 index, sense;
193216
u32 reg;
194217

195218
switch (type & IRQ_TYPE_SENSE_MASK) {
@@ -205,17 +228,17 @@ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
205228
return -EINVAL;
206229
}
207230

208-
offset = TITSR0;
231+
index = 0;
209232
if (titseln >= TITSR0_MAX_INT) {
210233
titseln -= TITSR0_MAX_INT;
211-
offset = TITSR1;
234+
index = 1;
212235
}
213236

214237
raw_spin_lock(&priv->lock);
215-
reg = readl_relaxed(priv->base + offset);
238+
reg = readl_relaxed(priv->base + TITSR(index));
216239
reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH));
217240
reg |= sense << (titseln * TITSEL_WIDTH);
218-
writel_relaxed(reg, priv->base + offset);
241+
writel_relaxed(reg, priv->base + TITSR(index));
219242
raw_spin_unlock(&priv->lock);
220243

221244
return 0;
@@ -236,6 +259,38 @@ static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type)
236259
return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
237260
}
238261

262+
static int rzg2l_irqc_irq_suspend(void)
263+
{
264+
struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
265+
void __iomem *base = rzg2l_irqc_data->base;
266+
267+
cache->iitsr = readl_relaxed(base + IITSR);
268+
for (u8 i = 0; i < 2; i++)
269+
cache->titsr[i] = readl_relaxed(base + TITSR(i));
270+
271+
return 0;
272+
}
273+
274+
static void rzg2l_irqc_irq_resume(void)
275+
{
276+
struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache;
277+
void __iomem *base = rzg2l_irqc_data->base;
278+
279+
/*
280+
* Restore only interrupt type. TSSRx will be restored at the
281+
* request of pin controller to avoid spurious interrupts due
282+
* to invalid PIN states.
283+
*/
284+
for (u8 i = 0; i < 2; i++)
285+
writel_relaxed(cache->titsr[i], base + TITSR(i));
286+
writel_relaxed(cache->iitsr, base + IITSR);
287+
}
288+
289+
static struct syscore_ops rzg2l_irqc_syscore_ops = {
290+
.suspend = rzg2l_irqc_irq_suspend,
291+
.resume = rzg2l_irqc_irq_resume,
292+
};
293+
239294
static const struct irq_chip irqc_chip = {
240295
.name = "rzg2l-irqc",
241296
.irq_eoi = rzg2l_irqc_eoi,
@@ -321,7 +376,6 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
321376
struct irq_domain *irq_domain, *parent_domain;
322377
struct platform_device *pdev;
323378
struct reset_control *resetn;
324-
struct rzg2l_irqc_priv *priv;
325379
int ret;
326380

327381
pdev = of_find_device_by_node(node);
@@ -334,15 +388,15 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
334388
return -ENODEV;
335389
}
336390

337-
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
338-
if (!priv)
391+
rzg2l_irqc_data = devm_kzalloc(&pdev->dev, sizeof(*rzg2l_irqc_data), GFP_KERNEL);
392+
if (!rzg2l_irqc_data)
339393
return -ENOMEM;
340394

341-
priv->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
342-
if (IS_ERR(priv->base))
343-
return PTR_ERR(priv->base);
395+
rzg2l_irqc_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
396+
if (IS_ERR(rzg2l_irqc_data->base))
397+
return PTR_ERR(rzg2l_irqc_data->base);
344398

345-
ret = rzg2l_irqc_parse_interrupts(priv, node);
399+
ret = rzg2l_irqc_parse_interrupts(rzg2l_irqc_data, node);
346400
if (ret) {
347401
dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
348402
return ret;
@@ -365,17 +419,19 @@ static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
365419
goto pm_disable;
366420
}
367421

368-
raw_spin_lock_init(&priv->lock);
422+
raw_spin_lock_init(&rzg2l_irqc_data->lock);
369423

370424
irq_domain = irq_domain_add_hierarchy(parent_domain, 0, IRQC_NUM_IRQ,
371425
node, &rzg2l_irqc_domain_ops,
372-
priv);
426+
rzg2l_irqc_data);
373427
if (!irq_domain) {
374428
dev_err(&pdev->dev, "failed to add irq domain\n");
375429
ret = -ENOMEM;
376430
goto pm_put;
377431
}
378432

433+
register_syscore_ops(&rzg2l_irqc_syscore_ops);
434+
379435
return 0;
380436

381437
pm_put:

0 commit comments

Comments
 (0)