All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Walle <michael@walle.cc>
To: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org,
	linux-pwm@vger.kernel.org, linux-watchdog@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Cc: "Linus Walleij" <linus.walleij@linaro.org>,
	"Bartosz Golaszewski" <bgolaszewski@baylibre.com>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Jean Delvare" <jdelvare@suse.com>,
	"Guenter Roeck" <linux@roeck-us.net>,
	"Lee Jones" <lee.jones@linaro.org>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Wim Van Sebroeck" <wim@linux-watchdog.org>,
	"Shawn Guo" <shawnguo@kernel.org>, "Li Yang" <leoyang.li@nxp.com>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Jason Cooper" <jason@lakedaemon.net>,
	"Marc Zyngier" <maz@kernel.org>,
	"Mark Brown" <broonie@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Michael Walle" <michael@walle.cc>
Subject: [PATCH v2 11/16] gpio: add support for the sl28cpld GPIO controller
Date: Thu,  2 Apr 2020 22:36:51 +0200	[thread overview]
Message-ID: <20200402203656.27047-12-michael@walle.cc> (raw)
In-Reply-To: <20200402203656.27047-1-michael@walle.cc>

This adds support for the GPIO controller of the sl28 board management
controller. This driver is part of a multi-function device.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 drivers/gpio/Kconfig         |  11 +++
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-sl28cpld.c | 186 +++++++++++++++++++++++++++++++++++
 3 files changed, 198 insertions(+)
 create mode 100644 drivers/gpio/gpio-sl28cpld.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a8e148f4b2e0..d6d54cb9558e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1215,6 +1215,17 @@ config GPIO_RC5T583
 	  This driver provides the support for driving/reading the gpio pins
 	  of RC5T583 device through standard gpio library.
 
+config GPIO_SL28CPLD
+	tristate "Kontron sl28 GPIO"
+	depends on MFD_SL28CPLD
+	select GPIO_REGMAP
+	select GPIOLIB_IRQCHIP
+	help
+	  This enables support for the GPIOs found on the Kontron sl28 CPLD.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called gpio-sl28cpld.
+
 config GPIO_STMPE
 	bool "STMPE GPIOs"
 	depends on MFD_STMPE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 93e139fdfa57..f50ccf13f5eb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -129,6 +129,7 @@ obj-$(CONFIG_GPIO_SCH311X)		+= gpio-sch311x.o
 obj-$(CONFIG_GPIO_SCH)			+= gpio-sch.o
 obj-$(CONFIG_GPIO_SIFIVE)		+= gpio-sifive.o
 obj-$(CONFIG_GPIO_SIOX)			+= gpio-siox.o
+obj-$(CONFIG_GPIO_SL28CPLD)		+= gpio-sl28cpld.o
 obj-$(CONFIG_GPIO_SODAVILLE)		+= gpio-sodaville.o
 obj-$(CONFIG_GPIO_SPEAR_SPICS)		+= gpio-spear-spics.o
 obj-$(CONFIG_GPIO_SPRD)			+= gpio-sprd.o
