Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-30 Thread Grant Likely
On Wed, 28 Mar 2012 18:41:03 -0700, David Daney  wrote:
> On 03/28/2012 03:22 PM, Grant Likely wrote:
> > On Tue, 27 Mar 2012 11:24:51 -0700, David Daney  
> > wrote:
> >> On 03/26/2012 06:56 PM, Rob Herring wrote:
> >>> On 03/26/2012 02:31 PM, David Daney wrote:
>  From: David Daney
> >> [...]
>  +static int octeon_irq_ciu_map(struct irq_domain *d,
>  +  unsigned int virq, irq_hw_number_t hw)
>  +{
>  +unsigned int line = hw>>   6;
>  +unsigned int bit = hw&   63;
>  +
>  +if (virq>= 256)
>  +return -EINVAL;
> >>>
> >>> Drop this. You should not care what the virq numbers are.
> >>
> >>
> >> I care that they don't overflow the width of octeon_irq_ciu_to_irq (a u8).
> >>
> >> So really I want to say:
> >>
> >>  if (virq>= (1<<  sizeof (octeon_irq_ciu_to_irq[0][0]))) {
> >>  WARN(...);
> >>  return -EINVAL;
> >>  }
> >>
> >>
> >> I need a map external to any one irq_domain.  The irq handling code
> >> handles sources that come from two separate irq_domains, as well as irqs
> >> that are not part of any domain.
> >
> > You can get past this limitation by using the struct irq_data .hwirq and
> > .domain members for the irq ==>  hwirq translation, and for hwirq ==>
> > irq the code should already have the context to know which user it is.
> >
> > For the irqs that are not covered by an irq_domain, the driver is free
> > to set the .hwirq value directly.  Ultimately however, it will
> > probably be best to add an irq domain for those users also.
> >
> > ...
> >
> > Howver, I don't understand where the risk is in overflowing
> > octeon_irq_ciu_to_irq[][].  From what I can see, the virq value isn't
> > used at all to calculate the array dereference.  line and bit are
> > calculated from the hwirq value.  What am I missing?
> >
> 
> We do the opposite.  We extract the hwirq value from the interrupt 
> controller and then look up virq in the table.  If the range of virq 
> overflows the width of u8, we would end up calling do_IRQ() with a bad 
> value.  Also this dispatch code is not aware of the various irq_domains 
> and non irq_domain irqs, it is a single function that handles them all 
> calling do_IRQ() with whatever it looks up in the table.
> 
> We could use a wider type for this lookup array, but that would increase 
> the cache footprint of the irq dispatcher...

Ah, I missed that octeon_irq_ciu_to_irq was a u8.  You're using Linux
though; your cache footprint is already trashed.  :-) Please just use
unsigned int for all irq storage since that is the type used by all
core interrupt handling code.  Anything else smells like premature
optimization.  :-)

Besides, now that we have it you should plan to switch to the common
mechanism of irq_domain for hwirq->irq reverse mapping anyway.  It
doesn't make any sense for each platform to reinvent it's own reverse
mapping scheme.

g.
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread David Daney

On 03/28/2012 03:08 PM, Grant Likely wrote:

On Wed, 28 Mar 2012 09:16:05 -0700, David Daney  wrote:

On 03/28/2012 07:21 AM, Rob Herring wrote:

On 03/27/2012 05:31 PM, David Daney wrote:

On 03/27/2012 03:05 PM, Rob Herring wrote:

On 03/27/2012 01:24 PM, David Daney wrote:

On 03/26/2012 06:56 PM, Rob Herring wrote:

On 03/26/2012 02:31 PM, David Daney wrote:

From: David Daney

[...]

+static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int
bit)
+{
+bool edge = false;
+
+if (line == 0)
+switch (bit) {
+case 48 ... 49: /* GMX DRP */
+case 50: /* IPD_DRP */
+case 52 ... 55: /* Timers */
+case 58: /* MPI */
+edge = true;
+break;
+default:
+break;
+}
+else /* line == 1 */
+switch (bit) {
+case 47: /* PTP */
+edge = true;
+break;
+default:
+break;
+}
+return edge;


Moving in the right direction, but I still don't get why this is not in
the CIU binding as a 3rd cell?


There are a several reasons, in no particular order they are:

o There is no 3rd cell.  The bindings were discussed with Grant here:
 http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html



Then add one.


I can't.  The dtb is already programmed into the bootloader ROMs,
changing the kernel code will not change that.  It is fait accompli.




o The edge/level thing cannot be changed, and the irq lines don't leave
the SOC, so hard coding it is possible.


Right, but DT describes h/w connections and this is an aspect of the
connection. This may be fixed for the SOC, but it's not fixed for the
CIU (i.e. could change in future chips), right?


In theory yes.  However:

1) The chip designers will not change it.

2) There will likely be no more designs with either CIU or CIU2, so we
know what all the different possibilities are today.

When CIU3 is deployed, we will use the lessons we have learned to do
things the Right Way.



There's 2 reasons why you would not put this into DTS:

- All irq lines' trigger type are the same, fixed and known.
- You can read a register to tell you the trigger type.

Even if it's not going to change ever, it's still worth putting into the
DTS as it is well suited for holding that data and it is just data.


