mbox series

[v4,0/6] Extend irqchip ocelot driver to support other SoCs

Message ID 20201120164108.2096359-1-gregory.clement@bootlin.com
Headers show
Series Extend irqchip ocelot driver to support other SoCs | expand

Message

Gregory CLEMENT Nov. 20, 2020, 4:41 p.m. UTC
Hello,

Ocelot SoC belongs to a larger family of SoCs which use the same
interrupt controller with a few variation.

This series of patches add support for Luton, Serval and Jaguar2, they
are all MIPS based.

The first patches of the series also updates the binding documentation
with the new compatible strings.

Gregory

Changelog:
v3 -> v4
 - Fix example in binding adding #address-cells property.

 - Split the intial "irqchip: ocelot: Add support for Luton platforms"
   patch with a new patch "irqchip: ocelot: prepare to support more
   SoC"

 - Move from u32 to u8 the type used inside the "struct chip_props"

 - Keep the function ocelot_irq_unmask as is and use generic function
   irq_gc_mask_disable_reg and irq_gc_unmask_enable_reg for Luton.

 - Removed the irq_set_irqchip_state callback, actually this function
   was never called on this platform and seemed in the end useless.

 - Add acked-by from Alexandre on the last 2 patches.

v2 -> v3
 - Fix new-line-at-end-of-file error in the yaml file

v1 -> v2:
 - Convert the binding to yaml
 - Squashed the patches adding new binding in a single one

Gregory CLEMENT (6):
  dt-bindings: interrupt-controller: convert icpu intr bindings to
    json-schema
  dt-bindings: interrupt-controller: Add binding for few Microsemi
    interrupt controllers
  irqchip: ocelot: prepare to support more SoC
  irqchip: ocelot: Add support for Luton platforms
  irqchip: ocelot: Add support for Serval platforms
  irqchip: ocelot: Add support for Jaguar2 platforms

 .../mscc,ocelot-icpu-intr.txt                 |  21 ---
 .../mscc,ocelot-icpu-intr.yaml                |  64 ++++++++
 drivers/irqchip/irq-mscc-ocelot.c             | 146 +++++++++++++++---
 3 files changed, 187 insertions(+), 44 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mscc,ocelot-icpu-intr.yaml

Comments

Alexandre Belloni Nov. 23, 2020, 8:04 a.m. UTC | #1
On 20/11/2020 17:41:05+0100, Gregory CLEMENT wrote:
> This patch extends irqchip driver for oceleot to be used with other
> vcoreiii base platforms.
> 
> Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

