[PATCH v3 1/2] GPIO: fxl6408: Add support for FXL6408 GPIO expander
Oleksandr Suvorov
cryosay at gmail.com
Thu Sep 16 10:46:44 CEST 2021
i Michal,
On Thu, Sep 16, 2021 at 10:05 AM Michal Simek <michal.simek at xilinx.com> wrote:
>
>
>
> On 9/15/21 8:35 PM, Oleksandr Suvorov wrote:
> > Hi Michal,
> >
> > On Fri, Sep 10, 2021 at 9:35 AM Michal Simek <michal.simek at xilinx.com> wrote:
> >>
> >>
> >>
> >> On 9/9/21 10:44 PM, Oleksandr Suvorov wrote:
> >>> From: Oleksandr Suvorov <oleksandr.suvorov at toradex.com>
> >>>
> >>> Initial support for Fairchild's 8 bit I2C gpio expander FXL6408.
> >>> The CONFIG_FXL6408_GPIO define enables support for such devices.
> >>>
> >>> Based on: https://patchwork.kernel.org/patch/9148419/
> >>>
> >>> Signed-off-by: Oleksandr Suvorov <oleksandr.suvorov at toradex.com>
> >>> Reviewed-by: Simon Glass <sjg at chromium.org>
> >>> Tested-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
> >>> Signed-off-by: Oleksandr Suvorov <cryosay at gmail.com>
> >>> Signed-off-by: Oleksandr Suvorov <oleksandr.suvorov at foundries.io>
> >>
> >> 3 emails for you. Would be the best to choose only one.
> >
> > Thanks, fixed. That habit to always add '-s' when committing changes :)
> >>
> >>> ---
> >>>
> >>> Changes in v3:
> >>> - fix a warning:
> >>> ...drivers/gpio/gpio-fxl6408.c:348:15: warning: format ‘%ld’
> >>> expects argument of type ‘long int’, but argument 3 has
> >>> type ‘int’ [-Wformat=]...
> >>> - add Tested-by record.
> >>>
> >>> drivers/gpio/Kconfig | 7 +
> >>> drivers/gpio/Makefile | 1 +
> >>> drivers/gpio/gpio-fxl6408.c | 366 ++++++++++++++++++++++++++++++++++++
> >>> 3 files changed, 374 insertions(+)
> >>> create mode 100644 drivers/gpio/gpio-fxl6408.c
> >>>
> >>> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> >>> index 4a89c1a62b..f56e4cc261 100644
> >>> --- a/drivers/gpio/Kconfig
> >>> +++ b/drivers/gpio/Kconfig
> >>> @@ -123,6 +123,13 @@ config DA8XX_GPIO
> >>> help
> >>> This driver supports the DA8xx GPIO controller
> >>>
> >>> +config FXL6408_GPIO
> >>> + bool "FXL6408 I2C GPIO expander driver"
> >>> + depends on DM_GPIO && DM_I2C
> >>> + help
> >>> + This driver supports the Fairchild FXL6408 device. FXL6408 is a
> >>> + fully configurable 8-bit I2C-controlled GPIO expander.
> >>> +
> >>> config INTEL_BROADWELL_GPIO
> >>> bool "Intel Broadwell GPIO driver"
> >>> depends on DM
> >>> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> >>> index 58f4704f6b..83d8b5c9d8 100644
> >>> --- a/drivers/gpio/Makefile
> >>> +++ b/drivers/gpio/Makefile
> >>> @@ -16,6 +16,7 @@ obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
> >>> obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o
> >>> obj-$(CONFIG_BCM6345_GPIO) += bcm6345_gpio.o
> >>> obj-$(CONFIG_CORTINA_GPIO) += cortina_gpio.o
> >>> +obj-$(CONFIG_FXL6408_GPIO) += gpio-fxl6408.o
> >>> obj-$(CONFIG_INTEL_GPIO) += intel_gpio.o
> >>> obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
> >>> obj-$(CONFIG_INTEL_BROADWELL_GPIO) += intel_broadwell_gpio.o
> >>> diff --git a/drivers/gpio/gpio-fxl6408.c b/drivers/gpio/gpio-fxl6408.c
> >>> new file mode 100644
> >>> index 0000000000..dbc68618f9
> >>> --- /dev/null
> >>> +++ b/drivers/gpio/gpio-fxl6408.c
> >>> @@ -0,0 +1,366 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/*
> >>> + * Copyright (C) 2021 Toradex
> >>> + * Copyright (C) 2016 Broadcom
> >>> + */
> >>> +
> >>> +/**
> >>
> >> Below is not kernel-doc format
> >
> > I don't think so. And without formatting comments of this block as a
> > kernel-doc, the kernel-doc tool shows the warning:
> > drivers/gpio/gpio-fxl6408.c:1: warning: no structured comments found
>
> Because script only checks format starting with /**.
Sure, missed that "little" thing :) Thanks!
>
> <snip>
>
> >>> +};
> >>> +
> >>> +/*
> >>
> >> /** this should be kernel doc.
> >>
> >> Run this
> >> ./scripts/kernel-doc -man -v 1>/dev/null *.c
> >>
> >> to check that all values are right.
> >
> > The kernel-doc doesn't found errors.
>
> Because it doesn't find any structure to check. Add here /** and run
> that script again.
>
> >
> >>> + * struct fxl6408_info - Data for fxl6408
> >>> + *
> >>> + * @dev: udevice structure for the device
> >>> + * @addr: i2c slave address
> >>> + * @reg_io_dir: hold the value of direction register
> >>> + * @reg_output: hold the value of output register
> >>> + */
> >>> +struct fxl6408_info {
> >>> + struct udevice *dev;
> >>> + int addr;
> >>> + u8 device_id;
> >>> + u8 reg_io_dir;
> >>> + u8 reg_output;
> >>> +};
> >>> +
> >>> +static inline int fxl6408_write(struct udevice *dev, int reg, u8 val)
> >>> +{
> >>> + return dm_i2c_write(dev, reg, &val, 1);
> >>> +}
> >>> +
> >>> +static int fxl6408_read(struct udevice *dev, int reg)
> >>> +{
> >>> + int ret;
> >>> + u8 tmp;
> >>> +
> >>> + ret = dm_i2c_read(dev, reg, &tmp, 1);
> >>> + if (!ret)
> >>> + ret = tmp;
> >>
> >> This looks completely wrong. What value are you returning in case of error.
> >
> > Nope. In case of error, I return an error value stored in "ret".
> >
> >> If ops->xfer is not defined dm_i2c_read returns -ENOSYS. tmp is not
> >> initialized and can have random value that's why here in case or error
> >> you will return ramdom value.
> >
> > !(-ENOSYS) == false, thus "if" op fails and doesn't perform "ret = tmp".
> > I don't see any errors here.
>
> You are right. I read it incorrectly.
>
>
> <snip>
>
> >>> + /*
> >>> + * If configured, set initial output state and direction,
> >>> + * otherwise read them from the chip.
> >>> + */
> >>> + if (dev_read_u32(dev, "initial_io_dir", &val32)) {
> >>
> >> Where do you have dt binding document for this chip? I can't see
> >> anything in the linux kernel or in your series.
> >>
> >> It is good that you read values from dt but you shouldn't do it in
> >> probe. You should create platdata and fill it by information from DT and
> >> then in probe just read them from platdata structure.
> >> This applied to all dt read in probe.
> >>
> >>
> >>> + ret = fxl6408_read(dev, REG_IO_DIR);
> >>> + if (ret < 0) {
> >>> + dev_err(dev, "Error reading direction register\n");
> >>> + return ret;
> >>> + }
> >>> + info->reg_io_dir = ret;
> >>> + } else {
> >>> + info->reg_io_dir = val32 & 0xFF;
> >>
> >> val32 is not initialized above. dev_read_u32 above fails that's why
> >> val32 wont't be initialized and here you do calculation with it.
> >> That's quite weird behavior. The same pattern visible below.
> >
> > Nope. dev_read_u32() returns 0 on success. The logic is correct.
>
> You are right again. I normally use reverse logic.
>
>
> >>> + ret = fxl6408_write(dev, REG_IO_DIR, info->reg_io_dir);
> >>> + if (ret < 0) {
> >>> + dev_err(dev, "Error setting direction register\n");
> >>> + return ret;
> >>> + }
> >>> + }
> >>> +
> >>> + if (dev_read_u32(dev, "initial_output", &val32)) {
> >>> + ret = fxl6408_read(dev, REG_OUT_STATE);
> >>> + if (ret < 0) {
> >>> + dev_err(dev, "Error reading output register\n");
> >>> + return ret;
> >>> + }
> >>> + info->reg_output = ret;
> >>> + } else {
> >>> + info->reg_output = val32 & 0xFF;
> >>> + ret = fxl6408_write(dev, REG_OUT_STATE, info->reg_output);
> >>> + if (ret < 0) {
> >>> + dev_err(dev, "Error setting output register\n");
> >>> + return ret;
> >>> + }
> >>> + }
> >>> +
> >>> + tmp = dev_read_prop(dev, "label", &size);
> >>> + if (tmp) {
> >>> + size = min(size, (int)sizeof(label) - 1);
> >>> + memcpy(label, tmp, size);
> >>> + label[size] = '\0';
> >>> + snprintf(name, sizeof(name), "%s@%x_", label, info->addr);
> >>> + } else {
> >>> + snprintf(name, sizeof(name), "gpio@%x_", info->addr);
> >>> + }
> >>
> >> I see some code around labels in gpio-uclass. I would be surprised if it
> >> is not there already because it should be core functionality not driver
> >> when labels are defined.
> >
> > This code is not about gpios labeling. It's about the bank name, it
> > just sets the uc_priv->bank_name which is used in gpio-uclass.
>
> Can you please use different variable name then label. If this is
> bank_name just call it bank name.
It makes sense. I'll rename it in the next revision. Thanks!
>
> Thanks,
> Michal
>
--
Best regards
Oleksandr
Oleksandr Suvorov
cryosay at gmail.com
More information about the U-Boot
mailing list