mirror of https://github.com/torvalds/linux.git
gpio: add QIXIS FPGA GPIO controller
Add support for the GPIO controller found on some QIXIS FPGAs in Layerscape boards such as LX2160ARDB and LS1046AQDS. This driver is using gpio-regmap. A GPIO controller has a maximum of 8 lines (all found in the same register). Even within the same controller, the GPIO lines' direction is fixed, which mean that both input and output lines are found in the same register. This is why the driver also passed to gpio-regmap the newly added .fixed_direction_output bitmap to represent the true direction of the lines. Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Michael Walle <mwalle@kernel.org> # for the gpio-regmap part Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
parent
ae495810cf
commit
e88500247d
|
|
@ -1565,6 +1565,15 @@ config GPIO_PMIC_EIC_SPRD
|
|||
help
|
||||
Say yes here to support Spreadtrum PMIC EIC device.
|
||||
|
||||
config GPIO_QIXIS_FPGA
|
||||
tristate "NXP QIXIS FPGA GPIO support"
|
||||
depends on MFD_SIMPLE_MFD_I2C || COMPILE_TEST
|
||||
select GPIO_REGMAP
|
||||
help
|
||||
This enables support for the GPIOs found in the QIXIS FPGA which is
|
||||
integrated on some NXP Layerscape boards such as LX2160ARDB and
|
||||
LS1046AQDS.
|
||||
|
||||
config GPIO_RC5T583
|
||||
bool "RICOH RC5T583 GPIO"
|
||||
depends on MFD_RC5T583
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
|
|||
obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o
|
||||
obj-$(CONFIG_GPIO_POLARFIRE_SOC) += gpio-mpfs.o
|
||||
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
|
||||
obj-$(CONFIG_GPIO_QIXIS_FPGA) += gpio-qixis-fpga.o
|
||||
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
|
||||
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
|
||||
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Layerscape GPIO QIXIS FPGA driver
|
||||
*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/regmap.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct qixis_cpld_gpio_config {
|
||||
u64 output_lines;
|
||||
};
|
||||
|
||||
static const struct qixis_cpld_gpio_config lx2160ardb_sfp_cfg = {
|
||||
.output_lines = BIT(0),
|
||||
};
|
||||
|
||||
static const struct qixis_cpld_gpio_config ls1046aqds_stat_pres2_cfg = {
|
||||
.output_lines = 0x0,
|
||||
};
|
||||
|
||||
static const struct regmap_config regmap_config_8r_8v = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int qixis_cpld_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
DECLARE_BITMAP(fixed_direction_output, 8);
|
||||
const struct qixis_cpld_gpio_config *cfg;
|
||||
struct gpio_regmap_config config = {0};
|
||||
struct regmap *regmap;
|
||||
void __iomem *reg;
|
||||
u32 base;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.parent)
|
||||
return -ENODEV;
|
||||
|
||||
cfg = device_get_match_data(&pdev->dev);
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "reg", &base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!regmap) {
|
||||
/* In case there is no regmap configured by the parent device,
|
||||
* create our own from the MMIO space.
|
||||
*/
|
||||
reg = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (!reg)
|
||||
return -ENODEV;
|
||||
|
||||
regmap = devm_regmap_init_mmio(&pdev->dev, reg, ®map_config_8r_8v);
|
||||
if (!regmap)
|
||||
return -ENODEV;
|
||||
|
||||
/* In this case, the offset of our register is 0 inside the
|
||||
* regmap area that we just created.
|
||||
*/
|
||||
base = 0;
|
||||
}
|
||||
config.reg_dat_base = GPIO_REGMAP_ADDR(base);
|
||||
config.reg_set_base = GPIO_REGMAP_ADDR(base);
|
||||
|
||||
config.drvdata = (void *)cfg;
|
||||
config.regmap = regmap;
|
||||
config.parent = &pdev->dev;
|
||||
config.ngpio_per_reg = 8;
|
||||
config.ngpio = 8;
|
||||
|
||||
bitmap_from_u64(fixed_direction_output, cfg->output_lines);
|
||||
config.fixed_direction_output = fixed_direction_output;
|
||||
|
||||
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&pdev->dev, &config));
|
||||
}
|
||||
|
||||
static const struct of_device_id qixis_cpld_gpio_of_match[] = {
|
||||
{
|
||||
.compatible = "fsl,lx2160ardb-fpga-gpio-sfp",
|
||||
.data = &lx2160ardb_sfp_cfg,
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,ls1046aqds-fpga-gpio-stat-pres2",
|
||||
.data = &ls1046aqds_stat_pres2_cfg,
|
||||
},
|
||||
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qixis_cpld_gpio_of_match);
|
||||
|
||||
static struct platform_driver qixis_cpld_gpio_driver = {
|
||||
.probe = qixis_cpld_gpio_probe,
|
||||
.driver = {
|
||||
.name = "gpio-qixis-cpld",
|
||||
.of_match_table = qixis_cpld_gpio_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(qixis_cpld_gpio_driver);
|
||||
Loading…
Reference in New Issue