Agreed that it could be in the DTS, and retrospect it probably should
have been put in the DTS, but it wasn't.  So I think what we have now is
a workable solution, and has the added attraction of working with
already deployed boards.


Aren't you building in the dtb to the kernel?


No.  This seems like a bit of a disconnect in this discussion.  From the
cover-letter:

o A device tree template is statically linked into the kernel image.
Based on SOC type and board type, legacy configuration probing code
is used to prune and patch the device tree template.

o New SOCs and boards will directly use a device tree passed by the
bootloader.


I think the real surprise here is that Octeron is depending on a
masked-in copy of the device tree.  It has alwasy been a strong
recommendation to store the .dtb along side the kernel in reflashable
storage for exactly the reason that updates may be required.  Review
is vitally important, but nobody can foresee all the implications
until the bindings are actually used.

I'm not going to harp over this, I understand that you're hamstrung
here, but please do pass on to the firmware engineers that storing the
.dtb in masked rom is risky.



Well in most cases it is not masked ROM, but rather some sort of 
persistent but modifiable storage.  But still getting people (both 
internal and external) to update it is not as easy as living with the 
status quo.  The idea is that someone should be able to get a kernel.orq 
kernel and use it, without having to re-flash their board's bootloader.


David Daney

___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread David Daney

On 03/28/2012 03:22 PM, Grant Likely wrote:

On Tue, 27 Mar 2012 11:24:51 -0700, David Daney  wrote:

On 03/26/2012 06:56 PM, Rob Herring wrote:

On 03/26/2012 02:31 PM, David Daney wrote:

From: David Daney

[...]

