RE: [PATCH v2] clk: Document of_parse_clkspec() some more

2019-08-27 Thread Phil Edworthy
Hi Stephen,

On 26 August 2019 22:21 Stephen Boyd wrote:
> The return value of of_parse_clkspec() is peculiar. If the function is
> called with a NULL argument for 'name' it will return -ENOENT, but if
> it's called with a non-NULL argument for 'name' it will return -EINVAL.
> This peculiarity is documented by commit 5c56dfe63b6e ("clk: Add comment
> about __of_clk_get_by_name() error values").
> 
> Let's further document this function so that it's clear what the return
> value is and how to use the arguments to parse clk specifiers.
> 
> Cc: Phil Edworthy 
> Signed-off-by: Stephen Boyd 

Thanks, this is much better than my comment!

Reviewed-by: Phil Edworthy 

> ---
>  drivers/clk/clk.c | 43 +--
>  1 file changed, 37 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c0990703ce54..5c6585eb35d4 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -4316,12 +4316,43 @@ void devm_of_clk_del_provider(struct device
> *dev)
>  }
>  EXPORT_SYMBOL(devm_of_clk_del_provider);
> 
> -/*
> - * Beware the return values when np is valid, but no clock provider is found.
> - * If name == NULL, the function returns -ENOENT.
> - * If name != NULL, the function returns -EINVAL. This is because
> - * of_parse_phandle_with_args() is called even if
> of_property_match_string()
> - * returns an error.
> +/**
> + * of_parse_clkspec() - Parse a DT clock specifier for a given device node
> + * @np: device node to parse clock specifier from
> + * @index: index of phandle to parse clock out of. If index < 0, @name is
> used
> + * @name: clock name to find and parse. If name is NULL, the index is used
> + * @out_args: Result of parsing the clock specifier
> + *
> + * Parses a device node's "clocks" and "clock-names" properties to find the
> + * phandle and cells for the index or name that is desired. The resulting
> clock
> + * specifier is placed into @out_args, or an errno is returned when there's a
> + * parsing error. The @index argument is ignored if @name is non-NULL.
> + *
> + * Example:
> + *
> + * phandle1: clock-controller@1 {
> + *   #clock-cells = <2>;
> + * }
> + *
> + * phandle2: clock-controller@2 {
> + *   #clock-cells = <1>;
> + * }
> + *
> + * clock-consumer@3 {
> + *   clocks = <&phandle1 1 2 &phandle2 3>;
> + *   clock-names = "name1", "name2";
> + * }
> + *
> + * To get a device_node for `clock-controller@2' node you may call this
> + * function a few different ways:
> + *
> + *   of_parse_clkspec(clock-consumer@3, -1, "name2", &args);
> + *   of_parse_clkspec(clock-consumer@3, 1, NULL, &args);
> + *   of_parse_clkspec(clock-consumer@3, 1, "name2", &args);
> + *
> + * Return: 0 upon successfully parsing the clock specifier. Otherwise, -
> ENOENT
> + * if @name is NULL or -EINVAL if @name is non-NULL and it can't be found
> in
> + * the "clock-names" property of @np.
>   */
>  static int of_parse_clkspec(const struct device_node *np, int index,
>   const char *name, struct of_phandle_args
> *out_args)
> --
> Sent by a computer through tubes



RE: [PATCH v3 1/2] dt-bindings: clock: renesas,r9a06g032-sysctrl: Document power Domains

2019-06-03 Thread Phil Edworthy
Hi Geert,

On 03 June 2019 09:39 Geert Uytterhoeven wrote:
> On Mon, Jun 3, 2019 at 10:29 AM Phil Edworthy wrote:
> > On 28 May 2019 08:29 Geert Uytterhoeven wrote:
> > > On Fri, May 24, 2019 at 5:32 PM Gareth Williams wrote:
> > > > The driver is gaining power domain support, so add the new property to
> > > > the DT binding and update the examples.
> > > >
> > > > Signed-off-by: Gareth Williams 
> 
> > > > ---
> > > > a/Documentation/devicetree/bindings/clock/renesas,r9a06g032-
> sysctrl.txt
> > > > +++ b/Documentation/devicetree/bindings/clock/renesas,r9a06g032-
> sysctrl.txt
> > > @@ -40,4 +42,5 @@ Examples
> > > > reg-io-width = <4>;
> > > > clocks = <&sysctrl R9A06G032_CLK_UART0>;
> > > > clock-names = "baudclk";
> > > > +   power-domains = <&sysctrl>;
> > >
> > > This is an interesting example: according to the driver,
> > > R9A06G032_CLK_UART0, is not clock used for power management?
> > >
> > > Oh, the real uart0 node in arch/arm/boot/dts/r9a06g032.dtsi uses
> > >
> > > clocks = <&sysctrl R9A06G032_CLK_UART0>, <&sysctrl
> > > R9A06G032_HCLK_UART0>;
> > > clock-names = "baudclk", "apb_pclk";
> > >
> > > That does make sense...
> > Note that the Synopsys DW uart driver already gets the "apb_pclk" clock,
> so
> > we don’t actually need to use clock domains to enable this clock.
> 
> That is not necessarily a problem:
>   1) DT describes hardware, not software policy,
>   2) It doesn't hurt to enable a clock twice.
Yes, that was my take as well.

> There are still some R-Car drivers that manage clocks themselves, but
> we're slowly migrating away from that, where possible. If the driver
> is e.g. shared with a platform without clock domains, we obviously cannot
> do that.
> 
> So you can take out that code again, that's up to you.
I think leaving it as is best.

> > This is also true for many of the peripheral drivers used on rzn1 (Synopsys
> > gpio controller, i2c controller, gmac, dmac, Arasan sdio controller). The
> > commit to add this clock to the i2c controller driver is my fault, as I was
> > following the pattern of the others.
> >
> > Of the few drivers that don't already get the hclk/pclk used to access the
> > peripherals is the Synopsys spi controller (though that currently doesn’t
> > support runtime PM) and the USB Host controller.
> 
> Good, so the latter will start working magically, I assume? ;-)
Yes, except for the usb PLL. The rzn1 has a mode bit that switches USB
between 2xHost and 1xHost + 1xFunc, however the PLL must be started after
the mode bit has been set. That still needs to be implemented...

BR
Phil
 
> Gr{oetje,eeting}s,
> 
> Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds


RE: [PATCH v3 1/2] dt-bindings: clock: renesas,r9a06g032-sysctrl: Document power Domains

2019-06-03 Thread Phil Edworthy
Hi Geert,

On 28 May 2019 08:29 Geert Uytterhoeven wrote:
> On Fri, May 24, 2019 at 5:32 PM Gareth Williams wrote:
> > The driver is gaining power domain support, so add the new property to
> > the DT binding and update the examples.
> >
> > Signed-off-by: Gareth Williams 
> 
> Thanks for your patch!
> 
> > ---
> > a/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.tx
> > t
> > +++ b/Documentation/devicetree/bindings/clock/renesas,r9a06g032-
> sysctr
> > +++ l.txt
> @@ -40,4 +42,5 @@ Examples
> > reg-io-width = <4>;
> > clocks = <&sysctrl R9A06G032_CLK_UART0>;
> > clock-names = "baudclk";
> > +   power-domains = <&sysctrl>;
> 
> This is an interesting example: according to the driver,
> R9A06G032_CLK_UART0, is not clock used for power management?
> 
> Oh, the real uart0 node in arch/arm/boot/dts/r9a06g032.dtsi uses
> 
> clocks = <&sysctrl R9A06G032_CLK_UART0>, <&sysctrl
> R9A06G032_HCLK_UART0>;
> clock-names = "baudclk", "apb_pclk";
> 
> That does make sense...
Note that the Synopsys DW uart driver already gets the "apb_pclk" clock, so
we don’t actually need to use clock domains to enable this clock.

This is also true for many of the peripheral drivers used on rzn1 (Synopsys
gpio controller, i2c controller, gmac, dmac, Arasan sdio controller). The
commit to add this clock to the i2c controller driver is my fault, as I was
following the pattern of the others.

Of the few drivers that don't already get the hclk/pclk used to access the
peripherals is the Synopsys spi controller (though that currently doesn’t
support runtime PM) and the USB Host controller.

BR
Phil
 
> With the above fixed:
> Reviewed-by: Geert Uytterhoeven 
> 
> Gr{oetje,eeting}s,
> 
> Geert
> 
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds


RE: [PATCH] clk: renesas: r9a06g032: Add clock domain support

2019-05-20 Thread Phil Edworthy
Hi Gareth,

On 17 May 2019 15:48, Gareth Williams wrote:
> There are several clocks on the r9ag032 which are currently not enabled
> in their drivers that can be delegated to clock domain system for power
> management. Therefore add support for clock domain functionality to the
> r9a06g032 clock driver.
> 
> Signed-off-by: Gareth Williams 

Your patch appears to be on top of some other work that is not in next
or elsewhere.
Please can you rebase it onto Geert's renesas-drivers branch
(kernel/git/geert/renesas-drivers.git).

Thanks
Phil

> ---
>  drivers/clk/renesas/r9a06g032-clocks.c | 243
> -
>  1 file changed, 176 insertions(+), 67 deletions(-)
> 
> diff --git a/drivers/clk/renesas/r9a06g032-clocks.c
> b/drivers/clk/renesas/r9a06g032-clocks.c
> index 0b492b5..8a278da 100644
> --- a/drivers/clk/renesas/r9a06g032-clocks.c
> +++ b/drivers/clk/renesas/r9a06g032-clocks.c
> @@ -15,6 +15,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -49,6 +51,7 @@ struct r9a06g032_gate {
>  /* This is used to describe a clock for instantiation */
>  struct r9a06g032_clkdesc {
>   const char *name;
> + bool managed;
>   u32 type: 3;
>   u32 index: 8;
>   u32 source : 8; /* source index + 1 (0 == none) */
> @@ -81,7 +84,11 @@ struct r9a06g032_clkdesc {
>  #define D_GATE(_idx, _n, _src, ...) \
>   { .type = K_GATE, .index = R9A06G032_##_idx, \
>   .source = 1 + R9A06G032_##_src, .name = _n, \
> - .gate = I_GATE(__VA_ARGS__), }
> + .managed = 0, .gate = I_GATE(__VA_ARGS__) }
> +#define D_MODULE(_idx, _n, _src, ...) \
> + { .type = K_GATE, .index = R9A06G032_##_idx, \
> + .source = 1 + R9A06G032_##_src, .name = _n, \
> + .managed = 1, .gate = I_GATE(__VA_ARGS__) }
>  /* Fixed-factor multipler and divider for root clocks */
>  #define D_ROOT(_idx, _n, _mul, _div) \
>   { .type = K_FFC, .index = R9A06G032_##_idx, .name = _n, \
> @@ -198,7 +205,7 @@ static const struct r9a06g032_clkdesc
> r9a06g032_clocks[] __initconst = {
>   D_GATE(CLK_P6_PG2, "clk_p6_pg2", DIV_P6_PG, 0x8a3, 0x8a4,
> 0x8a5, 0, 0xb61, 0, 0),
>   D_GATE(CLK_P6_PG3, "clk_p6_pg3", DIV_P6_PG, 0x8a6, 0x8a7,
> 0x8a8, 0, 0xb62, 0, 0),
>   D_GATE(CLK_P6_PG4, "clk_p6_pg4", DIV_P6_PG, 0x8a9, 0x8aa,
> 0x8ab, 0, 0xb63, 0, 0),
> - D_GATE(CLK_PCI_USB, "clk_pci_usb", CLKOUT_D40, 0xe6, 0, 0, 0, 0,
> 0, 0),
> + D_MODULE(CLK_PCI_USB, "clk_pci_usb", CLKOUT_D40, 0xe6, 0, 0, 0,
> 0, 0, 0),
>   D_GATE(CLK_QSPI0, "clk_qspi0", DIV_QSPI0, 0x2a4, 0x2a5, 0, 0, 0, 0,
> 0),
>   D_GATE(CLK_QSPI1, "clk_qspi1", DIV_QSPI1, 0x484, 0x485, 0, 0, 0, 0,
> 0),
>   D_GATE(CLK_RGMII_REF, "clk_rgmii_ref", CLKOUT_D8, 0x340, 0, 0, 0,
> 0, 0, 0),
> @@ -215,17 +222,17 @@ static const struct r9a06g032_clkdesc
> r9a06g032_clocks[] __initconst = {
>   D_GATE(CLK_SPI5, "clk_spi5", DIV_P4_PG, 0x822, 0x823, 0, 0, 0, 0, 0),
>   D_GATE(CLK_SWITCH, "clk_switch", DIV_SWITCH, 0x982, 0x983, 0, 0,
> 0, 0, 0),
>   D_DIV(DIV_MOTOR, "div_motor", CLKOUT_D5, 84, 2, 8),
> - D_GATE(HCLK_ECAT125, "hclk_ecat125", CLKOUT_D8, 0x400, 0x401,
> 0, 0x402, 0, 0x440, 0x441),
> - D_GATE(HCLK_PINCONFIG, "hclk_pinconfig", CLKOUT_D40, 0x740,
> 0x741, 0x742, 0, 0xae0, 0, 0),
> - D_GATE(HCLK_SERCOS, "hclk_sercos", CLKOUT_D10, 0x420, 0x422, 0,
> 0x421, 0, 0x460, 0x461),
> - D_GATE(HCLK_SGPIO2, "hclk_sgpio2", DIV_P5_PG, 0x8c3, 0x8c4,
> 0x8c5, 0, 0xb41, 0, 0),
> - D_GATE(HCLK_SGPIO3, "hclk_sgpio3", DIV_P5_PG, 0x8c6, 0x8c7,
> 0x8c8, 0, 0xb42, 0, 0),
> - D_GATE(HCLK_SGPIO4, "hclk_sgpio4", DIV_P5_PG, 0x8c9, 0x8ca,
> 0x8cb, 0, 0xb43, 0, 0),
> - D_GATE(HCLK_TIMER0, "hclk_timer0", CLKOUT_D40, 0x743, 0x744,
> 0x745, 0, 0xae1, 0, 0),
> - D_GATE(HCLK_TIMER1, "hclk_timer1", CLKOUT_D40, 0x746, 0x747,
> 0x748, 0, 0xae2, 0, 0),
> - D_GATE(HCLK_USBF, "hclk_usbf", CLKOUT_D8, 0xe3, 0, 0, 0xe4, 0,
> 0x102, 0x103),
> - D_GATE(HCLK_USBH, "hclk_usbh", CLKOUT_D8, 0xe0, 0xe1, 0, 0xe2,
> 0, 0x100, 0x101),
> - D_GATE(HCLK_USBPM, "hclk_usbpm", CLKOUT_D8, 0xe5, 0, 0, 0, 0,
> 0, 0),
> + D_MODULE(HCLK_ECAT125, "hclk_ecat125", CLKOUT_D8, 0x400,
> 0x401, 0, 0x402, 0, 0x440, 0x441),
> + D_MODULE(HCLK_PINCONFIG, "hclk_pinconfig", CLKOUT_D40,
> 0x740, 0x741, 0x742, 0, 0xae0, 0, 0),
> + D_MODULE(HCLK_SERCOS, "hclk_sercos", CLKOUT_D10, 0x420,
> 0x422, 0, 0x421, 0, 0x460, 0x461),
> + D_MODULE(HCLK_SGPIO2, "hclk_sgpio2", DIV_P5_PG, 0x8c3, 0x8c4,
> 0x8c5, 0, 0xb41, 0, 0),
> + D_MODULE(HCLK_SGPIO3, "hclk_sgpio3", DIV_P5_PG, 0x8c6, 0x8c7,
> 0x8c8, 0, 0xb42, 0, 0),
> + D_MODULE(HCLK_SGPIO4, "hclk_sgpio4", DIV_P5_PG, 0x8c9, 0x8ca,
> 0x8cb, 0, 0xb43, 0, 0),
> + D_MODULE(HCLK_TIMER0, "hclk_timer0", CLKOUT_D40, 0x743,
> 0x744, 0x745, 0, 0xae1, 0, 0),
> + D_MODULE(HCLK_TIMER1, "hclk_timer1", CLKOUT_D40, 0x746,
> 0x747, 0x748, 0, 0xae2, 0, 0),
> + D_MODULE(HCLK_USBF, "hclk_usbf", CLKOUT_

RE: [PATCH v4 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-25 Thread Phil Edworthy
Hi Marc,

On 20 February 2019 11:33 Phil Edworthy wrote:
> On 20 February 2019 10:05 Marc Zyngier wrote:
> > On Wed, 20 Feb 2019 09:07:02 +0000, Phil Edworthy wrote:
> > > On 19 February 2019 20:29 Marc Zyngier wrote:
> >
> > [...]
> >
> > > > > + for (i = 0; i < MAX_NR_INPUT_IRQS; i++)
> > > > > + irq_create_mapping(priv->irq_domain, i);
> > > >
> > > > This should never happen. Mappings should be created from
> > > > discovering
> > the
> > > > interrupt specifiers for devices in the DT, and not eagerly at probe 
> > > > time.
> > >
> > > The key issue here is that the mappings should not be dynamically
> > > allocated.  On the device that has this hardware, there is a Cortex
> > > M3 that is likely to use some of these GPIO interrupts.  Maybe it
> > > would be better to limit the number of GPIO irqs that Linux can
> > > configure dynamically.
> >
> > But whatever the M3 is going to use is known statically for a given
> > instance of this platform, right? You can always tell from the device
> > tree which pins are available for Linux and which are not. Or can't you?
> Yes, you can tell what pins are available to Linux. You can't tell how many 
> pins
> have been setup as GPIO irqs for use by the M3 though.
> I suppose the DT could describe the M3 as well, though I can imagine that
> could get complicated. I've not seen a DT that covers different cores running
> different software, esp. when the M3 firmware doesn't use DT.
> I was thinking that the DT could have a prop to tell this driver what GPIO 
> irqs
> are already in use.
I've just realised that it doesn't matter if we don't know how many interrupts
are used by the M3, as Linux will not claim more than the remaining interrupts.

Thanks
Phil

> > > Looks like I've gone off in the wrong direction yet again.
> >
> > Nothing we can't help with. If you can explain all the constraints of
> > the platform, we can come up with a fairly simple driver. And surely
> > LinusW can chime in for the DT part, which seems to need some loving
> > too.
> Many thanks, I need some help here!
> 
> Phil


RE: [PATCH v4 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-20 Thread Phil Edworthy
Hi Marc,

On 20 February 2019 10:05 Marc Zyngier wrote:
> On Wed, 20 Feb 2019 09:07:02 +0000, Phil Edworthy wrote:
> > On 19 February 2019 20:29 Marc Zyngier wrote:
> 
> [...]
> 
> > > > +   for (i = 0; i < MAX_NR_INPUT_IRQS; i++)
> > > > +   irq_create_mapping(priv->irq_domain, i);
> > >
> > > This should never happen. Mappings should be created from discovering
> the
> > > interrupt specifiers for devices in the DT, and not eagerly at probe time.
> >
> > The key issue here is that the mappings should not be dynamically
> > allocated.  On the device that has this hardware, there is a Cortex
> > M3 that is likely to use some of these GPIO interrupts.  Maybe it
> > would be better to limit the number of GPIO irqs that Linux can
> > configure dynamically.
> 
> But whatever the M3 is going to use is known statically for a given
> instance of this platform, right? You can always tell from the device
> tree which pins are available for Linux and which are not. Or can't you?
Yes, you can tell what pins are available to Linux. You can't tell how
many pins have been setup as GPIO irqs for use by the M3 though.
I suppose the DT could describe the M3 as well, though I can imagine
that could get complicated. I've not seen a DT that covers different
cores running different software, esp. when the M3 firmware doesn't
use DT.
I was thinking that the DT could have a prop to tell this driver what
GPIO irqs are already in use.
 
> > Looks like I've gone off in the wrong direction yet again.
> 
> Nothing we can't help with. If you can explain all the constraints of
> the platform, we can come up with a fairly simple driver. And surely
> LinusW can chime in for the DT part, which seems to need some loving
> too.
Many thanks, I need some help here!

Phil


RE: [PATCH v4 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-20 Thread Phil Edworthy
Hi Marc

On 19 February 2019 20:29 Marc Zyngier wrote:
> On Tue, 19 Feb 2019 15:55:11 +0000 Phil Edworthy wrote:
> 
> + LinusW, who seem to have taken an interest in irqchip hierarchies...
> 
> > On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > configured to have 32 interrupt outputs, so we have a total of 96 GPIO
> > interrupts. All of these are passed to the GPIO IRQ Muxer, which
> > selects
> > 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
> > aren't latched, so there is nothing to do in this driver when an
> > interrupt is received, other than tell the corresponding GPIO block.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > v4:
> >  - No change.
> > v3:
> >  - Use 'interrupt-map' DT property to map the interrupts, this is very 
> > similar
> >to PCIe MSI. The only difference is that we need to get hold of the
> interrupt
> >specifier for the interupts coming into the irqmux.
> >  - Do not use a chained interrupt controller.
> > v2:
> >  - Use interrupt-map to allow the GPIO controller info to be specified
> >as part of the irq.
> >  - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
> > ---
> >  drivers/irqchip/Kconfig|   9 ++
> >  drivers/irqchip/Makefile   |   1 +
> >  drivers/irqchip/rzn1-irq-mux.c | 205
> > +
> >  3 files changed, 215 insertions(+)
> >  create mode 100644 drivers/irqchip/rzn1-irq-mux.c
> >
> > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
> > 5dcb5456cd14..369f78d6b521 100644
> > --- a/drivers/irqchip/Kconfig
> > +++ b/drivers/irqchip/Kconfig
> > @@ -211,6 +211,15 @@ config RENESAS_IRQC
> > select GENERIC_IRQ_CHIP
> > select IRQ_DOMAIN
> >
> > +config RENESAS_RZN1_IRQ_MUX
> > +   bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
> > +   depends on ARCH_RZN1
> > +   select IRQ_DOMAIN
> > +   help
> > + Say yes here to add support for the GPIO IRQ multiplexer
> embedded
> > + in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
> > + the interrupts coming from the GPIO controllers are used.
> > +
> >  config ST_IRQCHIP
> > bool
> > select REGMAP
> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index
> > 7acd0e36d0b4..2edd42ef2182 100644
> > --- a/drivers/irqchip/Makefile
> > +++ b/drivers/irqchip/Makefile
> > @@ -46,6 +46,7 @@ obj-$(CONFIG_JCORE_AIC)   +=
> irq-jcore-aic.o
> >  obj-$(CONFIG_RDA_INTC) += irq-rda-intc.o
> >  obj-$(CONFIG_RENESAS_INTC_IRQPIN)  += irq-renesas-intc-irqpin.o
> >  obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
> > +obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX) += rzn1-irq-mux.o
> >  obj-$(CONFIG_VERSATILE_FPGA_IRQ)   += irq-versatile-fpga.o
> >  obj-$(CONFIG_ARCH_NSPIRE)  += irq-zevio.o
> >  obj-$(CONFIG_ARCH_VT8500)  += irq-vt8500.o
> > diff --git a/drivers/irqchip/rzn1-irq-mux.c
> > b/drivers/irqchip/rzn1-irq-mux.c new file mode 100644 index
> > ..ee7810b9b3f3
> > --- /dev/null
> > +++ b/drivers/irqchip/rzn1-irq-mux.c
> > @@ -0,0 +1,205 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * RZ/N1 GPIO Interrupt Multiplexer
> > + *
> > + * Copyright (C) 2018 Renesas Electronics Europe Limited
> > + *
> > + * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > +configured
> > + * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
> > + * All of these are passed to the GPIO IRQ Muxer, which selects 8 of
> > +the GPIO
> > + * interrupts to pass onto the GIC.
> 
> So that I get it right:
> 
> - 96 inputs
> - 8 outputs
> 
> This driver picks 8 of the inputs (and at most 8), and pass then down to the
> GIC. Do I understand that correctly?
Correct.

> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define MAX_NR_INPUT_IRQS  96
> > +#define MAX_NR_OUTPUT_IRQS 8
> > +
> > +/*
> > + * "interrupt-map" consists of 1 interrupt cell, 0 address cells,
> > +phandle to
> > + * interrupt parent, and parent interrupt specifier (3 cells for
> > +GIC), giving
> > + * a total of 5 cells.
> > + */
> > +#define IMAP_LENGTH5
> 
> Although the maths do check out, I f

[PATCH v4 0/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-19 Thread Phil Edworthy
On RZ/N1 devices, there are lots of GPIO interrupts that are multiplexed before
getting to the GIC interrupt controller. Other than the multiplexing, there is
no other logic applied to the signals.

The multiplexing cannot be handled dynamically because there is another CPU that
runs firmware. It's likely that the firmware will use some of these GPIO
interrupts and so we don't want them to move around.

Signed-off-by: Phil Edworthy 
---
v4:
 - Fix DT binding nits
v3:
 - Use 'interrupt-map' DT property to map the interrupts, this is very similar
   to PCIe MSI. The only difference is that we need to get hold of the interrupt
   specifier for the interupts coming into the irqmux.
   I had completely messed up the use of 'interrupt-map' in v2... oops.
 - Do not use a chained interrupt controller.
v2:
 - Split DT bindings into separate patch.
 - Use interrupt-map to allow the GPIO controller info to be specified
   as part of the irq.
 - Don't show status in binding examples.
 - Don't show the soc/board split in binding doc.
 - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.

Phil Edworthy (2):
  dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

 .../interrupt-controller/renesas,rzn1-mux.txt |  73 +++
 drivers/irqchip/Kconfig   |   9 +
 drivers/irqchip/Makefile  |   1 +
 drivers/irqchip/rzn1-irq-mux.c| 205 ++
 4 files changed, 288 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
 create mode 100644 drivers/irqchip/rzn1-irq-mux.c

-- 
2.17.1



[PATCH v4 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-19 Thread Phil Edworthy
On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
configured to have 32 interrupt outputs, so we have a total of 96 GPIO
interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
aren't latched, so there is nothing to do in this driver when an interrupt
is received, other than tell the corresponding GPIO block.

Signed-off-by: Phil Edworthy 
---
v4:
 - No change.
v3:
 - Use 'interrupt-map' DT property to map the interrupts, this is very similar
   to PCIe MSI. The only difference is that we need to get hold of the interrupt
   specifier for the interupts coming into the irqmux.
 - Do not use a chained interrupt controller.
v2:
 - Use interrupt-map to allow the GPIO controller info to be specified
   as part of the irq.
 - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
---
 drivers/irqchip/Kconfig|   9 ++
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/rzn1-irq-mux.c | 205 +
 3 files changed, 215 insertions(+)
 create mode 100644 drivers/irqchip/rzn1-irq-mux.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 5dcb5456cd14..369f78d6b521 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -211,6 +211,15 @@ config RENESAS_IRQC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
 
+config RENESAS_RZN1_IRQ_MUX
+   bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
+   depends on ARCH_RZN1
+   select IRQ_DOMAIN
+   help
+ Say yes here to add support for the GPIO IRQ multiplexer embedded
+ in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
+ the interrupts coming from the GPIO controllers are used.
+
 config ST_IRQCHIP
bool
select REGMAP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 7acd0e36d0b4..2edd42ef2182 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_JCORE_AIC)   += 
irq-jcore-aic.o
 obj-$(CONFIG_RDA_INTC) += irq-rda-intc.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)  += irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
+obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX) += rzn1-irq-mux.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)   += irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_NSPIRE)  += irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)  += irq-vt8500.o
diff --git a/drivers/irqchip/rzn1-irq-mux.c b/drivers/irqchip/rzn1-irq-mux.c
new file mode 100644
index ..ee7810b9b3f3
--- /dev/null
+++ b/drivers/irqchip/rzn1-irq-mux.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/N1 GPIO Interrupt Multiplexer
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each 
configured
+ * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
+ * All of these are passed to the GPIO IRQ Muxer, which selects 8 of the GPIO
+ * interrupts to pass onto the GIC.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_NR_INPUT_IRQS  96
+#define MAX_NR_OUTPUT_IRQS 8
+
+/*
+ * "interrupt-map" consists of 1 interrupt cell, 0 address cells, phandle to
+ * interrupt parent, and parent interrupt specifier (3 cells for GIC), giving
+ * a total of 5 cells.
+ */
+#define IMAP_LENGTH5
+
+struct irqmux_priv;
+struct irqmux_one {
+   unsigned int irq;
+   unsigned int src_hwirq;
+   struct irqmux_priv *priv;
+};
+
+struct irqmux_priv {
+   struct device *dev;
+   struct irq_domain *irq_domain;
+   unsigned int nr_irqs;
+   struct irqmux_one mux[MAX_NR_OUTPUT_IRQS];
+};
+
+static irqreturn_t irqmux_handler(int irq, void *data)
+{
+   struct irqmux_one *mux = data;
+   struct irqmux_priv *priv = mux->priv;
+   unsigned int virq;
+
+   virq = irq_find_mapping(priv->irq_domain, mux->src_hwirq);
+
+   generic_handle_irq(virq);
+
+   return IRQ_HANDLED;
+}
+
+static int irqmux_domain_map(struct irq_domain *h, unsigned int irq,
+irq_hw_number_t hwirq)
+{
+   irq_set_chip_data(irq, h->host_data);
+   irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+
+   return 0;
+}
+
+static const struct irq_domain_ops irqmux_domain_ops = {
+   .map = irqmux_domain_map,
+};
+
+static int irqmux_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct device_node *np = dev->of_node;
+   struct resource *res;
+   u32 __iomem *regs;
+   struct irqmux_priv *priv;
+   unsigned int i;
+   int nr_irqs;
+   int ret;
+   const __be32 *imap;
+   int imaplen;
+
+   priv = devm_kzalloc(dev, sizeof(*priv), GF

RE: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-19 Thread Phil Edworthy
Hi Marc,

> On Tue, 19 Feb 2019 15:27:25 +
> Phil Edworthy  wrote:
> 
> > Hello,
> >
> > Any comments on this patch?
> 
> Err... I'm afraid it fell through the cracks. It's been three months, and I've
> paged out most of last year.
> 
> Can you please resend it on top of a recent -rc, and I'll try to have a look. 
> No
> promise though.

Thanks, appreciate it you can!
Phil

> 
> Thanks,
> 
>   M.
> 
> >
> > Thanks
> > Phil
> >
> > > -Original Message-
> > > From: Phil Edworthy 
> > > Sent: 13 November 2018 13:09
> > > To: Marc Zyngier ; Thomas Gleixner
> > > ; Jason Cooper 
> > > Cc: Geert Uytterhoeven ; linux-renesas-
> > > s...@vger.kernel.org; linux-kernel@vger.kernel.org; Phil Edworthy
> > > 
> > > Subject: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO
> > > interrupt multiplexer
> > >
> > > On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > > configured to have 32 interrupt outputs, so we have a total of 96
> > > GPIO interrupts. All of these are passed to the GPIO IRQ Muxer,
> > > which selects
> > > 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
> > > aren't latched, so there is nothing to do in this driver when an
> > > interrupt is received, other than tell the corresponding GPIO block.
> > >
> > > Signed-off-by: Phil Edworthy 
> > > ---
> > > v3:
> > >  - Use 'interrupt-map' DT property to map the interrupts, this is very
> similar
> > >to PCIe MSI. The only difference is that we need to get hold of the
> interrupt
> > >specifier for the interupts coming into the irqmux.
> > >  - Do not use a chained interrupt controller.
> > > v2:
> > >  - Use interrupt-map to allow the GPIO controller info to be specified
> > >as part of the irq.
> > >  - Renamed struct and funcs from 'girq' to a more comprehenisble
> 'irqmux'.
> > > ---
> > >  drivers/irqchip/Kconfig|   9 ++
> > >  drivers/irqchip/Makefile   |   1 +
> > >  drivers/irqchip/rzn1-irq-mux.c | 205
> > > +
> > >  3 files changed, 215 insertions(+)
> > >  create mode 100644 drivers/irqchip/rzn1-irq-mux.c
> > >
> > > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
> > > 96451b581452..53c54bba1dd8 100644
> > > --- a/drivers/irqchip/Kconfig
> > > +++ b/drivers/irqchip/Kconfig
> > > @@ -204,6 +204,15 @@ config RENESAS_IRQC
> > >   select GENERIC_IRQ_CHIP
> > >   select IRQ_DOMAIN
> > >
> > > +config RENESAS_RZN1_IRQ_MUX
> > > + bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
> > > + depends on ARCH_RZN1
> > > + select IRQ_DOMAIN
> > > + help
> > > +   Say yes here to add support for the GPIO IRQ multiplexer
> > > embedded
> > > +   in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
> > > +   the interrupts coming from the GPIO controllers are used.
> > > +
> > >  config ST_IRQCHIP
> > >   bool
> > >   select REGMAP
> > > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> > > index b822199445ff..b090f84dd42e 100644
> > > --- a/drivers/irqchip/Makefile
> > > +++ b/drivers/irqchip/Makefile
> > > @@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)  +=
> irq-
> > > sirfsoc.o
> > >  obj-$(CONFIG_JCORE_AIC)  += irq-jcore-aic.o
> > >  obj-$(CONFIG_RENESAS_INTC_IRQPIN)+= irq-renesas-intc-irqpin.o
> > >  obj-$(CONFIG_RENESAS_IRQC)   += irq-renesas-irqc.o
> > > +obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX)   += rzn1-irq-mux.o
> > >  obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
> > >  obj-$(CONFIG_ARCH_NSPIRE)+= irq-zevio.o
> > >  obj-$(CONFIG_ARCH_VT8500)+= irq-vt8500.o
> > > diff --git a/drivers/irqchip/rzn1-irq-mux.c
> > > b/drivers/irqchip/rzn1-irq-mux.c new file mode 100644 index
> > > ..ee7810b9b3f3
> > > --- /dev/null
> > > +++ b/drivers/irqchip/rzn1-irq-mux.c
> > > @@ -0,0 +1,205 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * RZ/N1 GPIO Interrupt Multiplexer
> > > + *
> > > + * Copyright (C) 2018 Renesas Electronics Europe Limited
> > > + *
> > > + * On 

RE: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2019-02-19 Thread Phil Edworthy
Hello,

Any comments on this patch?

Thanks
Phil

> -Original Message-
> From: Phil Edworthy 
> Sent: 13 November 2018 13:09
> To: Marc Zyngier ; Thomas Gleixner
> ; Jason Cooper 
> Cc: Geert Uytterhoeven ; linux-renesas-
> s...@vger.kernel.org; linux-kernel@vger.kernel.org; Phil Edworthy
> 
> Subject: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO
> interrupt multiplexer
> 
> On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> configured to have 32 interrupt outputs, so we have a total of 96 GPIO
> interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
> 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals aren't
> latched, so there is nothing to do in this driver when an interrupt is 
> received,
> other than tell the corresponding GPIO block.
> 
> Signed-off-by: Phil Edworthy 
> ---
> v3:
>  - Use 'interrupt-map' DT property to map the interrupts, this is very similar
>to PCIe MSI. The only difference is that we need to get hold of the 
> interrupt
>specifier for the interupts coming into the irqmux.
>  - Do not use a chained interrupt controller.
> v2:
>  - Use interrupt-map to allow the GPIO controller info to be specified
>as part of the irq.
>  - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
> ---
>  drivers/irqchip/Kconfig|   9 ++
>  drivers/irqchip/Makefile   |   1 +
>  drivers/irqchip/rzn1-irq-mux.c | 205
> +
>  3 files changed, 215 insertions(+)
>  create mode 100644 drivers/irqchip/rzn1-irq-mux.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
> 96451b581452..53c54bba1dd8 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -204,6 +204,15 @@ config RENESAS_IRQC
>   select GENERIC_IRQ_CHIP
>   select IRQ_DOMAIN
> 
> +config RENESAS_RZN1_IRQ_MUX
> + bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
> + depends on ARCH_RZN1
> + select IRQ_DOMAIN
> + help
> +   Say yes here to add support for the GPIO IRQ multiplexer
> embedded
> +   in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
> +   the interrupts coming from the GPIO controllers are used.
> +
>  config ST_IRQCHIP
>   bool
>   select REGMAP
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index
> b822199445ff..b090f84dd42e 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)  += irq-
> sirfsoc.o
>  obj-$(CONFIG_JCORE_AIC)  += irq-jcore-aic.o
>  obj-$(CONFIG_RENESAS_INTC_IRQPIN)+= irq-renesas-intc-irqpin.o
>  obj-$(CONFIG_RENESAS_IRQC)   += irq-renesas-irqc.o
> +obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX)   += rzn1-irq-mux.o
>  obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
>  obj-$(CONFIG_ARCH_NSPIRE)+= irq-zevio.o
>  obj-$(CONFIG_ARCH_VT8500)+= irq-vt8500.o
> diff --git a/drivers/irqchip/rzn1-irq-mux.c b/drivers/irqchip/rzn1-irq-mux.c
> new file mode 100644 index ..ee7810b9b3f3
> --- /dev/null
> +++ b/drivers/irqchip/rzn1-irq-mux.c
> @@ -0,0 +1,205 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * RZ/N1 GPIO Interrupt Multiplexer
> + *
> + * Copyright (C) 2018 Renesas Electronics Europe Limited
> + *
> + * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> +configured
> + * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
> + * All of these are passed to the GPIO IRQ Muxer, which selects 8 of
> +the GPIO
> + * interrupts to pass onto the GIC.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define MAX_NR_INPUT_IRQS96
> +#define MAX_NR_OUTPUT_IRQS   8
> +
> +/*
> + * "interrupt-map" consists of 1 interrupt cell, 0 address cells,
> +phandle to
> + * interrupt parent, and parent interrupt specifier (3 cells for GIC),
> +giving
> + * a total of 5 cells.
> + */
> +#define IMAP_LENGTH  5
> +
> +struct irqmux_priv;
> +struct irqmux_one {
> + unsigned int irq;
> + unsigned int src_hwirq;
> + struct irqmux_priv *priv;
> +};
> +
> +struct irqmux_priv {
> + struct device *dev;
> + struct irq_domain *irq_domain;
> + unsigned int nr_irqs;
> + struct irqmux_one mux[MAX_NR_OUTPUT_IRQS]; };
> +
> +static irqreturn_t irqmux_handler(int irq, void *data) {
> + struct irqmux_one *mux = data;
> + struct irqmux_priv *priv = mux->priv;
> + 

RE: [PATCH v9 1/2] clk: Add comment about __of_clk_get_by_name() error values

2019-01-16 Thread Phil Edworthy
Hi,

Any other comments on this patch and patch 2/2 
(https://lkml.org/lkml/2018/12/3/326)?

Thanks
Phil

> -Original Message-
> From: Phil Edworthy
> Sent: 06 December 2018 12:31
> To: 'Andy Shevchenko' 
> Cc: Michael Turquette ; Stephen Boyd
> ; Russell King ; Geert
> Uytterhoeven ; Uwe Kleine-König  koe...@pengutronix.de>; linux-...@vger.kernel.org; linux-
> ker...@vger.kernel.org; linux-arm-ker...@lists.infradead.org
> Subject: RE: [PATCH v9 1/2] clk: Add comment about
> __of_clk_get_by_name() error values
> 
> Hi Andy,
> 
> On 03 December 2018 13:31 Andy Shevchenko wrote:
> > On Mon, Dec 03, 2018 at 11:13:08AM +, Phil Edworthy wrote:
> > > It's not immediately obvious from the code that failure to get a
> > > clock provider can return either -ENOENT or -EINVAL. Therefore, add
> > > a comment to highlight this.
> >
> > > +/*
> > > + * Beware the return values when np is valid, but no clock provider
> > > +is
> > found.
> > > + * If name = NULL, the function returns -ENOENT.
> > > + * If name != NULL, the function returns -EINVAL. This is because
> > > +__of_clk_get()
> >
> > I would start new sentence from new line (this will emphasize the
> > possible
> > variants)
> >
> >  * This is ...
> I disagree, the explanation is specifically related to the case where the
> function returns -EINVAL. Though this is a nit, so I'm not really bothered
> either way.
> 
> Thanks for the review!
> Phil
> 
> >  Otherwise looks good to me:
> >
> > Reviewed-by: Andy Shevchenko 
> >
> > > + * is called even if of_property_match_string() returns an error.
> > > + */
> > >  static struct clk *__of_clk_get_by_name(struct device_node *np,
> > >   const char *dev_id,
> > >   const char *name)
> > > --
> > > 2.17.1
> > >
> >
> > --
> > With Best Regards,
> > Andy Shevchenko
> >



RE: [PATCH v9 1/2] clk: Add comment about __of_clk_get_by_name() error values

2018-12-06 Thread Phil Edworthy
Hi Andy,

On 03 December 2018 13:31 Andy Shevchenko wrote:
> On Mon, Dec 03, 2018 at 11:13:08AM +0000, Phil Edworthy wrote:
> > It's not immediately obvious from the code that failure to get a clock
> > provider can return either -ENOENT or -EINVAL. Therefore, add a
> > comment to highlight this.
> 
> > +/*
> > + * Beware the return values when np is valid, but no clock provider is
> found.
> > + * If name = NULL, the function returns -ENOENT.
> > + * If name != NULL, the function returns -EINVAL. This is because
> > +__of_clk_get()
> 
> I would start new sentence from new line (this will emphasize the possible
> variants)
> 
>  * This is ...
I disagree, the explanation is specifically related to the case where the 
function
returns -EINVAL. Though this is a nit, so I'm not really bothered either way.

Thanks for the review!
Phil

>  Otherwise looks good to me:
> 
> Reviewed-by: Andy Shevchenko 
> 
> > + * is called even if of_property_match_string() returns an error.
> > + */
> >  static struct clk *__of_clk_get_by_name(struct device_node *np,
> > const char *dev_id,
> > const char *name)
> > --
> > 2.17.1
> >
> 
> --
> With Best Regards,
> Andy Shevchenko
> 



[PATCH v9 0/2] clk: Add functions to get optional clocks

2018-12-03 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a bus clock required to 
access peripheral's registers that is always enabled on some devices.

v9:
 - Add a separate patch to add a comment about __of_clk_get_by_name() error
   values.
 - Add brackets after devm_clk_get so people know it's a function.
 - Add kernel doc for clk_get_optional().


Phil Edworthy (2):
  clk: Add comment about __of_clk_get_by_name() error values
  clk: Add (devm_)clk_get_optional() functions

 drivers/clk/clk-devres.c | 11 +++
 drivers/clk/clkdev.c |  6 ++
 include/linux/clk.h  | 36 
 3 files changed, 53 insertions(+)

-- 
2.17.1



[PATCH v9 1/2] clk: Add comment about __of_clk_get_by_name() error values

2018-12-03 Thread Phil Edworthy
It's not immediately obvious from the code that failure to get a
clock provider can return either -ENOENT or -EINVAL. Therefore, add
a comment to highlight this.

Signed-off-by: Phil Edworthy 
---
 drivers/clk/clkdev.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8b3988..cc5df3970cd3 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -52,6 +52,12 @@ struct clk *of_clk_get(struct device_node *np, int index)
 }
 EXPORT_SYMBOL(of_clk_get);
 
+/*
+ * Beware the return values when np is valid, but no clock provider is found.
+ * If name = NULL, the function returns -ENOENT.
+ * If name != NULL, the function returns -EINVAL. This is because 
__of_clk_get()
+ * is called even if of_property_match_string() returns an error.
+ */
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
const char *name)
-- 
2.17.1



[PATCH v9 2/2] clk: Add (devm_)clk_get_optional() functions

2018-12-03 Thread Phil Edworthy
This adds clk_get_optional() and devm_clk_get_optional() functions to get
optional clocks.
They behave the same as (devm_)clk_get() except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
Reviewed-by: Andy Shevchenko 
---
v9:
 - Add brackets after devm_clk_get so people know it's a function.
 - Add kernel doc for clk_get_optional().
v8:
 - Remove else clause
v7:
 - Instead of messing with the core functions, simply wrap them for the
   _optional() versions. By putting clk_get_optional() inline in the header
   file, we can get rid of the arch specific patches as well.
v6:
 - Add doxygen style comment for devm_clk_get_optional() args
v5:
 - No changes.
v4:
 - No changes.
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 11 +++
 include/linux/clk.h  | 36 
 2 files changed, 47 insertions(+)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 12c87457eca1..8e8893168676 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -34,6 +34,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *clk = devm_clk_get(dev, id);
+
+   if (clk == ERR_PTR(-ENOENT))
+   return NULL;
+
+   return clk;
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index a7773b5c0b9f..d8bc1a856b39 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -383,6 +383,17 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
  */
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
+/**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as devm_clk_get() except where there is no clock producer.
+ * In this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
 /**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
@@ -718,6 +729,12 @@ static inline struct clk *devm_clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *devm_clk_get_optional(struct device *dev,
+   const char *id)
+{
+   return NULL;
+}
+
 static inline int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk_bulk_data *clks)
 {
@@ -862,6 +879,25 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
clk_bulk_unprepare(num_clks, clks);
 }
 
+/**
+ * clk_get_optional - lookup and obtain a reference to an optional clock
+ *   producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get() except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *clk = clk_get(dev, id);
+
+   if (clk == ERR_PTR(-ENOENT))
+   return NULL;
+
+   return clk;
+}
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
-- 
2.17.1



RE: [PATCH v8] clk: Add (devm_)clk_get_optional() functions

2018-11-30 Thread Phil Edworthy
Hi Stephen,

On 30 November 2018 09:09 Stephen Boyd wrote:
> Quoting Phil Edworthy (2018-11-20 06:14:45)
> > This adds clk_get_optional() and devm_clk_get_optional() functions to
> > get optional clocks.
> > They behave the same as (devm_)clk_get except where there is no clock
> > producer. In this case, instead of returning -ENOENT, the function
> > returns NULL. This makes error checking simpler and allows
> > clk_prepare_enable, etc to be called on the returned reference without
> > additional checks.
> 
> Ok. I guess that works by virtue of how -ENOENT is returned by various
> functions that are called deeper in the clk_get() path? I'm cautiously
> optimistic. So cautious, we should probably add a comment to these optional
> functions that indicate they rely on the functions they call to return -ENOENT
> under the various conditions that make a clk optional.
Yes, it does indeed rely on how clk_get() is implemented.
Specifically, that if __of_clk_get_by_name() returns -EINVAL, the error is
superseded by clk_get_sys() returning -ENOENT.
As you say, a comment may help here.


> >
> > diff --git a/include/linux/clk.h b/include/linux/clk.h index
> > a7773b5c0b9f..3ea3c78f62dd 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -383,6 +383,17 @@ int __must_check devm_clk_bulk_get_all(struct
> device *dev,
> >   */
> >  struct clk *devm_clk_get(struct device *dev, const char *id);
> >
> > +/**
> > + * devm_clk_get_optional - lookup and obtain a managed reference to an
> optional
> > + *clock producer.
> > + * @dev: device for clock "consumer"
> > + * @id: clock consumer ID
> > + *
> > + * Behaves the same as devm_clk_get except where there is no clock
> > +producer. In
> 
> Please add () around devm_clk_get() so we know it's a function.
Will do.


> > + * this case, instead of returning -ENOENT, the function returns NULL.
> > + */
> > +struct clk *devm_clk_get_optional(struct device *dev, const char
> > +*id);
> > +
> >  /**
> >   * devm_get_clk_from_child - lookup and obtain a managed reference to a
> >   *  clock producer from child node.
> > @@ -718,6 +729,12 @@ static inline struct clk *devm_clk_get(struct device
> *dev, const char *id)
> > return NULL;
> >  }
> >
> > +static inline struct clk *devm_clk_get_optional(struct device *dev,
> > +   const char *id) {
> > +   return NULL;
> > +}
> > +
> >  static inline int __must_check devm_clk_bulk_get(struct device *dev, int
> num_clks,
> >  struct clk_bulk_data
> > *clks)  { @@ -862,6 +879,16 @@ static inline void
> > clk_bulk_disable_unprepare(int num_clks,
> > clk_bulk_unprepare(num_clks, clks);  }
> >
> > +static inline struct clk *clk_get_optional(struct device *dev, const
> > +char *id)
> 
> Any kernel doc for this function?
I took my cue from the surrounding functions, let me know if I have to add it.

Thanks
Phil

> > +{
> > +   struct clk *clk = clk_get(dev, id);
> > +
> > +   if (clk == ERR_PTR(-ENOENT))
> > +   clk = NULL;
> > +
> > +   return clk;
> > +}
> > +


[PATCH] arm64: dts: alpine: Correct the GIC DT node name

2018-11-27 Thread Phil Edworthy
Harmless mistake, but it's incorrect. The DT spec provides recommendations
for the node names:
"The name of a node should be somewhat generic, reflecting the function
of the device and not its precise programming model. If appropriate, the
name should be one of the following choices:
...
interrupt-controller"

Signed-off-by: Phil Edworthy 
---
 arch/arm64/boot/dts/al/alpine-v2.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/al/alpine-v2.dtsi 
b/arch/arm64/boot/dts/al/alpine-v2.dtsi
index 5b7bef684256..6f35bab10e9d 100644
--- a/arch/arm64/boot/dts/al/alpine-v2.dtsi
+++ b/arch/arm64/boot/dts/al/alpine-v2.dtsi
@@ -113,7 +113,7 @@
 ;
};
 
-   gic: gic@f010 {
+   gic: interrupt-controller@f010 {
compatible = "arm,gic-v3";
reg = <0x0 0xf020 0x0 0x1>, /* GIC Dist */
  <0x0 0xf028 0x0 0x20>,/* GICR */
-- 
2.17.1



[PATCH] ARM: dts: alpine: Correct the GIC DT node name

2018-11-27 Thread Phil Edworthy
Harmless mistake, but it's incorrect. The DT spec provides recommendations
for the node names:
"The name of a node should be somewhat generic, reflecting the function
of the device and not its precise programming model. If appropriate, the
name should be one of the following choices:
...
interrupt-controller"

Signed-off-by: Phil Edworthy 
---
 arch/arm/boot/dts/alpine.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/alpine.dtsi b/arch/arm/boot/dts/alpine.dtsi
index 731df7a8c4e6..533c876497ff 100644
--- a/arch/arm/boot/dts/alpine.dtsi
+++ b/arch/arm/boot/dts/alpine.dtsi
@@ -85,7 +85,7 @@
};
 
