diff mbox series

[2/4] ath79: add GPIO-latch driver for Mikrotik RB91xG

Message ID 20210506162514.5913-3-denis281089@gmail.com
State Superseded
Delegated to: Koen Vandeputte
Headers show
Series RFC: ath79: add support for Mikrotik RB91xG | expand

Commit Message

Denis Kalashnikov May 6, 2021, 4:25 p.m. UTC
This driver exports GPIO lines on the latch that are not
used for NAND control lines (but used for data lines).
It doesn't request byself SoC gpio lines and set them
through API provided by rb91x-ngl. Exported lines are used
for power LED, user LED and nCS of the Shift Register.

Signed-off-by: Denis Kalashnikov <denis281089@gmail.com>
---
 .../files/drivers/gpio/gpio-latch-rb91x.c     | 127 ++++++++++++++++++
 target/linux/ath79/mikrotik/config-default    |   1 +
 .../patches-5.4/939-mikrotik-rb91x.patch      |  23 ++++
 3 files changed, 151 insertions(+)
 create mode 100644 target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c

Comments

Sergey Ryazanov May 14, 2021, 3:04 a.m. UTC | #1
On Thu, May 6, 2021 at 7:32 PM Denis Kalashnikov <denis281089@gmail.com> wrote:

[skipped]

> +#define DRIVER_NAME  "rb91x-gpio-latch"

Maybe just "rb91x-gpio"? Looks like this board has no more crazy GPIO
controllers.

> +static int get(struct gpio_chip *gc, unsigned offset)
> +{
> +       return -ENOSYS;
> +}

[skipped]

> +static int direction_input(struct gpio_chip *gc, unsigned offset)
> +{
> +       return -ENOSYS;
> +}

Just drop these two callbacks and gpiolib will care about attempts to
toggle line direction to input on the output-only controller.

> +
> +static int direction_output(struct gpio_chip *gc, unsigned offset, int value)

Use driver name as function prefix.

> +{
> +       struct rb91x_ngl *ngl = gpiochip_get_data(gc);
> +
> +       ngl->latch_gpio_set_value(ngl, offset, value);
> +
> +       return 0;
> +}
> +
> +static int probe(struct platform_device *pdev)

ditto

