Skip to content

Commit 86cd430

Browse files
aspeedtechKAGA-KOKO
authored andcommitted
irqchip/aspeed-scu-ic: Refactor driver to support variant-based initialization
The SCU IC driver handles each AST2600 instance with separate initialization functions and hardcoded register definitions, which is inflexible and creates duplicated code. Consolidate the implementation by introducing a variant-based structure, selected via compatible string, and use a unified init path and MMIO access via of_iomap(). This simplifies the code and prepares for upcoming SoCs like AST2700, which require split register handling. [ tglx: Cleaned up coding style and massaged change log ] Signed-off-by: Ryan Chen <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent a186120 commit 86cd430

File tree

1 file changed

+63
-94
lines changed

1 file changed

+63
-94
lines changed

drivers/irqchip/irq-aspeed-scu-ic.c

Lines changed: 63 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,56 @@
77
*/
88

99
#include <linux/bitops.h>
10+
#include <linux/io.h>
1011
#include <linux/irq.h>
1112
#include <linux/irqchip.h>
1213
#include <linux/irqchip/chained_irq.h>
1314
#include <linux/irqdomain.h>
14-
#include <linux/mfd/syscon.h>
15+
#include <linux/of_address.h>
1516
#include <linux/of_irq.h>
16-
#include <linux/regmap.h>
1717

18-
#define ASPEED_SCU_IC_REG 0x018
19-
#define ASPEED_SCU_IC_SHIFT 0
20-
#define ASPEED_SCU_IC_ENABLE GENMASK(15, ASPEED_SCU_IC_SHIFT)
21-
#define ASPEED_SCU_IC_NUM_IRQS 7
2218
#define ASPEED_SCU_IC_STATUS GENMASK(28, 16)
2319
#define ASPEED_SCU_IC_STATUS_SHIFT 16
2420

25-
#define ASPEED_AST2600_SCU_IC0_REG 0x560
26-
#define ASPEED_AST2600_SCU_IC0_SHIFT 0
27-
#define ASPEED_AST2600_SCU_IC0_ENABLE \
28-
GENMASK(5, ASPEED_AST2600_SCU_IC0_SHIFT)
29-
#define ASPEED_AST2600_SCU_IC0_NUM_IRQS 6
21+
struct aspeed_scu_ic_variant {
22+
const char *compatible;
23+
unsigned long irq_enable;
24+
unsigned long irq_shift;
25+
unsigned int num_irqs;
26+
};
27+
28+
#define SCU_VARIANT(_compat, _shift, _enable, _num) { \
29+
.compatible = _compat, \
30+
.irq_shift = _shift, \
31+
.irq_enable = _enable, \
32+
.num_irqs = _num, \
33+
}
3034

31-
#define ASPEED_AST2600_SCU_IC1_REG 0x570
32-
#define ASPEED_AST2600_SCU_IC1_SHIFT 4
33-
#define ASPEED_AST2600_SCU_IC1_ENABLE \
34-
GENMASK(5, ASPEED_AST2600_SCU_IC1_SHIFT)
35-
#define ASPEED_AST2600_SCU_IC1_NUM_IRQS 2
35+
static const struct aspeed_scu_ic_variant scu_ic_variants[] __initconst = {
36+
SCU_VARIANT("aspeed,ast2400-scu-ic", 0, GENMASK(15, 0), 7),
37+
SCU_VARIANT("aspeed,ast2500-scu-ic", 0, GENMASK(15, 0), 7),
38+
SCU_VARIANT("aspeed,ast2600-scu-ic0", 0, GENMASK(5, 0), 6),
39+
SCU_VARIANT("aspeed,ast2600-scu-ic1", 4, GENMASK(5, 4), 2),
40+
};
3641

3742
struct aspeed_scu_ic {
38-
unsigned long irq_enable;
39-
unsigned long irq_shift;
40-
unsigned int num_irqs;
41-
unsigned int reg;
42-
struct regmap *scu;
43-
struct irq_domain *irq_domain;
43+
unsigned long irq_enable;
44+
unsigned long irq_shift;
45+
unsigned int num_irqs;
46+
void __iomem *base;
47+
struct irq_domain *irq_domain;
4448
};
4549

