mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v3 0/3] Add atmel pinctrl driver
@ 2014-09-02 11:07 Raphaël Poggi
  2014-09-02 11:07 ` [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder Raphaël Poggi
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-02 11:07 UTC (permalink / raw)
  To: barebox

Change since v2:
        * Move all functions from mach-at91/gpio.h to match-at91/include/gpio.h
        * Remove pinctrl-at91.h file in patch

Change since v1:
        * Fix coding style issue
        * Register gpio clocks with CLKDEV_DEV_ID instead of CLKDEV_CON_DEV_ID

This patchset add atmel pinctrl/gpio driver and the corresponding clocks for
the at91sam9g45 device.

The pinctrl driver also include the gpio driver (like in linux) because the gpio and pinctrl parts share same structures.

Raphaël Poggi (3):
        (1) arm: mach-at91: move gpio.h to include folder
        (2) pinctrl: at91: add pinctrl driver
        (3) at91sam9g45: add device tree gpio clocks

 arch/arm/mach-at91/at91sam9g45.c       |    5 +
 arch/arm/mach-at91/gpio.c              |    2 +-
 arch/arm/mach-at91/gpio.h              |  148 ---------
 arch/arm/mach-at91/include/mach/gpio.h |  149 +++++++++
 drivers/pinctrl/Kconfig                |    6 +
 drivers/pinctrl/Makefile               |    1 +
 drivers/pinctrl/pinctrl-at91.c         |  527 ++++++++++++++++++++++++++++++++
 7 files changed, 689 insertions(+), 149 deletions(-)


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder
  2014-09-02 11:07 [PATCH v3 0/3] Add atmel pinctrl driver Raphaël Poggi
@ 2014-09-02 11:07 ` Raphaël Poggi
  2014-09-03  7:00   ` Sascha Hauer
  2014-09-02 11:07 ` [PATCH v3 2/3] pinctrl: at91: add pinctrl driver Raphaël Poggi
  2014-09-02 11:08 ` [PATCH v3 3/3] at91sam9g45: add device tree gpio clocks Raphaël Poggi
  2 siblings, 1 reply; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-02 11:07 UTC (permalink / raw)
  To: barebox; +Cc: Raphaël Poggi

This commit add functions from mach-at91/gpio.h in include/mach/gpio.h.
This allow to use these functions outside the mach-at91 folder.

Signed-off-by: Raphaël Poggi <poggi.raph@gmail.com>
---
 arch/arm/mach-at91/gpio.c              |    2 +-
 arch/arm/mach-at91/gpio.h              |  148 -------------------------------
 arch/arm/mach-at91/include/mach/gpio.h |  149 ++++++++++++++++++++++++++++++++
 3 files changed, 150 insertions(+), 149 deletions(-)
 delete mode 100644 arch/arm/mach-at91/gpio.h

diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 4f2c76e..402634b 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -32,7 +32,7 @@
 #include <driver.h>
 #include <getopt.h>
 
-#include "gpio.h"
+#include <mach/gpio.h>
 
 #define MAX_GPIO_BANKS		5
 
diff --git a/arch/arm/mach-at91/gpio.h b/arch/arm/mach-at91/gpio.h
deleted file mode 100644
index d40628b..0000000
--- a/arch/arm/mach-at91/gpio.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * Under GPLv2 only
- */
-
-#ifndef __AT91_GPIO_H__
-#define __AT91_GPIO_H__
-
-#ifndef __gpio_init
-#define __gpio_init
-#endif
-
-#define MAX_NB_GPIO_PER_BANK	32
-
-static inline unsigned pin_to_bank(unsigned pin)
-{
-	return pin / MAX_NB_GPIO_PER_BANK;
-}
-
-static inline unsigned pin_to_bank_offset(unsigned pin)
-{
-	return pin % MAX_NB_GPIO_PER_BANK;
-}
-
-static inline unsigned pin_to_mask(unsigned pin)
-{
-	return 1 << pin_to_bank_offset(pin);
-}
-
-static __gpio_init void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(mask, pio + PIO_IDR);
-}
-
-static __gpio_init void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
-{
-	__raw_writel(mask, pio + (on ? PIO_PUER : PIO_PUDR));
-}
-
-static __gpio_init void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
-{
-	__raw_writel(mask, pio + (on ? PIO_MDER : PIO_MDDR));
-}
-
-static __gpio_init void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(mask, pio + PIO_ASR);
-}
-
-static __gpio_init void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(mask, pio + PIO_BSR);
-}
-
-static __gpio_init void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
-{
-
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask,
-						pio + PIO_ABCDSR1);
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
-						pio + PIO_ABCDSR2);
-}
-
-static __gpio_init void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask,
-						pio + PIO_ABCDSR1);
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
-						pio + PIO_ABCDSR2);
-}
-
-static __gpio_init void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
-}
-
-static __gpio_init void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
-	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
-}
-
-static __gpio_init void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
-{
-	__raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
-}
-
-static __gpio_init void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
-{
-	if (is_on)
-		__raw_writel(mask, pio + PIO_IFSCDR);
-	at91_mux_set_deglitch(pio, mask, is_on);
-}
-
-static __gpio_init void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
-				bool is_on, u32 div)
-{
-	if (is_on) {
-		__raw_writel(mask, pio + PIO_IFSCER);
-		__raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
-		__raw_writel(mask, pio + PIO_IFER);
-	} else {
-		__raw_writel(mask, pio + PIO_IFDR);
-	}
-}
-
-static __gpio_init void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
-{
-	__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
-}
-
-static __gpio_init void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
-}
-
-static __gpio_init void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(mask, pio + PIO_PDR);
-}
-
-static __gpio_init void at91_mux_gpio_enable(void __iomem *pio, unsigned mask)
-{
-	__raw_writel(mask, pio + PIO_PER);
-}
-
-static __gpio_init void at91_mux_gpio_input(void __iomem *pio, unsigned mask, bool input)
-{
-	__raw_writel(mask, pio + (input ? PIO_ODR : PIO_OER));
-}
-
-static __gpio_init void at91_mux_gpio_set(void __iomem *pio, unsigned mask,
-int value)
-{
-	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
-}
-
-static __gpio_init int at91_mux_gpio_get(void __iomem *pio, unsigned mask)
-{
-       u32 pdsr;
-
-       pdsr = __raw_readl(pio + PIO_PDSR);
-       return (pdsr & mask) != 0;
-}
-
-#endif /* __AT91_GPIO_H__ */
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index 306ab4c..6a6b9cd 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -1 +1,150 @@
+/*
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#ifndef __AT91_GPIO_H__
+#define __AT91_GPIO_H__
+
 #include <asm-generic/gpio.h>
+
+#ifndef __gpio_init
+#define __gpio_init
+#endif
+
+#define MAX_NB_GPIO_PER_BANK	32
+
+static inline unsigned pin_to_bank(unsigned pin)
+{
+	return pin / MAX_NB_GPIO_PER_BANK;
+}
+
+static inline unsigned pin_to_bank_offset(unsigned pin)
+{
+	return pin % MAX_NB_GPIO_PER_BANK;
+}
+
+static inline unsigned pin_to_mask(unsigned pin)
+{
+	return 1 << pin_to_bank_offset(pin);
+}
+
+static __gpio_init void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(mask, pio + PIO_IDR);
+}
+
+static __gpio_init void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
+{
+	__raw_writel(mask, pio + (on ? PIO_PUER : PIO_PUDR));
+}
+
+static __gpio_init void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
+{
+	__raw_writel(mask, pio + (on ? PIO_MDER : PIO_MDDR));
+}
+
+static __gpio_init void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(mask, pio + PIO_ASR);
+}
+
+static __gpio_init void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(mask, pio + PIO_BSR);
+}
+
+static __gpio_init void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
+{
+
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask,
+						pio + PIO_ABCDSR1);
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
+						pio + PIO_ABCDSR2);
+}
+
+static __gpio_init void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask,
+						pio + PIO_ABCDSR1);
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
+						pio + PIO_ABCDSR2);
+}
+
+static __gpio_init void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static __gpio_init void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
+	__raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static __gpio_init void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+	__raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+}
+
+static __gpio_init void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+	if (is_on)
+		__raw_writel(mask, pio + PIO_IFSCDR);
+	at91_mux_set_deglitch(pio, mask, is_on);
+}
+
+static __gpio_init void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
+				bool is_on, u32 div)
+{
+	if (is_on) {
+		__raw_writel(mask, pio + PIO_IFSCER);
+		__raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
+		__raw_writel(mask, pio + PIO_IFER);
+	} else {
+		__raw_writel(mask, pio + PIO_IFDR);
+	}
+}
+
+static __gpio_init void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
+{
+	__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
+}
+
+static __gpio_init void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
+}
+
+static __gpio_init void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(mask, pio + PIO_PDR);
+}
+
+static __gpio_init void at91_mux_gpio_enable(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(mask, pio + PIO_PER);
+}
+
+static __gpio_init void at91_mux_gpio_input(void __iomem *pio, unsigned mask, bool input)
+{
+	__raw_writel(mask, pio + (input ? PIO_ODR : PIO_OER));
+}
+
+static __gpio_init void at91_mux_gpio_set(void __iomem *pio, unsigned mask,
+int value)
+{
+	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+}
+
+static __gpio_init int at91_mux_gpio_get(void __iomem *pio, unsigned mask)
+{
+       u32 pdsr;
+
+       pdsr = __raw_readl(pio + PIO_PDSR);
+       return (pdsr & mask) != 0;
+}
+
+#endif /* __AT91_GPIO_H__ */
-- 
1.7.9.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-02 11:07 [PATCH v3 0/3] Add atmel pinctrl driver Raphaël Poggi
  2014-09-02 11:07 ` [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder Raphaël Poggi
@ 2014-09-02 11:07 ` Raphaël Poggi
  2014-09-03  6:56   ` Sascha Hauer
  2014-09-02 11:08 ` [PATCH v3 3/3] at91sam9g45: add device tree gpio clocks Raphaël Poggi
  2 siblings, 1 reply; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-02 11:07 UTC (permalink / raw)
  To: barebox; +Cc: Raphaël Poggi

This driver is based on mach-at91/gpio.c and linux pinctrl driver.
The driver contains the gpio and pinctrl parts (like in linux) because the two parts
share some structures and logics.

Signed-off-by: Raphaël Poggi <poggi.raph@gmail.com>
---
 drivers/pinctrl/Kconfig        |    6 +
 drivers/pinctrl/Makefile       |    1 +
 drivers/pinctrl/pinctrl-at91.c |  527 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 534 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-at91.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index dffaa4e..ce55c7b 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -7,6 +7,12 @@ config PINCTRL
 	  from the devicetree. Legacy drivers here may not need this core
 	  support but instead provide their own SoC specific APIs
 
+config PINCTRL_AT91
+	select PINCTRL
+	bool
+	help
+	    The pinmux controller found on AT91 SoCs.
+
 config PINCTRL_IMX_IOMUX_V1
 	select PINCTRL if OFDEVICE
 	bool
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 566ba11..3ea8649 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PINCTRL)	+= pinctrl.o
+obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
 obj-$(CONFIG_PINCTRL_IMX_IOMUX_V1) += imx-iomux-v1.o
 obj-$(CONFIG_PINCTRL_IMX_IOMUX_V2) += imx-iomux-v2.o
 obj-$(CONFIG_PINCTRL_IMX_IOMUX_V3) += imx-iomux-v3.o
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
new file mode 100644
index 0000000..433862a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2005 HP Labs
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ * Copyright (C) 2014 Raphaël Poggi
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <errno.h>
+#include <io.h>
+#include <gpio.h>
+#include <init.h>
+#include <driver.h>
+#include <getopt.h>
+
+#include <mach/at91_pio.h>
+#include <mach/gpio.h>
+
+#include <pinctrl.h>
+
+struct at91_pinctrl {
+	struct pinctrl_device pctl;
+	struct at91_pinctrl_mux_ops	*ops;
+};
+
+struct at91_gpio_chip {
+	struct gpio_chip	chip;
+	void __iomem		*regbase;	/* PIO bank virtual address */
+	struct at91_pinctrl_mux_ops *ops;	/* ops */
+};
+
+enum at91_mux {
+	AT91_MUX_GPIO = 0,
+	AT91_MUX_PERIPH_A = 1,
+	AT91_MUX_PERIPH_B = 2,
+	AT91_MUX_PERIPH_C = 3,
+	AT91_MUX_PERIPH_D = 4,
+};
+
+#define MAX_GPIO_BANKS		5
+#define to_at91_pinctrl(c) container_of(c, struct at91_pinctrl, pctl);
+#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
+
+#define PULL_UP         (1 << 0)
+#define MULTI_DRIVE     (1 << 1)
+#define DEGLITCH        (1 << 2)
+#define PULL_DOWN       (1 << 3)
+#define DIS_SCHMIT      (1 << 4)
+#define DEBOUNCE        (1 << 16)
+#define DEBOUNCE_VAL_SHIFT      17
+#define DEBOUNCE_VAL    (0x3fff << DEBOUNCE_VAL_SHIFT)
+
+static int gpio_banks;
+
+static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
+
+static inline void __iomem *pin_to_controller(struct at91_pinctrl *info, unsigned pin)
+{
+	pin /= MAX_NB_GPIO_PER_BANK;
+	if (likely(pin < gpio_banks))
+		return gpio_chip[pin].regbase;
+
+	return NULL;
+}
+
+/**
+ * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
+ * on new IP with support for periph C and D the way to mux in
+ * periph A and B has changed
+ * So provide the right call back
+ * if not present means the IP does not support it
+ * @get_periph: return the periph mode configured
+ * @mux_A_periph: mux as periph A
+ * @mux_B_periph: mux as periph B
+ * @mux_C_periph: mux as periph C
+ * @mux_D_periph: mux as periph D
+ * @set_deglitch: enable/disable deglitch
+ * @set_debounce: enable/disable debounce
+ * @set_pulldown: enable/disable pulldown
+ * @disable_schmitt_trig: disable schmitt trigger
+ */
+struct at91_pinctrl_mux_ops {
+	enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
+	void (*mux_A_periph)(void __iomem *pio, unsigned mask);
+	void (*mux_B_periph)(void __iomem *pio, unsigned mask);
+	void (*mux_C_periph)(void __iomem *pio, unsigned mask);
+	void (*mux_D_periph)(void __iomem *pio, unsigned mask);
+	bool (*get_deglitch)(void __iomem *pio, unsigned pin);
+	void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
+	bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
+	void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
+	bool (*get_pulldown)(void __iomem *pio, unsigned pin);
+	void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
+	bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
+	void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
+};
+
+static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
+{
+	unsigned select;
+
+	if (__raw_readl(pio + PIO_PSR) & mask)
+		return AT91_MUX_GPIO;
+
+	select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask);
+	select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1);
+
+	return select + 1;
+}
+
+static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
+{
+	unsigned select;
+
+	if (__raw_readl(pio + PIO_PSR) & mask)
+		return AT91_MUX_GPIO;
+
+	select = __raw_readl(pio + PIO_ABSR) & mask;
+
+	return select + 1;
+}
+
+static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
+{
+	return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
+}
+
+static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
+{
+	*div = __raw_readl(pio + PIO_SCDR);
+
+	return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
+}
+
+static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
+{
+	return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
+}
+
+static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
+{
+	return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
+}
+
+static struct at91_pinctrl_mux_ops at91rm9200_ops = {
+	.get_periph	= at91_mux_get_periph,
+	.mux_A_periph	= at91_mux_set_A_periph,
+	.mux_B_periph	= at91_mux_set_B_periph,
+	.get_deglitch	= at91_mux_get_deglitch,
+	.set_deglitch	= at91_mux_set_deglitch,
+};
+
+static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
+	.get_periph	= at91_mux_pio3_get_periph,
+	.mux_A_periph	= at91_mux_pio3_set_A_periph,
+	.mux_B_periph	= at91_mux_pio3_set_B_periph,
+	.mux_C_periph	= at91_mux_pio3_set_C_periph,
+	.mux_D_periph	= at91_mux_pio3_set_D_periph,
+	.get_deglitch	= at91_mux_get_deglitch,
+	.set_deglitch	= at91_mux_pio3_set_deglitch,
+	.get_debounce	= at91_mux_pio3_get_debounce,
+	.set_debounce	= at91_mux_pio3_set_debounce,
+	.get_pulldown	= at91_mux_pio3_get_pulldown,
+	.set_pulldown	= at91_mux_pio3_set_pulldown,
+	.get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+};
+
+static int at91_mux_pin(struct at91_pinctrl *info, unsigned pin, enum at91_mux mux, int use_pullup)
+{
+	void __iomem	*pio = pin_to_controller(info, pin);
+	unsigned mask = pin_to_mask(pin);
+
+	if (!info)
+		return -EINVAL;
+
+	if (!pio)
+		return -EINVAL;
+
+	at91_mux_disable_interrupt(pio, mask);
+
+	switch (mux) {
+	case AT91_MUX_GPIO:
+		at91_mux_gpio_enable(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_A:
+		info->ops->mux_A_periph(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_B:
+		info->ops->mux_B_periph(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_C:
+		if (!info->ops->mux_C_periph)
+			return -EINVAL;
+		info->ops->mux_C_periph(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_D:
+		if (!info->ops->mux_D_periph)
+			return -EINVAL;
+		info->ops->mux_D_periph(pio, mask);
+		break;
+	}
+	if (mux)
+		at91_mux_gpio_disable(pio, mask);
+
+	if (use_pullup >= 0)
+		at91_mux_set_pullup(pio, mask, use_pullup);
+
+	return 0;
+}
+
+static struct of_device_id at91_pinctrl_dt_ids[] = {
+	{
+		.compatible = "atmel,at91rm9200-pinctrl",
+		.data = (unsigned long)&at91rm9200_ops,
+	}, {
+		.compatible = "atmel,at91sam9x5-pinctrl",
+		.data = (unsigned long)&at91sam9x5_ops,
+	}, {
+		/* sentinel */
+	}
+};
+
+static struct at91_pinctrl_mux_ops *at91_pinctrl_get_driver_data(struct device_d *dev)
+{
+	struct at91_pinctrl_mux_ops *ops_data = NULL;
+	int rc;
+
+	if (dev->device_node) {
+		const struct of_device_id *match;
+		match = of_match_node(at91_pinctrl_dt_ids, dev->device_node);
+		if (!match)
+			ops_data = NULL;
+		else
+			ops_data = (struct at91_pinctrl_mux_ops *)match->data;
+	} else {
+		rc = dev_get_drvdata(dev, (unsigned long *)&ops_data);
+		if (rc)
+			ops_data = NULL;
+	}
+
+	return ops_data;
+}
+
+static int at91_pinctrl_set_conf(struct at91_pinctrl *info, unsigned int pin_num, unsigned int mux, unsigned int conf)
+{
+	unsigned int mask;
+	void __iomem *pio;
+
+	pio = pin_to_controller(info, pin_num);
+	mask = pin_to_mask(pin_num);
+
+	if (conf & PULL_UP && conf & PULL_DOWN)
+		return -EINVAL;
+
+	at91_mux_set_pullup(pio, mask, conf & PULL_UP);
+	at91_mux_set_multidrive(pio, mask, conf & MULTI_DRIVE);
+	if (info->ops->set_deglitch)
+		info->ops->set_deglitch(pio, mask, conf & DEGLITCH);
+	if (info->ops->set_debounce)
+		info->ops->set_debounce(pio, mask, conf & DEBOUNCE,
+			(conf & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+	if (info->ops->set_pulldown)
+		info->ops->set_pulldown(pio, mask, conf & PULL_DOWN);
+	if (info->ops->disable_schmitt_trig && conf & DIS_SCHMIT)
+		info->ops->disable_schmitt_trig(pio, mask);
+
+	return 0;
+}
+
+static int at91_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *np)
+{
+	struct at91_pinctrl *info;
+	const __be32 *list;
+	int i, size;
+	int ret = 0;
+	int bank_num, pin_num, mux, conf;
+
+	info = to_at91_pinctrl(pdev);
+
+	list = of_get_property(np, "atmel,pins", &size);
+	size /= sizeof(*list);
+
+	if (!size || size % 4) {
+		dev_err(pdev->dev, "wrong pins number or pins and configs should be by 4\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i += 4) {
+		bank_num = be32_to_cpu(*list++);
+		pin_num = be32_to_cpu(*list++);
+		mux = be32_to_cpu(*list++);
+		conf = be32_to_cpu(*list++);
+
+		ret = at91_mux_pin(info, pin_num, mux, conf & PULL_UP);
+		if (ret) {
+			dev_err(pdev->dev, "failed to mux pin %d\n", pin_num);
+			return ret;
+		}
+
+		ret = at91_pinctrl_set_conf(info, pin_num, mux, conf);
+		if (ret) {
+			dev_err(pdev->dev, "failed to set conf on pin %d\n", pin_num);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static struct pinctrl_ops at91_pinctrl_ops = {
+	.set_state = at91_pinctrl_set_state,
+};
+
+static int at91_pinctrl_probe(struct device_d *dev)
+{
+	struct at91_pinctrl *info;
+	int ret;
+
+	info = xzalloc(sizeof(struct at91_pinctrl));
+
+	info->ops = at91_pinctrl_get_driver_data(dev);
+	if (!info->ops) {
+		dev_err(dev, "failed to retrieve driver data\n");
+		return -ENODEV;
+	}
+
+	info->pctl.dev = dev;
+	info->pctl.ops = &at91_pinctrl_ops;
+
+	ret = pinctrl_register(&info->pctl);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "AT91 pinctrl registered\n");
+
+	return 0;
+}
+
+static struct platform_device_id at91_pinctrl_ids[] = {
+	{
+		.name = "at91rm9200-pinctrl",
+		.driver_data = (unsigned long)&at91rm9200_ops,
+	}, {
+		.name = "at91sam9x5-pinctrl",
+		.driver_data = (unsigned long)&at91sam9x5_ops,
+	}, {
+		/* sentinel */
+	},
+};
+
+static struct driver_d at91_pinctrl_driver = {
+	.name = "pinctrl-at91",
+	.probe = at91_pinctrl_probe,
+	.id_table = at91_pinctrl_ids,
+	.of_compatible = DRV_OF_COMPAT(at91_pinctrl_dt_ids),
+};
+
+static int at91_pinctrl_init(void)
+{
+	return platform_driver_register(&at91_pinctrl_driver);
+}
+coredevice_initcall(at91_pinctrl_init);
+
+static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	return at91_mux_gpio_get(pio, mask);
+}
+
+static void at91_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	at91_mux_gpio_set(pio, mask, value);
+}
+
+static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	at91_mux_gpio_set(pio, mask, value);
+	__raw_writel(mask, pio + PIO_OER);
+
+	return 0;
+}
+
+static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	__raw_writel(mask, pio + PIO_ODR);
+
+	return 0;
+}
+
+static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
+		 'A' + pin_to_bank(chip->base), offset, chip->base + offset);
+	at91_mux_gpio_enable(pio, mask);
+
+	return 0;
+}
+
+static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
+		 'A' + pin_to_bank(chip->base), offset, chip->base + offset);
+}
+
+static struct gpio_ops at91_gpio_ops = {
+	.request = at91_gpio_request,
+	.free = at91_gpio_free,
+	.direction_input = at91_gpio_direction_input,
+	.direction_output = at91_gpio_direction_output,
+	.get = at91_gpio_get,
+	.set = at91_gpio_set,
+};
+
+static struct of_device_id at91_gpio_dt_ids[] = {
+	{
+		.compatible = "atmel,at91rm9200-gpio",
+	}, {
+		.compatible = "atmel,at91sam9x5-gpio",
+	}, {
+		/* sentinel */
+	},
+};
+
+static int at91_gpio_probe(struct device_d *dev)
+{
+	struct at91_gpio_chip *at91_gpio;
+	struct clk *clk;
+	int ret;
+	int alias_idx = of_alias_get_id(dev->device_node, "gpio");
+
+	BUG_ON(dev->id > MAX_GPIO_BANKS);
+
+	at91_gpio = &gpio_chip[alias_idx];
+
+	clk = clk_get(dev, NULL);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		dev_err(dev, "clock not found: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(clk);
+	if (ret < 0) {
+		dev_err(dev, "clock failed to enable: %d\n", ret);
+		clk_put(clk);
+		return ret;
+	}
+
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+	at91_gpio->regbase = dev_request_mem_region(dev, 0);
+
+	at91_gpio->chip.ops = &at91_gpio_ops;
+	at91_gpio->chip.ngpio = MAX_NB_GPIO_PER_BANK;
+	at91_gpio->chip.dev = dev;
+	at91_gpio->chip.base = dev->id * MAX_NB_GPIO_PER_BANK;
+
+	ret = gpiochip_add(&at91_gpio->chip);
+	if (ret) {
+		dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret);
+		return ret;
+	}
+
+	dev_info(dev, "AT91 gpio driver registered\n");
+
+	return 0;
+}
+
+static struct platform_device_id at91_gpio_ids[] = {
+	{
+		.name = "at91rm9200-gpio",
+	}, {
+		.name = "at91sam9x5-gpio",
+	}, {
+		/* sentinel */
+	},
+};
+
+static struct driver_d at91_gpio_driver = {
+	.name = "gpio-at91",
+	.probe = at91_gpio_probe,
+	.id_table = at91_gpio_ids,
+	.of_compatible	= DRV_OF_COMPAT(at91_gpio_dt_ids),
+};
+
+static int at91_gpio_init(void)
+{
+	return platform_driver_register(&at91_gpio_driver);
+}
+coredevice_initcall(at91_gpio_init);
-- 
1.7.9.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v3 3/3] at91sam9g45: add device tree gpio clocks
  2014-09-02 11:07 [PATCH v3 0/3] Add atmel pinctrl driver Raphaël Poggi
  2014-09-02 11:07 ` [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder Raphaël Poggi
  2014-09-02 11:07 ` [PATCH v3 2/3] pinctrl: at91: add pinctrl driver Raphaël Poggi
@ 2014-09-02 11:08 ` Raphaël Poggi
  2014-09-03  6:46   ` Sascha Hauer
  2 siblings, 1 reply; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-02 11:08 UTC (permalink / raw)
  To: barebox; +Cc: Raphaël Poggi

Signed-off-by: Raphaël Poggi <poggi.raph@gmail.com>
---
 arch/arm/mach-at91/at91sam9g45.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index d19d26a..8c020fa 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -201,6 +201,11 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_DEV_ID("at91rm9200-gpio2", &pioC_clk),
 	CLKDEV_DEV_ID("at91rm9200-gpio3", &pioDE_clk),
 	CLKDEV_DEV_ID("at91rm9200-gpio4", &pioDE_clk),
+	CLKDEV_DEV_ID("fffff200.gpio", &pioA_clk),
+	CLKDEV_DEV_ID("fffff400.gpio", &pioB_clk),
+	CLKDEV_DEV_ID("fffff600.gpio", &pioC_clk),
+	CLKDEV_DEV_ID("fffff800.gpio", &pioDE_clk),
+	CLKDEV_DEV_ID("fffffa00.gpio", &pioDE_clk),
 	CLKDEV_DEV_ID("at91-pit", &mck),
 	CLKDEV_CON_DEV_ID("hck1", "atmel_lcdfb", &lcdc_clk),
 };
-- 
1.7.9.5


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 3/3] at91sam9g45: add device tree gpio clocks
  2014-09-02 11:08 ` [PATCH v3 3/3] at91sam9g45: add device tree gpio clocks Raphaël Poggi
@ 2014-09-03  6:46   ` Sascha Hauer
  0 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2014-09-03  6:46 UTC (permalink / raw)
  To: Raphaël Poggi; +Cc: barebox

On Tue, Sep 02, 2014 at 01:08:00PM +0200, Raphaël Poggi wrote:
> Signed-off-by: Raphaël Poggi <poggi.raph@gmail.com>
> ---
>  arch/arm/mach-at91/at91sam9g45.c |    5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
> index d19d26a..8c020fa 100644
> --- a/arch/arm/mach-at91/at91sam9g45.c
> +++ b/arch/arm/mach-at91/at91sam9g45.c
> @@ -201,6 +201,11 @@ static struct clk_lookup periph_clocks_lookups[] = {
>  	CLKDEV_DEV_ID("at91rm9200-gpio2", &pioC_clk),
>  	CLKDEV_DEV_ID("at91rm9200-gpio3", &pioDE_clk),
>  	CLKDEV_DEV_ID("at91rm9200-gpio4", &pioDE_clk),
> +	CLKDEV_DEV_ID("fffff200.gpio", &pioA_clk),
> +	CLKDEV_DEV_ID("fffff400.gpio", &pioB_clk),
> +	CLKDEV_DEV_ID("fffff600.gpio", &pioC_clk),
> +	CLKDEV_DEV_ID("fffff800.gpio", &pioDE_clk),
> +	CLKDEV_DEV_ID("fffffa00.gpio", &pioDE_clk),

Same comment here as to the i2c clocks: Can you use
clkdev_add_physbase(), like this:

	clkdev_add_physbase(&pioA_clk, 0xfffff200, NULL);
	clkdev_add_physbase(&pioB_clk, 0xfffff400, NULL);
	clkdev_add_physbase(&pioC_clk, 0xfffff600, NULL);
	clkdev_add_physbase(&pioDE_clk, 0xfffff800, NULL);
	clkdev_add_physbase(&pioDE_clk, 0xfffffa00, NULL);

at91rm9200-gpiox clkdevs can be removed then.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-02 11:07 ` [PATCH v3 2/3] pinctrl: at91: add pinctrl driver Raphaël Poggi
@ 2014-09-03  6:56   ` Sascha Hauer
  2014-09-03 11:23     ` Raphaël Poggi
  0 siblings, 1 reply; 12+ messages in thread
From: Sascha Hauer @ 2014-09-03  6:56 UTC (permalink / raw)
  To: Raphaël Poggi; +Cc: barebox

On Tue, Sep 02, 2014 at 01:07:59PM +0200, Raphaël Poggi wrote:
> +static int at91_gpio_probe(struct device_d *dev)
> +{
> +	struct at91_gpio_chip *at91_gpio;
> +	struct clk *clk;
> +	int ret;
> +	int alias_idx = of_alias_get_id(dev->device_node, "gpio");
> +
> +	BUG_ON(dev->id > MAX_GPIO_BANKS);
> +
> +	at91_gpio = &gpio_chip[alias_idx];
> +
> +	clk = clk_get(dev, NULL);
> +	if (IS_ERR(clk)) {
> +		ret = PTR_ERR(clk);
> +		dev_err(dev, "clock not found: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = clk_enable(clk);
> +	if (ret < 0) {
> +		dev_err(dev, "clock failed to enable: %d\n", ret);
> +		clk_put(clk);
> +		return ret;
> +	}
> +
> +	gpio_banks = max(gpio_banks, alias_idx + 1);
> +	at91_gpio->regbase = dev_request_mem_region(dev, 0);

Please check the return value.

This driver duplicates the existing Atmel GPIO driver. Shouldn't the
existing driver be dropped? If yes, you should also make sure that this
driver is compiled unconditionally on Atmel SoCs and add a

	if (!IS_ENABLED(CONFIG_PINCTRL))
		return 0;

to at91_pinctrl_init() to reduce the overhead when pinctrl is disabled.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder
  2014-09-02 11:07 ` [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder Raphaël Poggi
@ 2014-09-03  7:00   ` Sascha Hauer
  0 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2014-09-03  7:00 UTC (permalink / raw)
  To: Raphaël Poggi; +Cc: barebox

On Tue, Sep 02, 2014 at 01:07:58PM +0200, Raphaël Poggi wrote:
> This commit add functions from mach-at91/gpio.h in include/mach/gpio.h.
> This allow to use these functions outside the mach-at91 folder.
> 
> Signed-off-by: Raphaël Poggi <poggi.raph@gmail.com>

Applied this one for now, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-03  6:56   ` Sascha Hauer
@ 2014-09-03 11:23     ` Raphaël Poggi
  2014-09-03 13:52       ` Sascha Hauer
  0 siblings, 1 reply; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-03 11:23 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Sounds good, but files like at91samXXX_devices.c need gpio functions.
I think the problem is that the mach-at91/gpio.c file include a gpio
driver which not belong to be here, the right place is in the
driver/pinctrl (like my patch). But all files like
at91samXXX_devices.c are using the functions from this gpio driver.

So I think we have to:

1. Rewrite mach-at91/gpio.c and populate it with basic gpio functions
(cf. http://lxr.free-electrons.com/source/arch/arm/mach-at91/gpio.c
from line 130 to 425).
2. Replace in at91samXXX_devices.c files, reference of functions from
the gpio driver by these basic new functions.

By this way, when AT91 code are registering the gpio subsystem, we use
the pinctrl/gpio driver and also we avoid duplicate code.

Let me know if I am on the right way or not.

Raphaël

2014-09-03 8:56 GMT+02:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Tue, Sep 02, 2014 at 01:07:59PM +0200, Raphaël Poggi wrote:
>> +static int at91_gpio_probe(struct device_d *dev)
>> +{
>> +     struct at91_gpio_chip *at91_gpio;
>> +     struct clk *clk;
>> +     int ret;
>> +     int alias_idx = of_alias_get_id(dev->device_node, "gpio");
>> +
>> +     BUG_ON(dev->id > MAX_GPIO_BANKS);
>> +
>> +     at91_gpio = &gpio_chip[alias_idx];
>> +
>> +     clk = clk_get(dev, NULL);
>> +     if (IS_ERR(clk)) {
>> +             ret = PTR_ERR(clk);
>> +             dev_err(dev, "clock not found: %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     ret = clk_enable(clk);
>> +     if (ret < 0) {
>> +             dev_err(dev, "clock failed to enable: %d\n", ret);
>> +             clk_put(clk);
>> +             return ret;
>> +     }
>> +
>> +     gpio_banks = max(gpio_banks, alias_idx + 1);
>> +     at91_gpio->regbase = dev_request_mem_region(dev, 0);
>
> Please check the return value.
>
> This driver duplicates the existing Atmel GPIO driver. Shouldn't the
> existing driver be dropped? If yes, you should also make sure that this
> driver is compiled unconditionally on Atmel SoCs and add a
>
>         if (!IS_ENABLED(CONFIG_PINCTRL))
>                 return 0;
>
> to at91_pinctrl_init() to reduce the overhead when pinctrl is disabled.
>
> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-03 11:23     ` Raphaël Poggi
@ 2014-09-03 13:52       ` Sascha Hauer
  2014-09-03 15:10         ` Raphaël Poggi
  0 siblings, 1 reply; 12+ messages in thread
From: Sascha Hauer @ 2014-09-03 13:52 UTC (permalink / raw)
  To: Raphaël Poggi; +Cc: barebox

On Wed, Sep 03, 2014 at 01:23:14PM +0200, Raphaël Poggi wrote:
> Sounds good, but files like at91samXXX_devices.c need gpio functions.
> I think the problem is that the mach-at91/gpio.c file include a gpio
> driver which not belong to be here, the right place is in the
> driver/pinctrl (like my patch). But all files like
> at91samXXX_devices.c are using the functions from this gpio driver.
> 
> So I think we have to:
> 
> 1. Rewrite mach-at91/gpio.c and populate it with basic gpio functions
> (cf. http://lxr.free-electrons.com/source/arch/arm/mach-at91/gpio.c
> from line 130 to 425).
> 2. Replace in at91samXXX_devices.c files, reference of functions from
> the gpio driver by these basic new functions.
> 
> By this way, when AT91 code are registering the gpio subsystem, we use
> the pinctrl/gpio driver and also we avoid duplicate code.
> 
> Let me know if I am on the right way or not.

Isn't it possible to move the functions into the pinctrl driver like
done in the following patch? It's not that nice to call from
architecture code directly into the driver code, but I think it should
work. We do the same for i.MX.

Sascha

---------------8<-------------------------

From a351ae7f3815d3e555290380c70d0cb35b04e7a3 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Wed, 3 Sep 2014 15:51:05 +0200
Subject: [PATCH] ARM: AT91: move arch/arm/mach-at91/gpio.c functions to
 pinctrl driver

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/Kconfig               |   1 +
 arch/arm/mach-at91/Makefile    |   2 +-
 arch/arm/mach-at91/gpio.c      | 670 -----------------------------------------
 drivers/pinctrl/Kconfig        |   2 +-
 drivers/pinctrl/pinctrl-at91.c | 246 ++++++++++++---
 5 files changed, 203 insertions(+), 718 deletions(-)
 delete mode 100644 arch/arm/mach-at91/gpio.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9f34e10..13f0bd4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -37,6 +37,7 @@ config ARCH_AT91
 	select HAS_DEBUG_LL
 	select HAVE_MACH_ARM_HEAD
 	select HAVE_CLK
+	select PINCTRL_AT91
 
 config ARCH_BCM2835
 	bool "Broadcom BCM2835 boards"
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index ab80e5f..8599f50 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -1,4 +1,4 @@
-obj-y += setup.o clock.o gpio.o irq_fixup.o
+obj-y += setup.o clock.o irq_fixup.o
 obj-$(CONFIG_CMD_AT91_BOOT_TEST) += boot_test_cmd.o
 
 obj-$(CONFIG_AT91_BOOTSTRAP) += bootstrap.o
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
deleted file mode 100644
index 402634b..0000000
--- a/arch/arm/mach-at91/gpio.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * Copyright (C) 2005 HP Labs
- * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <common.h>
-#include <command.h>
-#include <complete.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <errno.h>
-#include <io.h>
-#include <mach/iomux.h>
-#include <mach/io.h>
-#include <mach/cpu.h>
-#include <gpio.h>
-#include <init.h>
-#include <driver.h>
-#include <getopt.h>
-
-#include <mach/gpio.h>
-
-#define MAX_GPIO_BANKS		5
-
-static int gpio_banks = 0;
-
-/*
- * Functionnality can change with newer chips
- */
-struct at91_gpio_chip {
-	struct gpio_chip	chip;
-	void __iomem		*regbase;	/* PIO bank virtual address */
-	struct at91_pinctrl_mux_ops *ops;	/* ops */
-};
-
-#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
-
-static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
-
-static inline struct at91_gpio_chip *pin_to_controller(unsigned pin)
-{
-	pin /= MAX_NB_GPIO_PER_BANK;
-	if (likely(pin < gpio_banks))
-		return &gpio_chip[pin];
-
-	return NULL;
-}
-
-/**
- * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
- * on new IP with support for periph C and D the way to mux in
- * periph A and B has changed
- * So provide the right call back
- * if not present means the IP does not support it
- * @get_periph: return the periph mode configured
- * @mux_A_periph: mux as periph A
- * @mux_B_periph: mux as periph B
- * @mux_C_periph: mux as periph C
- * @mux_D_periph: mux as periph D
- * @set_deglitch: enable/disable deglitch
- * @set_debounce: enable/disable debounce
- * @set_pulldown: enable/disable pulldown
- * @disable_schmitt_trig: disable schmitt trigger
- */
-struct at91_pinctrl_mux_ops {
-	enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
-	void (*mux_A_periph)(void __iomem *pio, unsigned mask);
-	void (*mux_B_periph)(void __iomem *pio, unsigned mask);
-	void (*mux_C_periph)(void __iomem *pio, unsigned mask);
-	void (*mux_D_periph)(void __iomem *pio, unsigned mask);
-	bool (*get_deglitch)(void __iomem *pio, unsigned pin);
-	void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
-	bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
-	void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
-	bool (*get_pulldown)(void __iomem *pio, unsigned pin);
-	void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
-	bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
-	void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
-};
-
-#ifdef CONFIG_CMD_AT91MUX
-static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
-{
-	return (__raw_readl(pio + PIO_PUSR) >> pin) & 0x1;
-}
-
-static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
-{
-	return (__raw_readl(pio + PIO_MDSR) >> pin) & 0x1;
-}
-
-static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
-{
-	unsigned select;
-
-	if (__raw_readl(pio + PIO_PSR) & mask)
-		return AT91_MUX_GPIO;
-
-	select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask);
-	select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1);
-
-	return select + 1;
-}
-
-static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
-{
-	unsigned select;
-
-	if (__raw_readl(pio + PIO_PSR) & mask)
-		return AT91_MUX_GPIO;
-
-	select = __raw_readl(pio + PIO_ABSR) & mask;
-
-	return select + 1;
-}
-
-static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
-{
-	return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
-}
-
-static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
-{
-	*div = __raw_readl(pio + PIO_SCDR);
-
-	return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
-}
-
-static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
-{
-	return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
-}
-
-static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
-{
-	return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
-}
-#else
-#define at91_mux_get_periph		NULL
-#define at91_mux_pio3_get_periph	NULL
-#define at91_mux_get_deglitch		NULL
-#define at91_mux_pio3_get_debounce	NULL
-#define at91_mux_pio3_get_pulldown	NULL
-#define at91_mux_pio3_get_schmitt_trig	NULL
-#endif
-
-static struct at91_pinctrl_mux_ops at91rm9200_ops = {
-	.get_periph	= at91_mux_get_periph,
-	.mux_A_periph	= at91_mux_set_A_periph,
-	.mux_B_periph	= at91_mux_set_B_periph,
-	.get_deglitch	= at91_mux_get_deglitch,
-	.set_deglitch	= at91_mux_set_deglitch,
-};
-
-static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
-	.get_periph	= at91_mux_pio3_get_periph,
-	.mux_A_periph	= at91_mux_pio3_set_A_periph,
-	.mux_B_periph	= at91_mux_pio3_set_B_periph,
-	.mux_C_periph	= at91_mux_pio3_set_C_periph,
-	.mux_D_periph	= at91_mux_pio3_set_D_periph,
-	.get_deglitch	= at91_mux_get_deglitch,
-	.set_deglitch	= at91_mux_pio3_set_deglitch,
-	.get_debounce	= at91_mux_pio3_get_debounce,
-	.set_debounce	= at91_mux_pio3_set_debounce,
-	.get_pulldown	= at91_mux_pio3_get_pulldown,
-	.set_pulldown	= at91_mux_pio3_set_pulldown,
-	.get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
-	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
-};
-
-int at91_mux_pin(unsigned pin, enum at91_mux mux, int use_pullup)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem *pio;
-	struct device_d *dev;
-	unsigned mask = pin_to_mask(pin);
-	int bank = pin_to_bank(pin);
-
-	if (!at91_gpio)
-		return -EINVAL;
-
-	pio = at91_gpio->regbase;
-	if (!pio)
-		return -EINVAL;
-
-	dev = at91_gpio->chip.dev;
-	at91_mux_disable_interrupt(pio, mask);
-
-	pin %= MAX_NB_GPIO_PER_BANK;
-	if (mux) {
-		dev_dbg(dev, "pio%c%d configured as periph%c with pullup = %d\n",
-			bank + 'A', pin, mux - 1 + 'A', use_pullup);
-	} else {
-		dev_dbg(dev, "pio%c%d configured as gpio with pullup = %d\n",
-			bank + 'A', pin, use_pullup);
-	}
-
-	switch(mux) {
-	case AT91_MUX_GPIO:
-		at91_mux_gpio_enable(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_A:
-		at91_gpio->ops->mux_A_periph(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_B:
-		at91_gpio->ops->mux_B_periph(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_C:
-		if (!at91_gpio->ops->mux_C_periph)
-			return -EINVAL;
-		at91_gpio->ops->mux_C_periph(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_D:
-		if (!at91_gpio->ops->mux_D_periph)
-			return -EINVAL;
-		at91_gpio->ops->mux_D_periph(pio, mask);
-		break;
-	}
-	if (mux)
-		at91_mux_gpio_disable(pio, mask);
-
-	if (use_pullup >= 0)
-		at91_mux_set_pullup(pio, mask, use_pullup);
-
-	return 0;
-}
-EXPORT_SYMBOL(at91_mux_pin);
-
-/*
- * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
- * configure it for an input.
- */
-int at91_set_gpio_input(unsigned pin, int use_pullup)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-	int ret;
-
-	ret = at91_mux_pin(pin, AT91_MUX_GPIO, use_pullup);
-	if (ret)
-		return ret;
-
-	dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as input\n",
-		pin_to_bank(pin) + 'A', pin_to_bank_offset(pin));
-
-	at91_mux_gpio_input(pio, mask, true);
-
-	return 0;
-}
-
-/*
- * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
- * and configure it for an output.
- */
-int at91_set_gpio_output(unsigned pin, int value)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-	int ret;
-
-	ret = at91_mux_pin(pin, AT91_MUX_GPIO, -1);
-	if (ret)
-		return ret;
-
-	dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as output val = %d\n",
-		pin_to_bank(pin) + 'A', pin_to_bank_offset(pin), value);
-
-	at91_mux_gpio_input(pio, mask, false);
-	at91_mux_gpio_set(pio, mask, value);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_output);
-
-/*
- * enable/disable the glitch filter; mostly used with IRQ handling.
- */
-int at91_set_deglitch(unsigned pin, int is_on)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	at91_gpio->ops->set_deglitch(pio, mask, is_on);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_deglitch);
-
-/*
- * enable/disable the debounce filter;
- */
-int at91_set_debounce(unsigned pin, int is_on, int div)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio || !at91_gpio->ops->set_debounce)
-		return -EINVAL;
-
-	at91_gpio->ops->set_debounce(pio, mask, is_on, div);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_debounce);
-
-/*
- * enable/disable the multi-driver; This is only valid for output and
- * allows the output pin to run as an open collector output.
- */
-int at91_set_multi_drive(unsigned pin, int is_on)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio)
-		return -EINVAL;
-
-	at91_mux_set_multidrive(pio, mask, is_on);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_multi_drive);
-
-/*
- * enable/disable the pull-down.
- * If pull-up already enabled while calling the function, we disable it.
- */
-int at91_set_pulldown(unsigned pin, int is_on)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio || !at91_gpio->ops->set_pulldown)
-		return -EINVAL;
-
-	/* Disable pull-up anyway */
-	at91_mux_set_pullup(pio, mask, 0);
-	at91_gpio->ops->set_pulldown(pio, mask, is_on);
-	return 0;
-}
-EXPORT_SYMBOL(at91_set_pulldown);
-
-/*
- * disable Schmitt trigger
- */
-int at91_disable_schmitt_trig(unsigned pin)
-{
-	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
-	void __iomem	*pio = at91_gpio->regbase;
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio || !at91_gpio->ops->disable_schmitt_trig)
-		return -EINVAL;
-
-	at91_gpio->ops->disable_schmitt_trig(pio, mask);
-	return 0;
-}
-EXPORT_SYMBOL(at91_disable_schmitt_trig);
-
-#ifdef CONFIG_CMD_AT91MUX
-static void at91mux_printf_mode(unsigned bank, unsigned pin)
-{
-	struct at91_gpio_chip *at91_gpio = &gpio_chip[bank];
-	void __iomem *pio = at91_gpio->regbase;
-	enum at91_mux mode;
-	u32 pdsr;
-
-	unsigned mask = pin_to_mask(pin);
-
-	mode = at91_gpio->ops->get_periph(pio, mask);
-
-	if (mode == AT91_MUX_GPIO) {
-		pdsr = __raw_readl(pio + PIO_PDSR);
-
-		printf("[gpio] %s", pdsr & mask ? "set" : "clear");
-	} else {
-		printf("[periph %c]", mode + 'A' - 1);
-	}
-}
-
-static void at91mux_dump_config(void)
-{
-	int bank, j;
-
-	/* print heading */
-	printf("Pin\t");
-	for (bank = 0; bank < gpio_banks; bank++) {
-		printf("PIO%c\t\t", 'A' + bank);
-	};
-	printf("\n\n");
-
-	/* print pin status */
-	for (j = 0; j < 32; j++) {
-		printf("%i:\t", j);
-
-		for (bank = 0; bank < gpio_banks; bank++) {
-			at91mux_printf_mode(bank, j);
-
-			printf("\t");
-		}
-
-		printf("\n");
-	}
-}
-
-static void at91mux_print_en_disable(const char *str, bool is_on)
-{
-	printf("%s = ", str);
-
-	if (is_on)
-		printf("enable\n");
-	else
-		printf("disable\n");
-}
-
-static void at91mux_dump_pio_config(unsigned bank, unsigned pin)
-{
-	struct at91_gpio_chip *at91_gpio = &gpio_chip[bank];
-	void __iomem *pio = at91_gpio->regbase;
-	u32 div;
-
-	printf("pio%c%u configuration\n\n", bank + 'A', pin);
-
-	at91mux_printf_mode(bank, pin);
-	printf("\n");
-
-	at91mux_print_en_disable("multidrive",
-		at91_mux_get_multidrive(pio, pin));
-
-	at91mux_print_en_disable("pullup",
-		at91_mux_get_pullup(pio, pin));
-
-	if (at91_gpio->ops->get_deglitch)
-		at91mux_print_en_disable("degitch",
-			at91_gpio->ops->get_deglitch(pio, pin));
-
-	if (at91_gpio->ops->get_debounce) {
-		printf("debounce = ");
-		if (at91_gpio->ops->get_debounce(pio, pin, &div))
-			printf("enable at %d\n", div);
-		else
-			printf("disable\n");
-	}
-
-	if (at91_gpio->ops->get_pulldown)
-		at91mux_print_en_disable("pulldown",
-			at91_gpio->ops->get_pulldown(pio, pin));
-
-	if (at91_gpio->ops->get_schmitt_trig)
-		at91mux_print_en_disable("schmitt trigger",
-			!at91_gpio->ops->get_schmitt_trig(pio, pin));
-}
-
-static int do_at91mux(int argc, char *argv[])
-{
-	int opt;
-	unsigned bank = 0;
-	unsigned pin = 0;
-
-	if (argc < 2) {
-		at91mux_dump_config();
-		return 0;
-	}
-
-	while ((opt = getopt(argc, argv, "b:p:")) > 0) {
-		switch (opt) {
-		case 'b':
-			bank = simple_strtoul(optarg, NULL, 10);
-			break;
-		case 'p':
-			pin = simple_strtoul(optarg, NULL, 10);
-			break;
-		}
-	}
-
-	if (bank >= gpio_banks) {
-		printf("bank %c >= supported %c banks\n", bank + 'A',
-			gpio_banks + 'A');
-		return 1;
-	}
-
-	if (pin >= 32) {
-		printf("pin %u >= supported %d pins\n", pin, 32);
-		return 1;
-	}
-
-	at91mux_dump_pio_config(bank, pin);
-
-	return 0;
-}
-
-BAREBOX_CMD_HELP_START(at91mux)
-BAREBOX_CMD_HELP_TEXT("Dump current MUX configuration. If a BANK or PIN has been")
-BAREBOX_CMD_HELP_TEXT("specified dump pin details.")
-BAREBOX_CMD_HELP_TEXT("")
-BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT ("-p PIN", "pin number")
-BAREBOX_CMD_HELP_OPT ("-b BANK", "bank number")
-BAREBOX_CMD_HELP_END
-
-BAREBOX_CMD_START(at91mux)
-	.cmd		= do_at91mux,
-	BAREBOX_CMD_DESC("list MUX configuration")
-	BAREBOX_CMD_OPTS("[-pb]")
-	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
-	BAREBOX_CMD_HELP(cmd_at91mux_help)
-	BAREBOX_CMD_COMPLETE(empty_complete)
-BAREBOX_CMD_END
-#endif
-/*--------------------------------------------------------------------------*/
-
-static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-	void __iomem *pio = at91_gpio->regbase;
-	unsigned mask = 1 << offset;
-
-	return at91_mux_gpio_get(pio, mask);
-}
-
-static void at91_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-	void __iomem *pio = at91_gpio->regbase;
-	unsigned mask = 1 << offset;
-
-	at91_mux_gpio_set(pio, mask, value);
-}
-
-static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-		int value)
-{
-	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-	void __iomem *pio = at91_gpio->regbase;
-	unsigned mask = 1 << offset;
-
-	at91_mux_gpio_set(pio, mask, value);
-	__raw_writel(mask, pio + PIO_OER);
-
-	return 0;
-}
-
-static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-	void __iomem *pio = at91_gpio->regbase;
-	unsigned mask = 1 << offset;
-
-	__raw_writel(mask, pio + PIO_ODR);
-
-	return 0;
-}
-
-static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-	void __iomem *pio = at91_gpio->regbase;
-	unsigned mask = 1 << offset;
-
-	dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
-		 'A' + pin_to_bank(chip->base), offset, chip->base + offset);
-	at91_mux_gpio_enable(pio, mask);
-
-	return 0;
-}
-
-static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
-		 'A' + pin_to_bank(chip->base), offset, chip->base + offset);
-}
-
-static struct gpio_ops at91_gpio_ops = {
-	.request = at91_gpio_request,
-	.free = at91_gpio_free,
-	.direction_input = at91_gpio_direction_input,
-	.direction_output = at91_gpio_direction_output,
-	.get = at91_gpio_get,
-	.set = at91_gpio_set,
-};
-
-static int at91_gpio_probe(struct device_d *dev)
-{
-	struct at91_gpio_chip *at91_gpio;
-	struct clk *clk;
-	int ret;
-
-	BUG_ON(dev->id > MAX_GPIO_BANKS);
-
-	at91_gpio = &gpio_chip[dev->id];
-
-	ret = dev_get_drvdata(dev, (unsigned long *)&at91_gpio->ops);
-	if (ret) {
-		dev_err(dev, "dev_get_drvdata failed: %d\n", ret);
-		return ret;
-	}
-
-	clk = clk_get(dev, NULL);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
-		dev_err(dev, "clock not found: %d\n", ret);
-		return ret;
-	}
-
-	ret = clk_enable(clk);
-	if (ret < 0) {
-		dev_err(dev, "clock failed to enable: %d\n", ret);
-		clk_put(clk);
-		return ret;
-	}
-
-	gpio_banks = max(gpio_banks, dev->id + 1);
-	at91_gpio->regbase = dev_request_mem_region(dev, 0);
-
-	at91_gpio->chip.ops = &at91_gpio_ops;
-	at91_gpio->chip.ngpio = MAX_NB_GPIO_PER_BANK;
-	at91_gpio->chip.dev = dev;
-	at91_gpio->chip.base = dev->id * MAX_NB_GPIO_PER_BANK;
-
-	ret = gpiochip_add(&at91_gpio->chip);
-	if (ret) {
-		dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct platform_device_id at91_gpio_ids[] = {
-	{
-		.name = "at91rm9200-gpio",
-		.driver_data = (unsigned long)&at91rm9200_ops,
-	}, {
-		.name = "at91sam9x5-gpio",
-		.driver_data = (unsigned long)&at91sam9x5_ops,
-	}, {
-		/* sentinel */
-	},
-};
-
-static struct driver_d at91_gpio_driver = {
-	.name = "at91-gpio",
-	.probe = at91_gpio_probe,
-	.id_table = at91_gpio_ids,
-};
-
-static int at91_gpio_init(void)
-{
-	return platform_driver_register(&at91_gpio_driver);
-}
-postcore_initcall(at91_gpio_init);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 57281a1..398b931 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -8,7 +8,7 @@ config PINCTRL
 	  support but instead provide their own SoC specific APIs
 
 config PINCTRL_AT91
-	select PINCTRL
+	select PINCTRL if OFDEVICE
 	bool
 	help
 	    The pinmux controller found on AT91 SoCs.
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 433862a..597deea 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -71,7 +71,7 @@ static int gpio_banks;
 
 static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
 
-static inline void __iomem *pin_to_controller(struct at91_pinctrl *info, unsigned pin)
+static inline void __iomem *pin_to_controller(unsigned pin)
 {
 	pin /= MAX_NB_GPIO_PER_BANK;
 	if (likely(pin < gpio_banks))
@@ -112,6 +112,200 @@ struct at91_pinctrl_mux_ops {
 	void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
 };
 
+int at91_mux_pin(unsigned pin, enum at91_mux mux, int use_pullup)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem *pio;
+	struct device_d *dev;
+	unsigned mask = pin_to_mask(pin);
+	int bank = pin_to_bank(pin);
+
+	if (!at91_gpio)
+		return -EINVAL;
+
+	pio = at91_gpio->regbase;
+	if (!pio)
+		return -EINVAL;
+
+	dev = at91_gpio->chip.dev;
+	at91_mux_disable_interrupt(pio, mask);
+
+	pin %= MAX_NB_GPIO_PER_BANK;
+	if (mux) {
+		dev_dbg(dev, "pio%c%d configured as periph%c with pullup = %d\n",
+			bank + 'A', pin, mux - 1 + 'A', use_pullup);
+	} else {
+		dev_dbg(dev, "pio%c%d configured as gpio with pullup = %d\n",
+			bank + 'A', pin, use_pullup);
+	}
+
+	switch(mux) {
+	case AT91_MUX_GPIO:
+		at91_mux_gpio_enable(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_A:
+		at91_gpio->ops->mux_A_periph(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_B:
+		at91_gpio->ops->mux_B_periph(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_C:
+		if (!at91_gpio->ops->mux_C_periph)
+			return -EINVAL;
+		at91_gpio->ops->mux_C_periph(pio, mask);
+		break;
+	case AT91_MUX_PERIPH_D:
+		if (!at91_gpio->ops->mux_D_periph)
+			return -EINVAL;
+		at91_gpio->ops->mux_D_periph(pio, mask);
+		break;
+	}
+	if (mux)
+		at91_mux_gpio_disable(pio, mask);
+
+	if (use_pullup >= 0)
+		at91_mux_set_pullup(pio, mask, use_pullup);
+
+	return 0;
+}
+EXPORT_SYMBOL(at91_mux_pin);
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
+ * configure it for an input.
+ */
+int at91_set_gpio_input(unsigned pin, int use_pullup)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+	int ret;
+
+	ret = at91_mux_pin(pin, AT91_MUX_GPIO, use_pullup);
+	if (ret)
+		return ret;
+
+	dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as input\n",
+		pin_to_bank(pin) + 'A', pin_to_bank_offset(pin));
+
+	at91_mux_gpio_input(pio, mask, true);
+
+	return 0;
+}
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
+ * and configure it for an output.
+ */
+int at91_set_gpio_output(unsigned pin, int value)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+	int ret;
+
+	ret = at91_mux_pin(pin, AT91_MUX_GPIO, -1);
+	if (ret)
+		return ret;
+
+	dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as output val = %d\n",
+		pin_to_bank(pin) + 'A', pin_to_bank_offset(pin), value);
+
+	at91_mux_gpio_input(pio, mask, false);
+	at91_mux_gpio_set(pio, mask, value);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_output);
+
+/*
+ * enable/disable the glitch filter; mostly used with IRQ handling.
+ */
+int at91_set_deglitch(unsigned pin, int is_on)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	at91_gpio->ops->set_deglitch(pio, mask, is_on);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_deglitch);
+
+/*
+ * enable/disable the debounce filter;
+ */
+int at91_set_debounce(unsigned pin, int is_on, int div)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !at91_gpio->ops->set_debounce)
+		return -EINVAL;
+
+	at91_gpio->ops->set_debounce(pio, mask, is_on, div);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_debounce);
+
+/*
+ * enable/disable the multi-driver; This is only valid for output and
+ * allows the output pin to run as an open collector output.
+ */
+int at91_set_multi_drive(unsigned pin, int is_on)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+
+	at91_mux_set_multidrive(pio, mask, is_on);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_multi_drive);
+
+/*
+ * enable/disable the pull-down.
+ * If pull-up already enabled while calling the function, we disable it.
+ */
+int at91_set_pulldown(unsigned pin, int is_on)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !at91_gpio->ops->set_pulldown)
+		return -EINVAL;
+
+	/* Disable pull-up anyway */
+	at91_mux_set_pullup(pio, mask, 0);
+	at91_gpio->ops->set_pulldown(pio, mask, is_on);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_pulldown);
+
+/*
+ * disable Schmitt trigger
+ */
+int at91_disable_schmitt_trig(unsigned pin)
+{
+	struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !at91_gpio->ops->disable_schmitt_trig)
+		return -EINVAL;
+
+	at91_gpio->ops->disable_schmitt_trig(pio, mask);
+	return 0;
+}
+EXPORT_SYMBOL(at91_disable_schmitt_trig);
+
 static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
 {
 	unsigned select;
@@ -183,49 +377,6 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
 	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
 };
 