/* Interrupt Controller */
-   gic: gic@fb001000 {
+   gic: interrupt-controller@fb001000 {
compatible = "arm,cortex-a15-gic";
#interrupt-cells = <3>;
#size-cells = <0>;
-- 
2.17.1



[PATCH] ARM: dts: OX820: Correct the GIC DT node name

2018-11-27 Thread Phil Edworthy
Harmless mistake, but it's incorrect. The DT spec provides recommendations
for the node names:
"The name of a node should be somewhat generic, reflecting the function
of the device and not its precise programming model. If appropriate, the
name should be one of the following choices:
...
interrupt-controller"

Signed-off-by: Phil Edworthy 
---
 arch/arm/boot/dts/ox820.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/ox820.dtsi b/arch/arm/boot/dts/ox820.dtsi
index 085bbd33eadc..3a17ab4e7c2f 100644
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -286,7 +286,7 @@
clocks = <&armclk>;
};
 
-   gic: gic@1000 {
+   gic: interrupt-controller@1000 {
compatible = "arm,arm11mp-gic";
interrupt-controller;
#interrupt-cells = <3>;
-- 
2.17.1



RE: [PATCH] pinctrl: rzn1: Fix check for used MDIO bus

2018-11-23 Thread Phil Edworthy
Hi Geert,

On 23 November 2018 09:41 Geert Uytterhoeven wrote:
> Subject: Re: [PATCH] pinctrl: rzn1: Fix check for used MDIO bus
> On Mon, Nov 19, 2018 at 5:18 PM Phil Edworthy wrote:
> > This fixes the check for unused mdio bus setting and the following
> > static checker warning:
> >  drivers/pinctrl/pinctrl-rzn1.c:198 rzn1_pinctrl_mdio_select()
> >  warn: always true condition '(ipctl->mdio_func[mdio] >= 0) => (0-u32max
> >= 0)'
> >
> > It also fixes the return var when calling of_get_child_count()
> 
> I think this should be a separate patch.
Ok, I'll split them.


> > Reported-by: Dan Carpenter 
> > Signed-off-by: Phil Edworthy 
> 
> Reviewed-by: Geert Uytterhoeven 
> 
> BTW, I have a question about rzn1_pinctrl_mdio_select():
> 
> static void rzn1_pinctrl_mdio_select(struct rzn1_pinctrl *ipctl, int mdio,
>  u32 func) {
> if (ipctl->mdio_func[mdio] >= 0 && ipctl->mdio_func[mdio] != func)
> dev_warn(ipctl->dev, "conflicting setting for mdio%d!\n", 
> mdio);
> ipctl->mdio_func[mdio] = func;
> 
> dev_dbg(ipctl->dev, "setting mdio%d to %u\n", mdio, func);
> 
> writel(func, &ipctl->lev2->l2_mdio[mdio]); }
> 
> The check warns the user if it overrides an already initialized MDIO function
> with a different value.
> However, there is no method to uninitialize (reset to -1) mdio_func[], to
> avoid getting the warning.
> 
> For a use case, I was thinking about a DT overlay that would cause the MDIO
> function to be initialized on loading, and needs to uninitialize the MDIO
> function on removing.
> 
> Perhaps that is very unlikely or even impossible, given the function of the
> pins controlled by the MDIO function?
I hadn't considered that DT overlay possibility...
Since this MDIO muxing selects one of several different IP blocks as the
MDIO master, I guess it could happen. However, this is pretty unlikely!

I can't see any way via the pinctrl_ops or pinconf_ops to 'undo' a pin
setting, how would this work?
If a DT overlay causes remove() then probe() to be called again, the driver
resets mdio_func[] in probe(), so it'll work.

Thanks!
Phil


RE: [PATCH] pinctrl: rzn1: Fix check for used MDIO bus

2018-11-22 Thread Phil Edworthy
Hi Simon,

On 22 November 2018 14:09 Simon Horman wrote:
> On Mon, Nov 19, 2018 at 04:18:38PM +0000, Phil Edworthy wrote:
> > This fixes the check for unused mdio bus setting and the following
> > static checker warning:
> >  drivers/pinctrl/pinctrl-rzn1.c:198 rzn1_pinctrl_mdio_select()
> >  warn: always true condition '(ipctl->mdio_func[mdio] >= 0) => (0-u32max
> >= 0)'
> >
> > It also fixes the return var when calling of_get_child_count()
> >
> > Reported-by: Dan Carpenter 
> > Signed-off-by: Phil Edworthy 
> > ---
> > v2:
> >  - Don't rely on rely on the implicit typecast from -1 to uint
> > ---
> >  drivers/pinctrl/pinctrl-rzn1.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/pinctrl/pinctrl-rzn1.c
> > b/drivers/pinctrl/pinctrl-rzn1.c index 57886dcff53d..cc0e5aa9128a
> > 100644
> > --- a/drivers/pinctrl/pinctrl-rzn1.c
> > +++ b/drivers/pinctrl/pinctrl-rzn1.c
> > @@ -112,7 +112,7 @@ struct rzn1_pinctrl {
> > struct rzn1_pinctrl_regs __iomem *lev2;
> > u32 lev1_protect_phys;
> > u32 lev2_protect_phys;
> > -   u32 mdio_func[2];
> > +   int mdio_func[2];
> 
> Hi Phil,
> 
> rzn1_pinctrl_mdio_select() assigns values of type u32 to elements of
> mdio_func. Perhaps that warrants cleaning up too?
The source of the 'u32 func' arg is ultimately u32 values read from DT.
The code already ensures that these cannot be bigger than 7, so is fine
I think.

Thanks
Phil


> > struct rzn1_pin_group *groups;
> > unsigned int ngroups;
> > @@ -810,8 +810,8 @@ static int rzn1_pinctrl_probe_dt(struct
> platform_device *pdev,
> > struct device_node *np = pdev->dev.of_node;
> > struct device_node *child;
> > unsigned int maxgroups = 0;
> > -   unsigned int nfuncs = 0;
> > unsigned int i = 0;
> > +   int nfuncs = 0;
> > int ret;
> >
> > nfuncs = of_get_child_count(np);
> > --
> > 2.17.1
> >


[PATCH v8] clk: Add (devm_)clk_get_optional() functions

2018-11-20 Thread Phil Edworthy
This adds clk_get_optional() and devm_clk_get_optional() functions to get
optional clocks.
They behave the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
Reviewed-by: Andy Shevchenko 
---
v8:
 - Remove else clause
v7:
 - Instead of messing with the core functions, simply wrap them for the
   _optional() versions. By putting clk_get_optional() inline in the header
   file, we can get rid of the arch specific patches as well.
v6:
 - Add doxygen style comment for devm_clk_get_optional() args
v5:
 - No changes.
v4:
 - No changes.
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 11 +++
 include/linux/clk.h  | 27 +++
 2 files changed, 38 insertions(+)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 12c87457eca1..c6f4a1a92c5f 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -34,6 +34,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *clk = devm_clk_get(dev, id);
+
+   if (clk == ERR_PTR(-ENOENT))
+   clk = NULL;
+
+   return clk;
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index a7773b5c0b9f..3ea3c78f62dd 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -383,6 +383,17 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
  */
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
+/**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
 /**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
@@ -718,6 +729,12 @@ static inline struct clk *devm_clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *devm_clk_get_optional(struct device *dev,
+   const char *id)
+{
+   return NULL;
+}
+
 static inline int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk_bulk_data *clks)
 {
@@ -862,6 +879,16 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
clk_bulk_unprepare(num_clks, clks);
 }
 
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *clk = clk_get(dev, id);
+
+   if (clk == ERR_PTR(-ENOENT))
+   clk = NULL;
+
+   return clk;
+}
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
-- 
2.17.1



[PATCH] gpio: dwapb: Correct the DT node name in the example

2018-11-20 Thread Phil Edworthy
The sub-nodes should not be called gpio-controller, but simply gpio.

Signed-off-by: Phil Edworthy 
---
 Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 7276b50c3506..839dd32ffe11 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -43,7 +43,7 @@ gpio: gpio@2 {
#address-cells = <1>;
#size-cells = <0>;
 
-   porta: gpio-controller@0 {
+   porta: gpio@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
@@ -55,7 +55,7 @@ gpio: gpio@2 {
interrupts = <0>;
};
 
-   portb: gpio-controller@1 {
+   portb: gpio@1 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
-- 
2.17.1



RE: [PATCH] clk: Add (devm_)clk_get_optional() functions

2018-11-20 Thread Phil Edworthy
Hi Andy,

On 20 November 2018 10:39 Andy Shevchenko wrote:
> On Mon, Nov 19, 2018 at 02:12:59PM +0000, Phil Edworthy wrote:
> > This adds clk_get_optional() and devm_clk_get_optional() functions to
> > get optional clocks.
> > They behave the same as (devm_)clk_get except where there is no clock
> > producer. In this case, instead of returning -ENOENT, the function
> > returns NULL. This makes error checking simpler and allows
> > clk_prepare_enable, etc to be called on the returned reference without
> > additional checks.
> 
> >  - Instead of messing with the core functions, simply wrap them for the
> >_optional() versions. By putting clk_get_optional() inline in the header
> >file, we can get rid of the arch specific patches as well.
> 
> Fine if it would have no surprises with error handling.
There shouldn't be any surprises. My earlier attempts at implementing this
were hampered by the fact that of_clk_get_by_name() can return -EINVAL
in some circumstances. By directly wrapping the (devm_)clk_get() functions
that problem goes away.

> > +   if (ERR_PTR(-ENOENT))
Huh? That wasn't the code I sent...

> > +   return NULL;
> > +   else
> > +   return clk;
> 
> return clk == ERR_PTR(-ENOENT) ? NULL : clk;
> 
> ?
> 
> > +   if (clk == ERR_PTR(-ENOENT))
> > +   return NULL;
> > +   else
> > +   return clk;
> 
> Ditto.
Sure, will fix both.

Thanks
Phil


[PATCH] pinctrl: rzn1: Fix check for used MDIO bus

2018-11-19 Thread Phil Edworthy
This fixes the check for unused mdio bus setting and the following static
checker warning:
 drivers/pinctrl/pinctrl-rzn1.c:198 rzn1_pinctrl_mdio_select()
 warn: always true condition '(ipctl->mdio_func[mdio] >= 0) => (0-u32max >= 0)'

It also fixes the return var when calling of_get_child_count()

Reported-by: Dan Carpenter 
Signed-off-by: Phil Edworthy 
---
v2:
 - Don't rely on rely on the implicit typecast from -1 to uint
---
 drivers/pinctrl/pinctrl-rzn1.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-rzn1.c b/drivers/pinctrl/pinctrl-rzn1.c
index 57886dcff53d..cc0e5aa9128a 100644
--- a/drivers/pinctrl/pinctrl-rzn1.c
+++ b/drivers/pinctrl/pinctrl-rzn1.c
@@ -112,7 +112,7 @@ struct rzn1_pinctrl {
struct rzn1_pinctrl_regs __iomem *lev2;
u32 lev1_protect_phys;
u32 lev2_protect_phys;
-   u32 mdio_func[2];
+   int mdio_func[2];
 
struct rzn1_pin_group *groups;
unsigned int ngroups;
@@ -810,8 +810,8 @@ static int rzn1_pinctrl_probe_dt(struct platform_device 
*pdev,
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
unsigned int maxgroups = 0;
-   unsigned int nfuncs = 0;
unsigned int i = 0;
+   int nfuncs = 0;
int ret;
 
nfuncs = of_get_child_count(np);
-- 
2.17.1



[PATCH] clk: Add (devm_)clk_get_optional() functions

2018-11-19 Thread Phil Edworthy
This adds clk_get_optional() and devm_clk_get_optional() functions to get
optional clocks.
They behave the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
---
v7:
 - Instead of messing with the core functions, simply wrap them for the
   _optional() versions. By putting clk_get_optional() inline in the header
   file, we can get rid of the arch specific patches as well.
v6:
 - Add doxygen style comment for devm_clk_get_optional() args
v5:
 - No changes.
v4:
 - No changes.
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 11 +++
 include/linux/clk.h  | 27 +++
 2 files changed, 38 insertions(+)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 12c87457eca1..f0033d937c39 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -34,6 +34,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *clk = devm_clk_get(dev, id);
+
+   if (clk == ERR_PTR(-ENOENT))
+   return NULL;
+   else
+   return clk;
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index a7773b5c0b9f..c7bbb0678057 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -383,6 +383,17 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
  */
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
+/**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
 /**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
@@ -718,6 +729,12 @@ static inline struct clk *devm_clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *devm_clk_get_optional(struct device *dev,
+   const char *id)
+{
+   return NULL;
+}
+
 static inline int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk_bulk_data *clks)
 {
@@ -862,6 +879,16 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
clk_bulk_unprepare(num_clks, clks);
 }
 
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *clk = clk_get(dev, id);
+
+   if (clk == ERR_PTR(-ENOENT))
+   return NULL;
+   else
+   return clk;
+}
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
-- 
2.17.1



RE: [PATCH v6 1/6] clk: Add of_clk_get_by_name_optional() function

2018-11-19 Thread Phil Edworthy
Hi Uwe,

On 19 November 2018 12:58 Uwe Kleine-König wrote:
> On Mon, Nov 19, 2018 at 12:53:46PM +0000, Phil Edworthy wrote:
> > On 19 November 2018 10:46 Uwe Kleine-König wrote:
> > > On Mon, Nov 19, 2018 at 10:41:42AM +0000, Phil Edworthy wrote:
> > > > btw, do we need to add of_clk_get_by_name_optional()? I only added
> it
> > > > as a counterpart to of_clk_get_by_name(), but it may not be needed.
> > >
> > > I don't need it. Given that it is easy to add when someone has a need, I'd
> say,
> > > skip it for now.
> >
> > I'm wondering if we actually need clk_get_optional(). For me at least, I 
> > just
> > want devm_clk_get_optional(). That would get rid of the arch patches.
> 
> Given that clk_get_optional will be that simple, it can live in
> linux/clk.h for all implementors of the clk API, then you don't have to
> care about different archs. (Unless I'm missing something.)
You are absolutely right, I'm such a clutz sometimes!

Thanks
Phil

> I don't think it's a good idea to drop clk_get_optional even if you'd
> have to provide arch-specific stuff.
> 
> Best regards
> Uwe
> 
> --
> Pengutronix e.K.   | Uwe Kleine-König|
> Industrial Linux Solutions | http://www.pengutronix.de/  |


RE: [PATCH v6 1/6] clk: Add of_clk_get_by_name_optional() function

2018-11-19 Thread Phil Edworthy
Hi Uwe,

On 19 November 2018 10:46 Uwe Kleine-König wrote:
> On Mon, Nov 19, 2018 at 10:41:42AM +0000, Phil Edworthy wrote:
> > On 16 November 2018 16:11 Uwe Kleine-König wrote:
> > > On Fri, Nov 16, 2018 at 05:01:28PM +0100, Uwe Kleine-König wrote:
> > > > Other than that I think the patch is fine
> > >
> > > Thinking again, I wonder why not just do:
> > >
> > > static inline struct clk *clk_get_optional(struct device *dev, const char
> *id) {
> > >   struct clk *c = clk_get(dev, id);
> > >
> > >   if (c == ERR_PTR(-ENOENT))
> > >   return NULL;
> > >   else
> > >   return c;
> > > }
> >
> > Unfortunately, underneath this __of_clk_get_by_name() returns -EINVAL
> > when looking for a named clock, and the "clock-names" OF property
> > can't be found or the name is not in that prop. This is because the
> > index returned by of_property_match_string() will be an error code and
> > is then currently always passed to __of_clk_get().
> >
> > If, as you said, I split the patches into one that fixes the error
> > code, and then adds clk_get_optional() like above, it will make more sense.
> 
> Sounds like a good plan.
Now that I have removed of_clk_get_by_name_optional(), I see that clk_get()
deals with __of_clk_get_by_name() returning -EINVAL and -ENOENT the same
way. In both cases, clk_get_sys() will return -ENOENT... i.e. I no longer need 
to
modify __of_clk_get_by_name().
All I need is a simple wrapper just as you have outlined above.

> > btw, do we need to add of_clk_get_by_name_optional()? I only added it
> > as a counterpart to of_clk_get_by_name(), but it may not be needed.
> 
> I don't need it. Given that it is easy to add when someone has a need, I'd 
> say,
> skip it for now.
I'm wondering if we actually need clk_get_optional(). For me at least, I just
want devm_clk_get_optional(). That would get rid of the arch patches.

Thanks
Phil


RE: [PATCH v6 1/6] clk: Add of_clk_get_by_name_optional() function

2018-11-19 Thread Phil Edworthy
Hi Uwe,

On 16 November 2018 16:11 Uwe Kleine-König wrote:
> On Fri, Nov 16, 2018 at 05:01:28PM +0100, Uwe Kleine-König wrote:
> > Other than that I think the patch is fine
> 
> Thinking again, I wonder why not just do:
> 
> static inline struct clk *clk_get_optional(struct device *dev, const char 
> *id) {
>   struct clk *c = clk_get(dev, id);
> 
>   if (c == ERR_PTR(-ENOENT))
>   return NULL;
>   else
>   return c;
> }

Unfortunately, underneath this __of_clk_get_by_name() returns -EINVAL
when looking for a named clock, and the "clock-names" OF property can't
be found or the name is not in that prop. This is because the index
returned by of_property_match_string() will be an error code and is then
currently always passed to __of_clk_get().

If, as you said, I split the patches into one that fixes the error code, and 
then
adds clk_get_optional() like above, it will make more sense.

btw, do we need to add of_clk_get_by_name_optional()? I only added it as a
counterpart to of_clk_get_by_name(), but it may not be needed.

Thanks
Phil


RE: [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding

2018-11-19 Thread Phil Edworthy
Hi Rob,

On 17 November 2018 14:33 Rob Herring wrote:
> On Tue, Nov 13, 2018 at 01:09:09PM +0000, Phil Edworthy wrote:
> > Add device binding documentation for the Renesas RZ/N1 GPIO interrupt
> > multiplexer.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > v3:
> >  - Use 'interrupt-map' DT property correctly.
> > v2:
> >  - Use interrupt-map to allow the GPIO controller info to be specified
> >as part of the irq.
> >  - Don't show status in binding examples.
> >  - Don't show the soc/board split in binding doc.
> > ---
> >  .../interrupt-controller/renesas,rzn1-mux.txt | 73
> > +++
> >  1 file changed, 73 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mu
> > x.txt
> 
> A few nits, otherwise:
> 
> Reviewed-by: Rob Herring 
Thanks for the review!

> >
> > diff --git
> > a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > mux.txt
> > b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > mux.txt
> > new file mode 100644
> > index ..6515880e25cc
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,r
> > +++ zn1-mux.txt
> > @@ -0,0 +1,73 @@
> > +* Renesas RZ/N1 GPIO Interrupt Multiplexer
> > +
> > +On Renesas RZ/N1 devices, there are several GPIO Controllers each
> > +with a number of interrupt outputs. All of the interrupts from the
> > +GPIO Controllers are passed to the GPIO Interrupt Multiplexer, which
> > +selects a sub-set of the interrupts to pass onto the system interrupt
> controller.
> > +
> > +A single node in the device tree is used to describe the GPIO IRQ Muxer.
> > +
> > +Required properties:
> > +- compatible: SoC-specific compatible string "renesas,-
> gpioirqmux"
> > +  followed by "renesas,rzn1-gpioirqmux" as fallback. The SoC-specific
> > +compatible
> > +  strings must be one of:
> > +   "renesas,r9a06g032-gpioirqmux" for RZ/N1D
> > +   "renesas,r9a06g033-gpioirqmux" for RZ/N1S
> > +- reg: Base address and size of GPIO IRQ Muxer registers.
> > +- interrupts: List of output interrupts.
> > +- #interrupt-cells: Numder of cells in the input interrupt specifier, must 
> > be
> 1.
> > +- #address-cells: Must be 0.
> > +- interrupt-map-mask: must be 127.
> > +- interrupt-map: Standard property detailing the maps between input
> > +irqs and the
> > +  corresponding output irq. This consist of a list of:
> > +   
> > +  The input-irq-spec is from 0 to 95, corresponding to the outputs of
> > +the GPIO
> > +  Controllers.
> > +
> > +Example:
> > +
> > +   The following is an example for the RZ/N1D SoC.
> > +
> > +   gpioirqmux: gpioirqmux@51000480 {
> 
> interrupt-controller@...
Sure

> > +   compatible = "renesas,r9a06g032-gpioirqmux",
> > +   "renesas,rzn1-gpioirqmux";
> > +   reg = <0x51000480 0x20>;
> > +   interrupts =
> > +   ,
> > +   ;
> 
> This is a bit redundant as the same information is in interrupt-map, but I
> guess you need it to get the irq resources.
That's right.

> > +
> > +   #interrupt-cells = <1>;
> > +   #address-cells = <0>;
> > +   interrupt-map-mask = <127>;
> 
> Use hex for masks.
Ok.

> > +   interrupt-map =
> > +   /* gpio2a 24, pin 146: ETH Port 1 IRQ */
> > +   <88 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > +   /* gpio2a 26, pin 148: TouchSCRN_IRQ */
> > +   <90 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> > +   };
> > +
> > +   gpio2: gpio@5000d000 {
> > +   compatible = "snps,dw-apb-gpio";
> > +   reg = <0x5000d000 0x80>;
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +   clock-names = "bus";
> > +   clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
> > +
> > +   gpio2a: gpio-controller@0 {
> 
> gpio@0
Are you sure about this?
The bindings in Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
show an example where the sub-nodes for gpio banks are gpio-controller@.
This is also in Documentation/devicetree/bindings/gpio/gpio.txt.

Thanks
Phil

> > +   compatible = "snps,dw-apb-gpio-port";
> > +   bank-name = "gpio2a";
> > +   gpio-controller;
> > +   #gpio-cells = <2>;
> > +   snps,nr-gpios = <32>;
> > +   reg = <0>;
> > +
> > +   interrupt-controller;
> > +   interrupt-parent = <&gpioirqmux>;
> > +   interrupts =  < 64 65 66 67 68 69 70 71
> > +   72 73 74 75 76 77 78 79
> > +   80 81 82 83 84 85 86 87
> > +   88 89 90 91 92 93 94 95 >;
> > +   #interrupt-cells = <2>;
> > +   };
> > +   };
> > --
> > 2.17.1
> >


[PATCH v2 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2018-10-30 Thread Phil Edworthy
On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
configured to have 32 interrupt outputs, so we have a total of 96 GPIO
interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
aren't latched, so there is nothing to do in this driver when an interrupt
is received, other than tell the corresponding GPIO block.

Signed-off-by: Phil Edworthy 
---
v2:
 - Use interrupt-map to allow the GPIO controller info to be specified
   as part of the irq.
 - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
---
 drivers/irqchip/Kconfig|  10 ++
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/rzn1-irq-mux.c | 235 +
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/irqchip/rzn1-irq-mux.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 96451b581452..3a60a8af60dd 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -204,6 +204,16 @@ config RENESAS_IRQC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
 
+config RENESAS_RZN1_IRQ_MUX
+   bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
+   depends on ARCH_RZN1
+   select IRQ_DOMAIN
+   select IRQ_DOMAIN_HIERARCHY
+   help
+ Say yes here to add support for the GPIO IRQ multiplexer embedded
+ in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
+ the interrupts coming from the GPIO controllers are used.
+
 config ST_IRQCHIP
bool
select REGMAP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b822199445ff..b090f84dd42e 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)+= irq-sirfsoc.o
 obj-$(CONFIG_JCORE_AIC)+= irq-jcore-aic.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)  += irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
+obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX) += rzn1-irq-mux.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)   += irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_NSPIRE)  += irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)  += irq-vt8500.o
diff --git a/drivers/irqchip/rzn1-irq-mux.c b/drivers/irqchip/rzn1-irq-mux.c
new file mode 100644
index ..767ce67e34d2
--- /dev/null
+++ b/drivers/irqchip/rzn1-irq-mux.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/N1 GPIO Interrupt Multiplexer
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each 
configured
+ * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
+ * All of these are passed to the GPIO IRQ Muxer, which selects 8 of the GPIO
+ * interrupts to pass onto the GIC.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define GPIO_IRQ_SPEC_SIZE 3
+#define MAX_NR_GPIO_CONTROLLERS3
+#define MAX_NR_GPIO_IRQ32
+#define MAX_NR_INPUT_IRQS  (MAX_NR_GPIO_CONTROLLERS * MAX_NR_GPIO_IRQ)
+#define MAX_NR_OUTPUT_IRQS 8
+
+struct irqmux_priv;
+struct irqmux_one {
+   unsigned int mapped_irq;
+   unsigned int input_irq_nr;
+   struct irqmux_priv *priv;
+};
+
+struct irqmux_priv {
+   struct device *dev;
+   struct irq_chip irq_chip;
+   struct irq_domain *irq_domain;
+   unsigned int nr_irqs;
+   struct irqmux_one irq[MAX_NR_OUTPUT_IRQS];
+};
+
+static void irqmux_handler(struct irq_desc *desc)
+{
+   struct irq_chip *chip = irq_desc_get_chip(desc);
+   struct irqmux_one *girq = irq_desc_get_handler_data(desc);
+   struct irqmux_priv *priv = girq->priv;
+   unsigned int irq;
+
+   chained_irq_enter(chip, desc);
+
+   irq = irq_find_mapping(priv->irq_domain, girq->input_irq_nr);
+   generic_handle_irq(irq);
+
+   chained_irq_exit(chip, desc);
+}
+
+static int irqmux_domain_map(struct irq_domain *h, unsigned int irq,
+irq_hw_number_t hwirq)
+{
+   struct irqmux_priv *priv = h->host_data;
+
+   irq_set_chip_data(irq, h->host_data);
+   irq_set_chip_and_handler(irq, &priv->irq_chip, handle_simple_irq);
+
+   return 0;
+}
+
+static const struct irq_domain_ops irqmux_domain_ops = {
+   .map= irqmux_domain_map,
+};
+
+static int irqmux_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct device_node *np = dev->of_node;
+   struct resource *res;
+   u32 __iomem *regs;
+   struct irqmux_priv *priv;
+   u32 int_specs[MAX_NR_OUTPUT_IRQS][GPIO_IRQ_SPEC_SIZE];
+   DECLARE_BITMAP(irqs_in_used, MAX_NR_INPUT_IRQS);
+   unsigned int irqs_out_used = 0;
+   unsigned int i;
+   int nr_irqs;
+   int ret;
+
+   

[PATCH v6 3/3] ARM: dts: r9a06g032: Add pinctrl node

2018-09-27 Thread Phil Edworthy
This provides a pinctrl driver for the Renesas R9A06G032 SoC

Based on a patch originally written by Michel Pollet at Renesas.

Signed-off-by: Phil Edworthy 
---
v6:
 - No changes.

v5:
 - No changes.

v4:
 - No changes.

v3:
 - No changes.

v2:
 - Add "renesas,rzn1-pinctrl" compatible fallback string
 - Register size corrected.
---
 arch/arm/boot/dts/r9a06g032.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/r9a06g032.dtsi b/arch/arm/boot/dts/r9a06g032.dtsi
index eaf94976ed6d..2322268bc862 100644
--- a/arch/arm/boot/dts/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/r9a06g032.dtsi
@@ -165,6 +165,14 @@
status = "disabled";
};
 
+   pinctrl: pin-controller@40067000 {
+   compatible = "renesas,r9a06g032-pinctrl", 
"renesas,rzn1-pinctrl";
+   reg = <0x40067000 0x1000>, <0x5100 0x480>;
+   clocks = <&sysctrl R9A06G032_HCLK_PINCONFIG>;
+   clock-names = "bus";
+   status = "okay";
+   };
+
gic: gic@44101000 {
compatible = "arm,cortex-a7-gic", "arm,gic-400";
interrupt-controller;
-- 
2.17.1



[PATCH v6 2/3] pinctrl: renesas: Renesas RZ/N1 pinctrl driver

2018-09-27 Thread Phil Edworthy
This provides a pinctrl driver for the Renesas RZ/N1 device family.

Based on a patch originally written by Michel Pollet at Renesas.

Signed-off-by: Phil Edworthy 
Reviewed-by: Jacopo Mondi 
---
v6:
 - Instead of combining the pin nr and func into a single element, use
   a pair of 8-bit elements.
 - Simplified how the MDIO function is calculated

v5:
 - Address Jacopo's comments
 - Address Geert's comments

v4:
 - Address Jacopo's comments
 - Implement pin_config_group_get()
 - Fix function to get pin configs, i.e. return -EINVAL when disabled.

v3:
 - Use standard DT props instead of proprietary ones.
 - Replace virtual pins used for MDIO muxing with extra funcs.
 - Use pinctrl_utils funcs to handle the maps.
 - Remove the dbg functions to keep things simple.

v2:
 - Change filename to generic rzn1, instead of device specific.
 - Changed Kconfig symbol and file name to generic rzn1 family.
 - Added "renesas,rzn1-pinctrl" compatible fallback string
 - Changes suggested by Jacopo Mondi. Mainly formatting, plus:
   - Removed global ptr
   - Removed unused code accessing parent of node.
   - Removed check for null OF np that can't happen.
   - Replaced overlapping enums with #defines
 - Renamed some variables and symbols to clarify their use
 - Fix error handling during probe
 - Move probe from postcore_initcall to subsys_initcall to ensure
   drivers that require clocks get them instead of having to defer
   probing.
---
 drivers/pinctrl/Kconfig|  10 +
 drivers/pinctrl/Makefile   |   1 +
 drivers/pinctrl/pinctrl-rzn1.c | 941 +
 3 files changed, 952 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-rzn1.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 978b2ed4d014..4d8c00eac742 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -195,6 +195,16 @@ config PINCTRL_RZA1
help
  This selects pinctrl driver for Renesas RZ/A1 platforms.
 
+config PINCTRL_RZN1
+   bool "Renesas RZ/N1 pinctrl driver"
+   depends on OF
+   depends on ARCH_RZN1 || COMPILE_TEST
+   select GENERIC_PINCTRL_GROUPS
+   select GENERIC_PINMUX_FUNCTIONS
+   select GENERIC_PINCONF
+   help
+ This selects pinctrl driver for Renesas RZ/N1 devices.
+
 config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver"
depends on OF
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 8e127bd8610f..18a13c1e2c21 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_PINCTRL_PIC32)   += pinctrl-pic32.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
 obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o
+obj-$(CONFIG_PINCTRL_RZN1) += pinctrl-rzn1.o
 obj-$(CONFIG_PINCTRL_SINGLE)   += pinctrl-single.o
 obj-$(CONFIG_PINCTRL_SIRF) += sirf/
 obj-$(CONFIG_PINCTRL_SX150X)   += pinctrl-sx150x.o