4650
static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
4751
{
48-
unsigned int sts;
49-
unsigned long bit;
50-
unsigned long enabled;
51-
unsigned long max;
52-
unsigned long status;
5352
struct aspeed_scu_ic *scu_ic = irq_desc_get_handler_data(desc);
5453
struct irq_chip *chip = irq_desc_get_chip(desc);
55-
unsigned int mask = scu_ic->irq_enable << ASPEED_SCU_IC_STATUS_SHIFT;
54+
unsigned long bit, enabled, max, status;
55+
unsigned int sts, mask;
5656

5757
chained_irq_enter(chip, desc);
5858

59+
mask = scu_ic->irq_enable << ASPEED_SCU_IC_STATUS_SHIFT;
5960
/*
6061
* The SCU IC has just one register to control its operation and read
6162
* status. The interrupt enable bits occupy the lower 16 bits of the
@@ -66,19 +67,17 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
6667
* shifting the status down to get the mapping and then back up to
6768
* clear the bit.
6869
*/
69-
regmap_read(scu_ic->scu, scu_ic->reg, &sts);
70+
sts = readl(scu_ic->base);
7071
enabled = sts & scu_ic->irq_enable;
7172
status = (sts >> ASPEED_SCU_IC_STATUS_SHIFT) & enabled;
7273

7374
bit = scu_ic->irq_shift;
7475
max = scu_ic->num_irqs + bit;
7576

7677
for_each_set_bit_from(bit, &status, max) {
77-
generic_handle_domain_irq(scu_ic->irq_domain,
78-
bit - scu_ic->irq_shift);
79-
80-
regmap_write_bits(scu_ic->scu, scu_ic->reg, mask,
81-
BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT));
78+
generic_handle_domain_irq(scu_ic->irq_domain, bit - scu_ic->irq_shift);
79+
writel((readl(scu_ic->base) & ~mask) | BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT),
80+
scu_ic->base);
8281
}
8382

8483
chained_irq_exit(chip, desc);
@@ -87,30 +86,29 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
8786
static void aspeed_scu_ic_irq_mask(struct irq_data *data)
8887
{
8988
struct aspeed_scu_ic *scu_ic = irq_data_get_irq_chip_data(data);
90-
unsigned int mask = BIT(data->hwirq + scu_ic->irq_shift) |
91-
(scu_ic->irq_enable << ASPEED_SCU_IC_STATUS_SHIFT);
89+
unsigned int bit = BIT(data->hwirq + scu_ic->irq_shift);
90+
unsigned int mask = bit | (scu_ic->irq_enable << ASPEED_SCU_IC_STATUS_SHIFT);
9291

9392
/*
9493
* Status bits are cleared by writing 1. In order to prevent the mask
9594
* operation from clearing the status bits, they should be under the
9695
* mask and written with 0.
9796
*/
98-
regmap_update_bits(scu_ic->scu, scu_ic->reg, mask, 0);
97+
writel(readl(scu_ic->base) & ~mask, scu_ic->base);
9998
}
10099

101100
static void aspeed_scu_ic_irq_unmask(struct irq_data *data)
102101
{
103102
struct aspeed_scu_ic *scu_ic = irq_data_get_irq_chip_data(data);
104103
unsigned int bit = BIT(data->hwirq + scu_ic->irq_shift);
105-
unsigned int mask = bit |
106-
(scu_ic->irq_enable << ASPEED_SCU_IC_STATUS_SHIFT);
104+
unsigned int mask = bit | (scu_ic->irq_enable << ASPEED_SCU_IC_STATUS_SHIFT);
107105

108106
/*
109107
* Status bits are cleared by writing 1. In order to prevent the unmask
110108
* operation from clearing the status bits, they should be under the
111109
* mask and written with 0.
112110
*/
113-
regmap_update_bits(scu_ic->scu, scu_ic->reg, mask, bit);
111+
writel((readl(scu_ic->base) & ~mask) | bit, scu_ic->base);
114112
}
115113