-static int at91_mux_pin(struct at91_pinctrl *info, unsigned pin, enum at91_mux mux, int use_pullup)
-{
-	void __iomem	*pio = pin_to_controller(info, pin);
-	unsigned mask = pin_to_mask(pin);
-
-	if (!info)
-		return -EINVAL;
-
-	if (!pio)
-		return -EINVAL;
-
-	at91_mux_disable_interrupt(pio, mask);
-
-	switch (mux) {
-	case AT91_MUX_GPIO:
-		at91_mux_gpio_enable(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_A:
-		info->ops->mux_A_periph(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_B:
-		info->ops->mux_B_periph(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_C:
-		if (!info->ops->mux_C_periph)
-			return -EINVAL;
-		info->ops->mux_C_periph(pio, mask);
-		break;
-	case AT91_MUX_PERIPH_D:
-		if (!info->ops->mux_D_periph)
-			return -EINVAL;
-		info->ops->mux_D_periph(pio, mask);
-		break;
-	}
-	if (mux)
-		at91_mux_gpio_disable(pio, mask);
-
-	if (use_pullup >= 0)
-		at91_mux_set_pullup(pio, mask, use_pullup);
-
-	return 0;
-}
-
 static struct of_device_id at91_pinctrl_dt_ids[] = {
 	{
 		.compatible = "atmel,at91rm9200-pinctrl",
@@ -264,7 +415,7 @@ static int at91_pinctrl_set_conf(struct at91_pinctrl *info, unsigned int pin_num
 	unsigned int mask;
 	void __iomem *pio;
 
-	pio = pin_to_controller(info, pin_num);
+	pio = pin_to_controller(pin_num);
 	mask = pin_to_mask(pin_num);
 
 	if (conf & PULL_UP && conf & PULL_DOWN)
@@ -309,7 +460,7 @@ static int at91_pinctrl_set_state(struct pinctrl_device *pdev, struct device_nod
 		mux = be32_to_cpu(*list++);
 		conf = be32_to_cpu(*list++);
 
-		ret = at91_mux_pin(info, pin_num, mux, conf & PULL_UP);
+		ret = at91_mux_pin(pin_num, mux, conf & PULL_UP);
 		if (ret) {
 			dev_err(pdev->dev, "failed to mux pin %d\n", pin_num);
 			return ret;
@@ -334,6 +485,9 @@ static int at91_pinctrl_probe(struct device_d *dev)
 	struct at91_pinctrl *info;
 	int ret;
 
+	if (!IS_ENABLED(CONFIG_PINCTRL))
+		return 0;
+
 	info = xzalloc(sizeof(struct at91_pinctrl));
 
 	info->ops = at91_pinctrl_get_driver_data(dev);
-- 
2.1.0



-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-03 13:52       ` Sascha Hauer
@ 2014-09-03 15:10         ` Raphaël Poggi
  2014-09-04  9:26           ` Sascha Hauer
  0 siblings, 1 reply; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-03 15:10 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

This patch is perfect :-). You just miss to check the return value in
at91_gpio_probe.

Do I have to integrate this patch in mine ? or you will apply it yourself ?

2014-09-03 15:52 GMT+02:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Wed, Sep 03, 2014 at 01:23:14PM +0200, Raphaël Poggi wrote:
>> Sounds good, but files like at91samXXX_devices.c need gpio functions.
>> I think the problem is that the mach-at91/gpio.c file include a gpio
>> driver which not belong to be here, the right place is in the
>> driver/pinctrl (like my patch). But all files like
>> at91samXXX_devices.c are using the functions from this gpio driver.
>>
>> So I think we have to:
>>
>> 1. Rewrite mach-at91/gpio.c and populate it with basic gpio functions
>> (cf. http://lxr.free-electrons.com/source/arch/arm/mach-at91/gpio.c
>> from line 130 to 425).
>> 2. Replace in at91samXXX_devices.c files, reference of functions from
>> the gpio driver by these basic new functions.
>>
>> By this way, when AT91 code are registering the gpio subsystem, we use
>> the pinctrl/gpio driver and also we avoid duplicate code.
>>
>> Let me know if I am on the right way or not.
>
> Isn't it possible to move the functions into the pinctrl driver like
> done in the following patch? It's not that nice to call from
> architecture code directly into the driver code, but I think it should
> work. We do the same for i.MX.
>
> Sascha
>
> ---------------8<-------------------------
>
> From a351ae7f3815d3e555290380c70d0cb35b04e7a3 Mon Sep 17 00:00:00 2001
> From: Sascha Hauer <s.hauer@pengutronix.de>
> Date: Wed, 3 Sep 2014 15:51:05 +0200
> Subject: [PATCH] ARM: AT91: move arch/arm/mach-at91/gpio.c functions to
>  pinctrl driver
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/Kconfig               |   1 +
>  arch/arm/mach-at91/Makefile    |   2 +-
>  arch/arm/mach-at91/gpio.c      | 670 -----------------------------------------
>  drivers/pinctrl/Kconfig        |   2 +-
>  drivers/pinctrl/pinctrl-at91.c | 246 ++++++++++++---
>  5 files changed, 203 insertions(+), 718 deletions(-)
>  delete mode 100644 arch/arm/mach-at91/gpio.c
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 9f34e10..13f0bd4 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -37,6 +37,7 @@ config ARCH_AT91
>         select HAS_DEBUG_LL
>         select HAVE_MACH_ARM_HEAD
>         select HAVE_CLK
> +       select PINCTRL_AT91
>
>  config ARCH_BCM2835
>         bool "Broadcom BCM2835 boards"
> diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
> index ab80e5f..8599f50 100644
> --- a/arch/arm/mach-at91/Makefile
> +++ b/arch/arm/mach-at91/Makefile
> @@ -1,4 +1,4 @@
> -obj-y += setup.o clock.o gpio.o irq_fixup.o
> +obj-y += setup.o clock.o irq_fixup.o
>  obj-$(CONFIG_CMD_AT91_BOOT_TEST) += boot_test_cmd.o
>
>  obj-$(CONFIG_AT91_BOOTSTRAP) += bootstrap.o
> diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
> deleted file mode 100644
> index 402634b..0000000
> --- a/arch/arm/mach-at91/gpio.c
> +++ /dev/null
> @@ -1,670 +0,0 @@
> -/*
> - * Copyright (C) 2005 HP Labs
> - * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> - *
> - * See file CREDITS for list of people who contributed to this
> - * project.
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public License as
> - * published by the Free Software Foundation; either version 2 of
> - * the License, or (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - */
> -
> -#include <common.h>
> -#include <command.h>
> -#include <complete.h>
> -#include <linux/clk.h>
> -#include <linux/err.h>
> -#include <errno.h>
> -#include <io.h>
> -#include <mach/iomux.h>
> -#include <mach/io.h>
> -#include <mach/cpu.h>
> -#include <gpio.h>
> -#include <init.h>
> -#include <driver.h>
> -#include <getopt.h>
> -
> -#include <mach/gpio.h>
> -
> -#define MAX_GPIO_BANKS         5
> -
> -static int gpio_banks = 0;
> -
> -/*
> - * Functionnality can change with newer chips
> - */
> -struct at91_gpio_chip {
> -       struct gpio_chip        chip;
> -       void __iomem            *regbase;       /* PIO bank virtual address */
> -       struct at91_pinctrl_mux_ops *ops;       /* ops */
> -};
> -
> -#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
> -
> -static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
> -
> -static inline struct at91_gpio_chip *pin_to_controller(unsigned pin)
> -{
> -       pin /= MAX_NB_GPIO_PER_BANK;
> -       if (likely(pin < gpio_banks))
> -               return &gpio_chip[pin];
> -
> -       return NULL;
> -}
> -
> -/**
> - * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
> - * on new IP with support for periph C and D the way to mux in
> - * periph A and B has changed
> - * So provide the right call back
> - * if not present means the IP does not support it
> - * @get_periph: return the periph mode configured
> - * @mux_A_periph: mux as periph A
> - * @mux_B_periph: mux as periph B
> - * @mux_C_periph: mux as periph C
> - * @mux_D_periph: mux as periph D
> - * @set_deglitch: enable/disable deglitch
> - * @set_debounce: enable/disable debounce
> - * @set_pulldown: enable/disable pulldown
> - * @disable_schmitt_trig: disable schmitt trigger
> - */
> -struct at91_pinctrl_mux_ops {
> -       enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
> -       void (*mux_A_periph)(void __iomem *pio, unsigned mask);
> -       void (*mux_B_periph)(void __iomem *pio, unsigned mask);
> -       void (*mux_C_periph)(void __iomem *pio, unsigned mask);
> -       void (*mux_D_periph)(void __iomem *pio, unsigned mask);
> -       bool (*get_deglitch)(void __iomem *pio, unsigned pin);
> -       void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
> -       bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
> -       void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
> -       bool (*get_pulldown)(void __iomem *pio, unsigned pin);
> -       void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
> -       bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
> -       void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
> -};
> -
> -#ifdef CONFIG_CMD_AT91MUX
> -static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
> -{
> -       return (__raw_readl(pio + PIO_PUSR) >> pin) & 0x1;
> -}
> -
> -static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
> -{
> -       return (__raw_readl(pio + PIO_MDSR) >> pin) & 0x1;
> -}
> -
> -static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
> -{
> -       unsigned select;
> -
> -       if (__raw_readl(pio + PIO_PSR) & mask)
> -               return AT91_MUX_GPIO;
> -
> -       select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask);
> -       select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1);
> -
> -       return select + 1;
> -}
> -
> -static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
> -{
> -       unsigned select;
> -
> -       if (__raw_readl(pio + PIO_PSR) & mask)
> -               return AT91_MUX_GPIO;
> -
> -       select = __raw_readl(pio + PIO_ABSR) & mask;
> -
> -       return select + 1;
> -}
> -
> -static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
> -{
> -       return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
> -}
> -
> -static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
> -{
> -       *div = __raw_readl(pio + PIO_SCDR);
> -
> -       return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
> -}
> -
> -static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
> -{
> -       return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
> -}
> -
> -static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
> -{
> -       return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
> -}
> -#else
> -#define at91_mux_get_periph            NULL
> -#define at91_mux_pio3_get_periph       NULL
> -#define at91_mux_get_deglitch          NULL
> -#define at91_mux_pio3_get_debounce     NULL
> -#define at91_mux_pio3_get_pulldown     NULL
> -#define at91_mux_pio3_get_schmitt_trig NULL
> -#endif
> -
> -static struct at91_pinctrl_mux_ops at91rm9200_ops = {
> -       .get_periph     = at91_mux_get_periph,
> -       .mux_A_periph   = at91_mux_set_A_periph,
> -       .mux_B_periph   = at91_mux_set_B_periph,
> -       .get_deglitch   = at91_mux_get_deglitch,
> -       .set_deglitch   = at91_mux_set_deglitch,
> -};
> -
> -static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
> -       .get_periph     = at91_mux_pio3_get_periph,
> -       .mux_A_periph   = at91_mux_pio3_set_A_periph,
> -       .mux_B_periph   = at91_mux_pio3_set_B_periph,
> -       .mux_C_periph   = at91_mux_pio3_set_C_periph,
> -       .mux_D_periph   = at91_mux_pio3_set_D_periph,
> -       .get_deglitch   = at91_mux_get_deglitch,
> -       .set_deglitch   = at91_mux_pio3_set_deglitch,
> -       .get_debounce   = at91_mux_pio3_get_debounce,
> -       .set_debounce   = at91_mux_pio3_set_debounce,
> -       .get_pulldown   = at91_mux_pio3_get_pulldown,
> -       .set_pulldown   = at91_mux_pio3_set_pulldown,
> -       .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
> -       .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
> -};
> -
> -int at91_mux_pin(unsigned pin, enum at91_mux mux, int use_pullup)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem *pio;
> -       struct device_d *dev;
> -       unsigned mask = pin_to_mask(pin);
> -       int bank = pin_to_bank(pin);
> -
> -       if (!at91_gpio)
> -               return -EINVAL;
> -
> -       pio = at91_gpio->regbase;
> -       if (!pio)
> -               return -EINVAL;
> -
> -       dev = at91_gpio->chip.dev;
> -       at91_mux_disable_interrupt(pio, mask);
> -
> -       pin %= MAX_NB_GPIO_PER_BANK;
> -       if (mux) {
> -               dev_dbg(dev, "pio%c%d configured as periph%c with pullup = %d\n",
> -                       bank + 'A', pin, mux - 1 + 'A', use_pullup);
> -       } else {
> -               dev_dbg(dev, "pio%c%d configured as gpio with pullup = %d\n",
> -                       bank + 'A', pin, use_pullup);
> -       }
> -
> -       switch(mux) {
> -       case AT91_MUX_GPIO:
> -               at91_mux_gpio_enable(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_A:
> -               at91_gpio->ops->mux_A_periph(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_B:
> -               at91_gpio->ops->mux_B_periph(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_C:
> -               if (!at91_gpio->ops->mux_C_periph)
> -                       return -EINVAL;
> -               at91_gpio->ops->mux_C_periph(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_D:
> -               if (!at91_gpio->ops->mux_D_periph)
> -                       return -EINVAL;
> -               at91_gpio->ops->mux_D_periph(pio, mask);
> -               break;
> -       }
> -       if (mux)
> -               at91_mux_gpio_disable(pio, mask);
> -
> -       if (use_pullup >= 0)
> -               at91_mux_set_pullup(pio, mask, use_pullup);
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_mux_pin);
> -
> -/*
> - * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
> - * configure it for an input.
> - */
> -int at91_set_gpio_input(unsigned pin, int use_pullup)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -       int ret;
> -
> -       ret = at91_mux_pin(pin, AT91_MUX_GPIO, use_pullup);
> -       if (ret)
> -               return ret;
> -
> -       dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as input\n",
> -               pin_to_bank(pin) + 'A', pin_to_bank_offset(pin));
> -
> -       at91_mux_gpio_input(pio, mask, true);
> -
> -       return 0;
> -}
> -
> -/*
> - * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
> - * and configure it for an output.
> - */
> -int at91_set_gpio_output(unsigned pin, int value)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -       int ret;
> -
> -       ret = at91_mux_pin(pin, AT91_MUX_GPIO, -1);
> -       if (ret)
> -               return ret;
> -
> -       dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as output val = %d\n",
> -               pin_to_bank(pin) + 'A', pin_to_bank_offset(pin), value);
> -
> -       at91_mux_gpio_input(pio, mask, false);
> -       at91_mux_gpio_set(pio, mask, value);
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_set_gpio_output);
> -
> -/*
> - * enable/disable the glitch filter; mostly used with IRQ handling.
> - */
> -int at91_set_deglitch(unsigned pin, int is_on)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -
> -       if (!pio)
> -               return -EINVAL;
> -
> -       at91_gpio->ops->set_deglitch(pio, mask, is_on);
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_set_deglitch);
> -
> -/*
> - * enable/disable the debounce filter;
> - */
> -int at91_set_debounce(unsigned pin, int is_on, int div)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -
> -       if (!pio || !at91_gpio->ops->set_debounce)
> -               return -EINVAL;
> -
> -       at91_gpio->ops->set_debounce(pio, mask, is_on, div);
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_set_debounce);
> -
> -/*
> - * enable/disable the multi-driver; This is only valid for output and
> - * allows the output pin to run as an open collector output.
> - */
> -int at91_set_multi_drive(unsigned pin, int is_on)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -
> -       if (!pio)
> -               return -EINVAL;
> -
> -       at91_mux_set_multidrive(pio, mask, is_on);
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_set_multi_drive);
> -
> -/*
> - * enable/disable the pull-down.
> - * If pull-up already enabled while calling the function, we disable it.
> - */
> -int at91_set_pulldown(unsigned pin, int is_on)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -
> -       if (!pio || !at91_gpio->ops->set_pulldown)
> -               return -EINVAL;
> -
> -       /* Disable pull-up anyway */
> -       at91_mux_set_pullup(pio, mask, 0);
> -       at91_gpio->ops->set_pulldown(pio, mask, is_on);
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_set_pulldown);
> -
> -/*
> - * disable Schmitt trigger
> - */
> -int at91_disable_schmitt_trig(unsigned pin)
> -{
> -       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> -       void __iomem    *pio = at91_gpio->regbase;
> -       unsigned        mask = pin_to_mask(pin);
> -
> -       if (!pio || !at91_gpio->ops->disable_schmitt_trig)
> -               return -EINVAL;
> -
> -       at91_gpio->ops->disable_schmitt_trig(pio, mask);
> -       return 0;
> -}
> -EXPORT_SYMBOL(at91_disable_schmitt_trig);
> -
> -#ifdef CONFIG_CMD_AT91MUX
> -static void at91mux_printf_mode(unsigned bank, unsigned pin)
> -{
> -       struct at91_gpio_chip *at91_gpio = &gpio_chip[bank];
> -       void __iomem *pio = at91_gpio->regbase;
> -       enum at91_mux mode;
> -       u32 pdsr;
> -
> -       unsigned mask = pin_to_mask(pin);
> -
> -       mode = at91_gpio->ops->get_periph(pio, mask);
> -
> -       if (mode == AT91_MUX_GPIO) {
> -               pdsr = __raw_readl(pio + PIO_PDSR);
> -
> -               printf("[gpio] %s", pdsr & mask ? "set" : "clear");
> -       } else {
> -               printf("[periph %c]", mode + 'A' - 1);
> -       }
> -}
> -
> -static void at91mux_dump_config(void)
> -{
> -       int bank, j;
> -
> -       /* print heading */
> -       printf("Pin\t");
> -       for (bank = 0; bank < gpio_banks; bank++) {
> -               printf("PIO%c\t\t", 'A' + bank);
> -       };
> -       printf("\n\n");
> -
> -       /* print pin status */
> -       for (j = 0; j < 32; j++) {
> -               printf("%i:\t", j);
> -
> -               for (bank = 0; bank < gpio_banks; bank++) {
> -                       at91mux_printf_mode(bank, j);
> -
> -                       printf("\t");
> -               }
> -
> -               printf("\n");
> -       }
> -}
> -
> -static void at91mux_print_en_disable(const char *str, bool is_on)
> -{
> -       printf("%s = ", str);
> -
> -       if (is_on)
> -               printf("enable\n");
> -       else
> -               printf("disable\n");
> -}
> -
> -static void at91mux_dump_pio_config(unsigned bank, unsigned pin)
> -{
> -       struct at91_gpio_chip *at91_gpio = &gpio_chip[bank];
> -       void __iomem *pio = at91_gpio->regbase;
> -       u32 div;
> -
> -       printf("pio%c%u configuration\n\n", bank + 'A', pin);
> -
> -       at91mux_printf_mode(bank, pin);
> -       printf("\n");
> -
> -       at91mux_print_en_disable("multidrive",
> -               at91_mux_get_multidrive(pio, pin));
> -
> -       at91mux_print_en_disable("pullup",
> -               at91_mux_get_pullup(pio, pin));
> -
> -       if (at91_gpio->ops->get_deglitch)
> -               at91mux_print_en_disable("degitch",
> -                       at91_gpio->ops->get_deglitch(pio, pin));
> -
> -       if (at91_gpio->ops->get_debounce) {
> -               printf("debounce = ");
> -               if (at91_gpio->ops->get_debounce(pio, pin, &div))
> -                       printf("enable at %d\n", div);
> -               else
> -                       printf("disable\n");
> -       }
> -
> -       if (at91_gpio->ops->get_pulldown)
> -               at91mux_print_en_disable("pulldown",
> -                       at91_gpio->ops->get_pulldown(pio, pin));
> -
> -       if (at91_gpio->ops->get_schmitt_trig)
> -               at91mux_print_en_disable("schmitt trigger",
> -                       !at91_gpio->ops->get_schmitt_trig(pio, pin));
> -}
> -
> -static int do_at91mux(int argc, char *argv[])
> -{
> -       int opt;
> -       unsigned bank = 0;
> -       unsigned pin = 0;
> -
> -       if (argc < 2) {
> -               at91mux_dump_config();
> -               return 0;
> -       }
> -
> -       while ((opt = getopt(argc, argv, "b:p:")) > 0) {
> -               switch (opt) {
> -               case 'b':
> -                       bank = simple_strtoul(optarg, NULL, 10);
> -                       break;
> -               case 'p':
> -                       pin = simple_strtoul(optarg, NULL, 10);
> -                       break;
> -               }
> -       }
> -
> -       if (bank >= gpio_banks) {
> -               printf("bank %c >= supported %c banks\n", bank + 'A',
> -                       gpio_banks + 'A');
> -               return 1;
> -       }
> -
> -       if (pin >= 32) {
> -               printf("pin %u >= supported %d pins\n", pin, 32);
> -               return 1;
> -       }
> -
> -       at91mux_dump_pio_config(bank, pin);
> -
> -       return 0;
> -}
> -
> -BAREBOX_CMD_HELP_START(at91mux)
> -BAREBOX_CMD_HELP_TEXT("Dump current MUX configuration. If a BANK or PIN has been")
> -BAREBOX_CMD_HELP_TEXT("specified dump pin details.")
> -BAREBOX_CMD_HELP_TEXT("")
> -BAREBOX_CMD_HELP_TEXT("Options:")
> -BAREBOX_CMD_HELP_OPT ("-p PIN", "pin number")
> -BAREBOX_CMD_HELP_OPT ("-b BANK", "bank number")
> -BAREBOX_CMD_HELP_END
> -
> -BAREBOX_CMD_START(at91mux)
> -       .cmd            = do_at91mux,
> -       BAREBOX_CMD_DESC("list MUX configuration")
> -       BAREBOX_CMD_OPTS("[-pb]")
> -       BAREBOX_CMD_GROUP(CMD_GRP_INFO)
> -       BAREBOX_CMD_HELP(cmd_at91mux_help)
> -       BAREBOX_CMD_COMPLETE(empty_complete)
> -BAREBOX_CMD_END
> -#endif
> -/*--------------------------------------------------------------------------*/
> -
> -static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
> -{
> -       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> -       void __iomem *pio = at91_gpio->regbase;
> -       unsigned mask = 1 << offset;
> -
> -       return at91_mux_gpio_get(pio, mask);
> -}
> -
> -static void at91_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
> -{
> -       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> -       void __iomem *pio = at91_gpio->regbase;
> -       unsigned mask = 1 << offset;
> -
> -       at91_mux_gpio_set(pio, mask, value);
> -}
> -
> -static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
> -               int value)
> -{
> -       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> -       void __iomem *pio = at91_gpio->regbase;
> -       unsigned mask = 1 << offset;
> -
> -       at91_mux_gpio_set(pio, mask, value);
> -       __raw_writel(mask, pio + PIO_OER);
> -
> -       return 0;
> -}
> -
> -static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
> -{
> -       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> -       void __iomem *pio = at91_gpio->regbase;
> -       unsigned mask = 1 << offset;
> -
> -       __raw_writel(mask, pio + PIO_ODR);
> -
> -       return 0;
> -}
> -
> -static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
> -{
> -       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> -       void __iomem *pio = at91_gpio->regbase;
> -       unsigned mask = 1 << offset;
> -
> -       dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
> -                'A' + pin_to_bank(chip->base), offset, chip->base + offset);
> -       at91_mux_gpio_enable(pio, mask);
> -
> -       return 0;
> -}
> -
> -static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
> -{
> -       dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
> -                'A' + pin_to_bank(chip->base), offset, chip->base + offset);
> -}
> -
> -static struct gpio_ops at91_gpio_ops = {
> -       .request = at91_gpio_request,
> -       .free = at91_gpio_free,
> -       .direction_input = at91_gpio_direction_input,
> -       .direction_output = at91_gpio_direction_output,
> -       .get = at91_gpio_get,
> -       .set = at91_gpio_set,
> -};
> -
> -static int at91_gpio_probe(struct device_d *dev)
> -{
> -       struct at91_gpio_chip *at91_gpio;
> -       struct clk *clk;
> -       int ret;
> -
> -       BUG_ON(dev->id > MAX_GPIO_BANKS);
> -
> -       at91_gpio = &gpio_chip[dev->id];
> -
> -       ret = dev_get_drvdata(dev, (unsigned long *)&at91_gpio->ops);
> -       if (ret) {
> -               dev_err(dev, "dev_get_drvdata failed: %d\n", ret);
> -               return ret;
> -       }
> -
> -       clk = clk_get(dev, NULL);
> -       if (IS_ERR(clk)) {
> -               ret = PTR_ERR(clk);
> -               dev_err(dev, "clock not found: %d\n", ret);
> -               return ret;
> -       }
> -
> -       ret = clk_enable(clk);
> -       if (ret < 0) {
> -               dev_err(dev, "clock failed to enable: %d\n", ret);
> -               clk_put(clk);
> -               return ret;
> -       }
> -
> -       gpio_banks = max(gpio_banks, dev->id + 1);
> -       at91_gpio->regbase = dev_request_mem_region(dev, 0);
> -
> -       at91_gpio->chip.ops = &at91_gpio_ops;
> -       at91_gpio->chip.ngpio = MAX_NB_GPIO_PER_BANK;
> -       at91_gpio->chip.dev = dev;
> -       at91_gpio->chip.base = dev->id * MAX_NB_GPIO_PER_BANK;
> -
> -       ret = gpiochip_add(&at91_gpio->chip);
> -       if (ret) {
> -               dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret);
> -               return ret;
> -       }
> -
> -       return 0;
> -}
> -
> -static struct platform_device_id at91_gpio_ids[] = {
> -       {
> -               .name = "at91rm9200-gpio",
> -               .driver_data = (unsigned long)&at91rm9200_ops,
> -       }, {
> -               .name = "at91sam9x5-gpio",
> -               .driver_data = (unsigned long)&at91sam9x5_ops,
> -       }, {
> -               /* sentinel */
> -       },
> -};
> -
> -static struct driver_d at91_gpio_driver = {
> -       .name = "at91-gpio",
> -       .probe = at91_gpio_probe,
> -       .id_table = at91_gpio_ids,
> -};
> -
> -static int at91_gpio_init(void)
> -{
> -       return platform_driver_register(&at91_gpio_driver);
> -}
> -postcore_initcall(at91_gpio_init);
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 57281a1..398b931 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -8,7 +8,7 @@ config PINCTRL
>           support but instead provide their own SoC specific APIs
>
>  config PINCTRL_AT91
> -       select PINCTRL
> +       select PINCTRL if OFDEVICE
>         bool
>         help
>             The pinmux controller found on AT91 SoCs.
> diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
> index 433862a..597deea 100644
> --- a/drivers/pinctrl/pinctrl-at91.c
> +++ b/drivers/pinctrl/pinctrl-at91.c
> @@ -71,7 +71,7 @@ static int gpio_banks;
>
>  static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
>
> -static inline void __iomem *pin_to_controller(struct at91_pinctrl *info, unsigned pin)
> +static inline void __iomem *pin_to_controller(unsigned pin)
>  {
>         pin /= MAX_NB_GPIO_PER_BANK;
>         if (likely(pin < gpio_banks))
> @@ -112,6 +112,200 @@ struct at91_pinctrl_mux_ops {
>         void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
>  };
>
> +int at91_mux_pin(unsigned pin, enum at91_mux mux, int use_pullup)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem *pio;
> +       struct device_d *dev;
> +       unsigned mask = pin_to_mask(pin);
> +       int bank = pin_to_bank(pin);
> +
> +       if (!at91_gpio)
> +               return -EINVAL;
> +
> +       pio = at91_gpio->regbase;
> +       if (!pio)
> +               return -EINVAL;
> +
> +       dev = at91_gpio->chip.dev;
> +       at91_mux_disable_interrupt(pio, mask);
> +
> +       pin %= MAX_NB_GPIO_PER_BANK;
> +       if (mux) {
> +               dev_dbg(dev, "pio%c%d configured as periph%c with pullup = %d\n",
> +                       bank + 'A', pin, mux - 1 + 'A', use_pullup);
> +       } else {
> +               dev_dbg(dev, "pio%c%d configured as gpio with pullup = %d\n",
> +                       bank + 'A', pin, use_pullup);
> +       }
> +
> +       switch(mux) {
> +       case AT91_MUX_GPIO:
> +               at91_mux_gpio_enable(pio, mask);
> +               break;
> +       case AT91_MUX_PERIPH_A:
> +               at91_gpio->ops->mux_A_periph(pio, mask);
> +               break;
> +       case AT91_MUX_PERIPH_B:
> +               at91_gpio->ops->mux_B_periph(pio, mask);
> +               break;
> +       case AT91_MUX_PERIPH_C:
> +               if (!at91_gpio->ops->mux_C_periph)
> +                       return -EINVAL;
> +               at91_gpio->ops->mux_C_periph(pio, mask);
> +               break;
> +       case AT91_MUX_PERIPH_D:
> +               if (!at91_gpio->ops->mux_D_periph)
> +                       return -EINVAL;
> +               at91_gpio->ops->mux_D_periph(pio, mask);
> +               break;
> +       }
> +       if (mux)
> +               at91_mux_gpio_disable(pio, mask);
> +
> +       if (use_pullup >= 0)
> +               at91_mux_set_pullup(pio, mask, use_pullup);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_mux_pin);
> +
> +/*
> + * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
> + * configure it for an input.
> + */
> +int at91_set_gpio_input(unsigned pin, int use_pullup)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +       int ret;
> +
> +       ret = at91_mux_pin(pin, AT91_MUX_GPIO, use_pullup);
> +       if (ret)
> +               return ret;
> +
> +       dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as input\n",
> +               pin_to_bank(pin) + 'A', pin_to_bank_offset(pin));
> +
> +       at91_mux_gpio_input(pio, mask, true);
> +
> +       return 0;
> +}
> +
> +/*
> + * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
> + * and configure it for an output.
> + */
> +int at91_set_gpio_output(unsigned pin, int value)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +       int ret;
> +
> +       ret = at91_mux_pin(pin, AT91_MUX_GPIO, -1);
> +       if (ret)
> +               return ret;
> +
> +       dev_dbg(at91_gpio->chip.dev, "pio%c%d configured as output val = %d\n",
> +               pin_to_bank(pin) + 'A', pin_to_bank_offset(pin), value);
> +
> +       at91_mux_gpio_input(pio, mask, false);
> +       at91_mux_gpio_set(pio, mask, value);
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_set_gpio_output);
> +
> +/*
> + * enable/disable the glitch filter; mostly used with IRQ handling.
> + */
> +int at91_set_deglitch(unsigned pin, int is_on)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +
> +       if (!pio)
> +               return -EINVAL;
> +
> +       at91_gpio->ops->set_deglitch(pio, mask, is_on);
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_set_deglitch);
> +
> +/*
> + * enable/disable the debounce filter;
> + */
> +int at91_set_debounce(unsigned pin, int is_on, int div)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +
> +       if (!pio || !at91_gpio->ops->set_debounce)
> +               return -EINVAL;
> +
> +       at91_gpio->ops->set_debounce(pio, mask, is_on, div);
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_set_debounce);
> +
> +/*
> + * enable/disable the multi-driver; This is only valid for output and
> + * allows the output pin to run as an open collector output.
> + */
> +int at91_set_multi_drive(unsigned pin, int is_on)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +
> +       if (!pio)
> +               return -EINVAL;
> +
> +       at91_mux_set_multidrive(pio, mask, is_on);
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_set_multi_drive);
> +
> +/*
> + * enable/disable the pull-down.
> + * If pull-up already enabled while calling the function, we disable it.
> + */
> +int at91_set_pulldown(unsigned pin, int is_on)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +
> +       if (!pio || !at91_gpio->ops->set_pulldown)
> +               return -EINVAL;
> +
> +       /* Disable pull-up anyway */
> +       at91_mux_set_pullup(pio, mask, 0);
> +       at91_gpio->ops->set_pulldown(pio, mask, is_on);
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_set_pulldown);
> +
> +/*
> + * disable Schmitt trigger
> + */
> +int at91_disable_schmitt_trig(unsigned pin)
> +{
> +       struct at91_gpio_chip *at91_gpio = pin_to_controller(pin);
> +       void __iomem    *pio = at91_gpio->regbase;
> +       unsigned        mask = pin_to_mask(pin);
> +
> +       if (!pio || !at91_gpio->ops->disable_schmitt_trig)
> +               return -EINVAL;
> +
> +       at91_gpio->ops->disable_schmitt_trig(pio, mask);
> +       return 0;
> +}
> +EXPORT_SYMBOL(at91_disable_schmitt_trig);
> +
>  static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
>  {
>         unsigned select;
> @@ -183,49 +377,6 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
>         .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
>  };
>
> -static int at91_mux_pin(struct at91_pinctrl *info, unsigned pin, enum at91_mux mux, int use_pullup)
> -{
> -       void __iomem    *pio = pin_to_controller(info, pin);
> -       unsigned mask = pin_to_mask(pin);
> -
> -       if (!info)
> -               return -EINVAL;
> -
> -       if (!pio)
> -               return -EINVAL;
> -
> -       at91_mux_disable_interrupt(pio, mask);
> -
> -       switch (mux) {
> -       case AT91_MUX_GPIO:
> -               at91_mux_gpio_enable(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_A:
> -               info->ops->mux_A_periph(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_B:
> -               info->ops->mux_B_periph(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_C:
> -               if (!info->ops->mux_C_periph)
> -                       return -EINVAL;
> -               info->ops->mux_C_periph(pio, mask);
> -               break;
> -       case AT91_MUX_PERIPH_D:
> -               if (!info->ops->mux_D_periph)
> -                       return -EINVAL;
> -               info->ops->mux_D_periph(pio, mask);
> -               break;
> -       }
> -       if (mux)
> -               at91_mux_gpio_disable(pio, mask);
> -
> -       if (use_pullup >= 0)
> -               at91_mux_set_pullup(pio, mask, use_pullup);
> -
> -       return 0;
> -}
> -
>  static struct of_device_id at91_pinctrl_dt_ids[] = {
>         {
>                 .compatible = "atmel,at91rm9200-pinctrl",
> @@ -264,7 +415,7 @@ static int at91_pinctrl_set_conf(struct at91_pinctrl *info, unsigned int pin_num
>         unsigned int mask;
>         void __iomem *pio;
>
> -       pio = pin_to_controller(info, pin_num);
> +       pio = pin_to_controller(pin_num);
>         mask = pin_to_mask(pin_num);
>
>         if (conf & PULL_UP && conf & PULL_DOWN)
> @@ -309,7 +460,7 @@ static int at91_pinctrl_set_state(struct pinctrl_device *pdev, struct device_nod
>                 mux = be32_to_cpu(*list++);
>                 conf = be32_to_cpu(*list++);
>
> -               ret = at91_mux_pin(info, pin_num, mux, conf & PULL_UP);
> +               ret = at91_mux_pin(pin_num, mux, conf & PULL_UP);
>                 if (ret) {
>                         dev_err(pdev->dev, "failed to mux pin %d\n", pin_num);
>                         return ret;
> @@ -334,6 +485,9 @@ static int at91_pinctrl_probe(struct device_d *dev)
>         struct at91_pinctrl *info;
>         int ret;
>
> +       if (!IS_ENABLED(CONFIG_PINCTRL))
> +               return 0;
> +
>         info = xzalloc(sizeof(struct at91_pinctrl));
>
>         info->ops = at91_pinctrl_get_driver_data(dev);
> --
> 2.1.0
>
>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-03 15:10         ` Raphaël Poggi
@ 2014-09-04  9:26           ` Sascha Hauer
  2014-09-04  9:41             ` Raphaël Poggi
  0 siblings, 1 reply; 12+ messages in thread
From: Sascha Hauer @ 2014-09-04  9:26 UTC (permalink / raw)
  To: Raphaël Poggi; +Cc: barebox

On Wed, Sep 03, 2014 at 05:10:33PM +0200, Raphaël Poggi wrote:
> This patch is perfect :-). You just miss to check the return value in
> at91_gpio_probe.
> 
> Do I have to integrate this patch in mine ? or you will apply it yourself ?

I just added the return value check, squashed the patch into your
pinctrl driver patch and applied to -next.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v3 2/3] pinctrl: at91: add pinctrl driver
  2014-09-04  9:26           ` Sascha Hauer
@ 2014-09-04  9:41             ` Raphaël Poggi
  0 siblings, 0 replies; 12+ messages in thread
From: Raphaël Poggi @ 2014-09-04  9:41 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Perfect thank you, so I just have to send one patch for the gpio clock
registration.

2014-09-04 11:26 GMT+02:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Wed, Sep 03, 2014 at 05:10:33PM +0200, Raphaël Poggi wrote:
>> This patch is perfect :-). You just miss to check the return value in
>> at91_gpio_probe.
>>
>> Do I have to integrate this patch in mine ? or you will apply it yourself ?
>
> I just added the return value check, squashed the patch into your
> pinctrl driver patch and applied to -next.
>
> Sascha
>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2014-09-04  9:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-02 11:07 [PATCH v3 0/3] Add atmel pinctrl driver Raphaël Poggi
2014-09-02 11:07 ` [PATCH v3 1/3] arm: mach-at91: move gpio.h to include folder Raphaël Poggi
2014-09-03  7:00   ` Sascha Hauer
2014-09-02 11:07 ` [PATCH v3 2/3] pinctrl: at91: add pinctrl driver Raphaël Poggi
2014-09-03  6:56   ` Sascha Hauer
2014-09-03 11:23     ` Raphaël Poggi
2014-09-03 13:52       ` Sascha Hauer
2014-09-03 15:10         ` Raphaël Poggi
2014-09-04  9:26           ` Sascha Hauer
2014-09-04  9:41             ` Raphaël Poggi
2014-09-02 11:08 ` [PATCH v3 3/3] at91sam9g45: add device tree gpio clocks Raphaël Poggi
2014-09-03  6:46   ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox