Thread (50 messages) 50 messages, 8 authors, 2021-10-19

Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs

From: Emil Renner Berthing <kernel@esmil.dk>
Date: 2021-10-13 17:37:34
Also in: linux-clk, linux-devicetree, linux-gpio, linux-riscv, lkml

On Wed, 13 Oct 2021 at 18:59, Andy Shevchenko [off-list ref] wrote:
On Wed, Oct 13, 2021 at 06:38:14PM +0200, Emil Renner Berthing wrote:
quoted
On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko [off-list ref] wrote:
quoted
On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing [off-list ref] wrote:
...
quoted
quoted
quoted
+free_pinmux:
+       devm_kfree(dev, pinmux);
+free_pins:
+       devm_kfree(dev, pins);
+free_grpname:
+       devm_kfree(dev, grpname);
What the heck?!
Just to be clear. You mean we don't need to explicitly free them
because they're tied to the device right? I don't think the device
will go away just because a single device tree entry can't be parsed,
so on such errors this garbage would be left behind. You can still
argue we shouldn't optimize for broken device trees, I just want to
make it at conscious decision.
If you are using devm_kfree() it is quite likely shows either of the following
issues:

* you mustn't use devm_*() in the first place due to object lifetime;
* you shouldn't use devm_kfree() since this is the whole point of devm.
Hmm.. it seems like other drivers that dynamically builds the groups
and functions either also uses devm_kcalloc/devm_kfree like fx.
pinctrl-single or implements their own code to clean up groups and
functions when unloaded. There are no group destroy or function
destroy callbacks. I like devm_kcalloc/devm_kfree version better since
it's less code to write.
quoted
quoted
quoted
+free_pgnames:
+       devm_kfree(dev, pgnames);
Ditto.
...
quoted
quoted
quoted
+out:
Useless label.
Hmm.. my compiler disagrees.
The comment implies that you return directly instead of using `goto out;`.
quoted
quoted
quoted
+       return ret;
...
quoted
quoted
quoted
+               v = pinmux[i];
+               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
+               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
+               din  = (v >> 8) & 0xffU;
What is this voodoo for?
In order to do pinmux we need the following pieces of information from
the device tree for each pin ("GPIO" they call it):

output signal: 0-133 + 1bit reverse flag
output enable signal: 0-133 + 1bit reverse flag
optional input signal: 0-74 + special "none" value, right now 0xff
gpio number: 0-63

As the code is now all that info is packed into a u32 for each pin
using the GPIOMUX macro defined in the dt-binding header added in
patch 10. There is also a diagram for how this packing is done. The
above voodoo is for unpacking that.

I'd very much like to hear if you have a better solution for how to
convey that information from the device tree to here.
At very least this code should have something like above in the comment.
Will add!
...
quoted
quoted
quoted
+               if (din != 0xff)
+                       reg_din = sfp->base + GPIO_IN_OFFSET + 4 * din;
+               else
+                       reg_din = NULL;
This looks like you maybe use gpio-regmap instead?
This was discussed at length when Drew sent in the GPIO part of this code:
https://lore.kernel.org/linux-riscv/20210701002037.912625-1-drew@beagleboard.org/ (local)
The conclusion was that because pinmux and controlling the pins from
software in GPIO mode uses the same registers it is better to do a
combined driver like this that can share the lock among other things.
And what does prevent exactly to base the GPIO part on gpio-regmap?
Other reasons are that gpio-regmap doesn't implement the .set_config
and .add_pin_ranges callbacks. add_pin_ranges is needed because the 64
GPIOs map to different pin numbers depending on the chosen "signal
group".
...
quoted
quoted
quoted
+static const unsigned char starfive_drive_strength[] = {
+       14, 21, 28, 35, 42, 49, 56, 63,
Why table? Can you simply use the formula?!
Heh, yeah. So these are rounded values from a table and I never
noticed that after rounding they follow a nice arithmetic progression.
It'll probably still be nice to have an explanation in the comments
about the formula then.
Yup!
quoted
quoted
quoted
+};
...
quoted
quoted
quoted
+               irq_set_handler_locked(d, handle_bad_irq);
Why is this here? Move it to ->probe().
My thinking was that if something tries to set a an unsupported irq
type, we should make sure the caller doesn't get spurious interrupts
because we left the handler at its old value.
You already assigned to this handler in the ->probe(), what's this then?
But userspace could fx. first request IRQ_TYPE_EDGE_BOTH through the
gpio api and later load a driver that might request an unsupported irq
type right? Or am I missing something.
...
quoted
quoted
quoted
+               if (value <= 6)
+                       writel(value, sfp->padctl + IO_PADSHARE_SEL);
+               else
quoted
+                       dev_err(dev, "invalid signal group %u\n", value);
Why _err if you not bail out here?
My thinking was that if the device tree specifies an invalid signal
group we should just leave the setting alone and not break booting,
but still be loud about it. Maybe that's too lenient and it's better
to crash and burn immediately if someone does that.
Here is inconsistency between level of the message and following action.
There are (rare!) cases when it's justified, but I believe it's not the
case here. You have two choices or justify why you have to use error
level without stopping process.

...

All uncommented stuff you agreed on, correct?
Yes, thank you! (.. or at least I'll get back to you if something comes up ;)
--
With Best Regards,
Andy Shevchenko



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help