[PATCH v4 2/2] pinctrl: Add driver for Sunplus SP7021
Wells Lu 呂芳騰
wells.lu at sunplus.com
Wed Dec 15 07:32:55 PST 2021
Hi Andy,
Thank you for answers and comments.
I'll modify code accordingly and will
send a new patch when ready.
Thanks,
Wells Lu
> ...
>
> > > > +/* SP7021 Pin Controller Driver.
> > > > + * Copyright (C) Sunplus Tech/Tibbo Tech.
> > > > + */
> > >
> > > This is wrong style for multi-line comments. Fix it everywhere accordingly.
> >
> > I'll modify all multi-line comments, for example, as shown below:
> >
> > /*
> > * SP7021 Pin Controller Driver.
> > * Copyright (C) Sunplus Tech/Tibbo Tech.
> > */
> >
> > Now, I realized that each subsystem has its own comment style.
>
> Actually there are only two styles:
> - this one (as updated version) for entire kernel with the exception of
> - net / network one (as you used originally)
>
> > > ...
> > >
> > > > +#include <linux/platform_device.h> #include
> > > > +<linux/pinctrl/pinmux.h> #include <linux/gpio/driver.h> #include
> > > > +<linux/module.h> #include <linux/bitfield.h>
> > >
> > > Keep them in order. Besides that it seems missed a few headers, such as of.h.
> >
> > I am not sure what order should I keep for inclusions.
> > Reversed x'mas tree order? Alphabetic order?
>
> Alphabetical. When you don't see a direct answer the rule of thumb is to go to the recent
> contributions and check a few new drivers to see how they are doing.
>
> > Some reviewers ask to remove unnecessary header files.
>
> So that reviewers are right and maybe wrong (see below for the details), I don't see those
> reviews so I can't judge.
>
> > So I removed all unnecessary header files if compilation completes
> > without any errors or warnings.
>
> Have you checked how deep and sudden the header inclusion went?
>
> > I suppose <linux/of.h> has included by other inclusion.
>
> Of course and it's wrong in your case. No header from above guarantees that. See below.
>
> > Need I add <linux/of.h> or other inclusions back?
>
> The rule of thumb is that you have to include all headers you are a direct user of.
> There are some that guarantee inclusion of others, like bits.h is always included if you
> use bitmap.h (via bitops.h) or compiler_attributes.h is always provided by types.h.
>
> You have to find a golden ratio here (yes, it's kinda knowledge that doesn't come at once,
> needs to have some experience).
>
> ...
>
> > > > + val = (reg & BIT(bit_off)) ? 1 : 0;
> > >
> > > !!(...) may also work, but it's rather style preference.
> >
> > The return value is integer 0 or 1, not Boolean.
>
> Yes, and it's exactly what has been suggested. It's a C standard allowed trick. With the
> -O2 compiler gives you the same code for both (at least on x86).
>
> ...
>
> > > > + reg = readl(spp_gchip->gpioxt_base +
> > > > + SPPCTL_GPIO_OFF_MASTER + reg_off);
> > >
> > > I noticed a potentially big issue with this driver. Are you sure
> > > it's brave enough to do I/O without any synchronisation? Did I miss a lock?
> >
> > Do I need to add spin_lock() for all gpio operation functions?
> > Please teach me what operation functions I need to add lock or all
> > operation functions need lock?
>
> I don't know. You need to answer this question, it's your code. And you know how it's supposed
> to be used etc, etc.
>
> ...
>
> > > > + reg = readl(spp_gchip->gpioxt2_base + SPPCTL_GPIO_OFF_OD +
> > > > + reg_off);
> > >
> > > You may create an I/O wrappers to achieve a much better to read code
> > > (no repetition of this arithmetics, etc).
> >
> > I think this is the simplest in-line form:
>
> No, it's harder to read and easy to mistake what the base and / or offset is used, what
> value, etc.
>
> > "spp_gchip->gpioxt2_base" is base address.
> > SPPCTL_GPIO_OFF_OD is register offset to base of OD (open-drain) registers.
> > reg_off is register offset to an OD register (SP7021 has 7 OD registers totally).
> >
> > Need I add macros (wrappers) for accessing registers?
> >
> > For example,
> >
> > #define SPPCTL_GPIO_OD(off) (spp_gchip->gpioxt2_base + SPPCTL_GPIO_OFF_OD + off)
> >
> > reg = readl(SPPCTL_GPIO_OD(reg_off));
> >
> > or
> >
> > writel(reg, SPPCTL_GPIO_OD(reg_off));
> >
> >
> > Mr. Linus Walleij told me that he likes in-line (direct) form, instead
> > of macro because in-line form has better readability (No need to jump
> > to other file for reading macros).
> >
> > Could you please share me with your idea?
>
> It's an idea that is used in zillions of the drivers (and not via macros).
>
> static inline spp_readl(struct ... *spp, u32 offset) {
> return readl(...);
> }
>
> Same for _writel() and so on.
>
> ...
>
> > > Perhaps to show only requested ones? In such case you may use
> > > for_each_requested_gpio() macro.
> >
> > I'd like to keep showing status of all GPIOs.
> > This helps us know status of all GPIOs when debugging hardware issue.
>
> Since it's a pin control driver, the pin control debug callback can show this. For GPIO
> I would rather not be bothered with not requested pins. But it's your decision.
>
> ...
>
> > > > + gchip->parent = &pdev->dev;
> > >
> > > > + gchip->of_node = pdev->dev.of_node;
> > >
> > > Drop this dup. GPIO library already does it for you.
> >
> > But when I removed the two statements, I found both 'gchip->parent'
> > and 'gchip->of_node' are always 0. No one helps set it.
> >
> > Do I miss doing somethings?
>
> Yes, I put blank lines around the dup and left context (as a first
> line) to show why the second one is a dup. When you miss something, read the implementation
> code. It's open source at the end!
>
> ...
>
> > > > + dev_dbg(pctldev->dev, "%s(%d, %ld, %d)\n", __func__, pin,
> > > > + *configs, num_configs);
> > >
> > > Noise. Better to consider to add necessary tracepoints to pin control core.
> >
> > What should I do?
> > Should I remove it?
>
> I wouldn't expect these to be in the production-ready driver. And since you are committing
> to drivers/pinctrl and not to drivers/staging I consider that you are trying to push this
> code as production-ready.
>
> ...
>
> > > > + dev_dbg(pctldev->dev, "%s(%d)\n", __func__, offset);
> > >
> > > Noise. And so on, so on...
> >
> > Should I remove dev_dbg? Or modify it?
> > But it will not print out anything in normal run, only for debugging.
>
> See above.
>
> ...
>
> > > > + dev_dbg(pctldev->dev, "%s(%d), f_idx: %d, g_idx: %d, freg: %d\n",
> > > > + __func__, selector, g2fpm.f_idx, g2fpm.g_idx,
> > > > + f->freg);
> > >
> > > No need to use __func__, and especially in case of _dbg / _debug. It
> > > can be enabled at run-time with help of Dynamic Debug.
> >
> > Should I need to remove all __func__ in this driver?
>
> As the first step, the second one is to remove 90%+ of these messages as I explained above.
>
> ...
>
> > > Looking into this rather quite big function why you can't use what pin control core
> provides?
> >
> > No, we cannot use functions pin-control core provides.
> > Please refer to dt-bindings document, "pinctrl/sunplus,sp7021-pinctrl.yaml".
> > We have more explanation there.
>
> Fine, can you reuse some library functions, etc? Please, consider refactoring to make it
> more readable.
>
> ...
>
> > > > + sppctl->groups_name = devm_kzalloc(&pdev->dev, sppctl_list_funcs_sz *
> > > > + SPPCTL_MAX_GROUPS *
> > > > + sizeof(char *), GFP_KERNEL);
> > >
> > > Ditto. And check some interesting macros in overflow.h.
> >
> > I'll modify code to use devm_kcalloc().
> >
> > I'll modify sizeof() to use type of variable, that is:
> > sizeof(*sppctl->groups_name)
> >
> > Please teach me what macros should I check?
> > There are many macros in overflow.h.
>
> Do your homework, it's not me who makes this contribution :-)
> Hint: something about multiplication.
>
> ...
>
> > > > + if (IS_ERR(sppctl->moon2_base)) {
> > > > + ret = PTR_ERR(sppctl->moon2_base);
> > > > + goto ioremap_failed;
> > >
> > > What is this for? Use return dev_err_probe() directly.
> >
> > There are 5 devm_ioremap_resource() in this function.
> > To avoid from duplication, goto an error-handling when ioremap failed.
>
> What error handling? You have the same point which does the same for them, I don't see
> duplication avoidance. See below as well.
>
> > > > + }
>
> ...
>
> > > > +ioremap_failed:
> > > > + dev_err_probe(&pdev->dev, ret, "ioremap failed!\n");
> > >
> > > This doesn't bring any value,
> >> besides the fact that API you have used already prints a
> > > message.
>
> (1)
>
> > I'll modify code to as shown below (error-handling here):
> >
> > ioremap_failed:
> > return dev_err_probe(&pdev->dev, ret, "ioremap failed!\n"); }
> >
> > Is this ok?
>
> No.
>
> > If not, please teach me how to modify.
>
> Read again what I wrote in (1).
>
> > > > + pdev->dev.platform_data = sppctl;
> > >
> > > Don't we have special setter for this field?
> >
> > I know platform_set_drvdata() function is used to set "dev->driver_data".
> > I cannot find a function to set "dev->platform_data".
> > Please teach me what function should I use to set "dev->platform_data"?
>
> Ah, now I even may say that the above assignment is simply wrong.
> It's not designed for what you think it's for. Use different ways.
>
> ...
>
> > > > + dev_info(&pdev->dev, "SP7021 PinCtrl by Sunplus/Tibbo Tech.
> > > > + (c)");
> > >
> > > No value.
> >
> > This shows that pinctrl driver has probed successfully.
> > Many drivers show this kind of information.
>
> And there is no value in this information.
>
> > Do I need to remove it? Or change to dev_dbg(...).
>
> Neither in this case.
>
> Explain the point "why?". In general you have to explain each line of your code "why are
> you doing this or that?".
>
> ...
>
> > > > +#ifndef __SPPCTL_H__
> > > > +#define __SPPCTL_H__
> > >
> > > This header misses the inclusions such as bits.h.
> > > And I believe more than that.
> >
> > Some reviewers ask to remove unnecessary header files.
>
> What do you mean by this in this case. This is a clear miss of bits.h here as you use macros
> from it. Imagine if you include this file somewhere where bits.h hasn't found its mysterious
> ways.
>
> > I removed all unnecessary header files if compilation completes
> > without any errors or warnings.
> >
> > If compilation has done successfully,
>
> So what? It doesn't mean the code is bad in one way or another, :-)
>
> > does it mean all
> > necessary inclusions has included well?
>
> > Besides, before private header files are included, Linux or system
> > header files will be included.
> > No need extra inclusion here, right?
>
> See above.
>
> ...
>
> > > > +/* FIRST register:
> > > > + * 0: MUX
> > > > + * 1: GPIO/IOP
> > > > + * 2: No change
> > > > + */
> > >
> > > For all comments starting from here and for similar cases elsewhere:
> > > - why it is not in kernel doc?
> > > - what the value that add?
> > > (Some of them so cryptic or so obvious)
> >
> > The comment explains usage of 'enum mux_f_mg'
> > The 'enum' is only used in the driver.
> > It helps programmers to remember or look-up the define of the enum.
> > Need we add this kind of comment to kernel doc?
>
> Why not?
>
> > > > +static const struct sppctl_grp sp7021grps_spif[] = {
> > > > + EGRP("SPI_FLASH1", 1, pins_spif1),
> > > > + EGRP("SPI_FLASH2", 2, pins_spif2)
> > >
> > > Here and everywhere else, leave a comma if it's not a terminator entry.
> >
> > The constant array 'sp7021grps_spif[]' is declared and initialized to
> > have 2 elements. 'EGRP("SPI_FLASH2", 2, pins_spif2)' is the latest
> > element.
> > Why do we need to add 'comma' for the latest element of an array?
>
> To avoid the churn in the future when it will be expanded. Believe I saw this kind of "proves"
> that this or that won't ever be expanded and then... you may picture what happens.
>
> > If we add extra comma, the array will have one more element.
>
> Yes, with touching the "last" one here. Please, add commas where it's not a crystal clear
> a termination (which is not in many cases, usually arrays with NULL entry or enums with
> MAX value at the end).
>
> --
> With Best Regards,
> Andy Shevchenko
More information about the linux-arm-kernel
mailing list