From: Alex Elder <elder@riscstar.com>
To: Bartosz Golaszewski <brgl@kernel.org>
Cc: daniel@riscstar.com, mohd.anwar@oss.qualcomm.com,
a0987203069@gmail.com, alexandre.torgue@foss.st.com,
ast@kernel.org, boon.khai.ng@altera.com, chenchuangyu@xiaomi.com,
chenhuacai@kernel.org, daniel@iogearbox.net, hawk@kernel.org,
hkallweit1@gmail.com, inochiama@gmail.com,
john.fastabend@gmail.com, julianbraha@gmail.com,
livelycarpet87@gmail.com, matthew.gerlach@altera.com,
mcoquelin.stm32@gmail.com, me@ziyao.cc,
prabhakar.mahadev-lad.rj@bp.renesas.com,
richardcochran@gmail.com, rohan.g.thomas@altera.com,
sdf@fomichev.me, siyanteng@cqsoftware.com.cn,
weishangjuan@eswincomputing.com, wens@kernel.org,
netdev@vger.kernel.org, bpf@vger.kernel.org,
linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
linux-gpio@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, maxime.chevallier@bootlin.com,
rmk+kernel@armlinux.org.uk, andersson@kernel.org,
konradybcio@kernel.org, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, linusw@kernel.org, arnd@arndb.de,
gregkh@linuxfoundation.org
Subject: Re: [PATCH net-next 09/12] gpio: tc956x: add TC956x/QPS615 support
Date: Mon, 4 May 2026 08:07:50 -0500 [thread overview]
Message-ID: <53fb87c9-25f3-4da1-aa7b-104c10c92a06@riscstar.com> (raw)
In-Reply-To: <CAMRc=McWXCqyv1LmWMuEMmE3HqaURx_eMD8rkDs9AJT+7W2aYw@mail.gmail.com>
On 5/4/26 7:46 AM, Bartosz Golaszewski wrote:
> On Fri, 1 May 2026 17:54:17 +0200, Alex Elder <elder@riscstar.com> said:
>> Toshiba TC956x is an Ethernet-AVB/TSN bridge and is essentially
>> a small and highly-specialized SoC. TC956x includes a GPIO block that
>> can be accessed, alongside several other peripherals, via two PCIe
>> endpoint functions. The PCIe function driver creates an auxiliary
>> device for the GPIO block, and that device gets bound to this auxiliary
>> device driver.
>>
>> Co-developed-by: Daniel Thompson <daniel@riscstar.com>
>> Signed-off-by: Daniel Thompson <daniel@riscstar.com>
>> Signed-off-by: Alex Elder <elder@riscstar.com>
Thanks Bartosz, I've got some responses below.
>> ---
>> drivers/gpio/Kconfig | 11 ++
>> drivers/gpio/Makefile | 1 +
>> drivers/gpio/gpio-tc956x.c | 209 +++++++++++++++++++++++++++++++++++++
>> 3 files changed, 221 insertions(+)
>> create mode 100644 drivers/gpio/gpio-tc956x.c
>>
>> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
>> index 020e51e30317a..746cedea7e91d 100644
>> --- a/drivers/gpio/Kconfig
>> +++ b/drivers/gpio/Kconfig
>> @@ -1646,6 +1646,17 @@ config GPIO_TC3589X
>> This enables support for the GPIOs found on the TC3589X
>> I/O Expander.
>>
>> +config GPIO_TC956X
>> + tristate "Toshiba TC956X GPIO support"
>> + depends on TOSHIBA_TC956X_PCI
>> + default m if TOSHIBA_TC956X_PCI
>> + help
>> + This enables support for the GPIO controller embedded in the Toshiba
>> + TC956X (and Qualcomm QPS615). This device connects to the host
>> + via PCIe port, which is the upstream port on an internal PCIe
>> + switch. On some platforms, a few of the GPIO lines are used to
>> + manage external resets.
>> +
>> config GPIO_TIMBERDALE
>> bool "Support for timberdale GPIO IP"
>> depends on MFD_TIMBERDALE
>> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
>> index b267598b517de..c3584e7cba9b4 100644
>> --- a/drivers/gpio/Makefile
>> +++ b/drivers/gpio/Makefile
>> @@ -178,6 +178,7 @@ obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o
>> obj-$(CONFIG_GPIO_TANGIER) += gpio-tangier.o
>> obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o
>> obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
>> +obj-$(CONFIG_GPIO_TC956X) += gpio-tc956x.o
>> obj-$(CONFIG_GPIO_TEGRA186) += gpio-tegra186.o
>> obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
>> obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o
>> diff --git a/drivers/gpio/gpio-tc956x.c b/drivers/gpio/gpio-tc956x.c
>> new file mode 100644
>> index 0000000000000..12221d8f812d9
>> --- /dev/null
>> +++ b/drivers/gpio/gpio-tc956x.c
>> @@ -0,0 +1,209 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/*
>> + * Copyright (C) 2026 by RISCstar Solutions Corporation. All rights reserved.
>> + */
>> +
>> +/*
>> + * The Toshiba TC956X implements a PCIe Gen 3 switch that connects an
>> + * upstream x4 port to two downstream PCIe x2 ports. It incorporates
>> + * an internal endpoint on a internal PCIe port that implements two
>> + * Synopsys XGMAC Ethernet interfaces.
>> + *
>> + * 35 GPIOs are also implemented by an embedded GPIO controller. Three
>> + * registers control the first 32 GPIOs (other than 20 and 21, which are
>> + * reserved). Three other registers control GPIOs 32 through 36. GPIOs
>> + * 22-24, 27-28, 31, and 34 are treated as "input only".
>> + *
>> + * There is a TC956X PCI power controller driver that accesses the
>> + * direction and output value registers for GPIOs 2 and 3. These
>> + * GPIOs control the reset signal for the two downstream PCIe ports.
>> + * Their values will never change during operation of this driver, and
>> + * this driver reserves these two GPIOS.
>> + */
>> +
>> +#include <linux/auxiliary_bus.h>
>> +#include <linux/dev_printk.h>
>
> This is implied by device.h which is guarnteed by platform_device.h. Please
> drop it.
OK, I'll drop it.
>> +#include <linux/gpio/driver.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +
>> +#define DRIVER_NAME "tc956x-gpio"
>> +
>> +#define TC956X_GPIO_COUNT 37 /* Number of GPIOs (20-21 reserved) */
>> +
>> +/* The GPIO offsets are relative to 0x1200 in TC956X SFR space */
>> +#define GPIO_IN0_OFFSET 0x00 /* Input value (0-31) */
>> +#define GPIO_EN0_OFFSET 0x08 /* 0: out; 1: in (0-31) */
>> +#define GPIO_OUT0_OFFSET 0x10 /* Output value (0-31) */
>> +
>> +#define GPIO_IN1_OFFSET 0x04 /* Input value (32-36) */
>> +#define GPIO_EN1_OFFSET 0x0c /* 0: out; 1: in (32-36) */
>> +#define GPIO_OUT1_OFFSET 0x14 /* Output value (32-36) */
>> +
>> +/*
>> + * struct tc956x_gpio - Information related to the embedded GPIO controller
>> + * @chip: GPIO chip structure
>> + * @regmap: MMIO register map for SFR GPIO region access
>> + * @input_only: Bitmap indicating which GPIOs are input-only
>> + */
>> +struct tc956x_gpio {
>> + struct gpio_chip chip;
>> + struct regmap *regmap;
>> + DECLARE_BITMAP(input_only, TC956X_GPIO_COUNT);
>> +};
>> +
>> +static int tc956x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
>> +{
>> + struct tc956x_gpio *gpio = gpiochip_get_data(gc);
>> + u32 reg;
>> + u32 val;
>> +
>> + if (test_bit(offset, gpio->input_only))
>> + return GPIO_LINE_DIRECTION_IN;
>> +
>> + reg = offset < 32 ? GPIO_EN0_OFFSET : GPIO_EN1_OFFSET;
>> +
>> + regmap_read(gpio->regmap, reg, &val);
>> + if (val & BIT(offset % 32))
>> + return GPIO_LINE_DIRECTION_IN;
>> +
>> + return GPIO_LINE_DIRECTION_OUT;
>> +}
>> +
>> +static int tc956x_gpio_direction_input(struct gpio_chip *gc,
>> + unsigned int offset)
>> +{
>> + u32 reg = offset < 32 ? GPIO_EN0_OFFSET : GPIO_EN1_OFFSET;
>> + struct tc956x_gpio *gpio = gpiochip_get_data(gc);
>> + u32 mask = BIT(offset % 32);
>> +
>> + return regmap_update_bits(gpio->regmap, reg, mask, mask);
>> +}
>> +
>> +static int tc956x_gpio_direction_output(struct gpio_chip *gc,
>> + unsigned int offset, int value)
>> +{
>> + struct tc956x_gpio *gpio = gpiochip_get_data(gc);
>> + u32 vreg;
>> + u32 dreg;
>> + u32 mask;
>> +
>> + if (test_bit(offset, gpio->input_only))
>> + return -EINVAL;
>> +
>> + if (offset < 32) {
>> + vreg = GPIO_OUT0_OFFSET;
>> + dreg = GPIO_EN0_OFFSET;
>> + } else {
>> + vreg = GPIO_OUT1_OFFSET;
>> + dreg = GPIO_EN1_OFFSET;
>> + }
>> + mask = BIT(offset % 32);
>> +
>> + /* Set output value first, then direction */
>> + regmap_update_bits(gpio->regmap, vreg, mask, value ? mask : 0);
>> +
>> + return regmap_update_bits(gpio->regmap, dreg, mask, 0);
>> +}
>> +
>> +static int tc956x_gpio_get(struct gpio_chip *gc, unsigned int offset)
>> +{
>> + u32 reg = offset < 32 ? GPIO_IN0_OFFSET : GPIO_IN1_OFFSET;
>> + struct tc956x_gpio *gpio = gpiochip_get_data(gc);
>> + u32 val;
>> +
>> + regmap_read(gpio->regmap, reg, &val);
>> +
>> + return val & BIT(offset % 32) ? 1 : 0;
>> +}
>> +
>> +static int tc956x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
>> +{
>> + u32 reg = offset < 32 ? GPIO_OUT0_OFFSET : GPIO_OUT1_OFFSET;
>> + struct tc956x_gpio *gpio = gpiochip_get_data(gc);
>> + u32 mask = BIT(offset % 32);
>> +
>> + return regmap_update_bits(gpio->regmap, reg, mask, value ? mask : 0);
>> +}
>> +
>> +static int tc956x_gpio_init_valid_mask(struct gpio_chip *gc,
>> + unsigned long *valid_mask,
>> + unsigned int ngpios)
>> +{
>> + /*
>> + * GPIOs 2 and 3 are used by the PCI power control driver, and
>> + * we don't allow them to be used. GPIOs 20 and 21 are reserved
>> + * (and not usable).
>> + */
>> + bitmap_fill(valid_mask, ngpios);
>> + bitmap_clear(valid_mask, 2, 2);
>> + bitmap_clear(valid_mask, 20, 2);
>> +
>> + return 0;
>> +}
>> +
>> +static int tc956x_gpio_probe(struct auxiliary_device *adev,
>> + const struct auxiliary_device_id *id)
>> +{
>> + struct device *dev = &adev->dev;
>> + struct tc956x_gpio *gpio;
>> + struct gpio_chip *gc;
>> +
>> + if (!dev->platform_data)
>> + return -EINVAL;
>> +
>> + gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
>> + if (!gpio)
>> + return -ENOMEM;
>
> Add newline.
I will add a newline here.
>
>> + gpio->regmap = dev->platform_data;
>
> It's not clear whether this is an mmio regmap or a slow-bus one that can fail.
> In the code above you're checking the return values of regmap operations quite
> inconsistently. Could you please verify if you need it and either always check
> them or not at all?
You're right. I'm returning the result of regmap_update_bits()
from two callback functions. But yes, this is an MMIO regmap.
I will return 0 and ignore the return value of regmap_update_bits()
in those spots, and will add some comments that make it clear that
this is an MMIO regmap.
>> +
>> + /* Mark GPIOs 22, 23, 24, 27, 28, 31, and 34 as input only */
>> + bitmap_set(gpio->input_only, 22, 3);
>> + bitmap_set(gpio->input_only, 27, 2);
>> + set_bit(31, gpio->input_only);
>> + set_bit(34, gpio->input_only);
>> +
>> + gc = &gpio->chip;
>> +
>> + gc->label = DRIVER_NAME;
>> + gc->parent = dev->parent;
>> +
>> + gc->get_direction = tc956x_gpio_get_direction;
>> + gc->direction_input = tc956x_gpio_direction_input;
>> + gc->direction_output = tc956x_gpio_direction_output;
>> + gc->get = tc956x_gpio_get;
>> + gc->set = tc956x_gpio_set;
>> + gc->init_valid_mask = tc956x_gpio_init_valid_mask;
>> +
>> + gc->base = -1;
>> + gc->ngpio = TC956X_GPIO_COUNT;
>> + gc->can_sleep = false;
>
> This makes me think this is an MMIO regmap after all.
You are correct.
>
>> +
>> + dev_set_drvdata(dev, gpio);
>
> There's no corresponding dev_get_drvdata().
I hadn't noticed that. We're only using the GPIO chip data
field (gc->gpiodev->data) instead. I'll drop this call.
>> +
>> + return devm_gpiochip_add_data(dev, gc, gpio);
>> +}
>> +
>> +static const struct auxiliary_device_id tc956x_gpio_ids[] = {
>> + { .name = "tc956x_pci.tc9564-gpio", },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(auxiliary, tc956x_gpio_ids);
>> +
>> +static struct auxiliary_driver tc956x_gpio_driver = {
>> + .name = DRIVER_NAME,
>> + .probe = tc956x_gpio_probe,
>> + .id_table = tc956x_gpio_ids,
>> + .driver = {
>> + .name = DRIVER_NAME,
>> + .owner = THIS_MODULE,
>> + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
>> + },
>> +};
>> +module_auxiliary_driver(tc956x_gpio_driver);
>> +
>> +MODULE_DESCRIPTION("Toshiba TC956X PCIe GPIO Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("auxiliary:" DRIVER_NAME);
>> --
>> 2.51.0
>>
>>
>
> There are a few minor issues but overall looks good!
Thank you very much for the review Bartosz. I'll implement
all of your suggestions in the next version.
-Alex
>
> Bart
next prev parent reply other threads:[~2026-05-04 13:07 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 15:54 [PATCH net-next 00/12] net: enable TC956x support Alex Elder
2026-05-01 15:54 ` [PATCH net-next 01/12] net: pcs: pcs-xpcs-regmap: support XPCS memory-mapped MDIO bus via regmap Alex Elder
2026-05-01 15:54 ` [PATCH net-next 02/12] net: pcs: pcs-xpcs: select operating mode for 10G-baseR capable PCS Alex Elder
2026-05-01 16:50 ` Andrew Lunn
2026-05-01 18:07 ` Alex Elder
2026-05-01 15:54 ` [PATCH net-next 03/12] net: pcs: pcs-xpcs: Preserve BMCR_ANENBLE during link up Alex Elder
2026-05-01 17:06 ` Andrew Lunn
2026-05-01 15:54 ` [PATCH net-next 04/12] net: stmmac: dma: create a separate dma_device pointer Alex Elder
2026-05-01 17:13 ` Andrew Lunn
2026-05-01 18:06 ` Alex Elder
2026-05-01 20:55 ` Andrew Lunn
2026-05-04 13:36 ` Alex Elder
2026-05-01 15:54 ` [PATCH net-next 05/12] net: stmmac: dwxgmac2: Add multi MSI interrupt mode Alex Elder
2026-05-01 17:21 ` Andrew Lunn
2026-05-01 15:54 ` [PATCH net-next 06/12] net: stmmac: dwxgmac2: Add XGMAC 3.01a support Alex Elder
2026-05-01 15:54 ` [PATCH net-next 07/12] net: stmmac: dwxgmac2: export symbols for XGMAC 3.01a DMA Alex Elder
2026-05-01 15:54 ` [PATCH net-next 08/12] dt-bindings: net: toshiba,tc965x-dwmac: add TC956x Ethernet bridge Alex Elder
2026-05-01 17:38 ` Andrew Lunn
2026-05-03 2:22 ` Alex Elder
2026-05-04 11:00 ` Krzysztof Kozlowski
2026-05-04 13:34 ` Alex Elder
2026-05-01 15:54 ` [PATCH net-next 09/12] gpio: tc956x: add TC956x/QPS615 support Alex Elder
2026-05-01 18:36 ` Andrew Lunn
2026-05-03 1:45 ` Alex Elder
2026-05-03 2:48 ` Andrew Lunn
2026-05-03 3:05 ` Andrew Lunn
2026-05-03 3:42 ` Julian Braha
2026-05-04 12:46 ` Bartosz Golaszewski
2026-05-04 13:07 ` Alex Elder [this message]
2026-05-01 15:54 ` [PATCH net-next 10/12] net: stmmac: " Alex Elder
2026-05-01 19:04 ` Andrew Lunn
2026-05-01 15:54 ` [PATCH net-next 11/12] misc: tc956x_pci: " Alex Elder
2026-05-01 21:07 ` Andrew Lunn
2026-05-03 2:06 ` Alex Elder
2026-05-02 16:45 ` Jakub Kicinski
2026-05-03 2:06 ` Alex Elder
2026-05-03 2:14 ` Jakub Kicinski
2026-05-03 2:23 ` Alex Elder
2026-05-01 15:54 ` [PATCH net-next 12/12] arm64: dts: qcom: qcs6490-rb3gen2: enable TC9564 with a single QCS8081 phy Alex Elder
2026-05-01 21:09 ` Andrew Lunn
2026-05-02 16:47 ` [PATCH net-next 00/12] net: enable TC956x support Jakub Kicinski
2026-05-03 2:07 ` Alex Elder
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=53fb87c9-25f3-4da1-aa7b-104c10c92a06@riscstar.com \
--to=elder@riscstar.com \
--cc=a0987203069@gmail.com \
--cc=alexandre.torgue@foss.st.com \
--cc=andersson@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=arnd@arndb.de \
--cc=ast@kernel.org \
--cc=boon.khai.ng@altera.com \
--cc=bpf@vger.kernel.org \
--cc=brgl@kernel.org \
--cc=chenchuangyu@xiaomi.com \
--cc=chenhuacai@kernel.org \
--cc=conor+dt@kernel.org \
--cc=daniel@iogearbox.net \
--cc=daniel@riscstar.com \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=edumazet@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=hawk@kernel.org \
--cc=hkallweit1@gmail.com \
--cc=inochiama@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=julianbraha@gmail.com \
--cc=konradybcio@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=kuba@kernel.org \
--cc=linusw@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=livelycarpet87@gmail.com \
--cc=matthew.gerlach@altera.com \
--cc=maxime.chevallier@bootlin.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=me@ziyao.cc \
--cc=mohd.anwar@oss.qualcomm.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
--cc=richardcochran@gmail.com \
--cc=rmk+kernel@armlinux.org.uk \
--cc=robh@kernel.org \
--cc=rohan.g.thomas@altera.com \
--cc=sdf@fomichev.me \
--cc=siyanteng@cqsoftware.com.cn \
--cc=weishangjuan@eswincomputing.com \
--cc=wens@kernel.org \
/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