> +{
> +       struct gpio_chip *gc;
> +       struct device_node *of_node = pdev->dev.of_node;
> +       struct device *dev = &pdev->dev, *parent = pdev->dev.parent;
> +       struct rb91x_ngl *ngl;
> +       int ret;
> +       u32 val;
> +
> +       pr_info(DRIVER_NAME " driver probe\n");

Remove this custom trace on final submission.

> +
> +       if (!parent)
> +               return -ENODEV;
> +
> +       gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
> +       if (!gc)
> +               return -ENOMEM;
> +
> +       /*
> +       ret = of_property_read_u32(of_node, "base", &val);
> +       if (ret < 0) {
> +               dev_err(dev, "Could not read required 'base' property\n");
> +               return -EINVAL;
> +       }
> +       pr_info(DRIVER_NAME ": base = %d\n", val);
> +       gc->base = val;
> +       */
> +       gc->base = -1; /* Request dynamic allocation */
> +
> +       ngl = dev_get_drvdata(parent);
> +       if (!ngl) {
> +               pr_err(DRIVER_NAME " ngl is null\n");

dev_err(dev, ...)

> +               return -EINVAL;
> +       }
> +
> +       gc->label = DRIVER_NAME;
> +       gc->parent = dev;
> +       gc->can_sleep = true;
> +       gc->ngpio = ngl->latch_gpios_count(ngl);
> +       gc->get = get;
> +       gc->set = set;
> +       gc->direction_input = direction_input,
> +       gc->direction_output = direction_output;
> +       gc->of_node = of_node;
> +
> +       platform_set_drvdata(pdev, gc);
> +
> +       ret = gpiochip_add_data(gc, ngl);
> +       if (ret) {
> +               pr_err(DRIVER_NAME ": failed to add gpio chip: %d\n", ret);

dev_err(dev, ...)

> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int remove(struct platform_device *pdev)
> +{
> +       gpiochip_remove(platform_get_drvdata(pdev));
> +       return 0;
> +}
> +
> +static const struct of_device_id match[] = {

Use the driver name as prefix for global variables too.

> +       { .compatible = "mikrotik," DRIVER_NAME },
> +       {},
> +};

--
Sergey
diff mbox series

Patch

diff --git a/target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c b/target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c
new file mode 100644
index 0000000000..f1ed8ebc96
--- /dev/null
+++ b/target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c
@@ -0,0 +1,127 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver of GPIO controller on a 8-bit NAND latch (LVC573) on MikroTik RB91x.
+ *
+ * Copyright (C) 2021 Denis Kalashnikov <denis281089@gmail.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include <mfd/rb91x-ngl.h>
+
+#define DRIVER_NAME  "rb91x-gpio-latch"
+
+static int get(struct gpio_chip *gc, unsigned offset)
+{
+	return -ENOSYS;
+}
+
+static void set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct rb91x_ngl *ngl = gpiochip_get_data(gc);
+
+	ngl->latch_gpio_set_value(ngl, offset, value);
+}
+
+static int direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	return -ENOSYS;
+}
+
+static int direction_output(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct rb91x_ngl *ngl = gpiochip_get_data(gc);
+
+	ngl->latch_gpio_set_value(ngl, offset, value);
+
+	return 0;
+}
+
+static int probe(struct platform_device *pdev)
+{
+	struct gpio_chip *gc;
+	struct device_node *of_node = pdev->dev.of_node;
+	struct device *dev = &pdev->dev, *parent = pdev->dev.parent;
+	struct rb91x_ngl *ngl;
+	int ret;
+	u32 val;
+
+	pr_info(DRIVER_NAME " driver probe\n");
+
+	if (!parent)
+		return -ENODEV;
+
+	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
+	if (!gc)
+		return -ENOMEM;
+
+	/*
+	ret = of_property_read_u32(of_node, "base", &val);
+	if (ret < 0) {
+		dev_err(dev, "Could not read required 'base' property\n");
+		return -EINVAL;
+	}
+	pr_info(DRIVER_NAME ": base = %d\n", val);
+	gc->base = val;
+	*/
+	gc->base = -1; /* Request dynamic allocation */
+
+	ngl = dev_get_drvdata(parent);
+	if (!ngl) {
+		pr_err(DRIVER_NAME " ngl is null\n");
+		return -EINVAL;
+	}
+
+	gc->label = DRIVER_NAME;
+	gc->parent = dev;
+	gc->can_sleep = true;
+	gc->ngpio = ngl->latch_gpios_count(ngl);
+	gc->get = get;
+	gc->set = set;
+	gc->direction_input = direction_input,
+	gc->direction_output = direction_output;
+	gc->of_node = of_node;
+
+	platform_set_drvdata(pdev, gc);
+
+	ret = gpiochip_add_data(gc, ngl);
+	if (ret) {
+		pr_err(DRIVER_NAME ": failed to add gpio chip: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int remove(struct platform_device *pdev)
+{
+	gpiochip_remove(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static const struct of_device_id match[] = {
+	{ .compatible = "mikrotik," DRIVER_NAME },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, match);
+
+static struct platform_driver rb91x_gpio_latch_driver = {
+	.probe = probe,
+	.remove = remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = match,
+	},
+};
+
+module_platform_driver(rb91x_gpio_latch_driver);
+
+MODULE_DESCRIPTION("Driver for GPIO on MikroTik RB91x NAND latch");
+MODULE_AUTHOR("Denis Kalashnikov <denis281089@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/ath79/mikrotik/config-default b/target/linux/ath79/mikrotik/config-default
index 67c980a491..92b7824eba 100644
--- a/target/linux/ath79/mikrotik/config-default
+++ b/target/linux/ath79/mikrotik/config-default
@@ -1,6 +1,7 @@ 
 CONFIG_CRC16=y
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_GPIO_LATCH=y
+CONFIG_GPIO_LATCH_RB91X=y
 CONFIG_GPIO_RB4XX=y
 CONFIG_GPIO_WATCHDOG=y
 CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y
diff --git a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch
index a85db0892c..f2135d486b 100644
--- a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch
+++ b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch
@@ -19,3 +19,26 @@ 
  obj-$(CONFIG_MFD_RB4XX_CPLD)	+= rb4xx-cpld.o
 +
 +obj-$(CONFIG_MFD_RB91X_NGL)	+= rb91x-ngl.o
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -130,6 +130,10 @@ config GPIO_ATH79
+ 	  Select this option to enable GPIO driver for
+ 	  Atheros AR71XX/AR724X/AR913X SoC devices.
+ 
++config GPIO_LATCH_RB91X
++	tristate "Mikrotik RB91X GPIO latch driver"
++	depends on MFD_RB91X_NGL
++
+ config GPIO_RASPBERRYPI_EXP
+ 	tristate "Raspberry Pi 3 GPIO Expander"
+ 	default RASPBERRYPI_FIRMWARE
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_IT87)			+= gpio-it87.o
+ obj-$(CONFIG_GPIO_IXP4XX)		+= gpio-ixp4xx.o
+ obj-$(CONFIG_GPIO_JANZ_TTL)		+= gpio-janz-ttl.o
+ obj-$(CONFIG_GPIO_KEMPLD)		+= gpio-kempld.o
++obj-$(CONFIG_GPIO_LATCH_RB91X)		+= gpio-latch-rb91x.o
+ obj-$(CONFIG_GPIO_LOONGSON1)		+= gpio-loongson1.o
+ obj-$(CONFIG_GPIO_LOONGSON)		+= gpio-loongson.o
+ obj-$(CONFIG_GPIO_LP3943)		+= gpio-lp3943.o