+static int octeon_irq_ciu_map(struct irq_domain *d,
+ unsigned int virq, irq_hw_number_t hw)
+{
+   unsigned int line = hw>>   6;
+   unsigned int bit = hw&   63;
+
+   if (virq>= 256)
+   return -EINVAL;


Drop this. You should not care what the virq numbers are.



I care that they don't overflow the width of octeon_irq_ciu_to_irq (a u8).

So really I want to say:

 if (virq>= (1<<  sizeof (octeon_irq_ciu_to_irq[0][0]))) {
 WARN(...);
 return -EINVAL;
 }


I need a map external to any one irq_domain.  The irq handling code
handles sources that come from two separate irq_domains, as well as irqs
that are not part of any domain.


You can get past this limitation by using the struct irq_data .hwirq and
.domain members for the irq ==>  hwirq translation, and for hwirq ==>
irq the code should already have the context to know which user it is.

For the irqs that are not covered by an irq_domain, the driver is free
to set the .hwirq value directly.  Ultimately however, it will
probably be best to add an irq domain for those users also.

...

Howver, I don't understand where the risk is in overflowing
octeon_irq_ciu_to_irq[][].  From what I can see, the virq value isn't
used at all to calculate the array dereference.  line and bit are
calculated from the hwirq value.  What am I missing?



We do the opposite.  We extract the hwirq value from the interrupt 
controller and then look up virq in the table.  If the range of virq 
overflows the width of u8, we would end up calling do_IRQ() with a bad 
value.  Also this dispatch code is not aware of the various irq_domains 
and non irq_domain irqs, it is a single function that handles them all 
calling do_IRQ() with whatever it looks up in the table.


We could use a wider type for this lookup array, but that would increase 
the cache footprint of the irq dispatcher...



David Daney

David Daney


g.



___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread David Daney

On 03/28/2012 03:31 PM, Grant Likely wrote:

On Mon, 26 Mar 2012 12:31:19 -0700, David Daney  wrote:

From: David Daney

Create two domains.  One for the GPIO lines, and the other for on-chip
sources.

Signed-off-by: David Daney
---

[...]

+struct octeon_irq_gpio_domain_data {
+   unsigned int base_hwirq;
+};


Hmmm...


+static int octeon_irq_gpio_xlat(struct irq_domain *d,
+   struct device_node *node,
+   const u32 *intspec,
+   unsigned int intsize,
+   unsigned long *out_hwirq,
+   unsigned int *out_type)
+{

[...]

+   *out_hwirq = gpiod->base_hwirq + pin;


...base_hwirq is only used here...

[...]

+   gpiod = kzalloc(sizeof (*gpiod), GFP_KERNEL);
+   if (gpiod) {
+   /* gpio domain host_data is the base hwirq number. */
+   gpiod->base_hwirq = 16;
+   irq_domain_add_linear(gpio_node, 
16,&octeon_irq_domain_gpio_ops, gpiod);


... and it is unconditionally set to 16.  It looks to me like
base_hwirq and the associated kzalloc() is unnecessary.



There is a little information asymmetry here.  You don't know that I 
have a patch queued up to add another user of the GPIO irq_domain that 
has a different base_hwirq.


I could re-do this to hard code it, and then add it back.  But it would 
really just be busy work.


David Daney
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread Grant Likely
On Mon, 26 Mar 2012 12:31:19 -0700, David Daney  wrote:
> From: David Daney 
> 
> Create two domains.  One for the GPIO lines, and the other for on-chip
> sources.
> 
> Signed-off-by: David Daney 
> ---
[...]
> +struct octeon_irq_gpio_domain_data {
> + unsigned int base_hwirq;
> +};

Hmmm...

> +static int octeon_irq_gpio_xlat(struct irq_domain *d,
> + struct device_node *node,
> + const u32 *intspec,
> + unsigned int intsize,
> + unsigned long *out_hwirq,
> + unsigned int *out_type)
> +{
[...]
> + *out_hwirq = gpiod->base_hwirq + pin;

...base_hwirq is only used here...

[...]
> + gpiod = kzalloc(sizeof (*gpiod), GFP_KERNEL);
> + if (gpiod) {
> + /* gpio domain host_data is the base hwirq number. */
> + gpiod->base_hwirq = 16;
> + irq_domain_add_linear(gpio_node, 16, 
> &octeon_irq_domain_gpio_ops, gpiod);

... and it is unconditionally set to 16.  It looks to me like
base_hwirq and the associated kzalloc() is unnecessary.

g.
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread Grant Likely
On Tue, 27 Mar 2012 11:24:51 -0700, David Daney  wrote:
> On 03/26/2012 06:56 PM, Rob Herring wrote:
> > On 03/26/2012 02:31 PM, David Daney wrote:
> >> From: David Daney
> [...]
> >> +static int octeon_irq_ciu_map(struct irq_domain *d,
> >> +unsigned int virq, irq_hw_number_t hw)
> >> +{
> >> +  unsigned int line = hw>>  6;
> >> +  unsigned int bit = hw&  63;
> >> +
> >> +  if (virq>= 256)
> >> +  return -EINVAL;
> >
> > Drop this. You should not care what the virq numbers are.
> 
> 
> I care that they don't overflow the width of octeon_irq_ciu_to_irq (a u8).
> 
> So really I want to say:
> 
> if (virq >= (1 << sizeof (octeon_irq_ciu_to_irq[0][0]))) {
> WARN(...);
> return -EINVAL;
> }
> 
> 
> I need a map external to any one irq_domain.  The irq handling code 
> handles sources that come from two separate irq_domains, as well as irqs 
> that are not part of any domain.

You can get past this limitation by using the struct irq_data .hwirq and
.domain members for the irq ==> hwirq translation, and for hwirq ==>
irq the code should already have the context to know which user it is.

For the irqs that are not covered by an irq_domain, the driver is free
to set the .hwirq value directly.  Ultimately however, it will
probably be best to add an irq domain for those users also.

...

Howver, I don't understand where the risk is in overflowing
octeon_irq_ciu_to_irq[][].  From what I can see, the virq value isn't
used at all to calculate the array dereference.  line and bit are
calculated from the hwirq value.  What am I missing?

g.
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread Grant Likely
On Wed, 28 Mar 2012 09:16:05 -0700, David Daney  wrote:
> On 03/28/2012 07:21 AM, Rob Herring wrote:
> > On 03/27/2012 05:31 PM, David Daney wrote:
> >> On 03/27/2012 03:05 PM, Rob Herring wrote:
> >>> On 03/27/2012 01:24 PM, David Daney wrote:
>  On 03/26/2012 06:56 PM, Rob Herring wrote:
> > On 03/26/2012 02:31 PM, David Daney wrote:
> >> From: David Daney
>  [...]
> >> +static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int
> >> bit)
> >> +{
> >> +bool edge = false;
> >> +
> >> +if (line == 0)
> >> +switch (bit) {
> >> +case 48 ... 49: /* GMX DRP */
> >> +case 50: /* IPD_DRP */
> >> +case 52 ... 55: /* Timers */
> >> +case 58: /* MPI */
> >> +edge = true;
> >> +break;
> >> +default:
> >> +break;
> >> +}
> >> +else /* line == 1 */
> >> +switch (bit) {
> >> +case 47: /* PTP */
> >> +edge = true;
> >> +break;
> >> +default:
> >> +break;
> >> +}
> >> +return edge;
> >
> > Moving in the right direction, but I still don't get why this is not in
> > the CIU binding as a 3rd cell?
> 
>  There are a several reasons, in no particular order they are:
> 
>  o There is no 3rd cell.  The bindings were discussed with Grant here:
>  http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html
> 
> >>>
> >>> Then add one.
> >>
> >> I can't.  The dtb is already programmed into the bootloader ROMs,
> >> changing the kernel code will not change that.  It is fait accompli.
> >>
> >>>
>  o The edge/level thing cannot be changed, and the irq lines don't leave
>  the SOC, so hard coding it is possible.
> >>>
> >>> Right, but DT describes h/w connections and this is an aspect of the
> >>> connection. This may be fixed for the SOC, but it's not fixed for the
> >>> CIU (i.e. could change in future chips), right?
> >>
> >> In theory yes.  However:
> >>
> >> 1) The chip designers will not change it.
> >>
> >> 2) There will likely be no more designs with either CIU or CIU2, so we
> >> know what all the different possibilities are today.
> >>
> >> When CIU3 is deployed, we will use the lessons we have learned to do
> >> things the Right Way.
> >>
> >>>
> >>> There's 2 reasons why you would not put this into DTS:
> >>>
> >>> - All irq lines' trigger type are the same, fixed and known.
> >>> - You can read a register to tell you the trigger type.
> >>>
> >>> Even if it's not going to change ever, it's still worth putting into the
> >>> DTS as it is well suited for holding that data and it is just data.
> >>
> >> Agreed that it could be in the DTS, and retrospect it probably should
> >> have been put in the DTS, but it wasn't.  So I think what we have now is
> >> a workable solution, and has the added attraction of working with
> >> already deployed boards.
> >
> > Aren't you building in the dtb to the kernel?
> 
> No.  This seems like a bit of a disconnect in this discussion.  From the 
> cover-letter:
> 
> o A device tree template is statically linked into the kernel image.
>Based on SOC type and board type, legacy configuration probing code
>is used to prune and patch the device tree template.
> 
> o New SOCs and boards will directly use a device tree passed by the
>bootloader.

I think the real surprise here is that Octeron is depending on a
masked-in copy of the device tree.  It has alwasy been a strong
recommendation to store the .dtb along side the kernel in reflashable
storage for exactly the reason that updates may be required.  Review
is vitally important, but nobody can foresee all the implications
until the bindings are actually used.

I'm not going to harp over this, I understand that you're hamstrung
here, but please do pass on to the firmware engineers that storing the
.dtb in masked rom is risky.

> 
> 
> >
> > It could be argued it doesn't matter what you deployed without upstream
> > review.
> 
> A moot point, as all the bindings were reviewed with Grant Likely 
> precisely for the reason of minimizing surprises when merging upstream. 
>   In the intervening months, we have found a few rough edges like this, 
> but we cannot say that there was no upstream review.

Yes, you've been good about this and I much appreciate it.

g.
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread David Daney

On 03/28/2012 07:21 AM, Rob Herring wrote:

On 03/27/2012 05:31 PM, David Daney wrote:

On 03/27/2012 03:05 PM, Rob Herring wrote:

On 03/27/2012 01:24 PM, David Daney wrote:

On 03/26/2012 06:56 PM, Rob Herring wrote:

On 03/26/2012 02:31 PM, David Daney wrote:

From: David Daney

[...]

+static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int
bit)
+{
+bool edge = false;
+
+if (line == 0)
+switch (bit) {
+case 48 ... 49: /* GMX DRP */
+case 50: /* IPD_DRP */
+case 52 ... 55: /* Timers */
+case 58: /* MPI */
+edge = true;
+break;
+default:
+break;
+}
+else /* line == 1 */
+switch (bit) {
+case 47: /* PTP */
+edge = true;
+break;
+default:
+break;
+}
+return edge;


Moving in the right direction, but I still don't get why this is not in
the CIU binding as a 3rd cell?


There are a several reasons, in no particular order they are:

o There is no 3rd cell.  The bindings were discussed with Grant here:
http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html



Then add one.


I can't.  The dtb is already programmed into the bootloader ROMs,
changing the kernel code will not change that.  It is fait accompli.




o The edge/level thing cannot be changed, and the irq lines don't leave
the SOC, so hard coding it is possible.


Right, but DT describes h/w connections and this is an aspect of the
connection. This may be fixed for the SOC, but it's not fixed for the
CIU (i.e. could change in future chips), right?


In theory yes.  However:

1) The chip designers will not change it.

2) There will likely be no more designs with either CIU or CIU2, so we
know what all the different possibilities are today.

When CIU3 is deployed, we will use the lessons we have learned to do
things the Right Way.



There's 2 reasons why you would not put this into DTS:

- All irq lines' trigger type are the same, fixed and known.
- You can read a register to tell you the trigger type.

Even if it's not going to change ever, it's still worth putting into the
DTS as it is well suited for holding that data and it is just data.


Agreed that it could be in the DTS, and retrospect it probably should
have been put in the DTS, but it wasn't.  So I think what we have now is
a workable solution, and has the added attraction of working with
already deployed boards.


Aren't you building in the dtb to the kernel?


No.  This seems like a bit of a disconnect in this discussion.  From the 
cover-letter:


o A device tree template is statically linked into the kernel image.
  Based on SOC type and board type, legacy configuration probing code
  is used to prune and patch the device tree template.

o New SOCs and boards will directly use a device tree passed by the
  bootloader.




It could be argued it doesn't matter what you deployed without upstream
review.


A moot point, as all the bindings were reviewed with Grant Likely 
precisely for the reason of minimizing surprises when merging upstream. 
 In the intervening months, we have found a few rough edges like this, 
but we cannot say that there was no upstream review.




But as long as this contained then this one is fine with me.
However, this needs to be understood for each binding as I'm sure there
must be some blocks which will get reused.


Yes, there will be reuse.  There has in fact been reuse since the 
bindings were created, and for the most part things are going smoothly.



Thanks,
David Daney
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-28 Thread Rob Herring
On 03/27/2012 05:31 PM, David Daney wrote:
> On 03/27/2012 03:05 PM, Rob Herring wrote:
>> On 03/27/2012 01:24 PM, David Daney wrote:
>>> On 03/26/2012 06:56 PM, Rob Herring wrote:
 On 03/26/2012 02:31 PM, David Daney wrote:
> From: David Daney
>>> [...]
> +static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int
> bit)
> +{
> +bool edge = false;
> +
> +if (line == 0)
> +switch (bit) {
> +case 48 ... 49: /* GMX DRP */
> +case 50: /* IPD_DRP */
> +case 52 ... 55: /* Timers */
> +case 58: /* MPI */
> +edge = true;
> +break;
> +default:
> +break;
> +}
> +else /* line == 1 */
> +switch (bit) {
> +case 47: /* PTP */
> +edge = true;
> +break;
> +default:
> +break;
> +}
> +return edge;

 Moving in the right direction, but I still don't get why this is not in
 the CIU binding as a 3rd cell?
>>>
>>> There are a several reasons, in no particular order they are:
>>>
>>> o There is no 3rd cell.  The bindings were discussed with Grant here:
>>>http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html
>>>
>>
>> Then add one.
> 
> I can't.  The dtb is already programmed into the bootloader ROMs,
> changing the kernel code will not change that.  It is fait accompli.
> 
>>
>>> o The edge/level thing cannot be changed, and the irq lines don't leave
>>> the SOC, so hard coding it is possible.
>>
>> Right, but DT describes h/w connections and this is an aspect of the
>> connection. This may be fixed for the SOC, but it's not fixed for the
>> CIU (i.e. could change in future chips), right?
> 
> In theory yes.  However:
> 
> 1) The chip designers will not change it.
> 
> 2) There will likely be no more designs with either CIU or CIU2, so we
> know what all the different possibilities are today.
> 
> When CIU3 is deployed, we will use the lessons we have learned to do
> things the Right Way.
> 
>>
>> There's 2 reasons why you would not put this into DTS:
>>
>> - All irq lines' trigger type are the same, fixed and known.
>> - You can read a register to tell you the trigger type.
>>
>> Even if it's not going to change ever, it's still worth putting into the
>> DTS as it is well suited for holding that data and it is just data.
> 
> Agreed that it could be in the DTS, and retrospect it probably should
> have been put in the DTS, but it wasn't.  So I think what we have now is
> a workable solution, and has the added attraction of working with
> already deployed boards.

