Re: [PATCH v6 07/13] gpio: add support for the sl28cpld GPIO controller

2020-07-26 Thread Andy Shevchenko
On Sun, Jul 26, 2020 at 01:18:28AM +0200, Michael Walle wrote:
> Add support for the GPIO controller of the sl28 board management
> controller. This driver is part of a multi-function device.
> 
> A controller has 8 lines. There are three different flavors:
> full-featured GPIO with interrupt support, input-only and output-only.

FWIW,
Reviewed-by: Andy Shevchenko 

> Signed-off-by: Michael Walle 
> Reviewed-by: Linus Walleij 
> ---
> Changes since v5:
>  - added "select REGMAP_IRQ"
> 
> Changes since v4:
>  - update copyright year
>  - remove #include , suggested by Andy.
>  - use device_get_match_data(), suggested by Andy.
>  - drop the irq_support variable, instead call _init_irq() directly,
>suggested by Andy.
>  - also move the irq code a bit around to make it look nicer
>  - drop "struct sl28cpld_gpio". We don't need to actually store the
>irq_chip and irq_chip_data, everything is device resource managed.
>  - use 100 chars line limit, suggested by Andy.
>  - remove the platform device table
>  - don't use KBUID_MODNAME
> 
> Changes since v3:
>  - see cover letter
> 
>  drivers/gpio/Kconfig |  12 +++
>  drivers/gpio/Makefile|   1 +
>  drivers/gpio/gpio-sl28cpld.c | 161 +++
>  3 files changed, 174 insertions(+)
>  create mode 100644 drivers/gpio/gpio-sl28cpld.c
> 
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 8030fd91a3cc..f6a547b76432 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -1223,6 +1223,18 @@ 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 sl28cpld GPIO support"
> + select MFD_SIMPLE_MFD_I2C
> + select GPIO_REGMAP
> + select GPIOLIB_IRQCHIP
> + select REGMAP_IRQ
> + 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 4f9abff4f2dc..c3a4e7c94a91 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -132,6 +132,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 ..889b8f5622c2
> --- /dev/null
> +++ b/drivers/gpio/gpio-sl28cpld.c
> @@ -0,0 +1,161 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * sl28cpld GPIO driver
> + *
> + * Copyright 2020 Michael Walle 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/* 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,
> +};
> +
> +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 platform_device *pdev,
> +   unsigned int base,
> +   struct gpio_regmap_config *config)
> +{
> + struct regmap_irq_chip_data *irq_data;
> + struct regmap_irq_chip *irq_chip;
> + struct device *dev = >dev;
> + int irq, ret;
> +
> + if (!device_property_read_bool(dev, "interrupt-controller"))
> + return 0;
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return irq;
> +
> + irq_chip = devm_kzalloc(dev, sizeof(*irq_chip), GFP_KERNEL);
> + if (!irq_chip)
> + return -ENOMEM;
> +
> + 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 + 

[PATCH v6 07/13] gpio: add support for the sl28cpld GPIO controller

2020-07-25 Thread Michael Walle
Add support for the GPIO controller of the sl28 board management
controller. This driver is part of a multi-function device.

A controller has 8 lines. There are three different flavors:
full-featured GPIO with interrupt support, input-only and output-only.

Signed-off-by: Michael Walle 
Reviewed-by: Linus Walleij 
---
Changes since v5:
 - added "select REGMAP_IRQ"

Changes since v4:
 - update copyright year
 - remove #include , suggested by Andy.
 - use device_get_match_data(), suggested by Andy.
 - drop the irq_support variable, instead call _init_irq() directly,
   suggested by Andy.
 - also move the irq code a bit around to make it look nicer
 - drop "struct sl28cpld_gpio". We don't need to actually store the
   irq_chip and irq_chip_data, everything is device resource managed.
 - use 100 chars line limit, suggested by Andy.
 - remove the platform device table
 - don't use KBUID_MODNAME

Changes since v3:
 - see cover letter

 drivers/gpio/Kconfig |  12 +++
 drivers/gpio/Makefile|   1 +
 drivers/gpio/gpio-sl28cpld.c | 161 +++
 3 files changed, 174 insertions(+)
 create mode 100644 drivers/gpio/gpio-sl28cpld.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8030fd91a3cc..f6a547b76432 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1223,6 +1223,18 @@ 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 sl28cpld GPIO support"
+   select MFD_SIMPLE_MFD_I2C
+   select GPIO_REGMAP
+   select GPIOLIB_IRQCHIP
+   select REGMAP_IRQ
+   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 4f9abff4f2dc..c3a4e7c94a91 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -132,6 +132,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 ..889b8f5622c2
--- /dev/null
+++ b/drivers/gpio/gpio-sl28cpld.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sl28cpld GPIO driver
+ *
+ * Copyright 2020 Michael Walle 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* GPIO flavor */
+#define GPIO_REG_DIR   0x00
+#define GPIO_REG_OUT   0x01
+#define GPIO_REG_IN0x02
+#define GPIO_REG_IE0x03
+#define GPIO_REG_IP0x04
+
+/* input-only flavor */
+#define GPI_REG_IN 0x00
+
+/* output-only flavor */
+#define GPO_REG_OUT0x00
+
+enum sl28cpld_gpio_type {
+   SL28CPLD_GPIO = 1,
+   SL28CPLD_GPI,
+   SL28CPLD_GPO,
+};
+
+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 platform_device *pdev,
+ unsigned int base,
+ struct gpio_regmap_config *config)
+{
+   struct regmap_irq_chip_data *irq_data;
+   struct regmap_irq_chip *irq_chip;
+   struct device *dev = >dev;
+   int irq, ret;
+
+   if (!device_property_read_bool(dev, "interrupt-controller"))
+   return 0;
+
+   irq = platform_get_irq(pdev, 0);
+   if (irq < 0)
+   return irq;
+
+   irq_chip = devm_kzalloc(dev, sizeof(*irq_chip), GFP_KERNEL);
+   if (!irq_chip)
+   return -ENOMEM;
+
+   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;
+
+   ret = devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev),
+ config->regmap, irq,
+ IRQF_SHARED |