Skip to content

Commit deb904e

Browse files
Aisheng DongMarc Zyngier
authored andcommitted
irqchip/imx-irqsteer: Change to use reg_num instead of irq_group
One group can manage 64 interrupts by using two registers (e.g. STATUS/SET). However, the integrated irqsteer may support only 32 interrupts which needs only one register in a group. But the current driver assume there's a mininum of two registers in a group which result in a wrong register map for 32 interrupts per channel irqsteer. Let's use the reg_num caculated by interrupts per channel instead of irq_group to cover this case. Cc: Rob Herring <robh+dt@kernel.org> Cc: Shawn Guo <shawnguo@kernel.org> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent e482c01 commit deb904e

File tree

1 file changed

+19
-16
lines changed

1 file changed

+19
-16
lines changed

drivers/irqchip/irq-imx-irqsteer.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <linux/of_platform.h>
1414
#include <linux/spinlock.h>
1515

16-
#define CTRL_STRIDE_OFF(_t, _r) (_t * 8 * _r)
16+
#define CTRL_STRIDE_OFF(_t, _r) (_t * 4 * _r)
1717
#define CHANCTRL 0x0
1818
#define CHANMASK(n, t) (CTRL_STRIDE_OFF(t, 0) + 0x4 * (n) + 0x4)
1919
#define CHANSET(n, t) (CTRL_STRIDE_OFF(t, 1) + 0x4 * (n) + 0x4)
@@ -26,7 +26,7 @@ struct irqsteer_data {
2626
struct clk *ipg_clk;
2727
int irq;
2828
raw_spinlock_t lock;
29-
int irq_groups;
29+
int reg_num;
3030
int channel;
3131
struct irq_domain *domain;
3232
u32 *saved_reg;
@@ -35,7 +35,7 @@ struct irqsteer_data {
3535
static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
3636
unsigned long irqnum)
3737
{
38-
return (data->irq_groups * 2 - irqnum / 32 - 1);
38+
return (data->reg_num - irqnum / 32 - 1);
3939
}
4040

4141
static void imx_irqsteer_irq_unmask(struct irq_data *d)
@@ -46,9 +46,9 @@ static void imx_irqsteer_irq_unmask(struct irq_data *d)
4646
u32 val;
4747

4848
raw_spin_lock_irqsave(&data->lock, flags);
49-
val = readl_relaxed(data->regs + CHANMASK(idx, data->irq_groups));
49+
val = readl_relaxed(data->regs + CHANMASK(idx, data->reg_num));
5050
val |= BIT(d->hwirq % 32);
51-
writel_relaxed(val, data->regs + CHANMASK(idx, data->irq_groups));
51+
writel_relaxed(val, data->regs + CHANMASK(idx, data->reg_num));
5252
raw_spin_unlock_irqrestore(&data->lock, flags);
5353
}
5454

@@ -60,9 +60,9 @@ static void imx_irqsteer_irq_mask(struct irq_data *d)
6060
u32 val;
6161

6262
raw_spin_lock_irqsave(&data->lock, flags);
63-
val = readl_relaxed(data->regs + CHANMASK(idx, data->irq_groups));
63+
val = readl_relaxed(data->regs + CHANMASK(idx, data->reg_num));
6464
val &= ~BIT(d->hwirq % 32);
65-
writel_relaxed(val, data->regs + CHANMASK(idx, data->irq_groups));
65+
writel_relaxed(val, data->regs + CHANMASK(idx, data->reg_num));
6666
raw_spin_unlock_irqrestore(&data->lock, flags);
6767
}
6868

@@ -94,13 +94,13 @@ static void imx_irqsteer_irq_handler(struct irq_desc *desc)
9494

9595
chained_irq_enter(irq_desc_get_chip(desc), desc);
9696

97-
for (i = 0; i < data->irq_groups * 64; i += 32) {
97+
for (i = 0; i < data->reg_num * 32; i += 32) {
9898
int idx = imx_irqsteer_get_reg_index(data, i);
9999
unsigned long irqmap;
100100
int pos, virq;
101101

102102
irqmap = readl_relaxed(data->regs +
103-
CHANSTATUS(idx, data->irq_groups));
103+
CHANSTATUS(idx, data->reg_num));
104104

105105
for_each_set_bit(pos, &irqmap, 32) {
106106
virq = irq_find_mapping(data->domain, pos + i);
@@ -146,12 +146,15 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
146146

147147
raw_spin_lock_init(&data->lock);
148148

149-
of_property_read_u32(np, "fsl,irq-groups", &data->irq_groups);
149+
of_property_read_u32(np, "fsl,num-irqs", &data->reg_num);
150150
of_property_read_u32(np, "fsl,channel", &data->channel);
151151

152+
/* one register bit map represents 32 input interrupts */
153+
data->reg_num /= 32;
154+
152155
if (IS_ENABLED(CONFIG_PM_SLEEP)) {
153156
data->saved_reg = devm_kzalloc(&pdev->dev,
154-
sizeof(u32) * data->irq_groups * 2,
157+
sizeof(u32) * data->reg_num,
155158
GFP_KERNEL);
156159
if (!data->saved_reg)
157160
return -ENOMEM;
@@ -166,7 +169,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
166169
/* steer all IRQs into configured channel */
167170
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
168171

169-
data->domain = irq_domain_add_linear(np, data->irq_groups * 64,
172+
data->domain = irq_domain_add_linear(np, data->reg_num * 32,
170173
&imx_irqsteer_domain_ops, data);
171174
if (!data->domain) {
172175
dev_err(&pdev->dev, "failed to create IRQ domain\n");
@@ -199,19 +202,19 @@ static void imx_irqsteer_save_regs(struct irqsteer_data *data)
199202
{
200203
int i;
201204

202-
for (i = 0; i < data->irq_groups * 2; i++)
205+
for (i = 0; i < data->reg_num; i++)
203206
data->saved_reg[i] = readl_relaxed(data->regs +
204-
CHANMASK(i, data->irq_groups));
207+
CHANMASK(i, data->reg_num));
205208
}
206209

207210
static void imx_irqsteer_restore_regs(struct irqsteer_data *data)
208211
{
209212
int i;
210213

211214
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
212-
for (i = 0; i < data->irq_groups * 2; i++)
215+
for (i = 0; i < data->reg_num; i++)
213216
writel_relaxed(data->saved_reg[i],
214-
data->regs + CHANMASK(i, data->irq_groups));
217+
data->regs + CHANMASK(i, data->reg_num));
215218
}
216219

217220
static int imx_irqsteer_suspend(struct device *dev)

0 commit comments

Comments
 (0)