Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 1/2] ARM: sunxi: gpio: Add Allwinner SoCs GPIO drivers

150 views
Skip to first unread message

Maxime Ripard

unread,
Jan 4, 2013, 11:50:01 AM1/4/13
to
The IP responsible for the muxing on the Allwinner SoCs are also
handling the GPIOs on the system. This patch adds the needed driver that
relies on the pinctrl driver for most of its operations.

The number of pins available for GPIOs operations are already declared
in the pinctrl driver, we only need to probe a generic driver to handle
the banks available for each SoC.

This driver has been tested on a A13-Olinuxino.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
.../devicetree/bindings/gpio/gpio-sunxi.txt | 77 ++++++++++
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-sunxi.c | 150 ++++++++++++++++++++
drivers/pinctrl/pinctrl-sunxi.c | 106 ++++++++++++++
drivers/pinctrl/pinctrl-sunxi.h | 6 +-
6 files changed, 345 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-sunxi.txt
create mode 100644 drivers/gpio/gpio-sunxi.c

diff --git a/Documentation/devicetree/bindings/gpio/gpio-sunxi.txt b/Documentation/devicetree/bindings/gpio/gpio-sunxi.txt
new file mode 100644
index 0000000..cecdca0
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-sunxi.txt
@@ -0,0 +1,77 @@
+* Allwinner sunXi GPIO controller
+
+The Allwinner GPIO controller is part of the same IP than the PIN
+controller. The GPIOs are organized in port/bank. Each port consists
+of 32 GPIOs.
+
+As there is some interaction between the pinctrl driver and the gpio
+driver, you will need both enabled in your system for this driver to
+work.
+
+Required properties for GPIO node:
+- compatible : Should be "allwinner,sunxi-gpio".
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells : Should be one. The cell is the pin number.
+
+Note: Each GPIO port should have an alias correctly numbered in "aliases"
+node.
+
+Examples:
+aliases {
+ gpio1 = &pb;
+ gpio2 = &pc;
+ gpio3 = &pd;
+ gpio4 = &pe;
+ gpio5 = &pf;
+ gpio6 = &pg;
+};
+
+
+pinctrl@01c20800 {
+ compatible = "allwinner,sun5i-a13-pinctrl";
+ reg = <0x01c20800 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
+
+pb: gpio@01c20824 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c20824 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+};
+
+pc: gpio@01c20848 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c20848 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+};
+
+pd: gpio@01c2086c {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c2086c 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+};
+
+pe: gpio@01c20890 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c20890 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+};
+
+pf: gpio@01c208b4 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c208b4 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+};
+
+pg: gpio@01c208d8 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c208d8 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 682de75..6f4199f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -224,6 +224,12 @@ config GPIO_TS5500
blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
LCD port.

