linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Linus Walleij <linus.walleij@linaro.org>
To: Yinbo Zhu <zhuyinbo@loongson.cn>
Cc: Bartosz Golaszewski <brgl@bgdev.pl>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	WANG Xuerui <kernel@xen0n.name>,
	Jiaxun Yang <jiaxun.yang@flygoat.com>,
	Thomas Bogendoerfer <tsbogend@alpha.franken.de>,
	Juxin Gao <gaojuxin@loongson.cn>, Bibo Mao <maobibo@loongson.cn>,
	Yanteng Si <siyanteng@loongson.cn>,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, loongarch@lists.linux.dev,
	linux-mips@vger.kernel.org, Arnaud Patard <apatard@mandriva.com>,
	Huacai Chen <chenhuacai@kernel.org>,
	Jianmin Lv <lvjianmin@loongson.cn>,
	Hongchen Zhang <zhanghongchen@loongson.cn>,
	Liu Peibao <liupeibao@loongson.cn>
Subject: Re: [PATCH v5 2/3] gpio: loongson: add gpio driver support
Date: Mon, 21 Nov 2022 14:24:23 +0100	[thread overview]
Message-ID: <CACRpkda1adiNwbTZHdAyHKny3r5FFMP_XXVGbo1vnCdw9U1gNg@mail.gmail.com> (raw)
In-Reply-To: <20221121123803.3786-2-zhuyinbo@loongson.cn>

On Mon, Nov 21, 2022 at 1:38 PM Yinbo Zhu <zhuyinbo@loongson.cn> wrote:

> The Loongson platforms GPIO controller contains 60 GPIO pins in total,
> 4 of which are dedicated GPIO pins, and the remaining 56 are reused
> with other functions. Each GPIO can set input/output and has the
> interrupt capability.
>
> This driver added support for Loongson GPIO controller and support to
> use DTS or ACPI to descibe GPIO device resources.
>
> Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
> Signed-off-by: Hongchen Zhang <zhanghongchen@loongson.cn>
> Signed-off-by: Liu Peibao <liupeibao@loongson.cn>
> Signed-off-by: Juxin Gao <gaojuxin@loongson.cn>
> Signed-off-by: Yinbo Zhu <zhuyinbo@loongson.cn>
> ---
> Change in v5:

This is starting to look really good! We are getting to the final polish.

> +config GPIO_LOONGSON
> +       tristate "Loongson GPIO support"
> +       depends on LOONGARCH || COMPILE_TEST

select GPIO_GENERIC

You should use this in the "bit mode".

>  obj-$(CONFIG_GPIO_LOONGSON1)           += gpio-loongson1.o
> +obj-$(CONFIG_GPIO_LOONGSON)            += gpio-loongson.o

Isn't this a bit confusing? What about naming it
gpio-loongson2.c?

> +enum loongson_gpio_mode {
> +       BIT_CTRL_MODE,
> +       BYTE_CTRL_MODE,
> +};

I don't think you will need to track this, jus assume BYTE_CTRL_MODE
in your callbacks because we will replace the bit mode with assigned
accessors from GPIO_GENERIC.