> ---
>  drivers/irqchip/irq-mscc-ocelot.c | 76 ++++++++++++++++++++++---------
>  1 file changed, 54 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-mscc-ocelot.c b/drivers/irqchip/irq-mscc-ocelot.c
> index 88143c0b700c..6d4029a2ded0 100644
> --- a/drivers/irqchip/irq-mscc-ocelot.c
> +++ b/drivers/irqchip/irq-mscc-ocelot.c
> @@ -12,30 +12,51 @@
>  #include <linux/irqchip/chained_irq.h>
>  #include <linux/interrupt.h>
>  
> -#define ICPU_CFG_INTR_INTR_STICKY	0x10
> -#define ICPU_CFG_INTR_INTR_ENA		0x18
> -#define ICPU_CFG_INTR_INTR_ENA_CLR	0x1c
> -#define ICPU_CFG_INTR_INTR_ENA_SET	0x20
> -#define ICPU_CFG_INTR_DST_INTR_IDENT(x)	(0x38 + 0x4 * (x))
> -#define ICPU_CFG_INTR_INTR_TRIGGER(x)	(0x5c + 0x4 * (x))
> -
> -#define OCELOT_NR_IRQ 24
> +#define ICPU_CFG_INTR_DST_INTR_IDENT(_p, x) ((_p)->reg_off_ident + 0x4 * (x))
> +#define ICPU_CFG_INTR_INTR_TRIGGER(_p, x)   ((_p)->reg_off_trigger + 0x4 * (x))
> +
> +#define FLAGS_HAS_TRIGGER	BIT(0)
> +
> +struct chip_props {
> +	u8 flags;
> +	u8 reg_off_sticky;
> +	u8 reg_off_ena;
> +	u8 reg_off_ena_clr;
> +	u8 reg_off_ena_set;
> +	u8 reg_off_ident;
> +	u8 reg_off_trigger;
> +	u8 reg_off_ena_irq0;
> +	u8 n_irq;
> +};
> +
> +static struct chip_props ocelot_props = {
> +	.flags			= FLAGS_HAS_TRIGGER,
> +	.reg_off_sticky		= 0x10,
> +	.reg_off_ena		= 0x18,
> +	.reg_off_ena_clr	= 0x1c,
> +	.reg_off_ena_set	= 0x20,
> +	.reg_off_ident		= 0x38,
> +	.reg_off_trigger	= 0x5c,
> +	.n_irq			= 24,
> +};
>  
>  static void ocelot_irq_unmask(struct irq_data *data)
>  {
>  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
> +	struct irq_domain *d = data->domain;
> +	struct chip_props *p = d->host_data;
>  	struct irq_chip_type *ct = irq_data_get_chip_type(data);
>  	unsigned int mask = data->mask;
>  	u32 val;
>  
>  	irq_gc_lock(gc);
> -	val = irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(0)) |
> -	      irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(1));
> +	val = irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(p, 0)) |
> +		irq_reg_readl(gc, ICPU_CFG_INTR_INTR_TRIGGER(p, 1));
>  	if (!(val & mask))
> -		irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_STICKY);
> +		irq_reg_writel(gc, mask, p->reg_off_sticky);
>  
>  	*ct->mask_cache &= ~mask;
> -	irq_reg_writel(gc, mask, ICPU_CFG_INTR_INTR_ENA_SET);
> +	irq_reg_writel(gc, mask, p->reg_off_ena_set);
>  	irq_gc_unlock(gc);
>  }
>  
> @@ -43,8 +64,9 @@ static void ocelot_irq_handler(struct irq_desc *desc)
>  {
>  	struct irq_chip *chip = irq_desc_get_chip(desc);
>  	struct irq_domain *d = irq_desc_get_handler_data(desc);
> +	struct chip_props *p = d->host_data;
>  	struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
> -	u32 reg = irq_reg_readl(gc, ICPU_CFG_INTR_DST_INTR_IDENT(0));
> +	u32 reg = irq_reg_readl(gc, ICPU_CFG_INTR_DST_INTR_IDENT(p, 0));
>  
>  	chained_irq_enter(chip, desc);
>  
> @@ -58,8 +80,9 @@ static void ocelot_irq_handler(struct irq_desc *desc)
>  	chained_irq_exit(chip, desc);
>  }
>  
> -static int __init ocelot_irq_init(struct device_node *node,
> -				  struct device_node *parent)
> +static int __init vcoreiii_irq_init(struct device_node *node,
> +				    struct device_node *parent,
> +				    struct chip_props *p)
>  {
>  	struct irq_domain *domain;
>  	struct irq_chip_generic *gc;
> @@ -69,14 +92,14 @@ static int __init ocelot_irq_init(struct device_node *node,
>  	if (!parent_irq)
>  		return -EINVAL;
>  
> -	domain = irq_domain_add_linear(node, OCELOT_NR_IRQ,
> +	domain = irq_domain_add_linear(node, p->n_irq,
>  				       &irq_generic_chip_ops, NULL);
>  	if (!domain) {
>  		pr_err("%pOFn: unable to add irq domain\n", node);
>  		return -ENOMEM;
>  	}
>  
> -	ret = irq_alloc_domain_generic_chips(domain, OCELOT_NR_IRQ, 1,
> +	ret = irq_alloc_domain_generic_chips(domain, p->n_irq, 1,
>  					     "icpu", handle_level_irq,
>  					     0, 0, 0);
>  	if (ret) {
> @@ -92,16 +115,18 @@ static int __init ocelot_irq_init(struct device_node *node,
>  		goto err_gc_free;
>  	}
>  
> -	gc->chip_types[0].regs.ack = ICPU_CFG_INTR_INTR_STICKY;
> -	gc->chip_types[0].regs.mask = ICPU_CFG_INTR_INTR_ENA_CLR;
> +	gc->chip_types[0].regs.ack = p->reg_off_sticky;
> +	gc->chip_types[0].regs.mask = p->reg_off_ena_clr;
>  	gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
>  	gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
> -	gc->chip_types[0].chip.irq_unmask = ocelot_irq_unmask;
> +	if (p->flags & FLAGS_HAS_TRIGGER)
> +		gc->chip_types[0].chip.irq_unmask = ocelot_irq_unmask;
>  
>  	/* Mask and ack all interrupts */
> -	irq_reg_writel(gc, 0, ICPU_CFG_INTR_INTR_ENA);
> -	irq_reg_writel(gc, 0xffffffff, ICPU_CFG_INTR_INTR_STICKY);
> +	irq_reg_writel(gc, 0, p->reg_off_ena);
> +	irq_reg_writel(gc, 0xffffffff, p->reg_off_sticky);
>  
> +	domain->host_data = p;
>  	irq_set_chained_handler_and_data(parent_irq, ocelot_irq_handler,
>  					 domain);
>  
> @@ -115,4 +140,11 @@ static int __init ocelot_irq_init(struct device_node *node,
>  
>  	return ret;
>  }
> +
> +static int __init ocelot_irq_init(struct device_node *node,
> +				  struct device_node *parent)
> +{
> +	return vcoreiii_irq_init(node, parent, &ocelot_props);
> +}
> +
>  IRQCHIP_DECLARE(ocelot_icpu, "mscc,ocelot-icpu-intr", ocelot_irq_init);
> -- 
> 2.29.2
>
Alexandre Belloni Nov. 23, 2020, 8:04 a.m. UTC | #2
On 20/11/2020 17:41:06+0100, Gregory CLEMENT wrote:
> This patch extends irqchip driver for oceleot to be used with an other
> vcoreiii base platform: Luton.
> 
> For this platform there is a few differences:
>    - the interrupt must be enabled for the parent controller
>    - there is no trigger register needed to be managed
> 
> Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

> ---
>  drivers/irqchip/irq-mscc-ocelot.c | 38 +++++++++++++++++++++++++++----
>  1 file changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-mscc-ocelot.c b/drivers/irqchip/irq-mscc-ocelot.c
> index 6d4029a2ded0..496f955b8fc4 100644
> --- a/drivers/irqchip/irq-mscc-ocelot.c
> +++ b/drivers/irqchip/irq-mscc-ocelot.c
> @@ -16,6 +16,7 @@
>  #define ICPU_CFG_INTR_INTR_TRIGGER(_p, x)   ((_p)->reg_off_trigger + 0x4 * (x))
>  
>  #define FLAGS_HAS_TRIGGER	BIT(0)
> +#define FLAGS_NEED_INIT_ENABLE	BIT(1)
>  
>  struct chip_props {
>  	u8 flags;
> @@ -40,6 +41,17 @@ static struct chip_props ocelot_props = {
>  	.n_irq			= 24,
>  };
>  
> +static struct chip_props luton_props = {
> +	.flags			= FLAGS_NEED_INIT_ENABLE,
> +	.reg_off_sticky		= 0,
> +	.reg_off_ena		= 0x4,
> +	.reg_off_ena_clr	= 0x8,
> +	.reg_off_ena_set	= 0xc,
> +	.reg_off_ident		= 0x18,
> +	.reg_off_ena_irq0	= 0x14,
> +	.n_irq			= 28,
> +};
> +
>  static void ocelot_irq_unmask(struct irq_data *data)
>  {
>  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
> @@ -115,17 +127,27 @@ static int __init vcoreiii_irq_init(struct device_node *node,
>  		goto err_gc_free;
>  	}
>  
> -	gc->chip_types[0].regs.ack = p->reg_off_sticky;
> -	gc->chip_types[0].regs.mask = p->reg_off_ena_clr;
>  	gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
> -	gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
> -	if (p->flags & FLAGS_HAS_TRIGGER)
> +	gc->chip_types[0].regs.ack = p->reg_off_sticky;
> +	if (p->flags & FLAGS_HAS_TRIGGER) {
> +		gc->chip_types[0].regs.mask = p->reg_off_ena_clr;
>  		gc->chip_types[0].chip.irq_unmask = ocelot_irq_unmask;
> +		gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
> +	} else {
> +		gc->chip_types[0].regs.enable = p->reg_off_ena_set;
> +		gc->chip_types[0].regs.disable = p->reg_off_ena_clr;
> +		gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
> +		gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
> +	}
>  
>  	/* Mask and ack all interrupts */
>  	irq_reg_writel(gc, 0, p->reg_off_ena);
>  	irq_reg_writel(gc, 0xffffffff, p->reg_off_sticky);
>  
> +	/* Overall init */
> +	if (p->flags & FLAGS_NEED_INIT_ENABLE)
> +		irq_reg_writel(gc, BIT(0), p->reg_off_ena_irq0);
> +
>  	domain->host_data = p;
>  	irq_set_chained_handler_and_data(parent_irq, ocelot_irq_handler,
>  					 domain);
> @@ -148,3 +170,11 @@ static int __init ocelot_irq_init(struct device_node *node,
>  }
>  
>  IRQCHIP_DECLARE(ocelot_icpu, "mscc,ocelot-icpu-intr", ocelot_irq_init);
> +
> +static int __init luton_irq_init(struct device_node *node,
> +				 struct device_node *parent)
> +{
> +	return vcoreiii_irq_init(node, parent, &luton_props);
> +}
> +
> +IRQCHIP_DECLARE(luton_icpu, "mscc,luton-icpu-intr", luton_irq_init);
> -- 
> 2.29.2
>