linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V4] gpio: New driver for LSI ZEVIO SoCs
@ 2013-08-25 19:49 Fabian Vogt
  2013-08-26 16:58 ` Stephen Warren
  2013-08-27 14:40 ` Mark Rutland
  0 siblings, 2 replies; 4+ messages in thread
From: Fabian Vogt @ 2013-08-25 19:49 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-kernel, linux-doc, devicetree, linus.walleij, grant.likely,
	pawel.moll, rob.herring, mark.rutland, swarren, ian.campbell,
	Fabian Vogt

This driver supports the GPIO controller found in LSI ZEVIO SoCs.
It has been successfully tested on a TI nspire CX calculator.
---
 .../devicetree/bindings/gpio/gpio-zevio.txt        |  18 ++
 drivers/gpio/Kconfig                               |   6 +
 drivers/gpio/Makefile                              |   1 +
 drivers/gpio/gpio-zevio.c                          | 214 +++++++++++++++++++++
 4 files changed, 239 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio-zevio.txt
 create mode 100644 drivers/gpio/gpio-zevio.c

diff --git a/Documentation/devicetree/bindings/gpio/gpio-zevio.txt b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
new file mode 100644
index 0000000..892f953
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
@@ -0,0 +1,18 @@
+Zevio GPIO controller
+
+Required properties:
+- compatible = "lsi,zevio-gpio"
+- reg = <BASEADDR SIZE>
+- #gpio-cells = <2>
+- gpio-controller;
+
+Optional:
+- #ngpios = <32>: Number of GPIOs. Defaults to 32 if absent
+
+Example:
+	gpio: gpio@90000000 {
+		compatible = "lsi,zevio-gpio";
+		reg = <0x90000000 0x1000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b2450ba..49f8c62 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -138,6 +138,12 @@ config GPIO_EP93XX
 	depends on ARCH_EP93XX
 	select GPIO_GENERIC
 
+config GPIO_ZEVIO
+	bool "LSI ZEVIO SoC memory mapped GPIOs"
+	depends on OF
+	help
+	  Say yes here to support the GPIO controller in LSI ZEVIO SoCs.
+
 config GPIO_MM_LANTIQ
 	bool "Lantiq Memory mapped GPIOs"
 	depends on LANTIQ && SOC_XWAY
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ef3e983..b70cb1b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -87,3 +87,4 @@ obj-$(CONFIG_GPIO_WM831X)	+= gpio-wm831x.o
 obj-$(CONFIG_GPIO_WM8350)	+= gpio-wm8350.o
 obj-$(CONFIG_GPIO_WM8994)	+= gpio-wm8994.o
 obj-$(CONFIG_GPIO_XILINX)	+= gpio-xilinx.o
+obj-$(CONFIG_GPIO_ZEVIO)	+= gpio-zevio.o
diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
new file mode 100644
index 0000000..35a254b
--- /dev/null
+++ b/drivers/gpio/gpio-zevio.c
@@ -0,0 +1,214 @@
+/*
+ * GPIO controller in LSI ZEVIO SoCs.
+ *
+ * Author: Fabian Vogt <fabian@ritter-vogt.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+/*
+ * Memory layout:
+ * This chip has four gpio sections, each controls 8 GPIOs.
+ * Bit 0 in section 0 is GPIO 0, bit 2 in section 1 is GPIO 10.
+ * Disclaimer: Reverse engineered!
+ * For more information refer to:
+ * http://hackspire.unsads.com/wiki/index.php/Memory-mapped_I/O_ports#90000000_-_General_Purpose_I.2FO_.28GPIO.29
+ *
+ * 0x00-0x3F: Section 0
+ *     +0x00: Masked interrupt status (read-only)
+ *     +0x04: R: Interrupt status W: Reset interrupt status
+ *     +0x08: R: Interrupt mask W: Mask interrupt
+ *     +0x0C: W: Unmask interrupt (write-only)
+ *     +0x10: Direction: I/O=1/0
+ *     +0x14: Output
+ *     +0x18: Input (read-only)
+ *     +0x20: R: Level interrupt W: Set as level interrupt
+ * 0x40-0x7F: Section 1
+ * 0x80-0xBF: Section 2
+ * 0xC0-0xFF: Section 3
+ */
+
+#define ZEVIO_GPIO_SECTION_SIZE			0x40
+
+#define ZEVIO_GPIO_INT_MASKED_STATUS_OFFSET	0x00
+#define ZEVIO_GPIO_INT_STATUS_OFFSET		0x04
+#define ZEVIO_GPIO_INT_UNMASK_OFFSET		0x08
+#define ZEVIO_GPIO_INT_MASK_OFFSET		0x0C
+#define ZEVIO_GPIO_DIRECTION_OFFSET		0x10
+#define ZEVIO_GPIO_OUTPUT_OFFSET		0x14
+#define ZEVIO_GPIO_INPUT_OFFSET			0x18
+#define ZEVIO_GPIO_INT_STICKY_OFFSET		0x20
+
+#define to_zevio_gpio(chip) container_of(to_of_mm_gpio_chip(chip), \
+				struct zevio_gpio, chip)
+
+/* Bit of GPIO in section */
+#define ZEVIO_GPIO_BIT(gpio) (gpio&7)
+/* Offset to section of GPIO relative to base */
+#define ZEVIO_GPIO_SECTION_OFFSET(gpio) (((gpio>>3)&3)*ZEVIO_GPIO_SECTION_SIZE)
+/* Address of register, which is responsible for given GPIO */
+#define ZEVIO_GPIO(cntrlr, gpio, reg) IOMEM(cntrlr->chip.regs + \
+		ZEVIO_GPIO_SECTION_OFFSET(gpio) + ZEVIO_GPIO_##reg##_OFFSET)
+
+struct zevio_gpio {
+	spinlock_t		lock;
+	struct of_mm_gpio_chip	chip;
+};
+
+/* Functions for struct gpio_chip */
+static int zevio_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+	struct zevio_gpio *controller = to_zevio_gpio(chip);
+
+	/* Only reading allowed, so no spinlock needed */
+	u32 val = readl(ZEVIO_GPIO(controller, pin, INPUT));
+
+	return (val >> ZEVIO_GPIO_BIT(pin)) & 0x1;
+}
+
+static void zevio_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
+{
+	struct zevio_gpio *controller = to_zevio_gpio(chip);
+	u32 val;
+
+	spin_lock(&controller->lock);
+	val = readl(ZEVIO_GPIO(controller, pin, OUTPUT));
+	if (value)
+		val |= BIT(ZEVIO_GPIO_BIT(pin));
+	else
+		val &= ~(BIT(ZEVIO_GPIO_BIT(pin)));
+
+	writel(val, ZEVIO_GPIO(controller, pin, OUTPUT));
+	spin_unlock(&controller->lock);
+}
+
+static int zevio_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+{
+	struct zevio_gpio *controller = to_zevio_gpio(chip);
+	u32 val;
+
+	spin_lock(&controller->lock);
+
+	val = readl(ZEVIO_GPIO(controller, pin, DIRECTION));
+	val |= BIT(ZEVIO_GPIO_BIT(pin));
+	writel(val, ZEVIO_GPIO(controller, pin, DIRECTION));
+
+	spin_unlock(&controller->lock);
+
+	return 0;
+}
+
+static int zevio_gpio_direction_output(struct gpio_chip *chip,
+				       unsigned pin, int value)
+{
+	struct zevio_gpio *controller = to_zevio_gpio(chip);
+	u32 val;
+
+	spin_lock(&controller->lock);
+	val = readl(ZEVIO_GPIO(controller, pin, OUTPUT));
+	if (value)
+		val |= BIT(ZEVIO_GPIO_BIT(pin));
+	else
+		val &= ~(BIT(ZEVIO_GPIO_BIT(pin)));
+
+	writel(val, ZEVIO_GPIO(controller, pin, OUTPUT));
+	val = readl(ZEVIO_GPIO(controller, pin, DIRECTION));
+	val &= ~(BIT(ZEVIO_GPIO_BIT(pin)));
+	writel(val, ZEVIO_GPIO(controller, pin, DIRECTION));
+
+	spin_unlock(&controller->lock);
+
+	return 0;
+}
+
+static int zevio_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	/* TODO: Implement IRQs.
+           Not implemented yet due to weird lockups */
+
+	return -ENXIO;
+}
+
+static struct gpio_chip zevio_gpio_chip = {
+	.direction_input	= zevio_gpio_direction_input,
+	.direction_output	= zevio_gpio_direction_output,
+	.set			= zevio_gpio_set,
+	.get			= zevio_gpio_get,
+	.to_irq			= zevio_gpio_to_irq,
+	.base			= 0,
+	.owner			= THIS_MODULE,
+	.ngpio			= 32, /* Default, if not given in DT */
+	.of_gpio_n_cells	= 2,
+};
+
+/* Initialization */
+static int zevio_gpio_probe(struct platform_device *pdev)
+{
+	struct zevio_gpio *controller;
+	int status, i;
+	u32 ngpio;
+
+	controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL);
+	if (!controller) {
+		dev_err(&pdev->dev, "not enough free memory\n");
+		return -ENOMEM;
+	}
+
+	/* Copy our reference */
+	controller->chip.gc = zevio_gpio_chip;
+	controller->chip.gc.dev = &pdev->dev;
+
+	if (!of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio))
+		controller->chip.gc.ngpio = ngpio;
+
+	status = of_mm_gpiochip_add(pdev->dev.of_node, &(controller->chip));
+	if (status) {
+		kfree(controller);
+		dev_err(&pdev->dev, "failed to add gpiochip: %d\n", status);
+		return status;
+	}
+
+	spin_lock_init(&(controller->lock));
+
+	/* Disable interrupts, they only cause errors */
+	for (i = 0; i < controller->chip.gc.ngpio; i += 8)
+		writel(0xFF, ZEVIO_GPIO(controller, i, INT_MASK));
+
+	dev_dbg(controller->chip.gc.dev, "ZEVIO GPIO controller set up!\n");
+
+	return 0;
+}
+
+static struct of_device_id zevio_gpio_of_match[] = {
+	{ .compatible = "lsi,zevio-gpio", },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(of, zevio_gpio_of_match);
+
+static struct platform_driver zevio_gpio_driver = {
+	.driver		= {
+		.name	= "gpio-zevio",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(zevio_gpio_of_match),
+	},
+	.probe		= zevio_gpio_probe,
+};
+
+module_platform_driver(zevio_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fabian Vogt <fabian@ritter-vogt.de>");
+MODULE_DESCRIPTION("LSI ZEVIO SoC GPIO driver");
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH V4] gpio: New driver for LSI ZEVIO SoCs
  2013-08-25 19:49 [PATCH V4] gpio: New driver for LSI ZEVIO SoCs Fabian Vogt
@ 2013-08-26 16:58 ` Stephen Warren
  2013-08-27 14:40 ` Mark Rutland
  1 sibling, 0 replies; 4+ messages in thread
From: Stephen Warren @ 2013-08-26 16:58 UTC (permalink / raw)
  To: Fabian Vogt
  Cc: linux-gpio, linux-kernel, linux-doc, devicetree, linus.walleij,
	grant.likely, pawel.moll, rob.herring, mark.rutland,
	ian.campbell

On 08/25/2013 01:49 PM, Fabian Vogt wrote:
> This driver supports the GPIO controller found in LSI ZEVIO SoCs.
> It has been successfully tested on a TI nspire CX calculator.

> diff --git a/Documentation/devicetree/bindings/gpio/gpio-zevio.txt b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt

> +Optional:
> +- #ngpios = <32>: Number of GPIOs. Defaults to 32 if absent

I think the GPIO count should be derived from the compatible value
instead. If it turns out there's a clear need for the property, it can
be added later in a backwards-compatible way.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V4] gpio: New driver for LSI ZEVIO SoCs
  2013-08-25 19:49 [PATCH V4] gpio: New driver for LSI ZEVIO SoCs Fabian Vogt
  2013-08-26 16:58 ` Stephen Warren
@ 2013-08-27 14:40 ` Mark Rutland
  2013-08-27 20:11   ` Stephen Warren
  1 sibling, 1 reply; 4+ messages in thread
From: Mark Rutland @ 2013-08-27 14:40 UTC (permalink / raw)
  To: Fabian Vogt
  Cc: linux-gpio, linux-kernel, linux-doc, devicetree, linus.walleij,
	grant.likely, Pawel Moll, rob.herring, swarren, ian.campbell

On Sun, Aug 25, 2013 at 08:49:40PM +0100, Fabian Vogt wrote:
> This driver supports the GPIO controller found in LSI ZEVIO SoCs.
> It has been successfully tested on a TI nspire CX calculator.
> ---
>  .../devicetree/bindings/gpio/gpio-zevio.txt        |  18 ++
>  drivers/gpio/Kconfig                               |   6 +
>  drivers/gpio/Makefile                              |   1 +
>  drivers/gpio/gpio-zevio.c                          | 214 +++++++++++++++++++++
>  4 files changed, 239 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-zevio.txt
>  create mode 100644 drivers/gpio/gpio-zevio.c
> 
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-zevio.txt b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
> new file mode 100644
> index 0000000..892f953
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
> @@ -0,0 +1,18 @@
> +Zevio GPIO controller
> +
> +Required properties:
> +- compatible = "lsi,zevio-gpio"
> +- reg = <BASEADDR SIZE>
> +- #gpio-cells = <2>
> +- gpio-controller;

I take it there's nothing else known about at present that we might want
to describe in future (e.g. input clocks)?

This is more for the other dt maintainers, but I've seen a lot of
variation in how we describe properties, and it would be nice to unify
that. Does anyone fancy writing a document pushing for some standard
terminology and formatting, or should I?

> +
> +Optional:
> +- #ngpios = <32>: Number of GPIOs. Defaults to 32 if absent
> +
> +Example:
> +	gpio: gpio@90000000 {
> +		compatible = "lsi,zevio-gpio";
> +		reg = <0x90000000 0x1000>;
> +		gpio-controller;
> +		#gpio-cells = <2>;
> +	};
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index b2450ba..49f8c62 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -138,6 +138,12 @@ config GPIO_EP93XX
>  	depends on ARCH_EP93XX
>  	select GPIO_GENERIC
>  
> +config GPIO_ZEVIO
> +	bool "LSI ZEVIO SoC memory mapped GPIOs"
> +	depends on OF
> +	help
> +	  Say yes here to support the GPIO controller in LSI ZEVIO SoCs.
> +
>  config GPIO_MM_LANTIQ
>  	bool "Lantiq Memory mapped GPIOs"
>  	depends on LANTIQ && SOC_XWAY
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index ef3e983..b70cb1b 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -87,3 +87,4 @@ obj-$(CONFIG_GPIO_WM831X)	+= gpio-wm831x.o
>  obj-$(CONFIG_GPIO_WM8350)	+= gpio-wm8350.o
>  obj-$(CONFIG_GPIO_WM8994)	+= gpio-wm8994.o
>  obj-$(CONFIG_GPIO_XILINX)	+= gpio-xilinx.o
> +obj-$(CONFIG_GPIO_ZEVIO)	+= gpio-zevio.o
> diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
> new file mode 100644
> index 0000000..35a254b
> --- /dev/null
> +++ b/drivers/gpio/gpio-zevio.c
> @@ -0,0 +1,214 @@
> +/*
> + * GPIO controller in LSI ZEVIO SoCs.
> + *
> + * Author: Fabian Vogt <fabian@ritter-vogt.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/spinlock.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/of_device.h>
> +#include <linux/of_gpio.h>
> +#include <linux/slab.h>
> +#include <linux/gpio.h>
> +
> +/*
> + * Memory layout:
> + * This chip has four gpio sections, each controls 8 GPIOs.
> + * Bit 0 in section 0 is GPIO 0, bit 2 in section 1 is GPIO 10.
> + * Disclaimer: Reverse engineered!
> + * For more information refer to:
> + * http://hackspire.unsads.com/wiki/index.php/Memory-mapped_I/O_ports#90000000_-_General_Purpose_I.2FO_.28GPIO.29
> + *
> + * 0x00-0x3F: Section 0
> + *     +0x00: Masked interrupt status (read-only)
> + *     +0x04: R: Interrupt status W: Reset interrupt status
> + *     +0x08: R: Interrupt mask W: Mask interrupt
> + *     +0x0C: W: Unmask interrupt (write-only)
> + *     +0x10: Direction: I/O=1/0
> + *     +0x14: Output
> + *     +0x18: Input (read-only)
> + *     +0x20: R: Level interrupt W: Set as level interrupt
> + * 0x40-0x7F: Section 1
> + * 0x80-0xBF: Section 2
> + * 0xC0-0xFF: Section 3
> + */
> +
> +#define ZEVIO_GPIO_SECTION_SIZE			0x40
> +
> +#define ZEVIO_GPIO_INT_MASKED_STATUS_OFFSET	0x00
> +#define ZEVIO_GPIO_INT_STATUS_OFFSET		0x04
> +#define ZEVIO_GPIO_INT_UNMASK_OFFSET		0x08
> +#define ZEVIO_GPIO_INT_MASK_OFFSET		0x0C
> +#define ZEVIO_GPIO_DIRECTION_OFFSET		0x10
> +#define ZEVIO_GPIO_OUTPUT_OFFSET		0x14
> +#define ZEVIO_GPIO_INPUT_OFFSET			0x18
> +#define ZEVIO_GPIO_INT_STICKY_OFFSET		0x20
> +
> +#define to_zevio_gpio(chip) container_of(to_of_mm_gpio_chip(chip), \
> +				struct zevio_gpio, chip)
> +
> +/* Bit of GPIO in section */
> +#define ZEVIO_GPIO_BIT(gpio) (gpio&7)
> +/* Offset to section of GPIO relative to base */
> +#define ZEVIO_GPIO_SECTION_OFFSET(gpio) (((gpio>>3)&3)*ZEVIO_GPIO_SECTION_SIZE)

Some spacing in these would really aid readability.

> +/* Address of register, which is responsible for given GPIO */
> +#define ZEVIO_GPIO(cntrlr, gpio, reg) IOMEM(cntrlr->chip.regs + \
> +		ZEVIO_GPIO_SECTION_OFFSET(gpio) + ZEVIO_GPIO_##reg##_OFFSET)
> +
> +struct zevio_gpio {
> +	spinlock_t		lock;
> +	struct of_mm_gpio_chip	chip;
> +};
> +
> +/* Functions for struct gpio_chip */
> +static int zevio_gpio_get(struct gpio_chip *chip, unsigned pin)
> +{
> +	struct zevio_gpio *controller = to_zevio_gpio(chip);
> +
> +	/* Only reading allowed, so no spinlock needed */
> +	u32 val = readl(ZEVIO_GPIO(controller, pin, INPUT));
> +
> +	return (val >> ZEVIO_GPIO_BIT(pin)) & 0x1;
> +}
> +
> +static void zevio_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
> +{
> +	struct zevio_gpio *controller = to_zevio_gpio(chip);
> +	u32 val;
> +
> +	spin_lock(&controller->lock);
> +	val = readl(ZEVIO_GPIO(controller, pin, OUTPUT));
> +	if (value)
> +		val |= BIT(ZEVIO_GPIO_BIT(pin));
> +	else
> +		val &= ~(BIT(ZEVIO_GPIO_BIT(pin)));
> +
> +	writel(val, ZEVIO_GPIO(controller, pin, OUTPUT));
> +	spin_unlock(&controller->lock);
> +}
> +
> +static int zevio_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
> +{
> +	struct zevio_gpio *controller = to_zevio_gpio(chip);
> +	u32 val;
> +
> +	spin_lock(&controller->lock);
> +
> +	val = readl(ZEVIO_GPIO(controller, pin, DIRECTION));
> +	val |= BIT(ZEVIO_GPIO_BIT(pin));
> +	writel(val, ZEVIO_GPIO(controller, pin, DIRECTION));
> +
> +	spin_unlock(&controller->lock);
> +
> +	return 0;
> +}
> +
> +static int zevio_gpio_direction_output(struct gpio_chip *chip,
> +				       unsigned pin, int value)
> +{
> +	struct zevio_gpio *controller = to_zevio_gpio(chip);
> +	u32 val;
> +
> +	spin_lock(&controller->lock);
> +	val = readl(ZEVIO_GPIO(controller, pin, OUTPUT));
> +	if (value)
> +		val |= BIT(ZEVIO_GPIO_BIT(pin));
> +	else
> +		val &= ~(BIT(ZEVIO_GPIO_BIT(pin)));
> +
> +	writel(val, ZEVIO_GPIO(controller, pin, OUTPUT));
> +	val = readl(ZEVIO_GPIO(controller, pin, DIRECTION));
> +	val &= ~(BIT(ZEVIO_GPIO_BIT(pin)));
> +	writel(val, ZEVIO_GPIO(controller, pin, DIRECTION));
> +
> +	spin_unlock(&controller->lock);
> +
> +	return 0;
> +}
> +
> +static int zevio_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
> +{
> +	/* TODO: Implement IRQs.
> +           Not implemented yet due to weird lockups */

	/*
	 * Normally our multi-line block comments look something like
	 * this, with aligned asterisks down the left-hand side.
	 */

> +
> +	return -ENXIO;
> +}
> +
> +static struct gpio_chip zevio_gpio_chip = {
> +	.direction_input	= zevio_gpio_direction_input,
> +	.direction_output	= zevio_gpio_direction_output,
> +	.set			= zevio_gpio_set,
> +	.get			= zevio_gpio_get,
> +	.to_irq			= zevio_gpio_to_irq,
> +	.base			= 0,
> +	.owner			= THIS_MODULE,
> +	.ngpio			= 32, /* Default, if not given in DT */
> +	.of_gpio_n_cells	= 2,
> +};
> +
> +/* Initialization */
> +static int zevio_gpio_probe(struct platform_device *pdev)
> +{
> +	struct zevio_gpio *controller;
> +	int status, i;
> +	u32 ngpio;
> +
> +	controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL);
> +	if (!controller) {
> +		dev_err(&pdev->dev, "not enough free memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Copy our reference */
> +	controller->chip.gc = zevio_gpio_chip;
> +	controller->chip.gc.dev = &pdev->dev;
> +
> +	if (!of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio))
> +		controller->chip.gc.ngpio = ngpio;
> +
> +	status = of_mm_gpiochip_add(pdev->dev.of_node, &(controller->chip));
> +	if (status) {
> +		kfree(controller);

You shouldn't mix up the devm_* functions with their non devm_*
variants. devm_kzalloc should only be used with devm_kfree. Even better,
if you return an error in your probe function, the devm_kfree will
happen automatically anyway.

> +		dev_err(&pdev->dev, "failed to add gpiochip: %d\n", status);
> +		return status;
> +	}
> +
> +	spin_lock_init(&(controller->lock));

I don't think you need those inner brackets.

> +
> +	/* Disable interrupts, they only cause errors */
> +	for (i = 0; i < controller->chip.gc.ngpio; i += 8)
> +		writel(0xFF, ZEVIO_GPIO(controller, i, INT_MASK));

I thought I must have lost some context here, but I see that ZEVIO_GPIO
does some concatenation to get ZEVIO_GPIO_INT_MASK_OFFSET. I'm not sure
if people have any feelings on that kind of thing in drivers.

Thanks,
Mark.

> +
> +	dev_dbg(controller->chip.gc.dev, "ZEVIO GPIO controller set up!\n");
> +
> +	return 0;
> +}
> +
> +static struct of_device_id zevio_gpio_of_match[] = {
> +	{ .compatible = "lsi,zevio-gpio", },
> +	{ },
> +};
> +
> +MODULE_DEVICE_TABLE(of, zevio_gpio_of_match);
> +
> +static struct platform_driver zevio_gpio_driver = {
> +	.driver		= {
> +		.name	= "gpio-zevio",
> +		.owner	= THIS_MODULE,
> +		.of_match_table = of_match_ptr(zevio_gpio_of_match),
> +	},
> +	.probe		= zevio_gpio_probe,
> +};
> +
> +module_platform_driver(zevio_gpio_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Fabian Vogt <fabian@ritter-vogt.de>");
> +MODULE_DESCRIPTION("LSI ZEVIO SoC GPIO driver");
> -- 
> 1.8.1.4
> 
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V4] gpio: New driver for LSI ZEVIO SoCs
  2013-08-27 14:40 ` Mark Rutland