+config GPIO_SUNXI
+ def_bool y
+ depends on ARCH_SUNXI
+ select GPIO_GENERIC
+ select GENERIC_IRQ_CHIP
+
config GPIO_VT8500
bool "VIA/Wondermedia SoC GPIO Support"
depends on ARCH_VT8500
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c5aebd0..c5a9306 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
+obj-$(CONFIG_GPIO_SUNXI) += gpio-sunxi.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
diff --git a/drivers/gpio/gpio-sunxi.c b/drivers/gpio/gpio-sunxi.c
new file mode 100644
index 0000000..017ace4
--- /dev/null
+++ b/drivers/gpio/gpio-sunxi.c
@@ -0,0 +1,150 @@
+/*
+ * Allwinner A1X SoCs GPIO driver.
+ *
+ * Copyright (C) 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime...@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
+#include "../pinctrl/pinctrl-sunxi.h"
+
+struct sunxi_gpio_chip {
+ u32 bank;
+ struct gpio_chip *chip;
+ void __iomem *membase;
+};
+
+static int sunxi_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void sunxi_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int sunxi_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int sunxi_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct sunxi_gpio_chip *sunxi_chip = dev_get_drvdata(chip->dev);
+
+ u32 reg = offset / DATA_PINS_PER_REG * 0x04 + DATA_REGS_OFFSET;
+ u8 index = (offset % DATA_PINS_PER_REG) * DATA_PINS_BITS;
+ u32 val = (readl(sunxi_chip->membase + reg) >> index) & 0x1;
+
+ return val;
+}
+
+static int sunxi_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static void sunxi_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct sunxi_gpio_chip *sunxi_chip = dev_get_drvdata(chip->dev);
+ int reg = offset / DATA_PINS_PER_REG * 0x04 + DATA_REGS_OFFSET;
+ int index = (offset % DATA_PINS_PER_REG) * DATA_PINS_BITS;
+
+ writel((value & 0x1) << index, sunxi_chip->membase + reg);
+}
+
+static struct gpio_chip sunxi_pio_gpio_chip __devinitconst = {
+ .owner = THIS_MODULE,
+ .request = sunxi_gpio_request,
+ .free = sunxi_gpio_free,
+ .direction_input = sunxi_gpio_direction_input,
+ .direction_output = sunxi_gpio_direction_output,
+ .get = sunxi_gpio_get,
+ .set = sunxi_gpio_set,
+ .base = -1,
+ .can_sleep = 0,
+};
+
+
+static int __devinit sunxi_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct sunxi_gpio_chip *sunxi_chip;
+ int ret;
+
+ if (!node) {
+ dev_err(&pdev->dev, "No device tree node found\n");
+ return -ENODEV;
+ }
+
+ sunxi_chip = devm_kzalloc(&pdev->dev, sizeof(*sunxi_chip), GFP_KERNEL);
+ if (!sunxi_chip)
+ return -ENOMEM;
+
+ sunxi_chip->bank = of_alias_get_id(node, "gpio");
+ if (sunxi_chip->bank < 0) {
+ dev_err(&pdev->dev, "failed to get alias id\n");
+ return -EINVAL;
+ }
+
+ sunxi_chip->membase = of_iomap(node, 0);
+ if (!sunxi_chip->membase)
+ return -ENOMEM;
+
+ sunxi_chip->chip = &sunxi_pio_gpio_chip;
+ sunxi_chip->chip->base = sunxi_chip->bank * PINS_PER_BANK;
+ sunxi_chip->chip->ngpio = PINS_PER_BANK;
+ sunxi_chip->chip->label = dev_name(&pdev->dev);
+ sunxi_chip->chip->dev = &pdev->dev;
+ sunxi_chip->chip->owner = THIS_MODULE;
+
+ ret = gpiochip_add(sunxi_chip->chip);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, sunxi_chip);
+
+ dev_info(&pdev->dev, "initialized sunXi gpio bank\n");
+
+ return 0;
+}
+
+static const struct of_device_id sunxi_gpio_match[] = {
+ { .compatible = "allwinner,sunxi-gpio", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sunxi_gpio_match);
+
+static struct platform_driver sunxi_gpio_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sunxi-gpio",
+ .of_match_table = sunxi_gpio_match,
+ },
+ .probe = sunxi_gpio_probe,
+};
+
+static int __init sunxi_gpio_init(void)
+{
+ return platform_driver_register(&sunxi_gpio_driver);
+}
+postcore_initcall(sunxi_gpio_init);
+
+MODULE_AUTHOR("Maxime Ripard <maxime...@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner sunXi GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index e122f75..3db404b 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -599,11 +599,57 @@ static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
return 0;
}

+static int
+sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset,
+ bool input)
+{
+ struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct sunxi_desc_function *desc;
+ char *func, *pin_name;
+ u8 bank, pin;
+ int ret;
+
+ bank = (offset) / PINS_PER_BANK;
+ pin = (offset) % PINS_PER_BANK;
+
+ pin_name = kzalloc(5, GFP_KERNEL);
+ if (!pin_name)
+ return -ENOMEM;
+
+ ret = sprintf(pin_name, "P%c%d", 'A' + bank, pin);
+ if (!ret)
+ goto error;
+
+ if (input)
+ func = "gpio_in";
+ else
+ func = "gpio_out";
+
+ desc = sunxi_pinctrl_desc_find_function_by_name(pctl,
+ pin_name,
+ func);
+ if (!desc) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ sunxi_pmx_set(pctldev, offset, desc->muxval);
+
+ ret = 0;
+
+error:
+ kfree(pin_name);
+ return ret;
+}
+
static struct pinmux_ops sunxi_pmx_ops = {
.get_functions_count = sunxi_pmx_get_funcs_cnt,
.get_function_name = sunxi_pmx_get_func_name,
.get_function_groups = sunxi_pmx_get_func_groups,
.enable = sunxi_pmx_enable,
+ .gpio_set_direction = sunxi_pmx_gpio_set_direction,
};

static struct pinctrl_desc sunxi_pctrl_desc = {
@@ -721,6 +767,60 @@ static int __devinit sunxi_pinctrl_build_state(struct platform_device *pdev)
return 0;
}

+static int __devinit
+sunxi_pinctrl_register_gpio_ranges(struct sunxi_pinctrl *pctl)
+{
+ int id = 0, base = 0, npins = 1, i, prev_pin = -1;
+ struct pinctrl_gpio_range *range;
+
+ for (i = 0; i < pctl->desc->npins; i++) {
+ const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
+ unsigned pin_num = pin->pin.number;
+
+ if (prev_pin < 0) {
+ prev_pin = pin_num;
+ base = pin_num;
+ } else if (prev_pin + 1 != pin_num) {
+ range = devm_kzalloc(pctl->dev,
+ sizeof(*range),
+ GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+
+ range->name = "sunxi";
+ range->id = id;
+ range->base = base;
+ range->pin_base = base;
+ range->npins = npins;
+
+ pinctrl_add_gpio_range(pctl->pctl_dev, range);
+
+ id++;
+ npins = 1;
+ prev_pin = pin_num;
+ base = prev_pin;
+ } else {
+ prev_pin++;
+ npins++;
+ }
+ }
+
+ range = devm_kzalloc(pctl->dev, sizeof(*range),
+ GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+
+ range->name = "sunxi";
+ range->id = id;
+ range->base = base;
+ range->pin_base = base;
+ range->npins = npins;
+
+ pinctrl_add_gpio_range(pctl->pctl_dev, range);
+
+ return 0;
+}
+
static int __devinit sunxi_pinctrl_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -771,6 +871,12 @@ static int __devinit sunxi_pinctrl_probe(struct platform_device *pdev)
return -EINVAL;
}

+ ret = sunxi_pinctrl_register_gpio_ranges(pctl);
+ if (ret) {
+ dev_err(&pdev->dev, "couldn't register gpio ranges\n");
+ return -EINVAL;
+ }
+
dev_info(&pdev->dev, "initialized sunXi pin control driver\n");

return 0;
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index 34f2496..665fedc 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -256,12 +256,15 @@

#define BANK_MEM_SIZE 0x24
#define MUX_REGS_OFFSET 0x0
+#define DATA_REGS_OFFSET 0x10
#define DLEVEL_REGS_OFFSET 0x14
#define PULL_REGS_OFFSET 0x1c

#define PINS_PER_BANK 32
#define MUX_PINS_PER_REG 8
#define MUX_PINS_BITS 4
+#define DATA_PINS_PER_REG 32
+#define DATA_PINS_BITS 1
#define DLEVEL_PINS_PER_REG 16
#define DLEVEL_PINS_BITS 2
#define PULL_PINS_PER_REG 16
@@ -280,6 +283,8 @@ struct sunxi_desc_pin {
struct sunxi_pinctrl_desc {
const struct sunxi_desc_pin *pins;
int npins;
+ struct pinctrl_gpio_range *ranges;
+ int nranges;
};

struct sunxi_pinctrl_function {
@@ -318,7 +323,6 @@ struct sunxi_pinctrl {
.muxval = _val, \
}

-
/*
* The sunXi PIO registers are organized as is:
* 0x00 - 0x0c Muxing values.
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Maxime Ripard

unread,
Jan 4, 2013, 11:50:01 AM1/4/13
to
Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
arch/arm/boot/dts/sun5i-a13.dtsi | 51 ++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index e112189..dc650a6 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -14,6 +14,15 @@
/include/ "sunxi.dtsi"

/ {
+ aliases {
+ gpio1 = &pb;
+ gpio2 = &pc;
+ gpio3 = &pd;
+ gpio4 = &pe;
+ gpio5 = &pf;
+ gpio6 = &pg;
+ };
+
memory {
reg = <0x40000000 0x20000000>;
};
@@ -39,5 +48,47 @@
allwinner,pull = <0>;
};
};
+
+ pb: gpio@01c20824 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c20824 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ };
+
+ pc: gpio@01c20848 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c20848 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ };
+
+ pd: gpio@01c2086c {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c2086c 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ };
+
+ pe: gpio@01c20890 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c20890 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ };
+
+ pf: gpio@01c208b4 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c208b4 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ };
+
+ pg: gpio@01c208d8 {
+ compatible = "allwinner,sunxi-gpio";
+ reg = <0x01c208d8 0x24>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ };
};
};

Maxime Ripard

unread,
Jan 4, 2013, 11:50:02 AM1/4/13
to
Hi,

This patch adds support for the GPIOs for the Allwinner SoCs supported so
far.

It comes on top of my previous pinctrl patchset, and has been tested on a
A13-Olinuxino from Olimex.

Thanks,
Maxime

Maxime Ripard (2):
ARM: sunxi: gpio: Add Allwinner SoCs GPIO drivers
ARM: sunxi: Add the GPIOs node to the device tree

.../devicetree/bindings/gpio/gpio-sunxi.txt | 77 ++++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 51 +++++++
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-sunxi.c | 150 ++++++++++++++++++++
drivers/pinctrl/pinctrl-sunxi.c | 106 ++++++++++++++
drivers/pinctrl/pinctrl-sunxi.h | 6 +-
7 files changed, 396 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-sunxi.txt
create mode 100644 drivers/gpio/gpio-sunxi.c

Olof Johansson

unread,
Jan 5, 2013, 10:40:02 AM1/5/13
to
Hi,

On Fri, Jan 4, 2013 at 8:45 AM, Maxime Ripard
<maxime...@free-electrons.com> wrote:
> Hi,
>
> This patch adds support for the GPIOs for the Allwinner SoCs supported so
> far.
>
> It comes on top of my previous pinctrl patchset, and has been tested on a
> A13-Olinuxino from Olimex.
>
> Thanks,
> Maxime
>
> Maxime Ripard (2):
> ARM: sunxi: gpio: Add Allwinner SoCs GPIO drivers
> ARM: sunxi: Add the GPIOs node to the device tree
>
> .../devicetree/bindings/gpio/gpio-sunxi.txt | 77 ++++++++++
> arch/arm/boot/dts/sun5i-a13.dtsi | 51 +++++++
> drivers/gpio/Kconfig | 6 +
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-sunxi.c | 150 ++++++++++++++++++++
> drivers/pinctrl/pinctrl-sunxi.c | 106 ++++++++++++++
> drivers/pinctrl/pinctrl-sunxi.h | 6 +-

I haven't looked closely at the patch yet, but this is a case where it
makes sense to merge the gpio/pinctrl patch through Linus/Grant's
tree, and merge the dtsi update through arm-soc -- while you need
both, nothing is broken by having just one or the other, so taking the
separate merge paths are fine.

Linus, Grant, sound ok to you?

-Olof

Linus Walleij

unread,
Jan 10, 2013, 6:10:02 AM1/10/13
to
On Fri, Jan 4, 2013 at 5:45 PM, Maxime Ripard
<maxime...@free-electrons.com> wrote:

> The IP responsible for the muxing on the Allwinner SoCs are also
> handling the GPIOs on the system. This patch adds the needed driver that
> relies on the pinctrl driver for most of its operations.
>
> The number of pins available for GPIOs operations are already declared
> in the pinctrl driver, we only need to probe a generic driver to handle
> the banks available for each SoC.
>
> This driver has been tested on a A13-Olinuxino.
>
> Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>

Looking mostly good!
Really hairy way to add ranges right?

Registering ranges from the pinctrl side is deprecated and discouraged.

Instead register the ranges from the GPIO driver.

Use gpiochip_add_pin_range() from the GPIO driver.

An example is provided in
drivers/pinctrl/pinctrl-coh901.c

After you have done this, you can probably get rid of this as well:

+static int __init sunxi_gpio_init(void)
+{
+ return platform_driver_register(&sunxi_gpio_driver);
+}
+postcore_initcall(sunxi_gpio_init);

This will become a simple module_init() if you are handling
deferred probe correctly.

Yours,
Linus Walleij

Linus Walleij

unread,
Jan 10, 2013, 6:20:01 AM1/10/13
to
On Sat, Jan 5, 2013 at 4:35 PM, Olof Johansson <ol...@lixom.net> wrote:

> I haven't looked closely at the patch yet, but this is a case where it
> makes sense to merge the gpio/pinctrl patch through Linus/Grant's
> tree, and merge the dtsi update through arm-soc -- while you need
> both, nothing is broken by having just one or the other, so taking the
> separate merge paths are fine.
>
> Linus, Grant, sound ok to you?

Sure. But I have requested a few changes to the patch set...

Linus Walleij

Maxime Ripard

unread,
Jan 12, 2013, 4:00:02 AM1/12/13
to
On 10/01/2013 12:13, Linus Walleij wrote:
> On Sat, Jan 5, 2013 at 4:35 PM, Olof Johansson <ol...@lixom.net> wrote:
>
>> I haven't looked closely at the patch yet, but this is a case where it
>> makes sense to merge the gpio/pinctrl patch through Linus/Grant's
>> tree, and merge the dtsi update through arm-soc -- while you need
>> both, nothing is broken by having just one or the other, so taking the
>> separate merge paths are fine.
>>
>> Linus, Grant, sound ok to you?
>
> Sure. But I have requested a few changes to the patch set...

And we need to merge the pinctrl patches first also.

Maxime

--
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

Maxime Ripard

unread,
Jan 12, 2013, 4:10:01 AM1/12/13
to
Hi Linus,
Yes... I didn't find any best way to do so. It was either that or
duplicate the already existing informations we had about the pins ranges
into a ranges array, which is pretty error-prone.

I guess I could add some comments though.

> Registering ranges from the pinctrl side is deprecated and discouraged.
>
> Instead register the ranges from the GPIO driver.
>
> Use gpiochip_add_pin_range() from the GPIO driver.
>
> An example is provided in
> drivers/pinctrl/pinctrl-coh901.c

Ok, will do. But we need to find a way to share the pins arrays between
the pinctrl and gpio drivers then.

Maybe add a pinctrl-sunxi-pins.h file? or merge the pinctrl and gpio
drivers?

I'm kind of reluctant to merging the drivers into one single messy file,
but if that's the way to go, fine.

>
> After you have done this, you can probably get rid of this as well:
>
> +static int __init sunxi_gpio_init(void)
> +{
> + return platform_driver_register(&sunxi_gpio_driver);
> +}
> +postcore_initcall(sunxi_gpio_init);
>
> This will become a simple module_init() if you are handling
> deferred probe correctly.

Ok. Thanks for your review!
Maxime

--
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

Linus Walleij

unread,
Jan 17, 2013, 6:10:01 AM1/17/13
to
On Sat, Jan 12, 2013 at 10:06 AM, Maxime Ripard
<maxime...@free-electrons.com> wrote:

>> Use gpiochip_add_pin_range() from the GPIO driver.
>>
>> An example is provided in
>> drivers/pinctrl/pinctrl-coh901.c
>
> Ok, will do. But we need to find a way to share the pins arrays between
> the pinctrl and gpio drivers then.
>
> Maybe add a pinctrl-sunxi-pins.h file? or merge the pinctrl and gpio
> drivers?
>
> I'm kind of reluctant to merging the drivers into one single messy file,
> but if that's the way to go, fine.

Well, does it have to be that messy?

You can merge it different ways.

For example there is *no* need to have two different device driver
structs and two probe functions, right?

Just one device named pinctrl that has one state container and
one single dd and probe function. That makes everything sooo
much easier I think.

Just register both a pinctrl and GPIO interface (in that order).

See the recent pinctrl-abx500.c submission for an example on
how to do this.

Yours,
Linus Walleij

Maxime Ripard

unread,
Jan 23, 2013, 4:40:03 AM1/23/13
to
The IP responsible for the muxing on the Allwinner SoCs are also
handling the GPIOs on the system. This patch adds the needed driver that
relies on the pinctrl driver for most of its operations.

The number of pins available for GPIOs operations are already declared
in the pinctrl driver, we only need to probe a generic driver to handle
the banks available for each SoC.

This driver has been tested on a A13-Olinuxino.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
drivers/pinctrl/pinctrl-sunxi.c | 138 ++++++++++++++++++++++++++++++++++++++-
drivers/pinctrl/pinctrl-sunxi.h | 23 ++++++-
2 files changed, 158 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 6f02e34..bfca9e1 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -11,6 +11,7 @@
*/