diff --git a/drivers/gpio/gpio-sl28cpld.c b/drivers/gpio/gpio-sl28cpld.c
new file mode 100644
index 000000000000..1d199517e2e0
--- /dev/null
+++ b/drivers/gpio/gpio-sl28cpld.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sl28cpld GPIO driver.
+ *
+ * Copyright 2019 Michael Walle <michael@walle.cc>
+ */
+
+#include <linux/device.h>
+#include <linux/gpio-regmap.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* GPIO flavor */
+#define GPIO_REG_DIR	0x00
+#define GPIO_REG_OUT	0x01
+#define GPIO_REG_IN	0x02
+#define GPIO_REG_IE	0x03
+#define GPIO_REG_IP	0x04
+
+/* input-only flavor */
+#define GPI_REG_IN	0x00
+
+/* output-only flavor */
+#define GPO_REG_OUT	0x00
+
+enum sl28cpld_gpio_type {
+	SL28CPLD_GPIO = 1,
+	SL28CPLD_GPI,
+	SL28CPLD_GPO,
+};
+
+struct sl28cpld_gpio {
+	struct gpio_regmap gpio_chip;
+	struct regmap_irq_chip irq_chip;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+static const struct regmap_irq sl28cpld_gpio_irqs[] = {
+	REGMAP_IRQ_REG_LINE(0, 8),
+	REGMAP_IRQ_REG_LINE(1, 8),
+	REGMAP_IRQ_REG_LINE(2, 8),
+	REGMAP_IRQ_REG_LINE(3, 8),
+	REGMAP_IRQ_REG_LINE(4, 8),
+	REGMAP_IRQ_REG_LINE(5, 8),
+	REGMAP_IRQ_REG_LINE(6, 8),
+	REGMAP_IRQ_REG_LINE(7, 8),
+};
+
+static int sl28cpld_gpio_irq_init(struct device *dev,
+				   struct sl28cpld_gpio *gpio,
+				   struct regmap *regmap, unsigned int base,
+				   int irq)
+{
+	struct regmap_irq_chip *irq_chip = &gpio->irq_chip;
+
+	irq_chip->name = "sl28cpld-gpio-irq",
+	irq_chip->irqs = sl28cpld_gpio_irqs;
+	irq_chip->num_irqs = ARRAY_SIZE(sl28cpld_gpio_irqs);
+	irq_chip->num_regs = 1;
+	irq_chip->status_base = base + GPIO_REG_IP;
+	irq_chip->mask_base = base + GPIO_REG_IE;
+	irq_chip->mask_invert = true,
+	irq_chip->ack_base = base + GPIO_REG_IP;
+
+	return devm_regmap_add_irq_chip_np(dev, dev_of_node(dev), regmap,
+					   irq, IRQF_SHARED | IRQF_ONESHOT, 0,
+					   irq_chip, &gpio->irq_data);
+}
+
+static int sl28cpld_gpio_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *dev_id;
+	enum sl28cpld_gpio_type type;
+	struct sl28cpld_gpio *gpio;
+	struct gpio_regmap *gpio_chip;
+	struct regmap *regmap;
+	struct resource *res;
+	bool irq_support = false;
+	unsigned int base;
+	int ret;
+	int irq;
+
+	if (!pdev->dev.parent)
+		return -ENODEV;
+
+	dev_id = platform_get_device_id(pdev);
+	if (dev_id)
+		type = dev_id->driver_data;
+	else
+		type = (uintptr_t)of_device_get_match_data(&pdev->dev);
+	if (!type)
+		return -ENODEV;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (!res)
+		return -EINVAL;
+	base = res->start;
+
+	regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!regmap)
+		return -ENODEV;
+
+	gpio_chip = &gpio->gpio_chip;
+	gpio_chip->regmap = regmap;
+	gpio_chip->parent = &pdev->dev;
+	gpio_chip->ngpio = 8;
+
+	switch (type) {
+	case SL28CPLD_GPIO:
+		gpio_chip->reg_dat_base = GPIO_REGMAP_ADDR(base + GPIO_REG_IN);
+		gpio_chip->reg_set_base =
+				GPIO_REGMAP_ADDR(base + GPIO_REG_OUT);
+		gpio_chip->reg_dir_out_base =
+				GPIO_REGMAP_ADDR(base + GPIO_REG_DIR);
+		irq_support = true;
+		break;
+	case SL28CPLD_GPO:
+		gpio_chip->reg_set_base = GPIO_REGMAP_ADDR(base + GPO_REG_OUT);
+		break;
+	case SL28CPLD_GPI:
+		gpio_chip->reg_dat_base = GPIO_REGMAP_ADDR(base + GPI_REG_IN);
+		break;
+	default:
+		dev_err(&pdev->dev, "unknown type %d\n", type);
+		return -ENODEV;
+	}
+
+	if (irq_support &&
+	    device_property_read_bool(&pdev->dev, "interrupt-controller")) {
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return irq;
+
+		ret = sl28cpld_gpio_irq_init(&pdev->dev, gpio, regmap,
+					     base, irq);
+		if (ret)
+			return ret;
+
+		gpio_chip->irq_domain = regmap_irq_get_domain(gpio->irq_data);
+		dev_info(&pdev->dev, "registered IRQ %d\n", irq);
+	}
+
+	return devm_gpio_regmap_register(&pdev->dev, gpio_chip);
+}
+
+static const struct of_device_id sl28cpld_gpio_of_match[] = {
+	{ .compatible = "kontron,sl28cpld-gpio",
+	  .data = (void *)SL28CPLD_GPIO },
+	{ .compatible = "kontron,sl28cpld-gpi",
+	  .data = (void *)SL28CPLD_GPI },
+	{ .compatible = "kontron,sl28cpld-gpo",
+	  .data = (void *)SL28CPLD_GPO },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sl28cpld_gpio_of_match);
+
+static const struct platform_device_id sl28cpld_gpio_id_table[] = {
+	{ "sl28cpld-gpio", SL28CPLD_GPIO },
+	{ "sl28cpld-gpi", SL28CPLD_GPI },
+	{ "sl28cpld-gpo", SL28CPLD_GPO },
+	{}
+};
+MODULE_DEVICE_TABLE(platform, sl28cpld_gpio_id_table);
+
+static struct platform_driver sl28cpld_gpio_driver = {
+	.probe = sl28cpld_gpio_probe,
+	.id_table = sl28cpld_gpio_id_table,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = sl28cpld_gpio_of_match,
+	},
+};
+module_platform_driver(sl28cpld_gpio_driver);
+
+MODULE_DESCRIPTION("sl28cpld GPIO Driver");
+MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
+MODULE_LICENSE("GPL");
-- 
2.20.1


