gpio: tc9563: Add support for the embedded GPIO controller

Add a driver for the GPIO controller embedded in the Toshiba TC9563 PCIe
switch (and the Qualcomm QPS615). The device implements 37 GPIOs using two
register banks: three registers control the first 32 GPIOs and three more
control GPIOs 32-36.  GPIOs 20 and 21 are reserved while GPIOs 22-24,
27-28, 31, and 34 are input-only.

Register the driver as an auxiliary device driver. The TC9563 power
controller creates the auxiliary device and provides a regmap that gives
access to the GPIO registers, so use the gpio-regmap helpers to implement
the GPIO chip.

Signed-off-by: Alex Elder <elder@riscstar.com>
Co-developed-by: Daniel Thompson <daniel@riscstar.com>
Signed-off-by: Daniel Thompson <daniel@riscstar.com>
Co-developed-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
[bhelgaas: commit log per https://lore.kernel.org/arQ2mDjqHv4gmoOK@lore-desk]
[bhelgaas: squash Geert Uytterhoeven <geert+renesas@glider.be> Kconfig fix:
  https://lore.kernel.org/all/45484c37512a3102495d8b75b6e9f72a141ba42e.1792574560.git.geert+renesas@glider.be,
  Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
  Acked-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260909-pci-tc9563-aux-v5-2-c9b33f56c8d3@oss.qualcomm.com
This commit is contained in:
Alex Elder 2026-09-09 16:55:54 +02:00 committed by Bjorn Helgaas
parent 028f86457e
commit 03ba5646f0
4 changed files with 128 additions and 0 deletions

View File

@ -1830,6 +1830,18 @@ config GPIO_LTC4283
endmenu
config GPIO_TC9563
tristate "Toshiba TC9563 GPIO support"
depends on PCI_PWRCTRL_TC9563 || COMPILE_TEST
default m if ARCH_QCOM
select AUXILIARY_BUS
select GPIO_REGMAP
help
This enables support for the GPIO controller embedded in the Toshiba
TC9563 (and Qualcomm QPS615). This device connects to the host
via PCIe port, which is the upstream port on an internal PCIe
switch.
menu "PCI GPIO expanders"
depends on PCI

View File

@ -182,6 +182,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_TC9563) += gpio-tc9563.o
obj-$(CONFIG_GPIO_TEGRA186) += gpio-tegra186.o
obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o

View File

@ -0,0 +1,99 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2026 by RISCstar Solutions Corporation. All rights reserved.
*/
/*
* The Toshiba TC9563 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.
*
* 37 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".
*
*/
#include <linux/auxiliary_bus.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/regmap.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/soc/qcom/tc9563.h>
/*
* There are two sets of registers, each representing (up to) 32 GPIOs with a
* stride of 4 bytes (IN1 is 4 bytes past IN0, EN1 is 4 bytes past EN0, etc.).
*/
#define TC9563_GPIO_COUNT 37
#define TC9563_GPIO_PER_REG 32
#define TC9563_GPIO_REG_STRIDE 4
static int tc9563_gpio_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask,
unsigned int ngpios)
{
/* GPIOs 20 and 21 are reserved */
bitmap_fill(valid_mask, ngpios);
bitmap_clear(valid_mask, 20, 2);
return 0;
}
static int tc9563_gpio_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct gpio_regmap_config config = {
.parent = &adev->dev,
.ngpio = TC9563_GPIO_COUNT,
.reg_stride = TC9563_GPIO_REG_STRIDE,
.ngpio_per_reg = TC9563_GPIO_PER_REG,
.reg_dat_base = GPIO_REGMAP_ADDR(TC9563_GPIO_IN0_OFFSET),
.reg_set_base = GPIO_REGMAP_ADDR(TC9563_GPIO_OUT0_OFFSET),
.reg_dir_in_base = GPIO_REGMAP_ADDR(TC9563_GPIO_EN0_OFFSET),
.init_valid_mask = tc9563_gpio_init_valid_mask,
};
DECLARE_BITMAP(fixed_dir_mask, TC9563_GPIO_COUNT);
DECLARE_BITMAP(fixed_dir_out, TC9563_GPIO_COUNT);
config.regmap = dev_get_platdata(&adev->dev);
if (!config.regmap)
return -EINVAL;
/*
* Only some of our GPIOs are fixed direction:
* 22, 23, 24, 27, 28, 31, and 34 are input-only.
*/
bitmap_zero(fixed_dir_mask, TC9563_GPIO_COUNT);
bitmap_set(fixed_dir_mask, 22, 3);
bitmap_set(fixed_dir_mask, 27, 2);
set_bit(31, fixed_dir_mask);
set_bit(34, fixed_dir_mask);
config.fixed_direction_mask = fixed_dir_mask;
bitmap_zero(fixed_dir_out, TC9563_GPIO_COUNT);
config.fixed_direction_output = fixed_dir_out;
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&adev->dev, &config));
};
static const struct auxiliary_device_id tc9563_gpio_ids[] = {
{ "pci_pwrctrl_tc9563." TC9563_GPIO_DEV_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(auxiliary, tc9563_gpio_ids);
static struct auxiliary_driver tc9563_gpio_driver = {
.name = TC9563_GPIO_DEV_NAME,
.probe = tc9563_gpio_probe,
.id_table = tc9563_gpio_ids,
};
module_auxiliary_driver(tc9563_gpio_driver);
MODULE_AUTHOR("Alex Elder <elder@riscstar.com>");
MODULE_AUTHOR("Daniel Thompson <daniel@riscstar.com>");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>");
MODULE_DESCRIPTION("Toshiba TC9563 GPIO Driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
* Author: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
*/
#ifndef __QCOM_TC9563_H
#define __QCOM_TC9563_H
#define TC9563_GPIO_DEV_NAME "tc9563-gpio"
#define TC9563_GPIO_IN0_OFFSET 0x801200
#define TC9563_GPIO_EN0_OFFSET 0x801208
#define TC9563_GPIO_OUT0_OFFSET 0x801210
#endif /* __QCOM_TC9563_H */