Aren't you building in the dtb to the kernel?

It could be argued it doesn't matter what you deployed without upstream
review. But as long as this contained then this one is fine with me.
However, this needs to be understood for each binding as I'm sure there
must be some blocks which will get reused.

Rob
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-27 Thread David Daney

On 03/27/2012 03:05 PM, Rob Herring wrote:

On 03/27/2012 01:24 PM, David Daney wrote:

On 03/26/2012 06:56 PM, Rob Herring wrote:

On 03/26/2012 02:31 PM, David Daney wrote:

From: David Daney

[...]

+static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
+{
+bool edge = false;
+
+if (line == 0)
+switch (bit) {
+case 48 ... 49: /* GMX DRP */
+case 50: /* IPD_DRP */
+case 52 ... 55: /* Timers */
+case 58: /* MPI */
+edge = true;
+break;
+default:
+break;
+}
+else /* line == 1 */
+switch (bit) {
+case 47: /* PTP */
+edge = true;
+break;
+default:
+break;
+}
+return edge;


Moving in the right direction, but I still don't get why this is not in
the CIU binding as a 3rd cell?


There are a several reasons, in no particular order they are:

o There is no 3rd cell.  The bindings were discussed with Grant here:
   http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html



Then add one.


I can't.  The dtb is already programmed into the bootloader ROMs, 
changing the kernel code will not change that.  It is fait accompli.





o The edge/level thing cannot be changed, and the irq lines don't leave
the SOC, so hard coding it is possible.


Right, but DT describes h/w connections and this is an aspect of the
connection. This may be fixed for the SOC, but it's not fixed for the
CIU (i.e. could change in future chips), right?


In theory yes.  However:

1) The chip designers will not change it.