WARNING: multiple messages have this Message-ID (diff)
From: Michael Walle <michael-QKn5cuLxLXY@public.gmane.org>
To: linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-hwmon-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Cc: "Linus Walleij"
	<linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
	"Bartosz Golaszewski"
	<bgolaszewski-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>,
	"Rob Herring" <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	"Jean Delvare" <jdelvare-IBi9RG/b67k@public.gmane.org>,
	"Guenter Roeck" <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>,
	"Lee Jones" <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
	"Thierry Reding"
	<thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	"Uwe Kleine-König"
	<u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
	"Wim Van Sebroeck"
	<wim-Q8PRGTgFL9WUCWQAtAn6Ix2eb7JE58TQ@public.gmane.org>,
	"Shawn Guo" <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	"Li Yang" <leoyang.li-3arQi8VN3Tc@public.gmane.org>,
	"Thomas Gleixner" <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>,
	"Jason Cooper" <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>,
	"Marc Zyngier" <maz-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	"Mark Brown" <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	"Greg Kroah-Hartman"
	<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
	"Michael Walle" <michael-QKn5cuLxLXY@public.gmane.org>
Subject: [PATCH v2 11/16] gpio: add support for the sl28cpld GPIO controller
Date: Thu,  2 Apr 2020 22:36:51 +0200	[thread overview]
Message-ID: <20200402203656.27047-12-michael@walle.cc> (raw)
In-Reply-To: <20200402203656.27047-1-michael-QKn5cuLxLXY@public.gmane.org>

This adds support for the GPIO controller of the sl28 board management
controller. This driver is part of a multi-function device.

Signed-off-by: Michael Walle <michael-QKn5cuLxLXY@public.gmane.org>
---
 drivers/gpio/Kconfig         |  11 +++
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-sl28cpld.c | 186 +++++++++++++++++++++++++++++++++++
 3 files changed, 198 insertions(+)
 create mode 100644 drivers/gpio/gpio-sl28cpld.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a8e148f4b2e0..d6d54cb9558e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1215,6 +1215,17 @@ config GPIO_RC5T583
 	  This driver provides the support for driving/reading the gpio pins
 	  of RC5T583 device through standard gpio library.
 
+config GPIO_SL28CPLD
+	tristate "Kontron sl28 GPIO"
+	depends on MFD_SL28CPLD
+	select GPIO_REGMAP
+	select GPIOLIB_IRQCHIP
+	help
+	  This enables support for the GPIOs found on the Kontron sl28 CPLD.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called gpio-sl28cpld.
+
 config GPIO_STMPE
 	bool "STMPE GPIOs"
 	depends on MFD_STMPE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 93e139fdfa57..f50ccf13f5eb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -129,6 +129,7 @@ obj-$(CONFIG_GPIO_SCH311X)		+= gpio-sch311x.o
 obj-$(CONFIG_GPIO_SCH)			+= gpio-sch.o
 obj-$(CONFIG_GPIO_SIFIVE)		+= gpio-sifive.o
 obj-$(CONFIG_GPIO_SIOX)			+= gpio-siox.o
+obj-$(CONFIG_GPIO_SL28CPLD)		+= gpio-sl28cpld.o
 obj-$(CONFIG_GPIO_SODAVILLE)		+= gpio-sodaville.o
 obj-$(CONFIG_GPIO_SPEAR_SPICS)		+= gpio-spear-spics.o
 obj-$(CONFIG_GPIO_SPRD)			+= gpio-sprd.o
