sunxi: DM pinctrl implementation
Subsystems (4)
v2 cover sunxi: DM pinctrl implementation
Here's v2, which incorporates the feedback from Maxime and ChenYu into a more complete and less intrusive version.
The most elegant solution to our problem with pinctrl & gpio, which will also work equally well for ccu and reset, is to have the device model bind multiple drivers to a single node: for this reason, one patch of the series touches the device-model core.
To provide a bit more context, I've also include the change showing how this is enabled in our defconfig (i.e. a diff against our defconfig, even though the defconfig has not been submitted yet).
Changes in v2:
* two variants to reuse the sunxi_gpio layer:
- create a matching soc_data for sunxi_gpio and rebind
- have the device-model do this for us
* got rid of the gpio-banks and gpiobridge drivers
Philipp Tomsich (6):
sunxi: add pinctrl (UCLASS_PINCTRL) support for sunxi
dm: core: Allow multiple drivers to bind for a single node
sunxi: CONFIG_DM_ALLOW_MULTIPLE_DRIVERS for gpio/pinctrl binding
defconfig: lynx: enable CONFIG_DM_ALLOW_MULTIPLE_DRIVERS
sun50i: dts: add r_pio node and pinconfig entries into r_pio and pio
sun50i: dts: update DTS to avoid warnings
arch/arm/dts/sun50i-a64.dtsi | 62 ++- arch/arm/include/asm/arch-sunxi/gpio-internal.h | 19 + configs/lynx_defconfig | 1 + .../pinctrl/allwinner,pinctrl.txt | 65 +++ drivers/core/Kconfig | 14 + drivers/core/lists.c | 12 +- drivers/gpio/sunxi_gpio.c | 15 +- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 2 + drivers/pinctrl/sunxi/Makefile | 10 + drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c | 92 ++++ drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c | 577 +++++++++++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 321 ++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 311 +++++++++++ 14 files changed, 1479 insertions(+), 32 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/gpio-internal.h create mode 100644 doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt create mode 100644 drivers/pinctrl/sunxi/Makefile create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.h
Signature · 1 line
1.9.1
PATCH v2 1/6 sunxi: add pinctrl (UCLASS_PINCTRL) support for sunxi
This change adds a full device-model pinctrl driver for sunxi (tested with sun50iw1p1) based on the support available in Linux.
Details are:
* implements a driver for pinctrl devices and assigns sun50i-a64-pinctrl and sun50i-a64-r-pinctrl to it
* dynamically creates the driver_data for a sunxi_gpio (see sunxi_gpio.c) driver and binds it to the same device-tree node
* lifts and reuses the pinctrl-sunxi.h and pinctrl-sun50i-a64.c files from Linux (thanks to Maxime and Andre) and adds a pinctrl-sun50i-a64-r.c (to be picked up for inclusion into Linux again)
--- arch/arm/include/asm/arch-sunxi/gpio-internal.h | 19 + .../pinctrl/allwinner,pinctrl.txt | 65 +++ drivers/gpio/sunxi_gpio.c | 15 +- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 2 + drivers/pinctrl/sunxi/Makefile | 10 + drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c | 92 ++++ drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c | 577 +++++++++++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 317 +++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 311 +++++++++++ 10 files changed, 1411 insertions(+), 7 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/gpio-internal.h create mode 100644 doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt create mode 100644 drivers/pinctrl/sunxi/Makefile create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.h
arch/arm/include/asm/arch-sunxi/gpio-internal.h new file +19 -0
@@ -0,0 +1,19 @@ +/* +* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + + +#ifndef _SUNXI_GPIO_INTERNAL_H +#define _SUNXI_GPIO_INTERNAL_H + +/* This data structure is shared between the sunxi_gpio driver and +* the sunxi_pinctrl driver. +*/ +struct sunxi_gpio_soc_data { +int start; +int no_banks; +}; + +#endif
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +65 -0
65 lines not on this page · raw message
drivers/gpio/sunxi_gpio.c +8 -7
@@ -16,6 +16,7 @@#include <fdtdec.h> #include <malloc.h> #include <asm/arch/gpio.h> +#include <asm/arch/gpio-internal.h> #include <asm/io.h> #include <asm/gpio.h> #include <dm/device-internal.h>
@@ -275,11 +276,6 @@ static int gpio_sunxi_probe(struct udevice *dev)return 0 ; } -struct sunxi_gpio_soc_data { -int start; -int no_banks; -}; -/** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Sunxi bank.
@@ -353,18 +349,22 @@ static const struct udevice_id sunxi_gpio_ids[] = {ID ("allwinner,sun8i-a83t-pinctrl" , a_all),ID ("allwinner,sun8i-h3-pinctrl" , a_all),ID ("allwinner,sun9i-a80-pinctrl" , a_all), +#if !defined(CONFIG_SUNXI_PINCTRL)/* This is not strictly correct for the A64, as it is missing * bank 'A'. Yet, the register layout in the pinctrl block is * backward compatible and any accesses to the registers that * normally control bank 'A' will have no adverse effect. */ -ID ("allwinner,sun50i-a64-pinctrl" , a_all), +ID ("allwinner,sun50i-a64-pinctrl" , a_all), +#endifID ("allwinner,sun6i-a31-r-pinctrl" , l_2),ID ("allwinner,sun8i-a23-r-pinctrl" , l_1),ID ("allwinner,sun8i-a83t-r-pinctrl" , l_1),ID ("allwinner,sun8i-h3-r-pinctrl" , l_1),ID ("allwinner,sun9i-a80-r-pinctrl" , l_3), - ID("allwinner,sun50i-a64-r-pinctrl", l_1), +#if !defined(CONFIG_SUNXI_PINCTRL) + ID("allwinner,sun50i-a64-r-pinctrl", l_1), +#endif { } };
@@ -376,4 +376,5 @@ U_BOOT_DRIVER(gpio_sunxi) = { .bind = gpio_sunxi_bind, .probe = gpio_sunxi_probe, }; +#endif
drivers/pinctrl/Kconfig +10 -0
@@ -175,6 +175,16 @@ config PIC32_PINCTRL by a device tree node which contains both GPIO defintion and pin control functions. +config SUNXI_PINCTRL + bool "Allwinner Axx pin-control and pin-mux driver" + depends on DM && ARCH_SUNXI + default y + help + Supports pin multiplexing control, drive-strength and bias control on + Allwinner Axx SoCs. The driver is controlled by a device tree node which + contains both the GPIO definitions and the pin control functions for + each multiplex function. + endif source "drivers/pinctrl/meson/Kconfig"
drivers/pinctrl/Makefile +2 -0
@@ -16,3 +16,5 @@ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ + +obj-$(CONFIG_ARCH_SUNXI) += sunxi/
drivers/pinctrl/sunxi/Makefile new file +10 -0
@@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_SUNXI_PINCTRL) += pinctrl-sunxi.o +ifdef CONFIG_SUNXI_PINCTRL +obj-$(CONFIG_MACH_SUN50I) += pinctrl-sun50i-a64.o pinctrl-sun50i-a64-r.o +endif
drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c new file +92 -0
92 lines not on this page · raw message
drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c new file +577 -0
577 lines not on this page · raw message
drivers/pinctrl/sunxi/pinctrl-sunxi.c new file +317 -0
317 lines not on this page · raw message
drivers/pinctrl/sunxi/pinctrl-sunxi.h new file +311 -0
311 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v2 1/6 sunxi: add pinctrl (UCLASS_PINCTRL) support for sunxi
Quoted 67 lines · Philipp Tomsich
This change adds a full device-model pinctrl driver for sunxi (tested with sun50iw1p1) based on the support available in Linux.
Details are:
* implements a driver for pinctrl devices and assigns sun50i-a64-pinctrl and sun50i-a64-r-pinctrl to it
* dynamically creates thedriver_datafor asunxi_gpio(seesunxi_gpio.c) driver and binds it to the same device-tree node
* lifts and reuses thepinctrl-sunxi.handpinctrl-sun50i-a64.cfiles from Linux (thanks to Maxime and Andre) and adds apinctrl-sun50i-a64-r.c(to be picked up for inclusion into Linux again)Signed-off-by Philipp Tomsich <[email protected]>--- arch/arm/include/asm/arch-sunxi/gpio-internal.h | 19 + .../pinctrl/allwinner,pinctrl.txt | 65 +++ drivers/gpio/sunxi_gpio.c | 15 +- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 2 + drivers/pinctrl/sunxi/Makefile | 10 + drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c | 92 ++++ drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c | 577 +++++++++++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 317 +++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 311 +++++++++++ 10 files changed, 1411 insertions(+), 7 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/gpio-internal.h create mode 100644 doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt create mode 100644 drivers/pinctrl/sunxi/Makefile create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.harch/arm/include/asm/arch-sunxi/gpio-internal.h new file +19
-0@@ -0,0 +1,19 @@ +/* +* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + + +#ifndef _SUNXI_GPIO_INTERNAL_H +#define _SUNXI_GPIO_INTERNAL_H + +/* This data structure is shared between the sunxi_gpio driver and +* the sunxi_pinctrl driver. +*/ +struct sunxi_gpio_soc_data { +int start; +int no_banks; +}; + +#endif doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +3
-0@@ -0,0 +1,65 @@ +* Allwinner Pinmux Controller + +Allwinner integrates multiple banks (of 32 pins each) of pin-muxing,
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 13
Quoted 10 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +10
-0+GPIO functionality and (optional) external interrupt functionality +into a single controller. + +For each configurable pad (certain driver-cells, such as the IO from +integrated USB PHYs or DRAM, have a fixed function and can not be +configured), the muxing options (input, output or one of the several +functions) can be selected. + +Properties for the pinctrl node: + - compatible: should be "allwinner,sun50i-pinctrl"
There's a typo here, the compatible is sun50i-a64-pinctrl
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 16
Quoted 3 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +3
-0+ - reg: address and length of the register set for the device. + - interrupts: interrupt for the device + - clocks: A phandle to the reference clock for this device
(and ideally, this would take three clocks: the bus gate + the two oscillators).
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 20
Quoted 4 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +4
-0+ +Properties for the pinconfig sub-nodes: + - allwinner,pins: a list of pins (e.g. "PH2", "PH3") to configure + - allwinner,function: the name of pinmux function (e.g. "mmc2")
allwinner,pins and allwinner,function are also deprecated in favour of pins and function.
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 24
Quoted 4 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +4
-0+ - drive-strength: a drive-stength setting of 10, 20, 30 or 40 mA + - bias-pull-up + - bias-pull-down + - bias-disable (default)
The default is not bias-disable, but to keep the current configuration
Quoted 1,468 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +41
-0+ +Deprecated properties for the pinconfig sub-nodes: + - allwinner,drive: one of <SUN4I_PINCTRL_10_MA>, <SUN4I_PINCTRL_20_MA>, + <SUN4I_PINCTRL_30_MA> or <SUN4I_PINCTRL_40_MA> + - allwinner,pull: one of <SUN4I_PINCTRL_NO_PULL>, <SUN4I_PINCTRL_PULL_UP> + or <SUN4I_PINCTRL_PULL_DOWN> + +Example: + + pio: pinctrl at 1c20800 { + compatible = "allwinner,sun50i-a64-pinctrl"; + reg = <0x01c20800 0x400>; + + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bus_gates 69>; + + gpio-controller; + #gpio-cells = <3>; + + interrupt-controller; + #interrupt-cells = <2>; + + #address-cells = <1>; + #size-cells = <1>; + + uart0_pins_a: uart0_pins_a { + allwinner,pins = "PB8", "PB9"; + allwinner,function = "uart0"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + + uart0_pins_b: uart0_pins_b { + allwinner,pins = "PF2", "PF3"; + allwinner,function = "uart0"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + };drivers/gpio/sunxi_gpio.c +8
-7@@ -16,6 +16,7 @@#include <fdtdec.h> #include <malloc.h> #include <asm/arch/gpio.h> +#include <asm/arch/gpio-internal.h> #include <asm/io.h> #include <asm/gpio.h> #include <dm/device-internal.h> @@ -275,11 +276,6 @@ static int gpio_sunxi_probe(struct udevice *dev)return 0 ; } -struct sunxi_gpio_soc_data { -int start; -int no_banks; -}; -/** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Sunxi bank. @@ -353,18 +349,22 @@ static const struct udevice_id sunxi_gpio_ids[] = {ID ("allwinner,sun8i-a83t-pinctrl" , a_all),ID ("allwinner,sun8i-h3-pinctrl" , a_all),ID ("allwinner,sun9i-a80-pinctrl" , a_all), +#if !defined(CONFIG_SUNXI_PINCTRL)/* This is not strictly correct for the A64, as it is missing * bank 'A'. Yet, the register layout in the pinctrl block is * backward compatible and any accesses to the registers that * normally control bank 'A' will have no adverse effect. */ -ID ("allwinner,sun50i-a64-pinctrl" , a_all), +ID ("allwinner,sun50i-a64-pinctrl" , a_all), +#endifID ("allwinner,sun6i-a31-r-pinctrl" , l_2),ID ("allwinner,sun8i-a23-r-pinctrl" , l_1),ID ("allwinner,sun8i-a83t-r-pinctrl" , l_1),ID ("allwinner,sun8i-h3-r-pinctrl" , l_1),ID ("allwinner,sun9i-a80-r-pinctrl" , l_3), - ID("allwinner,sun50i-a64-r-pinctrl", l_1), +#if !defined(CONFIG_SUNXI_PINCTRL) + ID("allwinner,sun50i-a64-r-pinctrl", l_1), +#endif { } };@@ -376,4 +376,5 @@ U_BOOT_DRIVER(gpio_sunxi) = { .bind = gpio_sunxi_bind, .probe = gpio_sunxi_probe, }; +#endif drivers/pinctrl/Kconfig +10
-0@@ -175,6 +175,16 @@ config PIC32_PINCTRL by a device tree node which contains both GPIO defintion and pin control functions. +config SUNXI_PINCTRL + bool "Allwinner Axx pin-control and pin-mux driver" + depends on DM && ARCH_SUNXI + default y + help + Supports pin multiplexing control, drive-strength and bias control on + Allwinner Axx SoCs. The driver is controlled by a device tree node which + contains both the GPIO definitions and the pin control functions for + each multiplex function. + endif source "drivers/pinctrl/meson/Kconfig"drivers/pinctrl/Makefile +2
-0@@ -16,3 +16,5 @@ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ + +obj-$(CONFIG_ARCH_SUNXI) += sunxi/drivers/pinctrl/sunxi/Makefile new file +10
-0@@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_SUNXI_PINCTRL) += pinctrl-sunxi.o +ifdef CONFIG_SUNXI_PINCTRL +obj-$(CONFIG_MACH_SUN50I) += pinctrl-sun50i-a64.o pinctrl-sun50i-a64-r.o +endifdrivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c new file +92
-0@@ -0,0 +1,92 @@ +/* +* Allwinner A64 SoCs pinctrl driver. +* +* Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH. +* +* Based on pinctrl-sun7i-a20.c, which is: +* Copyright (C) 2014 Maxime Ripard <[email protected]> +* +* 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 <common.h> + +#include "pinctrl-sunxi.h" + +static const struct sunxi_desc_pin a64_r_pins[] = { +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_rsb" ),/* SCK */ +SUNXI_FUNCTION (0x3 ,"s_i2c" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_rsb" ),/* SDA */ +SUNXI_FUNCTION (0x3 ,"s_i2c" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_uart" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_uart" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* MS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* CK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* DO */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* DI */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_i2c" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_i2c" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,9 )),/* EINT9 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_pwm" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,10 )),/* EINT10 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_cir" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,11 )),/* EINT11 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,12 )),/* EINT12 */ +}; + +const struct sunxi_pinctrl_desc a64_r_pinctrl_data = { + .pins = a64_r_pins, + .npins =ARRAY_SIZE (a64_r_pins), + .pin_base =PL_BASE , + .irq_banks =1 , +};drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c new file +577
-0@@ -0,0 +1,577 @@ +/* +* Allwinner A64 SoCs pinctrl driver. +* +* Copyright (C) 2016 - ARM Ltd. +* Author: Andre Przywara <[email protected]> +* +* Based on pinctrl-sun7i-a20.c, which is: +* Copyright (C) 2014 Maxime Ripard <[email protected]> +* +* 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 <common.h> + +#include "pinctrl-sunxi.h" + +static const struct sunxi_desc_pin a64_pins[] = { +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* TX */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* MS0 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* RX */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* CK0 */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* VCCEN */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* RTS */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* DO0 */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* VPPEN */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* CTS */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* MCLK */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* DI0 */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* VPPPP */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* SYNC */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* SYNC */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* CLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* BCLK */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* BCLK */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* DATA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* DOUT */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* DOUT */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* RST */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* DIN */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* DIN */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* DET */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x4 ,"uart0" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x4 ,"uart0" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,9 )),/* EINT9 */ +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NWE */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* MOSI */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NALE */ +SUNXI_FUNCTION (0x3 ,"mmc2" ),/* DS */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* MISO */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NCLE */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* SCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NCE1 */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* CS */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" )),/* NCE0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NRE# */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* CLK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NRB0 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* CMD */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" )),/* NRB1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ0 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ1 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ2 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ3 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ4 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ5 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,14 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ6 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,15 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ7 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,16 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQS */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* RST */ +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D2 */ +SUNXI_FUNCTION (0x3 ,"uart3" ),/* TX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* CS */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* CLK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D3 */ +SUNXI_FUNCTION (0x3 ,"uart3" ),/* RX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* CLK */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* DE */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D4 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* TX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* MOSI */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* HSYNC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D5 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* RX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* MISO */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* VSYNC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D6 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* RTS */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D7 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* CTS */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D10 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D11 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D12 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ERXD3 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D13 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ERXD2 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D14 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXD1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D15 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXD0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D18 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP0 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D19 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN0 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXCTL */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,14 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D20 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP1 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ENULL */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,15 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D21 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN1 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ETXD3 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,16 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D22 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP2 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ETXD2 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,17 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D23 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN2 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXD1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,18 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* CLK */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VPC */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXD0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,19 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* DE */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VNC */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,20 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* HSYNC */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP3 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXCTL */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,21 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* VSYNC */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN3 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ECLKIN */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,22 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"pwm" ),/* PWM0 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* EMDC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,23 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x4 ,"emac" )),/* EMDIO */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,24 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* PCK */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* CLK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* CK */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* ERR */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* HSYNC */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* SYNC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* VSYNC */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* DVLD */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D0 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D1 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D2 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D3 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D4 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D5 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D6 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D7 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" )),/* SCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" )),/* SDA */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,14 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"pll" ),/* LOCK_DBG */ +SUNXI_FUNCTION (0x3 ,"i2c2" )),/* SCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,15 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x3 ,"i2c2" )),/* SDA */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,16 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,17 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D1 */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* MSI */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D0 */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* DI1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* CLK */ +SUNXI_FUNCTION (0x3 ,"uart0" )),/* TX */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* CMD */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* DO1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D3 */ +SUNXI_FUNCTION (0x4 ,"uart0" )),/* RX */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D2 */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* CK1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* CLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* CMD */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D0 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D1 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D2 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D3 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* RTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* CTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,9 )),/* EINT9 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* SYNC */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* SYNC */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,10 )),/* EINT10 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* BCLK */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* BCLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,11 )),/* EINT11 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* DOUT */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* DOUT */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,12 )),/* EINT12 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* DIN */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* DIN */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,13 )),/* EINT13 */ +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c0" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c0" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c1" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c1" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* RTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* CTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"spdif" ),/* OUT */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,9 )),/* EINT9 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mic" ),/* CLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,10 )),/* EINT10 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mic" ),/* DATA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,11 )),/* EINT11 */ +}; + +const struct sunxi_pinctrl_desc a64_pinctrl_data = { + .pins = a64_pins, + .npins =ARRAY_SIZE (a64_pins), + .irq_banks =3 , +};drivers/pinctrl/sunxi/pinctrl-sunxi.c new file +317
-0@@ -0,0 +1,317 @@ +/* +* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +* +* In parts based on linux/drivers/pinctrl/pinctrl-sunxi.c, which is +* Copyright (C) 2012 Maxime Ripard +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <syscon.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/gpio.h> +#include <asm/arch/gpio-internal.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <dt-bindings/pinctrl/sun4i-a10.h> +#include <dt-bindings/gpio/gpio.h> +#include <linux/kernel.h> +#include "pinctrl-sunxi.h" + +DECLARE_GLOBAL_DATA_PTR ; + +struct sunxi_pctrl_priv { +void *base; +#if defined(CONFIG_DM_GPIO ) +struct sunxi_gpio_soc_data gpio_soc_data; +struct udevice *gpio_dev; +#endif +}; + +static int sunxi_pctrl_parse_drive_prop (const void *blob,int node) +{ +int val; + +/* Try the new style binding */ + val =fdtdec_get_int (blob, node,"drive-strength" , -EINVAL ); +if (val >=0 ) { +/* We can't go below 10mA ... */ +if (val <10 ) +return -EINVAL ; + +/* ... and only up to 40 mA ... */ +if (val >40 ) + val =40 ; + +/* by steps of 10 mA */ +return rounddown (val,10 ); + } + +/* And then fall back to the old binding */ + val =fdtdec_get_int (blob, node,"allwinner,drive" , -EINVAL ); +if (val <0 ) +return -EINVAL ; + +return (val +1 ) *10 ; +} + +static int sunxi_pctrl_parse_bias_prop (const void *blob,int node) +{ +/* Try the new style binding */ +if (fdtdec_get_bool (blob, node,"bias-pull-up" )) +return SUN4I_PINCTRL_PULL_UP ; + +if (fdtdec_get_bool (blob, node,"bias-pull-down" )) +return SUN4I_PINCTRL_PULL_DOWN ; + +if (fdtdec_get_bool (blob, node,"bias-disable" )) +return SUN4I_PINCTRL_NO_PULL ; + +/* And fall back to the old binding */ +return fdtdec_get_int (blob, node,"allwinner,pull" , -EINVAL ); +} + +static const struct sunxi_desc_pin *sunxi_pctrl_pin_by_name (struct udevice *dev, +const char *name) +{ +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +int i; + +for (i =0 ; i < data->npins; ++i) +if (!strcmp (data->pins[i].pin.name, name)) +return &data->pins[i]; + +return NULL ; +} + +static int sunxi_pctrl_muxval_by_name (const struct sunxi_desc_pin *pin, +const char *name) +{ +const struct sunxi_desc_function *func; + +if (!pin) +return -EINVAL ; + +for (func = pin->functions; func->name; func++) +if (!strcmp (func->name, name)) +return func->muxval; + +return -ENOENT ; +} + +static void sunxi_pctrl_set_function (struct udevice *dev, +unsigned pin,int function) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +u32 val, mask; + +if (function <0 ) +return ; + + pin -= data->pin_base; + mask =MUX_PINS_MASK <<sunxi_mux_offset (pin); + val = function <<sunxi_mux_offset (pin); +clrsetbits_le32 (priv->base +sunxi_mux_reg (pin), mask, val); +} + +static void sunxi_pctrl_set_dlevel (struct udevice *dev, +unsigned pin,int dlevel) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +u32 val, mask; + +if (dlevel <0 ) +return ; + + pin -= data->pin_base; + mask =DLEVEL_PINS_MASK <<sunxi_dlevel_offset (pin); + val = dlevel <<sunxi_dlevel_offset (pin); +clrsetbits_le32 (priv->base +sunxi_dlevel_reg (pin), mask, val); +} + +static void sunxi_pctrl_set_bias (struct udevice *dev, +unsigned pin,int bias) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +u32 val, mask; + +if (bias <0 ) +return ; + + pin -= data->pin_base; + mask =PULL_PINS_MASK <<sunxi_pull_offset (pin); + val = bias <<sunxi_pull_offset (pin); +clrsetbits_le32 (priv->base +sunxi_pull_reg (pin), mask, val); +} + +static int sunxi_pctrl_set_state (struct udevice *dev,struct udevice *config) +{ +const char *pins; +const char *function; +int flen; +int len, curr_len; +int drive, bias; +int muxval; + +debug ("%s: %s %s\n" , __func__, dev->name, config->name); + + pins =fdt_getprop (gd->fdt_blob, config->of_offset, +"allwinner,pins" , &len); +if (!pins) { +debug ("%s: missing allwinner,pins property in node %s\n" , + dev->name, config->name); +return -EINVAL ; + } + + function =fdt_getprop (gd->fdt_blob, config->of_offset, +"allwinner,function" , &flen); +if (!function) { +debug ("%s: missing allwinner,function property in node %s\n" , + dev->name, config->name); +return -EINVAL ; + } + + drive =sunxi_pctrl_parse_drive_prop (gd->fdt_blob, config->of_offset); + bias =sunxi_pctrl_parse_bias_prop (gd->fdt_blob, config->of_offset); + +debug ("%s: function %s, drive %d, bias %d\n" , + config->name, function, drive, bias); + +/* Iterate through the pins and configure each */ +while (len && (curr_len =strnlen (pins, len))) { +const struct sunxi_desc_pin *pin; + +if (curr_len == len) { +error ("%s: unterminated string?" , __func__); +break ; + } + + pin =sunxi_pctrl_pin_by_name (dev, pins); +if (pin) { + muxval =sunxi_pctrl_muxval_by_name (pin, function); + +sunxi_pctrl_set_function (dev, pin->pin.number, muxval); +sunxi_pctrl_set_dlevel (dev, pin->pin.number, drive); +sunxi_pctrl_set_bias (dev, pin->pin.number, bias); + }else { +debug ("%s: could not find pin %s\n" , dev->name, pins); + } + +/* advance */ + pins += (curr_len +1 ); + len -= (curr_len +1 ); + } + +return 0 ; +} + +static inline void soc_data_from_desc (const struct sunxi_pinctrl_desc *data, +struct sunxi_gpio_soc_data *soc_data) +{ +int i; +unsigned pinnum; +unsigned low = data->pin_base /PINS_PER_BANK ; +unsigned high = data->pin_base; + +for (i =0 ; i < data->npins; ++i) { + pinnum = data->pins[i].pin.number; + high =max (high, pinnum); + } + +/* convert pin-numbers to bank numbers */ + high /=PINS_PER_BANK ; + + soc_data->start = low; + soc_data->no_banks = high - low +1 ; +} + +static int sunxi_pctrl_bind_gpio (struct udevice *dev) +{ +#if defined(CONFIG_DM_GPIO ) +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +struct driver *gpio_driver; +char name[20 ]; +int ret; + +/* Fill the soc_data for the gpio driver from the pinctrl_desc */ +soc_data_from_desc (data, &priv->gpio_soc_data); + + gpio_driver =lists_driver_lookup_name ("gpio_sunxi" ); +if (!gpio_driver) +return -ENOENT ; + + ret =device_bind_with_driver_data (dev, gpio_driver,"sunxi_gpio" , + (ulong)&priv->gpio_soc_data, + dev->of_offset, &priv->gpio_dev); + +if (ret <0 ) +return ret; + +snprintf (name,sizeof (name),"sunxi_gpio@%x" , (uint32_t )priv->base); +device_set_name (priv->gpio_dev, name); +#endif + +return 0 ; +} + +static int sunxi_pctrl_probe (struct udevice *dev) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +fdt_addr_t addr_base; +fdt_size_t size; + + addr_base =fdtdec_get_addr_size_auto_noparent (gd->fdt_blob, + dev->of_offset, +"reg" ,0 , &size, + false); +if (addr_base ==FDT_ADDR_T_NONE ) +return -EINVAL ; + + priv->base = (void *)addr_base; + +return sunxi_pctrl_bind_gpio (dev); +} + +static struct pinctrl_ops sunxi_pctrl_ops = { + .set_state = sunxi_pctrl_set_state, +}; + +#if defined(CONFIG_MACH_SUN50I ) +extern const struct sunxi_pinctrl_desc a64_pinctrl_data; +extern const struct sunxi_pinctrl_desc a64_r_pinctrl_data; +#endif + +static const struct udevice_id sunxi_pctrl_ids[] = { +#if defined(CONFIG_MACH_SUN50I) + { .compatible ="allwinner,sun50i-a64-pinctrl" , + .data = (ulong)&a64_pinctrl_data }, + { .compatible ="allwinner,sun50i-a64-r-pinctrl" , + .data = (ulong)&a64_r_pinctrl_data }, +#endif + { } +}; + +U_BOOT_DRIVER (pinctrl_sunxi) = { + .name ="sunxi_pctrl" , + .id =UCLASS_PINCTRL , + .of_match = sunxi_pctrl_ids, + .priv_auto_alloc_size =sizeof (struct sunxi_pctrl_priv ), + .ops = &sunxi_pctrl_ops, + .bind = dm_scan_fdt_dev, + .probe = sunxi_pctrl_probe, +}; +drivers/pinctrl/sunxi/pinctrl-sunxi.h new file +311
-0@@ -0,0 +1,311 @@ +/* +* Allwinner A1X SoCs pinctrl driver. +* +* Copyright (C) 2012 Maxime Ripard +* +* Maxime Ripard <[email protected]> +* +* 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. +*/ + +#ifndef __PINCTRL_SUNXI_H +#define __PINCTRL_SUNXI_H + +#define PA_BASE 0 +#define PB_BASE 32 +#define PC_BASE 64 +#define PD_BASE 96 +#define PE_BASE 128 +#define PF_BASE 160 +#define PG_BASE 192 +#define PH_BASE 224 +#define PI_BASE 256 +#define PL_BASE 352 +#define PM_BASE 384 +#define PN_BASE 416 + +#ifdef __UBOOT__ +/* Convenience macro to define a single named or anonymous pin descriptor */ +#define PINCTRL_PIN (a, b) { .number = a, .name = b } + +/** +* struct pinctrl_pin_desc - boards/machines provide information on their +* pins, pads or other muxable units in this struct +* @number: unique pin number from the global pin number space +* @name: a name for this pin +* @drv_data: driver-defined per-pin data. pinctrl core does not touch this +*/ +struct pinctrl_pin_desc { +unsigned number; +const char *name; +#ifndef __UBOOT__ +void *drv_data; +#endif +}; +#endif + +#define SUNXI_PINCTRL_PIN (bank, pin) \ + PINCTRL_PIN(P ## bank ## _BASE + (pin), "P" #bank #pin) + +#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 + +#define PINS_PER_BANK 32 +#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 +#define PULL_PINS_PER_REG 16 +#define PULL_PINS_BITS 2 +#define PULL_PINS_MASK 0x03 + +#define IRQ_PER_BANK 32 + +#define IRQ_CFG_REG 0x200 +#define IRQ_CFG_IRQ_PER_REG 8 +#define IRQ_CFG_IRQ_BITS 4 +#define IRQ_CFG_IRQ_MASK ((1 << IRQ_CFG_IRQ_BITS) - 1) +#define IRQ_CTRL_REG 0x210 +#define IRQ_CTRL_IRQ_PER_REG 32 +#define IRQ_CTRL_IRQ_BITS 1 +#define IRQ_CTRL_IRQ_MASK ((1 << IRQ_CTRL_IRQ_BITS) - 1) +#define IRQ_STATUS_REG 0x214 +#define IRQ_STATUS_IRQ_PER_REG 32 +#define IRQ_STATUS_IRQ_BITS 1 +#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1) + +#define IRQ_MEM_SIZE 0x20 + +#define IRQ_EDGE_RISING 0x00 +#define IRQ_EDGE_FALLING 0x01 +#define IRQ_LEVEL_HIGH 0x02 +#define IRQ_LEVEL_LOW 0x03 +#define IRQ_EDGE_BOTH 0x04 + +#define SUN4I_FUNC_INPUT 0 +#define SUN4I_FUNC_IRQ 6 + +struct sunxi_desc_function { +const char *name; +u8 muxval; +u8 irqbank; +u8 irqnum; +}; + +struct sunxi_desc_pin { +struct pinctrl_pin_desc pin; +struct sunxi_desc_function *functions; +}; + +struct sunxi_pinctrl_desc { +const struct sunxi_desc_pin *pins; +int npins; +unsigned pin_base; +unsigned irq_banks; +unsigned irq_bank_base; +bool irq_read_needs_mux; +}; + +struct sunxi_pinctrl_function { +const char *name; +const char **groups; +unsigned ngroups; +}; + +struct sunxi_pinctrl_group { +const char *name; +unsigned long config; +unsigned pin; +}; + +#ifndef __UBOOT__ +struct sunxi_pinctrl { +void __iomem *membase; +struct gpio_chip *chip; +const struct sunxi_pinctrl_desc *desc; +struct device *dev; +struct irq_domain *domain; +struct sunxi_pinctrl_function *functions; +unsigned nfunctions; +struct sunxi_pinctrl_group *groups; +unsigned ngroups; +int *irq; +unsigned *irq_array; +spinlock_t lock; +struct pinctrl_dev *pctl_dev; +}; +#endif + +#define SUNXI_PIN (_pin, ...) \ + { \ + .pin = _pin, \ + .functions = (struct sunxi_desc_function[]){ \ + __VA_ARGS__, { } }, \ + } + +#define SUNXI_FUNCTION (_val, _name) \ + { \ + .name = _name, \ + .muxval = _val, \ + } + +#define SUNXI_FUNCTION_IRQ (_val, _irq) \ + { \ + .name = "irq", \ + .muxval = _val, \ + .irqnum = _irq, \ + } + +#define SUNXI_FUNCTION_IRQ_BANK (_val, _bank, _irq) \ + { \ + .name = "irq", \ + .muxval = _val, \ + .irqbank = _bank, \ + .irqnum = _irq, \ + } + +/* +* The sunXi PIO registers are organized as is: +* 0x00 - 0x0c Muxing values. +* 8 pins per register, each pin having a 4bits value +* 0x10 Pin values +* 32 bits per register, each pin corresponding to one bit +* 0x14 - 0x18 Drive level +* 16 pins per register, each pin having a 2bits value +* 0x1c - 0x20 Pull-Up values +* 16 pins per register, each pin having a 2bits value +* +* This is for the first bank. Each bank will have the same layout, +* with an offset being a multiple of 0x24. +* +* The following functions calculate from the pin number the register +* and the bit offset that we should access. +*/ +static inline u32 sunxi_mux_reg (u16 pin) +{ +u8 bank = pin /PINS_PER_BANK ; +u32 offset = bank *BANK_MEM_SIZE ; + offset +=MUX_REGS_OFFSET ; + offset += pin %PINS_PER_BANK /MUX_PINS_PER_REG *0x04 ; +return round_down (offset,4 ); +} + +static inline u32 sunxi_mux_offset (u16 pin) +{ +u32 pin_num = pin %MUX_PINS_PER_REG ; +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 ; +u32 offset = bank *BANK_MEM_SIZE ; + offset +=DLEVEL_REGS_OFFSET ; + offset += pin %PINS_PER_BANK /DLEVEL_PINS_PER_REG *0x04 ; +return round_down (offset,4 ); +} + +static inline u32 sunxi_dlevel_offset (u16 pin) +{ +u32 pin_num = pin %DLEVEL_PINS_PER_REG ; +return pin_num *DLEVEL_PINS_BITS ; +} + +static inline u32 sunxi_pull_reg (u16 pin) +{ +u8 bank = pin /PINS_PER_BANK ; +u32 offset = bank *BANK_MEM_SIZE ; + offset +=PULL_REGS_OFFSET ; + offset += pin %PINS_PER_BANK /PULL_PINS_PER_REG *0x04 ; +return round_down (offset,4 ); +} + +static inline u32 sunxi_pull_offset (u16 pin) +{ +u32 pin_num = pin %PULL_PINS_PER_REG ; +return pin_num *PULL_PINS_BITS ; +} + +static inline u32 sunxi_irq_cfg_reg (u16 irq,unsigned bank_base) +{ +u8 bank = irq /IRQ_PER_BANK ; +u8 reg = (irq %IRQ_PER_BANK ) /IRQ_CFG_IRQ_PER_REG *0x04 ; + +return IRQ_CFG_REG + (bank_base + bank) *IRQ_MEM_SIZE + reg; +} + +static inline u32 sunxi_irq_cfg_offset (u16 irq) +{ +u32 irq_num = irq %IRQ_CFG_IRQ_PER_REG ; +return irq_num *IRQ_CFG_IRQ_BITS ; +} + +static inline u32 sunxi_irq_ctrl_reg_from_bank (u8 bank,unsigned bank_base) +{ +return IRQ_CTRL_REG + (bank_base + bank) *IRQ_MEM_SIZE ; +} + +static inline u32 sunxi_irq_ctrl_reg (u16 irq,unsigned bank_base) +{ +u8 bank = irq /IRQ_PER_BANK ; + +return sunxi_irq_ctrl_reg_from_bank (bank, bank_base); +} + +static inline u32 sunxi_irq_ctrl_offset (u16 irq) +{ +u32 irq_num = irq %IRQ_CTRL_IRQ_PER_REG ; +return irq_num *IRQ_CTRL_IRQ_BITS ; +} + +static inline u32 sunxi_irq_status_reg_from_bank (u8 bank,unsigned bank_base) +{ +return IRQ_STATUS_REG + (bank_base + bank) *IRQ_MEM_SIZE ; +} + +static inline u32 sunxi_irq_status_reg (u16 irq,unsigned bank_base) +{ +u8 bank = irq /IRQ_PER_BANK ; + +return sunxi_irq_status_reg_from_bank (bank, bank_base); +} + +static inline u32 sunxi_irq_status_offset (u16 irq) +{ +u32 irq_num = irq %IRQ_STATUS_IRQ_PER_REG ; +return irq_num *IRQ_STATUS_IRQ_BITS ; +} + +#ifndef __UBOOT__ +int sunxi_pinctrl_init (struct platform_device *pdev, +const struct sunxi_pinctrl_desc *desc); +#endif + +#endif /* __PINCTRL_SUNXI_H */ Signature · 1 line
1.9.1
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170222/1b5a1029/attachment.sig>
PATCH v2 1/6 sunxi: add pinctrl (UCLASS_PINCTRL) support for sunxi
Quoted 96 lines · Maxime Ripard
Quoted 67 lines · Philipp Tomsich
This change adds a full device-model pinctrl driver for sunxi (tested with sun50iw1p1) based on the support available in Linux.
Details are:
* implements a driver for pinctrl devices and assigns sun50i-a64-pinctrl and sun50i-a64-r-pinctrl to it
* dynamically creates thedriver_datafor asunxi_gpio(seesunxi_gpio.c) driver and binds it to the same device-tree node
* lifts and reuses thepinctrl-sunxi.handpinctrl-sun50i-a64.cfiles from Linux (thanks to Maxime and Andre) and adds apinctrl-sun50i-a64-r.c(to be picked up for inclusion into Linux again)Signed-off-by Philipp Tomsich <[email protected]>--- arch/arm/include/asm/arch-sunxi/gpio-internal.h | 19 + .../pinctrl/allwinner,pinctrl.txt | 65 +++ drivers/gpio/sunxi_gpio.c | 15 +- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 2 + drivers/pinctrl/sunxi/Makefile | 10 + drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c | 92 ++++ drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c | 577 +++++++++++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 317 +++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 311 +++++++++++ 10 files changed, 1411 insertions(+), 7 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/gpio-internal.h create mode 100644 doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt create mode 100644 drivers/pinctrl/sunxi/Makefile create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.harch/arm/include/asm/arch-sunxi/gpio-internal.h new file +19
-0@@ -0,0 +1,19 @@ +/* +* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + + +#ifndef _SUNXI_GPIO_INTERNAL_H +#define _SUNXI_GPIO_INTERNAL_H + +/* This data structure is shared between the sunxi_gpio driver and +* the sunxi_pinctrl driver. +*/ +struct sunxi_gpio_soc_data { +int start; +int no_banks; +}; + +#endif doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +3
-0@@ -0,0 +1,65 @@ +* Allwinner Pinmux Controller + +Allwinner integrates multiple banks (of 32 pins each) of pin-muxing,doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 13
Quoted 10 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +10
-0+GPIO functionality and (optional) external interrupt functionality +into a single controller. + +For each configurable pad (certain driver-cells, such as the IO from +integrated USB PHYs or DRAM, have a fixed function and can not be +configured), the muxing options (input, output or one of the several +functions) can be selected. + +Properties for the pinctrl node: + - compatible: should be "allwinner,sun50i-pinctrl"There's a typo here, the compatible is sun50i-a64-pinctrl
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 16
Quoted 3 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +3
-0+ - reg: address and length of the register set for the device. + - interrupts: interrupt for the device + - clocks: A phandle to the reference clock for this device(and ideally, this would take three clocks: the bus gate + the two oscillators).
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 20
Quoted 4 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +4
-0+ +Properties for the pinconfig sub-nodes: + - allwinner,pins: a list of pins (e.g. "PH2", "PH3") to configure + - allwinner,function: the name of pinmux function (e.g. "mmc2")allwinner,pins and allwinner,function are also deprecated in favour of pins and function.
Quoted 6 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 24
Quoted 4 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +4
-0+ - drive-strength: a drive-stength setting of 10, 20, 30 or 40 mA + - bias-pull-up + - bias-pull-down + - bias-disable (default)The default is not bias-disable, but to keep the current configuration
Shouldn't we just copy the binding docs from the Linux kernel? Afterall they are supposed to be the same.
ChenYu
Quoted 1,473 lines
Quoted 1,466 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +41
-0+ +Deprecated properties for the pinconfig sub-nodes: + - allwinner,drive: one of <SUN4I_PINCTRL_10_MA>, <SUN4I_PINCTRL_20_MA>, + <SUN4I_PINCTRL_30_MA> or <SUN4I_PINCTRL_40_MA> + - allwinner,pull: one of <SUN4I_PINCTRL_NO_PULL>, <SUN4I_PINCTRL_PULL_UP> + or <SUN4I_PINCTRL_PULL_DOWN> + +Example: + + pio: pinctrl at 1c20800 { + compatible = "allwinner,sun50i-a64-pinctrl"; + reg = <0x01c20800 0x400>; + + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bus_gates 69>; + + gpio-controller; + #gpio-cells = <3>; + + interrupt-controller; + #interrupt-cells = <2>; + + #address-cells = <1>; + #size-cells = <1>; + + uart0_pins_a: uart0_pins_a { + allwinner,pins = "PB8", "PB9"; + allwinner,function = "uart0"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + + uart0_pins_b: uart0_pins_b { + allwinner,pins = "PF2", "PF3"; + allwinner,function = "uart0"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + };drivers/gpio/sunxi_gpio.c +8
-7@@ -16,6 +16,7 @@#include <fdtdec.h> #include <malloc.h> #include <asm/arch/gpio.h> +#include <asm/arch/gpio-internal.h> #include <asm/io.h> #include <asm/gpio.h> #include <dm/device-internal.h> @@ -275,11 +276,6 @@ static int gpio_sunxi_probe(struct udevice *dev)return 0 ; } -struct sunxi_gpio_soc_data { -int start; -int no_banks; -}; -/** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Sunxi bank. @@ -353,18 +349,22 @@ static const struct udevice_id sunxi_gpio_ids[] = {ID ("allwinner,sun8i-a83t-pinctrl" , a_all),ID ("allwinner,sun8i-h3-pinctrl" , a_all),ID ("allwinner,sun9i-a80-pinctrl" , a_all), +#if !defined(CONFIG_SUNXI_PINCTRL)/* This is not strictly correct for the A64, as it is missing * bank 'A'. Yet, the register layout in the pinctrl block is * backward compatible and any accesses to the registers that * normally control bank 'A' will have no adverse effect. */ -ID ("allwinner,sun50i-a64-pinctrl" , a_all), +ID ("allwinner,sun50i-a64-pinctrl" , a_all), +#endifID ("allwinner,sun6i-a31-r-pinctrl" , l_2),ID ("allwinner,sun8i-a23-r-pinctrl" , l_1),ID ("allwinner,sun8i-a83t-r-pinctrl" , l_1),ID ("allwinner,sun8i-h3-r-pinctrl" , l_1),ID ("allwinner,sun9i-a80-r-pinctrl" , l_3), - ID("allwinner,sun50i-a64-r-pinctrl", l_1), +#if !defined(CONFIG_SUNXI_PINCTRL) + ID("allwinner,sun50i-a64-r-pinctrl", l_1), +#endif { } };@@ -376,4 +376,5 @@ U_BOOT_DRIVER(gpio_sunxi) = { .bind = gpio_sunxi_bind, .probe = gpio_sunxi_probe, }; +#endif drivers/pinctrl/Kconfig +10
-0@@ -175,6 +175,16 @@ config PIC32_PINCTRL by a device tree node which contains both GPIO defintion and pin control functions. +config SUNXI_PINCTRL + bool "Allwinner Axx pin-control and pin-mux driver" + depends on DM && ARCH_SUNXI + default y + help + Supports pin multiplexing control, drive-strength and bias control on + Allwinner Axx SoCs. The driver is controlled by a device tree node which + contains both the GPIO definitions and the pin control functions for + each multiplex function. + endif source "drivers/pinctrl/meson/Kconfig"drivers/pinctrl/Makefile +2
-0@@ -16,3 +16,5 @@ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ + +obj-$(CONFIG_ARCH_SUNXI) += sunxi/drivers/pinctrl/sunxi/Makefile new file +10
-0@@ -0,0 +1,10 @@ +# +# Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_SUNXI_PINCTRL) += pinctrl-sunxi.o +ifdef CONFIG_SUNXI_PINCTRL +obj-$(CONFIG_MACH_SUN50I) += pinctrl-sun50i-a64.o pinctrl-sun50i-a64-r.o +endifdrivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c new file +92
-0@@ -0,0 +1,92 @@ +/* +* Allwinner A64 SoCs pinctrl driver. +* +* Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH. +* +* Based on pinctrl-sun7i-a20.c, which is: +* Copyright (C) 2014 Maxime Ripard <[email protected]> +* +* 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 <common.h> + +#include "pinctrl-sunxi.h" + +static const struct sunxi_desc_pin a64_r_pins[] = { +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_rsb" ),/* SCK */ +SUNXI_FUNCTION (0x3 ,"s_i2c" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_rsb" ),/* SDA */ +SUNXI_FUNCTION (0x3 ,"s_i2c" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_uart" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_uart" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* MS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* CK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* DO */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_jtag" ),/* DI */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_i2c" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_i2c" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,9 )),/* EINT9 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_pwm" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,10 )),/* EINT10 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"s_cir" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,11 )),/* EINT11 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (L ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,12 )),/* EINT12 */ +}; + +const struct sunxi_pinctrl_desc a64_r_pinctrl_data = { + .pins = a64_r_pins, + .npins =ARRAY_SIZE (a64_r_pins), + .pin_base =PL_BASE , + .irq_banks =1 , +};drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c new file +577
-0@@ -0,0 +1,577 @@ +/* +* Allwinner A64 SoCs pinctrl driver. +* +* Copyright (C) 2016 - ARM Ltd. +* Author: Andre Przywara <[email protected]> +* +* Based on pinctrl-sun7i-a20.c, which is: +* Copyright (C) 2014 Maxime Ripard <[email protected]> +* +* 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 <common.h> + +#include "pinctrl-sunxi.h" + +static const struct sunxi_desc_pin a64_pins[] = { +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* TX */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* MS0 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* RX */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* CK0 */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* VCCEN */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* RTS */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* DO0 */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* VPPEN */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart2" ),/* CTS */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* MCLK */ +SUNXI_FUNCTION (0x4 ,"jtag" ),/* DI0 */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* VPPPP */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* SYNC */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* SYNC */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* CLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* BCLK */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* BCLK */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* DATA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* DOUT */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* DOUT */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* RST */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif2" ),/* DIN */ +SUNXI_FUNCTION (0x3 ,"i2s0" ),/* DIN */ +SUNXI_FUNCTION (0x5 ,"sim" ),/* DET */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x4 ,"uart0" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (B ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x4 ,"uart0" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,0 ,9 )),/* EINT9 */ +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NWE */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* MOSI */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NALE */ +SUNXI_FUNCTION (0x3 ,"mmc2" ),/* DS */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* MISO */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NCLE */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* SCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NCE1 */ +SUNXI_FUNCTION (0x4 ,"spi0" )),/* CS */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" )),/* NCE0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NRE# */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* CLK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NRB0 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* CMD */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" )),/* NRB1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ0 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ1 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ2 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ3 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ4 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ5 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,14 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ6 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,15 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQ7 */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* D7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (C ,16 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"nand0" ),/* NDQS */ +SUNXI_FUNCTION (0x3 ,"mmc2" )),/* RST */ +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D2 */ +SUNXI_FUNCTION (0x3 ,"uart3" ),/* TX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* CS */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* CLK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D3 */ +SUNXI_FUNCTION (0x3 ,"uart3" ),/* RX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* CLK */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* DE */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D4 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* TX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* MOSI */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* HSYNC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D5 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* RX */ +SUNXI_FUNCTION (0x4 ,"spi1" ),/* MISO */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* VSYNC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D6 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* RTS */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D7 */ +SUNXI_FUNCTION (0x3 ,"uart4" ),/* CTS */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D10 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D11 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D12 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ERXD3 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D13 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ERXD2 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D14 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXD1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D15 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXD0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D18 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP0 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D19 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN0 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ERXCTL */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,14 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D20 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP1 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ENULL */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,15 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D21 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN1 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ETXD3 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,16 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D22 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP2 */ +SUNXI_FUNCTION (0x4 ,"emac" ),/* ETXD2 */ +SUNXI_FUNCTION (0x5 ,"ccir" )),/* D7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,17 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* D23 */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN2 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXD1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,18 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* CLK */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VPC */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXD0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,19 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* DE */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VNC */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,20 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* HSYNC */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VP3 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ETXCTL */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,21 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"lcd0" ),/* VSYNC */ +SUNXI_FUNCTION (0x3 ,"lvds0" ),/* VN3 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* ECLKIN */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,22 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"pwm" ),/* PWM0 */ +SUNXI_FUNCTION (0x4 ,"emac" )),/* EMDC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,23 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x4 ,"emac" )),/* EMDIO */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (D ,24 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* PCK */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* CLK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* CK */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* ERR */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* HSYNC */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* SYNC */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* VSYNC */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* DVLD */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D0 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D1 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D2 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D3 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D4 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D5 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D6 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" ),/* D7 */ +SUNXI_FUNCTION (0x4 ,"ts0" )),/* D7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" )),/* SCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"csi0" )),/* SDA */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,14 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"pll" ),/* LOCK_DBG */ +SUNXI_FUNCTION (0x3 ,"i2c2" )),/* SCK */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,15 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x3 ,"i2c2" )),/* SDA */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,16 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +SUNXI_PIN (SUNXI_PINCTRL_PIN (E ,17 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D1 */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* MSI */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D0 */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* DI1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* CLK */ +SUNXI_FUNCTION (0x3 ,"uart0" )),/* TX */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* CMD */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* DO1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D3 */ +SUNXI_FUNCTION (0x4 ,"uart0" )),/* RX */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc0" ),/* D2 */ +SUNXI_FUNCTION (0x3 ,"jtag" )),/* CK1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (F ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" )), +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* CLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* CMD */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D0 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D1 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D2 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mmc1" ),/* D3 */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* RTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart1" ),/* CTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,9 )),/* EINT9 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* SYNC */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* SYNC */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,10 )),/* EINT10 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* BCLK */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* BCLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,11 )),/* EINT11 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,12 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* DOUT */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* DOUT */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,12 )),/* EINT12 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (G ,13 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"aif3" ),/* DIN */ +SUNXI_FUNCTION (0x3 ,"i2s1" ),/* DIN */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,1 ,13 )),/* EINT13 */ +/* Hole */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,0 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c0" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,0 )),/* EINT0 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,1 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c0" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,1 )),/* EINT1 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,2 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c1" ),/* SCK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,2 )),/* EINT2 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,3 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"i2c1" ),/* SDA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,3 )),/* EINT3 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,4 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* TX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,4 )),/* EINT4 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,5 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* RX */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,5 )),/* EINT5 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,6 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* RTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,6 )),/* EINT6 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,7 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"uart3" ),/* CTS */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,7 )),/* EINT7 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,8 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"spdif" ),/* OUT */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,8 )),/* EINT8 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,9 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,9 )),/* EINT9 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,10 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mic" ),/* CLK */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,10 )),/* EINT10 */ +SUNXI_PIN (SUNXI_PINCTRL_PIN (H ,11 ), +SUNXI_FUNCTION (0x0 ,"gpio_in" ), +SUNXI_FUNCTION (0x1 ,"gpio_out" ), +SUNXI_FUNCTION (0x2 ,"mic" ),/* DATA */ +SUNXI_FUNCTION_IRQ_BANK (0x6 ,2 ,11 )),/* EINT11 */ +}; + +const struct sunxi_pinctrl_desc a64_pinctrl_data = { + .pins = a64_pins, + .npins =ARRAY_SIZE (a64_pins), + .irq_banks =3 , +};drivers/pinctrl/sunxi/pinctrl-sunxi.c new file +317
-0@@ -0,0 +1,317 @@ +/* +* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +* +* In parts based on linux/drivers/pinctrl/pinctrl-sunxi.c, which is +* Copyright (C) 2012 Maxime Ripard +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <syscon.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/gpio.h> +#include <asm/arch/gpio-internal.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <dt-bindings/pinctrl/sun4i-a10.h> +#include <dt-bindings/gpio/gpio.h> +#include <linux/kernel.h> +#include "pinctrl-sunxi.h" + +DECLARE_GLOBAL_DATA_PTR ; + +struct sunxi_pctrl_priv { +void *base; +#if defined(CONFIG_DM_GPIO ) +struct sunxi_gpio_soc_data gpio_soc_data; +struct udevice *gpio_dev; +#endif +}; + +static int sunxi_pctrl_parse_drive_prop (const void *blob,int node) +{ +int val; + +/* Try the new style binding */ + val =fdtdec_get_int (blob, node,"drive-strength" , -EINVAL ); +if (val >=0 ) { +/* We can't go below 10mA ... */ +if (val <10 ) +return -EINVAL ; + +/* ... and only up to 40 mA ... */ +if (val >40 ) + val =40 ; + +/* by steps of 10 mA */ +return rounddown (val,10 ); + } + +/* And then fall back to the old binding */ + val =fdtdec_get_int (blob, node,"allwinner,drive" , -EINVAL ); +if (val <0 ) +return -EINVAL ; + +return (val +1 ) *10 ; +} + +static int sunxi_pctrl_parse_bias_prop (const void *blob,int node) +{ +/* Try the new style binding */ +if (fdtdec_get_bool (blob, node,"bias-pull-up" )) +return SUN4I_PINCTRL_PULL_UP ; + +if (fdtdec_get_bool (blob, node,"bias-pull-down" )) +return SUN4I_PINCTRL_PULL_DOWN ; + +if (fdtdec_get_bool (blob, node,"bias-disable" )) +return SUN4I_PINCTRL_NO_PULL ; + +/* And fall back to the old binding */ +return fdtdec_get_int (blob, node,"allwinner,pull" , -EINVAL ); +} + +static const struct sunxi_desc_pin *sunxi_pctrl_pin_by_name (struct udevice *dev, +const char *name) +{ +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +int i; + +for (i =0 ; i < data->npins; ++i) +if (!strcmp (data->pins[i].pin.name, name)) +return &data->pins[i]; + +return NULL ; +} + +static int sunxi_pctrl_muxval_by_name (const struct sunxi_desc_pin *pin, +const char *name) +{ +const struct sunxi_desc_function *func; + +if (!pin) +return -EINVAL ; + +for (func = pin->functions; func->name; func++) +if (!strcmp (func->name, name)) +return func->muxval; + +return -ENOENT ; +} + +static void sunxi_pctrl_set_function (struct udevice *dev, +unsigned pin,int function) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +u32 val, mask; + +if (function <0 ) +return ; + + pin -= data->pin_base; + mask =MUX_PINS_MASK <<sunxi_mux_offset (pin); + val = function <<sunxi_mux_offset (pin); +clrsetbits_le32 (priv->base +sunxi_mux_reg (pin), mask, val); +} + +static void sunxi_pctrl_set_dlevel (struct udevice *dev, +unsigned pin,int dlevel) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +u32 val, mask; + +if (dlevel <0 ) +return ; + + pin -= data->pin_base; + mask =DLEVEL_PINS_MASK <<sunxi_dlevel_offset (pin); + val = dlevel <<sunxi_dlevel_offset (pin); +clrsetbits_le32 (priv->base +sunxi_dlevel_reg (pin), mask, val); +} + +static void sunxi_pctrl_set_bias (struct udevice *dev, +unsigned pin,int bias) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +u32 val, mask; + +if (bias <0 ) +return ; + + pin -= data->pin_base; + mask =PULL_PINS_MASK <<sunxi_pull_offset (pin); + val = bias <<sunxi_pull_offset (pin); +clrsetbits_le32 (priv->base +sunxi_pull_reg (pin), mask, val); +} + +static int sunxi_pctrl_set_state (struct udevice *dev,struct udevice *config) +{ +const char *pins; +const char *function; +int flen; +int len, curr_len; +int drive, bias; +int muxval; + +debug ("%s: %s %s\n" , __func__, dev->name, config->name); + + pins =fdt_getprop (gd->fdt_blob, config->of_offset, +"allwinner,pins" , &len); +if (!pins) { +debug ("%s: missing allwinner,pins property in node %s\n" , + dev->name, config->name); +return -EINVAL ; + } + + function =fdt_getprop (gd->fdt_blob, config->of_offset, +"allwinner,function" , &flen); +if (!function) { +debug ("%s: missing allwinner,function property in node %s\n" , + dev->name, config->name); +return -EINVAL ; + } + + drive =sunxi_pctrl_parse_drive_prop (gd->fdt_blob, config->of_offset); + bias =sunxi_pctrl_parse_bias_prop (gd->fdt_blob, config->of_offset); + +debug ("%s: function %s, drive %d, bias %d\n" , + config->name, function, drive, bias); + +/* Iterate through the pins and configure each */ +while (len && (curr_len =strnlen (pins, len))) { +const struct sunxi_desc_pin *pin; + +if (curr_len == len) { +error ("%s: unterminated string?" , __func__); +break ; + } + + pin =sunxi_pctrl_pin_by_name (dev, pins); +if (pin) { + muxval =sunxi_pctrl_muxval_by_name (pin, function); + +sunxi_pctrl_set_function (dev, pin->pin.number, muxval); +sunxi_pctrl_set_dlevel (dev, pin->pin.number, drive); +sunxi_pctrl_set_bias (dev, pin->pin.number, bias); + }else { +debug ("%s: could not find pin %s\n" , dev->name, pins); + } + +/* advance */ + pins += (curr_len +1 ); + len -= (curr_len +1 ); + } + +return 0 ; +} + +static inline void soc_data_from_desc (const struct sunxi_pinctrl_desc *data, +struct sunxi_gpio_soc_data *soc_data) +{ +int i; +unsigned pinnum; +unsigned low = data->pin_base /PINS_PER_BANK ; +unsigned high = data->pin_base; + +for (i =0 ; i < data->npins; ++i) { + pinnum = data->pins[i].pin.number; + high =max (high, pinnum); + } + +/* convert pin-numbers to bank numbers */ + high /=PINS_PER_BANK ; + + soc_data->start = low; + soc_data->no_banks = high - low +1 ; +} + +static int sunxi_pctrl_bind_gpio (struct udevice *dev) +{ +#if defined(CONFIG_DM_GPIO ) +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +const struct sunxi_pinctrl_desc *data = + (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev); +struct driver *gpio_driver; +char name[20 ]; +int ret; + +/* Fill the soc_data for the gpio driver from the pinctrl_desc */ +soc_data_from_desc (data, &priv->gpio_soc_data); + + gpio_driver =lists_driver_lookup_name ("gpio_sunxi" ); +if (!gpio_driver) +return -ENOENT ; + + ret =device_bind_with_driver_data (dev, gpio_driver,"sunxi_gpio" , + (ulong)&priv->gpio_soc_data, + dev->of_offset, &priv->gpio_dev); + +if (ret <0 ) +return ret; + +snprintf (name,sizeof (name),"sunxi_gpio@%x" , (uint32_t )priv->base); +device_set_name (priv->gpio_dev, name); +#endif + +return 0 ; +} + +static int sunxi_pctrl_probe (struct udevice *dev) +{ +struct sunxi_pctrl_priv *priv =dev_get_priv (dev); +fdt_addr_t addr_base; +fdt_size_t size; + + addr_base =fdtdec_get_addr_size_auto_noparent (gd->fdt_blob, + dev->of_offset, +"reg" ,0 , &size, + false); +if (addr_base ==FDT_ADDR_T_NONE ) +return -EINVAL ; + + priv->base = (void *)addr_base; + +return sunxi_pctrl_bind_gpio (dev); +} + +static struct pinctrl_ops sunxi_pctrl_ops = { + .set_state = sunxi_pctrl_set_state, +}; + +#if defined(CONFIG_MACH_SUN50I ) +extern const struct sunxi_pinctrl_desc a64_pinctrl_data; +extern const struct sunxi_pinctrl_desc a64_r_pinctrl_data; +#endif + +static const struct udevice_id sunxi_pctrl_ids[] = { +#if defined(CONFIG_MACH_SUN50I) + { .compatible ="allwinner,sun50i-a64-pinctrl" , + .data = (ulong)&a64_pinctrl_data }, + { .compatible ="allwinner,sun50i-a64-r-pinctrl" , + .data = (ulong)&a64_r_pinctrl_data }, +#endif + { } +}; + +U_BOOT_DRIVER (pinctrl_sunxi) = { + .name ="sunxi_pctrl" , + .id =UCLASS_PINCTRL , + .of_match = sunxi_pctrl_ids, + .priv_auto_alloc_size =sizeof (struct sunxi_pctrl_priv ), + .ops = &sunxi_pctrl_ops, + .bind = dm_scan_fdt_dev, + .probe = sunxi_pctrl_probe, +}; +drivers/pinctrl/sunxi/pinctrl-sunxi.h new file +311
-1@@ -0,0 +1,311 @@ +/* +* Allwinner A1X SoCs pinctrl driver. +* +* Copyright (C) 2012 Maxime Ripard +* +* Maxime Ripard <[email protected]> +* +* 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. +*/ + +#ifndef __PINCTRL_SUNXI_H +#define __PINCTRL_SUNXI_H + +#define PA_BASE 0 +#define PB_BASE 32 +#define PC_BASE 64 +#define PD_BASE 96 +#define PE_BASE 128 +#define PF_BASE 160 +#define PG_BASE 192 +#define PH_BASE 224 +#define PI_BASE 256 +#define PL_BASE 352 +#define PM_BASE 384 +#define PN_BASE 416 + +#ifdef __UBOOT__ +/* Convenience macro to define a single named or anonymous pin descriptor */ +#define PINCTRL_PIN (a, b) { .number = a, .name = b } + +/** +* struct pinctrl_pin_desc - boards/machines provide information on their +* pins, pads or other muxable units in this struct +* @number: unique pin number from the global pin number space +* @name: a name for this pin +* @drv_data: driver-defined per-pin data. pinctrl core does not touch this +*/ +struct pinctrl_pin_desc { +unsigned number; +const char *name; +#ifndef __UBOOT__ +void *drv_data; +#endif +}; +#endif + +#define SUNXI_PINCTRL_PIN (bank, pin) \ + PINCTRL_PIN(P ## bank ## _BASE + (pin), "P" #bank #pin) + +#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 + +#define PINS_PER_BANK 32 +#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 +#define PULL_PINS_PER_REG 16 +#define PULL_PINS_BITS 2 +#define PULL_PINS_MASK 0x03 + +#define IRQ_PER_BANK 32 + +#define IRQ_CFG_REG 0x200 +#define IRQ_CFG_IRQ_PER_REG 8 +#define IRQ_CFG_IRQ_BITS 4 +#define IRQ_CFG_IRQ_MASK ((1 << IRQ_CFG_IRQ_BITS) - 1) +#define IRQ_CTRL_REG 0x210 +#define IRQ_CTRL_IRQ_PER_REG 32 +#define IRQ_CTRL_IRQ_BITS 1 +#define IRQ_CTRL_IRQ_MASK ((1 << IRQ_CTRL_IRQ_BITS) - 1) +#define IRQ_STATUS_REG 0x214 +#define IRQ_STATUS_IRQ_PER_REG 32 +#define IRQ_STATUS_IRQ_BITS 1 +#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1) + +#define IRQ_MEM_SIZE 0x20 + +#define IRQ_EDGE_RISING 0x00 +#define IRQ_EDGE_FALLING 0x01 +#define IRQ_LEVEL_HIGH 0x02 +#define IRQ_LEVEL_LOW 0x03 +#define IRQ_EDGE_BOTH 0x04 + +#define SUN4I_FUNC_INPUT 0 +#define SUN4I_FUNC_IRQ 6 + +struct sunxi_desc_function { +const char *name; +u8 muxval; +u8 irqbank; +u8 irqnum; +}; + +struct sunxi_desc_pin { +struct pinctrl_pin_desc pin; +struct sunxi_desc_function *functions; +}; + +struct sunxi_pinctrl_desc { +const struct sunxi_desc_pin *pins; +int npins; +unsigned pin_base; +unsigned irq_banks; +unsigned irq_bank_base; +bool irq_read_needs_mux; +}; + +struct sunxi_pinctrl_function { +const char *name; +const char **groups; +unsigned ngroups; +}; + +struct sunxi_pinctrl_group { +const char *name; +unsigned long config; +unsigned pin; +}; + +#ifndef __UBOOT__ +struct sunxi_pinctrl { +void __iomem *membase; +struct gpio_chip *chip; +const struct sunxi_pinctrl_desc *desc; +struct device *dev; +struct irq_domain *domain; +struct sunxi_pinctrl_function *functions; +unsigned nfunctions; +struct sunxi_pinctrl_group *groups; +unsigned ngroups; +int *irq; +unsigned *irq_array; +spinlock_t lock; +struct pinctrl_dev *pctl_dev; +}; +#endif + +#define SUNXI_PIN (_pin, ...) \ + { \ + .pin = _pin, \ + .functions = (struct sunxi_desc_function[]){ \ + __VA_ARGS__, { } }, \ + } + +#define SUNXI_FUNCTION (_val, _name) \ + { \ + .name = _name, \ + .muxval = _val, \ + } + +#define SUNXI_FUNCTION_IRQ (_val, _irq) \ + { \ + .name = "irq", \ + .muxval = _val, \ + .irqnum = _irq, \ + } + +#define SUNXI_FUNCTION_IRQ_BANK (_val, _bank, _irq) \ + { \ + .name = "irq", \ + .muxval = _val, \ + .irqbank = _bank, \ + .irqnum = _irq, \ + } + +/* +* The sunXi PIO registers are organized as is: +* 0x00 - 0x0c Muxing values. +* 8 pins per register, each pin having a 4bits value +* 0x10 Pin values +* 32 bits per register, each pin corresponding to one bit +* 0x14 - 0x18 Drive level +* 16 pins per register, each pin having a 2bits value +* 0x1c - 0x20 Pull-Up values +* 16 pins per register, each pin having a 2bits value +* +* This is for the first bank. Each bank will have the same layout, +* with an offset being a multiple of 0x24. +* +* The following functions calculate from the pin number the register +* and the bit offset that we should access. +*/ +static inline u32 sunxi_mux_reg (u16 pin) +{ +u8 bank = pin /PINS_PER_BANK ; +u32 offset = bank *BANK_MEM_SIZE ; + offset +=MUX_REGS_OFFSET ; + offset += pin %PINS_PER_BANK /MUX_PINS_PER_REG *0x04 ; +return round_down (offset,4 ); +} + +static inline u32 sunxi_mux_offset (u16 pin) +{ +u32 pin_num = pin %MUX_PINS_PER_REG ; +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 ; +u32 offset = bank *BANK_MEM_SIZE ; + offset +=DLEVEL_REGS_OFFSET ; + offset += pin %PINS_PER_BANK /DLEVEL_PINS_PER_REG *0x04 ; +return round_down (offset,4 ); +} + +static inline u32 sunxi_dlevel_offset (u16 pin) +{ +u32 pin_num = pin %DLEVEL_PINS_PER_REG ; +return pin_num *DLEVEL_PINS_BITS ; +} + +static inline u32 sunxi_pull_reg (u16 pin) +{ +u8 bank = pin /PINS_PER_BANK ; +u32 offset = bank *BANK_MEM_SIZE ; + offset +=PULL_REGS_OFFSET ; + offset += pin %PINS_PER_BANK /PULL_PINS_PER_REG *0x04 ; +return round_down (offset,4 ); +} + +static inline u32 sunxi_pull_offset (u16 pin) +{ +u32 pin_num = pin %PULL_PINS_PER_REG ; +return pin_num *PULL_PINS_BITS ; +} + +static inline u32 sunxi_irq_cfg_reg (u16 irq,unsigned bank_base) +{ +u8 bank = irq /IRQ_PER_BANK ; +u8 reg = (irq %IRQ_PER_BANK ) /IRQ_CFG_IRQ_PER_REG *0x04 ; + +return IRQ_CFG_REG + (bank_base + bank) *IRQ_MEM_SIZE + reg; +} + +static inline u32 sunxi_irq_cfg_offset (u16 irq) +{ +u32 irq_num = irq %IRQ_CFG_IRQ_PER_REG ; +return irq_num *IRQ_CFG_IRQ_BITS ; +} + +static inline u32 sunxi_irq_ctrl_reg_from_bank (u8 bank,unsigned bank_base) +{ +return IRQ_CTRL_REG + (bank_base + bank) *IRQ_MEM_SIZE ; +} + +static inline u32 sunxi_irq_ctrl_reg (u16 irq,unsigned bank_base) +{ +u8 bank = irq /IRQ_PER_BANK ; + +return sunxi_irq_ctrl_reg_from_bank (bank, bank_base); +} + +static inline u32 sunxi_irq_ctrl_offset (u16 irq) +{ +u32 irq_num = irq %IRQ_CTRL_IRQ_PER_REG ; +return irq_num *IRQ_CTRL_IRQ_BITS ; +} + +static inline u32 sunxi_irq_status_reg_from_bank (u8 bank,unsigned bank_base) +{ +return IRQ_STATUS_REG + (bank_base + bank) *IRQ_MEM_SIZE ; +} + +static inline u32 sunxi_irq_status_reg (u16 irq,unsigned bank_base) +{ +u8 bank = irq /IRQ_PER_BANK ; + +return sunxi_irq_status_reg_from_bank (bank, bank_base); +} + +static inline u32 sunxi_irq_status_offset (u16 irq) +{ +u32 irq_num = irq %IRQ_STATUS_IRQ_PER_REG ; +return irq_num *IRQ_STATUS_IRQ_BITS ; +} + +#ifndef __UBOOT__ +int sunxi_pinctrl_init (struct platform_device *pdev, +const struct sunxi_pinctrl_desc *desc); +#endif + +#endif /* __PINCTRL_SUNXI_H */ --Quoted 2 lines
1.9.1
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
PATCH v2 1/6 sunxi: add pinctrl (UCLASS_PINCTRL) support for sunxi
Quoted 103 lines · Chen-Yu Tsai
Quoted 101 lines · Maxime Ripard
Quoted 67 lines · Philipp Tomsich
This change adds a full device-model pinctrl driver for sunxi (tested with sun50iw1p1) based on the support available in Linux.
Details are:
* implements a driver for pinctrl devices and assigns sun50i-a64-pinctrl and sun50i-a64-r-pinctrl to it
* dynamically creates thedriver_datafor asunxi_gpio(seesunxi_gpio.c) driver and binds it to the same device-tree node
* lifts and reuses thepinctrl-sunxi.handpinctrl-sun50i-a64.cfiles from Linux (thanks to Maxime and Andre) and adds apinctrl-sun50i-a64-r.c(to be picked up for inclusion into Linux again)Signed-off-by Philipp Tomsich <[email protected]>--- arch/arm/include/asm/arch-sunxi/gpio-internal.h | 19 + .../pinctrl/allwinner,pinctrl.txt | 65 +++ drivers/gpio/sunxi_gpio.c | 15 +- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 2 + drivers/pinctrl/sunxi/Makefile | 10 + drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c | 92 ++++ drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c | 577 +++++++++++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 317 +++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 311 +++++++++++ 10 files changed, 1411 insertions(+), 7 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/gpio-internal.h create mode 100644 doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt create mode 100644 drivers/pinctrl/sunxi/Makefile create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64-r.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.c create mode 100644 drivers/pinctrl/sunxi/pinctrl-sunxi.harch/arm/include/asm/arch-sunxi/gpio-internal.h new file +19
-0@@ -0,0 +1,19 @@ +/* +* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + + +#ifndef _SUNXI_GPIO_INTERNAL_H +#define _SUNXI_GPIO_INTERNAL_H + +/* This data structure is shared between the sunxi_gpio driver and +* the sunxi_pinctrl driver. +*/ +struct sunxi_gpio_soc_data { +int start; +int no_banks; +}; + +#endif doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +3
-0@@ -0,0 +1,65 @@ +* Allwinner Pinmux Controller + +Allwinner integrates multiple banks (of 32 pins each) of pin-muxing,doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 13
Quoted 10 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +10
-0+GPIO functionality and (optional) external interrupt functionality +into a single controller. + +For each configurable pad (certain driver-cells, such as the IO from +integrated USB PHYs or DRAM, have a fixed function and can not be +configured), the muxing options (input, output or one of the several +functions) can be selected. + +Properties for the pinctrl node: + - compatible: should be "allwinner,sun50i-pinctrl"There's a typo here, the compatible is sun50i-a64-pinctrl
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 16
Quoted 3 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +3
-0+ - reg: address and length of the register set for the device. + - interrupts: interrupt for the device + - clocks: A phandle to the reference clock for this device(and ideally, this would take three clocks: the bus gate + the two oscillators).
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt line 20
Quoted 4 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +4
-0+ +Properties for the pinconfig sub-nodes: + - allwinner,pins: a list of pins (e.g. "PH2", "PH3") to configure + - allwinner,function: the name of pinmux function (e.g. "mmc2")allwinner,pins and allwinner,function are also deprecated in favour of pins and function.
Quoted 4 lines
doc/device-tree-bindings/pinctrl/allwinner,pinctrl.txt new file +4
-0+ - drive-strength: a drive-stength setting of 10, 20, 30 or 40 mA + - bias-pull-up + - bias-pull-down + - bias-disable (default)
Quoted 4 lines
Quoted 1 line
The default is not bias-disable, but to keep the current configuration
Shouldn't we just copy the binding docs from the Linux kernel? Afterall they are supposed to be the same.
Yep, that would probably be the easiest.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170223/ccf5b85f/attachment-0001.sig>
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
In reply to Philipp TomsichCurrently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need to bind against a single node
* clock (UCLASS_CLK) and reset (UCLASS_RESET) drivers also need to bind against a single node
--- drivers/core/Kconfig | 14 ++++++++++++++ drivers/core/lists.c | 12 +++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-)
drivers/core/Kconfig +14 -0
@@ -31,6 +31,20 @@ config DM_WARN This will cause dm_warn() to be compiled out - it will do nothing when called. +config DM_ALLOW_MULTIPLE_DRIVERS + bool "Allow multiple drivers to bind for one node" + depends on DM + default n + help + The driver model in U-Boot originally did not allow multiple + drivers to bind for a single device node. + + If enabled, multiple drivers can now bind for a single node + by using the same compatible string for matching: lists_bind_fdt() + will assume that binding multiple drivers is desirable, if the + caller does not request the pointer to the udevice structure to + be returned (i.e. if devp is NULL). + config DM_DEVICE_REMOVE bool "Support device removal" depends on DM
drivers/core/lists.c +11 -1
@@ -166,7 +166,11 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,dm_dbg (" - attempt to match compatible string '%s'\n" , compat); -for (entry = driver; entry != driver + n_ents; entry++) { + entry = driver; +#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS ) + allow_more_matches: +#endif +for (; entry != driver + n_ents; entry++) { ret =driver_check_compatible (entry->of_match, &id, compat);if (!ret)
@@ -190,6 +194,12 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, found = true;if (devp) *devp = dev; +#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS ) + else { + entry++; + goto allow_more_matches; + } +#endif }break ; }
Signature · 1 line
1.9.1
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
Hi Philipp,
Quoted 6 lines · Philipp Tomsich
Currently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
Quoted 6 lines
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need to bind against a single node
* clock (UCLASS_CLK) and reset (UCLASS_RESET) drivers also need to bind against a single node
Does linux work this way? Another approach would be to have a separate MISC driver with two children, one pinctrl, one clk.
Quoted 12 lines
Signed-off-by Philipp Tomsich <[email protected]>--- drivers/core/Kconfig | 14 ++++++++++++++ drivers/core/lists.c | 12 +++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-)drivers/core/Kconfig +0
-0
drivers/core/Kconfig config DM_WARN · line 37
Quoted 7 lines
drivers/core/Kconfig +4
-0@@ -31,6 +31,20 @@ config DM_WARN This will cause dm_warn() to be compiled out - it will do nothing when called. +config DM_ALLOW_MULTIPLE_DRIVERS + bool "Allow multiple drivers to bind for one node" + depends on DM + default n
You should be able to drop this line.
drivers/core/Kconfig config DM_WARN · line 46
Quoted 9 lines
drivers/core/Kconfig +9
-0+ help + The driver model in U-Boot originally did not allow multiple + drivers to bind for a single device node. + + If enabled, multiple drivers can now bind for a single node + by using the same compatible string for matching: lists_bind_fdt() + will assume that binding multiple drivers is desirable, if the + caller does not request the pointer to the udevice structure to + be returned (i.e. if devp is NULL).
Please update the function documentation in the header file.
Quoted 22 lines
drivers/core/Kconfig +1
-0+ config DM_DEVICE_REMOVE bool "Support device removal" depends on DMdrivers/core/lists.c +5
-1@@ -166,7 +166,11 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,dm_dbg (" - attempt to match compatible string '%s'\n" , compat); -for (entry = driver; entry != driver + n_ents; entry++) { + entry = driver; +#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS ) + allow_more_matches: +#endif +for (; entry != driver + n_ents; entry++) { ret =driver_check_compatible (entry->of_match, &id, compat);if (!ret)
drivers/core/lists.c int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, · line 197
Quoted 4 lines
drivers/core/lists.c +1
-0@@ -190,6 +194,12 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, found = true;if (devp) *devp = dev; +#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS )
Can you make this a variable, e.g. with allow_multiple = IS_ENABLED(DM_ALLOW_MULTIPLE_DRIVERS)? I'd prefer not to add #ifdefs in this file.
drivers/core/lists.c int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, · line 200
Quoted 3 lines
drivers/core/lists.c +3
-0+else { + entry++; + goto allow_more_matches;
Is it possible to loop without using goto?
Quoted 8 lines
drivers/core/lists.c +2
-1+ } +#endif }break ; } --1.9.1
Regards,
Simon
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
Hi Simon,
Quoted 19 lines · Simon Glass
Hi Philipp,
Quoted 6 lines · On 22 February 2017 at 13:47, Philipp Tomsich <philipp.tomsich at…
Currently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
Quoted 6 lines
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need to bind against a single node
* clock (UCLASS_CLK) and reset (UCLASS_RESET) drivers also need to bind against a single node
Quoted 2 lines
Does linux work this way? Another approach would be to have a separate MISC driver with two children, one pinctrl, one clk.
The linux CLK driver creates and registers a reset-controller; the PINCTRL driver does the same with the gpio-controller. Similar code to do this is easily possible in U-Boot … see sunxi_pctrl_bind_gpio(…) in [PATCH v2 1/6] of this series.
However, binding multiple times makes for much simpler code and allows to keep driver data in separate drivers.
Regards,
Philipp.
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
Hi,
Quoted 33 lines · Dr. Philipp Tomsich
Hi Simon,
On 03 Mar 2017, at 05:52, Simon Glass <[email protected]> wrote:
Hi Philipp,
On 22 February 2017 at 13:47, Philipp Tomsich
<[email protected]> wrote:Currently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need to bind against a single node
* clock (UCLASS_CLK) and reset (UCLASS_RESET) drivers also need to bind against a single nodeDoes linux work this way? Another approach would be to have a separate MISC driver with two children, one pinctrl, one clk.
The linux CLK driver creates and registers a reset-controller; the PINCTRL driver
does the same with the gpio-controller. Similar code to do this is easily possible in
U-Boot … seesunxi_pctrl_bind_gpio(…)in [PATCH v2 1/6] of this series.
Quoted 3 lines
However, binding multiple times makes for much simpler code and allows to keep
driver data in separate drivers.
My question was more whether Linux registers multiple drivers with one device node. It's just not something I expected.
I'm not really convinced on this. It will break the current one-to-one relationship, and functions like device_get_child_by_of_offset(). I think it would be better to have a MISC driver with two children.
Regards,
Simon
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
Hi Simon,
Am Sonntag, 12. März 2017, 14:21:35 CET schrieb Simon Glass:
Quoted 36 lines
Quoted 30 lines · Dr. Philipp Tomsich
On 03 Mar 2017, at 05:52, Simon Glass <[email protected]> wrote:
On 22 February 2017 at 13:47, Philipp Tomsich <[email protected]> wrote:Currently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need tobind against a single node
* clock (
UCLASS_CLK) and reset (UCLASS_RESET) drivers also need tobind against a single node
Does linux work this way? Another approach would be to have a separate MISC driver with two children, one pinctrl, one clk.
The linux CLK driver creates and registers a reset-controller; the PINCTRL driver
does the same with the gpio-controller. Similar code to do this is easily possible in
U-Boot … seesunxi_pctrl_bind_gpio(…)in [PATCH v2 1/6] of this series.Quoted 3 lines
However, binding multiple times makes for much simpler code and allows to keep
driver data in separate drivers.
Quoted 6 lines
My question was more whether Linux registers multiple drivers with one device node. It's just not something I expected.
I'm not really convinced on this. It will break the current one-to-one relationship, and functions like
device_get_child_by_of_offset(). I think it would be better to have a MISC driver with two children.
In the regular device model the Linux kernel also generally has a one-to-one model. There are special cases, like clock and timer init using special handling, or things like "syscon" which acts like more of a flag and can live next to a regular device.
Therefore things like the Rockchip clock controller create the reset controller included in the CRU block. A behaviour the uboot clk driver mimics.
Also doesn't allowing multiple drivers to sit on top of a node create contention on who gets access to registers? At least in the kernel multiple mappings of registers are generally not favoured.
Heiko
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
In reply to Simon GlassQuoted 37 lines · Simon Glass
Hi,
Quoted 33 lines · Dr. Philipp Tomsich
Hi Simon,
On 03 Mar 2017, at 05:52, Simon Glass <[email protected]> wrote:
Hi Philipp,
On 22 February 2017 at 13:47, Philipp Tomsich
<[email protected]> wrote:Currently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need to bind against a single node
* clock (UCLASS_CLK) and reset (UCLASS_RESET) drivers also need to bind against a single nodeDoes linux work this way? Another approach would be to have a separate MISC driver with two children, one pinctrl, one clk.
The linux CLK driver creates and registers a reset-controller; the PINCTRL driver
does the same with the gpio-controller. Similar code to do this is easily possible in
U-Boot … seesunxi_pctrl_bind_gpio(…)in [PATCH v2 1/6] of this series.
Quoted 6 lines
Quoted 3 lines
However, binding multiple times makes for much simpler code and allows to keep
driver data in separate drivers.My question was more whether Linux registers multiple drivers with one device node. It's just not something I expected.
It does, but it's not really what we're doing in the linux driver. It has one driver, with one device, but registering into multiple frameworks.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170320/13f2e446/attachment.sig>
PATCH v2 2/6 dm: core: Allow multiple drivers to bind for a single node
Hi,
Quoted 42 lines · Maxime Ripard
Quoted 41 lines · Simon Glass
Hi,
Quoted 36 lines · Dr. Philipp Tomsich
Hi Simon,
On 03 Mar 2017, at 05:52, Simon Glass <[email protected]> wrote:
Hi Philipp,
On 22 February 2017 at 13:47, Philipp Tomsich
<[email protected]> wrote:Currently, driver binding stops once it encounters the first compatible driver that doesn't refuse to bind. However, there are cases where a single node will need to be handled by multiple driver classes. For those cases we provide a configurable option to continue to bind after the first driver has been found.
The first use cases for this are from the DM conversion of the sunxi (Allwinner) architecture:
* pinctrl (UCLASS_PINCTRL) and gpio (UCLASS_GPIO) drivers need to bind against a single node
* clock (UCLASS_CLK) and reset (UCLASS_RESET) drivers also need to bind against a single nodeDoes linux work this way? Another approach would be to have a separate MISC driver with two children, one pinctrl, one clk.
The linux CLK driver creates and registers a reset-controller; the PINCTRL driver
does the same with the gpio-controller. Similar code to do this is easily possible in
U-Boot … seesunxi_pctrl_bind_gpio(…)in [PATCH v2 1/6] of this series.However, binding multiple times makes for much simpler code and allows to keep
driver data in separate drivers.
Quoted 6 lines
Quoted 2 lines
My question was more whether Linux registers multiple drivers with one device node. It's just not something I expected.
It does, but it's not really what we're doing in the linux driver. It has one driver, with one device, but registering into multiple frameworks.
I believe that the U-Boot equivalent of this is to have a parent device with several children each in its own uclass.
Regards,
Simon
PATCH v2 3/6 sunxi: CONFIG_DM_ALLOW_MULTIPLE_DRIVERS for gpio/pinctrl binding
In reply to Philipp TomsichOur gpio and pinctrl driver need to be bound against the same node. While this can be done by hand (i.e. explicitly looking up the driver, creating the driver-data and binding the device), it is much easier done when the new option for the binding of multiple drivers against a single node is configured.
--- drivers/gpio/sunxi_gpio.c | 4 ++-- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-)
drivers/gpio/sunxi_gpio.c +2 -2
@@ -349,7 +349,7 @@ static const struct udevice_id sunxi_gpio_ids[] = {ID ("allwinner,sun8i-a83t-pinctrl" , a_all),ID ("allwinner,sun8i-h3-pinctrl" , a_all),ID ("allwinner,sun9i-a80-pinctrl" , a_all), -#if !defined(CONFIG_SUNXI_PINCTRL) +#if !defined(CONFIG_SUNXI_PINCTRL) || defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS)/* This is not strictly correct for the A64, as it is missing * bank 'A'. Yet, the register layout in the pinctrl block is * backward compatible and any accesses to the registers that
@@ -362,7 +362,7 @@ static const struct udevice_id sunxi_gpio_ids[] = {ID ("allwinner,sun8i-a83t-r-pinctrl" , l_1),ID ("allwinner,sun8i-h3-r-pinctrl" , l_1),ID ("allwinner,sun9i-a80-r-pinctrl" , l_3), -#if !defined(CONFIG_SUNXI_PINCTRL) +#if !defined(CONFIG_SUNXI_PINCTRL) || defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS) ID("allwinner,sun50i-a64-r-pinctrl", l_1),#endif { }
drivers/pinctrl/sunxi/pinctrl-sunxi.c +6 -2
@@ -14,7 +14,9 @@#include <asm/io.h> #include <asm/arch/clock.h> #include <asm/gpio.h> +#if defined(CONFIG_DM_GPIO ) && !defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS )#include <asm/arch/gpio-internal.h> +#endif #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/pinctrl.h>
@@ -27,7 +29,7 @@ DECLARE_GLOBAL_DATA_PTR;struct sunxi_pctrl_priv {void *base; -#if defined(CONFIG_DM_GPIO ) +#if defined(CONFIG_DM_GPIO ) && !defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS )struct sunxi_gpio_soc_data gpio_soc_data;struct udevice *gpio_dev;#endif
@@ -217,6 +219,7 @@ static int sunxi_pctrl_set_state(struct udevice *dev, struct udevice *config)return 0 ; } +#if defined(CONFIG_DM_GPIO ) && !defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS )static inline void soc_data_from_desc (const struct sunxi_pinctrl_desc *data,struct sunxi_gpio_soc_data *soc_data) {
@@ -236,10 +239,11 @@ static inline void soc_data_from_desc(const struct sunxi_pinctrl_desc *data, soc_data->start = low; soc_data->no_banks = high - low + 1; } +#endif static int sunxi_pctrl_bind_gpio (struct udevice *dev) { -#if defined(CONFIG_DM_GPIO ) +#if defined(CONFIG_DM_GPIO ) && !defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS )struct sunxi_pctrl_priv *priv =dev_get_priv (dev);const struct sunxi_pinctrl_desc *data = (struct sunxi_pinctrl_desc *)dev_get_driver_data (dev);
Signature · 1 line
1.9.1
PATCH v2 4/6 defconfig: lynx: enable CONFIG_DM_ALLOW_MULTIPLE_DRIVERS
In reply to Philipp TomsichNow that we have the new functionality to allow multiple drivers to bind for a single node, we want to enable it for the A64-uQ7.
--- configs/lynx_defconfig | 1 + 1 file changed, 1 insertion(+)
configs/lynx_defconfig +1 -0
@@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y CONFIG_ARCH_SUNXI=y CONFIG_MACH_SUN50I=y +CONFIG_DM_ALLOW_MULTIPLE_DRIVERS=y CONFIG_PINCTRL=y CONFIG_SUNXI_PINCTRL=y CONFIG_CLK=y
Signature · 1 line
1.9.1
PATCH v2 4/6 defconfig: lynx: enable CONFIG_DM_ALLOW_MULTIPLE_DRIVERS
Quoted 13 lines · Philipp Tomsich
Now that we have the new functionality to allow multiple drivers to bind for a single node, we want to enable it for the A64-uQ7.
Signed-off-by Philipp Tomsich <[email protected]>--- configs/lynx_defconfig | 1 + 1 file changed, 1 insertion(+)configs/lynx_defconfig +0
-0
configs/lynx_defconfig CONFIG_ARM=y · line 5
Quoted 4 lines
configs/lynx_defconfig +1
-0@@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y CONFIG_ARCH_SUNXI=y CONFIG_MACH_SUN50I=y +CONFIG_DM_ALLOW_MULTIPLE_DRIVERS=y
I guess it would be better to just put the default value in Kconfig as MACH_SUN50I or even ARCH_SUNXI to enable it for all the boards
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170222/120eafaa/attachment.sig>
PATCH v2 5/6 sun50i: dts: add r_pio node and pinconfig entries into r_pio and pio
In reply to Philipp TomsichTo sync up with use of a pinctrl-driver, this updates the DTS.
--- arch/arm/dts/sun50i-a64.dtsi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
arch/arm/dts/sun50i-a64.dtsi +3 -4
@@ -376,9 +376,9 @@ gpio-controller; #gpio-cells = <3>; interrupt-controller; - #interrupt-cells = <2>; + #interrupt-cells = <3>; - uart0_pins_a: uart0 at 0 { + uart0_pins_a: uart0_pins_a { allwinner,pins = "PB8", "PB9"; allwinner,function = "uart0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>;
@@ -532,10 +532,9 @@ reg = <0x01f02c00 0x400>; interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; + #gpio-cells = <3>; interrupt-controller; #interrupt-cells = <3>; - #size-cells = <0>; - #gpio-cells = <3>; }; ahb_rst: reset at 1c202c0 {
Signature · 1 line
1.9.1
PATCH v2 6/6 sun50i: dts: update DTS to avoid warnings
In reply to Philipp TomsichNodes that don't contain a reg-entry should not have an @xxx name attached. To silence the dt-compiler warnings, we update the DTS.
--- arch/arm/dts/sun50i-a64.dtsi | 57 ++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 21 deletions(-)
arch/arm/dts/sun50i-a64.dtsi +36 -21
@@ -88,7 +88,7 @@ method = "smc"; }; - memory { + memory: memory at 40000000 { device_type = "memory"; reg = <0x40000000 0>; };
@@ -378,84 +378,84 @@ interrupt-controller; #interrupt-cells = <3>; - uart0_pins_a: uart0_pins_a { + uart0_pins_a: uart0-pins-a { allwinner,pins = "PB8", "PB9"; allwinner,function = "uart0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart0_pins_b: uart0 at 1 { + uart0_pins_b: uart0-pins-b { allwinner,pins = "PF2", "PF3"; allwinner,function = "uart0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart1_2pins: uart1_2 at 0 { + uart1_2pins: uart1-2pins { allwinner,pins = "PG6", "PG7"; allwinner,function = "uart1"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart1_4pins: uart1_4 at 0 { + uart1_4pins: uart1-4pins { allwinner,pins = "PG6", "PG7", "PG8", "PG9"; allwinner,function = "uart1"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart2_2pins: uart2_2 at 0 { + uart2_2pins: uart2-2pins { allwinner,pins = "PB0", "PB1"; allwinner,function = "uart2"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart2_4pins: uart2_4 at 0 { + uart2_4pins: uart2-4pins { allwinner,pins = "PB0", "PB1", "PB2", "PB3"; allwinner,function = "uart2"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart3_pins_a: uart3 at 0 { + uart3_pins_a: uart3-pins-a { allwinner,pins = "PD0", "PD1"; allwinner,function = "uart3"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart3_2pins_b: uart3_2 at 1 { + uart3_2pins_b: uart3-2pins-b { allwinner,pins = "PH4", "PH5"; allwinner,function = "uart3"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart3_4pins_b: uart3_4 at 1 { + uart3_4pins_b: uart3-4pins-b { allwinner,pins = "PH4", "PH5", "PH6", "PH7"; allwinner,function = "uart3"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart4_2pins: uart4_2 at 0 { + uart4_2pins: uart4-2pins { allwinner,pins = "PD2", "PD3"; allwinner,function = "uart4"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - uart4_4pins: uart4_4 at 0 { + uart4_4pins: uart4-4pins { allwinner,pins = "PD2", "PD3", "PD4", "PD5"; allwinner,function = "uart4"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - mmc0_pins: mmc0 at 0 { + mmc0_pins: mmc0-pins { allwinner,pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5"; allwinner,function = "mmc0";
@@ -463,14 +463,14 @@ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - mmc0_default_cd_pin: mmc0_cd_pin at 0 { + mmc0_default_cd_pin: mmc0-cd-pin { allwinner,pins = "PF6"; allwinner,function = "gpio_in"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_PULL_UP>; }; - mmc1_pins: mmc1 at 0 { + mmc1_pins: mmc1-pins { allwinner,pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5"; allwinner,function = "mmc1";
@@ -478,36 +478,51 @@ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - mmc2_pins: mmc2 at 0 { + mmc2_pins: mmc2-pins { allwinner,pins = "PC1", "PC5", "PC6", "PC8", "PC9", "PC10"; allwinner,function = "mmc2"; +<<<<<<< HEAD allwinner,drive = <SUN4I_PINCTRL_30_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; +======= + drive-strength = < 30 >; + bias-pull-up; }; - i2c0_pins: i2c0_pins { + mmc2_8bit_pins: mmc2-8bit { + allwinner,pins = "PC5", "PC6", "PC8", + "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", + "PC15", "PC16"; + allwinner,function = "mmc2"; + drive-strength = < 30 >; + bias-pull-up; +>>>>>>> 20221b3... [f] dts warnings + }; + + i2c0_pins: i2c0-pins { allwinner,pins = "PH0", "PH1"; allwinner,function = "i2c0"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - i2c1_pins: i2c1_pins { + i2c1_pins: i2c1-pins { allwinner,pins = "PH2", "PH3"; allwinner,function = "i2c1"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - i2c2_pins: i2c2_pins { + i2c2_pins: i2c2-pins { allwinner,pins = "PE14", "PE15"; allwinner,function = "i2c2"; allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - rmii_pins: rmii_pins { + rmii_pins: rmii-pins { allwinner,pins = "PD10", "PD11", "PD13", "PD14", "PD17", "PD18", "PD19", "PD20", "PD22", "PD23";
@@ -516,7 +531,7 @@ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; - rgmii_pins: rgmii_pins { + rgmii_pins: rgmii-pins { allwinner,pins = "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD15", "PD16", "PD17", "PD18", "PD19",
Signature · 1 line
1.9.1
PATCH v2 6/6 sun50i: dts: update DTS to avoid warnings
Quoted 8 lines · Philipp Tomsich
+<<<<<<< HEAD
arch/arm/dts/sun50i-a64.dtsi +3
-0allwinner,drive = <SUN4I_PINCTRL_30_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; +======= + drive-strength = < 30 >; + bias-pull-up; };
arch/arm/dts/sun50i-a64.dtsi line 501
Quoted 10 lines
arch/arm/dts/sun50i-a64.dtsi +9
-1- i2c0_pins: i2c0_pins { + mmc2_8bit_pins: mmc2-8bit { + allwinner,pins = "PC5", "PC6", "PC8", + "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", + "PC15", "PC16"; + allwinner,function = "mmc2"; + drive-strength = < 30 >; + bias-pull-up; +>>>>>>> 20221b3... [f] dts warnings
Hmmm, are you sure about those ? :)
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 801 bytes Desc: not available URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170222/18160e36/attachment.sig>
PATCH v2 6/6 sun50i: dts: update DTS to avoid warnings
Quoted 12 lines · Maxime Ripard
Quoted 8 lines · Philipp Tomsich
+<<<<<<< HEAD
allwinner,drive = <SUN4I_PINCTRL_30_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;+=======
(quoted diff) +2
-0+ drive-strength = < 30 >; + bias-pull-up;};
Quoted 12 lines
arch/arm/dts/sun50i-a64.dtsi line 501
Quoted 10 lines
arch/arm/dts/sun50i-a64.dtsi +9
-1- i2c0_pins: i2c0_pins { + mmc2_8bit_pins: mmc2-8bit { + allwinner,pins = "PC5", "PC6", "PC8", + "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", + "PC15", "PC16"; + allwinner,function = "mmc2"; + drive-strength = < 30 >; + bias-pull-up; +>>>>>>> 20221b3... [f] dts warningsHmmm, are you sure about those ? :)
I can?t believe this slipped through. I think I need more sleep. At least the patch-format wasn?t such a mess this time around?
Cheers,
Philipp.