Hi,
Subsystems (6)
v2 cover Hi,
this series add support for the pin and gpio controllers present on the Armada 37xx SoCs.
Each Armada 37xx SoC comes with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin.
The gpio controller is also capable to handle interrupt from gpio.
Gregory
Gregory CLEMENT (7):
pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
arm64: marvell: enable the Armada 37xx pinctrl driver
pinctrl: armada-37xx: Add pin controller support for Armada 37xx
pinctrl: armada-37xx: Add gpio support
pinctrl: aramda-37xx: Add irqchip support
ARM64: dts: marvell: Add pinctrl nodes for Armada 3700
ARM64: dts: marvell: armada37xx: add pinctrl definition
Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt | 7 +- Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 143 +++++++++++- arch/arm64/Kconfig.platforms | 2 +- arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 71 +++++- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mvebu/Kconfig | 7 +- drivers/pinctrl/mvebu/Makefile | 3 +- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 918 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 1153 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
base-commit: c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201
Signature · 1 line
git-series 0.9.1
PATCH v2 1/7 pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
Document the device tree binding for the pin controllers found on the Armada 37xx SoCs.
Update the binding documention of the xtal clk which is a subnode of this syscon node.
--- Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt | 7 ++-- Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt +4 -3
@@ -5,6 +5,7 @@ reading the gpio latch register. This node must be a subnode of the node exposing the register address of the GPIO block where the gpio latch is located. +See Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt Required properties: - compatible : shall be one of the following:
@@ -16,9 +17,9 @@ Optional properties: output names ("xtal") Example: -gpio1: gpio at 13800 { - compatible = "marvell,armada-3700-gpio", "syscon", "simple-mfd"; - reg = <0x13800 0x1000>; +pinctrl_nb: pinctrl-nb at 13800 { + compatible = "armada3710-nb-pinctrl", "syscon", "simple-mfd"; + reg = <0x13800 0x100>, <0x13C00 0x20>; xtalclk: xtal-clk { compatible = "marvell,armada-3700-xtal-clock";
Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt new file +143 -0
143 lines not on this page · raw message
Signature · 1 line
git-series 0.9.1
Re: [PATCH v2 1/7] pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
Quoted 7 lines · Gregory CLEMENT
Document the device tree binding for the pin controllers found on the Armada 37xx SoCs.
Update the binding documention of the xtal clk which is a subnode of this syscon node.
Signed-off-by Gregory CLEMENT <[email protected]>
These look all right to me, but let's see what the DT people say.
This business with a subnode named "gpio-controller" that the code is checking for is not in the bindings or examples, is this part of the old Armada bindings?
Yours,
Linus Walleij
Re: [PATCH v2 1/7] pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
Hi Linus,
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Gregory CLEMENT
Document the device tree binding for the pin controllers found on the Armada 37xx SoCs.
Update the binding documention of the xtal clk which is a subnode of this syscon node.
Quoted 7 lines
Quoted 1 line
Signed-off-by Gregory CLEMENT <[email protected]>These look all right to me, but let's see what the DT people say.
This business with a subnode named "gpio-controller" that the code is checking for is not in the bindings or examples, is this part of the old Armada bindings?
It was updated in the version 3 I sent last week.
Gregory
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v2 2/7 arm64: marvell: enable the Armada 37xx pinctrl driver
In reply to Gregory CLEMENTThis commit makes sure the driver for the Armada 37xx pin controller is enabled.
--- arch/arm64/Kconfig.platforms | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/Kconfig.platforms +2 -0
@@ -105,6 +105,8 @@ config ARCH_MVEBU select ARMADA_37XX_CLK select MVEBU_ODMI select MVEBU_PIC + select PINCTRL + select PINCTRL_ARMADA_37XX help This enables support for Marvell EBU familly, including: - Armada 3700 SoC Family
Signature · 1 line
git-series 0.9.1
PATCH v2 3/7 pinctrl: armada-37xx: Add pin controller support for Armada 37xx
In reply to Gregory CLEMENTThe Armada 37xx SoC come with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin. This constraint is reflected in the design of the driver:
only the group related functions are implemented.
--- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mvebu/Kconfig | 7 +- drivers/pinctrl/mvebu/Makefile | 3 +- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 605 +++++++++++++++++++++- 4 files changed, 615 insertions(+), 2 deletions(-) create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
drivers/pinctrl/Makefile +1 -1
@@ -44,7 +44,7 @@ obj-y += bcm/ obj-$(CONFIG_PINCTRL_BERLIN) += berlin/ obj-y += freescale/ obj-$(CONFIG_X86) += intel/ -obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ +obj-y += mvebu/ obj-y += nomadik/ obj-$(CONFIG_PINCTRL_PXA) += pxa/ obj-$(CONFIG_ARCH_QCOM) += qcom/
drivers/pinctrl/mvebu/Kconfig +7 -0
@@ -39,3 +39,10 @@ config PINCTRL_ORION select PINCTRL_MVEBU endif + +config PINCTRL_ARMADA_37XX + bool + select GENERIC_PINCONF + select MFD_SYSCON + select PINCONF + select PINMUX
drivers/pinctrl/mvebu/Makefile +2 -1
@@ -1,4 +1,4 @@ -obj-y += pinctrl-mvebu.o +obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
@@ -6,4 +6,5 @@ obj-$(CONFIG_PINCTRL_ARMADA_375) += pinctrl-armada-375.o obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o obj-$(CONFIG_PINCTRL_ARMADA_39X) += pinctrl-armada-39x.o obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o +obj-$(CONFIG_PINCTRL_ARMADA_37XX) += pinctrl-armada-37xx.o obj-$(CONFIG_PINCTRL_ORION) += pinctrl-orion.o
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +605 -0
605 lines not on this page · raw message
Signature · 1 line
git-series 0.9.1
Re: [PATCH v2 3/7] pinctrl: armada-37xx: Add pin controller support for Armada 37xx
Quoted 6 lines · Gregory CLEMENT
The Armada 37xx SoC come with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin. This constraint is reflected in the design of the driver:
only the group related functions are implemented.
Interesting!
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +7
-0+static int armada_37xx_pmx_direction_input (struct armada_37xx_pinctrl *info, +unsigned int offset) +{ +unsigned int reg =OUTPUT_EN ; +unsigned int mask; + +if (offset >=GPIO_PER_REG ) {
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 331
Quoted 10 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +10
-0+ offset -=GPIO_PER_REG ; + reg +=sizeof (u32); + } + mask =BIT (offset); + +return regmap_update_bits (info->regmap, reg, mask,0 ); +} + + +
A bit of excess whitespace, OK nitpicking.
Then this stuff:
Quoted 89 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +89
-0+static int armada_37xx_add_function (struct armada_37xx_pmx_func *funcs, +int *funcsize,const char *name) +{ +int i =0 ; + +if (*funcsize <=0 ) +return -EOVERFLOW ; + +while (funcs->ngroups) { +/* function already there */ +if (strcmp (funcs->name, name) ==0 ) { + funcs->ngroups++; + +return -EEXIST ; + } + funcs++; + i++; + } + +/* append new unique function */ + funcs->name = name; + funcs->ngroups =1 ; + (*funcsize)--; + +return 0 ; +} + +static int armada_37xx_fill_group (struct armada_37xx_pinctrl *info,int base) +{ +int n, num =0 , funcsize = info->data->nr_pins; + +for (n =0 ; n < info->ngroups; n++) { +struct armada_37xx_pin_group *grp = &info->groups[n]; +int i, j, f; + + grp->pins =devm_kzalloc (info->dev, + (grp->npins + grp->extra_npins) * +sizeof (*grp->pins),GFP_KERNEL ); +if (!grp->pins) +return -ENOMEM ; + +for (i =0 ; i < grp->npins; i++) + grp->pins[i] = grp->start_pin + base + i; + +for (j =0 ; j < grp->extra_npins; j++) + grp->pins[i+j] = grp->extra_pin + base + j; + +for (f =0 ; f <NB_FUNCS ; f++) { +int ret; +/* check for unique functions and count groups */ + ret =armada_37xx_add_function (info->funcs, &funcsize, + grp->funcs[f]); +if (ret == -EOVERFLOW ) +dev_err (info->dev, +"More functions than pins(%d)\n" , + info->data->nr_pins); +if (ret <0 ) +continue ; + num++; + } + } + + info->nfuncs = num; + +return 0 ; +} + +static int armada_37xx_fill_func (struct armada_37xx_pinctrl *info) +{ +struct armada_37xx_pmx_func *funcs = info->funcs; +int n; + +for (n =0 ; n < info->nfuncs; n++) { +const char *name = funcs[n].name; +const char **groups; +int g; + + funcs[n].groups =devm_kzalloc (info->dev, funcs[n].ngroups * +sizeof (*(funcs[n].groups)), +GFP_KERNEL ); +if (!funcs[n].groups) +return -ENOMEM ; + + groups = funcs[n].groups; + +for (g =0 ; g < info->ngroups; g++) { +struct armada_37xx_pin_group *gp = &info->groups[g]; +int f; +
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 487
Quoted 10 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +10
-0+for (f =0 ; f <NB_FUNCS ; f++) { +if (strcmp (gp->funcs[f], name) ==0 ) { + *groups = gp->name; + groups++; + } + } + } + } +return 0 ; +}
I would be happy if you add kerneldoc to these functions and explain what they do. Because I don't get it. I guess they are filling in the data structures but yeah. Hard to follow.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 586
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +2
-0+ match =of_match_node (armada_37xx_pinctrl_of_match, np); + info->data = (struct armada_37xx_pin_data *)match->data;
Use of_device_get_match_data()
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 605
Quoted 9 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +9
-0+static struct platform_driver armada_37xx_pinctrl_driver = { + .driver = { + .name ="armada-37xx-pinctrl" , + .of_match_table = armada_37xx_pinctrl_of_match, + }, + .probe = armada_37xx_pinctrl_probe, +}; + +builtin_platform_driver (armada_37xx_pinctrl_driver);
It almost looks like your could use builting_platform_driver_probe() actually, and tag the costly initfunctions with __init so they get dicarded after probe.
Yours,
Linus Walleij
Re: [PATCH v2 3/7] pinctrl: armada-37xx: Add pin controller support for Armada 37xx
Hi Linus,
Quoted 23 lines · Linus Walleij
Quoted 6 lines · Gregory CLEMENT
The Armada 37xx SoC come with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin. This constraint is reflected in the design of the driver:
only the group related functions are implemented.Interesting!
Quoted 11 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +11
-0+static int armada_37xx_pmx_direction_input (struct armada_37xx_pinctrl *info, +unsigned int offset) +{ +unsigned int reg =OUTPUT_EN ; +unsigned int mask; + +if (offset >=GPIO_PER_REG ) { + offset -=GPIO_PER_REG ; + reg +=sizeof (u32); + } + mask =BIT (offset);
Quoted 9 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 331
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +6
-0+ +return regmap_update_bits (info->regmap, reg, mask,0 ); +} + + +A bit of excess whitespace, OK nitpicking.
As I need to send a v4, I will fix it in the same time.
Quoted 97 lines
Then this stuff:
Quoted 95 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +95
-0+static int armada_37xx_add_function (struct armada_37xx_pmx_func *funcs, +int *funcsize,const char *name) +{ +int i =0 ; + +if (*funcsize <=0 ) +return -EOVERFLOW ; + +while (funcs->ngroups) { +/* function already there */ +if (strcmp (funcs->name, name) ==0 ) { + funcs->ngroups++; + +return -EEXIST ; + } + funcs++; + i++; + } + +/* append new unique function */ + funcs->name = name; + funcs->ngroups =1 ; + (*funcsize)--; + +return 0 ; +} + +static int armada_37xx_fill_group (struct armada_37xx_pinctrl *info,int base) +{ +int n, num =0 , funcsize = info->data->nr_pins; + +for (n =0 ; n < info->ngroups; n++) { +struct armada_37xx_pin_group *grp = &info->groups[n]; +int i, j, f; + + grp->pins =devm_kzalloc (info->dev, + (grp->npins + grp->extra_npins) * +sizeof (*grp->pins),GFP_KERNEL ); +if (!grp->pins) +return -ENOMEM ; + +for (i =0 ; i < grp->npins; i++) + grp->pins[i] = grp->start_pin + base + i; + +for (j =0 ; j < grp->extra_npins; j++) + grp->pins[i+j] = grp->extra_pin + base + j; + +for (f =0 ; f <NB_FUNCS ; f++) { +int ret; +/* check for unique functions and count groups */ + ret =armada_37xx_add_function (info->funcs, &funcsize, + grp->funcs[f]); +if (ret == -EOVERFLOW ) +dev_err (info->dev, +"More functions than pins(%d)\n" , + info->data->nr_pins); +if (ret <0 ) +continue ; + num++; + } + } + + info->nfuncs = num; + +return 0 ; +} + +static int armada_37xx_fill_func (struct armada_37xx_pinctrl *info) +{ +struct armada_37xx_pmx_func *funcs = info->funcs; +int n; + +for (n =0 ; n < info->nfuncs; n++) { +const char *name = funcs[n].name; +const char **groups; +int g; + + funcs[n].groups =devm_kzalloc (info->dev, funcs[n].ngroups * +sizeof (*(funcs[n].groups)), +GFP_KERNEL ); +if (!funcs[n].groups) +return -ENOMEM ; + + groups = funcs[n].groups; + +for (g =0 ; g < info->ngroups; g++) { +struct armada_37xx_pin_group *gp = &info->groups[g]; +int f; + +for (f =0 ; f <NB_FUNCS ; f++) { +if (strcmp (gp->funcs[f], name) ==0 ) { + *groups = gp->name; + groups++; + } + }
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 237
Quoted 4 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +4
-0+ } + } +return 0 ; +}I would be happy if you add kerneldoc to these functions and explain what they do. Because I don't get it. I guess they are filling in the data structures but yeah. Hard to follow.
OK
Quoted 5 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 586
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +2
-0+ match =of_match_node (armada_37xx_pinctrl_of_match, np); + info->data = (struct armada_37xx_pin_data *)match->data;Use
of_device_get_match_data()
OK
Quoted 15 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 605
Quoted 11 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c new file +9
-0+static struct platform_driver armada_37xx_pinctrl_driver = { + .driver = { + .name ="armada-37xx-pinctrl" , + .of_match_table = armada_37xx_pinctrl_of_match, + }, + .probe = armada_37xx_pinctrl_probe, +}; + +builtin_platform_driver (armada_37xx_pinctrl_driver);It almost looks like your could use
builting_platform_driver_probe()actually, and tag the costly initfunctions with__initso they get dicarded after probe.
Sure, I will do it
Thanks,
Gregory
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v2 4/7 pinctrl: armada-37xx: Add gpio support
In reply to Gregory CLEMENTGPIO management is pretty simple and is part of the same IP than the pin controller for the Armada 37xx SoCs. This patch adds the GPIO support to the pinctrl-armada-37xx.c file, it also allows sharing common functions between the gpiolib and the pinctrl drivers.
--- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 134 ++++++++++++++++++--- 1 file changed, 119 insertions(+), 15 deletions(-)
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +119 -15
@@ -10,6 +10,7 @@* without any warranty of any kind, whether express or implied. */ +#include <linux/gpio/driver.h> #include <linux/mfd/syscon.h> #include <linux/of.h> #include <linux/of_device.h>
@@ -24,6 +25,8 @@#include "../pinctrl-utils.h" #define OUTPUT_EN 0x0 +#define INPUT_VAL 0x10 +#define OUTPUT_VAL 0x18#define OUTPUT_CTL 0x20#define SELECTION 0x30
@@ -75,6 +78,7 @@ struct armada_37xx_pinctrl {struct regmap *regmap;struct armada_37xx_pin_data *data;struct device *dev; +struct gpio_chip gpio_chip;struct pinctrl_desc pctl;struct pinctrl_dev *pctl_dev;struct armada_37xx_pin_group *groups;
@@ -312,51 +316,99 @@ static int armada_37xx_pmx_set(struct pinctrl_dev *pctldev,return armada_37xx_pmx_set_by_name (pctldev, name, grp); } -static int armada_37xx_pmx_direction_input (struct armada_37xx_pinctrl *info, -unsigned int offset) +static inline void aramda_37xx_update_reg (unsigned int *reg, +unsigned int offset) { -unsigned int reg =OUTPUT_EN ; -unsigned int mask; - +/* We never have more than 2 registers */ if (offset >=GPIO_PER_REG ) { offset -=GPIO_PER_REG ; - reg +=sizeof (u32); + *reg +=sizeof (u32); } +} + +static int armada_37xx_gpio_direction_input (struct gpio_chip *chip, +unsigned int offset) +{ +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +unsigned int reg =OUTPUT_EN ; +unsigned int mask; + +aramda_37xx_update_reg (®, offset); mask =BIT (offset);return regmap_update_bits (info->regmap, reg, mask,0 ); } +static int armada_37xx_gpio_get_direction (struct gpio_chip *chip, +unsigned int offset) +{ +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +unsigned int reg =OUTPUT_EN ; +unsigned int val, mask; + +aramda_37xx_update_reg (®, offset); + mask =BIT (offset); + +regmap_read (info->regmap, reg, &val); +return !(val & mask); +} -static int armada_37xx_pmx_direction_output (struct armada_37xx_pinctrl *info, -unsigned int offset,int value) +static int armada_37xx_gpio_direction_output (struct gpio_chip *chip, +unsigned int offset,int value) { +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip);unsigned int reg =OUTPUT_EN ;unsigned int mask; -if (offset >=GPIO_PER_REG ) { - offset -=GPIO_PER_REG ; - reg +=sizeof (u32); - } +aramda_37xx_update_reg (®, offset); mask =BIT (offset);return regmap_update_bits (info->regmap, reg, mask, mask); } +static int armada_37xx_gpio_get (struct gpio_chip *chip,unsigned int offset) +{ +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +unsigned int reg =INPUT_VAL ; +unsigned int val, mask; + +aramda_37xx_update_reg (®, offset); + mask =BIT (offset); + +regmap_read (info->regmap, reg, &val); + +return (val & mask) !=0 ; +} + +static void armada_37xx_gpio_set (struct gpio_chip *chip,unsigned int offset, +int value) +{ +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +unsigned int reg =OUTPUT_VAL ; +unsigned int mask, val; + +aramda_37xx_update_reg (®, offset); + mask =BIT (offset); + val = value ? mask :0 ; + +regmap_update_bits (info->regmap, reg, mask, val); +} +static int armada_37xx_pmx_gpio_set_direction (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned int offset,bool input) {struct armada_37xx_pinctrl *info =pinctrl_dev_get_drvdata (pctldev); +struct gpio_chip *chip = range->gc;dev_dbg (info->dev,"gpio_direction for pin %u as %s-%d to %s\n" , offset, range->name, offset, input ?"input" :"output" );if (input) -armada_37xx_pmx_direction_input (info, offset); +armada_37xx_gpio_direction_input (chip, offset);else -armada_37xx_pmx_direction_output (info, offset,0 ); +armada_37xx_gpio_direction_output (chip, offset,0 );return 0 ; }
@@ -386,6 +438,49 @@ static const struct pinmux_ops armada_37xx_pmx_ops = { .gpio_set_direction = armada_37xx_pmx_gpio_set_direction, }; +static const struct gpio_chip armada_37xx_gpiolib_chip = { + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .set = armada_37xx_gpio_set, + .get = armada_37xx_gpio_get, + .get_direction = armada_37xx_gpio_get_direction, + .direction_input = armada_37xx_gpio_direction_input, + .direction_output = armada_37xx_gpio_direction_output, + .owner =THIS_MODULE , +}; + +static int armada_37xx_gpiochip_register (struct platform_device *pdev, +struct armada_37xx_pinctrl *info) +{ +struct device_node *np; +struct gpio_chip *gc; +int ret = -ENODEV ; + +for_each_child_of_node (info->dev->of_node, np) { +if (of_find_property (np,"gpio-controller" ,NULL )) { + ret =0 ; +break ; + } + }; +if (ret) +return ret; + + info->gpio_chip = armada_37xx_gpiolib_chip; + + gc = &info->gpio_chip; + gc->ngpio = info->data->nr_pins; + gc->parent = &pdev->dev; + gc->base =-1 ; + gc->of_node = np; + gc->label = info->data->name; + + ret =gpiochip_add_data (gc, info); +if (ret) +return ret; + +return 0 ; +} +static int armada_37xx_add_function (struct armada_37xx_pmx_func *funcs,int *funcsize,const char *name) {
@@ -566,7 +661,7 @@ static int armada_37xx_pinctrl_probe(struct platform_device *pdev)struct device *dev = &pdev->dev;struct device_node *np = dev->of_node;struct regmap *regmap; -int ret; +int ret, pinbase = global_pin; info =devm_kzalloc (dev,sizeof (struct armada_37xx_pinctrl ),GFP_KERNEL );
@@ -585,10 +680,19 @@ static int armada_37xx_pinctrl_probe(struct platform_device *pdev) match =of_match_node (armada_37xx_pinctrl_of_match, np); info->data = (struct armada_37xx_pin_data *)match->data; + ret =armada_37xx_gpiochip_register (pdev, info); +if (ret) +return ret; + ret =armada_37xx_pinctrl_register (pdev, info);if (ret)return ret; + ret =gpiochip_add_pin_range (&info->gpio_chip,dev_name (dev),0 , + pinbase, info->data->nr_pins); +if (ret) +return ret; +platform_set_drvdata (pdev, info);return 0 ;
Signature · 1 line
git-series 0.9.1
Re: [PATCH v2 4/7] pinctrl: armada-37xx: Add gpio support
On Tue, Mar 21, 2017 at 7:28 PM, Gregory CLEMENT
<[email protected]> wrote:
You should add something to your Kconfig including:
select GPIOLIB
select OF_GPIO
or so... or depends on. You certainly need them.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct pinmux_ops armada_37xx_pmx_ops = { · line 464
Quoted 13 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +13
-0+static int armada_37xx_gpiochip_register (struct platform_device *pdev, +struct armada_37xx_pinctrl *info) +{ +struct device_node *np; +struct gpio_chip *gc; +int ret = -ENODEV ; + +for_each_child_of_node (info->dev->of_node, np) { +if (of_find_property (np,"gpio-controller" ,NULL )) { + ret =0 ; +break ; + } + };
OK so several GPIO chips as subnodes, why not one device per chip? Or have we discussed this before? It seems a bit weird, apparently there is just one node with a gpio-controller, as you're just adding one pin range.
What happens if there would be two gpio-controllers? The second is just ignored without error?
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct pinmux_ops armada_37xx_pmx_ops = { · line 479
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+ ret =gpiochip_add_data (gc, info); +if (ret) +return ret;
Can't you use devm_gpiochip_add_data()?
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static int armada_37xx_pinctrl_probe(struct platform_device *pdev) · line 694
Quoted 4 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +4
-0+ ret =gpiochip_add_pin_range (&info->gpio_chip,dev_name (dev),0 , + pinbase, info->data->nr_pins); +if (ret) +return ret;
Why can't you put the range(s) into the device tree?
We already have code in drivers/gpio/gpiolib-of.c to do this for you. And generic range definition bindings.
Yours,
Linus Walleij
Re: [PATCH v2 4/7] pinctrl: armada-37xx: Add gpio support
Hi Linus,
Quoted 9 lines · Linus Walleij
On Tue, Mar 21, 2017 at 7:28 PM, Gregory CLEMENT
<[email protected]> wrote:You should add something to your
Kconfigincluding:select GPIOLIB
selectOF_GPIOor so... or depends on. You certainly need them.
I missed it I will do it in v4.
Quoted 11 lines
Quoted 11 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +10
-0+static int armada_37xx_gpiochip_register (struct platform_device *pdev, +struct armada_37xx_pinctrl *info) +{ +struct device_node *np; +struct gpio_chip *gc; +int ret = -ENODEV ; + +for_each_child_of_node (info->dev->of_node, np) { +if (of_find_property (np,"gpio-controller" ,NULL )) { + ret =0 ;
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct pinmux_ops armada_37xx_pmx_ops = { · line 464
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+break ; + } + };OK so several GPIO chips as subnodes, why not one device per chip? Or have we discussed this before? It seems a bit weird, apparently there is just one node with a gpio-controller, as you're just adding one pin range.
As you probably noticed pinctrl and gpio register are mixed in this hardware. One of the register is alos use to get some clock freqeuncy, so that's why I ended with a syscon node. The parent node is the pinctrl. My main motivation to use a subnode was to be ablee to have a phandle associated with the GPIO chip. In my first version I only have one node but then I realized that I could not use GPIO in the device tree without an phandle to point it.
If you have an other solution, I would be happy to remove this subnode.
Quoted 3 lines
What happens if there would be two gpio-controllers? The second is just ignored without error?
There won't be a second gpio-controllers because we only have one gpio controller by pin controller (as they are actually the same). Also as I said above, the subnode is mainly here to provide a phandle.
But I can add a comment to emphasize it.
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct pinmux_ops armada_37xx_pmx_ops = { · line 479
Quoted 4 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+ ret =gpiochip_add_data (gc, info); +if (ret) +return ret;Can't you use
devm_gpiochip_add_data()?
I think I can.
Quoted 10 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static int armada_37xx_pinctrl_probe(struct platform_device *pdev) · line 694
Quoted 5 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +4
-0+ ret =gpiochip_add_pin_range (&info->gpio_chip,dev_name (dev),0 , + pinbase, info->data->nr_pins); +if (ret) +return ret;Why can't you put the range(s) into the device tree?
We already have code in
drivers/gpio/gpiolib-of.cto do this for you. And generic range definition bindings.
It was done in the v3.
Tanks,
Gregory
Quoted 8 lines
Yours,
Linus Walleij_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v2 5/7 pinctrl: aramda-37xx: Add irqchip support
In reply to Gregory CLEMENTThe Armada 37xx SoCs can handle interrupt through GPIO. However it can only manage the edge ones.
The way the interrupt are managed are classical so we can use the generic interrupt chip model.
The only unusual "feature" is that many interrupts are connected to the parent interrupt controller. But we do not take advantage of this and use the chained irq with all of them.
--- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 223 ++++++++++++++++++++- 1 file changed, 216 insertions(+), 7 deletions(-)
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +216 -7
@@ -13,7 +13,9 @@#include <linux/gpio/driver.h> #include <linux/mfd/syscon.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinctrl.h>
@@ -30,6 +32,11 @@#define OUTPUT_CTL 0x20#define SELECTION 0x30 +#define IRQ_EN 0x0 +#define IRQ_POL 0x08 +#define IRQ_STATUS 0x10 +#define IRQ_WKUP 0x18 +static int global_pin;#define NB_FUNCS 2
@@ -76,9 +83,12 @@ struct armada_37xx_pmx_func {struct armada_37xx_pinctrl {struct regmap *regmap; +void __iomem *base;struct armada_37xx_pin_data *data;struct device *dev;struct gpio_chip gpio_chip; +struct irq_chip irq_chip; +spinlock_t irq_lock;struct pinctrl_desc pctl;struct pinctrl_dev *pctl_dev;struct armada_37xx_pin_group *groups;
@@ -316,7 +326,7 @@ static int armada_37xx_pmx_set(struct pinctrl_dev *pctldev,return armada_37xx_pmx_set_by_name (pctldev, name, grp); } -static inline void aramda_37xx_update_reg (unsigned int *reg, +static inline void armada_37xx_update_reg (unsigned int *reg,unsigned int offset) {/* We never have more than 2 registers */
@@ -326,6 +336,14 @@ static inline void aramda_37xx_update_reg(unsigned int *reg, } } +static inline void armada_37xx_irq_update_reg (unsigned int *reg, +struct irq_data *d) +{ +int offset =irqd_to_hwirq (d); + +armada_37xx_update_reg (reg, offset); +} +static int armada_37xx_gpio_direction_input (struct gpio_chip *chip,unsigned int offset) {
@@ -333,7 +351,7 @@ static int armada_37xx_gpio_direction_input(struct gpio_chip *chip,unsigned int reg =OUTPUT_EN ;unsigned int mask; -aramda_37xx_update_reg (®, offset); +armada_37xx_update_reg (®, offset); mask =BIT (offset);return regmap_update_bits (info->regmap, reg, mask,0 );
@@ -346,7 +364,7 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip,unsigned int reg =OUTPUT_EN ;unsigned int val, mask; -aramda_37xx_update_reg (®, offset); +armada_37xx_update_reg (®, offset); mask =BIT (offset);regmap_read (info->regmap, reg, &val);
@@ -361,7 +379,7 @@ static int armada_37xx_gpio_direction_output(struct gpio_chip *chip,unsigned int reg =OUTPUT_EN ;unsigned int mask; -aramda_37xx_update_reg (®, offset); +armada_37xx_update_reg (®, offset); mask =BIT (offset);return regmap_update_bits (info->regmap, reg, mask, mask);
@@ -373,7 +391,7 @@ static int armada_37xx_gpio_get(struct gpio_chip *chip, unsigned int offset)unsigned int reg =INPUT_VAL ;unsigned int val, mask; -aramda_37xx_update_reg (®, offset); +armada_37xx_update_reg (®, offset); mask =BIT (offset);regmap_read (info->regmap, reg, &val);
@@ -388,7 +406,7 @@ static void armada_37xx_gpio_set(struct gpio_chip *chip, unsigned int offset,unsigned int reg =OUTPUT_VAL ;unsigned int mask, val; -aramda_37xx_update_reg (®, offset); +armada_37xx_update_reg (®, offset); mask =BIT (offset); val = value ? mask :0 ;
@@ -449,6 +467,194 @@ static const struct gpio_chip armada_37xx_gpiolib_chip = { .owner = THIS_MODULE, }; +void armada_37xx_irq_ack (struct irq_data *d) +{ +struct gpio_chip *chip =irq_data_get_irq_chip_data (d); +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +u32 reg =IRQ_STATUS , mask = d->mask; +unsigned long flags; + +armada_37xx_irq_update_reg (®, d); +spin_lock_irqsave (&info->irq_lock, flags); +writel (mask, info->base + reg); +spin_unlock_irqrestore (&info->irq_lock, flags); +} + +void armada_37xx_irq_mask (struct irq_data *d) +{ +struct gpio_chip *chip =irq_data_get_irq_chip_data (d); +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +u32 val, reg =IRQ_EN , mask = d->mask; +unsigned long flags; + +armada_37xx_irq_update_reg (®, d); +spin_lock_irqsave (&info->irq_lock, flags); + val =readl (info->base + reg); +writel (val & ~mask, info->base + reg); +spin_unlock_irqrestore (&info->irq_lock, flags); +} + +void armada_37xx_irq_unmask (struct irq_data *d) +{ +struct gpio_chip *chip =irq_data_get_irq_chip_data (d); +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +u32 val, reg =IRQ_EN , mask = d->mask; +unsigned long flags; + +armada_37xx_irq_update_reg (®, d); +spin_lock_irqsave (&info->irq_lock, flags); + val =readl (info->base + reg); +writel (val | mask, info->base + reg); +spin_unlock_irqrestore (&info->irq_lock, flags); +} + +static int armada_37xx_irq_set_wake (struct irq_data *d,unsigned int on) +{ +struct gpio_chip *chip =irq_data_get_irq_chip_data (d); +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +u32 val, reg =IRQ_WKUP , mask = d->mask; +unsigned long flags; + +armada_37xx_irq_update_reg (®, d); +spin_lock_irqsave (&info->irq_lock, flags); + val =readl (info->base + reg); +if (on) + val |= mask; +else + val &= ~mask; +writel (val, info->base + reg); +spin_unlock_irqrestore (&info->irq_lock, flags); + +return 0 ; +} + +static int armada_37xx_irq_set_type (struct irq_data *d,unsigned int type) +{ +struct gpio_chip *chip =irq_data_get_irq_chip_data (d); +struct armada_37xx_pinctrl *info =gpiochip_get_data (chip); +u32 val, reg =IRQ_POL , mask = d->mask; +unsigned long flags; + +spin_lock_irqsave (&info->irq_lock, flags); +armada_37xx_irq_update_reg (®, d); + val =readl (info->base + reg); +switch (type) { +case IRQ_TYPE_EDGE_RISING : + val &= ~mask; +break ; +case IRQ_TYPE_EDGE_FALLING : + val |= mask; +break ; +default : +spin_unlock_irqrestore (&info->irq_lock, flags); +return -EINVAL ; + } +writel (val, info->base + reg); +spin_unlock_irqrestore (&info->irq_lock, flags); + +return 0 ; +} + + +static void armada_37xx_irq_handler (struct irq_desc *desc) +{ +struct gpio_chip *gc =irq_desc_get_handler_data (desc); +struct irq_chip *chip =irq_desc_get_chip (desc); +struct armada_37xx_pinctrl *info =gpiochip_get_data (gc); +struct irq_domain *d = gc->irqdomain; +int i; + +chained_irq_enter (chip, desc); +for (i =0 ; i <= d->revmap_size /GPIO_PER_REG ; i++) { +u32 status; +unsigned long flags; + +spin_lock_irqsave (&info->irq_lock, flags); + status =readl_relaxed (info->base +IRQ_STATUS +4 * i); +/* Manage only the interrupt that was enabled */ + status &=readl_relaxed (info->base +IRQ_EN +4 * i); +spin_unlock_irqrestore (&info->irq_lock, flags); +while (status) { +u32 hwirq =ffs (status) -1 ; +u32 virq =irq_linear_revmap (d, hwirq + + i *GPIO_PER_REG ); + +generic_handle_irq (virq); + status &= ~(1 << hwirq); + } + } +chained_irq_exit (chip, desc); +} + +static int armada_37xx_irqchip_register (struct platform_device *pdev, +struct armada_37xx_pinctrl *info) +{ +struct device_node *np = info->dev->of_node; +int nrirqs = info->data->nr_pins; +struct gpio_chip *gc = &info->gpio_chip; +struct irq_chip *irqchip = &info->irq_chip; +struct resource res; +int ret, i, nr_irq_parent; + +for_each_child_of_node (info->dev->of_node, np) { +if (of_find_property (np,"gpio-controller" ,NULL )) { + ret =0 ; +break ; + } + }; +if (ret) +return ret; + + nr_irq_parent =of_irq_count (np); +spin_lock_init (&info->irq_lock); + +if (!nr_irq_parent) { +dev_err (&pdev->dev,"Invalid or no IRQ\n" ); +return 0 ; + } + +if (of_address_to_resource (info->dev->of_node,1 , &res)) { +dev_err (info->dev,"cannot find IO resource\n" ); +return -ENOENT ; + } + + info->base =devm_ioremap_resource (info->dev, &res); +if (IS_ERR (info->base)) +return PTR_ERR (info->base); + + irqchip->irq_ack = armada_37xx_irq_ack; + irqchip->irq_mask = armada_37xx_irq_mask; + irqchip->irq_unmask = armada_37xx_irq_unmask; + irqchip->irq_set_wake = armada_37xx_irq_set_wake; + irqchip->irq_set_type = armada_37xx_irq_set_type; + irqchip->name = info->data->name; + + ret =gpiochip_irqchip_add (gc, irqchip,0 , + handle_level_irq,IRQ_TYPE_NONE ); +if (ret) { +dev_info (&pdev->dev,"could not add irqchip\n" ); +return ret; + } + +for (i =0 ; i < nrirqs; i++) { +struct irq_data *d =irq_get_irq_data (gc->irq_base + i); + + d->mask =1 << (i %GPIO_PER_REG ); + } + +for (i =0 ; i < nr_irq_parent; i++) { +int irq =irq_of_parse_and_map (np, i); + +if (irq <0 ) +continue ; + +gpiochip_set_chained_irqchip (gc, irqchip, irq, + armada_37xx_irq_handler); + } + +return 0 ; +} +static int armada_37xx_gpiochip_register (struct platform_device *pdev,struct armada_37xx_pinctrl *info) {
@@ -477,6 +683,9 @@ static int armada_37xx_gpiochip_register(struct platform_device *pdev, ret =gpiochip_add_data (gc, info);if (ret)return ret; + ret =armada_37xx_irqchip_register (pdev, info); +if (ret) +return ret;return 0 ; }
@@ -518,7 +727,7 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info, int base) grp->pins =devm_kzalloc (info->dev, (grp->npins + grp->extra_npins) * -sizeof (*grp->pins),GFP_KERNEL ); +sizeof (*grp->pins),GFP_KERNEL );if (!grp->pins)return -ENOMEM ;
Signature · 1 line
git-series 0.9.1
Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Quoted 11 lines · Gregory CLEMENT
The Armada 37xx SoCs can handle interrupt through GPIO. However it can only manage the edge ones.
The way the interrupt are managed are classical so we can use the generic interrupt chip model.
The only unusual "feature" is that many interrupts are connected to the parent interrupt controller. But we do not take advantage of this and use the chained irq with all of them.
Signed-off-by Gregory CLEMENT <[email protected]>
You need something in your Kconfig
doing select GPIOLIB_IRQCHIP unless there is
something I miss here.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 37
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+#define IRQ_EN 0x0 +#define IRQ_POL 0x08 +#define IRQ_STATUS 0x10
This just cries out to me that there is a register 0x0c and I bet it handles edges vs levels so you could also implement level IRQs. Am I right?
Quoted 2 lines
(quoted diff) +1
-1- aramda_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, offset);
(...)
Review
Quoted 2 lines
(quoted diff) +1
-1- aramda_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, offset);
These spelling fixes, do not do them in this patch, fix the first patch adding them
instead. It's super-confusing. Applies everywhere.
Quoted 12 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +12
-0+static void armada_37xx_irq_handler (struct irq_desc *desc) +{ +struct gpio_chip *gc =irq_desc_get_handler_data (desc); +struct irq_chip *chip =irq_desc_get_chip (desc); +struct armada_37xx_pinctrl *info =gpiochip_get_data (gc); +struct irq_domain *d = gc->irqdomain; +int i; + +chained_irq_enter (chip, desc); +for (i =0 ; i <= d->revmap_size /GPIO_PER_REG ; i++) { +u32 status; +unsigned long flags;
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 580
Quoted 10 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +10
-0+ +spin_lock_irqsave (&info->irq_lock, flags); + status =readl_relaxed (info->base +IRQ_STATUS +4 * i); +/* Manage only the interrupt that was enabled */ + status &=readl_relaxed (info->base +IRQ_EN +4 * i); +spin_unlock_irqrestore (&info->irq_lock, flags); +while (status) { +u32 hwirq =ffs (status) -1 ; +u32 virq =irq_linear_revmap (d, hwirq + + i *GPIO_PER_REG );
Use irq_find_mapping() instead please.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 583
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+generic_handle_irq (virq); + status &= ~(1 << hwirq);
Why not status &= ~BIT(hwirq);
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 586
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+ } + } +chained_irq_exit (chip, desc);
Apart from that nice, it re-reads status on every iteration which is good.
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +6
-0+static int armada_37xx_irqchip_register (struct platform_device *pdev, +struct armada_37xx_pinctrl *info) +{ +struct device_node *np = info->dev->of_node; +int nrirqs = info->data->nr_pins; +struct gpio_chip *gc = &info->gpio_chip;
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 604
Quoted 10 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +10
-0+struct irq_chip *irqchip = &info->irq_chip; +struct resource res; +int ret, i, nr_irq_parent; + +for_each_child_of_node (info->dev->of_node, np) { +if (of_find_property (np,"gpio-controller" ,NULL )) { + ret =0 ; +break ; + } + };
Now there is this thing again looping over the nodes.
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (ret) + return ret;
ret may be used uninitialized here, if you loop over all nodes and do not find any "gpio-controller".
The static code checks will just scream about this.
(Please fix in the other patch as well if present there.)
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 614
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +7
-0+ nr_irq_parent =of_irq_count (np); +spin_lock_init (&info->irq_lock); + +if (!nr_irq_parent) { +dev_err (&pdev->dev,"Invalid or no IRQ\n" ); +return 0 ; + }
What if it is > 1? That doesn't seem to work but will pass this check silently.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 633
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+ ret =gpiochip_irqchip_add (gc, irqchip,0 , + handle_level_irq,IRQ_TYPE_NONE );
If you also set up the handler in .set_type() you can assign handle_bad_irq() here and let .set_type set the right handler as e.g. drivers/gpio/gpio-pl061.c.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 643
Quoted 5 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +5
-0+for (i =0 ; i < nrirqs; i++) { +struct irq_data *d =irq_get_irq_data (gc->irq_base + i); + + d->mask =1 << (i %GPIO_PER_REG ); + }
What is this? It looks like a big hack. At least put in a fat comment about what is going on and why.
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 646
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+for (i =0 ; i < nr_irq_parent; i++) { +int irq =irq_of_parse_and_map (np, i);
I think gpiochip_irqchip_add() will do this for you already, as it calls irq_create_mapping() for all offsets which will call irq_of_parse_and_map() am I right?
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 653
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +7
-0+ +if (irq <0 ) +continue ; + +gpiochip_set_chained_irqchip (gc, irqchip, irq, + armada_37xx_irq_handler); + }
So only this statement for each IRQ should be all right.
I think this driver needs a bit of tinkering and refining.
Yours,
Linus Walleij
Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Hi Linus,
Quoted 13 lines · Linus Walleij
Quoted 10 lines · Gregory CLEMENT
The Armada 37xx SoCs can handle interrupt through GPIO. However it can only manage the edge ones.
The way the interrupt are managed are classical so we can use the generic interrupt chip model.
The only unusual "feature" is that many interrupts are connected to the parent interrupt controller. But we do not take advantage of this and use the chained irq with all of them.
Quoted 5 lines
Quoted 1 line
Signed-off-by Gregory CLEMENT <[email protected]>You need something in your
Kconfig
doing selectGPIOLIB_IRQCHIPunless there is
something I miss here.
I forgot to add it, I will do it in the v4.
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c line 37
Quoted 4 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+#define IRQ_EN 0x0 +#define IRQ_POL 0x08 +#define IRQ_STATUS 0x10This just cries out to me that there is a register
0x0cand I bet it handles edges vs levels so you could also implement level IRQs. Am I right?
Unfortunately, no :(
As far as I know there is now way to handle level. The 0xc register is the IRQ_POL for the GPIO above 32.
Quoted 10 lines
Quoted 3 lines
(quoted diff) +1
-1- aramda_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, offset);(...)
Review
Quoted 2 lines
(quoted diff) +1
-1- aramda_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, offset);These spelling fixes, do not do them in this patch, fix the first patch adding them
instead. It's super-confusing. Applies everywhere.
It was a typo (too much 'a' in the same word) that I properly fixed in the v3. (But I still need to fix the title of the patch in the v4)
Quoted 16 lines
Quoted 16 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +16
-0+static void armada_37xx_irq_handler (struct irq_desc *desc) +{ +struct gpio_chip *gc =irq_desc_get_handler_data (desc); +struct irq_chip *chip =irq_desc_get_chip (desc); +struct armada_37xx_pinctrl *info =gpiochip_get_data (gc); +struct irq_domain *d = gc->irqdomain; +int i; + +chained_irq_enter (chip, desc); +for (i =0 ; i <= d->revmap_size /GPIO_PER_REG ; i++) { +u32 status; +unsigned long flags; + +spin_lock_irqsave (&info->irq_lock, flags); + status =readl_relaxed (info->base +IRQ_STATUS +4 * i); +/* Manage only the interrupt that was enabled */
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 580
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +6
-0+ status &=readl_relaxed (info->base +IRQ_EN +4 * i); +spin_unlock_irqrestore (&info->irq_lock, flags); +while (status) { +u32 hwirq =ffs (status) -1 ; +u32 virq =irq_linear_revmap (d, hwirq + + i *GPIO_PER_REG );Use
irq_find_mapping()instead please.
As we are in the interrupt handler I chose to use this function because according to its documentation: "This is a fast path alternative to irq_find_mapping() that can be called directly by irq controller code to save a handful of instructions".
The only restriction is "It is always safe to call, but won't find irqs mapped using the radix tree.". So I think that for this driver it is okay.
Quoted 5 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 583
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+generic_handle_irq (virq); + status &= ~(1 << hwirq);Why not status &= ~BIT(hwirq);
OK
Quoted 18 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 586
Quoted 4 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +3
-0+ } + } +chained_irq_exit (chip, desc);Apart from that nice, it re-reads status on every iteration which is good.
Quoted 10 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +10
-0+static int armada_37xx_irqchip_register (struct platform_device *pdev, +struct armada_37xx_pinctrl *info) +{ +struct device_node *np = info->dev->of_node; +int nrirqs = info->data->nr_pins; +struct gpio_chip *gc = &info->gpio_chip; +struct irq_chip *irqchip = &info->irq_chip; +struct resource res; +int ret, i, nr_irq_parent; +
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 604
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +6
-0+for_each_child_of_node (info->dev->of_node, np) { +if (of_find_property (np,"gpio-controller" ,NULL )) { + ret =0 ; +break ; + } + };Now there is this thing again looping over the nodes.
As explained in the other patch we will only have one GPIO subnode.
Quoted 10 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ if (ret) + return ret;ret may be used uninitialized here, if you loop over all nodes and do not find any "gpio-controller".
The static code checks will just scream about this.
(Please fix in the other patch as well if present there.)
OK
Quoted 11 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 614
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +7
-0+ nr_irq_parent =of_irq_count (np); +spin_lock_init (&info->irq_lock); + +if (!nr_irq_parent) { +dev_err (&pdev->dev,"Invalid or no IRQ\n" ); +return 0 ; + }What if it is > 1? That doesn't seem to work but will pass this check silently.
If we have nr_irq_parent > 1, it will work and it is actually expected.
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 633
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+ ret =gpiochip_irqchip_add (gc, irqchip,0 , + handle_level_irq,IRQ_TYPE_NONE );If you also set up the handler in .set_type() you can assign
handle_bad_irq()here and let .set_type set the right handler as e.g.drivers/gpio/gpio-pl061.c.
Well the hardware can only manage the edge trigger, so there is no benefit to modify it each time we want to change the kind of edge we want (raising or falling). But your comment make me realized that I used the wrong one, I will move to handle_edge_irq in the v4.
Quoted 9 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 643
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +5
-0+for (i =0 ; i < nrirqs; i++) { +struct irq_data *d =irq_get_irq_data (gc->irq_base + i); + + d->mask =1 << (i %GPIO_PER_REG ); + }What is this? It looks like a big hack. At least put in a fat comment about what is going on and why.
I can reuse a part of the commit log here: "The only unusual "feature" is that many interrupts are connected to the parent interrupt controller. But we do not take advantage of this and use the chained irq with all of them."
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 646
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+for (i =0 ; i < nr_irq_parent; i++) { +int irq =irq_of_parse_and_map (np, i);I think
gpiochip_irqchip_add()will do this for you already, as it callsirq_create_mapping()for all offsets which will callirq_of_parse_and_map()am I right?
After reading the code, it doesn't seem it is the case. At least there is no irq_of_parse_and_map() call from gpiochip_irqchip_add(). And waht we need here is to associate each IRQ to the same GPIO handler.
I can still try without this line to confirm it.
Gregory
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Quoted 7 lines · Gregory CLEMENT
Quoted 4 lines · Linus Walleij
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 580
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+u32 virq =irq_linear_revmap (d, hwirq + + i *GPIO_PER_REG );Use
irq_find_mapping()instead please.
Quoted 8 lines
As we are in the interrupt handler I chose to use this function because according to its documentation: "This is a fast path alternative to
irq_find_mapping()that can be called directly by irq controller code to save a handful of instructions".The only restriction is "It is always safe to call, but won't find irqs mapped using the radix tree.". So I think that for this driver it is okay.
So you are relying on the core code in gpiolib to select a linear map. That is implicit semantics, and either all drivers using GPIOLIB_IRQCHIP should be changed to irq_linear_revmap() or all stay with irq_find_mapping().
In this case, I doubt it that you are actually so timing critical that it matters. Please use irq_find_mapping().
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +7
-0+ nr_irq_parent =of_irq_count (np); +spin_lock_init (&info->irq_lock); + +if (!nr_irq_parent) { +dev_err (&pdev->dev,"Invalid or no IRQ\n" ); +return 0 ; + }
Quoted 4 lines
Quoted 2 lines
What if it is > 1? That doesn't seem to work but will pass this check silently.
If we have
nr_irq_parent> 1, it will work and it is actually expected.
Ah, I get it. Nice.
Quoted 11 lines
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 633
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+ ret =gpiochip_irqchip_add (gc, irqchip,0 , + handle_level_irq,IRQ_TYPE_NONE );If you also set up the handler in .set_type() you can assign
handle_bad_irq()here and let .set_type set the right handler as e.g.drivers/gpio/gpio-pl061.c.Well the hardware can only manage the edge trigger, so there is no benefit to modify it each time we want to change the kind of edge we want (raising or falling). But your comment make me realized that I used the wrong one, I will move to
handle_edge_irqin the v4.
Ooops, yeah handle_edge_irq() is what calls the ACK callback.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +5
-0+for (i =0 ; i < nrirqs; i++) { +struct irq_data *d =irq_get_irq_data (gc->irq_base + i); + + d->mask =1 << (i %GPIO_PER_REG ); + }
Quoted 7 lines
Quoted 2 lines
What is this? It looks like a big hack. At least put in a fat comment about what is going on and why.
I can reuse a part of the commit log here: "The only unusual "feature" is that many interrupts are connected to the parent interrupt controller. But we do not take advantage of this and use the chained irq with all of them."
What you're doing is mocking around with core irqchip semantics. Is ->mask really supposed to be played around with from the outsid like this?
Anyways: BIT(i % GPIO_PER_REG) is nicer.
Quoted 7 lines
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 646
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+for (i =0 ; i < nr_irq_parent; i++) { +int irq =irq_of_parse_and_map (np, i);I think
gpiochip_irqchip_add()will do this for you already, as it callsirq_create_mapping()for all offsets which will callirq_of_parse_and_map()am I right?
Quoted 5 lines
After reading the code, it doesn't seem it is the case. At least there is no
irq_of_parse_and_map()call fromgpiochip_irqchip_add(). And waht we need here is to associate each IRQ to the same GPIO handler.I can still try without this line to confirm it.
It has irq_create_mapping(gpiochip->irqdomain, offset); that get called for every IRQ, and that will eventually call irq_of_parse_and_map() if the IRQs are defined in the device tree. (IIRC)
Yours,
Linus Walleij
Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Hi Linus,
Quoted 18 lines · Linus Walleij
Quoted 7 lines · Gregory CLEMENT
Quoted 4 lines · Linus Walleij
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 580
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+u32 virq =irq_linear_revmap (d, hwirq + + i *GPIO_PER_REG );Use
irq_find_mapping()instead please.Quoted 8 lines
As we are in the interrupt handler I chose to use this function because according to its documentation: "This is a fast path alternative to
irq_find_mapping()that can be called directly by irq controller code to save a handful of instructions".The only restriction is "It is always safe to call, but won't find irqs mapped using the radix tree.". So I think that for this driver it is okay.
Quoted 7 lines
So you are relying on the core code in gpiolib to select a linear map. That is implicit semantics, and either all drivers using
GPIOLIB_IRQCHIPshould be changed toirq_linear_revmap()or all stay withirq_find_mapping().In this case, I doubt it that you are actually so timing critical that it matters. Please use
irq_find_mapping().
OK
Quoted 23 lines
Quoted 11 lines
Quoted 6 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 633
Quoted 2 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+ ret =gpiochip_irqchip_add (gc, irqchip,0 , + handle_level_irq,IRQ_TYPE_NONE );If you also set up the handler in .set_type() you can assign
handle_bad_irq()here and let .set_type set the right handler as e.g.drivers/gpio/gpio-pl061.c.Well the hardware can only manage the edge trigger, so there is no benefit to modify it each time we want to change the kind of edge we want (raising or falling). But your comment make me realized that I used the wrong one, I will move to
handle_edge_irqin the v4.Ooops, yeah
handle_edge_irq()is what calls the ACK callback.Quoted 9 lines
Quoted 8 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 643
Quoted 5 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +5
-0+for (i =0 ; i < nrirqs; i++) { +struct irq_data *d =irq_get_irq_data (gc->irq_base + i); + + d->mask =1 << (i %GPIO_PER_REG ); + }What is this? It looks like a big hack. At least put in a fat comment about what is going on and why.
Quoted 8 lines
Quoted 4 lines
I can reuse a part of the commit log here: "The only unusual "feature" is that many interrupts are connected to the parent interrupt controller. But we do not take advantage of this and use the chained irq with all of them."
What you're doing is mocking around with core irqchip semantics. Is ->mask really supposed to be played around with from the outsid like this?
According to the documentation mask is a "precomputed bitmask for accessing the chip registers" and it is exactly the way it is used in this driver.
Moreover, currently ->mask is only used by the generic irqchip framework and not by the core of the irqchip subsystem. So the mask initialization is not done from the oustide but at the same level as the generic irqchip which is not used here.
Quoted 1 line
Anyways:
BIT(i % GPIO_PER_REG)is nicer.
OK
Quoted 12 lines
Quoted 12 lines
Quoted 7 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c static const struct gpio_chip armada_37xx_gpiolib_chip = { · line 646
Quoted 3 lines
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +2
-0+for (i =0 ; i < nr_irq_parent; i++) { +int irq =irq_of_parse_and_map (np, i);I think
gpiochip_irqchip_add()will do this for you already, as it callsirq_create_mapping()for all offsets which will callirq_of_parse_and_map()am I right?After reading the code, it doesn't seem it is the case. At least there is no
irq_of_parse_and_map()call fromgpiochip_irqchip_add(). And waht we need here is to associate each IRQ to the same GPIO handler.
Quoted 5 lines
Quoted 1 line
I can still try without this line to confirm it.
It has
irq_create_mapping(gpiochip->irqdomain, offset); that get called for every IRQ, and that will eventually callirq_of_parse_and_map()if the IRQs are defined in the device tree. (IIRC)
When I followed the functions called I never find a call to irq_of_parse_and_map(), the closer things related to device tree I found was:
"virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);"
http://elixir.free-electrons.com/source/kernel/irq/irqdomain.c?v=4.11-rc4#L507
Gregory
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Quoted 6 lines · Gregory CLEMENT
Quoted 3 lines · Linus Walleij
What you're doing is mocking around with core irqchip semantics. Is ->mask really supposed to be played around with from the outsid like this?
Quoted 8 lines
According to the documentation mask is a "precomputed bitmask for accessing the chip registers" and it is exactly the way it is used in this driver.
Moreover, currently ->mask is only used by the generic irqchip framework and not by the core of the irqchip subsystem. So the mask initialization is not done from the oustide but at the same level as the generic irqchip which is not used here.
OK excellent, sorry for my ignorance. We should rather point to your driver as a good example of how to do this. Care to add some few lines of comment as to what is going on for others that need to do the same?
Actually it would even be good to have something in Documentation/gpio/driver.txt
Quoted 10 lines
Quoted 3 lines
It has
irq_create_mapping(gpiochip->irqdomain, offset); that get called for every IRQ, and that will eventually callirq_of_parse_and_map()if the IRQs are defined in the device tree. (IIRC)When I followed the functions called I never find a call to
irq_of_parse_and_map(), the closer things related to device tree I found was:
"virq =irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);"
http://elixir.free-electrons.com/source/kernel/irq/irqdomain.c?v=4.11-rc4#L507
I don't know if I'm rambling or what. I'm pretty sure it gets called, maybe even earlier, like when the DT is parsed for the platform. We have so many drivers not seemingly needing this, but if your driver needs it, all others may need to be fixed too.
Can you put a print in irq_of_parse_and_map() and see what happens?
Yours,
Linus Walleij
Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Hi Linus,
Quoted 11 lines · Linus Walleij
Quoted 10 lines
Quoted 3 lines
It has
irq_create_mapping(gpiochip->irqdomain, offset); that get called for every IRQ, and that will eventually callirq_of_parse_and_map()if the IRQs are defined in the device tree. (IIRC)When I followed the functions called I never find a call to
irq_of_parse_and_map(), the closer things related to device tree I found was:
"virq =irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);"
http://elixir.free-electrons.com/source/kernel/irq/irqdomain.c?v=4.11-rc4#L507
Quoted 6 lines
I don't know if I'm rambling or what. I'm pretty sure it gets called, maybe even earlier, like when the DT is parsed for the platform. We have so many drivers not seemingly needing this, but if your driver needs it, all others may need to be fixed too.
Can you put a print in
irq_of_parse_and_map()and see what happens?
So if I don't call it explicitly in my driver, then this function is never called for the gpio.
Gregory
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH v2 6/7 ARM64: dts: marvell: Add pinctrl nodes for Armada 3700
In reply to Gregory CLEMENTAdd the nodes for the two pin controller present in the Armada 37xx SoCs.
Initially the node was named gpio1 using the same name that for the register range in the datasheet. However renaming it pinctr_nb (nb for North Bridge) makes more sens.
--- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 40 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-)
arch/arm64/boot/dts/marvell/armada-37xx.dtsi +37 -3
@@ -157,10 +157,28 @@ #clock-cells = <1>; }; - gpio1: gpio at 13800 { - compatible = "marvell,mvebu-gpio-3700", + pinctrl_nb: pinctrl-nb at 13800 { + compatible = "marvell,armada3710-nb-pinctrl", "syscon", "simple-mfd"; - reg = <0x13800 0x500>; + reg = <0x13800 0x100>, <0x13C00 0x20>; + gpionb: gpionb { + #gpio-cells = <2>; + gpio-controller; + interrupts = + <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; + + }; xtalclk: xtal-clk { compatible = "marvell,armada-3700-xtal-clock";
@@ -169,6 +187,22 @@ }; }; + pinctrl_sb: pinctrl-sb at 18800 { + compatible = "marvell,armada3710-sb-pinctrl", + "syscon", "simple-mfd"; + reg = <0x18800 0x100>, <0x18C00 0x20>; + gpiosb: gpiosb { + #gpio-cells = <2>; + gpio-controller; + interrupts = + <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + eth0: ethernet at 30000 { compatible = "marvell,armada-3700-neta"; reg = <0x30000 0x4000>;
Signature · 1 line
git-series 0.9.1
PATCH v2 7/7 ARM64: dts: marvell: armada37xx: add pinctrl definition
In reply to Gregory CLEMENTStart to populate the device tree of the Armada 37xx with the pincontrol configuration used on the board providing a dts.
--- arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +++++- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 31 +++++++++++++++++++- 2 files changed, 39 insertions(+)
arch/arm64/boot/dts/marvell/armada-3720-db.dts +8 -0
@@ -63,6 +63,8 @@ }; &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; status = "okay"; };
@@ -73,6 +75,8 @@ &spi0 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_quad_pins>; m25p80 at 0 { compatible = "jedec,spi-nor";
@@ -103,6 +107,8 @@ /* Exported on the micro USB connector CON32 through an FTDI */ &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; status = "okay"; };
@@ -128,6 +134,8 @@ }; ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; phy-mode = "rgmii-id"; phy = <&phy0>; status = "okay";
arch/arm64/boot/dts/marvell/armada-37xx.dtsi +31 -0
@@ -185,6 +185,31 @@ clock-output-names = "xtal"; #clock-cells = <0>; }; + + spi_quad_pins: spi-quad-pins { + groups = "spi_quad"; + function = "spi"; + }; + + i2c1_pins: i2c1-pins { + groups = "i2c1"; + function = "i2c"; + }; + + i2c2_pins: i2c2-pins { + groups = "i2c2"; + function = "i2c"; + }; + + uart1_pins: uart1-pins { + groups = "uart1"; + function = "uart"; + }; + + uart2_pins: uart2-pins { + groups = "uart2"; + function = "uart"; + }; }; pinctrl_sb: pinctrl-sb at 18800 {
@@ -201,6 +226,12 @@ <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; }; + + rgmii_pins: mii-pins { + groups = "rgmii"; + function = "mii"; + }; + }; eth0: ethernet at 30000 {
Signature · 1 line
git-series 0.9.1
v2 cover Add support for pinctrl/gpio on Armada 37xx Was Re: [PATCH v2 0/7] Hi,
In reply to Gregory CLEMENTHi,
Obviously this cover letter is wrong. Actually I forgot to commit it in git series. Here it is the correct one:
After several months here it is the second version of the series adding support for the pin and gpio controllers present on the Armada 37xx SoCs.
Each Armada 37xx SoC comes with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin.
The gpio controller is also capable to handle interrupt from gpio.
In the second version several changes has been done:
- Update binding documentation making clear that mfd and syscon must be used (patch 1).
- Split the fist patch adding pin controller support for Armada 37xx in arm64 part (for kconfig) and pinctrl part (patch 2 and 3)
- Add MFD_SYSCON dependency (patch 3)
- Add kerneldoc for the armada_37xx_pin_group struct (patch 3)
- Rename _add_function() to armada_37xx_add_function() (patch 3)
- Use an inline function to update the reg offset (patch 4)
- Rename gpiolib_register to gpiochip_register (patch 4)
- Add a comment about the two registers limit (patch 4)
- Add explicit gpio node in the device tree (patch 4)
- Convert the driver to use GPIOLIB_IRQCHIP (patch 5)
- Add a critical section when accessing the hardware registers (patch 5)
- Use the gpio sub-node (patch 5)
With these change most of the comment of the first revision have been addressed.
Thanks,
Gregory
Gregory CLEMENT (7):
pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
arm64: marvell: enable the Armada 37xx pinctrl driver
pinctrl: armada-37xx: Add pin controller support for Armada 37xx
pinctrl: armada-37xx: Add gpio support
pinctrl: aramda-37xx: Add irqchip support
ARM64: dts: marvell: Add pinctrl nodes for Armada 3700
ARM64: dts: marvell: armada37xx: add pinctrl definition
Documentation/devicetree/bindings/clock/armada3700-xtal-clock.txt | 7 +- Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 143 +++++++++++- arch/arm64/Kconfig.platforms | 2 +- arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 71 +++++- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mvebu/Kconfig | 7 +- drivers/pinctrl/mvebu/Makefile | 3 +- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 918 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 1153 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
Sorry for the noise,
Gregory
Quoted 38 lines · Gregory CLEMENT
this series add support for the pin and gpio controllers present on the Armada 37xx SoCs.
Each Armada 37xx SoC comes with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin.
The gpio controller is also capable to handle interrupt from gpio.
Gregory
Gregory CLEMENT (7):
pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
arm64: marvell: enable the Armada 37xx pinctrl driver
pinctrl: armada-37xx: Add pin controller support for Armada 37xx
pinctrl: armada-37xx: Add gpio support
pinctrl: aramda-37xx: Add irqchip support
ARM64: dts: marvell: Add pinctrl nodes for Armada 3700
ARM64: dts: marvell: armada37xx: add pinctrl definitionDocumentation/devicetree/bindings/clock/armada3700-xtal-clock.txt | 7 +- Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 143 +++++++++++- arch/arm64/Kconfig.platforms | 2 +- arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 71 +++++- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mvebu/Kconfig | 7 +- drivers/pinctrl/mvebu/Makefile | 3 +- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 918 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 1153 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-37xx.cbase-commit:
c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201Signature · 1 line
git-series 0.9.1
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Re: [PATCH v2 0/7] Add support for pinctrl/gpio on Armada 37xx Was Re: [PATCH v2 0/7] Hi,
Hi Linus,
Quoted 8 lines · Gregory CLEMENT
Hi,
Obviously this cover letter is wrong. Actually I forgot to commit it in git series. Here it is the correct one:
After several months here it is the second version of the series adding support for the pin and gpio controllers present on the Armada 37xx SoCs.
As the first version was sent in December here it is a link to it:
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-December/475216.html
Also I am going to answer to your review to point what I have done in this new series.
Gregory
Quoted 121 lines
Each Armada 37xx SoC comes with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin.
The gpio controller is also capable to handle interrupt from gpio.
In the second version several changes has been done:
- Update binding documentation making clear that mfd and syscon must be used (patch 1).
- Split the fist patch adding pin controller support for Armada 37xx in arm64 part (for kconfig) and pinctrl part (patch 2 and 3)
- Add
MFD_SYSCONdependency (patch 3)- Add kerneldoc for the
armada_37xx_pin_groupstruct (patch 3)- Rename
_add_function()toarmada_37xx_add_function()(patch 3)- Use an inline function to update the reg offset (patch 4)
- Rename
gpiolib_registertogpiochip_register(patch 4)- Add a comment about the two registers limit (patch 4)
- Add explicit gpio node in the device tree (patch 4)
- Convert the driver to use
GPIOLIB_IRQCHIP(patch 5)- Add a critical section when accessing the hardware registers (patch 5)
- Use the gpio sub-node (patch 5)
With these change most of the comment of the first revision have been addressed.
Thanks,
Gregory
Gregory CLEMENT (7):
pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
arm64: marvell: enable the Armada 37xx pinctrl driver
pinctrl: armada-37xx: Add pin controller support for Armada 37xx
pinctrl: armada-37xx: Add gpio support
pinctrl: aramda-37xx: Add irqchip support
ARM64: dts: marvell: Add pinctrl nodes for Armada 3700
ARM64: dts: marvell: armada37xx: add pinctrl definitionDocumentation/devicetree/bindings/clock/armada3700-xtal-clock.txt | 7 +- Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 143 +++++++++++- arch/arm64/Kconfig.platforms | 2 +- arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 71 +++++- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mvebu/Kconfig | 7 +- drivers/pinctrl/mvebu/Makefile | 3 +- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 918 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 1153 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-37xx.cSorry for the noise,
Gregory
Quoted 38 lines · Gregory CLEMENT
this series add support for the pin and gpio controllers present on the Armada 37xx SoCs.
Each Armada 37xx SoC comes with 2 pin controllers: one on the south bridge (managing 28 pins) and one on the north bridge (managing 36 pins).
At the hardware level the controller configure the pins by group and not pin by pin.
The gpio controller is also capable to handle interrupt from gpio.
Gregory
Gregory CLEMENT (7):
pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers
arm64: marvell: enable the Armada 37xx pinctrl driver
pinctrl: armada-37xx: Add pin controller support for Armada 37xx
pinctrl: armada-37xx: Add gpio support
pinctrl: aramda-37xx: Add irqchip support
ARM64: dts: marvell: Add pinctrl nodes for Armada 3700
ARM64: dts: marvell: armada37xx: add pinctrl definitionDocumentation/devicetree/bindings/clock/armada3700-xtal-clock.txt | 7 +- Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 143 +++++++++++- arch/arm64/Kconfig.platforms | 2 +- arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +- arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 71 +++++- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mvebu/Kconfig | 7 +- drivers/pinctrl/mvebu/Makefile | 3 +- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 918 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 1153 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt create mode 100644 drivers/pinctrl/mvebu/pinctrl-armada-37xx.cbase-commit:
c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201Signature · 1 line
git-series 0.9.1Signature · 9 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 4 lines
Gregory Clement, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com