#include <linux/io.h>
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -609,11 +610,57 @@ static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
return 0;
}

+static int
+sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset,
+ bool input)
+{
+ struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct sunxi_desc_function *desc;
+ char *func, *pin_name;
+ u8 bank, pin;
+ int ret;
+
+ bank = (offset) / PINS_PER_BANK;
+ pin = (offset) % PINS_PER_BANK;
+
+ pin_name = kzalloc(5, GFP_KERNEL);
+ if (!pin_name)
+ return -ENOMEM;
+
@@ -622,6 +669,60 @@ static struct pinctrl_desc sunxi_pctrl_desc = {
.pmxops = &sunxi_pmx_ops,
};

+static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
+ unsigned offset)
+{
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
+
+ u32 reg = sunxi_data_reg(offset);
+ u8 index = sunxi_data_offset(offset);
+ u32 val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
+
+ return val;
+}
+
+static int sunxi_pinctrl_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
+ u32 reg = sunxi_data_reg(offset);
+ u8 index = sunxi_data_offset(offset);
+
+ writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
+}
+
+static struct gpio_chip sunxi_pinctrl_gpio_chip __devinitconst = {
+ .owner = THIS_MODULE,
+ .request = sunxi_pinctrl_gpio_request,
+ .free = sunxi_pinctrl_gpio_free,
+ .direction_input = sunxi_pinctrl_gpio_direction_input,
+ .direction_output = sunxi_pinctrl_gpio_direction_output,
+ .get = sunxi_pinctrl_gpio_get,
+ .set = sunxi_pinctrl_gpio_set,
+ .can_sleep = 0,
+};
+
static struct of_device_id sunxi_pinctrl_match[] = {
{ .compatible = "allwinner,sun5i-a13-pinctrl", .data = (void *)&sun5i_a13_pinctrl_data },
{}
@@ -737,7 +838,7 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
const struct of_device_id *device;
struct pinctrl_pin_desc *pins;
struct sunxi_pinctrl *pctl;
- int i, ret;
+ int i, ret, last_pin;

pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -781,9 +882,42 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
return -EINVAL;
}

- dev_info(&pdev->dev, "initialized sunXi pin control driver\n");
+ pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
+ if (!pctl->chip) {
+ ret = -ENOMEM;
+ goto pinctrl_error;
+ }
+
+ last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
+ pctl->chip = &sunxi_pinctrl_gpio_chip;
+ pctl->chip->ngpio = round_up(last_pin, PINS_PER_BANK);
+ pctl->chip->label = dev_name(&pdev->dev);
+ pctl->chip->dev = &pdev->dev;
+ pctl->chip->base = 0;
+
+ ret = gpiochip_add(pctl->chip);
+ if (ret)
+ goto pinctrl_error;
+
+ for (i = 0; i < pctl->desc->npins; i++) {
+ const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
+
+ ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
+ pin->pin.number,
+ pin->pin.number, 1);
+ if (ret)
+ goto gpiochip_error;
+ }
+
+ dev_info(&pdev->dev, "initialized sunXi PIO driver\n");

return 0;
+
+gpiochip_error:
+ ret = gpiochip_remove(pctl->chip);
+pinctrl_error:
+ pinctrl_unregister(pctl->pctl_dev);
+ return ret;
}

static struct platform_driver sunxi_pinctrl_driver = {
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index 0dc3b9d..0416c36 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -256,6 +256,7 @@

#define BANK_MEM_SIZE 0x24
#define MUX_REGS_OFFSET 0x0
+#define DATA_REGS_OFFSET 0x10
#define DLEVEL_REGS_OFFSET 0x14
#define PULL_REGS_OFFSET 0x1c

@@ -263,6 +264,9 @@
#define MUX_PINS_PER_REG 8
#define MUX_PINS_BITS 4
#define MUX_PINS_MASK 0x0f
+#define DATA_PINS_PER_REG 32
+#define DATA_PINS_BITS 1
+#define DATA_PINS_MASK 0x01
#define DLEVEL_PINS_PER_REG 16
#define DLEVEL_PINS_BITS 2
#define DLEVEL_PINS_MASK 0x03
@@ -283,6 +287,8 @@ struct sunxi_desc_pin {
struct sunxi_pinctrl_desc {
const struct sunxi_desc_pin *pins;
int npins;
+ struct pinctrl_gpio_range *ranges;
+ int nranges;
};

struct sunxi_pinctrl_function {
@@ -299,6 +305,7 @@ struct sunxi_pinctrl_group {

struct sunxi_pinctrl {
void __iomem *membase;
+ struct gpio_chip *chip;
struct sunxi_pinctrl_desc *desc;
struct device *dev;
struct sunxi_pinctrl_function *functions;
@@ -321,7 +328,6 @@ struct sunxi_pinctrl {
.muxval = _val, \
}

-
/*
* The sunXi PIO registers are organized as is:
* 0x00 - 0x0c Muxing values.
@@ -354,6 +360,21 @@ static inline u32 sunxi_mux_offset(u16 pin)
return pin_num * MUX_PINS_BITS;
}

+static inline u32 sunxi_data_reg(u16 pin)
+{
+ u8 bank = pin / PINS_PER_BANK;
+ u32 offset = bank * BANK_MEM_SIZE;
+ offset += DATA_REGS_OFFSET;
+ offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04;
+ return round_down(offset, 4);
+}
+
+static inline u32 sunxi_data_offset(u16 pin)
+{
+ u32 pin_num = pin % DATA_PINS_PER_REG;
+ return pin_num * DATA_PINS_BITS;
+}
+
static inline u32 sunxi_dlevel_reg(u16 pin)
{
u8 bank = pin / PINS_PER_BANK;
--
1.7.10.4

Linus Walleij

unread,
Jan 23, 2013, 10:40:02 AM1/23/13
to
On Wed, Jan 23, 2013 at 10:34 AM, Maxime Ripard
<maxime...@free-electrons.com> wrote:

> The IP responsible for the muxing on the Allwinner SoCs are also
> handling the GPIOs on the system. This patch adds the needed driver that
> relies on the pinctrl driver for most of its operations.
>
> The number of pins available for GPIOs operations are already declared
> in the pinctrl driver, we only need to probe a generic driver to handle
> the banks available for each SoC.
>
> This driver has been tested on a A13-Olinuxino.
>
> Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>

Overall this is VERY NICE!

> + char *func, *pin_name;
(...)
> + pin_name = kzalloc(5, GFP_KERNEL);
> + if (!pin_name)
> + return -ENOMEM;
> +
> + ret = sprintf(pin_name, "P%c%d", 'A' + bank, pin);
> + if (!ret)
> + goto error;
(...)
> +error:
> + kfree(pin_name);

Isn't this a bit awkward?

Can't you either use something like a local
static char foo[MAX_SIZE]; or atleast try to use
one of the static string print functions from <linux/kernel.h>:

/* lib/printf utilities */

extern __printf(2, 3) int sprintf(char *buf, const char * fmt, ...);
extern __printf(2, 0) int vsprintf(char *buf, const char *, va_list);
extern __printf(3, 4)
int snprintf(char *buf, size_t size, const char *fmt, ...);
extern __printf(3, 0)
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
extern __printf(3, 4)
int scnprintf(char *buf, size_t size, const char *fmt, ...);
extern __printf(3, 0)
int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
extern __printf(2, 3)
char *kasprintf(gfp_t gfp, const char *fmt, ...);
extern char *kvasprintf(gfp_t gfp, const char *fmt, va_list args);

Yours,
Linus Walleij

Maxime Ripard

unread,
Jan 26, 2013, 4:40:01 AM1/26/13
to
The IP responsible for the muxing on the Allwinner SoCs are also
handling the GPIOs on the system. This patch adds the needed driver that
relies on the pinctrl driver for most of its operations.

The number of pins available for GPIOs operations are already declared
in the pinctrl driver, we only need to probe a generic driver to handle
the banks available for each SoC.

This driver has been tested on a A13-Olinuxino.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
Changes from v2:
- Removed the call to kzalloc to build the pin name

drivers/pinctrl/pinctrl-sunxi.c | 134 ++++++++++++++++++++++++++++++++++++++-
drivers/pinctrl/pinctrl-sunxi.h | 25 +++++++-
2 files changed, 156 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 6f02e34..4ed0e7e 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -11,6 +11,7 @@
*/

#include <linux/io.h>
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -609,11 +610,53 @@ static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
return 0;
}

+static int
+sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset,
+ bool input)
+{
+ struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct sunxi_desc_function *desc;
+ char pin_name[SUNXI_PIN_NAME_MAX_LEN];
+ char *func;
+ u8 bank, pin;
+ int ret;
+
+ bank = (offset) / PINS_PER_BANK;
+ pin = (offset) % PINS_PER_BANK;
+
+ ret = sprintf(pin_name, "P%c%d", 'A' + bank, pin);
+ if (!ret)
+ goto error;
+
+ if (input)
+ func = "gpio_in";
+ else
+ func = "gpio_out";
+
+ desc = sunxi_pinctrl_desc_find_function_by_name(pctl,
+ pin_name,
+ func);
+ if (!desc) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ sunxi_pmx_set(pctldev, offset, desc->muxval);
+
+ ret = 0;
+
+error:
+ return ret;
+}
+
static struct pinmux_ops sunxi_pmx_ops = {
.get_functions_count = sunxi_pmx_get_funcs_cnt,
.get_function_name = sunxi_pmx_get_func_name,
.get_function_groups = sunxi_pmx_get_func_groups,
.enable = sunxi_pmx_enable,
+ .gpio_set_direction = sunxi_pmx_gpio_set_direction,
};

static struct pinctrl_desc sunxi_pctrl_desc = {
@@ -622,6 +665,60 @@ static struct pinctrl_desc sunxi_pctrl_desc = {
@@ -737,7 +834,7 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
const struct of_device_id *device;
struct pinctrl_pin_desc *pins;
struct sunxi_pinctrl *pctl;
- int i, ret;
+ int i, ret, last_pin;

pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -781,9 +878,42 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
index 0dc3b9d..1ee35c0 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -254,8 +254,11 @@
#define SUNXI_PINCTRL_PIN_PG30 PINCTRL_PIN(PG_BASE + 30, "PG30")
#define SUNXI_PINCTRL_PIN_PG31 PINCTRL_PIN(PG_BASE + 31, "PG31")

+#define SUNXI_PIN_NAME_MAX_LEN 5
+
#define BANK_MEM_SIZE 0x24
#define MUX_REGS_OFFSET 0x0
+#define DATA_REGS_OFFSET 0x10
#define DLEVEL_REGS_OFFSET 0x14
#define PULL_REGS_OFFSET 0x1c

@@ -263,6 +266,9 @@
#define MUX_PINS_PER_REG 8
#define MUX_PINS_BITS 4
#define MUX_PINS_MASK 0x0f
+#define DATA_PINS_PER_REG 32
+#define DATA_PINS_BITS 1
+#define DATA_PINS_MASK 0x01
#define DLEVEL_PINS_PER_REG 16
#define DLEVEL_PINS_BITS 2
#define DLEVEL_PINS_MASK 0x03
@@ -283,6 +289,8 @@ struct sunxi_desc_pin {
struct sunxi_pinctrl_desc {
const struct sunxi_desc_pin *pins;
int npins;
+ struct pinctrl_gpio_range *ranges;
+ int nranges;
};

struct sunxi_pinctrl_function {
@@ -299,6 +307,7 @@ struct sunxi_pinctrl_group {

struct sunxi_pinctrl {
void __iomem *membase;
+ struct gpio_chip *chip;
struct sunxi_pinctrl_desc *desc;
struct device *dev;
struct sunxi_pinctrl_function *functions;
@@ -321,7 +330,6 @@ struct sunxi_pinctrl {
.muxval = _val, \
}

-
/*
* The sunXi PIO registers are organized as is:
* 0x00 - 0x0c Muxing values.
@@ -354,6 +362,21 @@ static inline u32 sunxi_mux_offset(u16 pin)
return pin_num * MUX_PINS_BITS;
}

+static inline u32 sunxi_data_reg(u16 pin)
+{
+ u8 bank = pin / PINS_PER_BANK;
+ u32 offset = bank * BANK_MEM_SIZE;
+ offset += DATA_REGS_OFFSET;
+ offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04;
+ return round_down(offset, 4);
+}
+
+static inline u32 sunxi_data_offset(u16 pin)
+{
+ u32 pin_num = pin % DATA_PINS_PER_REG;
+ return pin_num * DATA_PINS_BITS;
+}
+
static inline u32 sunxi_dlevel_reg(u16 pin)
{
u8 bank = pin / PINS_PER_BANK;
--
1.7.10.4

Ezequiel Garcia

unread,
Jan 26, 2013, 9:40:02 AM1/26/13
to
Hi Maxime,
Nitpick: const char *func.

--
Ezequiel

Emilio López

unread,
Jan 27, 2013, 5:30:01 PM1/27/13
to
Hello Maxime,

El 26/01/13 06:31, Maxime Ripard escribi�:
__devinitconst got dropped on commit 54b956b9, "Remove __dev* markings
from init.h".

Thanks for the patches, I will be trying them on my A10 board soon.

--
Emilio

Maxime Ripard

unread,
Jan 28, 2013, 3:40:01 PM1/28/13
to
The IP responsible for the muxing on the Allwinner SoCs are also
handling the GPIOs on the system. This patch adds the needed driver that
relies on the pinctrl driver for most of its operations.

The number of pins available for GPIOs operations are already declared
in the pinctrl driver, we only need to probe a generic driver to handle
the banks available for each SoC.

This driver has been tested on a A13-Olinuxino.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
drivers/pinctrl/pinctrl-sunxi.c | 134 ++++++++++++++++++++++++++++++++++++++-
drivers/pinctrl/pinctrl-sunxi.h | 25 +++++++-
2 files changed, 156 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 6f02e34..fb000b0 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -11,6 +11,7 @@
*/

#include <linux/io.h>
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -609,11 +610,53 @@ static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
return 0;
}

+static int
+sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset,
+ bool input)
+{
+ struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct sunxi_desc_function *desc;
+ char pin_name[SUNXI_PIN_NAME_MAX_LEN];
+ const char *func;
+static struct gpio_chip sunxi_pinctrl_gpio_chip = {

Linus Walleij

unread,
Jan 29, 2013, 5:40:02 PM1/29/13
to
On Mon, Jan 28, 2013 at 9:33 PM, Maxime Ripard
<maxime...@free-electrons.com> wrote:

> The IP responsible for the muxing on the Allwinner SoCs are also
> handling the GPIOs on the system. This patch adds the needed driver that
> relies on the pinctrl driver for most of its operations.
>
> The number of pins available for GPIOs operations are already declared
> in the pinctrl driver, we only need to probe a generic driver to handle
> the banks available for each SoC.
>
> This driver has been tested on a A13-Olinuxino.
>
> Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>

Applied to my allwinner branch.

I'm a bit confused with other patches floating around,
I hope I'm supposed to apply this first...

Thanks,
Linus Walleij

Maxime Ripard

unread,
Jan 29, 2013, 5:50:02 PM1/29/13
to
Hi Linus,

Le 29/01/2013 23:38, Linus Walleij a �crit :
> On Mon, Jan 28, 2013 at 9:33 PM, Maxime Ripard
> <maxime...@free-electrons.com> wrote:
>
>> The IP responsible for the muxing on the Allwinner SoCs are also
>> handling the GPIOs on the system. This patch adds the needed driver that
>> relies on the pinctrl driver for most of its operations.
>>
>> The number of pins available for GPIOs operations are already declared
>> in the pinctrl driver, we only need to probe a generic driver to handle
>> the banks available for each SoC.
>>
>> This driver has been tested on a A13-Olinuxino.
>>
>> Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
>
> Applied to my allwinner branch.
>
> I'm a bit confused with other patches floating around,
> I hope I'm supposed to apply this first...

Ah, yes, sorry, I forgot to mention the order of the patchset.

This one is indeed the first one, then comes "Add pinctrl/gpio support
for A10 SoCs", and finally "Add support for user LED on the A13-Olinuxino".

Since you already started to merge most of the patches for the sunxi
device tree, maybe the most reasonnable thing to do to avoid merge
conflicts would be for you to merge all of these patches.

Thanks!
Maxime


--
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
0 new messages