linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 0/5] pinctrl: SPEAr Updates
@ 2012-05-03 10:12 Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 1/5] pinctrl: SPEAr: Don't set all non muxreg bits on pinctrl_disable Viresh Kumar
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Viresh Kumar @ 2012-05-03 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Linus,

This patchset mainly focuses on providing support to configure SPEAr pads as
gpios. For this i have added a gpiolib based driver and few changes in other
SPEAr pinctrl drivers.

It also contains minor fixes.

V1->V2:
- Passing gpio node via DT. Patch for this support in gpiolib is
  gpiolib: Add of_get_gpio_chip_by_phandle() helper
- Other minor fixes

Viresh Kumar (5):
  pinctrl: SPEAr: Don't set all non muxreg bits on pinctrl_disable
  pinctrl: SPEAr1310: Fix pin numbers for clcd_high_res
  pinctrl: SPEAr: Add plgpio driver
  pinctrl: SPEAr: Add gpio ranges support
  SPEAr: Add plgpio node in device tree dtsi files

 arch/arm/boot/dts/spear1310-evb.dts       |    4 +
 arch/arm/boot/dts/spear1310.dtsi          |   22 +
 arch/arm/boot/dts/spear1340-evb.dts       |    4 +
 arch/arm/boot/dts/spear1340.dtsi          |   21 +
 arch/arm/boot/dts/spear310-evb.dts        |    4 +
 arch/arm/boot/dts/spear310.dtsi           |   15 +
 arch/arm/boot/dts/spear320-evb.dts        |    4 +
 arch/arm/boot/dts/spear320.dtsi           |   16 +
 drivers/pinctrl/spear/Kconfig             |   11 +
 drivers/pinctrl/spear/Makefile            |    1 +
 drivers/pinctrl/spear/pinctrl-plgpio.c    |  738 ++++++++++++++++++++++++++
 drivers/pinctrl/spear/pinctrl-spear.c     |  110 ++++-
 drivers/pinctrl/spear/pinctrl-spear.h     |   15 +
 drivers/pinctrl/spear/pinctrl-spear1310.c |  812 ++++++++++++++++++++++++++++-
 drivers/pinctrl/spear/pinctrl-spear1340.c |    8 +
 drivers/pinctrl/spear/pinctrl-spear300.c  |    2 +
 drivers/pinctrl/spear/pinctrl-spear310.c  |    2 +
 drivers/pinctrl/spear/pinctrl-spear320.c  |    2 +
 drivers/pinctrl/spear/pinctrl-spear3xx.c  |  120 +++++
 19 files changed, 1898 insertions(+), 13 deletions(-)
 create mode 100644 drivers/pinctrl/spear/pinctrl-plgpio.c

-- 
1.7.9

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

* [PATCH V2 1/5] pinctrl: SPEAr: Don't set all non muxreg bits on pinctrl_disable
  2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