@ 2013-08-27 20:11   ` Stephen Warren
  0 siblings, 0 replies; 4+ messages in thread
From: Stephen Warren @ 2013-08-27 20:11 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Fabian Vogt, linux-gpio, linux-kernel, linux-doc, devicetree,
	linus.walleij, grant.likely, Pawel Moll, rob.herring,
	ian.campbell

On 08/27/2013 08:40 AM, Mark Rutland wrote:
> On Sun, Aug 25, 2013 at 08:49:40PM +0100, Fabian Vogt wrote:
>> This driver supports the GPIO controller found in LSI ZEVIO SoCs.
>> It has been successfully tested on a TI nspire CX calculator.
>> ---
>>  .../devicetree/bindings/gpio/gpio-zevio.txt        |  18 ++
>>  drivers/gpio/Kconfig                               |   6 +
>>  drivers/gpio/Makefile                              |   1 +
>>  drivers/gpio/gpio-zevio.c                          | 214 +++++++++++++++++++++
>>  4 files changed, 239 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-zevio.txt
>>  create mode 100644 drivers/gpio/gpio-zevio.c
>>
>> diff --git a/Documentation/devicetree/bindings/gpio/gpio-zevio.txt b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
>> new file mode 100644
>> index 0000000..892f953
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/gpio/gpio-zevio.txt
>> @@ -0,0 +1,18 @@
>> +Zevio GPIO controller
>> +
>> +Required properties:
>> +- compatible = "lsi,zevio-gpio"
>> +- reg = <BASEADDR SIZE>
>> +- #gpio-cells = <2>
>> +- gpio-controller;
> 
> I take it there's nothing else known about at present that we might want
> to describe in future (e.g. input clocks)?
> 
> This is more for the other dt maintainers, but I've seen a lot of
> variation in how we describe properties, and it would be nice to unify
> that. Does anyone fancy writing a document pushing for some standard
> terminology and formatting, or should I?

I was hoping that the DT schema system would tighten this up, since
there would be specific syntax in the schema to describe all these options.

I was thinking of writing a DT binding review checklist, but so far
haven't made time to do so. It'd probably be reasonable to include any
specific wording requirements for property descriptions in that document.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-08-27 20:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-25 19:49 [PATCH V4] gpio: New driver for LSI ZEVIO SoCs Fabian Vogt
2013-08-26 16:58 ` Stephen Warren
2013-08-27 14:40 ` Mark Rutland
2013-08-27 20:11   ` Stephen Warren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).