[Letux-kernel] [RFC 12/28] irqchip/ingenic: Pass the whole priv struct to callbacks and add jz4730
H. Nikolaus Schaller
hns at goldelico.com
Sat Jan 23 17:28:38 CET 2021
From: Paul Boddie <paul at boddie.org.uk>
Although the jz4740-intc identification could be used, since the
general capabilities are the same, a separate identification has
been added because the controllers are technically different in
terms of interrupt assignments.
No functional change here. This will make it easier to pass more
information to the callbacks than just the regmap -- something that will
come useful for JZ4730 support.
Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>
Signed-off-by: Paul Boddie <paul at boddie.org.uk>
Signed-off-by: H. Nikolaus Schaller <hns at goldelico.com>
---
drivers/irqchip/irq-ingenic-tcu.c | 75 +++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 14 deletions(-)
diff --git a/drivers/irqchip/irq-ingenic-tcu.c b/drivers/irqchip/irq-ingenic-tcu.c
index 7a7222d4c19c0..1f15d2d3d4137 100644
--- a/drivers/irqchip/irq-ingenic-tcu.c
+++ b/drivers/irqchip/irq-ingenic-tcu.c
@@ -19,6 +19,7 @@ struct ingenic_tcu {
struct irq_domain *domain;
unsigned int nb_parent_irqs;
u32 parent_irqs[3];
+ bool jz4740_regs;
};
static void ingenic_tcu_intc_cascade(struct irq_desc *desc)
@@ -26,12 +27,23 @@ static void ingenic_tcu_intc_cascade(struct irq_desc *desc)
struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
struct irq_domain *domain = irq_desc_get_handler_data(desc);
struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
- struct regmap *map = gc->private;
+ struct ingenic_tcu *tcu = gc->private;
uint32_t irq_reg, irq_mask;
unsigned int i;
-
- regmap_read(map, TCU_REG_TFR, &irq_reg);
- regmap_read(map, TCU_REG_TMR, &irq_mask);
+ uint32 val;
+
+ if (tcu->jz4740_regs) {
+ regmap_read(tcu->map, TCU_REG_TFR, &irq_reg);
+ regmap_read(tcu->map, TCU_REG_TMR, &irq_mask);
+ } else {
+ irq_reg = 0;
+ irq_mask = 0;
+ for (i = 0; i < 3; i++) {
+ regmap_read(tcu->map, TCU_JZ4730_REG_TCSRc(i), &val);
+ irq_reg |= (val & TCU_JZ4730_TCSR_FLAG) ? BIT(i) : 0;
+ irq_mask |= (val & TCU_JZ4730_TCSR_EN) ? 0 : BIT(i);
+ }
+ }
chained_irq_enter(irq_chip, desc);
@@ -47,12 +59,21 @@ static void ingenic_tcu_gc_unmask_enable_reg(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- struct regmap *map = gc->private;
+ struct ingenic_tcu *tcu = gc->private;
u32 mask = d->mask;
+ unsigned int i;
irq_gc_lock(gc);
- regmap_write(map, ct->regs.ack, mask);
- regmap_write(map, ct->regs.enable, mask);
+ if (tcu->jz4740_regs) {
+ regmap_write(tcu->map, ct->regs.ack, mask);
+ regmap_write(tcu->map, ct->regs.enable, mask);
+ } else {
+ for_each_set_bit(i, (unsigned long *)&mask, 3) {
+ regmap_update_bits(tcu->map, TCU_JZ4730_REG_TCSRc(i),
+ TCU_JZ4730_TCSR_FLAG | TCU_JZ4730_TCSR_EN,
+ TCU_JZ4730_TCSR_EN);
+ }
+ }
*ct->mask_cache |= mask;
irq_gc_unlock(gc);
}
@@ -61,11 +82,19 @@ static void ingenic_tcu_gc_mask_disable_reg(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- struct regmap *map = gc->private;
+ struct ingenic_tcu *tcu = gc->private;
u32 mask = d->mask;
+ unsigned int i;
irq_gc_lock(gc);
- regmap_write(map, ct->regs.disable, mask);
+ if (tcu->jz4740_regs) {
+ regmap_write(tcu->map, ct->regs.disable, mask);
+ } else {
+ for_each_set_bit(i, (unsigned long *)&mask, 3) {
+ regmap_update_bits(tcu->map, TCU_JZ4730_REG_TCSRc(i),
+ TCU_JZ4730_TCSR_EN, 0);
+ }
+ }
*ct->mask_cache &= ~mask;
irq_gc_unlock(gc);
}
@@ -74,12 +103,20 @@ static void ingenic_tcu_gc_mask_disable_reg_and_ack(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = irq_data_get_chip_type(d);
- struct regmap *map = gc->private;
+ struct ingenic_tcu *tcu = gc->private;
u32 mask = d->mask;
+ unsigned int i;
irq_gc_lock(gc);
- regmap_write(map, ct->regs.ack, mask);
- regmap_write(map, ct->regs.disable, mask);
+ if (tcu->jz4740_regs) {
+ regmap_write(tcu->map, ct->regs.ack, mask);
+ regmap_write(tcu->map, ct->regs.disable, mask);
+ } else {
+ for_each_set_bit(i, (unsigned long *)&mask, 3) {
+ regmap_update_bits(tcu->map, TCU_JZ4730_REG_TCSRc(i),
+ TCU_JZ4730_TCSR_FLAG | TCU_JZ4730_TCSR_EN, 0);
+ }
+ }
irq_gc_unlock(gc);
}
@@ -101,6 +138,8 @@ static int __init ingenic_tcu_irq_init(struct device_node *np,
if (!tcu)
return -ENOMEM;
+ tcu->jz4740_regs = !of_device_is_compatible(np, "ingenic,jz4730-tcu");
+
tcu->map = map;
irqs = of_property_count_elems_of_size(np, "interrupts", sizeof(u32));
@@ -131,7 +170,7 @@ static int __init ingenic_tcu_irq_init(struct device_node *np,
ct = gc->chip_types;
gc->wake_enabled = IRQ_MSK(32);
- gc->private = tcu->map;
+ gc->private = tcu;
ct->regs.disable = TCU_REG_TMSR;
ct->regs.enable = TCU_REG_TMCR;
@@ -142,7 +181,14 @@ static int __init ingenic_tcu_irq_init(struct device_node *np,
ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
/* Mask all IRQs by default */
- regmap_write(tcu->map, TCU_REG_TMSR, IRQ_MSK(32));
+ if (tcu->jz4740_regs) {
+ regmap_write(tcu->map, TCU_REG_TMSR, IRQ_MSK(32));
+ } else {
+ for (i = 0; i < 3; i++) {
+ regmap_update_bits(tcu->map, TCU_JZ4730_REG_TCSRc(i),
+ TCU_JZ4730_TCSR_EN, 0);
+ }
+ }
/*
* On JZ4740, timer 0 and timer 1 have their own interrupt line;
@@ -179,5 +225,6 @@ static int __init ingenic_tcu_irq_init(struct device_node *np,
}
IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu", ingenic_tcu_irq_init);
IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu", ingenic_tcu_irq_init);
+IRQCHIP_DECLARE(jz4730_tcu_irq, "ingenic,jz4730-tcu", ingenic_tcu_irq_init);
IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu", ingenic_tcu_irq_init);
IRQCHIP_DECLARE(x1000_tcu_irq, "ingenic,x1000-tcu", ingenic_tcu_irq_init);
--
2.26.2
More information about the Letux-kernel
mailing list