diff --git a/drivers/pinctrl/pinctrl-rzn1.c b/drivers/pinctrl/pinctrl-rzn1.c
new file mode 100644
index ..c1c9ee4c502f
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-rzn1.c
@@ -0,0 +1,941 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014-2018 Renesas Electronics Europe Limited
+ *
+ * Phil Edworthy 
+ * Based on a driver originally written by Michel Pollet at Renesas.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+#define RZN1_FUNC_L2_MAX   RZN1_FUNC_MAC_MTIP_SWITCH
+#define RZN1_FUNC_MDIO_MAX RZN1_FUNC_MDIO1_E1_SWITCH
+
+/* Field positions and masks in the pinmux registers */
+#define RZN1_L1_PIN_DRIVE_STRENGTH 10
+#define RZN1_L1_PIN_DRIVE_STRENGTH_4MA 0
+#define RZN1_L1_PIN_DRIVE_STRENGTH_6MA 1
+#define RZN1_L1_PIN_DRIVE_STRENGTH_8MA 2
+#define RZN1_L1_PIN_DRIVE_STRENGTH_12MA3
+#define RZN1_L1_PIN_PULL   8
+#define RZN1_L1_PIN_PULL_NONE  0
+#define RZN1_L1_PIN_PULL_UP1
+#define RZN1_L1_PIN_PULL_DOWN  3
+#define RZN1_L1_FUNCTION   0
+#define RZN1_L1_FUNC_MASK  0xf
+#define RZN1_L1_FUNCTION_L20xf
+
+/*
+ * The hardware manual describes two levels of multiplexing, but it's more
+ * logical to think of the hardware as three levels, with level 3 consisting of
+ * the multiplexing for Ethernet MDIO signals.
+ *
+ * Level 1 functions go from 0 to 9, with level 1 function '15' (0xf) 
specifying
+ * that level 2 functions are used instead. Level 2 has a lot more options,
+ * going from 0 to 61. Level 3 allows selection of MDIO functions which can be
+ * floating, or one of seven internal peripherals. Unfortunately, there are two
+ * level 2 functions that can select MDIO, and t

[PATCH v6 1/3] dt-bindings: pinctrl: renesas,rzn1-pinctrl: documentation

2018-09-27 Thread Phil Edworthy
The Renesas RZ/N1 device family PINCTRL node description.

Based on a patch originally written by Michel Pollet at Renesas.

Signed-off-by: Phil Edworthy 
Reviewed-by: Jacopo Mondi 
---
v6:
 - Instead of combining the pin nr and func into a single element, use
   a pair of 8-bit elements.

v5:
 - 'Optional generic properties' => 'Optional generic pinconf properties'

v4:
 - Add alternative way to use the pinmux prop.
 - Remove mention of gpios.

v3:
 - Use standard bindings
 - Change the way the functions are defined so it is easy to check
   against the hardware numbering.
 - Add functions for the MDIO source peripheral instead of using
   virtual pins.

v2:
 - Change filename to generic rzn1, instead of device specific.
 - Add "renesas,rzn1-pinctrl" compatible fallback string.
 - Example register size corrected.
 - Typos fixed.
 - Changes suggested by Jacopo Mondi.
 - rzn1-pinctrl.h squashed into this as requested by Rob Herring.
---
 .../bindings/pinctrl/renesas,rzn1-pinctrl.txt | 155 ++
 include/dt-bindings/pinctrl/rzn1-pinctrl.h| 135 +++
 2 files changed, 290 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/renesas,rzn1-pinctrl.txt
 create mode 100644 include/dt-bindings/pinctrl/rzn1-pinctrl.h

diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzn1-pinctrl.txt 
b/Documentation/devicetree/bindings/pinctrl/renesas,rzn1-pinctrl.txt
new file mode 100644
index ..ca747b3b7455
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzn1-pinctrl.txt
@@ -0,0 +1,155 @@
+Renesas RZ/N1 SoC Pinctrl node description.
+
+Pin controller node
+---
+Required properties:
+- compatible: SoC-specific compatible string "renesas,-pinctrl"
+  followed by "renesas,rzn1-pinctrl" as fallback. The SoC-specific compatible
+  strings must be one of:
+   "renesas,r9a06g032-pinctrl" for RZ/N1D
+   "renesas,r9a06g033-pinctrl" for RZ/N1S
+- reg: Address base and length of the memory area where the pin controller
+  hardware is mapped to.
+- clocks: phandle for the clock, see the description of clock-names below.
+- clock-names: Contains the name of the clock:
+"bus", the bus clock, sometimes described as pclk, for register accesses.
+
+Example:
+   pinctrl: pin-controller@40067000 {
+   compatible = "renesas,r9a06g032-pinctrl", "renesas,rzn1-pinctrl";
+   reg = <0x40067000 0x1000>, <0x5100 0x480>;
+   clocks = <&sysctrl R9A06G032_HCLK_PINCONFIG>;
+   clock-names = "bus";
+   };
+
+Sub-nodes
+-
+
+The child nodes of the pin controller node describe a pin multiplexing
+function.
+
+- Pin multiplexing sub-nodes:
+  A pin multiplexing sub-node describes how to configure a set of
+  (or a single) pin in some desired alternate function mode.
+  A single sub-node may define several pin configurations.
+  Please refer to pinctrl-bindings.txt to get to know more on generic
+  pin properties usage.
+
+  The allowed generic formats for a pin multiplexing sub-node are the
+  following ones:
+
+  node-1 {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+  };
+
+  node-2 {
+  sub-node-1 {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+  };
+
+  sub-node-2 {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+  };
+
+  ...
+
+  sub-node-n {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+  };
+  };
+
+  node-3 {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+
+  sub-node-1 {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+  };
+
+  ...
+
+  sub-node-n {
+  pinmux = /bits/ 8 , , ... ;
+  GENERIC_PINCONFIG;
+  };
+  };
+
+  Use the latter two formats when pins part of the same logical group need to
+  have different generic pin configuration flags applied. Note that the generic
+  pinconfig in node-3 does not apply to the sub-nodes.
+
+  Client sub-nodes shall refer to pin multiplexing sub-nodes using the phandle
+  of the most external one.
+
+  Eg.
+
+  client-1 {
+  ...
+  pinctrl-0 = <&node-1>;
+  ...
+  };
+
+  client-2 {
+  ...
+  pinctrl-0 = <&node-2>;
+  ...
+  };
+
+  Required properties:
+- pinmux:
+  8-bit integer array consisting of PIN_NR pin number and MUX_FUNC pairs.
+  When a pin has to be configured in alternate function mode, use this
+  property to identify the pin by its global index, and provide its
+  alternate function configuration number.
+  When multiple pins are required to be configured as part of the same
+  alternate function they shall be specified as members of the same
+  argument list of a single "pinmux" property.
+  PIN_NR directly correspo

[PATCH v6 0/3] Renesas R9A06G032 PINCTRL Driver

2018-09-27 Thread Phil Edworthy
This implements the pinctrl driver for the RZ/N1 family of devices, including
the R9A06G032 (RZ/N1D) device.

This series was originally written by Michel Pollet whilst at Renesas, and I
have taken over this work.

Main changes:
v6:
 - Instead of combining the pin nr and func into a single element, use
   a pair of 8-bit elements.
 - Simplified how the MDIO function is calculated

v5:
 - Address Jacopo's further comments
 - Address Geert's comments

v4:
 - Address Jacopo's comments
 - Add alternative way to use the pinmux prop.
 - Remove mention of gpios.
 - Implement pin_config_group_get()
 - Fix function to get pin configs, i.e. return -EINVAL when disabled.

v3:
 - Use standard DT props instead of proprietary ones.
 - Replace virtual pins used for MDIO muxing with extra funcs.
 - Use pinctrl_utils funcs to handle the maps.
 - Remove the dbg functions to keep things simple.
 - Change the way the functions are defined so it is easy to check
   against the hardware numbering.

v2:
 - Change to generic rzn1 family driver, instead of device specific.
 - Review comments fixed.
 - Fix error handling during probe

Phil Edworthy (3):
  dt-bindings: pinctrl: renesas,rzn1-pinctrl: documentation
  pinctrl: renesas: Renesas RZ/N1 pinctrl driver
  ARM: dts: r9a06g032: Add pinctrl node

 .../bindings/pinctrl/renesas,rzn1-pinctrl.txt | 155 +++
 arch/arm/boot/dts/r9a06g032.dtsi  |   8 +
 drivers/pinctrl/Kconfig   |  10 +
 drivers/pinctrl/Makefile  |   1 +
 drivers/pinctrl/pinctrl-rzn1.c| 941 ++
 include/dt-bindings/pinctrl/rzn1-pinctrl.h| 135 +++
 6 files changed, 1250 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/renesas,rzn1-pinctrl.txt
 create mode 100644 drivers/pinctrl/pinctrl-rzn1.c
 create mode 100644 include/dt-bindings/pinctrl/rzn1-pinctrl.h

-- 
2.17.1



RE: [PATCH v4 2/3] pinctrl: renesas: Renesas RZ/N1 pinctrl driver

2018-09-24 Thread Phil Edworthy
Hi Geert,

On 24 September 2018 12:59 Geert Uytterhoeven wrote:
> On Wed, Sep 19, 2018 at 4:24 PM Phil Edworthy wrote:
> > This provides a pinctrl driver for the Renesas RZ/N1 device family.
> >
> > Based on a patch originally written by Michel Pollet at Renesas.
> >
> > Signed-off-by: Phil Edworthy 
> 
> Thanks for your patch!
> 
> > --- /dev/null
> > +++ b/drivers/pinctrl/pinctrl-rzn1.c
> 
> > +/*
> > + * Structure detailing the HW registers on the RZ/N1 devices.
> > + * Both the Level 1 mux registers and Level 2 mux registers have the
> > +same
> > + * structure. The only difference is that Level 2 has additional MDIO
> > +registers
> > + * at the end.
> > + */
> > +struct rzn1_pinctrl_regs {
> > +   union {
> > +   u32 conf[170];
> > +   u8  pad0[0x400];
> 
> This looks a bit confusing, and isn't really padding, as you use a union.
> What about getting rid of the union, and making it real padding?
> 
> u32 conf[170];
> u32 pad0[86];
> 
> > +   };
> > +   u32 status_protect; /* 0x400 */
> > +   /* MDIO mux registers, level2 only */
> > +   u32 l2_mdio[2];
> > +};
> 
> BTW, while using a struct instead of register offset definitions has its 
> merits,
> it also has its drawbacks, like the need for the "0x400" comment.
> You don't have to change it, though.
> 
> > +static const struct rzn1_pin_group *rzn1_pinctrl_find_group_by_name(
> > +   const struct rzn1_pinctrl *ipctl, const char *name) {
> > +   const struct rzn1_pin_group *grp = NULL;
> > +   int i;
> 
> unsigned int i;
> (rzn1_pinctrl.ngroups is unsigned int)
> 
> > +
> > +   for (i = 0; i < ipctl->ngroups; i++) {
> > +   if (!strcmp(ipctl->groups[i].name, name)) {
> > +   grp = &ipctl->groups[i];
> > +   break;
> > +   }
> > +   }
> > +
> > +   return grp;
> > +}
> 
> > +static int rzn1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
> > +   unsigned long *configs, unsigned int
> > +num_configs) {
> > +   struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
> > +   enum pin_config_param param;
> > +   int i;
> 
> unsigned int i;
> 
> > +   u32 arg;
> > +   u32 l1, l1_cache;
> > +   u32 drv;
> > +
> > +   if (pin >= ARRAY_SIZE(ipctl->lev1->conf))
> > +   return -EINVAL;
> > +
> > +   l1 = readl(&ipctl->lev1->conf[pin]);
> > +   l1_cache = l1;
> > +
> > +   for (i = 0; i < num_configs; i++) {
> 
> > +static int rzn1_pinconf_group_get(struct pinctrl_dev *pctldev,
> > + unsigned int selector,
> > + unsigned long *config) {
> > +   struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
> > +   struct rzn1_pin_group *grp = &ipctl->groups[selector];
> > +   unsigned long old = 0;
> > +   int i;
> 
> unsigned int i;
> 
> > +
> > +   dev_dbg(ipctl->dev, "group get %s selector:%d\n", grp->name,
> > + selector);
> 
> %u to format unsigned int.
> 
> > +
> > +   for (i = 0; i < grp->npins; i++) {
> 
> > +static int rzn1_pinconf_group_set(struct pinctrl_dev *pctldev,
> > + unsigned int selector,
> > + unsigned long *configs,
> > + unsigned int num_configs) {
> > +   struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
> > +   struct rzn1_pin_group *grp = &ipctl->groups[selector];
> > +   int ret, i;
> 
> unsigned int i;
> 
> > +
> > +   dev_dbg(ipctl->dev, "group set %s selector:%d
> > + configs:%p/%d\n",
> 
> %u
> 
> > +   grp->name, selector, configs, num_configs);
> > +
> > +   for (i = 0; i < grp->npins; i++) {
> > +   unsigned int pin = grp->pins[i];
> > +
> > +   ret = rzn1_pinconf_set(pctldev, pin, configs, num_configs);
> > +   if (ret)
> > +   return ret;
> > +   }
> > +
> > +   return 0;
> > +}
> 
> 
> > +static int rzn1_pinctrl_parse_functions(struct device_node *np,
> > +   struct r

RE: [PATCH v5 1/2] clk: Add of_clk_get_by_name_optional() function

2018-09-03 Thread Phil Edworthy
Hi Stephen,

On 03 September 2018 10:33 Phil Edworthy wrote:
> On 01 September 2018 03:46, Stephen Boyd wrote:
> > Quoting Phil Edworthy (2018-08-31 07:07:22)
> > > diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index
> > > 9ab3db8..4adb99e 100644
> > > --- a/drivers/clk/clkdev.c
> > > +++ b/drivers/clk/clkdev.c
> > > @@ -54,30 +54,29 @@ EXPORT_SYMBOL(of_clk_get);
> > >
> > >  static struct clk *__of_clk_get_by_name(struct device_node *np,
> > > const char *dev_id,
> > > -   const char *name)
> > > +   const char *name,
> > > +   bool optional)
> > >  {
> > > struct clk *clk = ERR_PTR(-ENOENT);
> > > +   struct device_node *child = np;
> > > +   int index = 0;
> > >
> > > /* Walk up the tree of devices looking for a clock that matches */
> > > while (np) {
> > > -   int index = 0;
> > >
> > > /*
> > >  * For named clocks, first look up the name in the
> > >  * "clock-names" property.  If it cannot be found, then
> > > -* index will be an error code, and of_clk_get() will 
> > > fail.
> > > +* index will be an error code.
> > >  */
> > > if (name)
> > > index = of_property_match_string(np, 
> > > "clock-names",
> name);
> > > -   clk = __of_clk_get(np, index, dev_id, name);
> > > -   if (!IS_ERR(clk)) {
> > > -   break;
> > > -   } else if (name && index >= 0) {
> > > -   if (PTR_ERR(clk) != -EPROBE_DEFER)
> > > -   pr_err("ERROR: could not get clock 
> > > %pOF:%s(%i)\n",
> > > -   np, name ? name : "", index);
> > > +   if (index >= 0)
> > > +   clk = __of_clk_get(np, index, dev_id, name);
> > > +   if (!IS_ERR(clk))
> >
> > Was this change necessary? It looks like we can leave it all alone and keep
> > passing a negative number to __of_clk_get() and have that return an error
> > pointer which we then return immediately as an error. But, if the clock is
> > optional and we've passed a name here, shouldn't we treat an error from
> > of_property_match_string() as success too? This is all looking pretty 
> > fragile
> so
> > maybe it can be better commented and also more explicit instead of relying
> > on the reader to jump through all the function calls to figure out what the
> > return value is in some cases.
> If we call __of_clk_get, with index < 0, we will not be able to differentiate
> between clock provider not present and other errors with the passed data,
> as it will just return -EINVAL.
> 
> of_property_match_string() will return -EINVAL if the "clock-names"
> property
> is missing, or -ENODATA if the specified clock name in the "clock-names"
> property is missing. That is why I have changed the code to conditionally
> call __of_clk_get, so the code will correctly treat optional clocks that are 
> not
> present.
When getting named optional clocks, if the node has a "clock-names" property,
but no clock matching the name we want, I think the function should stop there
and *not* walk up the tree of devices looking for a matching clock. In this 
case,
the code determines that the optional clock is not present.

If there isn’t a "clock-names" property in the current node, the function should
walk up the tree of devices looking for a matching optional clock. If there are 
no
parent nodes left and we haven't found a matching optional clock, we determine
that the clock isn’t there.

Is that how this should work?

Thanks
Phil


> > > return clk;
> > > -   }
> > > +   if (name && index >= 0)
> > > +   break;
> >
> > And this causes us to duplicate logic down below because we have to check
> it
> > again if it's not optional or some other error condition?
> Yes, the error handling is messy, though I have tried to make this simple.
> I'll have a think about some other way to make this cleaner.
> 
> 
> > >
> > > /*
> > &g

RE: [PATCH v5 1/2] clk: Add of_clk_get_by_name_optional() function

2018-09-03 Thread Phil Edworthy
Hi Stephen,

On 01 September 2018 03:46, Stephen Boyd wrote:
> Quoting Phil Edworthy (2018-08-31 07:07:22)
> > diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index
> > 9ab3db8..4adb99e 100644
> > --- a/drivers/clk/clkdev.c
> > +++ b/drivers/clk/clkdev.c
> > @@ -54,30 +54,29 @@ EXPORT_SYMBOL(of_clk_get);
> >
> >  static struct clk *__of_clk_get_by_name(struct device_node *np,
> > const char *dev_id,
> > -   const char *name)
> > +   const char *name,
> > +   bool optional)
> >  {
> > struct clk *clk = ERR_PTR(-ENOENT);
> > +   struct device_node *child = np;
> > +   int index = 0;
> >
> > /* Walk up the tree of devices looking for a clock that matches */
> > while (np) {
> > -   int index = 0;
> >
> > /*
> >  * For named clocks, first look up the name in the
> >  * "clock-names" property.  If it cannot be found, then
> > -* index will be an error code, and of_clk_get() will fail.
> > +* index will be an error code.
> >  */
> > if (name)
> > index = of_property_match_string(np, "clock-names", 
> > name);
> > -   clk = __of_clk_get(np, index, dev_id, name);
> > -   if (!IS_ERR(clk)) {
> > -   break;
> > -   } else if (name && index >= 0) {
> > -   if (PTR_ERR(clk) != -EPROBE_DEFER)
> > -   pr_err("ERROR: could not get clock 
> > %pOF:%s(%i)\n",
> > -   np, name ? name : "", index);
> > +   if (index >= 0)
> > +   clk = __of_clk_get(np, index, dev_id, name);
> > +   if (!IS_ERR(clk))
> 
> Was this change necessary? It looks like we can leave it all alone and keep
> passing a negative number to __of_clk_get() and have that return an error
> pointer which we then return immediately as an error. But, if the clock is
> optional and we've passed a name here, shouldn't we treat an error from
> of_property_match_string() as success too? This is all looking pretty fragile 
> so
> maybe it can be better commented and also more explicit instead of relying
> on the reader to jump through all the function calls to figure out what the
> return value is in some cases.
If we call __of_clk_get, with index < 0, we will not be able to differentiate
between clock provider not present and other errors with the passed data,
as it will just return -EINVAL.

of_property_match_string() will return -EINVAL if the "clock-names" property
is missing, or -ENODATA if the specified clock name in the "clock-names"
property is missing. That is why I have changed the code to conditionally
call __of_clk_get, so the code will correctly treat optional clocks that are not
present.


> > return clk;
> > -   }
> > +   if (name && index >= 0)
> > +   break;
> 
> And this causes us to duplicate logic down below because we have to check it
> again if it's not optional or some other error condition?
Yes, the error handling is messy, though I have tried to make this simple.
I'll have a think about some other way to make this cleaner.


> >
> > /*
> >  * No matching clock found on this node.  If the
> > parent node @@ -89,6 +88,16 @@ static struct clk
> *__of_clk_get_by_name(struct device_node *np,
> > break;
> > }
> >
> > +   /* The clock is not valid, but it could be optional or deferred */
> > +   if (optional && PTR_ERR(clk) == -ENOENT) {
> > +   clk = NULL;
> > +   pr_info("no optional clock %pOF:%s\n", child,
> > +   name ? name : "");
> 
> Is this intentionally pr_info?
Yes, it's not an error if an optional clock isn’t there.
Would pr_debug be more appropriate?


> > +   } else if (name && index >= 0 && PTR_ERR(clk) != -EPROBE_DEFER) {
> > +   pr_err("ERROR: could not get clock %pOF:%s(%i)\n",
> > +   child, name, index);
> > +   }
> > +
> > return clk;
> >  }
> >

Thanks
Phil


[PATCH v5 2/2] clk: Add functions to get optional clocks

2018-08-31 Thread Phil Edworthy
Behaves the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
---
v5:
 - No changes.
v4:
 - No changes.
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 18 --
 drivers/clk/clkdev.c | 17 +++--
 include/linux/clk.h  | 29 +
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..a2bb01a 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -14,7 +14,7 @@ static void devm_clk_release(struct device *dev, void *res)
clk_put(*(struct clk **)res);
 }
 
-struct clk *devm_clk_get(struct device *dev, const char *id)
+static struct clk *__devm_clk_get(struct device *dev, const char *id, bool 
optional)
 {
struct clk **ptr, *clk;
 
@@ -22,7 +22,10 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
if (!ptr)
return ERR_PTR(-ENOMEM);
 
-   clk = clk_get(dev, id);
+   if (!optional)
+   clk = clk_get(dev, id);
+   else
+   clk = clk_get_optional(dev, id);
if (!IS_ERR(clk)) {
*ptr = clk;
devres_add(dev, ptr);
@@ -32,8 +35,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 
return clk;
 }
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, false);
+}
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, true);
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 4adb99e..6355573 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -222,21 +222,34 @@ struct clk *clk_get_sys(const char *dev_id, const char 
*con_id)
 }
 EXPORT_SYMBOL(clk_get_sys);
 
-struct clk *clk_get(struct device *dev, const char *con_id)
+static struct clk *internal_clk_get(struct device *dev, const char *con_id,
+   bool optional)
 {
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id,
+  optional);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
 
return clk_get_sys(dev_id, con_id);
 }
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, false);
+}
 EXPORT_SYMBOL(clk_get);
 
+struct clk *clk_get_optional(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, true);
+}
+EXPORT_SYMBOL(clk_get_optional);
+
 void clk_put(struct clk *clk)
 {
__clk_put(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index de0e5e0..58ec7bc 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -291,6 +291,16 @@ static inline void clk_bulk_unprepare(int num_clks, struct 
clk_bulk_data *clks)
 struct clk *clk_get(struct device *dev, const char *id);
 
 /**
+ * clk_get_optional - lookup and obtain a reference to optional clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get except where there is no clock producer. In this
+ * case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *clk_get_optional(struct device *dev, const char *id);
+
+/**
  * clk_bulk_get - lookup and obtain a number of references to clock producer.
  * @dev: device for clock "consumer"
  * @num_clks: the number of clk_bulk_data
@@ -349,6 +359,14 @@ int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
 /**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
+/**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
  * @dev: device for clock "consumer"
@@ -636,6 +654,11 @@ static inline struct clk *clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *clk_

[PATCH v5 1/2] clk: Add of_clk_get_by_name_optional() function

2018-08-31 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a clock required
to access peripheral's registers that is always enabled on some
devices.

This function behaves the same as of_clk_get_by_name() except that
it will return NULL instead of -ENOENT.

Signed-off-by: Phil Edworthy 
---
v5:
 - Simplified the code by handling all the error conditions on exit
v4:
 - For optional named clocks of_property_match_string() will return
   -EINVAL if the "clock-names" property is missing, or -ENODATA if
   the specified clock name in the "clock-names" property is missing.
   If we then call __of_clk_get() with these errors as the index, we
   get clk = -EINVAL. This is then filtered later on so users don't
   see it. However, if the clock is not named, __of_clk_get() will
   return -ENOENT is the clock provide is not there.
   So for optional named clocks, use index to determine if the clock
   provider is there or not, and for unnamed clocks, simply check if
   __of_clk_get() returns -ENOENT.

v3:
 - Fix check for clock not present. __of_clk_get() returns -EINVAL
   if it's not there. Cover case of when there is no clock name.
 - of_clk_get_by_name_optional() should return NULL if !np.
 - Add dummy version of of_clk_get_by_name_optional() for the
   !OF || !COMMON_CLK case.
---
 drivers/clk/clkdev.c | 59 +++-
 include/linux/clk.h  |  6 ++
 2 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8..4adb99e 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -54,30 +54,29 @@ EXPORT_SYMBOL(of_clk_get);
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
struct clk *clk = ERR_PTR(-ENOENT);
+   struct device_node *child = np;
+   int index = 0;
 
/* Walk up the tree of devices looking for a clock that matches */
while (np) {
-   int index = 0;
 
/*
 * For named clocks, first look up the name in the
 * "clock-names" property.  If it cannot be found, then
-* index will be an error code, and of_clk_get() will fail.
+* index will be an error code.
 */
if (name)
index = of_property_match_string(np, "clock-names", 
name);
-   clk = __of_clk_get(np, index, dev_id, name);
-   if (!IS_ERR(clk)) {
-   break;
-   } else if (name && index >= 0) {
-   if (PTR_ERR(clk) != -EPROBE_DEFER)
-   pr_err("ERROR: could not get clock 
%pOF:%s(%i)\n",
-   np, name ? name : "", index);
+   if (index >= 0)
+   clk = __of_clk_get(np, index, dev_id, name);
+   if (!IS_ERR(clk))
return clk;
-   }
+   if (name && index >= 0)
+   break;
 
/*
 * No matching clock found on this node.  If the parent node
@@ -89,6 +88,16 @@ static struct clk *__of_clk_get_by_name(struct device_node 
*np,
break;
}
 
+   /* The clock is not valid, but it could be optional or deferred */
+   if (optional && PTR_ERR(clk) == -ENOENT) {
+   clk = NULL;
+   pr_info("no optional clock %pOF:%s\n", child,
+   name ? name : "");
+   } else if (name && index >= 0 && PTR_ERR(clk) != -EPROBE_DEFER) {
+   pr_err("ERROR: could not get clock %pOF:%s(%i)\n",
+   child, name, index);
+   }
+
return clk;
 }
 
@@ -106,15 +115,37 @@ struct clk *of_clk_get_by_name(struct device_node *np, 
const char *name)
if (!np)
return ERR_PTR(-ENOENT);
 
-   return __of_clk_get_by_name(np, np->full_name, name);
+   return __of_clk_get_by_name(np, np->full_name, name, false);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 
+/**
+ * of_clk_get_by_name_optional() - Parse and lookup an optional clock 
referenced
+ * by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties, and uses them to
+ * look up the struct clk from the registered list of clock providers.
+ * It behaves the same as of_clk_get_by_name(), except when np is NULL or no
+ * clock provider is found, when it then returns NULL.
+ */
+struct clk *of_clk_

[PATCH v5 0/2] clk: Add functions to get optional clocks

2018-08-31 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a bus clock required to 
access peripheral's registers that is always enabled on some devices.

Phil Edworthy (2):
  clk: Add of_clk_get_by_name_optional() function
  clk: Add functions to get optional clocks

 drivers/clk/clk-devres.c | 18 ++--
 drivers/clk/clkdev.c | 74 ++--
 include/linux/clk.h  | 35 +++
 3 files changed, 110 insertions(+), 17 deletions(-)

-- 
2.7.4



RE: [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function

2018-08-30 Thread Phil Edworthy
Hi Andy,

On 29 August 2018 18:11 Andy Shevchenko wrote:
> On Tue, Jul 31, 2018 at 01:10:59PM +0100, Phil Edworthy wrote:
> > Quite a few drivers get an optional clock, e.g. a clock required
> > to access peripheral's registers that is always enabled on some
> > devices.
> >
> > This function behaves the same as of_clk_get_by_name() except that
> > it will return NULL instead of -ENOENT.
> 
> > +   if (optional && (index == -EINVAL || index == -ENODATA ||
> > +   PTR_ERR(clk) == -ENOENT)) {
> 
> A nit: I would rather rearrange this to be
> 
> if (optional &&
> (... || ... || ...)) {
> 
> (disregard 80 characters limit for second line)

Thanks for the review. I'm not particularly happy with the patch as is, it's
pretty messy. I was in rush trying to get things done before holidays - always
a mistake.
Would you mind if I sent a v5 that I feel is somewhat clearer?

Thanks
Phil


[PATCH v4 2/2] clk: Add functions to get optional clocks

2018-07-31 Thread Phil Edworthy
Behaves the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
---
v4:
 - No changes.
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 18 --
 drivers/clk/clkdev.c | 17 +++--
 include/linux/clk.h  | 29 +
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..a2bb01a 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -14,7 +14,7 @@ static void devm_clk_release(struct device *dev, void *res)
clk_put(*(struct clk **)res);
 }
 
-struct clk *devm_clk_get(struct device *dev, const char *id)
+static struct clk *__devm_clk_get(struct device *dev, const char *id, bool 
optional)
 {
struct clk **ptr, *clk;
 
@@ -22,7 +22,10 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
if (!ptr)
return ERR_PTR(-ENOMEM);
 
-   clk = clk_get(dev, id);
+   if (!optional)
+   clk = clk_get(dev, id);
+   else
+   clk = clk_get_optional(dev, id);
if (!IS_ERR(clk)) {
*ptr = clk;
devres_add(dev, ptr);
@@ -32,8 +35,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 
return clk;
 }
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, false);
+}
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, true);
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index f8f6ba9..0ad6c31 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -226,21 +226,34 @@ struct clk *clk_get_sys(const char *dev_id, const char 
*con_id)
 }
 EXPORT_SYMBOL(clk_get_sys);
 
-struct clk *clk_get(struct device *dev, const char *con_id)
+static struct clk *internal_clk_get(struct device *dev, const char *con_id,
+   bool optional)
 {
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id,
+  optional);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
 
return clk_get_sys(dev_id, con_id);
 }
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, false);
+}
 EXPORT_SYMBOL(clk_get);
 
+struct clk *clk_get_optional(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, true);
+}
+EXPORT_SYMBOL(clk_get_optional);
+
 void clk_put(struct clk *clk)
 {
__clk_put(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index de0e5e0..58ec7bc 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -291,6 +291,16 @@ static inline void clk_bulk_unprepare(int num_clks, struct 
clk_bulk_data *clks)
 struct clk *clk_get(struct device *dev, const char *id);
 
 /**
+ * clk_get_optional - lookup and obtain a reference to optional clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get except where there is no clock producer. In this
+ * case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *clk_get_optional(struct device *dev, const char *id);
+
+/**
  * clk_bulk_get - lookup and obtain a number of references to clock producer.
  * @dev: device for clock "consumer"
  * @num_clks: the number of clk_bulk_data
@@ -349,6 +359,14 @@ int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
 /**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
+/**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
  * @dev: device for clock "consumer"
@@ -636,6 +654,11 @@ static inline struct clk *clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *clk_get_optional(struct devi

[PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function

2018-07-31 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a clock required
to access peripheral's registers that is always enabled on some
devices.

This function behaves the same as of_clk_get_by_name() except that
it will return NULL instead of -ENOENT.

Signed-off-by: Phil Edworthy 
---
v4:
 - For optional named clocks of_property_match_string() will return
   -EINVAL if the "clock-names" property is missing, or -ENODATA if
   the specified clock name in the "clock-names" property is missing.
   If we then call __of_clk_get() with these errors as the index, we
   get clk = -EINVAL. This is then filtered later on so users don't
   see it. However, if the clock is not named, __of_clk_get() will
   return -ENOENT is the clock provide is not there.
   So for optional named clocks, use index to determine if the clock
   provider is there or not, and for unnamed clocks, simply check if
   __of_clk_get() returns -ENOENT.

v3:
 - Fix check for clock not present. __of_clk_get() returns -EINVAL
   if it's not there. Cover case of when there is no clock name.
 - of_clk_get_by_name_optional() should return NULL if !np.
 - Add dummy version of of_clk_get_by_name_optional() for the
   !OF || !COMMON_CLK case.
---
 drivers/clk/clkdev.c | 43 +++
 include/linux/clk.h  |  6 ++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8..f8f6ba9 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(of_clk_get);
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -70,6 +71,12 @@ static struct clk *__of_clk_get_by_name(struct device_node 
*np,
if (name)
index = of_property_match_string(np, "clock-names", 
name);
clk = __of_clk_get(np, index, dev_id, name);
+   if (optional && (index == -EINVAL || index == -ENODATA ||
+   PTR_ERR(clk) == -ENOENT)) {
+   clk = NULL;
+   pr_info("optional clock is not present %pOF:%s\n", np,
+   name ? name : "");
+   }
if (!IS_ERR(clk)) {
break;
} else if (name && index >= 0) {
@@ -89,6 +96,12 @@ static struct clk *__of_clk_get_by_name(struct device_node 
*np,
break;
}
 
+   if (optional && PTR_ERR(clk) == -ENOENT) {
+   clk = NULL;
+   pr_info("optional clock is not present %pOF:%s\n", np,
+   name ? name : "");
+   }
+
return clk;
 }
 
@@ -106,15 +119,37 @@ struct clk *of_clk_get_by_name(struct device_node *np, 
const char *name)
if (!np)
return ERR_PTR(-ENOENT);
 
-   return __of_clk_get_by_name(np, np->full_name, name);
+   return __of_clk_get_by_name(np, np->full_name, name, false);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 
+/**
+ * of_clk_get_by_name_optional() - Parse and lookup an optional clock 
referenced
+ * by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties, and uses them to
+ * look up the struct clk from the registered list of clock providers.
+ * It behaves the same as of_clk_get_by_name(), except when np is NULL or no
+ * clock provider is found, when it then returns NULL.
+ */
+struct clk *of_clk_get_by_name_optional(struct device_node *np,
+   const char *name)
+{
+   if (!np)
+   return NULL;
+
+   return __of_clk_get_by_name(np, np->full_name, name, true);
+}
+EXPORT_SYMBOL(of_clk_get_by_name_optional);
+
 #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
return ERR_PTR(-ENOENT);
 }
@@ -197,7 +232,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)

[PATCH v4 0/2] clk: Add functions to get optional clocks

2018-07-31 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a bus clock required to 
access peripheral's registers that is always enabled on some devices.

Phil Edworthy (2):
  clk: Add of_clk_get_by_name_optional() function
  clk: Add functions to get optional clocks

 drivers/clk/clk-devres.c | 18 +--
 drivers/clk/clkdev.c | 58 +++-
 include/linux/clk.h  | 35 +
 3 files changed, 104 insertions(+), 7 deletions(-)

-- 
2.7.4



RE: [PATCH v3 1/2] clk: Add of_clk_get_by_name_optional() function

2018-07-30 Thread Phil Edworthy
Hi Andy,

On 30 July 2018 17:04, Andy Shevchenko wrote:
> On Mon, 2018-07-30 at 14:31 +0100, Phil Edworthy wrote:
> > Quite a few drivers get an optional clock, e.g. a clock required to
> > access peripheral's registers that is always enabled on some devices.
> >
> > This function behaves the same as of_clk_get_by_name() except that it
> > will return NULL instead of -EINVAL.
> 
> I'm puzzled a bit.
> 
> __of_clk_get() may return few error codes, and to me ENOENT sounds
> correct when clock is not found. Other error codes should be passed to the
> caller even for optional clocks.
> 
> If above is not true, we need to understand what circumstances for each
> possible returned code are, and fix / act accordingly.
>
> P.S. Possible way like regulator framework does is to return -ENODEV.
> 
> So, basically what I'm asking here is to be sure that single error code (for 
> now
> supposed -EINVAL) in this case is _the_ error code for absent / can't be
> found clock.
of_property_match_string() can return different return values for when:
 the "clock-names" property is missing (-EINVAL),
 the specified clock name in the "clock-names" property is missing  (-ENODATA),
 or internal errors, (e.g. -EILSEQ).
However, if you then call __of_clk_get() with the failed index, you just get
the -EINVAL error.

Looking at it further, __of_clk_get() should return -ENOENT if passed a valid
index (e.g. 0 when name=NULL) and the clock is not there. However, I think
it will take a while to check all possible return values as it's not immediately
clear what they are (to me).

I think the best thing is to test the return value of of_property_match_string()
for -ENODATA, and deal with it then. Then deal with the case of name=NULL
separately.

Thanks
Phil

 >  - Fix check for clock not present. __of_clk_get() returns -EINVAL
> >if it's not there. Cover case of when there is no clock name.
> 
> --
> Andy Shevchenko 
> Intel Finland Oy


[PATCH v3 2/2] clk: Add functions to get optional clocks

2018-07-30 Thread Phil Edworthy
Behaves the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
---
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 18 --
 drivers/clk/clkdev.c | 17 +++--
 include/linux/clk.h  | 29 +
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..a2bb01a 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -14,7 +14,7 @@ static void devm_clk_release(struct device *dev, void *res)
clk_put(*(struct clk **)res);
 }
 
-struct clk *devm_clk_get(struct device *dev, const char *id)
+static struct clk *__devm_clk_get(struct device *dev, const char *id, bool 
optional)
 {
struct clk **ptr, *clk;
 
@@ -22,7 +22,10 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
if (!ptr)
return ERR_PTR(-ENOMEM);
 
-   clk = clk_get(dev, id);
+   if (!optional)
+   clk = clk_get(dev, id);
+   else
+   clk = clk_get_optional(dev, id);
if (!IS_ERR(clk)) {
*ptr = clk;
devres_add(dev, ptr);
@@ -32,8 +35,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 
return clk;
 }
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, false);
+}
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, true);
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index a710333..2245ba6 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -219,21 +219,34 @@ struct clk *clk_get_sys(const char *dev_id, const char 
*con_id)
 }
 EXPORT_SYMBOL(clk_get_sys);
 
-struct clk *clk_get(struct device *dev, const char *con_id)
+static struct clk *internal_clk_get(struct device *dev, const char *con_id,
+   bool optional)
 {
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id,
+  optional);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
 
return clk_get_sys(dev_id, con_id);
 }
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, false);
+}
 EXPORT_SYMBOL(clk_get);
 
