Skip to content

Commit 129993d

Browse files
committed
Merge tag 'irq-for-riscv-02-23-24' into irq/msi
Pick up RISCV INTC changes to handle conflicts with the AIA updates. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2 parents 5aa3c0c + f4cc33e commit 129993d

File tree

2 files changed

+87
-13
lines changed

2 files changed

+87
-13
lines changed

drivers/irqchip/irq-riscv-intc.c

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,19 @@
1717
#include <linux/module.h>
1818
#include <linux/of.h>
1919
#include <linux/smp.h>
20+
#include <linux/soc/andes/irq.h>
2021

2122
static struct irq_domain *intc_domain;
23+
static unsigned int riscv_intc_nr_irqs __ro_after_init = BITS_PER_LONG;
24+
static unsigned int riscv_intc_custom_base __ro_after_init = BITS_PER_LONG;
25+
static unsigned int riscv_intc_custom_nr_irqs __ro_after_init;
2226

2327
static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
2428
{
2529
unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;
2630

27-
if (unlikely(cause >= BITS_PER_LONG))
28-
panic("unexpected interrupt cause");
29-
30-
generic_handle_domain_irq(intc_domain, cause);
31+
if (generic_handle_domain_irq(intc_domain, cause))
32+
pr_warn_ratelimited("Failed to handle interrupt (cause: %ld)\n", cause);
3133
}
3234