@ 2012-05-03 10:12 ` Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 2/5] pinctrl: SPEAr1310: Fix pin numbers for clcd_high_res Viresh Kumar
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Viresh Kumar @ 2012-05-03 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/pinctrl/spear/pinctrl-spear.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 5ae50aa..8653569 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 			else
 				temp = ~muxreg->val;
 
-			val |= temp;
+			val |= muxreg->mask & temp;
 			pmx_writel(pmx, val, muxreg->reg);
 		}
 	}
-- 
1.7.9

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

* [PATCH V2 2/5] pinctrl: SPEAr1310: Fix pin numbers for clcd_high_res
  2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 1/5] pinctrl: SPEAr: Don't set all non muxreg bits on pinctrl_disable Viresh Kumar
@ 2012-05-03 10:12 ` Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 3/5] pinctrl: SPEAr: Add plgpio driver Viresh Kumar
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Viresh Kumar @ 2012-05-03 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/pinctrl/spear/pinctrl-spear1310.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index 12b094d..fff168b 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -437,7 +437,7 @@ static struct spear_pingroup clcd_pingroup = {
 };
 
 static const unsigned clcd_high_res_pins[] = { 30, 31, 32, 33, 34, 35, 36, 37,
-	38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 };
+	38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
 static struct spear_muxreg clcd_high_res_muxreg[] = {
 	{
 		.reg = PAD_FUNCTION_EN_1,
-- 
1.7.9

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

* [PATCH V2 3/5] pinctrl: SPEAr: Add plgpio driver
  2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 1/5] pinctrl: SPEAr: Don't set all non muxreg bits on pinctrl_disable Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 2/5] pinctrl: SPEAr1310: Fix pin numbers for clcd_high_res Viresh Kumar
@ 2012-05-03 10:12 ` Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support Viresh Kumar
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Viresh Kumar @ 2012-05-03 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Most of SPEAr SoCs, which support pinctrl, can configure & use pads as gpio.
This patch adds plgpio driver for configuring these pads as gpio.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/pinctrl/spear/Kconfig          |    7 +
 drivers/pinctrl/spear/Makefile         |    1 +
 drivers/pinctrl/spear/pinctrl-plgpio.c |  738 ++++++++++++++++++++++++++++++++
 3 files changed, 746 insertions(+), 0 deletions(-)
 create mode 100644 drivers/pinctrl/spear/pinctrl-plgpio.c

diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 91558791..6f9a1e8 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -41,4 +41,11 @@ config PINCTRL_SPEAR1340
 	depends on MACH_SPEAR1340
 	select PINCTRL_SPEAR
 
+config PINCTRL_SPEAR_PLGPIO
+	bool "SPEAr SoC PLGPIO Controller"
+	depends on GPIOLIB && PINCTRL_SPEAR
+	help
+	  Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
+	  SoCs.
+
 endif
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
index b28a7ba..0e400eb 100644
--- a/drivers/pinctrl/spear/Makefile
+++ b/drivers/pinctrl/spear/Makefile
@@ -1,5 +1,6 @@
 # SPEAr pinmux support
 
+obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO)	+= pinctrl-plgpio.o
 obj-$(CONFIG_PINCTRL_SPEAR)	+= pinctrl-spear.o
 obj-$(CONFIG_PINCTRL_SPEAR3XX)	+= pinctrl-spear3xx.o
 obj-$(CONFIG_PINCTRL_SPEAR300)	+= pinctrl-spear300.o
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
new file mode 100644
index 0000000..f016e14
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -0,0 +1,738 @@
+/*
+ * SPEAr platform PLGPIO driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/spinlock.h>
+#include <asm/mach/irq.h>
+
+#define MAX_GPIO_PER_REG		32
+#define PIN_OFFSET(pin)			(pin % MAX_GPIO_PER_REG)
+#define REG_OFFSET(base, reg, pin)	(base + reg + (pin / MAX_GPIO_PER_REG) \
+							* sizeof(int *))
+
+/*
+ * plgpio pins in all machines are not one to one mapped, bitwise with registers
+ * bits. These set of macros define register masks for which below functions
+ * (pin_to_offset and offset_to_pin) are required to be called.
+ */
+#define PTO_ENB_REG		0x001
+#define PTO_WDATA_REG		0x002
+#define PTO_DIR_REG		0x004
+#define PTO_IE_REG		0x008
+#define PTO_RDATA_REG		0x010
+#define PTO_MIS_REG		0x020
+
+struct plgpio_regs {
+	u32 enb;		/* enable register */
+	u32 wdata;		/* write data register */
+	u32 dir;		/* direction set register */
+	u32 rdata;		/* read data register */
+	u32 ie;			/* interrupt enable register */
+	u32 mis;		/* mask interrupt status register */
+	u32 eit;		/* edge interrupt type */
+};
+
+/*
+ * struct plgpio: plgpio driver specific structure
+ *
+ * lock: lock for guarding gpio registers
+ * base: base address of plgpio block
+ * irq_base: irq number of plgpio0
+ * chip: gpio framework specific chip information structure
+ * p2o: function ptr for pin to offset conversion. This is required only for
+ *	machines where mapping b/w pin and offset is not 1-to-1.
+ * o2p: function ptr for offset to pin conversion. This is required only for
+ *	machines where mapping b/w pin and offset is not 1-to-1.
+ * p2o_regs: mask of registers for which p2o and o2p are applicable
+ * regs: register offsets
+ * csave_regs: context save registers for standby/sleep/hibernate cases
+ */
+struct plgpio {
+	spinlock_t		lock;
+	void __iomem		*base;
+	struct clk		*clk;
+	unsigned		irq_base;
+	struct gpio_chip	chip;
+	int			(*p2o)(int pin);	/* pin_to_offset */
+	int			(*o2p)(int offset);	/* offset_to_pin */
+	u32			p2o_regs;
+	struct plgpio_regs	regs;
+#ifdef CONFIG_PM
+	struct plgpio_regs	*csave_regs;
+#endif
+};
+
+/* register manipulation inline functions */
+static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	return !!(val & (1 << offset));
+}
+
+static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	writel_relaxed(val | (1 << offset), reg_off);
+}
+
+static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	writel_relaxed(val & ~(1 << offset), reg_off);
+}
+
+/* gpio framework specific routines */
+static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+	return 0;
+}
+
+static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	unsigned long flags;
+	unsigned dir_offset = offset, wdata_offset = offset, tmp;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
+		tmp = plgpio->p2o(offset);
+		if (tmp == -1)
+			return -EINVAL;
+
+		if (plgpio->p2o_regs & PTO_DIR_REG)
+			dir_offset = tmp;
+		if (plgpio->p2o_regs & PTO_WDATA_REG)
+			wdata_offset = tmp;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	if (value)
+		plgpio_reg_set(plgpio->base, wdata_offset,
+				plgpio->regs.wdata);
+	else
+		plgpio_reg_reset(plgpio->base, wdata_offset,
+				plgpio->regs.wdata);
+
+	plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+	return 0;
+}
+
+static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return -EINVAL;
+	}
+
+	return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
+}
+
+static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (offset >= chip->ngpio)
+		return;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	if (value)
+		plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
+	else
+		plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
+}
+
+static int plgpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	int gpio = chip->base + offset;
+	unsigned long flags;
+	int ret = 0;
+
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	ret = pinctrl_request_gpio(gpio);
+	if (ret)
+		return ret;
+
+	if (!IS_ERR(plgpio->clk)) {
+		ret = clk_prepare_enable(plgpio->clk);
+		if (ret)
+			goto err0;
+	}
+
+	if (plgpio->regs.enb == -1)
+		return 0;
+
+	/*
+	 * put gpio in IN mode before enabling it. This make enabling gpio safe
+	 */
+	ret = plgpio_direction_input(chip, offset);
+	if (ret)
+		goto err1;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1) {
+			ret = -EINVAL;
+			goto err1;
+		}
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+	return 0;
+
+err1:
+	clk_disable_unprepare(plgpio->clk);
+err0:
+	pinctrl_free_gpio(gpio);
+	return ret;
+}
+
+static void plgpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	int gpio = chip->base + offset;
+	unsigned long flags;
+
+	if (offset >= chip->ngpio)
+		return;
+
+	if (plgpio->regs.enb == -1)
+		goto disable_clk;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+disable_clk:
+	if (!IS_ERR(plgpio->clk))
+		clk_disable_unprepare(plgpio->clk);
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (plgpio->irq_base < 0)
+		return -EINVAL;
+
+	return plgpio->irq_base + offset;
+}
+
+/* PLGPIO IRQ */
+static void plgpio_irq_disable(struct irq_data *d)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static void plgpio_irq_enable(struct irq_data *d)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	void __iomem *reg_off;
+	unsigned int supported_type = 0, val;
+
+	if (offset >= plgpio->chip.ngpio)
+		return -EINVAL;
+
+	if (plgpio->regs.eit == -1)
+		supported_type = IRQ_TYPE_LEVEL_HIGH;
+	else
+		supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+	if (!(trigger & supported_type))
+		return -EINVAL;
+
+	if (plgpio->regs.eit == -1)
+		return 0;
+
+	reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
+	val = readl_relaxed(reg_off);
+
+	offset = PIN_OFFSET(offset);
+	if (trigger & IRQ_TYPE_EDGE_RISING)
+		writel_relaxed(val | (1 << offset), reg_off);
+	else
+		writel_relaxed(val & ~(1 << offset), reg_off);
+
+	return 0;
+}
+
+static struct irq_chip plgpio_irqchip = {
+	.name		= "PLGPIO",
+	.irq_enable	= plgpio_irq_enable,
+	.irq_disable	= plgpio_irq_disable,
+	.irq_set_type	= plgpio_irq_set_type,
+};
+
+static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct plgpio *plgpio = irq_get_handler_data(irq);
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	int regs_count, count, pin, offset, i = 0;
+	unsigned long pending;
+
+	count = plgpio->chip.ngpio;
+	regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
+
+	chained_irq_enter(irqchip, desc);
+	/* check all plgpio MIS registers for a possible interrupt */
+	for (; i < regs_count; i++) {
+		pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
+				i * sizeof(int *));
+		if (!pending)
+			continue;
+
+		/* clear interrupts */
+		writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
+				i * sizeof(int *));
+		/*
+		 * clear extra bits in last register having gpios < MAX/REG
+		 * ex: Suppose there are max 102 plgpios. then last register
+		 * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
+		 * so, we must not take other 28 bits into consideration for
+		 * checking interrupt. so clear those bits.
+		 */
+		count = count - i * MAX_GPIO_PER_REG;
+		if (count < MAX_GPIO_PER_REG)
+			pending &= (1 << count) - 1;
+
+		for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
+			/* get correct pin for "offset" */
+			if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
+				pin = plgpio->o2p(offset);
+				if (pin == -1)
+					continue;
+			} else
+				pin = offset;
+
+			/* get correct irq line number */
+			pin = i * MAX_GPIO_PER_REG + pin;
+			generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+		}
+	}
+	chained_irq_exit(irqchip, desc);
+}
+
+/*
+ * pin to offset and offset to pin converter functions
+ *
+ * In spear310 there is inconsistency among bit positions in plgpio regiseters,
+ * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
+ * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
+ */
+static int spear310_p2o(int pin)
+{
+	int offset = pin;
+
+	if (pin <= 27)
+		offset += 4;
+	else if (pin <= 33)
+		offset = -1;
+	else if (pin <= 97)
+		offset -= 2;
+	else if (pin <= 101)
+		offset = 101 - pin;
+	else
+		offset = -1;
+
+	return offset;
+}
+
+int spear310_o2p(int offset)
+{
+	if (offset <= 3)
+		return 101 - offset;
+	else if (offset <= 31)
+		return offset - 4;
+	else
+		return offset + 2;
+}
+
+static int __devinit plgpio_probe_dt(struct platform_device *pdev,
+		struct plgpio *plgpio)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret = -EINVAL;
+	u32 val;
+
+	if (of_machine_is_compatible("st,spear310")) {
+		plgpio->p2o = spear310_p2o;
+		plgpio->o2p = spear310_o2p;
+		plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
+			PTO_RDATA_REG | PTO_MIS_REG;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
+		plgpio->chip.ngpio = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
+		plgpio->regs.enb = val;
+	else
+		plgpio->regs.enb = -1;
+
+	if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
+		plgpio->regs.wdata = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
+		plgpio->regs.dir = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid dir reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
+		plgpio->regs.ie = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid ie reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
+		plgpio->regs.rdata = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
+		plgpio->regs.mis = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid mis reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
+		plgpio->regs.eit = val;
+	else
+		plgpio->regs.eit = -1;
+
+	if (!of_property_read_u32(np, "st-plgpio,irq_base", &val))
+		plgpio->irq_base = val;
+	else
+		plgpio->irq_base = -1;
+
+	return 0;
+
+end:
+	return ret;
+}
+static int __devinit plgpio_probe(struct platform_device *pdev)
+{
+	struct plgpio *plgpio;
+	struct resource *res;
+	int ret, irq, i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+		return -EBUSY;
+	}
+
+	plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
+	if (!plgpio) {
+		dev_err(&pdev->dev, "memory allocation fail\n");
+		return -ENOMEM;
+	}
+
+	plgpio->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!plgpio->base) {
+		dev_err(&pdev->dev, "request and ioremap fail\n");
+		return -ENOMEM;
+	}
+
+	plgpio->irq_base = 0;
+	ret = plgpio_probe_dt(pdev, plgpio);
+	if (ret) {
+		dev_err(&pdev->dev, "DT probe failed\n");
+		return ret;
+	}
+
+	plgpio->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(plgpio->clk))
+		dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
+
+#ifdef CONFIG_PM
+	plgpio->csave_regs = devm_kzalloc(&pdev->dev,
+			sizeof(*plgpio->csave_regs) *
+			DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
+			GFP_KERNEL);
+	if (!plgpio->csave_regs) {
+		dev_err(&pdev->dev, "csave registers memory allocation fail\n");
+		return -ENOMEM;
+	}
+#endif
+
+	platform_set_drvdata(pdev, plgpio);
+	spin_lock_init(&plgpio->lock);
+
+	plgpio->chip.base = -1;
+	plgpio->chip.request = plgpio_request;
+	plgpio->chip.free = plgpio_free;
+	plgpio->chip.direction_input = plgpio_direction_input;
+	plgpio->chip.direction_output = plgpio_direction_output;
+	plgpio->chip.get = plgpio_get_value;
+	plgpio->chip.set = plgpio_set_value;
+	plgpio->chip.to_irq = plgpio_to_irq;
+	plgpio->chip.label = dev_name(&pdev->dev);
+	plgpio->chip.dev = &pdev->dev;
+	plgpio->chip.owner = THIS_MODULE;
+
+	ret = gpiochip_add(&plgpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpio chip\n");
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "irqs not supported\n");
+		return 0;
+	}
+
+	/* irq_chip support */
+	if (plgpio->irq_base < 0) {
+		dev_info(&pdev->dev, "Error: invalid irqbase passed\n");
+		goto remove_gpiochip;
+	}
+
+	irq_set_chained_handler(irq, plgpio_irq_handler);
+	for (i = 0; i < plgpio->chip.ngpio; i++) {
+		irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
+				handle_simple_irq);
+		set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
+		irq_set_chip_data(i + plgpio->irq_base, plgpio);
+	}
+
+	irq_set_handler_data(irq, plgpio);
+	dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
+
+	return 0;
+
+remove_gpiochip:
+	dev_info(&pdev->dev, "Remove gpiochip\n");
+	if (gpiochip_remove(&plgpio->chip))
+		dev_err(&pdev->dev, "unable to remove gpiochip\n");
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int plgpio_suspend(struct device *dev)
+{
+	struct plgpio *plgpio = dev_get_drvdata(dev);
+	int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+	void __iomem *off;
+
+	for (i = 0; i < reg_count; i++) {
+		off = plgpio->base + i * sizeof(int *);
+
+		if (plgpio->regs.enb != -1)
+			plgpio->csave_regs[i].enb =
+				readl_relaxed(plgpio->regs.enb + off);
+		if (plgpio->regs.eit != -1)
+			plgpio->csave_regs[i].eit =
+				readl_relaxed(plgpio->regs.eit + off);
+		plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
+				off);
+		plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
+				off);
+		plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
+	}
+
+	return 0;
+}
+
+/*
+ * This is used to correct the values in end registers. End registers contain
+ * extra bits that might be used for other purpose in platform. So, we shouldn't
+ * overwrite these bits. This macro, reads given register again, preserves other
+ * bit values (non-plgpio bits), and retain captured value (plgpio bits).
+ */
+#define plgpio_prepare_reg(__reg, _off, _mask, _tmp)		\
+{								\
+	_tmp = readl_relaxed(plgpio->regs.__reg + _off);		\
+	_tmp &= ~_mask;						\
+	plgpio->csave_regs[i].__reg =				\
+		_tmp | (plgpio->csave_regs[i].__reg & _mask);	\
+}
+
+static int plgpio_resume(struct device *dev)
+{
+	struct plgpio *plgpio = dev_get_drvdata(dev);
+	int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+	void __iomem *off;
+	u32 mask, tmp;
+
+	for (i = 0; i < reg_count; i++) {
+		off = plgpio->base + i * sizeof(int *);
+
+		if (i == reg_count - 1) {
+			mask = (1 << (plgpio->chip.ngpio - i *
+						MAX_GPIO_PER_REG)) - 1;
+
+			if (plgpio->regs.enb != -1)
+				plgpio_prepare_reg(enb, off, mask, tmp);
+
+			if (plgpio->regs.eit != -1)
+				plgpio_prepare_reg(eit, off, mask, tmp);
+
+			plgpio_prepare_reg(wdata, off, mask, tmp);
+			plgpio_prepare_reg(dir, off, mask, tmp);
+			plgpio_prepare_reg(ie, off, mask, tmp);
+		}
+
+		writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
+				off);
+		writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
+				off);
+
+		if (plgpio->regs.eit != -1)
+			writel_relaxed(plgpio->csave_regs[i].eit,
+					plgpio->regs.eit + off);
+
+		writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
+
+		if (plgpio->regs.enb != -1)
+			writel_relaxed(plgpio->csave_regs[i].enb,
+					plgpio->regs.enb + off);
+	}
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
+
+static const struct of_device_id plgpio_of_match[] = {
+	{ .compatible = "st,spear-plgpio" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, plgpio_of_match);
+
+static struct platform_driver plgpio_driver = {
+	.probe = plgpio_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "spear-plgpio",
+		.pm = &plgpio_dev_pm_ops,
+		.of_match_table = of_match_ptr(plgpio_of_match),
+	},
+};
+
+static int __init plgpio_init(void)
+{
+	return platform_driver_register(&plgpio_driver);
+}
+arch_initcall(plgpio_init);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver");
+MODULE_LICENSE("GPL");
-- 
1.7.9

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

* [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support
  2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
                   ` (2 preceding siblings ...)
  2012-05-03 10:12 ` [PATCH V2 3/5] pinctrl: SPEAr: Add plgpio driver Viresh Kumar
@ 2012-05-03 10:12 ` Viresh Kumar
  2012-05-04  5:51   ` Viresh Kumar
  2012-05-03 10:12 ` [PATCH V2 5/5] SPEAr: Add plgpio node in device tree dtsi files Viresh Kumar
  2012-05-07 13:11 ` [PATCH V2 0/5] pinctrl: SPEAr Updates Linus Walleij
  5 siblings, 1 reply; 8+ messages in thread
From: Viresh Kumar @ 2012-05-03 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Most of SPEAr SoCs, which support pinctrl, can configure & use pads as gpio.
This patch gpio enable support for SPEAr pinctrl drivers.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/pinctrl/spear/Kconfig             |    4 +
 drivers/pinctrl/spear/pinctrl-spear.c     |  110 ++++-
 drivers/pinctrl/spear/pinctrl-spear.h     |   15 +
 drivers/pinctrl/spear/pinctrl-spear1310.c |  810 +++++++++++++++++++++++++++++
 drivers/pinctrl/spear/pinctrl-spear1340.c |    8 +
 drivers/pinctrl/spear/pinctrl-spear300.c  |    2 +
 drivers/pinctrl/spear/pinctrl-spear310.c  |    2 +
 drivers/pinctrl/spear/pinctrl-spear320.c  |    2 +
 drivers/pinctrl/spear/pinctrl-spear3xx.c  |  120 +++++
 9 files changed, 1061 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 6f9a1e8..04d93e6 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -25,21 +25,25 @@ config PINCTRL_SPEAR310
 	bool "ST Microelectronics SPEAr310 SoC pin controller driver"
 	depends on MACH_SPEAR310
 	select PINCTRL_SPEAR3XX
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR320
 	bool "ST Microelectronics SPEAr320 SoC pin controller driver"
 	depends on MACH_SPEAR320
 	select PINCTRL_SPEAR3XX
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1310
 	bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
 	depends on MACH_SPEAR1310
 	select PINCTRL_SPEAR
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1340
 	bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
 	depends on MACH_SPEAR1340
 	select PINCTRL_SPEAR
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR_PLGPIO
 	bool "SPEAr SoC PLGPIO Controller"
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 8653569..2596fa6 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
@@ -38,6 +39,23 @@ static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
 	writel_relaxed(val, pmx->vbase + reg);
 }
 
+static void muxreg_endisable(struct spear_pmx *pmx, struct spear_muxreg *muxreg,
+		bool enable)
+{
+	u32 val, temp;
+
+	val = pmx_readl(pmx, muxreg->reg);
+	val &= ~muxreg->mask;
+
+	if (enable)
+		temp = muxreg->val;
+	else
+		temp = ~muxreg->val;
+
+	val |= muxreg->mask & temp;
+	pmx_writel(pmx, val, muxreg->reg);
+}
+
 static int set_mode(struct spear_pmx *pmx, int mode)
 {
 	struct spear_pmx_mode *pmx_mode = NULL;
@@ -70,6 +88,16 @@ static int set_mode(struct spear_pmx *pmx, int mode)
 	return 0;
 }
 
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+		unsigned count, u16 reg)
+{
+	int i = 0;
+
+	for (; i < count; i++)
+		gpio_pingroup[i].muxreg.reg = reg;
+}
+
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
 {
 	struct spear_pingroup *pgroup;
@@ -217,7 +245,6 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 	const struct spear_pingroup *pgroup;
 	const struct spear_modemux *modemux;
 	struct spear_muxreg *muxreg;
-	u32 val, temp;
 	int i, j;
 	bool found = false;
 
@@ -235,17 +262,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 		found = true;
 		for (j = 0; j < modemux->nmuxregs; j++) {
 			muxreg = &modemux->muxregs[j];
-
-			val = pmx_readl(pmx, muxreg->reg);
-			val &= ~muxreg->mask;
-
-			if (enable)
-				temp = muxreg->val;
-			else
-				temp = ~muxreg->val;
-
-			val |= muxreg->mask & temp;
-			pmx_writel(pmx, val, muxreg->reg);
+			muxreg_endisable(pmx, muxreg, enable);
 		}
 	}
 
@@ -270,12 +287,68 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
 	spear_pinctrl_endisable(pctldev, function, group, false);
 }
 
+/* gpio with pinmux */
+static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
+		unsigned pin)
+{
+	struct spear_gpio_pingroup *gpio_pingroup;
+	int i = 0, j;
+
+	if (!pmx->machdata->gpio_pingroups)
+		return NULL;
+
+	for (; i < pmx->machdata->ngpio_pingroups; i++) {
+		gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
+
+		for (j = 0; j < gpio_pingroup->npins; j++) {
+			if (gpio_pingroup->pins[j] == pin)
+				return gpio_pingroup;
+		}
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int gpio_request_endisable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset, bool enable)
+{
+	struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct spear_gpio_pingroup *gpio_pingroup;
+
+	gpio_pingroup = get_gpio_pingroup(pmx, offset);
+	if (PTR_ERR(gpio_pingroup))
+		return PTR_ERR(gpio_pingroup);
+
+	if (gpio_pingroup) {
+		struct spear_muxreg *muxreg;
+
+		muxreg = &gpio_pingroup->muxreg;
+		muxreg_endisable(pmx, muxreg, enable);
+	}
+
+	return 0;
+}
+
+static int gpio_request_enable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	return gpio_request_endisable(pctldev, range, offset, true);
+}
+
+static void gpio_disable_free(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	gpio_request_endisable(pctldev, range, offset, false);
+}
+
 static struct pinmux_ops spear_pinmux_ops = {
 	.get_functions_count = spear_pinctrl_get_funcs_count,
 	.get_function_name = spear_pinctrl_get_func_name,
 	.get_function_groups = spear_pinctrl_get_func_groups,
 	.enable = spear_pinctrl_enable,
 	.disable = spear_pinctrl_disable,
+	.gpio_request_enable = gpio_request_enable,
+	.gpio_disable_free = gpio_disable_free,
 };
 
 static struct pinctrl_desc spear_pinctrl_desc = {
@@ -291,6 +364,7 @@ int __devinit spear_pinctrl_probe(struct platform_device *pdev,
 	struct device_node *np = pdev->dev.of_node;
 	struct resource *res;
 	struct spear_pmx *pmx;
+	struct gpio_chip *gc;
 
 	if (!machdata)
 		return -ENODEV;
@@ -341,6 +415,18 @@ int __devinit spear_pinctrl_probe(struct platform_device *pdev,
 		return PTR_ERR(pmx->pctl);
 	}
 
+	gc = of_get_gpio_chip_by_phandle(np);
+	if (!gc) {
+		dev_err(&pdev->dev, "Couldn't find gpiochip, no gpio ranges registered\n");
+		return 0;
+	}
+
+	dev_info(&pdev->dev, "gpiochip bound with pinctrl is %s with base %d\n",
+			dev_name(gc->dev), gc->base);
+
+	machdata->ranges->base = gc->base;
+	pinctrl_add_gpio_range(pmx->pctl, machdata->ranges);
+
 	return 0;
 }
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
index 9155783..dd0d88e 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.h
+++ b/drivers/pinctrl/spear/pinctrl-spear.h
@@ -46,6 +46,12 @@ struct spear_muxreg {
 	u32 val;
 };
 
+struct spear_gpio_pingroup {
+	const unsigned *pins;
+	unsigned npins;
+	struct spear_muxreg muxreg;
+};
+
 /**
  * struct spear_modemux - SPEAr mode mux configuration
  * @modes: mode ids supported by this group of muxregs
@@ -100,6 +106,9 @@ struct spear_function {
  * @nfunctions: The numbmer of entries in @functions.
  * @groups: An array describing all pin groups the pin SoC supports.
  * @ngroups: The numbmer of entries in @groups.
+ * @ranges: PLGPIO ranges for the machine
+ * @gpio_pingroups: gpio pingroups
+ * @ngpio_pingroups: gpio pingroups count
  *
  * @modes_supported: Does SoC support modes
  * @mode: mode configured from probe
@@ -113,6 +122,9 @@ struct spear_pinctrl_machdata {
 	unsigned nfunctions;
 	struct spear_pingroup **groups;
 	unsigned ngroups;
+	struct pinctrl_gpio_range *ranges;
+	struct spear_gpio_pingroup *gpio_pingroups;
+	unsigned ngpio_pingroups;
 
 	bool modes_supported;
 	u16 mode;
@@ -136,6 +148,9 @@ struct spear_pmx {
 
 /* exported routines */
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+		unsigned count, u16 reg);
 int __devinit spear_pinctrl_probe(struct platform_device *pdev,
 		struct spear_pinctrl_machdata *machdata);
 int __devexit spear_pinctrl_remove(struct platform_device *pdev);
diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index fff168b..362808d 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -2143,6 +2143,813 @@ static struct spear_function *spear1310_functions[] = {
 	&gpt64_function,
 };
 
+static struct pinctrl_gpio_range spear1310_plgpio_range = {
+	.name		= "SPEAr1310 PLGPIO",
+	.id		= 0,
+	.pin_base	= 0,
+	.npins		= ARRAY_SIZE(spear1310_pins),
+};
+
+static const unsigned pin18[] = { 18, };
+static const unsigned pin19[] = { 19, };
+static const unsigned pin20[] = { 20, };
+static const unsigned pin21[] = { 21, };
+static const unsigned pin22[] = { 22, };
+static const unsigned pin23[] = { 23, };
+static const unsigned pin54[] = { 54, };
+static const unsigned pin55[] = { 55, };
+static const unsigned pin56[] = { 56, };
+static const unsigned pin57[] = { 57, };
+static const unsigned pin58[] = { 58, };
+static const unsigned pin59[] = { 59, };
+static const unsigned pin60[] = { 60, };
+static const unsigned pin61[] = { 61, };
+static const unsigned pin62[] = { 62, };
+static const unsigned pin63[] = { 63, };
+static const unsigned pin143[] = { 143, };
+static const unsigned pin144[] = { 144, };
+static const unsigned pin145[] = { 145, };
+static const unsigned pin146[] = { 146, };
+static const unsigned pin147[] = { 147, };
+static const unsigned pin148[] = { 148, };
+static const unsigned pin149[] = { 149, };
+static const unsigned pin150[] = { 150, };
+static const unsigned pin151[] = { 151, };
+static const unsigned pin152[] = { 152, };
+static const unsigned pin205[] = { 205, };
+static const unsigned pin206[] = { 206, };
+static const unsigned pin211[] = { 211, };
+static const unsigned pin212[] = { 212, };
+static const unsigned pin213[] = { 213, };
+static const unsigned pin214[] = { 214, };
+static const unsigned pin215[] = { 215, };
+static const unsigned pin216[] = { 216, };
+static const unsigned pin217[] = { 217, };
+static const unsigned pin218[] = { 218, };
+static const unsigned pin219[] = { 219, };
+static const unsigned pin220[] = { 220, };
+static const unsigned pin221[] = { 221, };
+static const unsigned pin222[] = { 222, };
+static const unsigned pin223[] = { 223, };
+static const unsigned pin224[] = { 224, };
+static const unsigned pin225[] = { 225, };
+static const unsigned pin226[] = { 226, };
+static const unsigned pin227[] = { 227, };
+static const unsigned pin228[] = { 228, };
+static const unsigned pin229[] = { 229, };
+static const unsigned pin230[] = { 230, };
+static const unsigned pin231[] = { 231, };
+static const unsigned pin232[] = { 232, };
+static const unsigned pin233[] = { 233, };
+static const unsigned pin234[] = { 234, };
+static const unsigned pin235[] = { 235, };
+static const unsigned pin236[] = { 236, };
+static const unsigned pin237[] = { 237, };
+static const unsigned pin238[] = { 238, };
+static const unsigned pin239[] = { 239, };
+static const unsigned pin240[] = { 240, };
+static const unsigned pin241[] = { 241, };
+static const unsigned pin242[] = { 242, };
+static const unsigned pin243[] = { 243, };
+static const unsigned pin244[] = { 244, };
+static const unsigned pin245[] = { 245, };
+
+static const unsigned pin_grp0[] = { 173, 174, };
+static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, };
+static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189,
+	190, 191, 192, };
+static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, };
+static const unsigned pin_grp4[] = { 199, 200, };
+static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
+static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, };
+static const unsigned pin_grp7[] = { 98, 99, };
+static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165,
+	166, 167, 168, 169, 170, 171, 172, };
+
+static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = {
+	{
+		.pins = i2c0_pins,
+		.npins = ARRAY_SIZE(i2c0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_I2C0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = ssp0_pins,
+		.npins = ARRAY_SIZE(ssp0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_SSP0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = ssp0_cs0_pins,
+		.npins = ARRAY_SIZE(ssp0_cs0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_SSP0_CS0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = ssp0_cs1_2_pins,
+		.npins = ARRAY_SIZE(ssp0_cs1_2_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_SSP0_CS1_2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = i2s0_pins,
+		.npins = ARRAY_SIZE(i2s0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_I2S0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = i2s1_pins,
+		.npins = ARRAY_SIZE(i2s1_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_I2S1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = clcd_pins,
+		.npins = ARRAY_SIZE(clcd_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_CLCD1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = clcd_high_res_pins,
+		.npins = ARRAY_SIZE(clcd_high_res_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_CLCD2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin18,
+		.npins = ARRAY_SIZE(pin18),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO15_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin19,
+		.npins = ARRAY_SIZE(pin19),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO14_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin20,
+		.npins = ARRAY_SIZE(pin20),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO13_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin21,
+		.npins = ARRAY_SIZE(pin21),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO12_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin22,
+		.npins = ARRAY_SIZE(pin22),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO11_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin23,
+		.npins = ARRAY_SIZE(pin23),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO10_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin143,
+		.npins = ARRAY_SIZE(pin143),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO00_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin144,
+		.npins = ARRAY_SIZE(pin144),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO01_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin145,
+		.npins = ARRAY_SIZE(pin145),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO02_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin146,
+		.npins = ARRAY_SIZE(pin146),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO03_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin147,
+		.npins = ARRAY_SIZE(pin147),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO04_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin148,
+		.npins = ARRAY_SIZE(pin148),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO05_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin149,
+		.npins = ARRAY_SIZE(pin149),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO06_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin150,
+		.npins = ARRAY_SIZE(pin150),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO07_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin151,
+		.npins = ARRAY_SIZE(pin151),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO08_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin152,
+		.npins = ARRAY_SIZE(pin152),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_EGPIO09_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = smi_2_chips_pins,
+		.npins = ARRAY_SIZE(smi_2_chips_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_SMI_MASK,
+			.val = 0,
+			},
+	}, {
+		.pins = pin54,
+		.npins = ARRAY_SIZE(pin54),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_SMINCS3_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin55,
+		.npins = ARRAY_SIZE(pin55),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_SMINCS2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin56,
+		.npins = ARRAY_SIZE(pin56),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_NFRSTPWDWN3_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin57,
+		.npins = ARRAY_SIZE(pin57),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFRSTPWDWN2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin58,
+		.npins = ARRAY_SIZE(pin58),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFRSTPWDWN1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin59,
+		.npins = ARRAY_SIZE(pin59),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFRSTPWDWN0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin60,
+		.npins = ARRAY_SIZE(pin60),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFWPRT3_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin61,
+		.npins = ARRAY_SIZE(pin61),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFCE3_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin62,
+		.npins = ARRAY_SIZE(pin62),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFAD25_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin63,
+		.npins = ARRAY_SIZE(pin63),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFAD24_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp0,
+		.npins = ARRAY_SIZE(pin_grp0),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_GMIICLK_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp1,
+		.npins = ARRAY_SIZE(pin_grp1),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp2,
+		.npins = ARRAY_SIZE(pin_grp2),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_RXCLK_RDV_TXEN_D03_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp3,
+		.npins = ARRAY_SIZE(pin_grp3),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_GMIID47_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp4,
+		.npins = ARRAY_SIZE(pin_grp4),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_MDC_MDIO_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp5,
+		.npins = ARRAY_SIZE(pin_grp5),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_NFAD23_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp6,
+		.npins = ARRAY_SIZE(pin_grp6),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_MCI_DATA8_15_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp7,
+		.npins = ARRAY_SIZE(pin_grp7),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_NFCE2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin_grp8,
+		.npins = ARRAY_SIZE(pin_grp8),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_NAND8_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = nand_16bit_pins,
+		.npins = ARRAY_SIZE(nand_16bit_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_NAND16BIT_1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin205,
+		.npins = ARRAY_SIZE(pin205),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_KBD_COL1_MASK | PMX_NFCE1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin206,
+		.npins = ARRAY_SIZE(pin206),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_KBD_COL0_MASK | PMX_NFCE2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin211,
+		.npins = ARRAY_SIZE(pin211),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin212,
+		.npins = ARRAY_SIZE(pin212),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin213,
+		.npins = ARRAY_SIZE(pin213),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_MCIDATA0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin214,
+		.npins = ARRAY_SIZE(pin214),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_MCIDATA1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin215,
+		.npins = ARRAY_SIZE(pin215),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_MCIDATA2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin216,
+		.npins = ARRAY_SIZE(pin216),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_MCIDATA3_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin217,
+		.npins = ARRAY_SIZE(pin217),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_MCIDATA4_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin218,
+		.npins = ARRAY_SIZE(pin218),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATA5_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin219,
+		.npins = ARRAY_SIZE(pin219),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATA6_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin220,
+		.npins = ARRAY_SIZE(pin220),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATA7_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin221,
+		.npins = ARRAY_SIZE(pin221),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATA1SD_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin222,
+		.npins = ARRAY_SIZE(pin222),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATA2SD_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin223,
+		.npins = ARRAY_SIZE(pin223),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATA3SD_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin224,
+		.npins = ARRAY_SIZE(pin224),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIADDR0ALE_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin225,
+		.npins = ARRAY_SIZE(pin225),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIADDR1CLECLK_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin226,
+		.npins = ARRAY_SIZE(pin226),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIADDR2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin227,
+		.npins = ARRAY_SIZE(pin227),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICECF_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin228,
+		.npins = ARRAY_SIZE(pin228),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICEXD_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin229,
+		.npins = ARRAY_SIZE(pin229),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICESDMMC_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin230,
+		.npins = ARRAY_SIZE(pin230),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICDCF1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin231,
+		.npins = ARRAY_SIZE(pin231),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICDCF2_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin232,
+		.npins = ARRAY_SIZE(pin232),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICDXD_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin233,
+		.npins = ARRAY_SIZE(pin233),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICDSDMMC_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin234,
+		.npins = ARRAY_SIZE(pin234),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDATADIR_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin235,
+		.npins = ARRAY_SIZE(pin235),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDMARQWP_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin236,
+		.npins = ARRAY_SIZE(pin236),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIIORDRE_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin237,
+		.npins = ARRAY_SIZE(pin237),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIIOWRWE_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin238,
+		.npins = ARRAY_SIZE(pin238),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIRESETCF_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin239,
+		.npins = ARRAY_SIZE(pin239),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICS0CE_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin240,
+		.npins = ARRAY_SIZE(pin240),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICFINTR_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin241,
+		.npins = ARRAY_SIZE(pin241),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIIORDY_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin242,
+		.npins = ARRAY_SIZE(pin242),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCICS1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin243,
+		.npins = ARRAY_SIZE(pin243),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCIDMAACK_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin244,
+		.npins = ARRAY_SIZE(pin244),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCISDCMD_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = pin245,
+		.npins = ARRAY_SIZE(pin245),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_MCILEDS_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = keyboard_rowcol6_8_pins,
+		.npins = ARRAY_SIZE(keyboard_rowcol6_8_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_KBD_ROWCOL68_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = uart0_pins,
+		.npins = ARRAY_SIZE(uart0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_0,
+			.mask = PMX_UART0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = uart0_modem_pins,
+		.npins = ARRAY_SIZE(uart0_modem_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_UART0_MODEM_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = gpt0_tmr0_pins,
+		.npins = ARRAY_SIZE(gpt0_tmr0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_GPT0_TMR0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = gpt0_tmr1_pins,
+		.npins = ARRAY_SIZE(gpt0_tmr1_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_GPT0_TMR1_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = gpt1_tmr0_pins,
+		.npins = ARRAY_SIZE(gpt1_tmr0_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_GPT1_TMR0_MASK,
+			.val = 0,
+		},
+	}, {
+		.pins = gpt1_tmr1_pins,
+		.npins = ARRAY_SIZE(gpt1_tmr1_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_1,
+			.mask = PMX_GPT1_TMR1_MASK,
+			.val = 0,
+		},
+	}, {
+		.npins = ARRAY_SIZE(touch_xy_pins),
+		.muxreg = {
+			.reg = PAD_FUNCTION_EN_2,
+			.mask = PMX_TOUCH_XY_MASK,
+			.val = 0,
+		},
+	},
+};
+
 static struct spear_pinctrl_machdata spear1310_machdata = {
 	.pins = spear1310_pins,
 	.npins = ARRAY_SIZE(spear1310_pins),
@@ -2150,6 +2957,9 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
 	.ngroups = ARRAY_SIZE(spear1310_pingroups),
 	.functions = spear1310_functions,
 	.nfunctions = ARRAY_SIZE(spear1310_functions),
+	.ranges = &spear1310_plgpio_range,
+	.gpio_pingroups = spear1310_gpio_pingroup,
+	.ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup),
 	.modes_supported = false,
 };
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
index a8ab2a6..9380507 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
@@ -1934,6 +1934,13 @@ static struct spear_function *spear1340_functions[] = {
 	&sata_function,
 };
 
+static struct pinctrl_gpio_range spear1340_plgpio_range = {
+	.name		= "SPEAr1340 PLGPIO",
+	.id		= 0,
+	.pin_base	= 0,
+	.npins		= ARRAY_SIZE(spear1340_pins),
+};
+
 static struct spear_pinctrl_machdata spear1340_machdata = {
 	.pins = spear1340_pins,
 	.npins = ARRAY_SIZE(spear1340_pins),
@@ -1941,6 +1948,7 @@ static struct spear_pinctrl_machdata spear1340_machdata = {
 	.ngroups = ARRAY_SIZE(spear1340_pingroups),
 	.functions = spear1340_functions,
 	.nfunctions = ARRAY_SIZE(spear1340_functions),
+	.ranges = &spear1340_plgpio_range,
 	.modes_supported = false,
 };
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
index 9c82a35..faa9169 100644
--- a/drivers/pinctrl/spear/pinctrl-spear300.c
+++ b/drivers/pinctrl/spear/pinctrl-spear300.c
@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
 	spear3xx_machdata.functions = spear300_functions;
 	spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
+	spear3xx_machdata.gpio_pingroups = NULL;
+	spear3xx_machdata.ngpio_pingroups = 0;
 
 	spear3xx_machdata.modes_supported = true;
 	spear3xx_machdata.pmx_modes = spear300_pmx_modes;
diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
index 1a97076..f393639 100644
--- a/drivers/pinctrl/spear/pinctrl-spear310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear310.c
@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
 
 	pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+	pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+			spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
 	spear3xx_machdata.modes_supported = false;
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
index de726e6..e8c2d65 100644
--- a/drivers/pinctrl/spear/pinctrl-spear320.c
+++ b/drivers/pinctrl/spear/pinctrl-spear320.c
@@ -3427,6 +3427,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
 
 	pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+	pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+			spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
 	ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
 	if (ret)
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c
index 91c883b..1c04033 100644
--- a/drivers/pinctrl/spear/pinctrl-spear3xx.c
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c
@@ -481,7 +481,127 @@ struct spear_function spear3xx_timer_2_3_function = {
 	.ngroups = ARRAY_SIZE(timer_2_3_grps),
 };
 
+/* plgpio */
+static struct pinctrl_gpio_range spear3xx_plgpio_range = {
+	.name		= "SPEAr3xx PLGPIO",
+	.id		= 0,
+	.pin_base	= 0,
+	.npins		= ARRAY_SIZE(spear3xx_pins),
+};
+
+static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
+	{
+		.pins = firda_pins,
+		.npins = ARRAY_SIZE(firda_pins),
+		.muxreg = {
+			.mask = PMX_FIRDA_MASK,
+			.val = PMX_FIRDA_MASK,
+		},
+	}, {
+		.pins = i2c_pins,
+		.npins = ARRAY_SIZE(i2c_pins),
+		.muxreg = {
+			.mask = PMX_I2C_MASK,
+			.val = PMX_I2C_MASK,
+		},
+	}, {
+		.pins = ssp_cs_pins,
+		.npins = ARRAY_SIZE(ssp_cs_pins),
+		.muxreg = {
+			.mask = PMX_SSP_CS_MASK,
+			.val = PMX_SSP_CS_MASK,
+		},
+	}, {
+		.pins = ssp_pins,
+		.npins = ARRAY_SIZE(ssp_pins),
+		.muxreg = {
+			.mask = PMX_SSP_MASK,
+			.val = PMX_SSP_MASK,
+		},
+	}, {
+		.pins = mii_pins,
+		.npins = ARRAY_SIZE(mii_pins),
+		.muxreg = {
+			.mask = PMX_MII_MASK,
+			.val = PMX_MII_MASK,
+		},
+	}, {
+		.pins = gpio0_pin0_pins,
+		.npins = ARRAY_SIZE(gpio0_pin0_pins),
+		.muxreg = {
+			.mask = PMX_GPIO_PIN0_MASK,
+			.val = PMX_GPIO_PIN0_MASK,
+		},
+	}, {
+		.pins = gpio0_pin1_pins,
+		.npins = ARRAY_SIZE(gpio0_pin1_pins),
+		.muxreg = {
+			.mask = PMX_GPIO_PIN1_MASK,
+			.val = PMX_GPIO_PIN1_MASK,
+		},
+	}, {
+		.pins = gpio0_pin2_pins,
+		.npins = ARRAY_SIZE(gpio0_pin2_pins),
+		.muxreg = {
+			.mask = PMX_GPIO_PIN2_MASK,
+			.val = PMX_GPIO_PIN2_MASK,
+		},
+	}, {
+		.pins = gpio0_pin3_pins,
+		.npins = ARRAY_SIZE(gpio0_pin3_pins),
+		.muxreg = {
+			.mask = PMX_GPIO_PIN3_MASK,
+			.val = PMX_GPIO_PIN3_MASK,
+		},
+	}, {
+		.pins = gpio0_pin4_pins,
+		.npins = ARRAY_SIZE(gpio0_pin4_pins),
+		.muxreg = {
+			.mask = PMX_GPIO_PIN4_MASK,
+			.val = PMX_GPIO_PIN4_MASK,
+		},
+	}, {
+		.pins = gpio0_pin5_pins,
+		.npins = ARRAY_SIZE(gpio0_pin5_pins),
+		.muxreg = {
+			.mask = PMX_GPIO_PIN5_MASK,
+			.val = PMX_GPIO_PIN5_MASK,
+		},
+	}, {
+		.pins = uart0_ext_pins,
+		.npins = ARRAY_SIZE(uart0_ext_pins),
+		.muxreg = {
+			.mask = PMX_UART0_MODEM_MASK,
+			.val = PMX_UART0_MODEM_MASK,
+		},
+	}, {
+		.pins = uart0_pins,
+		.npins = ARRAY_SIZE(uart0_pins),
+		.muxreg = {
+			.mask = PMX_UART0_MASK,
+			.val = PMX_UART0_MASK,
+		},
+	}, {
+		.pins = timer_0_1_pins,
+		.npins = ARRAY_SIZE(timer_0_1_pins),
+		.muxreg = {
+			.mask = PMX_TIMER_0_1_MASK,
+			.val = PMX_TIMER_0_1_MASK,
+		},
+	}, {
+		.pins = timer_2_3_pins,
+		.npins = ARRAY_SIZE(timer_2_3_pins),
+		.muxreg = {
+			.mask = PMX_TIMER_2_3_MASK,
+			.val = PMX_TIMER_2_3_MASK,
+		},
+	},
+};
+
 struct spear_pinctrl_machdata spear3xx_machdata = {
 	.pins = spear3xx_pins,
 	.npins = ARRAY_SIZE(spear3xx_pins),
+	.ranges = &spear3xx_plgpio_range,
+	.gpio_pingroups = spear3xx_gpio_pingroup,
+	.ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
 };
-- 
1.7.9

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

* [PATCH V2 5/5] SPEAr: Add plgpio node in device tree dtsi files
  2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
                   ` (3 preceding siblings ...)
  2012-05-03 10:12 ` [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support Viresh Kumar
@ 2012-05-03 10:12 ` Viresh Kumar
  2012-05-07 13:11 ` [PATCH V2 0/5] pinctrl: SPEAr Updates Linus Walleij
  5 siblings, 0 replies; 8+ messages in thread
From: Viresh Kumar @ 2012-05-03 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/boot/dts/spear1310-evb.dts |    4 ++++
 arch/arm/boot/dts/spear1310.dtsi    |   22 ++++++++++++++++++++++
 arch/arm/boot/dts/spear1340-evb.dts |    4 ++++
 arch/arm/boot/dts/spear1340.dtsi    |   21 +++++++++++++++++++++
 arch/arm/boot/dts/spear310-evb.dts  |    4 ++++
 arch/arm/boot/dts/spear310.dtsi     |   15 +++++++++++++++
 arch/arm/boot/dts/spear320-evb.dts  |    4 ++++
 arch/arm/boot/dts/spear320.dtsi     |   16 ++++++++++++++++
 8 files changed, 90 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index 8a51303..c090833 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -181,6 +181,10 @@
 			       status = "okay";
 			};
 
+			gpio at d8400000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at e0280000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 9e61da4..c63bba2 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -70,6 +70,12 @@
 			status = "disabled";
 		};
 
+		pinmux at e0700000 {
+			compatible = "st,spear1310-pinmux";
+			reg = <0xe0700000 0x1000>;
+			gpio-phandle = <&gpiopinctrl>;
+		};
+
 		spi1: spi at 5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
@@ -179,6 +185,22 @@
 			thermal at e07008c4 {
 				st,thermal-flags = <0x7000>;
 			};
+
+			gpiopinctrl: gpio at d8400000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xd8400000 0x1000>;
+				interrupts = <0 132 0x4>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <246>;
+				st-plgpio,enb-reg = <0xd0>;
+				st-plgpio,wdata-reg = <0x90>;
+				st-plgpio,dir-reg = <0xb0>;
+				st-plgpio,ie-reg = <0x30>;
+				st-plgpio,rdata-reg = <0x70>;
+				st-plgpio,mis-reg = <0x10>;
+				st-plgpio,eit-reg = <0x50>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index 60e0e12..0bf9d8f 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -193,6 +193,10 @@
 			       status = "okay";
 			};
 
+			gpio at e2800000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at e0280000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index a26fc47..e5d4e05 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -24,6 +24,12 @@
 			status = "disabled";
 		};
 
+		pinmux at e0700000 {
+			compatible = "st,spear1340-pinmux";
+			reg = <0xe0700000 0x1000>;
+			gpio-phandle = <&gpiopinctrl>;
+		};
+
 		spi1: spi at 5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
@@ -51,6 +57,21 @@
 			thermal at e07008c4 {
 				st,thermal-flags = <0x2a00>;
 			};
+
+			gpiopinctrl: gpio at e2800000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xe2800000 0x1000>;
+				interrupts = <0 139 0x4>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <250>;
+				st-plgpio,wdata-reg = <0x40>;
+				st-plgpio,dir-reg = <0x00>;
+				st-plgpio,ie-reg = <0x80>;
+				st-plgpio,rdata-reg = <0x20>;
+				st-plgpio,mis-reg = <0xa0>;
+				st-plgpio,eit-reg = <0x60>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear310-evb.dts b/arch/arm/boot/dts/spear310-evb.dts
index a551ee0..12ac5ed 100644
--- a/arch/arm/boot/dts/spear310-evb.dts
+++ b/arch/arm/boot/dts/spear310-evb.dts
@@ -148,6 +148,10 @@
 			       status = "okay";
 			};
 
+			gpio at b4000000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at d0180000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index e47081c..fddf84c 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -25,6 +25,7 @@
 		pinmux at b4000000 {
 			compatible = "st,spear310-pinmux";
 			reg = <0xb4000000 0x1000>;
+			gpio-phandle = <&gpiopinctrl>;
 		};
 
 		fsmc: flash at 44000000 {
@@ -75,6 +76,20 @@
 				reg = <0xb2200000 0x1000>;
 				status = "disabled";
 			};
+
+			gpiopinctrl: gpio at b4000000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xb4000000 0x1000>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <102>;
+				st-plgpio,enb-reg = <0x10>;
+				st-plgpio,wdata-reg = <0x20>;
+				st-plgpio,dir-reg = <0x30>;
+				st-plgpio,ie-reg = <0x50>;
+				st-plgpio,rdata-reg = <0x40>;
+				st-plgpio,mis-reg = <0x60>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts
index 26366f4..a2115aa 100644
--- a/arch/arm/boot/dts/spear320-evb.dts
+++ b/arch/arm/boot/dts/spear320-evb.dts
@@ -166,6 +166,10 @@
 			       status = "okay";
 			};
 
+			gpio at b3000000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at d0180000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index 5372ca3..9adac5b 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -24,6 +24,7 @@
 		pinmux at b3000000 {
 			compatible = "st,spear320-pinmux";
 			reg = <0xb3000000 0x1000>;
+			gpio-phandle = <&gpiopinctrl>;
 		};
 
 		clcd at 90000000 {
@@ -90,6 +91,21 @@
 				reg = <0xa4000000 0x1000>;
 				status = "disabled";
 			};
+
+			gpiopinctrl: gpio at b3000000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xb3000000 0x1000>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <102>;
+				st-plgpio,enb-reg = <0x24>;
+				st-plgpio,wdata-reg = <0x34>;
+				st-plgpio,dir-reg = <0x44>;
+				st-plgpio,ie-reg = <0x64>;
+				st-plgpio,rdata-reg = <0x54>;
+				st-plgpio,mis-reg = <0x84>;
+				st-plgpio,eit-reg = <0x94>;
+			};
 		};
 	};
 };
-- 
1.7.9

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

* [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support
  2012-05-03 10:12 ` [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support Viresh Kumar
@ 2012-05-04  5:51   ` Viresh Kumar
  0 siblings, 0 replies; 8+ messages in thread
From: Viresh Kumar @ 2012-05-04  5:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 5/3/2012 3:42 PM, Viresh KUMAR wrote:
> +static int gpio_request_endisable(struct pinctrl_dev *pctldev,
> +               struct pinctrl_gpio_range *range, unsigned offset, bool enable)
> +{
> +       struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
> +       struct spear_gpio_pingroup *gpio_pingroup;
> +
> +       gpio_pingroup = get_gpio_pingroup(pmx, offset);
> +       if (PTR_ERR(gpio_pingroup))
> +               return PTR_ERR(gpio_pingroup);
> +

Minor fixup:

---
 drivers/pinctrl/spear/pinctrl-spear.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 2596fa6..c0c3b28 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -316,7 +316,7 @@ static int gpio_request_endisable(struct pinctrl_dev *pctldev,
        struct spear_gpio_pingroup *gpio_pingroup;
 
        gpio_pingroup = get_gpio_pingroup(pmx, offset);
-       if (PTR_ERR(gpio_pingroup))
+       if (IS_ERR(gpio_pingroup))
                return PTR_ERR(gpio_pingroup);
 
        if (gpio_pingroup) {

-- 
viresh

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

* [PATCH V2 0/5] pinctrl: SPEAr Updates
  2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
                   ` (4 preceding siblings ...)
  2012-05-03 10:12 ` [PATCH V2 5/5] SPEAr: Add plgpio node in device tree dtsi files Viresh Kumar
@ 2012-05-07 13:11 ` Linus Walleij
  5 siblings, 0 replies; 8+ messages in thread
From: Linus Walleij @ 2012-05-07 13:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 3, 2012 at 12:12 PM, Viresh Kumar <viresh.kumar@st.com> wrote:

> - Passing gpio node via DT. Patch for this support in gpiolib is
> ?gpiolib: Add of_get_gpio_chip_by_phandle() helper
> - Other minor fixes

Clever, if you fix the macro I commented on for v1, you can add my
Acked-by: Linus Walleij <linus.walleij@linaro.org>
for this V2 series.

Yours,
Linus Walleij

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

end of thread, other threads:[~2012-05-07 13:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-03 10:12 [PATCH V2 0/5] pinctrl: SPEAr Updates Viresh Kumar
2012-05-03 10:12 ` [PATCH V2 1/5] pinctrl: SPEAr: Don't set all non muxreg bits on pinctrl_disable Viresh Kumar
2012-05-03 10:12 ` [PATCH V2 2/5] pinctrl: SPEAr1310: Fix pin numbers for clcd_high_res Viresh Kumar
2012-05-03 10:12 ` [PATCH V2 3/5] pinctrl: SPEAr: Add plgpio driver Viresh Kumar
2012-05-03 10:12 ` [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support Viresh Kumar
2012-05-04  5:51   ` Viresh Kumar
2012-05-03 10:12 ` [PATCH V2 5/5] SPEAr: Add plgpio node in device tree dtsi files Viresh Kumar
2012-05-07 13:11 ` [PATCH V2 0/5] pinctrl: SPEAr Updates Linus Walleij

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).