2) There will likely be no more designs with either CIU or CIU2, so we 
know what all the different possibilities are today.


When CIU3 is deployed, we will use the lessons we have learned to do 
things the Right Way.




There's 2 reasons why you would not put this into DTS:

- All irq lines' trigger type are the same, fixed and known.
- You can read a register to tell you the trigger type.

Even if it's not going to change ever, it's still worth putting into the
DTS as it is well suited for holding that data and it is just data.


Agreed that it could be in the DTS, and retrospect it probably should 
have been put in the DTS, but it wasn't.  So I think what we have now is 
a workable solution, and has the added attraction of working with 
already deployed boards.


David Daney
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-27 Thread Rob Herring
On 03/27/2012 01:24 PM, David Daney wrote:
> On 03/26/2012 06:56 PM, Rob Herring wrote:
>> On 03/26/2012 02:31 PM, David Daney wrote:
>>> From: David Daney
> [...]
>>> +static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
>>> +{
>>> +bool edge = false;
>>> +
>>> +if (line == 0)
>>> +switch (bit) {
>>> +case 48 ... 49: /* GMX DRP */
>>> +case 50: /* IPD_DRP */
>>> +case 52 ... 55: /* Timers */
>>> +case 58: /* MPI */
>>> +edge = true;
>>> +break;
>>> +default:
>>> +break;
>>> +}
>>> +else /* line == 1 */
>>> +switch (bit) {
>>> +case 47: /* PTP */
>>> +edge = true;
>>> +break;
>>> +default:
>>> +break;
>>> +}
>>> +return edge;
>>
>> Moving in the right direction, but I still don't get why this is not in
>> the CIU binding as a 3rd cell?
> 
> There are a several reasons, in no particular order they are:
> 
> o There is no 3rd cell.  The bindings were discussed with Grant here:
>   http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html
> 

Then add one.

> o The edge/level thing cannot be changed, and the irq lines don't leave
> the SOC, so hard coding it is possible.

Right, but DT describes h/w connections and this is an aspect of the
connection. This may be fixed for the SOC, but it's not fixed for the
CIU (i.e. could change in future chips), right?

There's 2 reasons why you would not put this into DTS:

- All irq lines' trigger type are the same, fixed and known.
- You can read a register to tell you the trigger type.

Even if it's not going to change ever, it's still worth putting into the
DTS as it is well suited for holding that data and it is just data.

> 
>>
>>> +}
>>> +
>>> +struct octeon_irq_gpio_domain_data {
>>> +unsigned int base_hwirq;
>>> +};
>>> +
>>> +static int octeon_irq_gpio_xlat(struct irq_domain *d,
>>> +struct device_node *node,
>>> +const u32 *intspec,
>>> +unsigned int intsize,
>>> +unsigned long *out_hwirq,
>>> +unsigned int *out_type)
>>> +{
>>> +unsigned int type;
>>> +unsigned int pin;
>>> +unsigned int trigger;
>>> +bool set_edge_handler = false;
>>> +struct octeon_irq_gpio_domain_data *gpiod;
>>> +
>>> +if (d->of_node != node)
>>> +return -EINVAL;
>>> +
>>> +if (intsize<  2)
>>> +return -EINVAL;
>>> +
>>> +pin = intspec[0];
>>> +if (pin>= 16)
>>> +return -EINVAL;
>>> +
>>> +trigger = intspec[1];
>>> +
>>> +switch (trigger) {
>>> +case 1:
>>> +type = IRQ_TYPE_EDGE_RISING;
>>> +set_edge_handler = true;
>>
>> This is never used.
> 
> Right, it was leftover from the previous version.
> 
>>
>>> +break;
>>> +case 2:
>>> +type = IRQ_TYPE_EDGE_FALLING;
>>> +set_edge_handler = true;
>>> +break;
>>> +case 4:
>>> +type = IRQ_TYPE_LEVEL_HIGH;
>>> +break;
>>> +case 8:
>>> +type = IRQ_TYPE_LEVEL_LOW;
>>> +break;
>>> +default:
>>> +pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
>>> +   node->name,
>>> +   trigger);
>>> +type = IRQ_TYPE_LEVEL_LOW;
>>> +break;
>>> +}
>>> +*out_type = type;
>>
>> Can't you get rid of the whole switch statement and just do:
>>
>> *out_type = intspec[1];
> 
> That wouldn't catch erroneous values like 6.
> 