3335
/*
@@ -47,6 +49,31 @@ static void riscv_intc_irq_unmask(struct irq_data *d)
4749
csr_set(CSR_IE, BIT(d->hwirq));
4850
}
4951

52+
static void andes_intc_irq_mask(struct irq_data *d)
53+
{
54+
/*
55+
* Andes specific S-mode local interrupt causes (hwirq)
56+
* are defined as (256 + n) and controlled by n-th bit
57+
* of SLIE.
58+
*/
59+
unsigned int mask = BIT(d->hwirq % BITS_PER_LONG);
60+
61+
if (d->hwirq < ANDES_SLI_CAUSE_BASE)
62+
csr_clear(CSR_IE, mask);
63+
else
64+
csr_clear(ANDES_CSR_SLIE, mask);
65+
}
66+
67+
static void andes_intc_irq_unmask(struct irq_data *d)
68+
{
69+
unsigned int mask = BIT(d->hwirq % BITS_PER_LONG);
70+
71+
if (d->hwirq < ANDES_SLI_CAUSE_BASE)
72+
csr_set(CSR_IE, mask);
73+
else
74+
csr_set(ANDES_CSR_SLIE, mask);
75+
}
76+
5077
static void riscv_intc_irq_eoi(struct irq_data *d)
5178
{
5279
/*
@@ -70,12 +97,21 @@ static struct irq_chip riscv_intc_chip = {
7097
.irq_eoi = riscv_intc_irq_eoi,
7198
};
7299

100+
static struct irq_chip andes_intc_chip = {
101+
.name = "RISC-V INTC",
102+
.irq_mask = andes_intc_irq_mask,
103+
.irq_unmask = andes_intc_irq_unmask,
104+
.irq_eoi = riscv_intc_irq_eoi,
105+
};
106+
73107
static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
74108
irq_hw_number_t hwirq)
75109
{
110+
struct irq_chip *chip = d->host_data;
111+
76112
irq_set_percpu_devid(irq);
77-
irq_domain_set_info(d, irq, hwirq, &riscv_intc_chip, d->host_data,
78-
handle_percpu_devid_irq, NULL, NULL);
113+
irq_domain_set_info(d, irq, hwirq, chip, NULL, handle_percpu_devid_irq,
114+
NULL, NULL);
79115

80116
return 0;
81117
}
@@ -93,6 +129,14 @@ static int riscv_intc_domain_alloc(struct irq_domain *domain,
93129
if (ret)
94130
return ret;
95131

132+
/*
133+
* Only allow hwirq for which we have corresponding standard or
134+
* custom interrupt enable register.
135+
*/
136+
if ((hwirq >= riscv_intc_nr_irqs && hwirq < riscv_intc_custom_base) ||
137+
(hwirq >= riscv_intc_custom_base + riscv_intc_custom_nr_irqs))
138+
return -EINVAL;
139+
96140
for (i = 0; i < nr_irqs; i++) {
97141
ret = riscv_intc_domain_map(domain, virq + i, hwirq + i);
98142
if (ret)
@@ -113,12 +157,12 @@ static struct fwnode_handle *riscv_intc_hwnode(void)
113157
return intc_domain->fwnode;
114158
}
115159

116-
static int __init riscv_intc_init_common(struct fwnode_handle *fn)
160+
static int __init riscv_intc_init_common(struct fwnode_handle *fn,
161+
struct irq_chip *chip)
117162
{
118163
int rc;
119164

120-
intc_domain = irq_domain_create_linear(fn, BITS_PER_LONG,
121-
&riscv_intc_domain_ops, NULL);
165+
intc_domain = irq_domain_create_tree(fn, &riscv_intc_domain_ops, chip);
122166
if (!intc_domain) {
123167
pr_err("unable to add IRQ domain\n");
124168
return -ENXIO;
@@ -132,16 +176,21 @@ static int __init riscv_intc_init_common(struct fwnode_handle *fn)
132176

133177
riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
134178

135-
pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
179+
pr_info("%d local interrupts mapped\n", riscv_intc_nr_irqs);
180+
if (riscv_intc_custom_nr_irqs) {
181+
pr_info("%d custom local interrupts mapped\n",
182+
riscv_intc_custom_nr_irqs);
183+
}
136184

137185
return 0;
138186
}
139187

140188
static int __init riscv_intc_init(struct device_node *node,
141189
struct device_node *parent)
142190
{
143-
int rc;
191+
struct irq_chip *chip = &riscv_intc_chip;
144192
unsigned long hartid;
193+
int rc;
145194

146195
rc = riscv_of_parent_hartid(node, &hartid);
147196
if (rc < 0) {
@@ -166,10 +215,17 @@ static int __init riscv_intc_init(struct device_node *node,
166215
return 0;
167216
}
168217

169-
return riscv_intc_init_common(of_node_to_fwnode(node));
218+
if (of_device_is_compatible(node, "andestech,cpu-intc")) {
219+
riscv_intc_custom_base = ANDES_SLI_CAUSE_BASE;
220+
riscv_intc_custom_nr_irqs = ANDES_RV_IRQ_LAST;
221+
chip = &andes_intc_chip;
222+
}
223+
224+
return riscv_intc_init_common(of_node_to_fwnode(node), chip);
170225
}
171226

172227
IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
228+
IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);
173229

174230
#ifdef CONFIG_ACPI
175231

@@ -196,7 +252,7 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
196252
return -ENOMEM;
197253
}
198254

199-
return riscv_intc_init_common(fn);
255+
return riscv_intc_init_common(fn, &riscv_intc_chip);
200256
}
201257

202258
IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,

include/linux/soc/andes/irq.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2023 Andes Technology Corporation
4+
*/
5+
#ifndef __ANDES_IRQ_H
6+
#define __ANDES_IRQ_H
7+
8+
/* Andes PMU irq number */
9+
#define ANDES_RV_IRQ_PMOVI 18
10+
#define ANDES_RV_IRQ_LAST ANDES_RV_IRQ_PMOVI
11+
#define ANDES_SLI_CAUSE_BASE 256
12+
13+
/* Andes PMU related registers */
14+
#define ANDES_CSR_SLIE 0x9c4
15+
#define ANDES_CSR_SLIP 0x9c5
16+
#define ANDES_CSR_SCOUNTEROF 0x9d4
17+
18+
#endif /* __ANDES_IRQ_H */

0 commit comments

Comments
 (0)