diff --git a/drivers/gpio/gpio-sl28cpld.c b/drivers/gpio/gpio-sl28cpld.c
new file mode 100644
index 000000000000..1d199517e2e0
--- /dev/null
+++ b/drivers/gpio/gpio-sl28cpld.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sl28cpld GPIO driver.
+ *
+ * Copyright 2019 Michael Walle <michael-QKn5cuLxLXY@public.gmane.org>
+ */
+
+#include <linux/device.h>
+#include <linux/gpio-regmap.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* GPIO flavor */
+#define GPIO_REG_DIR	0x00
+#define GPIO_REG_OUT	0x01
+#define GPIO_REG_IN	0x02
+#define GPIO_REG_IE	0x03
+#define GPIO_REG_IP	0x04
+
+/* input-only flavor */
+#define GPI_REG_IN	0x00
+
+/* output-only flavor */
+#define GPO_REG_OUT	0x00
+
+enum sl28cpld_gpio_type {
+	SL28CPLD_GPIO = 1,
+	SL28CPLD_GPI,
+	SL28CPLD_GPO,
+};
+
+struct sl28cpld_gpio {
+	struct gpio_regmap gpio_chip;
+	struct regmap_irq_chip irq_chip;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+static const struct regmap_irq sl28cpld_gpio_irqs[] = {
+	REGMAP_IRQ_REG_LINE(0, 8),
+	REGMAP_IRQ_REG_LINE(1, 8),
+	REGMAP_IRQ_REG_LINE(2, 8),
+	REGMAP_IRQ_REG_LINE(3, 8),
+	REGMAP_IRQ_REG_LINE(4, 8),
+	REGMAP_IRQ_REG_LINE(5, 8),
+	REGMAP_IRQ_REG_LINE(6, 8),
+	REGMAP_IRQ_REG_LINE(7, 8),
+};
+
+static int sl28cpld_gpio_irq_init(struct device *dev,
+				   struct sl28cpld_gpio *gpio,
+				   struct regmap *regmap, unsigned int base,
+				   int irq)
+{
+	struct regmap_irq_chip *irq_chip = &gpio->irq_chip;
+
+	irq_chip->name = "sl28cpld-gpio-irq",
+	irq_chip->irqs = sl28cpld_gpio_irqs;
+	irq_chip->num_irqs = ARRAY_SIZE(sl28cpld_gpio_irqs);
+	irq_chip->num_regs = 1;
+	irq_chip->status_base = base + GPIO_REG_IP;
+	irq_chip->mask_base = base + GPIO_REG_IE;
+	irq_chip->mask_invert = true,
+	irq_chip->ack_base = base + GPIO_REG_IP;
+
+	return devm_regmap_add_irq_chip_np(dev, dev_of_node(dev), regmap,
+					   irq, IRQF_SHARED | IRQF_ONESHOT, 0,
+					   irq_chip, &gpio->irq_data);
+}
+
+static int sl28cpld_gpio_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *dev_id;
+	enum sl28cpld_gpio_type type;
+	struct sl28cpld_gpio *gpio;
+	struct gpio_regmap *gpio_chip;
+	struct regmap *regmap;
+	struct resource *res;
+	bool irq_support = false;
+	unsigned int base;
+	int ret;
+	int irq;
+
+	if (!pdev->dev.parent)
+		return -ENODEV;
+
+	dev_id = platform_get_device_id(pdev);
+	if (dev_id)
+		type = dev_id->driver_data;
+	else
+		type = (uintptr_t)of_device_get_match_data(&pdev->dev);
+	if (!type)
+		return -ENODEV;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (!res)
+		return -EINVAL;
+	base = res->start;
+
+	regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!regmap)
+		return -ENODEV;
+
+	gpio_chip = &gpio->gpio_chip;
+	gpio_chip->regmap = regmap;
+	gpio_chip->parent = &pdev->dev;
+	gpio_chip->ngpio = 8;
+
+	switch (type) {
+	case SL28CPLD_GPIO:
+		gpio_chip->reg_dat_base = GPIO_REGMAP_ADDR(base + GPIO_REG_IN);
+		gpio_chip->reg_set_base =
+				GPIO_REGMAP_ADDR(base + GPIO_REG_OUT);
+		gpio_chip->reg_dir_out_base =
+				GPIO_REGMAP_ADDR(base + GPIO_REG_DIR);
+		irq_support = true;
+		break;
+	case SL28CPLD_GPO:
+		gpio_chip->reg_set_base = GPIO_REGMAP_ADDR(base + GPO_REG_OUT);
+		break;
+	case SL28CPLD_GPI:
+		gpio_chip->reg_dat_base = GPIO_REGMAP_ADDR(base + GPI_REG_IN);
+		break;
+	default:
+		dev_err(&pdev->dev, "unknown type %d\n", type);
+		return -ENODEV;
+	}
+
+	if (irq_support &&
+	    device_property_read_bool(&pdev->dev, "interrupt-controller")) {
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return irq;
+
+		ret = sl28cpld_gpio_irq_init(&pdev->dev, gpio, regmap,
+					     base, irq);
+		if (ret)
+			return ret;
+
+		gpio_chip->irq_domain = regmap_irq_get_domain(gpio->irq_data);
+		dev_info(&pdev->dev, "registered IRQ %d\n", irq);
+	}
+
+	return devm_gpio_regmap_register(&pdev->dev, gpio_chip);
+}
+
+static const struct of_device_id sl28cpld_gpio_of_match[] = {
+	{ .compatible = "kontron,sl28cpld-gpio",
+	  .data = (void *)SL28CPLD_GPIO },
+	{ .compatible = "kontron,sl28cpld-gpi",
+	  .data = (void *)SL28CPLD_GPI },
+	{ .compatible = "kontron,sl28cpld-gpo",
+	  .data = (void *)SL28CPLD_GPO },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sl28cpld_gpio_of_match);
+
+static const struct platform_device_id sl28cpld_gpio_id_table[] = {
+	{ "sl28cpld-gpio", SL28CPLD_GPIO },
+	{ "sl28cpld-gpi", SL28CPLD_GPI },
+	{ "sl28cpld-gpo", SL28CPLD_GPO },
+	{}
+};
+MODULE_DEVICE_TABLE(platform, sl28cpld_gpio_id_table);
+
+static struct platform_driver sl28cpld_gpio_driver = {
+	.probe = sl28cpld_gpio_probe,
+	.id_table = sl28cpld_gpio_id_table,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = sl28cpld_gpio_of_match,
+	},
+};
+module_platform_driver(sl28cpld_gpio_driver);
+
+MODULE_DESCRIPTION("sl28cpld GPIO Driver");
+MODULE_AUTHOR("Michael Walle <michael-QKn5cuLxLXY@public.gmane.org>");
+MODULE_LICENSE("GPL");
-- 
2.20.1

