From: Lorenzo Bianconi <lorenzo@kernel.org>
To: Linus Walleij <linus.walleij@linaro.org>
Cc: "Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Sean Wang" <sean.wang@kernel.org>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
"AngeloGioacchino Del Regno"
<angelogioacchino.delregno@collabora.com>,
"Lee Jones" <lee@kernel.org>,
"Uwe Kleine-König" <ukleinek@kernel.org>,
linux-mediatek@lists.infradead.org, linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
upstream@airoha.com, benjamin.larsson@genexis.eu,
ansuelsmth@gmail.com, linux-pwm@vger.kernel.org
Subject: Re: [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC
Date: Tue, 24 Sep 2024 12:12:11 +0200 [thread overview]
Message-ID: <ZvKQe73ZKIFy4fny@lore-desk> (raw)
In-Reply-To: <CACRpkdZbyQ5bk8oR+Q4UmQCdM5h1mF1ztBc26YzqNsze_B=ehA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 14003 bytes --]
> Hi Lorenzo / Benjamin,
>
> thanks for your patch!
>
> This is a real nice driver, I like the design of the pin database to support
> this pretty complex pin controller.
Hi Linus,
thx for the review, some questions inline.
Regards,
Lorenzo
>
> Some comments and nits:
>
> On Wed, Sep 11, 2024 at 9:51 PM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> > Introduce pinctrl driver for EN7581 SoC. Current EN7581 pinctrl driver
> > supports the following functionalities:
> > - pin multiplexing
> > - pin pull-up, pull-down, open-drain, current strength,
> > {input,output}_enable, output_{low,high}
> > - gpio controller
> > - irq controller
> >
> > Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
> > Co-developed-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
> > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
>
> (...)
>
> > +#include <dt-bindings/pinctrl/mt65xx.h>
> > +#include <linux/bitfield.h>
>
> Isn't just <linux/bits.h> enough for what you're using?
ack, I will fix it in v5
>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/irq.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/kernel.h>
>
> What do you use from kernel.h? We usually use more fingrained
> headers these days.
ack, I will remove it in v5
>
> (...)
>
> > +#include <linux/mfd/airoha-en7581-mfd.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/pinctrl/consumer.h>
>
> Why do you need the consumer header?
we need it for pinctrl_gpio_direction_output() and
pinctrl_gpio_direction_input() for direction_input and direction_output
callbacks.
>
> (...)
>
> > +static u32 airoha_pinctrl_rmw_unlock(void __iomem *addr, u32 mask, u32 val)
> > +{
> > + val |= (readl(addr) & ~mask);
> > + writel(val, addr);
> > +
> > + return val;
> > +}
> > +
> > +#define airoha_pinctrl_set_unlock(addr, val) \
> > + airoha_pinctrl_rmw_unlock((addr), 0, (val))
> > +#define airoha_pinctrl_clear_unlock(addr, mask) \
> > + airoha_pinctrl_rmw_unlock((addr), (mask), (0))
> > +
> > +static u32 airoha_pinctrl_rmw(struct airoha_pinctrl *pinctrl,
> > + void __iomem *addr, u32 mask, u32 val)
> > +{
> > + mutex_lock(&pinctrl->mutex);
> > + val = airoha_pinctrl_rmw_unlock(addr, mask, val);
> > + mutex_unlock(&pinctrl->mutex);
> > +
> > + return val;
> > +}
>
> Thus looks like a reimplementation of regmap-mmio, can't you just use
> regmap MMIO? You use it for the SCU access already...
>
> If you persist with this solution, please use a guard:
>
> #include <linux/cleanup.h>
>
> guard(mutex)(&pinctrl->mutex);
>
> And the lock will be released when you exit the function.
I am fine to switch to regmap but I guess we need to enable fast_io
since it can run even in interrupt context. Btw, I figured out even
airoha_pinctrl_rmw needs to grab a spin_lock since we can exec a led
trigger (like timer) where we run airoha_pinctrl_rmw in interrupt context
(so it should be fine to use a single regmap for it).
However, I guess we need to keep the spin_lock in airoha_pinctrl_gpiochip
since we need to grab it in airoha_pinctrl_gpio_irq_unmask() and
airoha_pinctrl_gpio_irq_type() (we access irq_type array there).
A possible solution would be to keep the local spin_lock and set
disable_locking. What do you think? Do you prefer to switch to regmap or
keep the current implementation using 'guard(spinlock_irqsave)' instead?
>
> > +static int airoha_pinctrl_get_gpio_from_pin(struct pinctrl_dev *pctrl_dev,
> > + int pin)
> > +{
> > + struct pinctrl_gpio_range *range;
> > + int gpio;
> > +
> > + range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev, pin);
> > + if (!range)
> > + return -EINVAL;
> > +
> > + gpio = pin - range->pin_base;
> > + if (gpio < 0)
> > + return -EINVAL;
> > +
> > + return gpio;
> > +}
>
> This function is just used here:
it is used in airoha_pinconf_get()/airoha_pinconf_set()
>
> > +static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev,
> > + unsigned int pin, unsigned long *config)
> > +{
> > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
> > + enum pin_config_param param = pinconf_to_config_param(*config);
> > + u32 arg;
> > +
> > + switch (param) {
> > + case PIN_CONFIG_BIAS_PULL_DOWN:
> > + case PIN_CONFIG_BIAS_DISABLE:
> > + case PIN_CONFIG_BIAS_PULL_UP: {
> > + u32 pull_up, pull_down;
> > +
> > + if (airoha_pinctrl_get_pullup_conf(pinctrl, pin, &pull_up) ||
> > + airoha_pinctrl_get_pulldown_conf(pinctrl, pin, &pull_down))
> > + return -EINVAL;
> > +
> > + if (param == PIN_CONFIG_BIAS_PULL_UP &&
> > + !(pull_up && !pull_down))
> > + return -EINVAL;
> > + else if (param == PIN_CONFIG_BIAS_PULL_DOWN &&
> > + !(pull_down && !pull_up))
> > + return -EINVAL;
> > + else if (pull_up || pull_down)
> > + return -EINVAL;
> > +
> > + arg = 1;
> > + break;
> > + }
> > + case PIN_CONFIG_DRIVE_STRENGTH: {
> > + u32 e2, e4;
> > +
> > + if (airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, &e2) ||
> > + airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, &e4))
> > + return -EINVAL;
> > +
> > + arg = e4 << 1 | e2;
> > + break;
> > + }
> > + case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> > + if (airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, &arg))
> > + return -EINVAL;
> > + break;
> > + case PIN_CONFIG_OUTPUT_ENABLE:
> > + case PIN_CONFIG_INPUT_ENABLE: {
> > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin);
> > +
> > + if (gpio < 0)
> > + return gpio;
> > +
> > + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio);
>
> I don't see why a pin would have to exist in a GPIO range in order to
> be set as output or input?
>
> Can't you just set up the pin as requested and not care whether
> it has a corresponding GPIO range?
>
> Is it over-reuse of the GPIO code? I'd say just set up the pin instead.
Do you mean to get rid of PIN_CONFIG_OUTPUT_ENABLE, PIN_CONFIG_INPUT_ENABLE
(and even PIN_CONFIG_OUTPUT in airoha_pinconf_set()) here?
E.g. we need PIN_CONFIG_OUTPUT_ENABLE to enable pwm for pwm-leds:
&mfd {
...
pio: pinctrl {
...
pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins {
function = "pwm";
pins = "gpio18";
output-enable;
};
};
};
>
> > +static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev,
> > + unsigned int pin, unsigned long *configs,
> > + unsigned int num_configs)
> > +{
> > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
> > + int i;
> > +
> > + for (i = 0; i < num_configs; i++) {
> > + u32 param = pinconf_to_config_param(configs[i]);
> > + u32 arg = pinconf_to_config_argument(configs[i]);
> > +
> > + switch (param) {
> > + case PIN_CONFIG_BIAS_DISABLE:
> > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0);
> > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0);
> > + break;
> > + case PIN_CONFIG_BIAS_PULL_UP:
> > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0);
> > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1);
> > + break;
> > + case PIN_CONFIG_BIAS_PULL_DOWN:
> > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1);
> > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0);
> > + break;
> > + case PIN_CONFIG_DRIVE_STRENGTH: {
> > + u32 e2 = 0, e4 = 0;
> > +
> > + switch (arg) {
> > + case MTK_DRIVE_2mA:
> > + break;
> > + case MTK_DRIVE_4mA:
> > + e2 = 1;
> > + break;
> > + case MTK_DRIVE_6mA:
> > + e4 = 1;
> > + break;
> > + case MTK_DRIVE_8mA:
> > + e2 = 1;
> > + e4 = 1;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2);
> > + airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4);
> > + break;
> > + }
> > + case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> > + airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg);
> > + break;
> > + case PIN_CONFIG_OUTPUT_ENABLE:
> > + case PIN_CONFIG_INPUT_ENABLE:
> > + case PIN_CONFIG_OUTPUT: {
> > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin);
> > + bool input = param == PIN_CONFIG_INPUT_ENABLE;
> > +
> > + if (gpio < 0)
> > + return gpio;
> > +
> > + airoha_pinctrl_gpio_set_direction(pinctrl, gpio, input);
> > + if (param == PIN_CONFIG_OUTPUT)
> > + airoha_pinctrl_gpio_set_value(pinctrl, gpio, !!arg);
> > + break;
>
> Dito. No need to reuse the GPIO set direction function. Make a helper
> that just work on the pin instead, and perhaps the GPIO set direction
> can use that instead.
ack, I will fix it in v5.
>
> > +static int airoha_pinctrl_gpio_direction_output(struct gpio_chip *chip,
> > + unsigned int gpio, int value)
> > +{
> > + int err;
> > +
> > + err = pinctrl_gpio_direction_output(chip, gpio);
> > + if (err)
> > + return err;
> > +
> > + airoha_pinctrl_gpio_set(chip, gpio, value);
>
> Hm I get a bit confused by the similarly named helpers I guess...
Naming is always hard, I will try to improve :)
>
> > +static void airoha_pinctrl_gpio_irq_unmask(struct irq_data *data)
> > +{
> > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO;
> > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO;
> > + u32 mask = GENMASK(2 * offset + 1, 2 * offset);
> > + struct airoha_pinctrl_gpiochip *gpiochip;
> > + u32 val = BIT(2 * offset);
> > + unsigned long flags;
> > +
> > + gpiochip = irq_data_get_irq_chip_data(data);
> > + if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)))
> > + return;
> > +
> > + spin_lock_irqsave(&gpiochip->lock, flags);
>
> Use a scoped guard here
>
> guard(spinlock_irqsave)(&gpiochip->lock);
>
> > +static void airoha_pinctrl_gpio_irq_mask(struct irq_data *data)
> > +{
> > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO;
> > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO;
> > + u32 mask = GENMASK(2 * offset + 1, 2 * offset);
> > + struct airoha_pinctrl_gpiochip *gpiochip;
> > + unsigned long flags;
> > +
> > + gpiochip = irq_data_get_irq_chip_data(data);
> > +
> > + spin_lock_irqsave(&gpiochip->lock, flags);
>
> Dito
>
> > +static int airoha_pinctrl_gpio_irq_type(struct irq_data *data,
> > + unsigned int type)
> > +{
> > + struct airoha_pinctrl_gpiochip *gpiochip;
> > + unsigned long flags;
> > +
> > + gpiochip = irq_data_get_irq_chip_data(data);
> > + if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))
> > + return -EINVAL;
> > +
> > + spin_lock_irqsave(&gpiochip->lock, flags);
>
> Dito
>
> > + girq->chip = devm_kzalloc(dev, sizeof(*girq->chip), GFP_KERNEL);
> > + if (!girq->chip)
> > + return -ENOMEM;
> > +
> > + girq->chip->name = dev_name(dev);
> > + girq->chip->irq_unmask = airoha_pinctrl_gpio_irq_unmask;
> > + girq->chip->irq_mask = airoha_pinctrl_gpio_irq_mask;
> > + girq->chip->irq_mask_ack = airoha_pinctrl_gpio_irq_mask;
> > + girq->chip->irq_set_type = airoha_pinctrl_gpio_irq_type;
> > + girq->chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE;
> > + girq->default_type = IRQ_TYPE_NONE;
> > + girq->handler = handle_simple_irq;
>
> If the irqchip is immutable it is const and there is no point to malloc it.
>
> Just
>
> static const struct irq_chip airoha_gpio_irq_chip = {...
>
> And assign it:
>
> girq = &g->gc.irq;
> gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip);
ack, I will fix it in v5.
Regards,
Lorenzo
>
> Yours,
> Linus Walleij
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
next prev parent reply other threads:[~2024-09-24 10:12 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi
2024-09-11 19:50 ` [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for " Lorenzo Bianconi
2024-09-11 21:12 ` Rob Herring (Arm)
2024-09-11 21:46 ` Lorenzo Bianconi
2024-09-12 16:43 ` Rob Herring
2024-09-11 19:50 ` [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Lorenzo Bianconi
2024-09-11 21:12 ` Rob Herring (Arm)
2024-09-11 21:48 ` Lorenzo Bianconi
2024-09-12 16:44 ` Rob Herring (Arm)
2024-09-11 19:50 ` [PATCH v4 3/5] mfd: airoha: Add support for Airoha EN7581 MFD Lorenzo Bianconi
2024-09-11 19:50 ` [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC Lorenzo Bianconi
2024-09-24 7:34 ` Linus Walleij
2024-09-24 10:12 ` Lorenzo Bianconi [this message]
2024-09-24 21:22 ` Lorenzo Bianconi
2024-10-02 12:58 ` Linus Walleij
2024-10-02 15:36 ` Lorenzo Bianconi
2024-09-11 19:50 ` [PATCH v4 5/5] pwm: " Lorenzo Bianconi
2024-09-23 9:53 ` [PATCH v4 0/5] Add mfd, pinctrl and pwm support to " Christian Marangi
2024-09-25 9:47 ` Lee Jones
2024-09-25 9:51 ` Christian Marangi
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=ZvKQe73ZKIFy4fny@lore-desk \
--to=lorenzo@kernel.org \
--cc=angelogioacchino.delregno@collabora.com \
--cc=ansuelsmth@gmail.com \
--cc=benjamin.larsson@genexis.eu \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=lee@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-pwm@vger.kernel.org \
--cc=matthias.bgg@gmail.com \
--cc=robh@kernel.org \
--cc=sean.wang@kernel.org \
--cc=ukleinek@kernel.org \
--cc=upstream@airoha.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.