devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Linus Walleij <linus.walleij@linaro.org>
To: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
Cc: Bartosz Golaszewski <brgl@bgdev.pl>,
	Rob Herring <robh@kernel.org>,
	 Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	 Chester Lin <chester62515@gmail.com>,
	Matthias Brugger <mbrugger@suse.com>,
	 Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	 linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	 linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	 NXP S32 Linux Team <s32@nxp.com>,
	Christophe Lizzi <clizzi@redhat.com>,
	Alberto Ruiz <aruizrui@redhat.com>,
	 Enric Balletbo <eballetb@redhat.com>
Subject: Re: [PATCH v4 3/4] gpio: siul2-s32g2: add NXP S32G2/S32G3 SoCs support
Date: Tue, 1 Oct 2024 15:15:43 +0200	[thread overview]
Message-ID: <CACRpkdaYcis2r6eNDfdXV9zcXof6x_XfGHFADJ2RojxLNp7C-A@mail.gmail.com> (raw)
In-Reply-To: <20240926143122.1385658-4-andrei.stefanescu@oss.nxp.com>

Hi Andrei,

thanks for your patch!

Sorry for being so late in giving any deeper review of it.

On Thu, Sep 26, 2024 at 4:32 PM Andrei Stefanescu
<andrei.stefanescu@oss.nxp.com> wrote:

> Add the GPIO driver for S32G2/S32G3 SoCs. This driver uses the SIUL2
> (System Integration Unit Lite2) hardware module. There are two
> SIUL2 hardware modules present, SIUL2_0(controlling GPIOs 0-101) and
> SIUL2_1 for the rest.
>
> The GPIOs are not fully contiguous, there are some gaps:
> - GPIO102 up to GPIO111(inclusive) are invalid
> - GPIO123 up to GPIO143(inclusive) are invalid
>
> Some GPIOs are input only(i.e. GPI182) though this restriction
> is not yet enforced in code.
>
> This patch adds basic GPIO functionality(no interrupts, no
> suspend/resume functions).
>
> Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
> Signed-off-by: Larisa Grigore <larisa.grigore@nxp.com>
> Signed-off-by: Phu Luu An <phu.luuan@nxp.com>
> Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>

(...)

> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/pinctrl/consumer.h>

Hm, are you sure you don't want one of those combined
GPIO+pinctrl drivers? Look in drivers/pinctrl for examples such
as drivers/pinctrl/pinctrl-stmfx.c

> +/* PGPDOs are 16bit registers that come in big endian
> + * order if they are grouped in pairs of two.
> + *
> + * For example, the order is PGPDO1, PGPDO0, PGPDO3, PGPDO2...
> + */
> +#define SIUL2_PGPDO(N)         (((N) ^ 1) * 2)
> +#define S32G2_SIUL2_NUM                2
> +#define S32G2_PADS_DTS_TAG_LEN 7
> +
> +#define SIUL2_GPIO_16_PAD_SIZE 16

You seem to be manipulating "pads" which is pin control territory.
That should be done in a pin control driver.

> +/**
> + * struct siul2_device_data  - platform data attached to the compatible.
> + * @pad_access: access table for I/O pads, consists of S32G2_SIUL2_NUM tables.
> + * @reset_cnt: reset the pin name counter to zero when switching to SIUL2_1.
> + */
> +struct siul2_device_data {
> +       const struct regmap_access_table **pad_access;
> +       const bool reset_cnt;

I don't understand the reset_cnt variable at all. Explain why it exists in the
kerneldoc please.

> +/**
> + * struct siul2_desc - describes a SIUL2 hw module.
> + * @pad_access: array of valid I/O pads.

Now that is really pin control isn't it.

> + * @opadmap: the regmap of the Parallel GPIO Pad Data Out Register.
> + * @ipadmap: the regmap of the Parallel GPIO Pad Data In Register.
> + * @gpio_base: the first GPIO pin.
> + * @gpio_num: the number of GPIO pins.
> + */
> +struct siul2_desc {
> +       const struct regmap_access_table *pad_access;
> +       struct regmap *opadmap;
> +       struct regmap *ipadmap;
> +       u32 gpio_base;
> +       u32 gpio_num;
> +};
(...)

> +static int siul2_get_gpio_pinspec(struct platform_device *pdev,
> +                                 struct of_phandle_args *pinspec,
> +                                 unsigned int range_index)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +
> +       return of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
> +                                               range_index, pinspec);
> +}