WARNING: multiple messages have this Message-ID (diff)
From: Michael Walle <michael@walle.cc>
To: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org,
	linux-pwm@vger.kernel.org, linux-watchdog@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Cc: "Marc Zyngier" <maz@kernel.org>,
	"Jean Delvare" <jdelvare@suse.com>,
	"Jason Cooper" <jason@lakedaemon.net>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Shawn Guo" <shawnguo@kernel.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Li Yang" <leoyang.li@nxp.com>,
	"Bartosz Golaszewski" <bgolaszewski@baylibre.com>,
	"Michael Walle" <michael@walle.cc>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Mark Brown" <broonie@kernel.org>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Wim Van Sebroeck" <wim@linux-watchdog.org>,
	"Lee Jones" <lee.jones@linaro.org>,
	"Guenter Roeck" <linux@roeck-us.net>
Subject: [PATCH v2 11/16] gpio: add support for the sl28cpld GPIO controller
Date: Thu,  2 Apr 2020 22:36:51 +0200	[thread overview]
Message-ID: <20200402203656.27047-12-michael@walle.cc> (raw)
In-Reply-To: <20200402203656.27047-1-michael@walle.cc>

This adds support for the GPIO controller of the sl28 board management
controller. This driver is part of a multi-function device.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 drivers/gpio/Kconfig         |  11 +++
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-sl28cpld.c | 186 +++++++++++++++++++++++++++++++++++
 3 files changed, 198 insertions(+)
 create mode 100644 drivers/gpio/gpio-sl28cpld.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a8e148f4b2e0..d6d54cb9558e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1215,6 +1215,17 @@ config GPIO_RC5T583
 	  This driver provides the support for driving/reading the gpio pins
 	  of RC5T583 device through standard gpio library.
 