if (!x || fls(x) != ffs(x))
// ERROR


>>
> [...]
>>> +static int octeon_irq_ciu_map(struct irq_domain *d,
>>> +  unsigned int virq, irq_hw_number_t hw)
>>> +{
>>> +unsigned int line = hw>>  6;
>>> +unsigned int bit = hw&  63;
>>> +
>>> +if (virq>= 256)
>>> +return -EINVAL;
>>
>> Drop this. You should not care what the virq numbers are.
> 
> 
> I care that they don't overflow the width of octeon_irq_ciu_to_irq (a u8).
> 
> So really I want to say:
> 
>if (virq >= (1 << sizeof (octeon_irq_ciu_to_irq[0][0]))) {
>WARN(...);
>return -EINVAL;
>}
> 
> 
> I need a map external to any one irq_domain.  The irq handling code
> handles sources that come from two separate irq_domains, as well as irqs
> that are not part of any domain.
> 

Okay, but ultimately this needs to go. The irqdomain provides no
guarantee of irq numbers assigned.

Rob
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-27 Thread David Daney

On 03/26/2012 06:56 PM, Rob Herring wrote:

On 03/26/2012 02:31 PM, David Daney wrote:

From: David Daney

[...]

+static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
+{
+   bool edge = false;
+
+   if (line == 0)
+   switch (bit) {
+   case 48 ... 49: /* GMX DRP */
+   case 50: /* IPD_DRP */
+   case 52 ... 55: /* Timers */
+   case 58: /* MPI */
+   edge = true;
+   break;
+   default:
+   break;
+   }
+   else /* line == 1 */
+   switch (bit) {
+   case 47: /* PTP */
+   edge = true;
+   break;
+   default:
+   break;
+   }
+   return edge;


Moving in the right direction, but I still don't get why this is not in
the CIU binding as a 3rd cell?


There are a several reasons, in no particular order they are:

o There is no 3rd cell.  The bindings were discussed with Grant here:
  http://www.linux-mips.org/archives/linux-mips/2011-05/msg00355.html

o The edge/level thing cannot be changed, and the irq lines don't leave 
the SOC, so hard coding it is possible.





+}
+
+struct octeon_irq_gpio_domain_data {
+   unsigned int base_hwirq;
+};
+
+static int octeon_irq_gpio_xlat(struct irq_domain *d,
+   struct device_node *node,
+   const u32 *intspec,
+   unsigned int intsize,
+   unsigned long *out_hwirq,
+   unsigned int *out_type)
+{
+   unsigned int type;
+   unsigned int pin;
+   unsigned int trigger;
+   bool set_edge_handler = false;
+   struct octeon_irq_gpio_domain_data *gpiod;
+
+   if (d->of_node != node)
+   return -EINVAL;
+
+   if (intsize<  2)
+   return -EINVAL;
+
+   pin = intspec[0];
+   if (pin>= 16)
+   return -EINVAL;
+
+   trigger = intspec[1];
+
+   switch (trigger) {
+   case 1:
+   type = IRQ_TYPE_EDGE_RISING;
+   set_edge_handler = true;


This is never used.


Right, it was leftover from the previous version.




+   break;
+   case 2:
+   type = IRQ_TYPE_EDGE_FALLING;
+   set_edge_handler = true;
+   break;
+   case 4:
+   type = IRQ_TYPE_LEVEL_HIGH;
+   break;
+   case 8:
+   type = IRQ_TYPE_LEVEL_LOW;
+   break;
+   default:
+   pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
+  node->name,
+  trigger);
+   type = IRQ_TYPE_LEVEL_LOW;
+   break;
+   }
+   *out_type = type;


Can't you get rid of the whole switch statement and just do:

*out_type = intspec[1];


That wouldn't catch erroneous values like 6.




[...]

+static int octeon_irq_ciu_map(struct irq_domain *d,
+ unsigned int virq, irq_hw_number_t hw)
+{
+   unsigned int line = hw>>  6;
+   unsigned int bit = hw&  63;
+
+   if (virq>= 256)
+   return -EINVAL;


Drop this. You should not care what the virq numbers are.



I care that they don't overflow the width of octeon_irq_ciu_to_irq (a u8).

So really I want to say:

   if (virq >= (1 << sizeof (octeon_irq_ciu_to_irq[0][0]))) {
   WARN(...);
   return -EINVAL;
   }


I need a map external to any one irq_domain.  The irq handling code 
handles sources that come from two separate irq_domains, as well as irqs 
that are not part of any domain.



Thanks for looking at this again,  I will re-spin the patch,
David Daney
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-26 Thread Rob Herring
On 03/26/2012 02:31 PM, David Daney wrote:
> From: David Daney 
> 
> Create two domains.  One for the GPIO lines, and the other for on-chip
> sources.
> 
> Signed-off-by: David Daney 
> ---
>  arch/mips/cavium-octeon/octeon-irq.c |  208 
> --
>  1 files changed, 199 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/mips/cavium-octeon/octeon-irq.c 
> b/arch/mips/cavium-octeon/octeon-irq.c
> index 89b6f27..550c03d 100644
> --- a/arch/mips/cavium-octeon/octeon-irq.c
> +++ b/arch/mips/cavium-octeon/octeon-irq.c
> @@ -3,14 +3,17 @@
>   * License.  See the file "COPYING" in the main directory of this archive
>   * for more details.
>   *
> - * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
> + * Copyright (C) 2004-2012 Cavium, Inc.
>   */
>  
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  
> @@ -42,9 +45,9 @@ struct octeon_core_chip_data {
>  
>  static struct octeon_core_chip_data 
> octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
>  
> -static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
> -   struct irq_chip *chip,
> -   irq_flow_handler_t handler)
> +static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
> +struct irq_chip *chip,
> +irq_flow_handler_t handler)
>  {
>   union octeon_ciu_chip_data cd;
>  
> @@ -838,6 +841,171 @@ static struct irq_chip octeon_irq_chip_ciu_wd = {
>   .irq_mask = octeon_irq_dummy_mask,
>  };
>  
> +static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
> +{
> + bool edge = false;
> +
> + if (line == 0)
> + switch (bit) {
> + case 48 ... 49: /* GMX DRP */
> + case 50: /* IPD_DRP */
> + case 52 ... 55: /* Timers */
> + case 58: /* MPI */
> + edge = true;
> + break;
> + default:
> + break;
> + }
> + else /* line == 1 */
> + switch (bit) {
> + case 47: /* PTP */
> + edge = true;
> + break;
> + default:
> + break;
> + }
> + return edge;

Moving in the right direction, but I still don't get why this is not in
the CIU binding as a 3rd cell?

> +}
> +
> +struct octeon_irq_gpio_domain_data {
> + unsigned int base_hwirq;
> +};
> +
> +static int octeon_irq_gpio_xlat(struct irq_domain *d,
> + struct device_node *node,
> + const u32 *intspec,
> + unsigned int intsize,
> + unsigned long *out_hwirq,
> + unsigned int *out_type)
> +{
> + unsigned int type;
> + unsigned int pin;
> + unsigned int trigger;
> + bool set_edge_handler = false;
> + struct octeon_irq_gpio_domain_data *gpiod;
> +
> + if (d->of_node != node)
> + return -EINVAL;
> +
> + if (intsize < 2)
> + return -EINVAL;
> +
> + pin = intspec[0];
> + if (pin >= 16)
> + return -EINVAL;
> +
> + trigger = intspec[1];
> +
> + switch (trigger) {
> + case 1:
> + type = IRQ_TYPE_EDGE_RISING;
> + set_edge_handler = true;

This is never used.

> + break;
> + case 2:
> + type = IRQ_TYPE_EDGE_FALLING;
> + set_edge_handler = true;
> + break;
> + case 4:
> + type = IRQ_TYPE_LEVEL_HIGH;
> + break;
> + case 8:
> + type = IRQ_TYPE_LEVEL_LOW;
> + break;
> + default:
> + pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
> +node->name,
> +trigger);
> + type = IRQ_TYPE_LEVEL_LOW;
> + break;
> + }
> + *out_type = type;

Can't you get rid of the whole switch statement and just do:

*out_type = intspec[1];

> + gpiod = d->host_data;
> + *out_hwirq = gpiod->base_hwirq + pin;
> +
> + return 0;
> +}
> +
> +static int octeon_irq_ciu_xlat(struct irq_domain *d,
> +struct device_node *node,
> +const u32 *intspec,
> +unsigned int intsize,
> +unsigned long *out_hwirq,
> +unsigned int *out_type)
> +{
> + unsigned int ciu, bit;
> +
> + ciu = intspec[0];
> + bit = intspec[1];
> +
> + if (ciu > 1 || bit > 63)
> + return -EINVAL;
> +
> + /* These are the GPIO lines */
> + if (ciu == 0 && bit >= 16 && bit < 32)
> + return -EINVAL;
> +
> + *out_hwirq = (ciu << 6) | bit;
> + *out_type = 0;
> +
> + return 0;
> +}
> +
> +static st

[PATCH v7 2/4] MIPS: Octeon: Setup irq_domains for interrupts.

2012-03-26 Thread David Daney
From: David Daney 

Create two domains.  One for the GPIO lines, and the other for on-chip
sources.

Signed-off-by: David Daney 
---
 arch/mips/cavium-octeon/octeon-irq.c |  208 --
 1 files changed, 199 insertions(+), 9 deletions(-)

diff --git a/arch/mips/cavium-octeon/octeon-irq.c 
b/arch/mips/cavium-octeon/octeon-irq.c
index 89b6f27..550c03d 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -3,14 +3,17 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
+ * Copyright (C) 2004-2012 Cavium, Inc.
  */
 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -42,9 +45,9 @@ struct octeon_core_chip_data {
 
 static struct octeon_core_chip_data 
octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
 
-static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
- struct irq_chip *chip,
- irq_flow_handler_t handler)
+static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
+  struct irq_chip *chip,
+  irq_flow_handler_t handler)
 {
union octeon_ciu_chip_data cd;
 
@@ -838,6 +841,171 @@ static struct irq_chip octeon_irq_chip_ciu_wd = {
.irq_mask = octeon_irq_dummy_mask,
 };
 
+static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
+{
+   bool edge = false;
+
+   if (line == 0)
+   switch (bit) {
+   case 48 ... 49: /* GMX DRP */
+   case 50: /* IPD_DRP */
+   case 52 ... 55: /* Timers */
+   case 58: /* MPI */
+   edge = true;
+   break;
+   default:
+   break;
+   }
+   else /* line == 1 */
+   switch (bit) {
+   case 47: /* PTP */
+   edge = true;
+   break;
+   default:
+   break;
+   }
+   return edge;
+}
+
+struct octeon_irq_gpio_domain_data {
+   unsigned int base_hwirq;
+};
+
+static int octeon_irq_gpio_xlat(struct irq_domain *d,
+   struct device_node *node,
+   const u32 *intspec,
+   unsigned int intsize,
+   unsigned long *out_hwirq,
+   unsigned int *out_type)
+{
+   unsigned int type;
+   unsigned int pin;
+   unsigned int trigger;
+   bool set_edge_handler = false;
+   struct octeon_irq_gpio_domain_data *gpiod;
+
+   if (d->of_node != node)
+   return -EINVAL;
+
+   if (intsize < 2)
+   return -EINVAL;
+
+   pin = intspec[0];
+   if (pin >= 16)
+   return -EINVAL;
+
+   trigger = intspec[1];
+
+   switch (trigger) {
+   case 1:
+   type = IRQ_TYPE_EDGE_RISING;
+   set_edge_handler = true;
+   break;
+   case 2:
+   type = IRQ_TYPE_EDGE_FALLING;
+   set_edge_handler = true;
+   break;
+   case 4:
+   type = IRQ_TYPE_LEVEL_HIGH;
+   break;
+   case 8:
+   type = IRQ_TYPE_LEVEL_LOW;
+   break;
+   default:
+   pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
+  node->name,
+  trigger);
+   type = IRQ_TYPE_LEVEL_LOW;
+   break;
+   }
+   *out_type = type;
+   gpiod = d->host_data;
+   *out_hwirq = gpiod->base_hwirq + pin;
+
+   return 0;
+}
+
+static int octeon_irq_ciu_xlat(struct irq_domain *d,
+  struct device_node *node,
+  const u32 *intspec,
+  unsigned int intsize,
+  unsigned long *out_hwirq,
+  unsigned int *out_type)
+{
+   unsigned int ciu, bit;
+
+   ciu = intspec[0];
+   bit = intspec[1];
+
+   if (ciu > 1 || bit > 63)
+   return -EINVAL;
+
+   /* These are the GPIO lines */
+   if (ciu == 0 && bit >= 16 && bit < 32)
+   return -EINVAL;
+
+   *out_hwirq = (ciu << 6) | bit;
+   *out_type = 0;
+
+   return 0;
+}
+
+static struct irq_chip *octeon_irq_ciu_chip;
+static struct irq_chip *octeon_irq_gpio_chip;
+
+static int octeon_irq_ciu_map(struct irq_domain *d,
+ unsigned int virq, irq_hw_number_t hw)
+{
+   unsigned int line = hw >> 6;
+   unsigned int bit = hw & 63;
+
+   if (virq >= 256)
+   return -EINVAL;
+
+   if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
+