I do not see why a driver would parse gpio-ranges since the gpiolib
core should normally deal with the translation between GPIO lines
and pins.

This looks hacky and probably an indication that you want to use
a combined pinctrl+gpio driver so the different parts of the driver
can access the same structures easily without hacks.

> +static void siul2_gpio_set_direction(struct siul2_gpio_dev *dev,
> +                                    unsigned int gpio, int dir)
> +{
> +       guard(raw_spinlock_irqsave)(&dev->lock);
> +
> +       if (dir == GPIO_LINE_DIRECTION_IN)
> +               __clear_bit(gpio, dev->pin_dir_bitmap);
> +       else
> +               __set_bit(gpio, dev->pin_dir_bitmap);
> +}

This looks like a job for gpio regmap?

select GPIO_REGMAP,
look in other driver for examples of how to use it.

> +static int siul2_get_direction(struct siul2_gpio_dev *dev,
> +                              unsigned int gpio)
> +{
> +       return test_bit(gpio, dev->pin_dir_bitmap) ? GPIO_LINE_DIRECTION_OUT :
> +                                                    GPIO_LINE_DIRECTION_IN;
> +}

Also looks like a reimplementation of GPIO_REGMAP.

> +static int siul2_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio,
> +                             int val)
> +{
> +       struct siul2_gpio_dev *gpio_dev;
> +       int ret = 0;
> +
> +       gpio_dev = to_siul2_gpio_dev(chip);
> +       siul2_gpio_set_val(chip, gpio, val);
> +
> +       ret = pinctrl_gpio_direction_output(chip, gpio);
(...)

This is nice, pin control is properly used as the back-end.

> +static int siul2_gpio_remove_reserved_names(struct device *dev,
> +                                           struct siul2_gpio_dev *gpio_dev,
> +                                           char **names)
> +{
> +       struct device_node *np = dev->of_node;
> +       int num_ranges, i, j, ret;
> +       u32 base_gpio, num_gpio;
> +
> +       /* Parse the gpio-reserved-ranges to know which GPIOs to exclude. */
> +
> +       num_ranges = of_property_count_u32_elems(dev->of_node,
> +                                                "gpio-reserved-ranges");
> +
> +       /* The "gpio-reserved-ranges" is optional. */
> +       if (num_ranges < 0)
> +               return 0;
> +       num_ranges /= 2;
> +
> +       for (i = 0; i < num_ranges; i++) {
> +               ret = of_property_read_u32_index(np, "gpio-reserved-ranges",
> +                                                i * 2, &base_gpio);
> +               if (ret) {
> +                       dev_err(dev, "Could not parse the start GPIO: %d\n",
> +                               ret);
> +                       return ret;
> +               }
> +
> +               ret = of_property_read_u32_index(np, "gpio-reserved-ranges",
> +                                                i * 2 + 1, &num_gpio);
> +               if (ret) {
> +                       dev_err(dev, "Could not parse num. GPIOs: %d\n", ret);
> +                       return ret;
> +               }
> +
> +               if (base_gpio + num_gpio > gpio_dev->gc.ngpio) {
> +                       dev_err(dev, "Reserved GPIOs outside of GPIO range\n");
> +                       return -EINVAL;
> +               }
> +
> +               /* Remove names set for reserved GPIOs. */
> +               for (j = base_gpio; j < base_gpio + num_gpio; j++) {
> +                       devm_kfree(dev, names[j]);
> +                       names[j] = NULL;
> +               }
> +       }
> +
> +       return 0;
> +}

I don't get this. gpio-reserved-ranges is something that is parsed and
handled by gpiolib. Read the code in gpiolib.c and you'll probably
figure out how to let gpiolib take care of this for you.

> +static int siul2_gpio_populate_names(struct device *dev,
> +                                    struct siul2_gpio_dev *gpio_dev)
> +{
> +       unsigned int num_index = 0;
> +       char ch_index = 'A';
> +       char **names;
> +       int i, ret;
> +
> +       names = devm_kcalloc(dev, gpio_dev->gc.ngpio, sizeof(*names),
> +                            GFP_KERNEL);
> +       if (!names)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < S32G2_SIUL2_NUM; i++) {
> +               ret = siul2_gen_names(dev, gpio_dev->siul2[i].gpio_num,
> +                                     names + gpio_dev->siul2[i].gpio_base,
> +                                     &ch_index, &num_index);
> +               if (ret) {
> +                       dev_err(dev, "Could not set names for SIUL2_%d GPIOs\n",
> +                               i);
> +                       return ret;
> +               }
> +
> +               if (gpio_dev->platdata->reset_cnt)
> +                       num_index = 0;
> +
> +               ch_index++;
> +       }
> +
> +       ret = siul2_gpio_remove_reserved_names(dev, gpio_dev, names);
> +       if (ret)
> +               return ret;
> +
> +       gpio_dev->gc.names = (const char *const *)names;
> +
> +       return 0;
> +}