+struct clk *clk_get_optional(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, true);
+}
+EXPORT_SYMBOL(clk_get_optional);
+
 void clk_put(struct clk *clk)
 {
__clk_put(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index de0e5e0..58ec7bc 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -291,6 +291,16 @@ static inline void clk_bulk_unprepare(int num_clks, struct 
clk_bulk_data *clks)
 struct clk *clk_get(struct device *dev, const char *id);
 
 /**
+ * clk_get_optional - lookup and obtain a reference to optional clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get except where there is no clock producer. In this
+ * case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *clk_get_optional(struct device *dev, const char *id);
+
+/**
  * clk_bulk_get - lookup and obtain a number of references to clock producer.
  * @dev: device for clock "consumer"
  * @num_clks: the number of clk_bulk_data
@@ -349,6 +359,14 @@ int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
 /**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
+/**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
  * @dev: device for clock "consumer"
@@ -636,6 +654,11 @@ static inline struct clk *clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *clk_get_optional(struct device *dev, const

[PATCH v3 0/2] clk: Add functions to get optional clocks

2018-07-30 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a bus clock required to 
access peripheral's registers that is always enabled on some devices.

Phil Edworthy (2):
  clk: Add of_clk_get_by_name_optional() function
  clk: Add functions to get optional clocks

 drivers/clk/clk-devres.c | 18 +++--
 drivers/clk/clkdev.c | 51 +++-
 include/linux/clk.h  | 35 +
 3 files changed, 97 insertions(+), 7 deletions(-)

-- 
2.7.4



[PATCH v3 1/2] clk: Add of_clk_get_by_name_optional() function

2018-07-30 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a clock required
to access peripheral's registers that is always enabled on some
devices.

This function behaves the same as of_clk_get_by_name() except that
it will return NULL instead of -EINVAL.

Signed-off-by: Phil Edworthy 
---
v3:
 - Fix check for clock not present. __of_clk_get() returns -EINVAL
   if it's not there. Cover case of when there is no clock name.
 - of_clk_get_by_name_optional() should return NULL if !np.
 - Add dummy version of of_clk_get_by_name_optional() for the
   !OF || !COMMON_CLK case.
---
 drivers/clk/clkdev.c | 36 
 include/linux/clk.h  |  6 ++
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8..a710333 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(of_clk_get);
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -70,6 +71,11 @@ static struct clk *__of_clk_get_by_name(struct device_node 
*np,
if (name)
index = of_property_match_string(np, "clock-names", 
name);
clk = __of_clk_get(np, index, dev_id, name);
+   if (optional && PTR_ERR(clk) == -EINVAL) {
+   clk = NULL;
+   pr_info("optional clock is not present %pOF:%s\n", np,
+   name ? name : "");
+   }
if (!IS_ERR(clk)) {
break;
} else if (name && index >= 0) {
@@ -106,15 +112,37 @@ struct clk *of_clk_get_by_name(struct device_node *np, 
const char *name)
if (!np)
return ERR_PTR(-ENOENT);
 
-   return __of_clk_get_by_name(np, np->full_name, name);
+   return __of_clk_get_by_name(np, np->full_name, name, false);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 
+/**
+ * of_clk_get_by_name_optional() - Parse and lookup an optional clock 
referenced
+ * by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties, and uses them to
+ * look up the struct clk from the registered list of clock providers.
+ * It behaves the same as of_clk_get_by_name(), except when np is NULL or no
+ * clock provider is found, when it then returns NULL.
+ */
+struct clk *of_clk_get_by_name_optional(struct device_node *np,
+   const char *name)
+{
+   if (!np)
+   return NULL;
+
+   return __of_clk_get_by_name(np, np->full_name, name, true);
+}
+EXPORT_SYMBOL(of_clk_get_by_name_optional);
+
 #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
return ERR_PTR(-ENOENT);
 }
@@ -197,7 +225,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4f750c4..de0e5e0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -777,6 +777,7 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
+struct clk *of_clk_get_by_name_optional(struct device_node *np, const char 
*name);
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
 #else
 static inline struct clk *of_clk_get(struct device_node *np, int index)
@@ -788,6 +789,11 @@ static inline struct clk *of_clk_get_by_name(struct 
device_node *np,
 {
return ERR_PTR(-ENOENT);
 }
+static inline struct clk *of_clk_get_by_name_optional(struct device_node *np,
+ const char *name)
+{
+   return NULL;
+}
 static inline struct clk *of_clk_get_from_provider(struct of_phandle_args 
*clkspec)
 {
return ERR_PTR(-ENOENT);
-- 
2.7.4



RE: [PATCH v2 1/2] clk: Add of_clk_get_by_name_optional() function

2018-07-30 Thread Phil Edworthy
Hi Geert,

On 30 July 2018 09:56, Geert Uytterhoeven wrote:
> On Mon, Jul 30, 2018 at 10:36 AM Phil Edworthy wrote:
> > Quite a few drivers get an optional clock, e.g. a clock required to
> > access peripheral's registers that is always enabled on some devices.
> >
> > This function behaves the same as of_clk_get_by_name() except that it
> > will return NULL instead of -ENOENT. This makes error checking for
> > users easier and allows clk_prepare_enable, etc to be called on the
> > returned reference without additional checks.
> >
> > Signed-off-by: Phil Edworthy 
> 
> Thanks for your patch!
> 
> > --- a/drivers/clk/clkdev.c
> > +++ b/drivers/clk/clkdev.c
> > @@ -54,7 +54,8 @@ EXPORT_SYMBOL(of_clk_get);
> >
> >  static struct clk *__of_clk_get_by_name(struct device_node *np,
> > const char *dev_id,
> > -   const char *name)
> > +   const char *name,
> > +   bool optional)
> >  {
> > struct clk *clk = ERR_PTR(-ENOENT);
> >
> > @@ -73,6 +74,8 @@ static struct clk *__of_clk_get_by_name(struct
> device_node *np,
> > if (!IS_ERR(clk)) {
> > break;
> > } else if (name && index >= 0) {
> > +   if (optional && PTR_ERR(clk) == -ENOENT)
> > +   clk = NULL;
> 
> This only handles the "name && index >= 0" case.
> If that condition is never true, the loop will end, eventually, and the last 
> value
> of clk will be returned. Hence there should be a similar check at the end of
> the function.
Oops, I was only considering named optional clocks, I'll fix this.

> > if (PTR_ERR(clk) != -EPROBE_DEFER)
> > pr_err("ERROR: could not get clock 
> > %pOF:%s(%i)\n",
> > np, name ? name : "", index);
> 
> Hence if not found, this will always print an error, even if the clock is
> optional?
Right.

> > @@ -106,15 +109,38 @@ struct clk *of_clk_get_by_name(struct
> device_node *np, const char *name)
> > if (!np)
> > return ERR_PTR(-ENOENT);
> >
> > -   return __of_clk_get_by_name(np, np->full_name, name);
> > +   return __of_clk_get_by_name(np, np->full_name, name, false);
> >  }
> >  EXPORT_SYMBOL(of_clk_get_by_name);
> >
> > +/**
> > + * of_clk_get_by_name_optional() - Parse and lookup an optional clock
> > +referenced
> > + * by a device node
> > + * @np: pointer to clock consumer node
> > + * @name: name of consumer's clock input, or NULL for the first clock
> > +reference
> > + *
> > + * This function parses the clocks and clock-names properties,
> > + * and uses them to look up the struct clk from the registered list
> > +of clock
> > + * providers.
> > + * It behaves the same as of_clk_get_by_name(), except when no clock is
> found.
> > + * In this case, instead of returning -ENOENT, it returns NULL.
> > + */
> > +struct clk *of_clk_get_by_name_optional(struct device_node *np,
> > +   const char *name) {
> > +   if (!np)
> > +   return ERR_PTR(-ENOENT);
> 
> Shouldn't this return NULL?
I wasn’t sure on this, I thought the node should be valid, but I guess the node
is also optional. I'll fix.

> Or let __of_clk_get_by_name() handle that (cfr. above)?

> Hmm, of_clk_get_by_name() has a similar check, while the current
> __of_clk_get_by_name() already handle np == NULL, too.
Yes I see, I'll clean that up.

 
> > +
> > +   return __of_clk_get_by_name(np, np->full_name, name, true); }
> > +EXPORT_SYMBOL(of_clk_get_by_name_optional);
> > +
> >  #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
> >
> >  static struct clk *__of_clk_get_by_name(struct device_node *np,
> > const char *dev_id,
> > -   const char *name)
> > +   const char *name,
> > +   bool optional)
> >  {
> > return ERR_PTR(-ENOENT);
> >  }
> > @@ -197,7 +223,7 @@ struct clk *clk_get(struct device *dev, const char
> *con_id)
> > struct clk *clk;
> >
> > if (dev && dev->of_node) {
> > -  

[PATCH v2 1/2] clk: Add of_clk_get_by_name_optional() function

2018-07-30 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a clock required
to access peripheral's registers that is always enabled on some
devices.

This function behaves the same as of_clk_get_by_name() except that
it will return NULL instead of -ENOENT. This makes error checking
for users easier and allows clk_prepare_enable, etc to be called
on the returned reference without additional checks.

Signed-off-by: Phil Edworthy 
---
 drivers/clk/clkdev.c | 34 ++
 include/linux/clk.h  |  1 +
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8..c1b7262 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(of_clk_get);
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -73,6 +74,8 @@ static struct clk *__of_clk_get_by_name(struct device_node 
*np,
if (!IS_ERR(clk)) {
break;
} else if (name && index >= 0) {
+   if (optional && PTR_ERR(clk) == -ENOENT)
+   clk = NULL;
if (PTR_ERR(clk) != -EPROBE_DEFER)
pr_err("ERROR: could not get clock 
%pOF:%s(%i)\n",
np, name ? name : "", index);
@@ -106,15 +109,38 @@ struct clk *of_clk_get_by_name(struct device_node *np, 
const char *name)
if (!np)
return ERR_PTR(-ENOENT);
 
-   return __of_clk_get_by_name(np, np->full_name, name);
+   return __of_clk_get_by_name(np, np->full_name, name, false);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 
+/**
+ * of_clk_get_by_name_optional() - Parse and lookup an optional clock 
referenced
+ * by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the struct clk from the registered list of clock
+ * providers.
+ * It behaves the same as of_clk_get_by_name(), except when no clock is found.
+ * In this case, instead of returning -ENOENT, it returns NULL.
+ */
+struct clk *of_clk_get_by_name_optional(struct device_node *np,
+   const char *name)
+{
+   if (!np)
+   return ERR_PTR(-ENOENT);
+
+   return __of_clk_get_by_name(np, np->full_name, name, true);
+}
+EXPORT_SYMBOL(of_clk_get_by_name_optional);
+
 #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
return ERR_PTR(-ENOENT);
 }
@@ -197,7 +223,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4f750c4..8cb5455 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -777,6 +777,7 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
+struct clk *of_clk_get_by_name_optional(struct device_node *np, const char 
*name);
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
 #else
 static inline struct clk *of_clk_get(struct device_node *np, int index)
-- 
2.7.4



[PATCH v2 0/2] Add functions to get optional clocks

2018-07-30 Thread Phil Edworthy
Quite a few drivers get an optional clock, e.g. a clock required
to access peripheral's registers that is always enabled on some
devices.

Phil Edworthy (2):
  clk: Add of_clk_get_by_name_optional() function
  clk: Add functions to get optional clocks

 drivers/clk/clk-devres.c | 18 --
 drivers/clk/clkdev.c | 49 +++-
 include/linux/clk.h  | 30 +
 3 files changed, 90 insertions(+), 7 deletions(-)

-- 
2.7.4



[PATCH v2 2/2] clk: Add functions to get optional clocks

2018-07-30 Thread Phil Edworthy
Behaves the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
---
 drivers/clk/clk-devres.c | 18 --
 drivers/clk/clkdev.c | 17 +++--
 include/linux/clk.h  | 29 +
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..a2bb01a 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -14,7 +14,7 @@ static void devm_clk_release(struct device *dev, void *res)
clk_put(*(struct clk **)res);
 }
 
-struct clk *devm_clk_get(struct device *dev, const char *id)
+static struct clk *__devm_clk_get(struct device *dev, const char *id, bool 
optional)
 {
struct clk **ptr, *clk;
 
@@ -22,7 +22,10 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
if (!ptr)
return ERR_PTR(-ENOMEM);
 
-   clk = clk_get(dev, id);
+   if (!optional)
+   clk = clk_get(dev, id);
+   else
+   clk = clk_get_optional(dev, id);
if (!IS_ERR(clk)) {
*ptr = clk;
devres_add(dev, ptr);
@@ -32,8 +35,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 
return clk;
 }
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, false);
+}
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   return __devm_clk_get(dev, id, true);
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c1b7262..484a444 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -217,21 +217,34 @@ struct clk *clk_get_sys(const char *dev_id, const char 
*con_id)
 }
 EXPORT_SYMBOL(clk_get_sys);
 
-struct clk *clk_get(struct device *dev, const char *con_id)
+static struct clk *internal_clk_get(struct device *dev, const char *con_id,
+   bool optional)
 {
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;
 
if (dev && dev->of_node) {
-   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
+   clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id,
+  optional);
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
 
return clk_get_sys(dev_id, con_id);
 }
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, false);
+}
 EXPORT_SYMBOL(clk_get);
 
+struct clk *clk_get_optional(struct device *dev, const char *con_id)
+{
+   return internal_clk_get(dev, con_id, true);
+}
+EXPORT_SYMBOL(clk_get_optional);
+
 void clk_put(struct clk *clk)
 {
__clk_put(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 8cb5455..22040ea 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -291,6 +291,16 @@ static inline void clk_bulk_unprepare(int num_clks, struct 
clk_bulk_data *clks)
 struct clk *clk_get(struct device *dev, const char *id);
 
 /**
+ * clk_get_optional - lookup and obtain a reference to optional clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get except where there is no clock producer. In this
+ * case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *clk_get_optional(struct device *dev, const char *id);
+
+/**
  * clk_bulk_get - lookup and obtain a number of references to clock producer.
  * @dev: device for clock "consumer"
  * @num_clks: the number of clk_bulk_data
@@ -349,6 +359,14 @@ int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
 /**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
+/**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
  * @dev: device for clock "consumer"
@@ -636,6 +654,11 @@ static inline struct clk *clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+   re

RE: [PATCH] clk: Add functions to get optional clocks

2018-07-27 Thread Phil Edworthy
Hi Stephen,

On 25 July 2018 23:37, Stephen Boyd wrote:
> Quoting Phil Edworthy (2018-07-18 06:56:26)
> > On 18 July 2018 14:19, Geert Uytterhoeven wrote:
> > > On Wed, Jul 18, 2018 at 3:02 PM Russell King - ARM Linux  wrote:
> > > > On Wed, Jul 18, 2018 at 01:57:38PM +0100, Phil Edworthy wrote:
> > > > > Behaves the same as (devm_)clk_get except where there is no
> > > > > clock producer. In this case, instead of returning -ENOENT, the
> > > > > function returns NULL. This makes error checking simpler and
> > > > > allows clk_prepare_enable, etc to be called on the returned
> > > > > reference without additional checks.
> > > >
> > > > How does this work with non-DT systems, where looking a clock up
> > > > which isn't yet registered with clkdev returns -ENOENT ?
> > > >
> > > > (clkdev doesn't know when all clocks are registered with it.)
> > >
> > > Good question.
> > >
> > > I guess all drivers trying to handle optional clocks this way are
> > > already broken on non-DT systems where clocks may be registered late...
> >
> > So how do non-DT systems that look a clock up which isn't yet
> > registered with clkdev, determine that an optional clock is there or
> > not?
> >
> 
> Short answer is they don't. I'd still prefer we have this API though.
> 
> Can you rework this patch to be a little more invasive into the
> clk_get() path, perhaps by reworking __of_clk_get_by_name() a little to
> take an 'optional' argument, so that it only returns NULL when the clk is
> looked up from DT? The fallback path in clkdev where we have a DT based
> system looking up a clk through clkdev lookups doesn't seem to be a real
> scenario that we should worry about here. I think sometimes people use
> clkdev lookups when they're migrating to DT systems and things aren't wired
> up properly in DT, but that isn't the norm.
Do you mean something like this:

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 7f2cd1e..42a7d4e 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -57,7 +57,8 @@ EXPORT_SYMBOL(of_clk_get);
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -79,6 +80,8 @@ static struct clk *__of_clk_get_by_name(struct device_node 
*np,
if (PTR_ERR(clk) != -EPROBE_DEFER)
pr_err("ERROR: could not get clock 
%pOF:%s(%i)\n",
np, name ? name : "", index);
+   if (optional && PTR_ERR(clk) == -ENOENT)
+   clk = NULL;
return clk;
}
 
@@ -109,15 +112,38 @@ struct clk *of_clk_get_by_name(struct device_node *np, 
const char *name)
if (!np)
return ERR_PTR(-ENOENT);
 
-   return __of_clk_get_by_name(np, np->full_name, name);
+   return __of_clk_get_by_name(np, np->full_name, name, false);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 
+/**
+ * of_clk_get_by_name_optional() - Parse and lookup an optional clock 
referenced
+ * by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the struct clk from the registered list of clock
+ * providers.
+ * It behaves the same as of_clk_get_by_name(), except when no clock is found.
+ * In this case, instead of returning -ENOENT, it returns NULL.
+ */
+struct clk *of_clk_get_by_name_optional(struct device_node *np,
+   const char *name)
+{
+   if (!np)
+   return ERR_PTR(-ENOENT);
+
+   return __of_clk_get_by_name(np, np->full_name, name, true);
+}
+EXPORT_SYMBOL(of_clk_get_by_name_optional);
+
 #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
const char *dev_id,
-   const char *name)
+   const char *name,
+   bool optional)
 {
return ERR_PTR(-ENOENT);
 }
@@ -200,7 +226,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
struct clk *clk;
 