> +
> +struct loongson_gpio_platform_data {
> +       const char              *label;
> +       enum loongson_gpio_mode mode;

So drop this.

> +static int loongson_gpio_request(
> +                       struct gpio_chip *chip, unsigned int pin)
> +{
> +       if (pin >= chip->ngpio)
> +               return -EINVAL;

This is not needed, the gpiolib core already checks this. Drop it.

> +static inline void __set_direction(struct loongson_gpio_chip *lgpio,
> +                       unsigned int pin, int input)
> +{
> +       u64 qval;
> +       u8  bval;
> +
> +       if (lgpio->p_data->mode == BIT_CTRL_MODE) {
> +               qval = readq(LOONGSON_GPIO_OEN(lgpio));
> +               if (input)
> +                       qval |= 1ULL << pin;
> +               else
> +                       qval &= ~(1ULL << pin);
> +               writeq(qval, LOONGSON_GPIO_OEN(lgpio));
> +       } else {
> +               bval = input ? 1 : 0;
> +               writeb(bval, LOONGSON_GPIO_OEN_BYTE(lgpio, pin));
> +       }

Drop bit mode keep only byte mode.

> +static void __set_level(struct loongson_gpio_chip *lgpio, unsigned int pin,
> +                       int high)
> +{
> +       u64 qval;
> +       u8 bval;
> +
> +       if (lgpio->p_data->mode == BIT_CTRL_MODE) {
> +               qval = readq(LOONGSON_GPIO_OUT(lgpio));
> +               if (high)
> +                       qval |= 1ULL << pin;
> +               else
> +                       qval &= ~(1ULL << pin);
> +               writeq(qval, LOONGSON_GPIO_OUT(lgpio));
> +       } else {
> +               bval = high ? 1 : 0;
> +               writeb(bval, LOONGSON_GPIO_OUT_BYTE(lgpio, pin));
> +       }

Dito.

> +static int loongson_gpio_get(struct gpio_chip *chip, unsigned int pin)
> +{
> +       u64 qval;
> +       u8  bval;
> +       int val;
> +
> +       struct loongson_gpio_chip *lgpio =
> +               container_of(chip, struct loongson_gpio_chip, chip);
> +
> +       if (lgpio->p_data->mode == BIT_CTRL_MODE) {
> +               qval = readq(LOONGSON_GPIO_IN(lgpio));
> +               val = (qval & (1ULL << pin)) != 0;
> +       } else {
> +               bval = readb(LOONGSON_GPIO_IN_BYTE(lgpio, pin));
> +               val = bval & 1;
> +       }

Dito.

> +static int loongson_gpio_to_irq(
> +                       struct gpio_chip *chip, unsigned int offset)
> +{
> +       struct platform_device *pdev =
> +               container_of(chip->parent, struct platform_device, dev);
> +       struct loongson_gpio_chip *lgpio =
> +               container_of(chip, struct loongson_gpio_chip, chip);
> +
> +       if (offset >= chip->ngpio)
> +               return -EINVAL;
> +
> +       if ((lgpio->gsi_idx_map != NULL) && (offset < lgpio->mapsize))
> +               offset = lgpio->gsi_idx_map[offset];
> +       else
> +               return -EINVAL;
> +
> +       return platform_get_irq(pdev, offset);
> +}

I'm a bit suspicious about this. See the following in
Documentation/driver-api/gpio/driver.rst:

------------------
It is legal for any IRQ consumer to request an IRQ from any irqchip even if it
is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
irq_chip are orthogonal, and offering their services independent of each
other.

gpiod_to_irq() is just a convenience function to figure out the IRQ for a
certain GPIO line and should not be relied upon to have been called before
the IRQ is used.

Always prepare the hardware and make it ready for action in respective
callbacks from the GPIO and irq_chip APIs. Do not rely on gpiod_to_irq() having
been called first.
------------------

I am bit suspicious that your IRQchip implementation expects consumers
to call gpiod_to_irq() first and this is not legal.

> +static int loongson_gpio_init(
> +                       struct device *dev, struct loongson_gpio_chip *lgpio,
> +                       struct device_node *np, void __iomem *base)
> +{

Do something like this:

#define LOONGSON_GPIO_IN(x)            (x->base + x->p_data->in_offset)
+#define LOONGSON_GPIO_OUT(x)           (x->base + x->p_data->out_offset)
+#define LOONGSON_GPIO_OEN(x)           (x->base + x->p_data->conf_offset)

if (lgpio->p_data->mode == BIT_CTRL_MODE) {
       ret = bgpio_init(&g->gc, dev, 8,
                         lgpio->base + lgpio->p_data->in_offset,
                         lgpio->base + lgpio->p_data->out_offset,
                         0,
                         lgpio->base + lgpio->p_data->conf_offset,
                         NULL,
                         0);
        if (ret) {
                dev_err(dev, "unable to init generic GPIO\n");
                goto dis_clk;
        }

If you actually have a special purpose clear register in your hardware
which is not included here, then add it in the line with just 0 for that
function.

See the kerneldoc in bgpio_init() in drivers/gpio/gpio-mmio.c.

Then:

}  else {

> +       lgpio->chip.request = loongson_gpio_request;
> +       lgpio->chip.direction_input = loongson_gpio_direction_input;
> +       lgpio->chip.get = loongson_gpio_get;
> +       lgpio->chip.direction_output = loongson_gpio_direction_output;
> +       lgpio->chip.set = loongson_gpio_set;

Note also: implement loongson_gpio_get_direction(). To read the setting
of the conf register on startup. You now only need to implement it for
byte mode.

}

After this you should set ngpios, because bgpio_init() will overwrite it
with 64, so it cannot be done directly when parsing platform data,
cache it somewhere and write it here.

(...)

Yours,
Linus Walleij

  reply	other threads:[~2022-11-21 13:24 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-21 12:38 [PATCH v5 1/3] gpio: loongson2ef: move driver to original location Yinbo Zhu
2022-11-21 12:38 ` [PATCH v5 2/3] gpio: loongson: add gpio driver support Yinbo Zhu
2022-11-21 13:24   ` Linus Walleij [this message]
2022-11-23  8:02     ` Yinbo Zhu
2022-11-23 22:05       ` Linus Walleij
2022-11-24  2:22         ` Yinbo Zhu
2022-11-24  8:54           ` Linus Walleij
2022-12-12  8:12             ` Yinbo Zhu
2022-12-13  9:36               ` Linus Walleij
2022-12-20  3:27                 ` Yinbo Zhu
2022-12-12  8:34         ` Yinbo Zhu
2022-12-13  9:45           ` Linus Walleij
2022-11-21 12:38 ` [PATCH v5 3/3] dt-bindings: gpio: add loongson gpio Yinbo Zhu
2022-11-21 13:30 ` [PATCH v5 1/3] gpio: loongson2ef: move driver to original location Linus Walleij

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=CACRpkda1adiNwbTZHdAyHKny3r5FFMP_XXVGbo1vnCdw9U1gNg@mail.gmail.com \
    --to=linus.walleij@linaro.org \
    --cc=apatard@mandriva.com \
    --cc=brgl@bgdev.pl \
    --cc=chenhuacai@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gaojuxin@loongson.cn \
    --cc=jiaxun.yang@flygoat.com \
    --cc=kernel@xen0n.name \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=liupeibao@loongson.cn \
    --cc=loongarch@lists.linux.dev \
    --cc=lvjianmin@loongson.cn \
    --cc=maobibo@loongson.cn \
    --cc=robh+dt@kernel.org \
    --cc=siyanteng@loongson.cn \
    --cc=tsbogend@alpha.franken.de \
    --cc=zhanghongchen@loongson.cn \
    --cc=zhuyinbo@loongson.cn \
    /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).