116114
static int aspeed_scu_ic_irq_set_affinity(struct irq_data *data,
@@ -143,21 +141,15 @@ static const struct irq_domain_ops aspeed_scu_ic_domain_ops = {
143141
static int aspeed_scu_ic_of_init_common(struct aspeed_scu_ic *scu_ic,
144142
struct device_node *node)
145143
{
146-
int irq;
147-
int rc = 0;
144+
int irq, rc = 0;
148145

149-
if (!node->parent) {
150-
rc = -ENODEV;
146+
scu_ic->base = of_iomap(node, 0);
147+
if (IS_ERR(scu_ic->base)) {
148+
rc = PTR_ERR(scu_ic->base);
151149
goto err;
152150
}
153-
154-
scu_ic->scu = syscon_node_to_regmap(node->parent);
155-
if (IS_ERR(scu_ic->scu)) {
156-
rc = PTR_ERR(scu_ic->scu);
157-
goto err;
158-
}
159-
regmap_write_bits(scu_ic->scu, scu_ic->reg, ASPEED_SCU_IC_STATUS, ASPEED_SCU_IC_STATUS);
160-
regmap_write_bits(scu_ic->scu, scu_ic->reg, ASPEED_SCU_IC_ENABLE, 0);
151+
writel(ASPEED_SCU_IC_STATUS, scu_ic->base);
152+
writel(0, scu_ic->base);
161153

162154
irq = irq_of_parse_and_map(node, 0);
163155
if (!irq) {
@@ -166,8 +158,7 @@ static int aspeed_scu_ic_of_init_common(struct aspeed_scu_ic *scu_ic,
166158
}
167159

168160
scu_ic->irq_domain = irq_domain_create_linear(of_fwnode_handle(node), scu_ic->num_irqs,
169-
&aspeed_scu_ic_domain_ops,
170-
scu_ic);
161+
&aspeed_scu_ic_domain_ops, scu_ic);
171162
if (!scu_ic->irq_domain) {
172163
rc = -ENOMEM;
173164
goto err;
@@ -180,61 +171,39 @@ static int aspeed_scu_ic_of_init_common(struct aspeed_scu_ic *scu_ic,
180171

181172
err:
182173
kfree(scu_ic);
183-
184174
return rc;
185175
}
186176

187-
static int __init aspeed_scu_ic_of_init(struct device_node *node,
188-
struct device_node *parent)
177+
static const struct aspeed_scu_ic_variant *aspeed_scu_ic_find_variant(struct device_node *np)
189178
{
190-
struct aspeed_scu_ic *scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
191-
192-
if (!scu_ic)
193-
return -ENOMEM;
194-
195-
scu_ic->irq_enable = ASPEED_SCU_IC_ENABLE;
196-
scu_ic->irq_shift = ASPEED_SCU_IC_SHIFT;
197-
scu_ic->num_irqs = ASPEED_SCU_IC_NUM_IRQS;
198-
scu_ic->reg = ASPEED_SCU_IC_REG;
199-
200-
return aspeed_scu_ic_of_init_common(scu_ic, node);
179+
for (int i = 0; i < ARRAY_SIZE(scu_ic_variants); i++) {
180+
if (of_device_is_compatible(np, scu_ic_variants[i].compatible))
181+
return &scu_ic_variants[i];
182+
}
183+
return NULL;
201184
}
202185

203-
static int __init aspeed_ast2600_scu_ic0_of_init(struct device_node *node,
204-
struct device_node *parent)
186+
static int __init aspeed_scu_ic_of_init(struct device_node *node, struct device_node *parent)
205187
{
206-
struct aspeed_scu_ic *scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
207-
208-
if (!scu_ic)
209-
return -ENOMEM;
210-
211-
scu_ic->irq_enable = ASPEED_AST2600_SCU_IC0_ENABLE;
212-
scu_ic->irq_shift = ASPEED_AST2600_SCU_IC0_SHIFT;
213-
scu_ic->num_irqs = ASPEED_AST2600_SCU_IC0_NUM_IRQS;
214-
scu_ic->reg = ASPEED_AST2600_SCU_IC0_REG;
215-
216-
return aspeed_scu_ic_of_init_common(scu_ic, node);
217-
}
188+
const struct aspeed_scu_ic_variant *variant;
189+
struct aspeed_scu_ic *scu_ic;
218190

219-
static int __init aspeed_ast2600_scu_ic1_of_init(struct device_node *node,
220-
struct device_node *parent)
221-
{
222-
struct aspeed_scu_ic *scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
191+
variant = aspeed_scu_ic_find_variant(node);
192+
if (!variant)
193+
return -ENODEV;
223194

195+
scu_ic = kzalloc(sizeof(*scu_ic), GFP_KERNEL);
224196
if (!scu_ic)
225197
return -ENOMEM;
226198

227-
scu_ic->irq_enable = ASPEED_AST2600_SCU_IC1_ENABLE;
228-
scu_ic->irq_shift = ASPEED_AST2600_SCU_IC1_SHIFT;
229-
scu_ic->num_irqs = ASPEED_AST2600_SCU_IC1_NUM_IRQS;
230-
scu_ic->reg = ASPEED_AST2600_SCU_IC1_REG;
199+
scu_ic->irq_enable = variant->irq_enable;
200+
scu_ic->irq_shift = variant->irq_shift;
201+
scu_ic->num_irqs = variant->num_irqs;
231202

232203
return aspeed_scu_ic_of_init_common(scu_ic, node);
233204
}
234205

235206
IRQCHIP_DECLARE(ast2400_scu_ic, "aspeed,ast2400-scu-ic", aspeed_scu_ic_of_init);
236207
IRQCHIP_DECLARE(ast2500_scu_ic, "aspeed,ast2500-scu-ic", aspeed_scu_ic_of_init);
237-
IRQCHIP_DECLARE(ast2600_scu_ic0, "aspeed,ast2600-scu-ic0",
238-
aspeed_ast2600_scu_ic0_of_init);
239-
IRQCHIP_DECLARE(ast2600_scu_ic1, "aspeed,ast2600-scu-ic1",
240-
aspeed_ast2600_scu_ic1_of_init);
208+
IRQCHIP_DECLARE(ast2600_scu_ic0, "aspeed,ast2600-scu-ic0", aspeed_scu_ic_of_init);
209+
IRQCHIP_DECLARE(ast2600_scu_ic1, "aspeed,ast2600-scu-ic1", aspeed_scu_ic_of_init);

0 commit comments

Comments
 (0)