Re: [PATCH] irqchip/irq-csky-mpintc: Add triger type and priority setting

2019-01-18 Thread Guo Ren
On Fri, Jan 18, 2019 at 09:32:03AM +, Marc Zyngier wrote:
> On 18/01/2019 06:28, Guo Ren wrote:
> > Thx Marc,
> > 
> > On Thu, Jan 17, 2019 at 05:17:45PM +, Marc Zyngier wrote:
> >> Hi Guo,
> >>
> >> On 15/01/2019 16:36, guo...@kernel.org wrote:
> >>> From: Guo Ren 
> >>>
> >>> Support 4 triger types:
> >>>  - IRQ_TYPE_LEVEL_HIGH
> >>>  - IRQ_TYPE_LEVEL_LOW
> >>>  - IRQ_TYPE_EDGE_RISING
> >>>  - IRQ_TYPE_EDGE_FALLING
> >>>
> >>> Support 0-255 priority setting for each irq.
> >>>
> >>> Signed-off-by: Guo Ren 
> >>> ---
> >>>  .../bindings/interrupt-controller/csky,mpintc.txt  | 24 ++-
> >>>  drivers/irqchip/irq-csky-mpintc.c  | 78 
> >>> +-
> >>>  2 files changed, 99 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git 
> >>> a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt 
> >>> b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> >>> index ab921f1..364b789 100644
> >>> --- 
> >>> a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> >>> +++ 
> >>> b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> >>> @@ -11,6 +11,14 @@ Interrupt number definition:
> >>>   16-31  : private  irq, and we use 16 as the co-processor timer.
> >>>   31-1024: common irq for soc ip.
> >>>  
> >>> +Interrupt triger mode:
> >>> +  IRQ_TYPE_LEVEL_HIGH (default)
> >>> +  IRQ_TYPE_LEVEL_LOW
> >>> +  IRQ_TYPE_EDGE_RISING
> >>> +  IRQ_TYPE_EDGE_FALLING
> >>> +
> >>> +Interrupt priority range: 0-255
> >>> +
> >>>  =
> >>>  intc node bindings definition
> >>>  =
> >>> @@ -26,7 +34,7 @@ intc node bindings definition
> >>>   - #interrupt-cells
> >>>   Usage: required
> >>>   Value type: 
> >>> - Definition: must be <1>
> >>> + Definition: could be <1> or <2>
> >>>   - interrupt-controller:
> >>>   Usage: required
> >>>  
> >>> @@ -35,6 +43,18 @@ Examples:
> >>>  
> >>>   intc: interrupt-controller {
> >>>   compatible = "csky,mpintc";
> >>> - #interrupt-cells = <1>;
> >>> + #interrupt-cells = <2>;
> >>>   interrupt-controller;
> >>>   };
> >>> +
> >>> + 0: device-example {
> >>> + ...
> >>> + interrupts = <33 IRQ_TYPE_EDGE_RISING>;
> >>> + interrupt-parent = <&intc>;
> >>> + };
> >>> +
> >>> + 1: device-example {
> >>> + ...
> >>> + interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
> >>> + interrupt-parent = <&intc>;
> >>> + };
> >>> diff --git a/drivers/irqchip/irq-csky-mpintc.c 
> >>> b/drivers/irqchip/irq-csky-mpintc.c
> >>> index c67c961..9edc6d3 100644
> >>> --- a/drivers/irqchip/irq-csky-mpintc.c
> >>> +++ b/drivers/irqchip/irq-csky-mpintc.c
> >>> @@ -29,9 +29,12 @@ static void __iomem *INTCL_base;
> >>>  
> >>>  #define INTCG_ICTLR  0x0
> >>>  #define INTCG_CICFGR 0x100
> >>> +#define INTCG_CIPRTR 0x200
> >>>  #define INTCG_CIDSTR 0x1000
> >>>  
> >>>  #define INTCL_PICTLR 0x0
> >>> +#define INTCL_CFGR   0x14
> >>> +#define INTCL_PRTR   0x20
> >>>  #define INTCL_SIGR   0x60
> >>>  #define INTCL_HPPIR  0x68
> >>>  #define INTCL_RDYIR  0x6c
> >>> @@ -73,6 +76,78 @@ static void csky_mpintc_eoi(struct irq_data *d)
> >>>   writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
> >>>  }
> >>>  
> >>> +static int csky_mpintc_set_type(struct irq_data *d, unsigned int type)
> >>> +{
> >>> + unsigned int priority, triger;
> >>
> >> nit: s/triger/trigger/ everywhere.
> > Ok
> > 
> >>
> >>> + unsigned int offset, bit_offset;
> >>> + void __iomem *reg_base;
> >>> +
> >>> + /*
> >>> +  * type Bit field: | 32 - 12  |  11 - 4  |   3 - 0|
> >>> +  *   reserved   priority   triger type
> >>> +  */
> >>> + triger   = type & IRQ_TYPE_SENSE_MASK;
> >>> + priority = (type >> 4) & 0xff;
> >>
> >> Definitely not. The Linux API to set the trigger does not carry any
> >> priority information, nor should it. Priorities should be set
> >> statically, and no driver should ever be able to change it.
> > Currently priority in dts is:
> > 
> > interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
> > 
> > change it to:
> > 
> > interrupts = <34 IRQ_TYPE_EDGE_RISING priority>;
> > 
> 
> I don't think you need to change the DT format, as this is quite painful
> for users.
I'll keep this style and I think it's good place to set priority.

> 
> > Implement csky own csky_irq_domain_xlate_cells() ...
> > 
> > int csky_irq_domain_xlate_cells(struct irq_domain *d, struct device_node 
> > *ctrlr,
> > const u32 *intspec, unsigned int intsize,
> > irq_hw_number_t *out_hwirq, unsigned int *out_type)
> > {
> > if (WARN_ON(intsize < 1))
> > return -EINVAL;
> > *out_hwirq = intspec[0];
> > if (intsize > 1)
> > *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
> > else
> > *out_type = IRQ_TYPE_NONE;
> > 
> >

Re: [PATCH] irqchip/irq-csky-mpintc: Add triger type and priority setting

2019-01-18 Thread Marc Zyngier
On 18/01/2019 06:28, Guo Ren wrote:
> Thx Marc,
> 
> On Thu, Jan 17, 2019 at 05:17:45PM +, Marc Zyngier wrote:
>> Hi Guo,
>>
>> On 15/01/2019 16:36, guo...@kernel.org wrote:
>>> From: Guo Ren 
>>>
>>> Support 4 triger types:
>>>  - IRQ_TYPE_LEVEL_HIGH
>>>  - IRQ_TYPE_LEVEL_LOW
>>>  - IRQ_TYPE_EDGE_RISING
>>>  - IRQ_TYPE_EDGE_FALLING
>>>
>>> Support 0-255 priority setting for each irq.
>>>
>>> Signed-off-by: Guo Ren 
>>> ---
>>>  .../bindings/interrupt-controller/csky,mpintc.txt  | 24 ++-
>>>  drivers/irqchip/irq-csky-mpintc.c  | 78 
>>> +-
>>>  2 files changed, 99 insertions(+), 3 deletions(-)
>>>
>>> diff --git 
>>> a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt 
>>> b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
>>> index ab921f1..364b789 100644
>>> --- a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
>>> +++ b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
>>> @@ -11,6 +11,14 @@ Interrupt number definition:
>>>   16-31  : private  irq, and we use 16 as the co-processor timer.
>>>   31-1024: common irq for soc ip.
>>>  
>>> +Interrupt triger mode:
>>> +  IRQ_TYPE_LEVEL_HIGH (default)
>>> +  IRQ_TYPE_LEVEL_LOW
>>> +  IRQ_TYPE_EDGE_RISING
>>> +  IRQ_TYPE_EDGE_FALLING
>>> +
>>> +Interrupt priority range: 0-255
>>> +
>>>  =
>>>  intc node bindings definition
>>>  =
>>> @@ -26,7 +34,7 @@ intc node bindings definition
>>> - #interrupt-cells
>>> Usage: required
>>> Value type: 
>>> -   Definition: must be <1>
>>> +   Definition: could be <1> or <2>
>>> - interrupt-controller:
>>> Usage: required
>>>  
>>> @@ -35,6 +43,18 @@ Examples:
>>>  
>>> intc: interrupt-controller {
>>> compatible = "csky,mpintc";
>>> -   #interrupt-cells = <1>;
>>> +   #interrupt-cells = <2>;
>>> interrupt-controller;
>>> };
>>> +
>>> +   0: device-example {
>>> +   ...
>>> +   interrupts = <33 IRQ_TYPE_EDGE_RISING>;
>>> +   interrupt-parent = <&intc>;
>>> +   };
>>> +
>>> +   1: device-example {
>>> +   ...
>>> +   interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
>>> +   interrupt-parent = <&intc>;
>>> +   };
>>> diff --git a/drivers/irqchip/irq-csky-mpintc.c 
>>> b/drivers/irqchip/irq-csky-mpintc.c
>>> index c67c961..9edc6d3 100644
>>> --- a/drivers/irqchip/irq-csky-mpintc.c
>>> +++ b/drivers/irqchip/irq-csky-mpintc.c
>>> @@ -29,9 +29,12 @@ static void __iomem *INTCL_base;
>>>  
>>>  #define INTCG_ICTLR0x0
>>>  #define INTCG_CICFGR   0x100
>>> +#define INTCG_CIPRTR   0x200
>>>  #define INTCG_CIDSTR   0x1000
>>>  
>>>  #define INTCL_PICTLR   0x0
>>> +#define INTCL_CFGR 0x14
>>> +#define INTCL_PRTR 0x20
>>>  #define INTCL_SIGR 0x60
>>>  #define INTCL_HPPIR0x68
>>>  #define INTCL_RDYIR0x6c
>>> @@ -73,6 +76,78 @@ static void csky_mpintc_eoi(struct irq_data *d)
>>> writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
>>>  }
>>>  
>>> +static int csky_mpintc_set_type(struct irq_data *d, unsigned int type)
>>> +{
>>> +   unsigned int priority, triger;
>>
>> nit: s/triger/trigger/ everywhere.
> Ok
> 
>>
>>> +   unsigned int offset, bit_offset;
>>> +   void __iomem *reg_base;
>>> +
>>> +   /*
>>> +* type Bit field: | 32 - 12  |  11 - 4  |   3 - 0|
>>> +*   reserved   priority   triger type
>>> +*/
>>> +   triger   = type & IRQ_TYPE_SENSE_MASK;
>>> +   priority = (type >> 4) & 0xff;
>>
>> Definitely not. The Linux API to set the trigger does not carry any
>> priority information, nor should it. Priorities should be set
>> statically, and no driver should ever be able to change it.
> Currently priority in dts is:
> 
>   interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
> 
> change it to:
> 
>   interrupts = <34 IRQ_TYPE_EDGE_RISING priority>;
> 

I don't think you need to change the DT format, as this is quite painful
for users.

> Implement csky own csky_irq_domain_xlate_cells() ...
> 
> int csky_irq_domain_xlate_cells(struct irq_domain *d, struct device_node 
> *ctrlr,
>   const u32 *intspec, unsigned int intsize,
>   irq_hw_number_t *out_hwirq, unsigned int *out_type)
> {
>   if (WARN_ON(intsize < 1))
>   return -EINVAL;
>   *out_hwirq = intspec[0];
>   if (intsize > 1)
>   *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
>   else
>   *out_type = IRQ_TYPE_NONE;
> 
>   if (intsize > 2)
>   setup_priority(d->hwirq, intspec[2]);

That's still a problem. Linux doesn't expect interrupts to have
different priorities. All interrupts are equal in that respect, and
interrupt nesting is not something we expect.

I'd be more confident if you programmed a default priority at boot time,
and completely ign

Re: [PATCH] irqchip/irq-csky-mpintc: Add triger type and priority setting

2019-01-17 Thread Guo Ren
Thx Marc,

On Thu, Jan 17, 2019 at 05:17:45PM +, Marc Zyngier wrote:
> Hi Guo,
> 
> On 15/01/2019 16:36, guo...@kernel.org wrote:
> > From: Guo Ren 
> > 
> > Support 4 triger types:
> >  - IRQ_TYPE_LEVEL_HIGH
> >  - IRQ_TYPE_LEVEL_LOW
> >  - IRQ_TYPE_EDGE_RISING
> >  - IRQ_TYPE_EDGE_FALLING
> > 
> > Support 0-255 priority setting for each irq.
> > 
> > Signed-off-by: Guo Ren 
> > ---
> >  .../bindings/interrupt-controller/csky,mpintc.txt  | 24 ++-
> >  drivers/irqchip/irq-csky-mpintc.c  | 78 
> > +-
> >  2 files changed, 99 insertions(+), 3 deletions(-)
> > 
> > diff --git 
> > a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt 
> > b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> > index ab921f1..364b789 100644
> > --- a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> > @@ -11,6 +11,14 @@ Interrupt number definition:
> >   16-31  : private  irq, and we use 16 as the co-processor timer.
> >   31-1024: common irq for soc ip.
> >  
> > +Interrupt triger mode:
> > +  IRQ_TYPE_LEVEL_HIGH (default)
> > +  IRQ_TYPE_LEVEL_LOW
> > +  IRQ_TYPE_EDGE_RISING
> > +  IRQ_TYPE_EDGE_FALLING
> > +
> > +Interrupt priority range: 0-255
> > +
> >  =
> >  intc node bindings definition
> >  =
> > @@ -26,7 +34,7 @@ intc node bindings definition
> > - #interrupt-cells
> > Usage: required
> > Value type: 
> > -   Definition: must be <1>
> > +   Definition: could be <1> or <2>
> > - interrupt-controller:
> > Usage: required
> >  
> > @@ -35,6 +43,18 @@ Examples:
> >  
> > intc: interrupt-controller {
> > compatible = "csky,mpintc";
> > -   #interrupt-cells = <1>;
> > +   #interrupt-cells = <2>;
> > interrupt-controller;
> > };
> > +
> > +   0: device-example {
> > +   ...
> > +   interrupts = <33 IRQ_TYPE_EDGE_RISING>;
> > +   interrupt-parent = <&intc>;
> > +   };
> > +
> > +   1: device-example {
> > +   ...
> > +   interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
> > +   interrupt-parent = <&intc>;
> > +   };
> > diff --git a/drivers/irqchip/irq-csky-mpintc.c 
> > b/drivers/irqchip/irq-csky-mpintc.c
> > index c67c961..9edc6d3 100644
> > --- a/drivers/irqchip/irq-csky-mpintc.c
> > +++ b/drivers/irqchip/irq-csky-mpintc.c
> > @@ -29,9 +29,12 @@ static void __iomem *INTCL_base;
> >  
> >  #define INTCG_ICTLR0x0
> >  #define INTCG_CICFGR   0x100
> > +#define INTCG_CIPRTR   0x200
> >  #define INTCG_CIDSTR   0x1000
> >  
> >  #define INTCL_PICTLR   0x0
> > +#define INTCL_CFGR 0x14
> > +#define INTCL_PRTR 0x20
> >  #define INTCL_SIGR 0x60
> >  #define INTCL_HPPIR0x68
> >  #define INTCL_RDYIR0x6c
> > @@ -73,6 +76,78 @@ static void csky_mpintc_eoi(struct irq_data *d)
> > writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
> >  }
> >  
> > +static int csky_mpintc_set_type(struct irq_data *d, unsigned int type)
> > +{
> > +   unsigned int priority, triger;
> 
> nit: s/triger/trigger/ everywhere.
Ok

> 
> > +   unsigned int offset, bit_offset;
> > +   void __iomem *reg_base;
> > +
> > +   /*
> > +* type Bit field: | 32 - 12  |  11 - 4  |   3 - 0|
> > +*   reserved   priority   triger type
> > +*/
> > +   triger   = type & IRQ_TYPE_SENSE_MASK;
> > +   priority = (type >> 4) & 0xff;
> 
> Definitely not. The Linux API to set the trigger does not carry any
> priority information, nor should it. Priorities should be set
> statically, and no driver should ever be able to change it.
Currently priority in dts is:

interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;

change it to:

interrupts = <34 IRQ_TYPE_EDGE_RISING priority>;

Implement csky own csky_irq_domain_xlate_cells() ...

int csky_irq_domain_xlate_cells(struct irq_domain *d, struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type)
{
if (WARN_ON(intsize < 1))
return -EINVAL;
*out_hwirq = intspec[0];
if (intsize > 1)
*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
else
*out_type = IRQ_TYPE_NONE;

if (intsize > 2)
setup_priority(d->hwirq, intspec[2]);

return 0;
}
Hmm?

> 
> > +
> > +   switch (triger) {
> > +   case IRQ_TYPE_LEVEL_HIGH:
> > +   triger = 0;
> > +   break;
> > +   case IRQ_TYPE_LEVEL_LOW:
> > +   triger = 1;
> > +   break;
> > +   case IRQ_TYPE_EDGE_RISING:
> > +   triger = 2;
> > +   break;
> > +   case IRQ_TYPE_EDGE_FALLING:
> > +   triger = 3;
> 
> Can you define some macros that represent th

Re: [PATCH] irqchip/irq-csky-mpintc: Add triger type and priority setting

2019-01-17 Thread Marc Zyngier
Hi Guo,

On 15/01/2019 16:36, guo...@kernel.org wrote:
> From: Guo Ren 
> 
> Support 4 triger types:
>  - IRQ_TYPE_LEVEL_HIGH
>  - IRQ_TYPE_LEVEL_LOW
>  - IRQ_TYPE_EDGE_RISING
>  - IRQ_TYPE_EDGE_FALLING
> 
> Support 0-255 priority setting for each irq.
> 
> Signed-off-by: Guo Ren 
> ---
>  .../bindings/interrupt-controller/csky,mpintc.txt  | 24 ++-
>  drivers/irqchip/irq-csky-mpintc.c  | 78 
> +-
>  2 files changed, 99 insertions(+), 3 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt 
> b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> index ab921f1..364b789 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
> @@ -11,6 +11,14 @@ Interrupt number definition:
>   16-31  : private  irq, and we use 16 as the co-processor timer.
>   31-1024: common irq for soc ip.
>  
> +Interrupt triger mode:
> +  IRQ_TYPE_LEVEL_HIGH (default)
> +  IRQ_TYPE_LEVEL_LOW
> +  IRQ_TYPE_EDGE_RISING
> +  IRQ_TYPE_EDGE_FALLING
> +
> +Interrupt priority range: 0-255
> +
>  =
>  intc node bindings definition
>  =
> @@ -26,7 +34,7 @@ intc node bindings definition
>   - #interrupt-cells
>   Usage: required
>   Value type: 
> - Definition: must be <1>
> + Definition: could be <1> or <2>
>   - interrupt-controller:
>   Usage: required
>  
> @@ -35,6 +43,18 @@ Examples:
>  
>   intc: interrupt-controller {
>   compatible = "csky,mpintc";
> - #interrupt-cells = <1>;
> + #interrupt-cells = <2>;
>   interrupt-controller;
>   };
> +
> + 0: device-example {
> + ...
> + interrupts = <33 IRQ_TYPE_EDGE_RISING>;
> + interrupt-parent = <&intc>;
> + };
> +
> + 1: device-example {
> + ...
> + interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
> + interrupt-parent = <&intc>;
> + };
> diff --git a/drivers/irqchip/irq-csky-mpintc.c 
> b/drivers/irqchip/irq-csky-mpintc.c
> index c67c961..9edc6d3 100644
> --- a/drivers/irqchip/irq-csky-mpintc.c
> +++ b/drivers/irqchip/irq-csky-mpintc.c
> @@ -29,9 +29,12 @@ static void __iomem *INTCL_base;
>  
>  #define INTCG_ICTLR  0x0
>  #define INTCG_CICFGR 0x100
> +#define INTCG_CIPRTR 0x200
>  #define INTCG_CIDSTR 0x1000
>  
>  #define INTCL_PICTLR 0x0
> +#define INTCL_CFGR   0x14
> +#define INTCL_PRTR   0x20
>  #define INTCL_SIGR   0x60
>  #define INTCL_HPPIR  0x68
>  #define INTCL_RDYIR  0x6c
> @@ -73,6 +76,78 @@ static void csky_mpintc_eoi(struct irq_data *d)
>   writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
>  }
>  
> +static int csky_mpintc_set_type(struct irq_data *d, unsigned int type)
> +{
> + unsigned int priority, triger;

nit: s/triger/trigger/ everywhere.

> + unsigned int offset, bit_offset;
> + void __iomem *reg_base;
> +
> + /*
> +  * type Bit field: | 32 - 12  |  11 - 4  |   3 - 0|
> +  *   reserved   priority   triger type
> +  */
> + triger   = type & IRQ_TYPE_SENSE_MASK;
> + priority = (type >> 4) & 0xff;

Definitely not. The Linux API to set the trigger does not carry any
priority information, nor should it. Priorities should be set
statically, and no driver should ever be able to change it.

> +
> + switch (triger) {
> + case IRQ_TYPE_LEVEL_HIGH:
> + triger = 0;
> + break;
> + case IRQ_TYPE_LEVEL_LOW:
> + triger = 1;
> + break;
> + case IRQ_TYPE_EDGE_RISING:
> + triger = 2;
> + break;
> + case IRQ_TYPE_EDGE_FALLING:
> + triger = 3;

Can you define some macros that represent these magic values?

> + break;
> + default:
> + triger = 0;
> + break;

If you get an invalid combination, you shouldn't blindly accept it, but
instead return an error.

> + }
> +
> + if (d->hwirq < COMM_IRQ_BASE) {
> + reg_base = this_cpu_read(intcl_reg);

Are you guaranteed to be in a non-preemptible section here? I can see
things going wrong if not.

> +
> + if (triger) {
> + offset = ((d->hwirq * 2) / 32) * 4;
> + bit_offset = (d->hwirq * 2) % 32;

This needs to be turned into a set of macros so that the non-percpu code
can reuse it.

> +
> + writel_relaxed(triger << bit_offset,
> + reg_base + INTCL_CFGR + offset);
> + }
> +
> + if (priority) {
> + offset = ((d->hwirq * 8) / 32) * 4;
> + bit_offset = (d->hwirq * 8) % 32;
> +
> + writel_relaxed(priority << bit_offset,
> + reg_base + INTCL_PRTR

[PATCH] irqchip/irq-csky-mpintc: Add triger type and priority setting

2019-01-15 Thread guoren
From: Guo Ren 

Support 4 triger types:
 - IRQ_TYPE_LEVEL_HIGH
 - IRQ_TYPE_LEVEL_LOW
 - IRQ_TYPE_EDGE_RISING
 - IRQ_TYPE_EDGE_FALLING

Support 0-255 priority setting for each irq.

Signed-off-by: Guo Ren 
---
 .../bindings/interrupt-controller/csky,mpintc.txt  | 24 ++-
 drivers/irqchip/irq-csky-mpintc.c  | 78 +-
 2 files changed, 99 insertions(+), 3 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt 
b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
index ab921f1..364b789 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
@@ -11,6 +11,14 @@ Interrupt number definition:
  16-31  : private  irq, and we use 16 as the co-processor timer.
  31-1024: common irq for soc ip.
 
+Interrupt triger mode:
+  IRQ_TYPE_LEVEL_HIGH (default)
+  IRQ_TYPE_LEVEL_LOW
+  IRQ_TYPE_EDGE_RISING
+  IRQ_TYPE_EDGE_FALLING
+
+Interrupt priority range: 0-255
+
 =
 intc node bindings definition
 =
@@ -26,7 +34,7 @@ intc node bindings definition
- #interrupt-cells
Usage: required
Value type: 
-   Definition: must be <1>
+   Definition: could be <1> or <2>
- interrupt-controller:
Usage: required
 
@@ -35,6 +43,18 @@ Examples:
 
intc: interrupt-controller {
compatible = "csky,mpintc";
-   #interrupt-cells = <1>;
+   #interrupt-cells = <2>;
interrupt-controller;
};
+
+   0: device-example {
+   ...
+   interrupts = <33 IRQ_TYPE_EDGE_RISING>;
+   interrupt-parent = <&intc>;
+   };
+
+   1: device-example {
+   ...
+   interrupts = <34 ((priority << 4) | IRQ_TYPE_EDGE_RISING)>;
+   interrupt-parent = <&intc>;
+   };
diff --git a/drivers/irqchip/irq-csky-mpintc.c 
b/drivers/irqchip/irq-csky-mpintc.c
index c67c961..9edc6d3 100644
--- a/drivers/irqchip/irq-csky-mpintc.c
+++ b/drivers/irqchip/irq-csky-mpintc.c
@@ -29,9 +29,12 @@ static void __iomem *INTCL_base;
 
 #define INTCG_ICTLR0x0
 #define INTCG_CICFGR   0x100
+#define INTCG_CIPRTR   0x200
 #define INTCG_CIDSTR   0x1000
 
 #define INTCL_PICTLR   0x0
+#define INTCL_CFGR 0x14
+#define INTCL_PRTR 0x20
 #define INTCL_SIGR 0x60
 #define INTCL_HPPIR0x68
 #define INTCL_RDYIR0x6c
@@ -73,6 +76,78 @@ static void csky_mpintc_eoi(struct irq_data *d)
writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
 }
 
+static int csky_mpintc_set_type(struct irq_data *d, unsigned int type)
+{
+   unsigned int priority, triger;
+   unsigned int offset, bit_offset;
+   void __iomem *reg_base;
+
+   /*
+* type Bit field: | 32 - 12  |  11 - 4  |   3 - 0|
+*   reserved   priority   triger type
+*/
+   triger   = type & IRQ_TYPE_SENSE_MASK;
+   priority = (type >> 4) & 0xff;
+
+   switch (triger) {
+   case IRQ_TYPE_LEVEL_HIGH:
+   triger = 0;
+   break;
+   case IRQ_TYPE_LEVEL_LOW:
+   triger = 1;
+   break;
+   case IRQ_TYPE_EDGE_RISING:
+   triger = 2;
+   break;
+   case IRQ_TYPE_EDGE_FALLING:
+   triger = 3;
+   break;
+   default:
+   triger = 0;
+   break;
+   }
+
+   if (d->hwirq < COMM_IRQ_BASE) {
+   reg_base = this_cpu_read(intcl_reg);
+
+   if (triger) {
+   offset = ((d->hwirq * 2) / 32) * 4;
+   bit_offset = (d->hwirq * 2) % 32;
+
+   writel_relaxed(triger << bit_offset,
+   reg_base + INTCL_CFGR + offset);
+   }
+
+   if (priority) {
+   offset = ((d->hwirq * 8) / 32) * 4;
+   bit_offset = (d->hwirq * 8) % 32;
+
+   writel_relaxed(priority << bit_offset,
+   reg_base + INTCL_PRTR + offset);
+   }
+   } else {
+   reg_base = INTCG_base;
+
+   if (triger) {
+   offset = (((d->hwirq - COMM_IRQ_BASE) * 2) / 32) * 4;
+   bit_offset = ((d->hwirq - COMM_IRQ_BASE) * 2) % 32;
+
+   writel_relaxed(triger << bit_offset,
+   reg_base + INTCG_CICFGR + offset);
+   }
+
+   if (priority) {
+   offset = (((d->hwirq - COMM_IRQ_BASE) * 8) / 32) * 4;
+   bit_offset = ((d->hwirq - COMM_IRQ_BASE) * 8) % 32;
+
+   writel_relaxed(priority << bit_offset,
+   reg_base + INTCG_CIPRTR + offset);
+   }
+