Interesting!

I'm not against, on the contrary this looks really helpful to users.

> +       gc = &gpio_dev->gc;

No poking around in the gpiolib internals please.

Look at what other drivers do and do like they do.

On top of these comments:
everywhere you do [raw_spin_]locks: try to use guards or
scoped guards instead. git grep guard drivers/gpio for
many examples.

Yours,
Linus Walleij

  parent reply	other threads:[~2024-10-01 13:15 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-26 14:31 [PATCH v4 0/4] gpio: siul2-s32g2: add initial GPIO driver Andrei Stefanescu
2024-09-26 14:31 ` [PATCH v4 1/4] drivers: provide devm_platform_get_and_ioremap_resource_byname() Andrei Stefanescu
2024-10-03 11:59   ` Greg Kroah-Hartman
2024-09-26 14:31 ` [PATCH v4 2/4] dt-bindings: gpio: add support for NXP S32G2/S32G3 SoCs Andrei Stefanescu
2024-09-26 15:38   ` Conor Dooley
2024-09-27  7:13     ` Andrei Stefanescu
2024-09-30 15:00       ` Conor Dooley
2024-09-30 15:07         ` Conor Dooley
2024-10-01  9:00           ` Andrei Stefanescu
2024-10-03 10:22             ` Andrei Stefanescu
2024-10-03 21:01               ` Conor Dooley
2024-10-04 11:10                 ` Andrei Stefanescu
2024-10-06 13:33                   ` Krzysztof Kozlowski
2024-09-26 17:43   ` Rob Herring (Arm)
2024-09-27  7:19     ` Andrei Stefanescu
2024-09-28  8:21       ` Krzysztof Kozlowski
2024-09-26 14:31 ` [PATCH v4 3/4] gpio: siul2-s32g2: add NXP S32G2/S32G3 SoCs support Andrei Stefanescu
2024-09-27  7:03   ` kernel test robot
2024-09-28  2:00   ` kernel test robot
2024-09-28  3:24   ` kernel test robot
2024-10-01 13:15   ` Linus Walleij [this message]
2024-10-02 15:05     ` Andrei Stefanescu
2024-09-26 14:31 ` [PATCH v4 4/4] MAINTAINERS: add MAINTAINER for S32G2 SIUL2 GPIO driver Andrei Stefanescu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CACRpkdaYcis2r6eNDfdXV9zcXof6x_XfGHFADJ2RojxLNp7C-A@mail.gmail.com \
    --to=linus.walleij@linaro.org \
    --cc=andrei.stefanescu@oss.nxp.com \
    --cc=aruizrui@redhat.com \
    --cc=brgl@bgdev.pl \
    --cc=chester62515@gmail.com \
    --cc=clizzi@redhat.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=eballetb@redhat.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mbrugger@suse.com \
    --cc=rafael@kernel.org \
    --cc=robh@kernel.org \
    --cc=s32@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).