+config GPIO_SL28CPLD
+	tristate "Kontron sl28 GPIO"
+	depends on MFD_SL28CPLD
+	select GPIO_REGMAP
+	select GPIOLIB_IRQCHIP
+	help
+	  This enables support for the GPIOs found on the Kontron sl28 CPLD.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called gpio-sl28cpld.
+
 config GPIO_STMPE
 	bool "STMPE GPIOs"
 	depends on MFD_STMPE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 93e139fdfa57..f50ccf13f5eb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -129,6 +129,7 @@ obj-$(CONFIG_GPIO_SCH311X)		+= gpio-sch311x.o
 obj-$(CONFIG_GPIO_SCH)			+= gpio-sch.o
 obj-$(CONFIG_GPIO_SIFIVE)		+= gpio-sifive.o
 obj-$(CONFIG_GPIO_SIOX)			+= gpio-siox.o
+obj-$(CONFIG_GPIO_SL28CPLD)		+= gpio-sl28cpld.o
 obj-$(CONFIG_GPIO_SODAVILLE)		+= gpio-sodaville.o
 obj-$(CONFIG_GPIO_SPEAR_SPICS)		+= gpio-spear-spics.o
 obj-$(CONFIG_GPIO_SPRD)			+= gpio-sprd.o
diff --git a/drivers/gpio/gpio-sl28cpld.c b/drivers/gpio/gpio-sl28cpld.c
new file mode 100644
index 000000000000..1d199517e2e0
--- /dev/null
+++ b/drivers/gpio/gpio-sl28cpld.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sl28cpld GPIO driver.
+ *
+ * Copyright 2019 Michael Walle <michael@walle.cc>
+ */
+
+#include <linux/device.h>
+#include <linux/gpio-regmap.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* GPIO flavor */
+#define GPIO_REG_DIR	0x00
+#define GPIO_REG_OUT	0x01
+#define GPIO_REG_IN	0x02
+#define GPIO_REG_IE	0x03
+#define GPIO_REG_IP	0x04
+
+/* input-only flavor */
+#define GPI_REG_IN	0x00
+
+/* output-only flavor */
+#define GPO_REG_OUT	0x00
+
+enum sl28cpld_gpio_type {
+	SL28CPLD_GPIO = 1,
+	SL28CPLD_GPI,
+	SL28CPLD_GPO,
+};
+
+struct sl28cpld_gpio {
+	struct gpio_regmap gpio_chip;
+	struct regmap_irq_chip irq_chip;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+static const struct regmap_irq sl28cpld_gpio_irqs[] = {
+	REGMAP_IRQ_REG_LINE(0, 8),
+	REGMAP_IRQ_REG_LINE(1, 8),
+	REGMAP_IRQ_REG_LINE(2, 8),
+	REGMAP_IRQ_REG_LINE(3, 8),
+	REGMAP_IRQ_REG_LINE(4, 8),
+	REGMAP_IRQ_REG_LINE(5, 8),
+	REGMAP_IRQ_REG_LINE(6, 8),
+	REGMAP_IRQ_REG_LINE(7, 8),
+};
+
+static int sl28cpld_gpio_irq_init(struct device *dev,
+				   struct sl28cpld_gpio *gpio,
+				   struct regmap *regmap, unsigned int base,
+				   int irq)
+{
+	struct regmap_irq_chip *irq_chip = &gpio->irq_chip;
+
+	irq_chip->name = "sl28cpld-gpio-irq",
+	irq_chip->irqs = sl28cpld_gpio_irqs;
+	irq_chip->num_irqs = ARRAY_SIZE(sl28cpld_gpio_irqs);
+	irq_chip->num_regs = 1;
+	irq_chip->status_base = base + GPIO_REG_IP;
+	irq_chip->mask_base = base + GPIO_REG_IE;
+	irq_chip->mask_invert = true,
+	irq_chip->ack_base = base + GPIO_REG_IP;
+
+	return devm_regmap_add_irq_chip_np(dev, dev_of_node(dev), regmap,
+					   irq, IRQF_SHARED | IRQF_ONESHOT, 0,
+					   irq_chip, &gpio->irq_data);
+}
+
+static int sl28cpld_gpio_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *dev_id;
+	enum sl28cpld_gpio_type type;
+	struct sl28cpld_gpio *gpio;
+	struct gpio_regmap *gpio_chip;
+	struct regmap *regmap;
+	struct resource *res;
+	bool irq_support = false;
+	unsigned int base;
+	int ret;
+	int irq;
+
+	if (!pdev->dev.parent)
+		return -ENODEV;
+
+	dev_id = platform_get_device_id(pdev);
+	if (dev_id)
+		type = dev_id->driver_data;
+	else
+		type = (uintptr_t)of_device_get_match_data(&pdev->dev);
+	if (!type)
+		return -ENODEV;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+	if (!res)
+		return -EINVAL;
+	base = res->start;
+
+	regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!regmap)
+		return -ENODEV;
+
+	gpio_chip = &gpio->gpio_chip;
+	gpio_chip->regmap = regmap;
+	gpio_chip->parent = &pdev->dev;
+	gpio_chip->ngpio = 8;
+
+	switch (type) {
+	case SL28CPLD_GPIO:
+		gpio_chip->reg_dat_base = GPIO_REGMAP_ADDR(base + GPIO_REG_IN);
+		gpio_chip->reg_set_base =
+				GPIO_REGMAP_ADDR(base + GPIO_REG_OUT);
+		gpio_chip->reg_dir_out_base =
+				GPIO_REGMAP_ADDR(base + GPIO_REG_DIR);
+		irq_support = true;
+		break;
+	case SL28CPLD_GPO:
+		gpio_chip->reg_set_base = GPIO_REGMAP_ADDR(base + GPO_REG_OUT);
+		break;
+	case SL28CPLD_GPI:
+		gpio_chip->reg_dat_base = GPIO_REGMAP_ADDR(base + GPI_REG_IN);
+		break;
+	default:
+		dev_err(&pdev->dev, "unknown type %d\n", type);
+		return -ENODEV;
+	}
+
+	if (irq_support &&
+	    device_property_read_bool(&pdev->dev, "interrupt-controller")) {
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return irq;
+
+		ret = sl28cpld_gpio_irq_init(&pdev->dev, gpio, regmap,
+					     base, irq);
+		if (ret)
+			return ret;
+
+		gpio_chip->irq_domain = regmap_irq_get_domain(gpio->irq_data);
+		dev_info(&pdev->dev, "registered IRQ %d\n", irq);
+	}
+
+	return devm_gpio_regmap_register(&pdev->dev, gpio_chip);
+}
+
+static const struct of_device_id sl28cpld_gpio_of_match[] = {
+	{ .compatible = "kontron,sl28cpld-gpio",
+	  .data = (void *)SL28CPLD_GPIO },
+	{ .compatible = "kontron,sl28cpld-gpi",
+	  .data = (void *)SL28CPLD_GPI },
+	{ .compatible = "kontron,sl28cpld-gpo",
+	  .data = (void *)SL28CPLD_GPO },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sl28cpld_gpio_of_match);
+
+static const struct platform_device_id sl28cpld_gpio_id_table[] = {
+	{ "sl28cpld-gpio", SL28CPLD_GPIO },
+	{ "sl28cpld-gpi", SL28CPLD_GPI },
+	{ "sl28cpld-gpo", SL28CPLD_GPO },
+	{}
+};
+MODULE_DEVICE_TABLE(platform, sl28cpld_gpio_id_table);
+
+static struct platform_driver sl28cpld_gpio_driver = {
+	.probe = sl28cpld_gpio_probe,
+	.id_table = sl28cpld_gpio_id_table,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = sl28cpld_gpio_of_match,
+	},
+};
+module_platform_driver(sl28cpld_gpio_driver);
+
+MODULE_DESCRIPTION("sl28cpld GPIO Driver");
+MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
+MODULE_LICENSE("GPL");
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2020-04-02 20:37 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-02 20:36 [PATCH v2 00/16] Add support for Kontron sl28cpld Michael Walle
2020-04-02 20:36 ` Michael Walle
2020-04-02 20:36 ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 01/16] include/linux/ioport.h: add helper to define REG resource constructs Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 02/16] mfd: mfd-core: Don't overwrite the dma_mask of the child device Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 03/16] mfd: mfd-core: match device tree node against reg property Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 04/16] regmap-irq: make it possible to add irq_chip do a specific device node Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-14 15:37   ` Applied "regmap-irq: make it possible to add irq_chip do a specific device node" to the regmap tree Mark Brown
2020-04-14 15:37     ` Mark Brown
2020-04-14 15:37     ` Mark Brown
2020-04-14 17:12   ` [PATCH v2 04/16] regmap-irq: make it possible to add irq_chip do a specific device node Mark Brown
2020-04-14 17:12     ` Mark Brown
2020-04-14 17:12     ` Mark Brown
2020-04-02 20:36 ` [PATCH v2 05/16] dt-bindings: mfd: Add bindings for sl28cpld Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 06/16] mfd: Add support for Kontron sl28cpld management controller Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 07/16] irqchip: add sl28cpld interrupt controller support Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 08/16] watchdog: add support for sl28cpld watchdog Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-03  6:25   ` Guenter Roeck
2020-04-03  6:25     ` Guenter Roeck
2020-04-03  6:25     ` Guenter Roeck
2020-04-02 20:36 ` [PATCH v2 09/16] pwm: add support for sl28cpld PWM controller Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 10/16] gpio: add a reusable generic gpio_chip using regmap Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-06  7:47   ` Bartosz Golaszewski
2020-04-06  7:47     ` Bartosz Golaszewski
2020-04-06  7:47     ` Bartosz Golaszewski
2020-04-06 10:10     ` Michael Walle
2020-04-06 10:10       ` Michael Walle
2020-04-06 10:10       ` Michael Walle
2020-04-14  9:50       ` Bartosz Golaszewski
2020-04-14  9:50         ` Bartosz Golaszewski
2020-04-14  9:50         ` Bartosz Golaszewski
2020-04-14 10:07         ` Michael Walle
2020-04-14 10:07           ` Michael Walle
2020-04-14 10:07           ` Michael Walle
2020-04-14 17:00           ` Bartosz Golaszewski
2020-04-14 17:00             ` Bartosz Golaszewski
2020-04-14 17:00             ` Bartosz Golaszewski
2020-04-14 18:41             ` Michael Walle
2020-04-14 18:41               ` Michael Walle
2020-04-14 18:41               ` Michael Walle
2020-04-14 19:57               ` Michael Walle
2020-04-14 19:57                 ` Michael Walle
2020-04-16  9:20                 ` Linus Walleij
2020-04-16  9:20                   ` Linus Walleij
2020-04-16  9:20                   ` Linus Walleij
2020-04-16  9:34                   ` Michael Walle
2020-04-16  9:34                     ` Michael Walle
2020-04-16  9:34                     ` Michael Walle
2020-04-14 17:21           ` Mark Brown
2020-04-14 17:21             ` Mark Brown
2020-04-14 17:21             ` Mark Brown
2020-04-14 18:36             ` Michael Walle
2020-04-14 18:36               ` Michael Walle
2020-04-14 18:36               ` Michael Walle
2020-04-14 18:39               ` Mark Brown
2020-04-14 18:39                 ` Mark Brown
2020-04-14 18:39                 ` Mark Brown
2020-04-16  9:27   ` Linus Walleij
2020-04-16  9:27     ` Linus Walleij
2020-04-16  9:27     ` Linus Walleij
2020-04-17  6:34     ` Michael Walle
2020-04-17  6:34       ` Michael Walle
2020-04-17  6:34       ` Michael Walle
2020-04-21 10:50       ` Michael Walle
2020-04-21 10:50         ` Michael Walle
2020-04-21 10:50         ` Michael Walle
2020-04-02 20:36 ` Michael Walle [this message]
2020-04-02 20:36   ` [PATCH v2 11/16] gpio: add support for the sl28cpld GPIO controller Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-16  8:34   ` Linus Walleij
2020-04-16  8:34     ` Linus Walleij
2020-04-16  8:34     ` Linus Walleij
2020-04-16  8:55     ` Michael Walle
2020-04-16  8:55       ` Michael Walle
2020-04-16  8:55       ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 12/16] hwmon: add support for the sl28cpld hardware monitoring controller Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 21:30   ` Guenter Roeck
2020-04-02 21:30     ` Guenter Roeck
2020-04-02 21:30     ` Guenter Roeck
2020-04-02 20:36 ` [PATCH v2 13/16] arm64: dts: freescale: sl28: enable sl28cpld Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 14/16] arm64: dts: freescale: sl28: map GPIOs to input events Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 15/16] arm64: dts: freescale: sl28: enable LED support Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36 ` [PATCH v2 16/16] arm64: dts: freescale: sl28: enable fan support Michael Walle
2020-04-02 20:36   ` Michael Walle
2020-04-02 20:36   ` Michael Walle

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=20200402203656.27047-12-michael@walle.cc \
    --to=michael@walle.cc \
    --cc=bgolaszewski@baylibre.com \
    --cc=broonie@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jason@lakedaemon.net \
    --cc=jdelvare@suse.com \
    --cc=lee.jones@linaro.org \
    --cc=leoyang.li@nxp.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=maz@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=shawnguo@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    --cc=wim@linux-watchdog.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 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.