if (dev) {
-   clk = __of_clk_get_by_name(dev->of_node, 

RE: [PATCH] clk: renesas: r9a06g032: Avoid needless probe deferring

2018-07-20 Thread Phil Edworthy
Hi Geert,

On 20 July 2018 13:12, Geert Uytterhoeven wrote:
> On Fri, Jul 20, 2018 at 2:06 PM Phil Edworthy  wrote:
> > On 20 July 2018 12:21, Geert Uytterhoeven wrote:
> > > On Wed, Jul 18, 2018 at 4:34 PM Phil Edworthy wrote:
> > > > To avoid all SoC peripheral drivers deferring their probes, both
> > > > clock and pinctrl drivers should already be probed. Since the
> > > > pinctrl driver requires a clock to access the registers, the clock
> > > > driver should be probed before the pinctrl driver.
> > > >
> > > > Therefore, move the clock driver from subsys_initcall to core_initcall.
> > > >
> > > > Signed-off-by: Phil Edworthy 
> > >
> > > Thanks for your patch!
> > Thanks for your review!
> >
> > > The (not yet upstreamed) pinctrl driver uses postcore_initcall(), right?
> > No, the pinctrl driver uses subsys_initcall, but postcore_initcall or
> > arch_initcall may be better to make it clear about the dependencies.
> 
> if the pinctrl driver uses subsys_initcall(), ...
> 
> > > > --- a/drivers/clk/renesas/r9a06g032-clocks.c
> > > > +++ b/drivers/clk/renesas/r9a06g032-clocks.c
> > > > @@ -877,17 +877,18 @@ static const struct of_device_id
> > > r9a06g032_match[] = {
> > > > { }
> > > >  };
> > > >
> > > > -static struct platform_driver r9a06g032_clock_driver = {
> > > > +static struct platform_driver r9a06g032_clock_driver __refdata =
> > > > +{
> > > > .driver = {
> > > > .name   = "renesas,r9a06g032-sysctrl",
> > > > .of_match_table = r9a06g032_match,
> > > > },
> > > > +   .probe = r9a06g032_clocks_probe,
> > > >  };
> > > >
> > > >  static int __init r9a06g032_clocks_init(void)  {
> > > > -   return platform_driver_probe(&r9a06g032_clock_driver,
> > > > -   r9a06g032_clocks_probe);
> > > > +   platform_driver_register(&r9a06g032_clock_driver);
> > > > +   return 0;
> > That should be:
> > +   return platform_driver_register(&r9a06g032_clock_driver);
> >
> > > >  }
> > >
> > > Why are all of the above changes needed?
> > > Shouldn't the platform_driver_probe() keep on working?
> > > If it does not, it means the clock driver has some other dependency,
> > > and cannot be bound immediately.  This is potentially a dangerous
> > > situation, as
> > > r9a06g032_clocks_probe() is __init, but can still be called at any time 
> > > later.
> > > Hence using platform_driver_probe() is the safe thing to do,
> > > possibly with a different reshuffling of the clock and pinctrl initcall
> priorities.
> > No, you cannot call platform_driver_probe() from core_initcall.
> > All drivers that are in core_initcall call platform_driver_register().
> 
> Hence they cannot have their probe function __init.
> 
> >
> > Thanks
> > Phil
> >
> > > > -subsys_initcall(r9a06g032_clocks_init);
> > > > +core_initcall(r9a06g032_clocks_init);
> 
> ... using postcore_initcall() or arch_initcall() here, should work with
> platform_driver_probe()?
Nope, you have to use platform_driver_register() for DT based drivers.
subsys_initcall is the earliest you can use platform_driver_probe().

Thanks
Phil

> Gr{oetje,eeting}s,
> 
> Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds


RE: [PATCH] clk: Add functions to get optional clocks

2018-07-18 Thread Phil Edworthy
Hi Russell,

On 18 July 2018 14:19, Geert Uytterhoeven wrote:
> On Wed, Jul 18, 2018 at 3:02 PM Russell King - ARM Linux  wrote:
> > On Wed, Jul 18, 2018 at 01:57:38PM +0100, Phil Edworthy wrote:
> > > Behaves the same as (devm_)clk_get except where there is no clock
> > > producer. In this case, instead of returning -ENOENT, the function
> > > returns NULL. This makes error checking simpler and allows
> > > clk_prepare_enable, etc to be called on the returned reference
> > > without additional checks.
> >
> > How does this work with non-DT systems, where looking a clock up which
> > isn't yet registered with clkdev returns -ENOENT ?
> >
> > (clkdev doesn't know when all clocks are registered with it.)
> 
> Good question.
> 
> I guess all drivers trying to handle optional clocks this way are already 
> broken
> on non-DT systems where clocks may be registered late...

So how do non-DT systems that look a clock up which isn't yet
registered with clkdev, determine that an optional clock is there
or not?

Thanks
Phil


[PATCH] clk: Add functions to get optional clocks

2018-07-18 Thread Phil Edworthy
Behaves the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy 
---
 drivers/clk/clk-devres.c | 11 +++
 drivers/clk/clkdev.c | 11 +++
 include/linux/clk.h  | 27 +++
 3 files changed, 49 insertions(+)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..63295d9 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -34,6 +34,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *c = devm_clk_get(dev, id);
+
+   if (PTR_ERR(c) == -ENOENT)
+   return NULL;
+
+   return c;
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 7513411..7f2cd1e 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -209,6 +209,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 }
 EXPORT_SYMBOL(clk_get);
 
+struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+   struct clk *c = clk_get(dev, id);
+
+   if (PTR_ERR(c) == -ENOENT)
+   return NULL;
+
+   return c;
+}
+EXPORT_SYMBOL(clk_get_optional);
+
 void clk_put(struct clk *clk)
 {
__clk_put(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0dbd088..907202b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -258,6 +258,14 @@ static inline void clk_bulk_unprepare(int num_clks, struct 
clk_bulk_data *clks)
 struct clk *clk_get(struct device *dev, const char *id);
 
 /**
+ * clk_get_optional - lookup and obtain a reference to optional clock producer.
+ *
+ * Behaves the same as clk_get except where there is no clock producer. In this
+ * case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *clk_get_optional(struct device *dev, const char *id);
+
+/**
  * clk_bulk_get - lookup and obtain a number of references to clock producer.
  * @dev: device for clock "consumer"
  * @num_clks: the number of clk_bulk_data
@@ -316,6 +324,14 @@ int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
 /**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
+/**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *  clock producer from child node.
  * @dev: device for clock "consumer"
@@ -603,6 +619,11 @@ static inline struct clk *clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+   return NULL;
+}
+
 static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
struct clk_bulk_data *clks)
 {
@@ -614,6 +635,12 @@ static inline struct clk *devm_clk_get(struct device *dev, 
const char *id)
return NULL;
 }
 
+static inline struct clk *devm_clk_get_optional(struct device *dev,
+   const char *id)
+{
+   return NULL;
+}
+
 static inline int __must_check devm_clk_bulk_get(struct device *dev, int 
num_clks,
 struct clk_bulk_data *clks)
 {
-- 
2.7.4



[PATCH 1/2] dt: snps,designware-i2c: Add clock bindings documentation

2018-07-16 Thread Phil Edworthy
The driver requires an undocumented clock property, so detail it.
Add documentation for a separate bus clock.

Signed-off-by: Phil Edworthy 
---
 Documentation/devicetree/bindings/i2c/i2c-designware.txt | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-designware.txt 
b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
index fbb0a6d..e9f4387 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-designware.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
@@ -1,16 +1,21 @@
 * Synopsys DesignWare I2C
 
 Required properties :
-
  - compatible : should be "snps,designware-i2c"
  - reg : Offset and length of the register set for the device
  - interrupts :  where IRQ is the interrupt number.
+ - clocks : phandles for the clocks, see the description of clock-names below.
+   The phandle for the "ic_clk" clock is required. The phandle for the "bus"
+   clock is optional. If a single clock is specified but no clock-name, it is
+   the "ic_clk" clock. If both clocks are listed, the "ic_clk" must be first.
 
 Recommended properties :
-
  - clock-frequency : desired I2C bus clock frequency in Hz.
 
 Optional properties :
+ - clock-names : Contains the names of the clocks:
+"ic_clk", for the core clock used to generate the external I2C clock.
+"bus", the bus clock, sometimes described as pclk, for register accesses.
  - i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
This option is only supported in hardware blocks version 1.11a or newer.
 
-- 
2.7.4



[PATCH 2/2] i2c: designware: Add support for a bus clock

2018-07-16 Thread Phil Edworthy
The Synopsys I2C Controller has a bus clock, but typically SoCs hide this away.
However, on some SoCs you need to explicity enable the bus clock in order to
access the registers.
Therefore, enable an optional bus clock specified by DT.

Signed-off-by: Phil Edworthy 
---
 drivers/i2c/busses/i2c-designware-common.c  | 14 +-
 drivers/i2c/busses/i2c-designware-core.h|  1 +
 drivers/i2c/busses/i2c-designware-platdrv.c |  2 ++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-designware-common.c 
b/drivers/i2c/busses/i2c-designware-common.c
index 48914df..4fa67d6 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -186,13 +186,25 @@ unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
 
 int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare)
 {
+   int ret;
+
if (IS_ERR(dev->clk))
return PTR_ERR(dev->clk);
 
-   if (prepare)
+   if (prepare) {
+   /* Optional bus clock */
+   if (!IS_ERR(dev->busclk)) {
+   ret = clk_prepare_enable(dev->busclk);
+   if (ret)
+   return ret;
+   }
+
return clk_prepare_enable(dev->clk);
+   }
 
clk_disable_unprepare(dev->clk);
+   clk_disable_unprepare(dev->busclk);
+
return 0;
 }
 EXPORT_SYMBOL_GPL(i2c_dw_prepare_clk);
diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index d690e64..10f905d 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -239,6 +239,7 @@ struct dw_i2c_dev {
void __iomem*base;
struct completion   cmd_complete;
struct clk  *clk;
+   struct clk  *busclk;
struct reset_control*rst;
struct i2c_client   *slave;
u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index 5660daf..64389fe 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -332,6 +332,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
else
i2c_dw_configure_master(dev);
 
+   /* Optional bus clock */
+   dev->busclk = devm_clk_get(&pdev->dev, "bus");
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_prepare_clk(dev, true)) {
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
-- 
2.7.4



RE: [PATCH] gpio: dwapb: fix a signedness bug handling IRQs

2018-05-31 Thread Phil Edworthy
Hi Dan,

On 31 May 2018 07:24 Dan Carpenter wrote:
> Smatch flags a couple bugs here:
> 
> drivers/gpio/gpio-dwapb.c:447 dwapb_configure_irqs() warn: always true
> condition '(pp->irq[i] >= 0) => (0-u32max >= 0)'
> drivers/gpio/gpio-dwapb.c:627 dwapb_gpio_get_pdata() warn: always true
> condition '(pp->irq[j] >= 0) => (0-u32max >= 0)'
> 
> The problem is that we're storing error codes in pp->irq[] so it needs to be
> signed for the error handling to work correctly.
> 
> Fixes: da069d5d2b81 ("gpio: dwapb: Rework support for 1 interrupt per port
> A GPIO")
> Signed-off-by: Dan Carpenter 

Thanks for the patch, I had already noticed the mistake and sent a patch.

Thanks
Phil

> diff --git a/include/linux/platform_data/gpio-dwapb.h
> b/include/linux/platform_data/gpio-dwapb.h
> index 5a52d69c13f3..419cfacb4b42 100644
> --- a/include/linux/platform_data/gpio-dwapb.h
> +++ b/include/linux/platform_data/gpio-dwapb.h
> @@ -19,7 +19,7 @@ struct dwapb_port_property {
>   unsigned intidx;
>   unsigned intngpio;
>   unsigned intgpio_base;
> - unsigned intirq[32];
> + int irq[32];
>   boolhas_irq;
>   boolirq_shared;
>  };


[PATCH] gpio: dwapb: Fix rework support for 1 interrupt per port A GPIO

2018-05-25 Thread Phil Edworthy
Commit da069d5d2b814d9887989dcdb29fb0202eac8b38 ("gpio: dwapb: Rework
support for 1 interrupt per port A GPIO"), was an incremental patch that
was supposed to provide the delta between v5 and v6 patch set for
adding support for 1 interupt per port A GPIO. v5 was applied, then some
other feedback came afterwards.

However, in my haste I managed to drop the changes made to dwapb_port_property
struct. This patch includes those missing changes.

Signed-off-by: Phil Edworthy 
---
 include/linux/platform_data/gpio-dwapb.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/platform_data/gpio-dwapb.h 
b/include/linux/platform_data/gpio-dwapb.h
index 5a52d69..419cfac 100644
--- a/include/linux/platform_data/gpio-dwapb.h
+++ b/include/linux/platform_data/gpio-dwapb.h
@@ -19,7 +19,7 @@ struct dwapb_port_property {
unsigned intidx;
unsigned intngpio;
unsigned intgpio_base;
-   unsigned intirq[32];
+   int irq[32];
boolhas_irq;
boolirq_shared;
 };
-- 
2.7.4



RE: [PATCH] gpio: dwapb: Rework support for 1 interrupt per port A GPIO

2018-05-23 Thread Phil Edworthy
Hi Simon,

On 23 May 2018 10:12 Simon Horman wrote:
> On Wed, May 23, 2018 at 09:52:44AM +0100, Phil Edworthy wrote:
> > Treat DT and ACPI the same as much as possible. Note that we can't use
> > platform_get_irq() to get the DT interrupts as they are in the port
> > sub-node and hence do not have an associated platform device.
> >
> > This also fixes a problem introduced with error checking when calling
> > platform_get_irq().
> 
> What is the problem? In general I think fixes should be in separate patches.
The ACPI code would ignore errors returned by platform_get_irq(), instead
treating the error as an interrupt number.

Andy Shevchenko provided some late feedback to the v5 patch, but v5 was 
already applied by Linus W. This patch just has the incremental changes that
were made in v6 of the patch.

BR
Phil

> >
> > Signed-off-by: Phil Edworthy 
> > ---
> >  drivers/gpio/gpio-dwapb.c | 53
> > ---
> >  1 file changed, 22 insertions(+), 31 deletions(-)
> >
> > diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
> > index 7dcd06b..15b4154 100644
> > --- a/drivers/gpio/gpio-dwapb.c
> > +++ b/drivers/gpio/gpio-dwapb.c
> > @@ -444,7 +444,7 @@ static void dwapb_configure_irqs(struct
> dwapb_gpio *gpio,
> > int i;
> >
> > for (i = 0; i < pp->ngpio; i++) {
> > -   if (pp->irq[i])
> > +   if (pp->irq[i] >= 0)
> > irq_set_chained_handler_and_data(pp-
> >irq[i],
> > dwapb_irq_handler, gpio);
> > }
> > @@ -562,7 +562,7 @@ dwapb_gpio_get_pdata(struct device *dev)
> > struct dwapb_platform_data *pdata;
> > struct dwapb_port_property *pp;
> > int nports;
> > -   int i;
> > +   int i, j;
> >
> > nports = device_get_child_node_count(dev);
> > if (nports == 0)
> > @@ -580,6 +580,8 @@ dwapb_gpio_get_pdata(struct device *dev)
> >
> > i = 0;
> > device_for_each_child_node(dev, fwnode)  {
> > +   struct device_node *np = NULL;
> > +
> > pp = &pdata->properties[i++];
> > pp->fwnode = fwnode;
> >
> > @@ -599,46 +601,35 @@ dwapb_gpio_get_pdata(struct device *dev)
> > pp->ngpio = 32;
> > }
> >
> > +   pp->irq_shared  = false;
> > +   pp->gpio_base   = -1;
> > +
> > /*
> >  * Only port A can provide interrupts in all configurations of
> >  * the IP.
> >  */
> > -   if (dev->of_node && pp->idx == 0 &&
> > -   fwnode_property_read_bool(fwnode,
> > - "interrupt-controller")) {
> > -   struct device_node *np = to_of_node(fwnode);
> > -   unsigned int j;
> > -
> > -   /*
> > -* The IP has configuration options to allow a single
> > -* combined interrupt or one per gpio. If one per
> gpio,
> > -* some might not be used.
> > -*/
> > -   for (j = 0; j < pp->ngpio; j++) {
> > -   int irq = of_irq_get(np, j);
> > -   if (irq < 0)
> > -   continue;
> > -
> > -   pp->irq[j] = irq;
> > -   pp->has_irq = true;
> > -   }
> > +   if (pp->idx != 0)
> > +   continue;
> >
> > -   if (!pp->has_irq)
> > -   dev_warn(dev, "no irq for port%d\n", pp-
> >idx);
> > +   if (dev->of_node && fwnode_property_read_bool(fwnode,
> > + "interrupt-controller")) {
> > +   np = to_of_node(fwnode);
> > }
> >
> > -   if (has_acpi_companion(dev) && pp->idx == 0) {
> > -   unsigned int j;
> > +   for (j = 0; j < pp->ngpio; j++) {
> > +   pp->irq[j] = -ENXIO;
> >
> > -   for (j = 0; j < pp->ngpio; j++) {
> > +   if (np)
> > +   pp->irq[j] = of_irq_get(np, j);
> > +   else if (has_acpi_companion(dev))
> > pp->irq[j] =
> platform_get_irq(to_platform_device(dev), j);
> > -   if (pp->irq[j])
> > -   pp->has_irq = true;
> > -   }
> > +
> > +   if (pp->irq[j] >= 0)
> > +   pp->has_irq = true;
> > }
> >
> > -   pp->irq_shared  = false;
> > -   pp->gpio_base   = -1;
> > +   if (!pp->has_irq)
> > +   dev_warn(dev, "no irq for port%d\n", pp->idx);
> > }
> >
> > return pdata;
> > --
> > 2.7.4
> >


[PATCH] gpio: dwapb: Rework support for 1 interrupt per port A GPIO

2018-05-23 Thread Phil Edworthy
Treat DT and ACPI the same as much as possible. Note that we can't use
platform_get_irq() to get the DT interrupts as they are in the port
sub-node and hence do not have an associated platform device.

This also fixes a problem introduced with error checking when calling
platform_get_irq().

Signed-off-by: Phil Edworthy 
---
 drivers/gpio/gpio-dwapb.c | 53 ---
 1 file changed, 22 insertions(+), 31 deletions(-)

diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 7dcd06b..15b4154 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -444,7 +444,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
int i;
 
for (i = 0; i < pp->ngpio; i++) {
-   if (pp->irq[i])
+   if (pp->irq[i] >= 0)
irq_set_chained_handler_and_data(pp->irq[i],
dwapb_irq_handler, gpio);
}
@@ -562,7 +562,7 @@ dwapb_gpio_get_pdata(struct device *dev)
struct dwapb_platform_data *pdata;
struct dwapb_port_property *pp;
int nports;
-   int i;
+   int i, j;
 
nports = device_get_child_node_count(dev);
if (nports == 0)
@@ -580,6 +580,8 @@ dwapb_gpio_get_pdata(struct device *dev)
 
i = 0;
device_for_each_child_node(dev, fwnode)  {
+   struct device_node *np = NULL;
+
pp = &pdata->properties[i++];
pp->fwnode = fwnode;
 
@@ -599,46 +601,35 @@ dwapb_gpio_get_pdata(struct device *dev)
pp->ngpio = 32;
}
 
+   pp->irq_shared  = false;
+   pp->gpio_base   = -1;
+
/*
 * Only port A can provide interrupts in all configurations of
 * the IP.
 */
-   if (dev->of_node && pp->idx == 0 &&
-   fwnode_property_read_bool(fwnode,
- "interrupt-controller")) {
-   struct device_node *np = to_of_node(fwnode);
-   unsigned int j;
-
-   /*
-* The IP has configuration options to allow a single
-* combined interrupt or one per gpio. If one per gpio,
-* some might not be used.
-*/
-   for (j = 0; j < pp->ngpio; j++) {
-   int irq = of_irq_get(np, j);
-   if (irq < 0)
-   continue;
-
-   pp->irq[j] = irq;
-   pp->has_irq = true;
-   }
+   if (pp->idx != 0)
+   continue;
 
-   if (!pp->has_irq)
-   dev_warn(dev, "no irq for port%d\n", pp->idx);
+   if (dev->of_node && fwnode_property_read_bool(fwnode,
+ "interrupt-controller")) {
+   np = to_of_node(fwnode);
}
 
-   if (has_acpi_companion(dev) && pp->idx == 0) {
-   unsigned int j;
+   for (j = 0; j < pp->ngpio; j++) {
+   pp->irq[j] = -ENXIO;
 
-   for (j = 0; j < pp->ngpio; j++) {
+   if (np)
+   pp->irq[j] = of_irq_get(np, j);
+   else if (has_acpi_companion(dev))
pp->irq[j] = 
platform_get_irq(to_platform_device(dev), j);
-   if (pp->irq[j])
-   pp->has_irq = true;
-   }
+
+   if (pp->irq[j] >= 0)
+   pp->has_irq = true;
}
 
-   pp->irq_shared  = false;
-   pp->gpio_base   = -1;
+   if (!pp->has_irq)
+   dev_warn(dev, "no irq for port%d\n", pp->idx);
}
 
return pdata;
-- 
2.7.4



RE: [PATCH v6] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-05-23 Thread Phil Edworthy
Hi Linus,

On 23 May 2018 09:29, Linus Walleij wrote:
> On Fri, May 11, 2018 at 10:31 AM, Phil Edworthy wrote:
> 
> > The DesignWare GPIO IP can be configured for either 1 interrupt or 1
> > per GPIO in port A, but the driver currently only supports 1 interrupt.
> > See the DesignWare DW_apb_gpio Databook description of the
> > 'GPIO_INTR_IO' parameter.
> >
> > This change allows the driver to work with up to 32 interrupts, it
> > will get as many interrupts as specified in the DT 'interrupts' property.
> > It doesn't do anything clever with the different interrupts, it just
> > calls the same handler used for single interrupt hardware.
> >
> > Signed-off-by: Phil Edworthy 
> > Reviewed-by: Rob Herring 
> > Acked-by: Lee Jones 
> > ---
> > One point to mention is that I have made it possible for users to have
> > unconnected interrupts by specifying holes in the list of interrupts.
> > This is done by supporting the interrupts-extended DT prop.
> > However, I have no use for this and had to hack some test case for this.
> > Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?
> >
> > v6:
> >  - Treat DT and ACPI the same as much as possible. Note that we can't use
> >platform_get_irq() to get the DT interrupts as they are in the port
> >sub-node and hence do not have an associated platform device.
> 
> I already applied this patch in some version, can you check what is in my
> devel branch and send incremental patches on top if something needs
> changing?
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-
> gpio.git/commit/?h=devel&id=e6ca26abd37606ba4864f20c85d3fe4a2173b93f
> 
> Sorry for not knowing by heart what was applied or when, it's just too much
> for me sometimes.
No problem, I'll send a patch with the incremental changes.

Thanks
Phil


[PATCH v6] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-05-11 Thread Phil Edworthy
The DesignWare GPIO IP can be configured for either 1 interrupt or 1
per GPIO in port A, but the driver currently only supports 1 interrupt.
See the DesignWare DW_apb_gpio Databook description of the
'GPIO_INTR_IO' parameter.

This change allows the driver to work with up to 32 interrupts, it will
get as many interrupts as specified in the DT 'interrupts' property.
It doesn't do anything clever with the different interrupts, it just calls
the same handler used for single interrupt hardware.

Signed-off-by: Phil Edworthy 
Reviewed-by: Rob Herring 
Acked-by: Lee Jones 
---
One point to mention is that I have made it possible for users to have
unconnected interrupts by specifying holes in the list of interrupts. This is
done by supporting the interrupts-extended DT prop.
However, I have no use for this and had to hack some test case for this.
Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?

v6:
 - Treat DT and ACPI the same as much as possible. Note that we can't use
   platform_get_irq() to get the DT interrupts as they are in the port
   sub-node and hence do not have an associated platform device.
v5:
 - Rolled ACPI companion code provided by Hoan Tran into this patch.
v4:
 - Use of_irq_get() instead of of_irq_parse_one()+irq_create_of_mapping()
v3:
 - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid bisect problems
v2:
 - Replaced interrupt-mask DT prop with support for the interrupts-extended
   prop. This means replacing the call to irq_of_parse_and_map() with calls
   to of_irq_parse_one() and irq_create_of_mapping().
---
 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |  9 +++-
 drivers/gpio/gpio-dwapb.c  | 49 +++---
 drivers/mfd/intel_quark_i2c_gpio.c |  3 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 4 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 4a75da7..3c1118b 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -26,8 +26,13 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any are 
unconnected,
+  use the interrupts-extended property to specify the interrupts and set the
+  interrupt controller handle for unused interrupts to 0.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f..15b4154 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
 
if (!pp->irq_shared) {
-   irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-gpio);
+   int i;
+
+   for (i = 0; i < pp->ngpio; i++) {
+   if (pp->irq[i] >= 0)
+   irq_set_chained_handler_and_data(pp->irq[i],
+   dwapb_irq_handler, gpio);
+   }
} else {
/*
 * Request a shared IRQ since where MFD would have devices
 * using the same irq pin
 */
-   err = devm_request_irq(gpio->dev, pp->irq,
+   err = devm_request_irq(gpio->dev, pp->irq[0],
   dwapb_irq_handler_mfd,
   IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
 
-   if (pp->irq)
+   if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
 
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
 
/* Add GPIO-signaled ACPI event support */
-   if (pp->irq)
+

[PATCH] serial: 8250_dw: Fix runtime PM handling

2018-05-10 Thread Phil Edworthy
When using kgdb, you get an abort when accessing the UART registers.
This is because the driver has already entered runtime PM and so turned
off the bus clock needed to access the registers.

To fix this, set the capability indicating Runtime PM is active while idle.

Signed-off-by: Phil Edworthy 
---
 drivers/tty/serial/8250/8250_dw.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_dw.c 
b/drivers/tty/serial/8250/8250_dw.c
index 0529b5c..aff04f1 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -576,6 +576,10 @@ static int dw8250_probe(struct platform_device *pdev)
if (!data->skip_autocfg)
dw8250_setup_port(p);
 
+#ifdef CONFIG_PM
+   uart.capabilities |= UART_CAP_RPM;
+#endif
+
/* If we have a valid fifosize, try hooking up DMA */
if (p->fifosize) {
data->dma.rxconf.src_maxburst = p->fifosize / 4;
-- 
2.7.4



[PATCH] USB: rndis: Fix for handling garbled messages

2018-05-10 Thread Phil Edworthy
From: Michel Pollet 

A message can be forged to crash the stack; here we make sure we don't
completely break the system if this occurs

Signed-off-by: Michel Pollet 
---
 drivers/usb/gadget/function/rndis.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/gadget/function/rndis.c 
b/drivers/usb/gadget/function/rndis.c
index 51dd3e9..04c142c 100644
--- a/drivers/usb/gadget/function/rndis.c
+++ b/drivers/usb/gadget/function/rndis.c
@@ -851,6 +851,9 @@ int rndis_msg_parser(struct rndis_params *params, u8 *buf)
 */
pr_warn("%s: unknown RNDIS message 0x%08X len %d\n",
__func__, MsgType, MsgLength);
+   /* Garbled message can be huge, so limit what we display */
+   if (MsgLength > 16)
+   MsgLength = 16;
print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET,
 buf, MsgLength);
break;
-- 
2.7.4



RE: [PATCH v5] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-05-09 Thread Phil Edworthy
Hi Andy,

On 05 May 2018 11:49 Andy Shevchenko wrote:
> On Thu, Apr 26, 2018 at 7:19 PM, Phil Edworthy wrote:
> 
> Sotty fo a late response. Consider follow up fixes for below.
> 
> > if (!pp->irq_shared) {
> > +   int i;
> > +
> > +   for (i = 0; i < pp->ngpio; i++) {
> > +   if (pp->irq[i])
> > +   irq_set_chained_handler_and_data(pp->irq[i],
> > +   dwapb_irq_handler, gpio);
> > +   }
> > } else {
> > /*
> >  * Request a shared IRQ since where MFD would have devices
> >  * using the same irq pin
> >  */
> > +   err = devm_request_irq(gpio->dev, pp->irq[0],
> >dwapb_irq_handler_mfd,
> >IRQF_SHARED, "gpio-dwapb-mfd",
> > gpio);
> 
> > +   if (pp->has_irq)
> > dwapb_configure_irqs(gpio, port, pp);
> 
> I would rather make irq array a type of signed int and move conditional into
> the function to test per IRQ based.
Ok, though since the driver can be used without interrupts, it has to check
if any are used before the driver does all the other interrupt related things.
 
> > /* Add GPIO-signaled ACPI event support */
> > +   if (pp->has_irq)
> > acpi_gpiochip_request_interrupts(&port->gc);
> 
> Perhaps something similar.
> 
> > if (dev->of_node && pp->idx == 0 &&
> > fwnode_property_read_bool(fwnode,
> >
> > "interrupt-controller")) {
> 
> > +   struct device_node *np = to_of_node(fwnode);
> > +   unsigned int j;
> > +
> > +   /*
> > +* The IP has configuration options to allow a 
> > single
> > +* combined interrupt or one per gpio. If one per 
> > gpio,
> > +* some might not be used.
> > +*/
> > +   for (j = 0; j < pp->ngpio; j++) {
> > +   int irq = of_irq_get(np, j);
> > +   if (irq < 0)
> > +   continue;
> > +
> > +   pp->irq[j] = irq;
> > +   pp->has_irq = true;
> > +   }
> 
> for (...)
>  pp->irq = of_irq_get();
> 
> > }
> 
> > +   if (has_acpi_companion(dev) && pp->idx == 0) {
> > +   unsigned int j;
> > +
> > +   for (j = 0; j < pp->ngpio; j++) {
> > +   pp->irq[j] = 
> > platform_get_irq(to_platform_device(dev), j);
> > +   if (pp->irq[j])
> > +   pp->has_irq = true;
> > +   }
> 
> Ditto.
> Moreover you have a bug here. See my proposal at the top of this message.
I guess you mean that it doesn’t check for errors returned?

> And now even better to ask, why platform_get_irq() wouldn't work for DT
> case?
The problem is that the interrupts are defined in the port sub-node in DT,
not in the gpio controller node, causing platform_get_irq() to fail. The
port sub-node doesn’t have an associated platform device. I don’t think
there is a way around this...

> > +
> > +   if (!pp->has_irq)
> > dev_warn(dev, "no irq for port%d\n",
> > pp->idx);
> 
> This could be issued in the actual function which will try to allocate IRQs
> (perhaps on debug level)
> 
> 
> P.S. Just think about it, perhaps you find even better solutions.
There's certainly some duplication between DT and ACPI that can be removed.

Thanks
Phil


RE: [PATCH] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2018-05-01 Thread Phil Edworthy
Hi Rob,

On 01 May 2018 14:29 Rob Herring wrote:
> On Mon, Apr 23, 2018 at 02:33:06PM +0100, Phil Edworthy wrote:
> > On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > configured to have 32 interrupt outputs, so we have a total of 96 GPIO
> > interrupts. All of these are passed to the GPIO IRQ Muxer, which
> > selects
> > 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
> > aren't latched, so there is nothing to do in this driver when an
> > interrupt is received, other than tell the corresponding GPIO block.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> >  .../interrupt-controller/renesas,rzn1-mux.txt  |  85 ++
> 
> Please split bindings to a separate patch.
Will do.

> >  drivers/irqchip/Kconfig|  10 ++
> >  drivers/irqchip/Makefile   |   1 +
> >  drivers/irqchip/irq-rzn1-irq-mux.c | 178
> +
> >  4 files changed, 274 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mu
> > x.txt  create mode 100644 drivers/irqchip/irq-rzn1-irq-mux.c
> >
> > diff --git
> > a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > mux.txt
> > b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > mux.txt
> > new file mode 100644
> > index 000..f28a365
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,r
> > +++ zn1-mux.txt
> > @@ -0,0 +1,85 @@
> > +* Renesas RZ/N1 GPIO Interrupt Multiplexer
> > +
> > +On Renesas RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks
> > +each configured to have 32 interrupt outputs, so we have a total of
> > +96 GPIO interrupts. All of these are passed to the GPIO IRQ Muxer,
> > +which selects
> > +8 of the GPIO interrupts to pass onto the GIC.
> > +
> > +A single node in the device tree is used to describe the GPIO IRQ Muxer.
> > +
> > +Required properties:
> > +- compatible: the SoC specific name, i.e. "renesas,r9a06g032-gpioirq"
> > +   or "renesas,r9a06g033-gpioirq" followed by the SoC family name, i.e.
> > +   "renesas,rzn1-gpioirq".
> > +- interrupt-controller: Identifies the node as an interrupt controller.
> > +- #interrupt-cells: should be <1>. The meaning of the cells is the input
> > +   interrupt index, 0 to 95.
> > +- reg: Base address and size of GPIO IRQ Muxer registers.
> > +- interrupts: The list of interrupts generated by the muxer which are then
> > +   connected to a parent interrupt controller. The format of the interrupt
> > +   specifier depends in the interrupt parent controller.
> > +- gpioirq-#N: One property for each interrupt output from the GPIO IRQ
> Muxer
> > +   that specifies the input interrupt to use, #N is from 0 to 7.
> 
> Why do you need this in DT? Can't the driver handle this dynamically?
> When you request an interrupt on a GPIO line, then connect that GPIO line
> to a free IRQ line.
On the SoC that has this block, there is another CPU that runs firmware.
It's likely that the firmware will use some of these GPIO interrupts and
so we don't want them to move around. The firmware runs before Linux is
up, and luckily setting up the registers again won't affect the interrupts.

> If you really need this in DT, then interrupt-map can be used here.
Ok

> > +
> > +Optional properties:
> > +- interrupt-parent: pHandle of the parent interrupt controller, if not
> > +   inherited from the parent node.
> > +
> > +
> > +Example:
> > +
> > +   The following is an example for the RZ/N1D SoC.
> > +
> > +   gpioirq: gpioirq@51000480 {
> > +   compatible = "renesas,r9a06g032-gpioirq",
> > +   "renesas,rzn1-gpioirq";
> > +   reg = <0x51000480 0x20>;
> > +   interrupts =
> > +   ,
> > +   ,
> > +   ,
> > +   ,
> > +   ,
> > +   ,
> > +   ,
> > +   ;
> > +   interrupt-controller;
> > +   #interrupt-cells = <1>;
> > +   status = "disabled";
> 
> Don't show status in examples.
Ok

> > +   };
> > +
> > +   gpio0: gpio@5000b000 {
> > +   compatible = "snps,dw-apb-gpio";
> > +   reg = <0x5000b000 0x80>;
> > + 

[PATCH v5] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-26 Thread Phil Edworthy
The DesignWare GPIO IP can be configured for either 1 interrupt or 1
per GPIO in port A, but the driver currently only supports 1 interrupt.
See the DesignWare DW_apb_gpio Databook description of the
'GPIO_INTR_IO' parameter.

This change allows the driver to work with up to 32 interrupts, it will
get as many interrupts as specified in the DT 'interrupts' property.
It doesn't do anything clever with the different interrupts, it just calls
the same handler used for single interrupt hardware.

ACPI companion code provided by Hoan Tran . This was tested
on X-Gene by Hoan.

Signed-off-by: Phil Edworthy 
Reviewed-by: Rob Herring 
Acked-by: Lee Jones 
---
One point to mention is that I have made it possible for users to have
unconncted interrupts by specifying holes in the list of interrupts. This is
done by supporting the interrupts-extended DT prop.
However, I have no use for this and had to hack some test case for this.
Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?

v5:
 - Rolled ACPI companion code provided by Hoan Tran into this patch.
v4:
 - Use of_irq_get() instead of of_irq_parse_one()+irq_create_of_mapping()
v3:
 - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid bisect problems
v2:
 - Replaced interrupt-mask DT prop with support for the interrupts-extended
   prop. This means replacing the call to irq_of_parse_and_map() with calls
   to of_irq_parse_one() and irq_create_of_mapping().

Note: There are a few *code* lines over 80 chars, but this is just guidance,
   right? Especially as there are already some lines over 80 chars.
---
 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |  9 -
 drivers/gpio/gpio-dwapb.c  | 46 +-
 drivers/mfd/intel_quark_i2c_gpio.c |  3 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 4 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 4a75da7..3c1118b 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -26,8 +26,13 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any are 
unconnected,
+  use the interrupts-extended property to specify the interrupts and set the
+  interrupt controller handle for unused interrupts to 0.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f..7dcd06b 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
 
if (!pp->irq_shared) {
-   irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-gpio);
+   int i;
+
+   for (i = 0; i < pp->ngpio; i++) {
+   if (pp->irq[i])
+   irq_set_chained_handler_and_data(pp->irq[i],
+   dwapb_irq_handler, gpio);
+   }
} else {
/*
 * Request a shared IRQ since where MFD would have devices
 * using the same irq pin
 */
-   err = devm_request_irq(gpio->dev, pp->irq,
+   err = devm_request_irq(gpio->dev, pp->irq[0],
   dwapb_irq_handler_mfd,
   IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
 
-   if (pp->irq)
+   if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
 
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
 
/* Add GPIO-signaled ACPI event support */
-   if (pp->irq)
+   i

[PATCH] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

2018-04-23 Thread Phil Edworthy
On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
configured to have 32 interrupt outputs, so we have a total of 96 GPIO
interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
aren't latched, so there is nothing to do in this driver when an interrupt
is received, other than tell the corresponding GPIO block.

Signed-off-by: Phil Edworthy 
---
 .../interrupt-controller/renesas,rzn1-mux.txt  |  85 ++
 drivers/irqchip/Kconfig|  10 ++
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/irq-rzn1-irq-mux.c | 178 +
 4 files changed, 274 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
 create mode 100644 drivers/irqchip/irq-rzn1-irq-mux.c

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt 
b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
new file mode 100644
index 000..f28a365
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
@@ -0,0 +1,85 @@
+* Renesas RZ/N1 GPIO Interrupt Multiplexer
+
+On Renesas RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
+configured to have 32 interrupt outputs, so we have a total of 96 GPIO
+interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
+8 of the GPIO interrupts to pass onto the GIC.
+
+A single node in the device tree is used to describe the GPIO IRQ Muxer.
+
+Required properties:
+- compatible: the SoC specific name, i.e. "renesas,r9a06g032-gpioirq"
+   or "renesas,r9a06g033-gpioirq" followed by the SoC family name, i.e.
+   "renesas,rzn1-gpioirq".
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: should be <1>. The meaning of the cells is the input
+   interrupt index, 0 to 95.
+- reg: Base address and size of GPIO IRQ Muxer registers.
+- interrupts: The list of interrupts generated by the muxer which are then
+   connected to a parent interrupt controller. The format of the interrupt
+   specifier depends in the interrupt parent controller.
+- gpioirq-#N: One property for each interrupt output from the GPIO IRQ Muxer
+   that specifies the input interrupt to use, #N is from 0 to 7.
+
+Optional properties:
+- interrupt-parent: pHandle of the parent interrupt controller, if not
+   inherited from the parent node.
+
+
+Example:
+
+   The following is an example for the RZ/N1D SoC.
+
+   gpioirq: gpioirq@51000480 {
+   compatible = "renesas,r9a06g032-gpioirq",
+   "renesas,rzn1-gpioirq";
+   reg = <0x51000480 0x20>;
+   interrupts =
+   ,
+   ,
+   ,
+   ,
+   ,
+   ,
+   ,
+   ;
+   interrupt-controller;
+   #interrupt-cells = <1>;
+   status = "disabled";
+   };
+
+   gpio0: gpio@5000b000 {
+   compatible = "snps,dw-apb-gpio";
+   reg = <0x5000b000 0x80>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   clock-names = "bus";
+   clocks = <&hclk_gpio0>;
+   status = "disabled";
+
+   gpio0a: gpio-controller@0 {
+   compatible = "snps,dw-apb-gpio-port";
+   bank-name = "gpio0a";
+   gpio-controller;
+   #gpio-cells = <2>;
+   snps,nr-gpios = <32>;
+   reg = <0>;
+
+   interrupt-controller;
+   interrupt-parent = <&gpioirq>;
+   interrupts =   < 0  1  2  3  4  5  6  7
+8  9 10 11 12 13 14 15
+   16 17 18 19 20 21 22 23
+   24 25 26 27 28 29 30 31 >;
+   #interrupt-cells = <2>;
+   };
+   };
+
+
+   The following is an example for a board using this.
+
+   &gpioirq {
+   status = "okay";
+   gpioirq-0 = <24>;   /* gpio0a 24 */
+   gpioirq-4 = <3>;/* gpio0a 3 */
+   };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index e9233db..16f2633 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -204,6 +204,16 @@ config RENESAS_IRQC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
 
+config RENESAS_RZN1_IRQ_MUX
+

RE: [PATCH v3] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-19 Thread Phil Edworthy
Hi Hoan

On 18 April 2018 08:03 Hoan Tran wrote:
> On Fri, Apr 13, 2018 at 9:47 AM, Phil Edworthy wrote:
> > On 13 April 2018 17:37 Hoan Tran wrote:
> >> On Fri, Apr 13, 2018 at 1:51 AM, Phil Edworthy wrote:
> >> > The DesignWare GPIO IP can be configured for either 1 interrupt or
> >> > 1 per GPIO in port A, but the driver currently only supports 1 interrupt.
> >> > See the DesignWare DW_apb_gpio Databook description of the
> >> > 'GPIO_INTR_IO' parameter.
> >> >
> >> > This change allows the driver to work with up to 32 interrupts, it
> >> > will get as many interrupts as specified in the DT 'interrupts' property.
> >> > It doesn't do anything clever with the different interrupts, it
> >> > just calls the same handler used for single interrupt hardware.
> >> >
> >> > Signed-off-by: Phil Edworthy 
> >> > ---
> >> > One point to mention is that I have made it possible for users to
> >> > have unconncted interrupts by specifying holes in the list of interrupts.
> >> > This is done by supporting the interrupts-extended DT prop.
> >> > However, I have no use for this and had to hack some test case for this.
> >> > Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?
> >> >
> >> > v3:
> >> >  - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid
> >> > bisect problems
> >> > v2:
> >> >  - Replaced interrupt-mask DT prop with support for the interrupts-
> >> extended
> >> >prop. This means replacing the call to irq_of_parse_and_map() with
> calls
> >> >to of_irq_parse_one() and irq_create_of_mapping().
> >> >
> >> > Note: There are a few *code* lines over 80 chars, but this is just
> guidance,
> >> >right? Especially as there are already some lines over 80 chars.
> >> > ---
> > [snip]
> >
> >> > -   if (has_acpi_companion(dev) && pp->idx == 0)
> >> > -   pp->irq = 
> >> > platform_get_irq(to_platform_device(dev), 0);
> >> > +   if (has_acpi_companion(dev) && pp->idx == 0) {
> >> > +   pp->irq[0] = 
> >> > platform_get_irq(to_platform_device(dev),
> 0);
> >> > +   if (pp->irq[0])
> >> > +   pp->has_irq = true;
> >> > +   }
> >>
> >> It doesn't work for ACPI. Could you do the same logic for ACPI?
> > I don’t have access to any device that was baked (i.e. fabbed) with
> > multiple output interrupts from the Synopsys GPIO blocks and use ACPI.
> > I don't know if any such device exists.
> 
> Below code is tested on X-Gene system which supports 1 interrupt per GPIO
> on Port A. You can update it into your patch.
> 
> -   if (has_acpi_companion(dev) && pp->idx == 0)
> -   pp->irq = platform_get_irq(to_platform_device(dev), 
> 0);
> +   if (has_acpi_companion(dev) && pp->idx == 0) {
> +   unsigned int j;
> +   for (j = 0; j < pp->ngpio; j++) {
> +   pp->irq[j] =
> platform_get_irq(to_platform_device(dev), j);
> +   if (pp->irq[j])
> +   pp->has_irq = true;
> +   }
> +   }
Since I've already got some reviewed-by and acks for v4, I'll leave it to Linus
to decide if he wants me to roll your changes into this patch or for you to
submit a separate patch.

Thanks
Phil


> >> > pp->irq_shared  = false;
> >> > pp->gpio_base   = -1;
> >> > diff --git a/drivers/mfd/intel_quark_i2c_gpio.c
> >> > b/drivers/mfd/intel_quark_i2c_gpio.c
> >> > index 90e35de..5bddb84 100644
> >> > --- a/drivers/mfd/intel_quark_i2c_gpio.c
> >> > +++ b/drivers/mfd/intel_quark_i2c_gpio.c
> >> > @@ -233,7 +233,8 @@ static int intel_quark_gpio_setup(struct
> >> > pci_dev
> >> *pdev, struct mfd_cell *cell)
> >> > pdata->properties->idx  = 0;
> >> > pdata->properties->ngpio= INTEL_QUARK_MFD_NGPIO;
> >> > pdata->properties->gpio_base=
> INTEL_QUARK_MFD_GPIO_BASE;
> >> > -   pdata->properties->irq  = pdev->irq;
> >> > +   pdata->properties->irq[0]   = pdev->irq;
> >> > +   pdata->properties->has_irq  = true;
> >> > pdata->properties->irq_shared   = true;
> >> >
> >> > cell->platform_data = pdata; diff --git
> >> > a/include/linux/platform_data/gpio-dwapb.h
> >> > b/include/linux/platform_data/gpio-dwapb.h
> >> > index 2dc7f4a..5a52d69 100644
> >> > --- a/include/linux/platform_data/gpio-dwapb.h
> >> > +++ b/include/linux/platform_data/gpio-dwapb.h
> >> > @@ -19,7 +19,8 @@ struct dwapb_port_property {
> >> > unsigned intidx;
> >> > unsigned intngpio;
> >> > unsigned intgpio_base;
> >> > -   unsigned intirq;
> >> > +   unsigned intirq[32];
> >> > +   boolhas_irq;
> >> > boolirq_shared;
> >> >  };
> >> >
> >> > --
> >> > 2.7.4
> >> >


[PATCH v4] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-17 Thread Phil Edworthy
The DesignWare GPIO IP can be configured for either 1 interrupt or 1
per GPIO in port A, but the driver currently only supports 1 interrupt.
See the DesignWare DW_apb_gpio Databook description of the
'GPIO_INTR_IO' parameter.

This change allows the driver to work with up to 32 interrupts, it will
get as many interrupts as specified in the DT 'interrupts' property.
It doesn't do anything clever with the different interrupts, it just calls
the same handler used for single interrupt hardware.

Signed-off-by: Phil Edworthy 
---
One point to mention is that I have made it possible for users to have
unconncted interrupts by specifying holes in the list of interrupts. This is
done by supporting the interrupts-extended DT prop.
However, I have no use for this and had to hack some test case for this.
Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?

v4:
 - Use of_irq_get() instead of of_irq_parse_one()+irq_create_of_mapping()
v3:
 - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid bisect problems
v2:
 - Replaced interrupt-mask DT prop with support for the interrupts-extended
   prop. This means replacing the call to irq_of_parse_and_map() with calls
   to of_irq_parse_one() and irq_create_of_mapping().

Note: There are a few *code* lines over 80 chars, but this is just guidance,
   right? Especially as there are already some lines over 80 chars.

snps:gpio fix

Signed-off-by: Phil Edworthy 
---
 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |  9 +++--
 drivers/gpio/gpio-dwapb.c  | 42 +-
 drivers/mfd/intel_quark_i2c_gpio.c |  3 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 4 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 4a75da7..3c1118b 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -26,8 +26,13 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any are 
unconnected,
+  use the interrupts-extended property to specify the interrupts and set the
+  interrupt controller handle for unused interrupts to 0.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f..7a1022f 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
 
if (!pp->irq_shared) {
-   irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-gpio);
+   int i;
+
+   for (i = 0; i < pp->ngpio; i++) {
+   if (pp->irq[i])
+   irq_set_chained_handler_and_data(pp->irq[i],
+   dwapb_irq_handler, gpio);
+   }
} else {
/*
 * Request a shared IRQ since where MFD would have devices
 * using the same irq pin
 */
-   err = devm_request_irq(gpio->dev, pp->irq,
+   err = devm_request_irq(gpio->dev, pp->irq[0],
   dwapb_irq_handler_mfd,
   IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
 
-   if (pp->irq)
+   if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
 
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
 
/* Add GPIO-signaled ACPI event support */
-   if (pp->irq)
+   if (pp->has_irq)
acpi_gpiochip_request_interrupts(&port->gc);
 
return err;
@@ -601,

RE: [PATCH v3] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-17 Thread Phil Edworthy
Hi Rob,

On 16 April 2018 21:03 Rob Herring wrote:
> On Fri, Apr 13, 2018 at 09:51:12AM +0100, Phil Edworthy wrote:
> > The DesignWare GPIO IP can be configured for either 1 interrupt or 1
> > per GPIO in port A, but the driver currently only supports 1 interrupt.
> > See the DesignWare DW_apb_gpio Databook description of the
> > 'GPIO_INTR_IO' parameter.
> >
> > This change allows the driver to work with up to 32 interrupts, it
> > will get as many interrupts as specified in the DT 'interrupts' property.
> > It doesn't do anything clever with the different interrupts, it just
> > calls the same handler used for single interrupt hardware.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > One point to mention is that I have made it possible for users to have
> > unconncted interrupts by specifying holes in the list of interrupts.
> > This is done by supporting the interrupts-extended DT prop.
> > However, I have no use for this and had to hack some test case for this.
> > Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?
> >
> > v3:
> >  - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid
> > bisect problems
> > v2:
> >  - Replaced interrupt-mask DT prop with support for the interrupts-
> extended
> >prop. This means replacing the call to irq_of_parse_and_map() with calls
> >to of_irq_parse_one() and irq_create_of_mapping().
> >
> > Note: There are a few *code* lines over 80 chars, but this is just guidance,
> >right? Especially as there are already some lines over 80 chars.
> > ---
[snip]

> > +   for (j = 0; j < pp->ngpio; j++) {
> > +   if (of_irq_parse_one(np, j, &oirq))
> > +   continue;
> > +
> > +   pp->irq[j] = irq_create_of_mapping(&oirq);
> 
> I'm hoping to not have new users of of_irq_parse_one and
> irq_create_of_mapping. Can you use of_irq_get instead? It will base back
> error codes so you can distinguish different conditions.
Sure, I hadn't noticed that particular variant!

Thanks
Phil

> > +   if (pp->irq[j])
> > +   pp->has_irq = true;
> > +   }
> > +
> > +   if (!pp->has_irq)
> > dev_warn(dev, "no irq for port%d\n", pp-
> >idx);
> > }
> >
> > -   if (has_acpi_companion(dev) && pp->idx == 0)
> > -   pp->irq =
> platform_get_irq(to_platform_device(dev), 0);
> > +   if (has_acpi_companion(dev) && pp->idx == 0) {
> > +   pp->irq[0] =
> platform_get_irq(to_platform_device(dev), 0);
> > +   if (pp->irq[0])
> > +   pp->has_irq = true;
> > +   }
> >
> > pp->irq_shared  = false;
> > pp->gpio_base   = -1;


RE: [PATCH v3] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-13 Thread Phil Edworthy
Hi Hoan,

On 13 April 2018 17:37 Hoan Tran wrote:
> On Fri, Apr 13, 2018 at 1:51 AM, Phil Edworthy wrote:
> > The DesignWare GPIO IP can be configured for either 1 interrupt or 1
> > per GPIO in port A, but the driver currently only supports 1 interrupt.
> > See the DesignWare DW_apb_gpio Databook description of the
> > 'GPIO_INTR_IO' parameter.
> >
> > This change allows the driver to work with up to 32 interrupts, it
> > will get as many interrupts as specified in the DT 'interrupts' property.
> > It doesn't do anything clever with the different interrupts, it just
> > calls the same handler used for single interrupt hardware.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > One point to mention is that I have made it possible for users to have
> > unconncted interrupts by specifying holes in the list of interrupts.
> > This is done by supporting the interrupts-extended DT prop.
> > However, I have no use for this and had to hack some test case for this.
> > Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?
> >
> > v3:
> >  - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid
> > bisect problems
> > v2:
> >  - Replaced interrupt-mask DT prop with support for the interrupts-
> extended
> >prop. This means replacing the call to irq_of_parse_and_map() with calls
> >to of_irq_parse_one() and irq_create_of_mapping().
> >
> > Note: There are a few *code* lines over 80 chars, but this is just guidance,
> >right? Especially as there are already some lines over 80 chars.
> > ---
[snip]

> > -   if (has_acpi_companion(dev) && pp->idx == 0)
> > -   pp->irq = platform_get_irq(to_platform_device(dev), 
> > 0);
> > +   if (has_acpi_companion(dev) && pp->idx == 0) {
> > +   pp->irq[0] = 
> > platform_get_irq(to_platform_device(dev), 0);
> > +   if (pp->irq[0])
> > +   pp->has_irq = true;
> > +   }
> 
> It doesn't work for ACPI. Could you do the same logic for ACPI?
I don’t have access to any device that was baked (i.e. fabbed) with multiple
output interrupts from the Synopsys GPIO blocks and use ACPI. I don't
know if any such device exists.

I would prefer not writing code that can be tested easily. I cannot even
test the current, albeit small, changes to the Intel Quark MFD.

Regards
Phil

> Thanks
> Hoan
> 
> >
> > pp->irq_shared  = false;
> > pp->gpio_base   = -1;
> > diff --git a/drivers/mfd/intel_quark_i2c_gpio.c
> > b/drivers/mfd/intel_quark_i2c_gpio.c
> > index 90e35de..5bddb84 100644
> > --- a/drivers/mfd/intel_quark_i2c_gpio.c
> > +++ b/drivers/mfd/intel_quark_i2c_gpio.c
> > @@ -233,7 +233,8 @@ static int intel_quark_gpio_setup(struct pci_dev
> *pdev, struct mfd_cell *cell)
> > pdata->properties->idx  = 0;
> > pdata->properties->ngpio= INTEL_QUARK_MFD_NGPIO;
> > pdata->properties->gpio_base= INTEL_QUARK_MFD_GPIO_BASE;
> > -   pdata->properties->irq  = pdev->irq;
> > +   pdata->properties->irq[0]   = pdev->irq;
> > +   pdata->properties->has_irq  = true;
> > pdata->properties->irq_shared   = true;
> >
> > cell->platform_data = pdata;
> > diff --git a/include/linux/platform_data/gpio-dwapb.h
> > b/include/linux/platform_data/gpio-dwapb.h
> > index 2dc7f4a..5a52d69 100644
> > --- a/include/linux/platform_data/gpio-dwapb.h
> > +++ b/include/linux/platform_data/gpio-dwapb.h
> > @@ -19,7 +19,8 @@ struct dwapb_port_property {
> > unsigned intidx;
> > unsigned intngpio;
> > unsigned intgpio_base;
> > -   unsigned intirq;
> > +   unsigned intirq[32];
> > +   boolhas_irq;
> > boolirq_shared;
> >  };
> >
> > --
> > 2.7.4
> >


[PATCH v3] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-13 Thread Phil Edworthy
The DesignWare GPIO IP can be configured for either 1 interrupt or 1
per GPIO in port A, but the driver currently only supports 1 interrupt.
See the DesignWare DW_apb_gpio Databook description of the
'GPIO_INTR_IO' parameter.

This change allows the driver to work with up to 32 interrupts, it will
get as many interrupts as specified in the DT 'interrupts' property.
It doesn't do anything clever with the different interrupts, it just calls
the same handler used for single interrupt hardware.

Signed-off-by: Phil Edworthy 
---
One point to mention is that I have made it possible for users to have
unconncted interrupts by specifying holes in the list of interrupts. This is
done by supporting the interrupts-extended DT prop.
However, I have no use for this and had to hack some test case for this.
Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?

v3:
 - Rolled mfd: intel_quark_i2c_gpio fix into this patch to avoid bisect problems
v2:
 - Replaced interrupt-mask DT prop with support for the interrupts-extended
   prop. This means replacing the call to irq_of_parse_and_map() with calls
   to of_irq_parse_one() and irq_create_of_mapping().

Note: There are a few *code* lines over 80 chars, but this is just guidance,
   right? Especially as there are already some lines over 80 chars.
---
 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |  9 -
 drivers/gpio/gpio-dwapb.c  | 43 +-
 drivers/mfd/intel_quark_i2c_gpio.c |  3 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 4 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 4a75da7..3c1118b 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -26,8 +26,13 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any are 
unconnected,
+  use the interrupts-extended property to specify the interrupts and set the
+  interrupt controller handle for unused interrupts to 0.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f..3273504 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
 
if (!pp->irq_shared) {
-   irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-gpio);
+   int i;
+
+   for (i = 0; i < pp->ngpio; i++) {
+   if (pp->irq[i])
+   irq_set_chained_handler_and_data(pp->irq[i],
+   dwapb_irq_handler, gpio);
+   }
} else {
/*
 * Request a shared IRQ since where MFD would have devices
 * using the same irq pin
 */
-   err = devm_request_irq(gpio->dev, pp->irq,
+   err = devm_request_irq(gpio->dev, pp->irq[0],
   dwapb_irq_handler_mfd,
   IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
 
-   if (pp->irq)
+   if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
 
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
 
/* Add GPIO-signaled ACPI event support */
-   if (pp->irq)
+   if (pp->has_irq)
acpi_gpiochip_request_interrupts(&port->gc);
 
return err;
@@ -601,13 +606,33 @@ dwapb_gpio_get_pdata(struct device *dev)
if (dev->of_node && pp->idx == 0 &&

RE: [PATCH v2 2/2] mfd: intel_quark_i2c_gpio: Update Synopsys GPIO interrupts

2018-04-13 Thread Phil Edworthy
Hi Geert,

On 13 April 2018 09:20 Geert Uytterhoeven wrote:
> On Fri, Apr 13, 2018 at 10:08 AM, Phil Edworthy wrote:
> > Since the way the Synopsys GPIO interrupts are stored has changed,
> > this driver needs to be updated in line with the changes.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > v2:
> >  - New patch in v2 to fix the only other user of struct
> dwapb_port_property.
> 
> Thanks for your patch!
> 
> To avoid bisection compile failures due to the changed type of
> dwapb_port_property.irq, I think this should be folded into the first patch,
Right, thanks for pointing this out!
Phil

> > ---
> >  drivers/mfd/intel_quark_i2c_gpio.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mfd/intel_quark_i2c_gpio.c
> > b/drivers/mfd/intel_quark_i2c_gpio.c
> > index 90e35de..5bddb84 100644
> > --- a/drivers/mfd/intel_quark_i2c_gpio.c
> > +++ b/drivers/mfd/intel_quark_i2c_gpio.c
> > @@ -233,7 +233,8 @@ static int intel_quark_gpio_setup(struct pci_dev
> *pdev, struct mfd_cell *cell)
> > pdata->properties->idx  = 0;
> > pdata->properties->ngpio= INTEL_QUARK_MFD_NGPIO;
> > pdata->properties->gpio_base= INTEL_QUARK_MFD_GPIO_BASE;
> > -   pdata->properties->irq  = pdev->irq;
> > +   pdata->properties->irq[0]   = pdev->irq;
> > +   pdata->properties->has_irq  = true;
> > pdata->properties->irq_shared   = true;
> >
> > cell->platform_data = pdata;
> 
> Gr{oetje,eeting}s,
> 
> Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds


[PATCH v2 2/2] mfd: intel_quark_i2c_gpio: Update Synopsys GPIO interrupts

2018-04-13 Thread Phil Edworthy
Since the way the Synopsys GPIO interrupts are stored has changed, this
driver needs to be updated in line with the changes.

Signed-off-by: Phil Edworthy 
---
v2:
 - New patch in v2 to fix the only other user of struct dwapb_port_property.
---
 drivers/mfd/intel_quark_i2c_gpio.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/intel_quark_i2c_gpio.c 
b/drivers/mfd/intel_quark_i2c_gpio.c
index 90e35de..5bddb84 100644
--- a/drivers/mfd/intel_quark_i2c_gpio.c
+++ b/drivers/mfd/intel_quark_i2c_gpio.c
@@ -233,7 +233,8 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, 
struct mfd_cell *cell)
pdata->properties->idx  = 0;
pdata->properties->ngpio= INTEL_QUARK_MFD_NGPIO;
pdata->properties->gpio_base= INTEL_QUARK_MFD_GPIO_BASE;
-   pdata->properties->irq  = pdev->irq;
+   pdata->properties->irq[0]   = pdev->irq;
+   pdata->properties->has_irq  = true;
pdata->properties->irq_shared   = true;
 
cell->platform_data = pdata;
-- 
2.7.4



[PATCH v2 1/2] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-13 Thread Phil Edworthy
The DesignWare GPIO IP can be configured for either 1 interrupt or 1
per GPIO in port A, but the driver currently only supports 1 interrupt.
See the DesignWare DW_apb_gpio Databook description of the
'GPIO_INTR_IO' parameter.

This change allows the driver to work with up to 32 interrupts, it will
get as many interrupts as specified in the DT 'interrupts' property.
It doesn't do anything clever with the different interrupts, it just calls
the same handler used for single interrupt hardware.

Signed-off-by: Phil Edworthy 
---
v2:
 - Replaced interrupt-mask DT prop with support for the interrupts-extended
   prop. This means replacing the call to irq_of_parse_and_map() with calls
   to of_irq_parse_one() and irq_create_of_mapping().

Note: There are a few *code* lines over 80 chars, but this is just guidance,
   right? Especially as there are already some lines over 80 chars.
---
 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |  9 -
 drivers/gpio/gpio-dwapb.c  | 43 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 3 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 4a75da7..3c1118b 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -26,8 +26,13 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any are 
unconnected,
+  use the interrupts-extended property to specify the interrupts and set the
+  interrupt controller handle for unused interrupts to 0.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f..3273504 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
 
if (!pp->irq_shared) {
-   irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-gpio);
+   int i;
+
+   for (i = 0; i < pp->ngpio; i++) {
+   if (pp->irq[i])
+   irq_set_chained_handler_and_data(pp->irq[i],
+   dwapb_irq_handler, gpio);
+   }
} else {
/*
 * Request a shared IRQ since where MFD would have devices
 * using the same irq pin
 */
-   err = devm_request_irq(gpio->dev, pp->irq,
+   err = devm_request_irq(gpio->dev, pp->irq[0],
   dwapb_irq_handler_mfd,
   IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
 
-   if (pp->irq)
+   if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
 
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
 
/* Add GPIO-signaled ACPI event support */
-   if (pp->irq)
+   if (pp->has_irq)
acpi_gpiochip_request_interrupts(&port->gc);
 
return err;
@@ -601,13 +606,33 @@ dwapb_gpio_get_pdata(struct device *dev)
if (dev->of_node && pp->idx == 0 &&
fwnode_property_read_bool(fwnode,
  "interrupt-controller")) {
-   pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0);
-   if (!pp->irq)
+   struct device_node *np = to_of_node(fwnode);
+   struct of_phandle_args oirq;
+   unsigned int j;
+
+   /*
+* The IP has configuration options to all

[PATCH v2 0/2] gpio: dwapb: Add support for 1 interrupt per port A GPIO

2018-04-13 Thread Phil Edworthy
All details about the change is in patch 0001. patch 0002 fixes up other users
of 'struct dwapb_port_property'.

One point to mention is that I have made it possible for users to have
unconncted interrupts by specifying holes in the list of interrupts. This is
done by supporting the interrupts-extended DT prop.
However, I have no use for this and had to hack some test case for this.
Perhaps the driver should support 1 interrupt or all GPIOa as interrupts?

Phil Edworthy (2):
  gpio: dwapb: Add support for 1 interrupt per port A GPIO
  mfd: intel_quark_i2c_gpio: Update Synopsys GPIO interrupts

 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   |  9 -
 drivers/gpio/gpio-dwapb.c  | 43 +-
 drivers/mfd/intel_quark_i2c_gpio.c |  3 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 4 files changed, 45 insertions(+), 13 deletions(-)

-- 
2.7.4



RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-04-11 Thread Phil Edworthy
Hi Andy,

On 05 April 2018 10:43, Phil Edworthy wrote:
> On 30 March 2018 22:26 Andy Shevchenko wrote:
> > On Wed, Mar 28, 2018 at 5:22 PM, Phil Edworthy wrote:
> > > The DesignWare GPIO IP can be configured for either 1 or 32
> > > interrupts,
> >
> > 1 to 32, or just a choice between two?
> Just a choice of 1 or 32.
Sorry, I was wrong about this... the manual does not say 1 or 32. It says:
"Port A can be configured to generate multiple interrupt signals or
a single combined interrupt flag. When set to 1, the component generates a
single combined interrupt flag."

There is no other text describing this option, but I believe all GPIOs on
port A will have an interrupt. In our case we have 32 GPIOs on port A
and 32 interrupts connected to them.

Thanks
Phil


RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-04-10 Thread Phil Edworthy
Hi Geert,

On 10 April 2018 15:29 Geert Uytterhoeven wrote:
> On Tue, Apr 10, 2018 at 4:23 PM, Phil Edworthy wrote:
> > On 10 April 2018 07:24 Phil Edworthy wrote:
> >> On 09 April 2018 20:20 Rob Herring wrote:
> >> > On Wed, Mar 28, 2018 at 03:22:30PM +0100, Phil Edworthy wrote:
> > [...]
> >> > > +- interrupt-mask : a 32-bit bit mask that specifies which
> >> > > +interrupts in the list
> >> > > +  of interrupts is valid, bit is 1 for a valid irq.
> >> >
> >> > This is not a standard property and would need a vendor prefix.
> >> > However,
> >> I'd
> >> > prefer you just skip any not connected interrupts with an invalid
> >> > interrupt number. Then the GPIO number is the index into "interrupts".
> >> Makes sense, I'll rework it to do this.
> > Err, what would an invalid interrupt number be?
> > If I use -1, I get a DT parsing error and 0 is certainly valid. If the
> > number is larger than the valid interrupt range I get errors during probe.
> 
> Perhaps using interrupts-extended instead of interrupts?
> 
> E.g.
> 
> interrupts-extended = <&intc1 5 1>, <0>, <&intc2 1 0>;

Thanks for the pointer, I'll have a look.
Phil


RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-04-10 Thread Phil Edworthy
Hi Rob,

On 10 April 2018 07:24 Phil Edworthy wrote:
> On 09 April 2018 20:20 Rob Herring wrote:
> > On Wed, Mar 28, 2018 at 03:22:30PM +0100, Phil Edworthy wrote:
[...]
> > > +- interrupt-mask : a 32-bit bit mask that specifies which interrupts
> > > +in the list
> > > +  of interrupts is valid, bit is 1 for a valid irq.
> >
> > This is not a standard property and would need a vendor prefix. However,
> I'd
> > prefer you just skip any not connected interrupts with an invalid interrupt
> > number. Then the GPIO number is the index into "interrupts".
> Makes sense, I'll rework it to do this.
Err, what would an invalid interrupt number be?
If I use -1, I get a DT parsing error and 0 is certainly valid. If the number is
larger than the valid interrupt range I get errors during probe.

Thanks
Phil


RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-04-09 Thread Phil Edworthy
Hi Rob,

On 09 April 2018 20:20 Rob Herring wrote:
> On Wed, Mar 28, 2018 at 03:22:30PM +0100, Phil Edworthy wrote:
> > The DesignWare GPIO IP can be configured for either 1 or 32
> > interrupts, but the driver currently only supports 1 interrupt. See
> > the DesignWare DW_apb_gpio Databook description of the
> 'GPIO_INTR_IO' parameter.
> 
> Someday h/w designers will realize this does nothing to optimize interrupt
> handling...
I can imagine some software where the isr is written to handle a specific GPIO
interrupt _could_ be faster, though no sane software would be designed like
that.

> > This change allows the driver to work with up to 32 interrupts, it
> > will get as many interrupts as specified in the DT 'interrupts' property.
> > It doesn't do anything clever with the different interrupts, it just
> > calls the same handler used for single interrupt hardware.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > Note: There are a few lines over 80 chars, but this is just guidance, right?
> >   Especially as there are already some lines over 80 chars.
> 
> Code, yes, but not for paragraphs of text in DT bindings.
Good, that's what I did.

> > ---
> >  .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   | 10 -
> >  drivers/gpio/gpio-dwapb.c  | 44 
> > +-
> >  include/linux/platform_data/gpio-dwapb.h   |  3 +-
> >  3 files changed, 45 insertions(+), 12 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> > b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> > index 4a75da7..e343581 100644
> > --- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> > +++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> > @@ -26,8 +26,14 @@ controller.
> >the second encodes the triger flags encoded as described in
> >
> > Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> >  - interrupt-parent : The parent interrupt controller.
> > -- interrupts : The interrupt to the parent controller raised when
> > GPIOs
> > -  generate the interrupts.
> > +- interrupts : The interrupts to the parent controller raised when
> > +GPIOs
> > +  generate the interrupts. If the controller provides one combined
> > +interrupt
> > +  for all GPIOs, specify a single interrupt. If the controller
> > +provides one
> > +  interrupt for each GPIO, provide a list of interrupts that
> > +correspond to each
> > +  of the GPIO pins. When specifying multiple interrupts, if any of
> > +the GPIOs are
> > +  not connected to an interrupt, use the interrupt-mask property.
> > +- interrupt-mask : a 32-bit bit mask that specifies which interrupts
> > +in the list
> > +  of interrupts is valid, bit is 1 for a valid irq.
> 
> This is not a standard property and would need a vendor prefix. However, I'd
> prefer you just skip any not connected interrupts with an invalid interrupt
> number. Then the GPIO number is the index into "interrupts".
Makes sense, I'll rework it to do this.

> >  - snps,nr-gpios : The number of pins in the port, a single cell.
> 
> This BTW should be deprecated to use "nr-gpios" instead, but that's another
> patch.

Thanks for your comments,
Phil


RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-04-06 Thread Phil Edworthy
Hi Geert,

On 06 April 2018 10:57 Geert Uytterhoeven wrote:
> On Thu, Apr 5, 2018 at 11:42 AM, Phil Edworthy wrote:
> > On 30 March 2018 22:26 Andy Shevchenko wrote:
> >> On Wed, Mar 28, 2018 at 5:22 PM, Phil Edworthy wrote:
> >> > The DesignWare GPIO IP can be configured for either 1 or 32
> >> > interrupts,
> >>
> >> 1 to 32, or just a choice between two?
> > Just a choice of 1 or 32.
> > Note that by 'configured' I am talking about the hardware being
> > configured in RTL prior to manufacturing a device. Once made, you cannot
> change it.
> > This configuration affects the number of output interrupt signals from
> > the GPIO Controller block that are connected to an interrupt controller.
> 
> Differentiating between different versions of an IP block using DT properties
> is usually a bad idea, for several reasons:
>   - What if you discover another difference later?
>   - You cannot add differentiating properties retroactively, because of
> backwards
>  compatibility with old DTBS.
> 
> Hence I think you should introduce a new compatible value instead.

This is not a different version of the IP, just a different configuration 
option.
Most IP blocks have a huge number of knobs that can be twiddled by the HW
people, such as cache size, UART fifo depth. I think this is no different.

Thanks
Phil



RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-04-05 Thread Phil Edworthy
Hi Andy,

On 30 March 2018 22:26 Andy Shevchenko wrote:
> On Wed, Mar 28, 2018 at 5:22 PM, Phil Edworthy wrote:
> > The DesignWare GPIO IP can be configured for either 1 or 32
> > interrupts,
> 
> 1 to 32, or just a choice between two?
Just a choice of 1 or 32.
Note that by 'configured' I am talking about the hardware being configured in
RTL prior to manufacturing a device. Once made, you cannot change it.
This configuration affects the number of output interrupt signals from the GPIO
Controller block that are connected to an interrupt controller.

> > but the driver currently only supports 1 interrupt. See the DesignWare
> > DW_apb_gpio Databook description of the 'GPIO_INTR_IO' parameter.
> 
> Will see after holiday and perhaps make more comments. Here is just a brief
> review.
> 
> > +- interrupts : The interrupts to the parent controller raised when
> > +GPIOs
> > +  generate the interrupts. If the controller provides one combined
> > +interrupt
> > +  for all GPIOs, specify a single interrupt. If the controller
> > +provides one
> > +  interrupt for each GPIO, provide a list of interrupts that
> > +correspond to each
> > +  of the GPIO pins. When specifying multiple interrupts, if any of
> > +the GPIOs are
> > +  not connected to an interrupt, use the interrupt-mask property.
> > +- interrupt-mask : a 32-bit bit mask that specifies which interrupts
> > +in the list
> > +  of interrupts is valid, bit is 1 for a valid irq.
> 
> So, but why one will need that in practice? GPIO driver usually provides a pin
> based IRQ chip which maps each pin to the corresponding offset inside
> specific IRQ domain.
On an ARM device we have this GPIO block connected to the GIC interrupt
controller, i.e. the Synopsys GPIO controller interrupts can* have a 1 to 1
mapping to the GIC interrupts. At the moment, the GPIO driver only allows a
single irq signal to specified.
* this is not strictly accurate on the device I am working on, there is another
block of IP between the two, but that doesn't matter in this case.

> > +   struct device_node *np = to_of_node(fwnode);
> > +   u32 irq_mask = 0x;
> 
> Why? Shouldn't it be dependent to the amount of actual pins / ports?
> Intel Quark has only 8 AFAIR.
It's just a default which can be overridden via device tree.
For Quark, since you currently only use a single irq, I guess the HW was
configured that way. In which case, you wouldn't use any of this.

> > +   int j;
> > +
> > +   /* Optional irq mask */
> > +   fwnode_property_read_u32(fwnode,
> > + "interrupt-mask", &irq_mask);
> > +
> > +   /*
> > +* The IP has configuration options to allow a 
> > single
> > +* combined interrupt or one per gpio. If one per 
> > gpio,
> > +* some might not be used.
> > +*/
> 
> > +   for (j = 0; j < pp->ngpio; j++) {
> > +   if (irq_mask & BIT(j)) {
> 
> for_each_set_bit() is in kernel for ages!
There's lot of stuff in the kernel for ages that I can't remember!
I'll fix this :)

> > +   pp->irq[j] = 
> > irq_of_parse_and_map(np, j);
> > +   if (pp->irq[j])
> > +   pp->has_irq = true;
> > +   }
> > +   }
> 
> 
> So, on the first glance the patch looks either superfluous or taking wrong
> approach. Please, elaborate more why it's done in this way and what the
> case for all this in practice.
Hopefully I have explained it a bit better above.

Thanks for your comments
Phil


RE: [PATCH] gpio: dwapb: Add support for 32 interrupts

2018-03-29 Thread Phil Edworthy
Hi,

On 28 March 2018 15:23, Phil Edworthy wrote:
> The DesignWare GPIO IP can be configured for either 1 or 32 interrupts,
> but the driver currently only supports 1 interrupt. See the DesignWare
> DW_apb_gpio Databook description of the 'GPIO_INTR_IO' parameter.
> 
> This change allows the driver to work with up to 32 interrupts, it will
> get as many interrupts as specified in the DT 'interrupts' property.
> It doesn't do anything clever with the different interrupts, it just calls
> the same handler used for single interrupt hardware.
> 
> Signed-off-by: Phil Edworthy 
> ---
> Note: There are a few lines over 80 chars, but this is just guidance, right?
>   Especially as there are already some lines over 80 chars.
> ---
>  .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   | 10 -
>  drivers/gpio/gpio-dwapb.c  | 44 
> +-
>  include/linux/platform_data/gpio-dwapb.h   |  3 +-
>  3 files changed, 45 insertions(+), 12 deletions(-)

This patch triggers a build error for Quark MFD driver, which is the only user
of the structure outside of the driver. I will fix that with an additional 
patch,
but I'll wait to see what other comments I get first.

Thanks
Phil


> diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> index 4a75da7..e343581 100644
> --- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> +++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> @@ -26,8 +26,14 @@ controller.
>the second encodes the triger flags encoded as described in
>Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
>  - interrupt-parent : The parent interrupt controller.
> -- interrupts : The interrupt to the parent controller raised when GPIOs
> -  generate the interrupts.
> +- interrupts : The interrupts to the parent controller raised when GPIOs
> +  generate the interrupts. If the controller provides one combined interrupt
> +  for all GPIOs, specify a single interrupt. If the controller provides one
> +  interrupt for each GPIO, provide a list of interrupts that correspond to 
> each
> +  of the GPIO pins. When specifying multiple interrupts, if any of the GPIOs
> are
> +  not connected to an interrupt, use the interrupt-mask property.
> +- interrupt-mask : a 32-bit bit mask that specifies which interrupts in the 
> list
> +  of interrupts is valid, bit is 1 for a valid irq.
>  - snps,nr-gpios : The number of pins in the port, a single cell.
>  - resets : Reset line for the controller.
> 
> diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
> index 226977f..47d82f9 100644
> --- a/drivers/gpio/gpio-dwapb.c
> +++ b/drivers/gpio/gpio-dwapb.c
> @@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct
> dwapb_gpio *gpio,
>   irq_gc->chip_types[1].handler = handle_edge_irq;
> 
>   if (!pp->irq_shared) {
> - irq_set_chained_handler_and_data(pp->irq,
> dwapb_irq_handler,
> -  gpio);
> + int i;
> +
> + for (i = 0; i < pp->ngpio; i++) {
> + if (pp->irq[i])
> + irq_set_chained_handler_and_data(pp-
> >irq[i],
> + dwapb_irq_handler, gpio);
> + }
>   } else {
>   /*
>* Request a shared IRQ since where MFD would have
> devices
>* using the same irq pin
>*/
> - err = devm_request_irq(gpio->dev, pp->irq,
> + err = devm_request_irq(gpio->dev, pp->irq[0],
>  dwapb_irq_handler_mfd,
>  IRQF_SHARED, "gpio-dwapb-mfd", gpio);
>   if (err) {
> @@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio
> *gpio,
>   if (pp->idx == 0)
>   port->gc.set_config = dwapb_gpio_set_config;
> 
> - if (pp->irq)
> + if (pp->has_irq)
>   dwapb_configure_irqs(gpio, port, pp);
> 
>   err = gpiochip_add_data(&port->gc, port);
> @@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio
> *gpio,
>   port->is_registered = true;
> 
>   /* Add GPIO-signaled ACPI event support */
> - if (pp->irq)
> + if (pp->has_irq)
>   acpi_gpiochip_request_interrupts(&port->gc);
> 
>   return err;
> @@ -601,13 +606,34 @@ dwapb_gpio_get_pdata(struct device *dev)
>   if (dev->of_node && pp->id

[PATCH] gpio: dwapb: Add support for 32 interrupts

2018-03-28 Thread Phil Edworthy
The DesignWare GPIO IP can be configured for either 1 or 32 interrupts,
but the driver currently only supports 1 interrupt. See the DesignWare
DW_apb_gpio Databook description of the 'GPIO_INTR_IO' parameter.

This change allows the driver to work with up to 32 interrupts, it will
get as many interrupts as specified in the DT 'interrupts' property.
It doesn't do anything clever with the different interrupts, it just calls
the same handler used for single interrupt hardware.

Signed-off-by: Phil Edworthy 
---
Note: There are a few lines over 80 chars, but this is just guidance, right?
  Especially as there are already some lines over 80 chars.
---
 .../devicetree/bindings/gpio/snps-dwapb-gpio.txt   | 10 -
 drivers/gpio/gpio-dwapb.c  | 44 +-
 include/linux/platform_data/gpio-dwapb.h   |  3 +-
 3 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt 
b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
index 4a75da7..e343581 100644
--- a/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
@@ -26,8 +26,14 @@ controller.
   the second encodes the triger flags encoded as described in
   Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 - interrupt-parent : The parent interrupt controller.
-- interrupts : The interrupt to the parent controller raised when GPIOs
-  generate the interrupts.
+- interrupts : The interrupts to the parent controller raised when GPIOs
+  generate the interrupts. If the controller provides one combined interrupt
+  for all GPIOs, specify a single interrupt. If the controller provides one
+  interrupt for each GPIO, provide a list of interrupts that correspond to each
+  of the GPIO pins. When specifying multiple interrupts, if any of the GPIOs 
are
+  not connected to an interrupt, use the interrupt-mask property.
+- interrupt-mask : a 32-bit bit mask that specifies which interrupts in the 
list
+  of interrupts is valid, bit is 1 for a valid irq.
 - snps,nr-gpios : The number of pins in the port, a single cell.
 - resets : Reset line for the controller.
 
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 226977f..47d82f9 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -441,14 +441,19 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
irq_gc->chip_types[1].handler = handle_edge_irq;
 
if (!pp->irq_shared) {
-   irq_set_chained_handler_and_data(pp->irq, dwapb_irq_handler,
-gpio);
+   int i;
+
+   for (i = 0; i < pp->ngpio; i++) {
+   if (pp->irq[i])
+   irq_set_chained_handler_and_data(pp->irq[i],
+   dwapb_irq_handler, gpio);
+   }
} else {
/*
 * Request a shared IRQ since where MFD would have devices
 * using the same irq pin
 */
-   err = devm_request_irq(gpio->dev, pp->irq,
+   err = devm_request_irq(gpio->dev, pp->irq[0],
   dwapb_irq_handler_mfd,
   IRQF_SHARED, "gpio-dwapb-mfd", gpio);
if (err) {
@@ -524,7 +529,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
 
-   if (pp->irq)
+   if (pp->has_irq)
dwapb_configure_irqs(gpio, port, pp);
 
err = gpiochip_add_data(&port->gc, port);
@@ -535,7 +540,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->is_registered = true;
 
/* Add GPIO-signaled ACPI event support */
-   if (pp->irq)
+   if (pp->has_irq)
acpi_gpiochip_request_interrupts(&port->gc);
 
return err;
@@ -601,13 +606,34 @@ dwapb_gpio_get_pdata(struct device *dev)
if (dev->of_node && pp->idx == 0 &&
fwnode_property_read_bool(fwnode,
  "interrupt-controller")) {
-   pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0);
-   if (!pp->irq)
+   struct device_node *np = to_of_node(fwnode);
+   u32 irq_mask = 0x;
+   int j;
+
+   /* Optional irq mask */
+   fwnode_property_read_u32(fwnode, "interrupt-mask", 
&irq_mask);
+
+   /*
+* The IP has configuration 

RE: [PATCH v2] gpio: dwapb: Add support for a bus clock

2018-03-13 Thread Phil Edworthy
Hi Andy,

On 13 March 2018 16:36, Andy Shevchenko wrote:
> On Mon, Mar 12, 2018 at 8:30 PM, Phil Edworthy
>  wrote:
> > Enable an optional bus clock provided by DT.
> 
> FWIW,
> Reviewed-by: Andy Shevchenko 
Thanks!
 
> (Assuming it has been tested on clock-less cases)
I hacked together a test where the bus clock for the device I have
is always on, and the clock for this driver is not present in the DTB.
Whilst not ideal, it does test the clock-less case.

Thanks
Phil
 
> > Signed-off-by: Phil Edworthy 
> > ---
> > v2:
> >  - Fix include order.
> >  - Use a clock name.
> >  - Check errors from clk_prepare_enable()
> >  - Add calls to enable/disable the clock in PM
> > ---
> >  drivers/gpio/gpio-dwapb.c | 20 +++-
> >  1 file changed, 19 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
> > index b0704a8..226977f 100644
> > --- a/drivers/gpio/gpio-dwapb.c
> > +++ b/drivers/gpio/gpio-dwapb.c
> > @@ -8,8 +8,9 @@
> >   * All enquiries to supp...@picochip.com
> >   */
> >  #include 
> > -#include 
> > +#include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -98,6 +99,7 @@ struct dwapb_gpio {
> > struct irq_domain   *domain;
> > unsigned intflags;
> > struct reset_control*rst;
> > +   struct clk  *clk;
> >  };
> >
> >  static inline u32 gpio_reg_v2_convert(unsigned int offset) @@ -670,6
> > +672,16 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
> > if (IS_ERR(gpio->regs))
> > return PTR_ERR(gpio->regs);
> >
> > +   /* Optional bus clock */
> > +   gpio->clk = devm_clk_get(&pdev->dev, "bus");
> > +   if (!IS_ERR(gpio->clk)) {
> > +   err = clk_prepare_enable(gpio->clk);
> > +   if (err) {
> > +   dev_info(&pdev->dev, "Cannot enable clock\n");
> > +   return err;
> > +   }
> > +   }
> > +
> > gpio->flags = 0;
> > if (dev->of_node) {
> > const struct of_device_id *of_devid; @@ -712,6 +724,7
> > @@ static int dwapb_gpio_remove(struct platform_device *pdev)
> > dwapb_gpio_unregister(gpio);
> > dwapb_irq_teardown(gpio);
> > reset_control_assert(gpio->rst);
> > +   clk_disable_unprepare(gpio->clk);
> >
> > return 0;
> >  }
> > @@ -757,6 +770,8 @@ static int dwapb_gpio_suspend(struct device *dev)
> > }
> > spin_unlock_irqrestore(&gc->bgpio_lock, flags);
> >
> > +   clk_disable_unprepare(gpio->clk);
> > +
> > return 0;
> >  }
> >
> > @@ -768,6 +783,9 @@ static int dwapb_gpio_resume(struct device *dev)
> > unsigned long flags;
> > int i;
> >
> > +   if (!IS_ERR(gpio->clk))
> > +   clk_prepare_enable(gpio->clk);
> > +
> > spin_lock_irqsave(&gc->bgpio_lock, flags);
> > for (i = 0; i < gpio->nr_ports; i++) {
> > unsigned int offset;
> > --
> > 2.7.4
> >
> 
> 
> 
> --
> With Best Regards,
> Andy Shevchenko


[PATCH v2] mmc: sdhci-of-arasan: Add quirk to avoid unexpected interrupt msgs

2018-03-13 Thread Phil Edworthy
On SD 2.00 cards we get lots of these messages:
"mmc0: Got data interrupt 0x0002 even though no data operation was in 
progress"
By applying the SDHCI_QUIRK2_STOP_WITH_TC quirk, the messages no longer happen.

A single card claiming to be SD 3.00 compliant also generates the interrupts,
but since the card's manfacturing date is 2002 mar, it's unlikely to really be
SD 3.00. This card is a 8GB SanDisk 'SU08G' 8.0 (SDHC class 4).

This has been reported on Xilinx devices that also use the Arasan IP.
See https://patchwork.kernel.org/patch/8062871/

This has been tested on the Renesas RZ/ND-DB board with the RZ/N1 SoC. The
Arasan IP in this device is version 1.39a and uses a max SD clock of 50MHz and
does not support DDR modes.

Signed-off-by: Phil Edworthy 
---
v2:
 - Changed commit msg to detail the cards that fail.
 - Provided the IP version and further background info.
---
 drivers/mmc/host/sdhci-of-arasan.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c 
b/drivers/mmc/host/sdhci-of-arasan.c
index c33a5f7..ab66e32 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -290,7 +290,8 @@ static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
.ops = &sdhci_arasan_ops,
.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
-   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
+   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
+   SDHCI_QUIRK2_STOP_WITH_TC,
 };
 
 static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
-- 
2.7.4



[PATCH v2] gpio: dwapb: Add support for a bus clock

2018-03-12 Thread Phil Edworthy
Enable an optional bus clock provided by DT.

Signed-off-by: Phil Edworthy 
---
v2:
 - Fix include order.
 - Use a clock name.
 - Check errors from clk_prepare_enable()
 - Add calls to enable/disable the clock in PM
---
 drivers/gpio/gpio-dwapb.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index b0704a8..226977f 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -8,8 +8,9 @@
  * All enquiries to supp...@picochip.com
  */
 #include 
-#include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -98,6 +99,7 @@ struct dwapb_gpio {
struct irq_domain   *domain;
unsigned intflags;
struct reset_control*rst;
+   struct clk  *clk;
 };
 
 static inline u32 gpio_reg_v2_convert(unsigned int offset)
@@ -670,6 +672,16 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs);
 
+   /* Optional bus clock */
+   gpio->clk = devm_clk_get(&pdev->dev, "bus");
+   if (!IS_ERR(gpio->clk)) {
+   err = clk_prepare_enable(gpio->clk);
+   if (err) {
+   dev_info(&pdev->dev, "Cannot enable clock\n");
+   return err;
+   }
+   }
+
gpio->flags = 0;
if (dev->of_node) {
const struct of_device_id *of_devid;
@@ -712,6 +724,7 @@ static int dwapb_gpio_remove(struct platform_device *pdev)
dwapb_gpio_unregister(gpio);
dwapb_irq_teardown(gpio);
reset_control_assert(gpio->rst);
+   clk_disable_unprepare(gpio->clk);
 
return 0;
 }
@@ -757,6 +770,8 @@ static int dwapb_gpio_suspend(struct device *dev)
}
spin_unlock_irqrestore(&gc->bgpio_lock, flags);
 
+   clk_disable_unprepare(gpio->clk);
+
return 0;
 }
 
@@ -768,6 +783,9 @@ static int dwapb_gpio_resume(struct device *dev)
unsigned long flags;
int i;
 
+   if (!IS_ERR(gpio->clk))
+   clk_prepare_enable(gpio->clk);
+
spin_lock_irqsave(&gc->bgpio_lock, flags);
for (i = 0; i < gpio->nr_ports; i++) {
unsigned int offset;
-- 
2.7.4



[PATCH] gpio: dwapb: Add support for a bus clock

2018-03-09 Thread Phil Edworthy
From: Michel Pollet 

Enable specified clocks from DTS, if any.

Signed-off-by: Michel Pollet 
---
 drivers/gpio/gpio-dwapb.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index b0704a8..56c58b5 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "gpiolib.h"
 
@@ -637,6 +638,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
int err;
struct device *dev = &pdev->dev;
struct dwapb_platform_data *pdata = dev_get_platdata(dev);
+   struct clk *clk;
 
if (!pdata) {
pdata = dwapb_gpio_get_pdata(dev);
@@ -670,6 +672,10 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs);
 
+   clk = devm_clk_get(&pdev->dev, NULL);
+   if (!IS_ERR(clk) && clk_prepare_enable(clk))
+   dev_info(&pdev->dev, "no clock source\n");
+
gpio->flags = 0;
if (dev->of_node) {
const struct of_device_id *of_devid;
-- 
2.7.4



RE: [PATCH] mmc: sdhci-of-arasan: Add quirk to avoid erroneous msg

2018-03-05 Thread Phil Edworthy
Hi Shawn,

On 28 February 2018 01:53, Shawn Lin wrote:
> On 2018/2/27 23:05, Phil Edworthy wrote:
> > On 27 February 2018 14:42, Shawn Lin wrote:
> >> On 2018/2/27 22:31, Phil Edworthy wrote:
> >>> On 27 February 2018 14:28, Shawn Lin wrote:
> >>>> 在 2018/2/27 21:55, Phil Edworthy 写道:
> >>>>> Since the controller does not support the end-of-busy IRQ, don't use
> it.
> >>>>> Otherwise, on older SD cards you will get lots of these messages:
> >>>>> "mmc0: Got data interrupt 0x0002 even though no data operation
> >>>>> was
> >>>> in progress"
> >>>>>
> >>>>
> >>>> I'm afraid you have to explain which version of arasan's IP suffer
> >>>> from this and what does the "older SD cards" mean?
> >>> Ok, I'll try to find out the IP version...
> >>> For "older SD cards", I can provide a list of a few cards that
> >>> exhibit this problem and others that don't, is that enough info?
> >>
> >> What I meant is could you elaborate more about what kind of cards,
> >> e.g, are them the  legacy SDSC cards or SDHC cards, or maybe they are
> >> only running with defaut speed? or whatever, but not just with a
> >> vague "older" cards. :)
> > Unfortunately, I have one SDHC card that works, one that doesn't. Both
> > cards are running with a 50MHz SD clock. All I know is this:
> 
> Thanks for sharing these, though it looks wired as I never remember I saw
> this problem when extensively tested SD cards on one of arasan controllers
> in 2014.
Not sure what you mean by 'wired'?

Note that this is on a relatively slow device, a dual core Cortex A7 @500MHz.
Maybe that has some effect.

It's also interesting that someone posted the same fix for Xilinx a while
back, I linked to it in the commit msg.

Thanks
Phil


> > SD cards that report unexpected interrupts:
> > 2GB Sandisk Extreme III (e624 SD02G 1.89 GiB)
> > 8GB Sandisk (SDHC class 4)  ( SU08G 7.40 GiB)
> > 8GB Sandisk Extreme III (SDHC class 6)(bb4e SD08G 7.61 GiB)
> >
> > SD cards that work ok:
> > 16GB Samsung (microSDHC U1 class 10)  (0001 0 14.6 GiB)
> > 16GB Sandisk Ultra (microSDHC U1 class 10)( SL16G 14.8 GiB)
> > 32GB Sandisk Ultra (microSDHC U1 class 10)( SL32G 29.7 GiB)
> >
> > Thanks
> > Phil
> >
> >>>>> This has been reported on Xilinx devices that also use the Arasan IP.
> >>>>> See https://patchwork.kernel.org/patch/8062871/
> >>>>>
> >>>>> This has been tested on the Renesas RZ/ND-DB board with the RZ/N1
> >> SoC.
> >>>>>
> >>>>> Signed-off-by: Phil Edworthy 
> >>>>> ---
> >>>>> drivers/mmc/host/sdhci-of-arasan.c | 3 ++-
> >>>>> 1 file changed, 2 insertions(+), 1 deletion(-)
> >>>>>
> >>>>> diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> >>>>> b/drivers/mmc/host/sdhci-of-arasan.c
> >>>>> index c33a5f7..ab66e32 100644
> >>>>> --- a/drivers/mmc/host/sdhci-of-arasan.c
> >>>>> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> >>>>> @@ -290,7 +290,8 @@ static const struct sdhci_pltfm_data
> >>>> sdhci_arasan_pdata = {
> >>>>> .ops = &sdhci_arasan_ops,
> >>>>> .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> >>>>> .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
> >>>>> -   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
> >>>>> +   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN
> |
> >>>>> +   SDHCI_QUIRK2_STOP_WITH_TC,
> >>>>> };
> >>>>>
> >>>>> static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32
> >>>>> intmask)
> >>>>>
> >>>>
> >>>>
> >>>> --
> >>>> Best Regards
> >>>> Shawn Lin
> >>>
> >>>
> >>>
> >>>
> >>
> >>
> >> --
> >> Best Regards
> >> Shawn Lin
> >
> >
> >
> >



RE: [PATCH] mmc: sdhci-of-arasan: Add quirk to avoid erroneous msg

2018-02-27 Thread Phil Edworthy
Hi Shawn,

On 27 February 2018 14:42, Shawn Lin wrote:
> On 2018/2/27 22:31, Phil Edworthy wrote:
> > Hi Shawn,
> >
> > On 27 February 2018 14:28, Shawn Lin wrote:
> >> 在 2018/2/27 21:55, Phil Edworthy 写道:
> >>> Since the controller does not support the end-of-busy IRQ, don't use it.
> >>> Otherwise, on older SD cards you will get lots of these messages:
> >>> "mmc0: Got data interrupt 0x0002 even though no data operation
> >>> was
> >> in progress"
> >>>
> >>
> >> I'm afraid you have to explain which version of arasan's IP suffer
> >> from this and what does the "older SD cards" mean?
> > Ok, I'll try to find out the IP version...
> > For "older SD cards", I can provide a list of a few cards that exhibit
> > this problem and others that don't, is that enough info?
> 
> What I meant is could you elaborate more about what kind of cards, e.g, are
> them the  legacy SDSC cards or SDHC cards, or maybe they are only running
> with defaut speed? or whatever, but not just with a vague "older" cards. :)
Unfortunately, I have one SDHC card that works, one that doesn't. Both cards
are running with a 50MHz SD clock. All I know is this:

SD cards that report unexpected interrupts:
2GB Sandisk Extreme III (e624 SD02G 1.89 GiB)
8GB Sandisk (SDHC class 4)  ( SU08G 7.40 GiB)
8GB Sandisk Extreme III (SDHC class 6)(bb4e SD08G 7.61 GiB)

SD cards that work ok:
16GB Samsung (microSDHC U1 class 10)  (0001 0 14.6 GiB)
16GB Sandisk Ultra (microSDHC U1 class 10)( SL16G 14.8 GiB)
32GB Sandisk Ultra (microSDHC U1 class 10)( SL32G 29.7 GiB)

Thanks
Phil

> >>> This has been reported on Xilinx devices that also use the Arasan IP.
> >>> See https://patchwork.kernel.org/patch/8062871/
> >>>
> >>> This has been tested on the Renesas RZ/ND-DB board with the RZ/N1
> SoC.
> >>>
> >>> Signed-off-by: Phil Edworthy 
> >>> ---
> >>>drivers/mmc/host/sdhci-of-arasan.c | 3 ++-
> >>>1 file changed, 2 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> >>> b/drivers/mmc/host/sdhci-of-arasan.c
> >>> index c33a5f7..ab66e32 100644
> >>> --- a/drivers/mmc/host/sdhci-of-arasan.c
> >>> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> >>> @@ -290,7 +290,8 @@ static const struct sdhci_pltfm_data
> >> sdhci_arasan_pdata = {
> >>>   .ops = &sdhci_arasan_ops,
> >>>   .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> >>>   .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
> >>> - SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
> >>> + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
> >>> + SDHCI_QUIRK2_STOP_WITH_TC,
> >>>};
> >>>
> >>>static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32
> >>> intmask)
> >>>
> >>
> >>
> >> --
> >> Best Regards
> >> Shawn Lin
> >
> >
> >
> >
> 
> 
> --
> Best Regards
> Shawn Lin



RE: [PATCH] mmc: sdhci-of-arasan: Add quirk to avoid erroneous msg

2018-02-27 Thread Phil Edworthy
Hi Shawn,

On 27 February 2018 14:28, Shawn Lin wrote:
> 在 2018/2/27 21:55, Phil Edworthy 写道:
> > Since the controller does not support the end-of-busy IRQ, don't use it.
> > Otherwise, on older SD cards you will get lots of these messages:
> > "mmc0: Got data interrupt 0x0002 even though no data operation was
> in progress"
> >
> 
> I'm afraid you have to explain which version of arasan's IP suffer from this
> and what does the "older SD cards" mean?
Ok, I'll try to find out the IP version...
For "older SD cards", I can provide a list of a few cards that exhibit this 
problem
and others that don't, is that enough info?

Thanks
Phil

> > This has been reported on Xilinx devices that also use the Arasan IP.
> > See https://patchwork.kernel.org/patch/8062871/
> >
> > This has been tested on the Renesas RZ/ND-DB board with the RZ/N1 SoC.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> >   drivers/mmc/host/sdhci-of-arasan.c | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> > b/drivers/mmc/host/sdhci-of-arasan.c
> > index c33a5f7..ab66e32 100644
> > --- a/drivers/mmc/host/sdhci-of-arasan.c
> > +++ b/drivers/mmc/host/sdhci-of-arasan.c
> > @@ -290,7 +290,8 @@ static const struct sdhci_pltfm_data
> sdhci_arasan_pdata = {
> > .ops = &sdhci_arasan_ops,
> > .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> > .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
> > -   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
> > +   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
> > +   SDHCI_QUIRK2_STOP_WITH_TC,
> >   };
> >
> >   static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32
> > intmask)
> >
> 
> 
> --
> Best Regards
> Shawn Lin



RE: [PATCH] mmc: sdhci-of-arasan: Add quirk to avoid erroneous msg

2018-02-27 Thread Phil Edworthy
Hi Adrian,

On 27 February 2018 14:08, Adrian Hunter wrote:
> On 27/02/18 15:55, Phil Edworthy wrote:
> > Since the controller does not support the end-of-busy IRQ, don't use it.
> > Otherwise, on older SD cards you will get lots of these messages:
> > "mmc0: Got data interrupt 0x0002 even though no data operation was
> in progress"
> 
> SDHCI_QUIRK2_STOP_WITH_TC may be the quirk you want but it doesn't
> match your description.  SDHCI_QUIRK2_STOP_WITH_TC is when we always
> get a TC
> (end-of-busy) IRQ with the STOP command even when we didn't ask for
> one.
> Hence the TC interrupt (0x0002) comes when we think we are already
> finished.
Right, thanks for clarifying, I'll fixup the message.

> >
> > This has been reported on Xilinx devices that also use the Arasan IP.
> > See https://patchwork.kernel.org/patch/8062871/
> >
> > This has been tested on the Renesas RZ/ND-DB board with the RZ/N1 SoC.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> >  drivers/mmc/host/sdhci-of-arasan.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/host/sdhci-of-arasan.c
> > b/drivers/mmc/host/sdhci-of-arasan.c
> > index c33a5f7..ab66e32 100644
> > --- a/drivers/mmc/host/sdhci-of-arasan.c
> > +++ b/drivers/mmc/host/sdhci-of-arasan.c
> > @@ -290,7 +290,8 @@ static const struct sdhci_pltfm_data
> sdhci_arasan_pdata = {
> > .ops = &sdhci_arasan_ops,
> > .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> > .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
> > -   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
> > +   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
> > +   SDHCI_QUIRK2_STOP_WITH_TC,
> >  };
> >
> >  static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32
> > intmask)
> >



[PATCH] mmc: sdhci-of-arasan: Add quirk to avoid erroneous msg

2018-02-27 Thread Phil Edworthy
Since the controller does not support the end-of-busy IRQ, don't use it.
Otherwise, on older SD cards you will get lots of these messages:
"mmc0: Got data interrupt 0x0002 even though no data operation was in 
progress"

This has been reported on Xilinx devices that also use the Arasan IP.
See https://patchwork.kernel.org/patch/8062871/

This has been tested on the Renesas RZ/ND-DB board with the RZ/N1 SoC.

Signed-off-by: Phil Edworthy 
---
 drivers/mmc/host/sdhci-of-arasan.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c 
b/drivers/mmc/host/sdhci-of-arasan.c
index c33a5f7..ab66e32 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -290,7 +290,8 @@ static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
.ops = &sdhci_arasan_ops,
.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
-   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
+   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
+   SDHCI_QUIRK2_STOP_WITH_TC,
 };
 
 static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
-- 
2.7.4



RE: [PATCH 0/2] arm: Support for Renesas RZ/N1D (R9A06G032)

2018-02-27 Thread Phil Edworthy
Hi Simon,

On 26 February 2018, Michel Pollet wrote:
> 
> This series adds the plain basic support for booting a bare
> kernel on the RZ/N1D-DB Board. It's been trimmed to the strict
> minimum as a 'base', further patches that will add the
> rest of the support, pinctrl, clock architecture and quite
> a few others.
I spoke to Magnus about helping to get the RZ/N1 patches upstream.
We're trying to sort out making the device manual and board schematics
available, hopefully it won't take too long. We're also trying to sort out
access to a board... that might take a bit longer.

btw, what do you want to do about shmobile_defconfig? Should we add
any changes needed for RZ/N1 to it? Note that only one IP block is the
same as R-Car.

Thanks
Phil


RE: [PATCH] ARM: dts: r8a7791: Don't disable referenced optional clocks

2016-04-08 Thread Phil Edworthy
Hi,

On 07 April 2016 20:14, Sergei Shtylyov wrote:
> On 04/07/2016 10:00 AM, Sjoerd Simons wrote:
> 
> > Hey Sergei,
> >
> > Thanks for your review.
> 
> You're welcome. :-)
> 
> > On Thu, 2016-04-07 at 02:15 +0300, Sergei Shtylyov wrote:
> >> On 04/06/2016 03:52 PM, Sjoerd Simons wrote:
> >>
> >>>
> >>> clk_get on a disabled clock node will return EPROBE_DEFER, which
> >>> can
> >>> cause drivers to be deferred forever if such clocks are referenced
> >>> in
> >>> their clocks property.
> >>>
> >>> Update the various disabled external clock nodes to default to a
> >>> frequency of 0, but don't disable them to prevent this.
> >>>
> >>> Signed-off-by: Sjoerd Simons 
> >>>
> >>> ---
> >>>
> >>>arch/arm/boot/dts/r8a7791-koelsch.dts | 1 +
> >>>arch/arm/boot/dts/r8a7791-porter.dts  | 1 +
> >>>arch/arm/boot/dts/r8a7791.dtsi| 5 +
> >>>3 files changed, 3 insertions(+), 4 deletions(-)
> >>>
> >>> diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts
> >>> b/arch/arm/boot/dts/r8a7791-koelsch.dts
> >>> index 1adf877..da59c28 100644
> >>> --- a/arch/arm/boot/dts/r8a7791-koelsch.dts
> >>> +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
> >>> @@ -660,6 +660,7 @@
> >>>};
> >>>
> >>>&pcie_bus_clk {
> >>> + clock-frequency = <1>;
> 
> >>  Hmmm, looking at the Koelsch schematics, I don't see this clock.
> >> :-/
> >
> > I don't have the schematics so i was simply keeping the current state.
> 
> I understand. I was just surprised by what checking the code against the
> schematics revealed.
> 
> > I've added Phil Edworthy to the list as he was the one originally
> 
> I should've CC'ed Phil myself...
>
> > enable the bus clk for Koelsh according to git. Hopefully he can
> > clarify :)
> 
> Let's hope he'd reply...
> 
> >>>   status = "okay";
> >>>};
> >>>
> >>> diff --git a/arch/arm/boot/dts/r8a7791-porter.dts
> >>> b/arch/arm/boot/dts/r8a7791-porter.dts
> >>> index 9554d13..19b257e 100644
> >>> --- a/arch/arm/boot/dts/r8a7791-porter.dts
> >>> +++ b/arch/arm/boot/dts/r8a7791-porter.dts
> >>> @@ -413,6 +413,7 @@
> >>>};
> >>>
> >>>&pcie_bus_clk {
> >>> + clock-frequency = <1>;
> >>>   status = "okay";
> >>>};
> >>>
> >>  Again, looking at the Porter schematics, I don't see this clock
> >> either. :-/
> >
> > You were the one enabling this clock for Porter ;) I don't have PCIE
> 
> Yes, of course. I don't remember the gory details already -- I might have
> blindly copied what was in the Koelsch's .dts.
> 
> > hardware to test with on my porter board, might be worth if you could
> > disable this clock and see if PCI-E still fucntions as expected (maybe
> > in practise it just happens to prefer the internal clock?) ?
> 
> I know the PCIe driver does require this clock in order to function -- it
> would be the same eternal -EPROBE_DEFER condition you'd already described;
> see drivers/pci/host/pcie-rcar.c yourself...
> 
> >>> diff --git a/arch/arm/boot/dts/r8a7791.dtsi
> >>> b/arch/arm/boot/dts/r8a7791.dtsi
> >>> index 8693888..676df63 100644
> >>> --- a/arch/arm/boot/dts/r8a7791.dtsi
> >>> +++ b/arch/arm/boot/dts/r8a7791.dtsi
> >>> @@ -1104,8 +1104,7 @@
> >>>   pcie_bus_clk: pcie_bus {
> >>>   compatible = "fixed-clock";
> >>>   #clock-cells = <0>;
> >>> - clock-frequency = <1>;
> >>> - status = "disabled";
> >>> + clock-frequency = <0>;
> >>  If the clock has a good default frequency, I don't think you need
> >> to
> >> remove it. Otherwise you missed USB_EXTAL which is 48 MHz (and can be
> >> overridden).
> >
> > I did that as it was by default disabled, so if i do enable it but
> > don't drop the default frequency to 0 board swithout that clock will
> > suddenly have it added to their dtb.
> 
> Zero frequency is hardly any better then the default...
> 
> > For the usb external clock I didn't touch it as it was already enabled
> > by default with a proper frequency, so it wouldn't hit the issue i was
> > trying to fix here. But i agree, both looking at other Renesas dtsis
> > and how all other external clocks are done in this dtsi, this node is
> > odd.
> 
> It's not that odd given that the R-Car gen2 manual specifically says it
> should be 48 MHz.
> Looking into the manual again, the PCIe bus clock must be the onne
> presented on the CICREF[PN]1_SATA/PCIe input signals and it indeed should be
> 100 MHz... So Phil was correct.

PCIe always requires a 100MHz reference clock. On Koelsch, this clock is
generated by U6 and always on. Some boards may need additional hardware
to be setup in order to output the clock, hence the DT node for the clock.

I hope that clarifies the situation!
Phil



  1   2   >