support pinconf in pinctrl single driver
Subsystems (5)
Haojian Zhuang
maintainerv7 cover support pinconf in pinctrl single driver
Changelog:
v7:
1. Discard the method of adding gpio range from pinctrl-single driver. Use gpiolib driver to support gpio range from DTS instead.
2. Add gpio request function to claim pin in gpio pl061 driver.
3. Adjust the initcall level in gpio pl061 driver.
4. Allocate gpio number from lowest gpio number to highest. The original implementation is inverted. It's hard to use since it inverted the sequence of gpio number.
5. Remove the support of pxa910 temporarily since gpio pxa driver need to be updated for supporting this solution.
v6:
1. Two configuration array will be created for each pin group. This first array is stored in pcs_function structure. The 32-bit configruation argument is stored in this array. Driver stores data while parsing DTS file, and loads these config array if function selector is indicated.
The second array is stored in pinctrl_map structure. Driver won't use it directly. So we could avoid to append lookup pinctrl map method that is introduced in v5.
v5:
1. Move the properties of pinconf into pin group. So those mask properties could be merged with other pinconf properties.
2. Append lookup pinctrl map method.
3. Append input schmitt disable config parameter.
4. Clean code.
v4:
1. Define gpio range as sub-node, not label. And remove pinctrl-single,gpio-ranges property.
2. Use new two properties in sub-node, reg & pinctrl-single,gpio. GPIO number & GPIO function are listed in the pinctrl-single,gpio property.
3. Reference the names like pinctrl-single,bias.
4. Add compatible name "pinconf-single". If the compatible name is "pinctrl-single", there's no pinconf. If the compatible name is "pinconf-single", there's the generic pinconf in pinctrl-single.
5. Update documents.
v3:
1. Add more comments in document.
2. Replace pcs_readl() & pcs_writel() by pcs->read() & pcs->write().
3. Clean code.
v2:
1. Remove "pinctrl-single,gpio-mask". Since GPIO function is one of the mux function in the pinmux register of both OMAP and PXA/MMP silicons. Use "pinctrl-single,function-mask" instead.
Haojian Zhuang
maintainerPATCH v7 1/15 Revert "pinctrl: single: support gpio request and free"
This reverts commit 2e8b2eab94c35d83bb7da71c63b4695f32ddca88.
Conflicts:
drivers/pinctrl/pinctrl-single.c
ERROR: "__aeabi_uldivmod" [drivers/pinctrl/pinctrl-single.ko] undefined!]
Quoted 7 lines · Russell King
The above error happens in builds including pinctrl-single - the reason
is this, whereresource_size_tmay be 64-bit.gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
The reason of not fixing this issue and reverting the patch instead is this patch can't handle another case. It's not easy to handle multiple gpios sharing one pin register. So this gpio range feature will be implemented by other patches.
--- drivers/pinctrl/pinctrl-single.c | 79 +------------------------------------- 1 file changed, 2 insertions(+), 77 deletions(-)
drivers/pinctrl/pinctrl-single.c +2 -77
@@ -30,7 +30,6 @@#define PCS_MUX_BITS_NAME "pinctrl-single,bits"#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)#define PCS_OFF_DISABLED ~0U -#define PCS_MAX_GPIO_VALUES 2/** * struct pcs_pingroup - pingroups for a function
@@ -78,16 +77,6 @@ struct pcs_function { };/** -* struct pcs_gpio_range - pinctrl gpio range -* @range: subrange of the GPIO number space -* @gpio_func: gpio function value in the pinmux register -*/ -struct pcs_gpio_range { -struct pinctrl_gpio_range range; -int gpio_func; -}; - -/** * struct pcs_data - wrapper for data needed by pinctrl framework * @pa: pindesc array * @cur: index to current element
@@ -414,26 +403,9 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, }static int pcs_request_gpio (struct pinctrl_dev *pctldev, -struct pinctrl_gpio_range *range,unsigned pin) +struct pinctrl_gpio_range *range,unsigned offset) { -struct pcs_device *pcs =pinctrl_dev_get_drvdata (pctldev); -struct pcs_gpio_range *gpio =NULL ; -int end, mux_bytes; -unsigned data; - - gpio = container_of(range, struct pcs_gpio_range, range); - end = range->pin_base + range->npins -1 ; -if (pin < range->pin_base || pin > end) { -dev_err (pctldev->dev, -"pin %d isn't in the range of %d to %d\n" , - pin, range->pin_base, end); -return -EINVAL ; - } - mux_bytes = pcs->width /BITS_PER_BYTE ; - data = pcs->read (pcs->base + pin * mux_bytes) & ~pcs->fmask; - data |= gpio->gpio_func; - pcs->write (data, pcs->base + pin * mux_bytes); -return 0 ; +return -ENOTSUPP ; }static struct pinmux_ops pcs_pinmux_ops = {
@@ -907,49 +879,6 @@ static void pcs_free_resources(struct pcs_device *pcs)static struct of_device_id pcs_of_match[]; -static int pcs_add_gpio_range (struct device_node *node,struct pcs_device *pcs) -{ -struct pcs_gpio_range *gpio; -struct device_node *child; -struct resource r; -const char name[] ="pinctrl-single" ; -u32 gpiores[PCS_MAX_GPIO_VALUES ]; -int ret, i =0 , mux_bytes =0 ; - -for_each_child_of_node (node, child) { - ret =of_address_to_resource (child,0 , &r); -if (ret <0 ) -continue ; -memset (gpiores,0 ,sizeof (u32) *PCS_MAX_GPIO_VALUES ); - ret =of_property_read_u32_array (child,"pinctrl-single,gpio" , - gpiores,PCS_MAX_GPIO_VALUES ); -if (ret <0 ) -continue ; - gpio =devm_kzalloc (pcs->dev,sizeof (*gpio),GFP_KERNEL ); -if (!gpio) { -dev_err (pcs->dev,"failed to allocate pcs gpio\n" ); -return -ENOMEM ; - } - gpio->range.name =devm_kzalloc (pcs->dev,sizeof (name), -GFP_KERNEL ); -if (!gpio->range.name) { -dev_err (pcs->dev,"failed to allocate range name\n" ); -return -ENOMEM ; - } -memcpy ((char *)gpio->range.name, name,sizeof (name)); - - gpio->range.id = i++; - gpio->range.base = gpiores[0 ]; - gpio->gpio_func = gpiores[1 ]; - mux_bytes = pcs->width /BITS_PER_BYTE ; - gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; - gpio->range.npins = (r.end - r.start) / mux_bytes +1 ; - -pinctrl_add_gpio_range (pcs->pctl, &gpio->range); - } -return 0 ; -} -static int pcs_probe (struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;
@@ -1046,10 +975,6 @@ static int pcs_probe(struct platform_device *pdev) goto free; } - ret =pcs_add_gpio_range (np, pcs); -if (ret <0 ) - goto free; -dev_info (pcs->dev,"%i pins at pa %p size %u\n" , pcs->desc.npins, pcs->base, pcs->size);
Signature · 1 line
1.7.10.4
Tony Lindgren
maintainerPATCH v7 1/15 Revert "pinctrl: single: support gpio request and free"
Quoted 14 lines · Haojian Zhuang
This reverts commit
2e8b2eab94c35d83bb7da71c63b4695f32ddca88.Conflicts:
drivers/pinctrl/pinctrl-single.cERROR: "
__aeabi_uldivmod" [drivers/pinctrl/pinctrl-single.ko] undefined!]Quoted 4 lines · Russell King
The above error happens in builds including pinctrl-single - the reason
is this, whereresource_size_tmay be 64-bit.
Quoted 8 lines
Quoted 3 lines
gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; gpio->range.npins = (r.end - r.start) / mux_bytes + 1;The reason of not fixing this issue and reverting the patch instead is this patch can't handle another case. It's not easy to handle multiple gpios sharing one pin register. So this gpio range feature will be implemented by other patches.
Makes sense to me, I don't think we have any users yet for this:
Quoted 126 lines
--- drivers/pinctrl/pinctrl-single.c | 79 +------------------------------------- 1 file changed, 2 insertions(+), 77 deletions(-)drivers/pinctrl/pinctrl-single.c +2
-77@@ -30,7 +30,6 @@#define PCS_MUX_BITS_NAME "pinctrl-single,bits"#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)#define PCS_OFF_DISABLED ~0U -#define PCS_MAX_GPIO_VALUES 2/** * struct pcs_pingroup - pingroups for a function @@ -78,16 +77,6 @@ struct pcs_function { };/** -* struct pcs_gpio_range - pinctrl gpio range -* @range: subrange of the GPIO number space -* @gpio_func: gpio function value in the pinmux register -*/ -struct pcs_gpio_range { -struct pinctrl_gpio_range range; -int gpio_func; -}; - -/** * struct pcs_data - wrapper for data needed by pinctrl framework * @pa: pindesc array * @cur: index to current element @@ -414,26 +403,9 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, }static int pcs_request_gpio (struct pinctrl_dev *pctldev, -struct pinctrl_gpio_range *range,unsigned pin) +struct pinctrl_gpio_range *range,unsigned offset) { -struct pcs_device *pcs =pinctrl_dev_get_drvdata (pctldev); -struct pcs_gpio_range *gpio =NULL ; -int end, mux_bytes; -unsigned data; - - gpio = container_of(range, struct pcs_gpio_range, range); - end = range->pin_base + range->npins -1 ; -if (pin < range->pin_base || pin > end) { -dev_err (pctldev->dev, -"pin %d isn't in the range of %d to %d\n" , - pin, range->pin_base, end); -return -EINVAL ; - } - mux_bytes = pcs->width /BITS_PER_BYTE ; - data = pcs->read (pcs->base + pin * mux_bytes) & ~pcs->fmask; - data |= gpio->gpio_func; - pcs->write (data, pcs->base + pin * mux_bytes); -return 0 ; +return -ENOTSUPP ; }static struct pinmux_ops pcs_pinmux_ops = {@@ -907,49 +879,6 @@ static void pcs_free_resources(struct pcs_device *pcs)static struct of_device_id pcs_of_match[]; -static int pcs_add_gpio_range (struct device_node *node,struct pcs_device *pcs) -{ -struct pcs_gpio_range *gpio; -struct device_node *child; -struct resource r; -const char name[] ="pinctrl-single" ; -u32 gpiores[PCS_MAX_GPIO_VALUES ]; -int ret, i =0 , mux_bytes =0 ; - -for_each_child_of_node (node, child) { - ret =of_address_to_resource (child,0 , &r); -if (ret <0 ) -continue ; -memset (gpiores,0 ,sizeof (u32) *PCS_MAX_GPIO_VALUES ); - ret =of_property_read_u32_array (child,"pinctrl-single,gpio" , - gpiores,PCS_MAX_GPIO_VALUES ); -if (ret <0 ) -continue ; - gpio =devm_kzalloc (pcs->dev,sizeof (*gpio),GFP_KERNEL ); -if (!gpio) { -dev_err (pcs->dev,"failed to allocate pcs gpio\n" ); -return -ENOMEM ; - } - gpio->range.name =devm_kzalloc (pcs->dev,sizeof (name), -GFP_KERNEL ); -if (!gpio->range.name) { -dev_err (pcs->dev,"failed to allocate range name\n" ); -return -ENOMEM ; - } -memcpy ((char *)gpio->range.name, name,sizeof (name)); - - gpio->range.id = i++; - gpio->range.base = gpiores[0 ]; - gpio->gpio_func = gpiores[1 ]; - mux_bytes = pcs->width /BITS_PER_BYTE ; - gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; - gpio->range.npins = (r.end - r.start) / mux_bytes +1 ; - -pinctrl_add_gpio_range (pcs->pctl, &gpio->range); - } -return 0 ; -} -static int pcs_probe (struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;@@ -1046,10 +975,6 @@ static int pcs_probe(struct platform_device *pdev) goto free; } - ret =pcs_add_gpio_range (np, pcs); -if (ret <0 ) - goto free; -dev_info (pcs->dev,"%i pins at pa %p size %u\n" , pcs->desc.npins, pcs->base, pcs->size);Signature · 1 line
1.7.10.4
Linus Walleij
AppliedPATCH v7 1/15 Revert "pinctrl: single: support gpio request and free"
In reply to Haojian ZhuangQuoted 7 lines · Haojian Zhuang
This reverts commit
2e8b2eab94c35d83bb7da71c63b4695f32ddca88.Conflicts:
drivers/pinctrl/pinctrl-single.cERROR: "
__aeabi_uldivmod" [drivers/pinctrl/pinctrl-single.ko] undefined!]
Applied to fixes with Tony's ACK.
I also took the liberty to add your Signed-off-by.
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 2/15 pinctrl: core: get devname from pinctrl_dev
In reply to Haojian ZhuangAdd new function to get devname from pinctrl_dev. pinctrl_dev_get_name() can only get pinctrl description name. If we want to use gpio driver to find pinctrl device node, we need to fetch the pinctrl device name.
--- drivers/pinctrl/core.c | 6 ++++++ include/linux/pinctrl/pinctrl.h | 1 + 2 files changed, 7 insertions(+)
drivers/pinctrl/core.c +6 -0
@@ -83,6 +83,12 @@ const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev) }EXPORT_SYMBOL_GPL (pinctrl_dev_get_name); +const char *pinctrl_dev_get_devname (struct pinctrl_dev *pctldev) +{ +return dev_name (pctldev->dev); +} +EXPORT_SYMBOL_GPL (pinctrl_dev_get_devname); +void *pinctrl_dev_get_drvdata (struct pinctrl_dev *pctldev) {return pctldev->driver_data;
include/linux/pinctrl/pinctrl.h +1 -0
@@ -154,6 +154,7 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np)#endif /* CONFIG_OF */ extern const char *pinctrl_dev_get_name (struct pinctrl_dev *pctldev); +extern const char *pinctrl_dev_get_devname (struct pinctrl_dev *pctldev);extern void *pinctrl_dev_get_drvdata (struct pinctrl_dev *pctldev);#else
Signature · 1 line
1.7.10.4
PATCH v7 2/15 pinctrl: core: get devname from pinctrl_dev
Quoted 5 lines · Haojian Zhuang
Add new function to get devname from
pinctrl_dev.pinctrl_dev_get_name()can only get pinctrl description name. If we want to use gpio driver to find pinctrl device node, we need to fetch the pinctrl device name.Signed-off-by Haojian Zhuang <[email protected]>
Looks helpful in its own right, patch applied!
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 3/15 gpio: use pinctrl device name for add range
In reply to Haojian Zhuanggpiochip_add_pin_range() needs pinctrl device name as parameter. Currently the parameter is pinctrl description name. So fix it.
--- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpiolib-of.c +1 -1
@@ -250,7 +250,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)* on the same GPIO chip. */ ret =gpiochip_add_pin_range (chip, -pinctrl_dev_get_name (pctldev), +pinctrl_dev_get_devname (pctldev),0 ,/* offset in gpiochip */ pinspec.args[0 ], pinspec.args[1 ]);
Signature · 1 line
1.7.10.4
PATCH v7 3/15 gpio: use pinctrl device name for add range
Quoted 13 lines · Haojian Zhuang
gpiochip_add_pin_range()needs pinctrl device name as parameter. Currently the parameter is pinctrl description name. So fix it.Signed-off-by Haojian Zhuang <[email protected]>--- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/gpio/gpiolib-of.c +0
-0
drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip *chip) · line 256
Quoted 8 lines
drivers/gpio/gpiolib-of.c +1
-1@@ -250,7 +250,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)* on the same GPIO chip. */ ret =gpiochip_add_pin_range (chip, -pinctrl_dev_get_name (pctldev), +pinctrl_dev_get_devname (pctldev),0 ,/* offset in gpiochip */ pinspec.args[0 ], pinspec.args[1 ]);
Hm looks like the right thing to do!
Patch applied.
It must be such that everyone using this so far has just set the name to be identical to the device name.
Maybe we should just drop the name in the descriptor if it's causing problems like this?
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 3/15 gpio: use pinctrl device name for add range
Quoted 29 lines · Linus Walleij
Quoted 13 lines · Haojian Zhuang
gpiochip_add_pin_range()needs pinctrl device name as parameter. Currently the parameter is pinctrl description name. So fix it.Signed-off-by Haojian Zhuang <[email protected]>--- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/gpio/gpiolib-of.c +0
-0drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip *chip) · line 256
Quoted 8 lines
drivers/gpio/gpiolib-of.c +1
-1@@ -250,7 +250,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)* on the same GPIO chip. */ ret =gpiochip_add_pin_range (chip, -pinctrl_dev_get_name (pctldev), +pinctrl_dev_get_devname (pctldev),0 ,/* offset in gpiochip */ pinspec.args[0 ], pinspec.args[1 ]);Hm looks like the right thing to do!
Patch applied.
Quoted 8 lines
It must be such that everyone using this so far has just set the name to be identical to the device name.
Maybe we should just drop the name in the descriptor if it's causing problems like this?
Yours,
Linus Walleij
It seems that dropping the name won't impact any problem. I'll try to drop it in new patches.
Regards
Haojian
Haojian Zhuang
maintainerPATCH v7 4/15 gpio: set gpio range cells property as 3
In reply to Haojian ZhuangAdd gpio offset into "gpio-range-cells" property. It's used to support sparse pinctrl range in gpio chip.
--- Documentation/devicetree/bindings/gpio/gpio.txt | 6 +++--- arch/arm/boot/dts/spear1310.dtsi | 4 ++-- arch/arm/boot/dts/spear1340.dtsi | 4 ++-- arch/arm/boot/dts/spear310.dtsi | 4 ++-- arch/arm/boot/dts/spear320.dtsi | 4 ++-- drivers/gpio/gpiolib-of.c | 7 ++----- 6 files changed, 13 insertions(+), 16 deletions(-)
Documentation/devicetree/bindings/gpio/gpio.txt +3 -3
@@ -98,7 +98,7 @@ announce the pinrange to the pin ctrl subsystem. For example, compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; reg = <0x1460 0x18>; gpio-controller; - gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>; + gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>; }
@@ -107,8 +107,8 @@ where, Next values specify the base pin and number of pins for the range handled by 'qe_pio_e' gpio. In the given example from base pin 20 to - pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled - by this gpio controller. + pin 29 under pinctrl1 with gpio offset 0 and pin 50 to pin 69 under + pinctrl2 with gpio offset 10 is handled by this gpio controller. The pinctrl node must have "#gpio-range-cells" property to show number of arguments to pass with phandle from gpio controllers node.
arch/arm/boot/dts/spear1310.dtsi +2 -2
@@ -89,7 +89,7 @@ pinmux: pinmux at e0700000 { compatible = "st,spear1310-pinmux"; reg = <0xe0700000 0x1000>; - #gpio-range-cells = <2>; + #gpio-range-cells = <3>; }; apb {
@@ -212,7 +212,7 @@ interrupt-controller; gpio-controller; #gpio-cells = <2>; - gpio-ranges = <&pinmux 0 246>; + gpio-ranges = <&pinmux 0 0 246>; status = "disabled"; st-plgpio,ngpio = <246>;
arch/arm/boot/dts/spear1340.dtsi +2 -2
@@ -63,7 +63,7 @@ pinmux: pinmux at e0700000 { compatible = "st,spear1340-pinmux"; reg = <0xe0700000 0x1000>; - #gpio-range-cells = <2>; + #gpio-range-cells = <3>; }; pwm: pwm at e0180000 {
@@ -127,7 +127,7 @@ interrupt-controller; gpio-controller; #gpio-cells = <2>; - gpio-ranges = <&pinmux 0 252>; + gpio-ranges = <&pinmux 0 0 252>; status = "disabled"; st-plgpio,ngpio = <250>;
arch/arm/boot/dts/spear310.dtsi +2 -2
@@ -25,7 +25,7 @@ pinmux: pinmux at b4000000 { compatible = "st,spear310-pinmux"; reg = <0xb4000000 0x1000>; - #gpio-range-cells = <2>; + #gpio-range-cells = <3>; }; fsmc: flash at 44000000 {
@@ -102,7 +102,7 @@ interrupt-controller; gpio-controller; #gpio-cells = <2>; - gpio-ranges = <&pinmux 0 102>; + gpio-ranges = <&pinmux 0 0 102>; status = "disabled"; st-plgpio,ngpio = <102>;
arch/arm/boot/dts/spear320.dtsi +2 -2
@@ -24,7 +24,7 @@ pinmux: pinmux at b3000000 { compatible = "st,spear320-pinmux"; reg = <0xb3000000 0x1000>; - #gpio-range-cells = <2>; + #gpio-range-cells = <3>; }; clcd at 90000000 {
@@ -130,7 +130,7 @@ interrupt-controller; gpio-controller; #gpio-cells = <2>; - gpio-ranges = <&pinmux 0 102>; + gpio-ranges = <&pinmux 0 0 102>; status = "disabled"; st-plgpio,ngpio = <102>;
drivers/gpio/gpiolib-of.c +2 -5
@@ -245,15 +245,12 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)* to add different ranges for one and the same GPIO chip, * as the code assumes that we have one consecutive range * on both, mapping 1-to-1. -* -* TODO: make the OF bindings handle multiple sparse ranges -* on the same GPIO chip. */ ret =gpiochip_add_pin_range (chip,pinctrl_dev_get_devname (pctldev), -0 ,/* offset in gpiochip */ pinspec.args[0 ], - pinspec.args[1 ]); + pinspec.args[1 ], + pinspec.args[2 ]);if (ret)break ;
Signature · 1 line
1.7.10.4
PATCH v7 4/15 gpio: set gpio range cells property as 3
Quoted 4 lines · Haojian Zhuang
Add gpio offset into "gpio-range-cells" property. It's used to support sparse pinctrl range in gpio chip.
Signed-off-by Haojian Zhuang <[email protected]>
Need Shiraz to comment on this.
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 5/15 gpio: fix wrong checking condition for gpio range
In reply to Haojian ZhuangSince index++ calculates from 0, the checking condition of "while (index++)" is always fake. So replace it by unconditional loop.
--- drivers/gpio/gpiolib-of.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpio/gpiolib-of.c +3 -3
@@ -228,7 +228,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (!np)return ; - do { +for (;;) { ret =of_parse_phandle_with_args (np,"gpio-ranges" ,"#gpio-range-cells" , index, &pinspec);if (ret)
@@ -254,8 +254,8 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (ret)break ; - - }while (index++); + index++; + } }#else
Signature · 1 line
1.7.10.4
PATCH v7 5/15 gpio: fix wrong checking condition for gpio range
Hello.
Quoted 13 lines · Haojian Zhuang
Since index++ calculates from 0, the checking condition of "while (index++)" is always fake. So replace it by unconditional loop.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/gpio/gpiolib-of.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/gpio/gpiolib-of.c +0
-0
drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip *chip) · line 231
Quoted 5 lines
drivers/gpio/gpiolib-of.c +1
-1@@ -228,7 +228,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (!np)return ; - do { +for (;;) {
Why not:
for (;; index++) {drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip *chip) · line 259
Quoted 12 lines
drivers/gpio/gpiolib-of.c +2
-2ret =of_parse_phandle_with_args (np,"gpio-ranges" ,"#gpio-range-cells" , index, &pinspec);if (ret)@@ -254,8 +254,8 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (ret)break ; - - }while (index++); + index++; + } }
WBR, Sergei
Haojian Zhuang
maintainerPATCH v7 5/15 gpio: fix wrong checking condition for gpio range
Quoted 24 lines · Sergei Shtylyov
Hello.
Quoted 19 lines · Haojian Zhuang
Since index++ calculates from 0, the checking condition of "while (index++)" is always fake. So replace it by unconditional loop.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/gpio/gpiolib-of.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/gpio/gpiolib-of.c +0
-0@@ -228,7 +228,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (!np)return ;
Quoted 8 lines
drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip *chip) · line 231
Quoted 2 lines
drivers/gpio/gpiolib-of.c +1
-1- do { +for (;;) {Why not: for (;; index++) {
OK. I'll update it.
Quoted 18 lines
Quoted 5 lines
drivers/gpio/gpiolib-of.c +0
-0ret =of_parse_phandle_with_args (np,"gpio-ranges" ,"#gpio-range-cells" , index, &pinspec);if (ret)
drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip · line 260
Quoted 9 lines
drivers/gpio/gpiolib-of.c +2
-2@@ -254,8 +254,8 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (ret)break ; - - }while (index++); + index++; + } }WBR, Sergei
PATCH v7 5/15 gpio: fix wrong checking condition for gpio range
In reply to Haojian ZhuangQuoted 2 lines · Haojian Zhuang
Since index++ calculates from 0, the checking condition of "while (index++)" is always fake.
You meanbt "false"? Actually if 'index' starts from 0, the loop will end
after the first iteration.
Quoted 21 lines
So replace it by unconditional loop.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/gpio/gpiolib-of.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/gpio/gpiolib-of.c +1
-1@@ -228,7 +228,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (!np)return ; - do { +for (;;) { ret =of_parse_phandle_with_args (np,"gpio-ranges" ,"#gpio-range-cells" , index, &pinspec);if (ret)
drivers/gpio/gpiolib-of.c static void of_gpiochip_add_pin_range(struct gpio_chip *chip) · line 259
Quoted 8 lines
drivers/gpio/gpiolib-of.c +2
-2@@ -254,8 +254,8 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)if (ret)break ; - - }while (index++); + index++; + } }
WBR, Sergei
Haojian Zhuang
maintainerPATCH v7 6/15 gpio: find gpio base by ascend order
In reply to Haojian Zhuanggpiochip_find_base() always tries to find valid gpio with descend order. It's inconvient if gpio information is passing from DTS. Now try to find valid gpio with ascend order.
--- drivers/gpio/gpiolib.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/gpio/gpiolib.c +10 -9
@@ -128,20 +128,21 @@ static int gpiochip_find_base(int ngpio)int spare =0 ;int base = -ENOSPC ; -for (i =ARCH_NR_GPIOS -1 ; i >=0 ; i--) { +for (i =0 , base =0 ; i <ARCH_NR_GPIOS ; i++) {struct gpio_desc *desc = &gpio_desc[i];struct gpio_chip *chip = desc->chip; -if (!chip && !test_bit (FLAG_RESERVED , &desc->flags)) { +if (chip) { + spare =0 ; + i += chip->ngpio -1 ; + base = i +1 ; + }else if (test_bit (FLAG_RESERVED , &desc->flags)) { + spare =0 ; + base = i +1 ; + }else { spare++; -if (spare == ngpio) { - base = i; +if (spare == ngpio)break ; - } - }else { - spare =0 ; -if (chip) - i -= chip->ngpio -1 ; } }
Signature · 1 line
1.7.10.4
PATCH v7 6/15 gpio: find gpio base by ascend order
Quoted 5 lines · Haojian Zhuang
gpiochip_find_base()always tries to find valid gpio with descend order. It's inconvient if gpio information is passing from DTS. Now try to find valid gpio with ascend order.Signed-off-by Haojian Zhuang <[email protected]>
Grant, can you comment on this?
You know DT and GPIO better than me....
Yours,
Linus Walleij
PATCH v7 6/15 gpio: find gpio base by ascend order
In reply to Haojian ZhuangQuoted 3 lines · Haojian Zhuang
gpiochip_find_base()always tries to find valid gpio with descend order. It's inconvient if gpio information is passing from DTS. Now try to find valid gpio with ascend order.
Why is it more convenient? Just to make the numbers smaller? The reason it uses a descending search is to mimimize the possibility of collision with fixed GPIO numbers.
g.
Haojian Zhuang
maintainerPATCH v7 6/15 gpio: find gpio base by ascend order
Quoted 11 lines · Grant Likely
Quoted 3 lines · Haojian Zhuang
gpiochip_find_base()always tries to find valid gpio with descend order. It's inconvient if gpio information is passing from DTS. Now try to find valid gpio with ascend order.Why is it more convenient? Just to make the numbers smaller? The reason it uses a descending search is to mimimize the possibility of collision with fixed GPIO numbers.
g.
I tried to parse global gpio number dynamically from DT, so I also used gpiochip_find_base() to seek gpio number. If it's descending order, all the gpio number are not also descending order. It will be inconvenient for linking it to SoC datasheet & schematic. Since changing it to ascending order may break user space application, Linus NACKed.
Now I'm trying to use fixed gpio number from machine driver.
Regards
Haojian
Haojian Zhuang
maintainerPATCH v7 7/15 gpio: pl061: allocate irq dynamically
In reply to Haojian ZhuangIn original implementation, irq base is always specified in platform data. If it's not specified, pl061 gpio driver can't pass the probe() function since irq base is missing. While moving to device tree, everything should be parsed from DTS file. So allocate irq dynamically for irq base.
--- drivers/gpio/gpio-pl061.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/gpio/gpio-pl061.c +12 -3
@@ -15,6 +15,7 @@#include <linux/io.h> #include <linux/ioport.h> #include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/bitops.h> #include <linux/workqueue.h> #include <linux/gpio.h>
@@ -211,6 +212,10 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); } +static const struct irq_domain_ops pl061_domain_ops = { + .xlate = irq_domain_xlate_twocell, +}; +static int pl061_probe (struct amba_device *adev,const struct amba_id *id) {struct device *dev = &adev->dev;
@@ -225,10 +230,14 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)if (pdata) { chip->gc.base = pdata->gpio_base; chip->irq_base = pdata->irq_base; - }else if (adev->dev.of_node) { + }else { chip->gc.base =-1 ; - chip->irq_base =0 ; - }else + chip->irq_base =irq_alloc_descs (-1 ,0 ,PL061_GPIO_NR ,0 ); +if (chip->irq_base <0 ) +return chip->irq_base; + } +if (!irq_domain_add_legacy (adev->dev.of_node,PL061_GPIO_NR , + chip->irq_base,0 , &pl061_domain_ops, chip))return -ENODEV ; if (!devm_request_mem_region(dev, adev->res.start,
Signature · 1 line
1.7.10.4
Haojian Zhuang
maintainerPATCH v7 8/15 gpio: pl061: bind pinctrl by gpio request
In reply to Haojian ZhuangAdd the pl061_gpio_request() to request pinctrl. Create the logic between pl061 gpio driver and pinctrl (pinctrl-single) driver.
While a gpio pin is requested, it will request pinctrl driver to set that pin with gpio function mode. So pinctrl driver should append .gpio_request_enable() in pinmux_ops.
--- drivers/gpio/gpio-pl061.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
drivers/gpio/gpio-pl061.c +19 -0
@@ -23,6 +23,7 @@#include <linux/amba/bus.h> #include <linux/amba/pl061.h> #include <linux/slab.h> +#include <linux/pinctrl/consumer.h> #include <linux/pm.h> #include <asm/mach/irq.h>
@@ -61,6 +62,23 @@ struct pl061_gpio {#endif }; +static int pl061_gpio_request (struct gpio_chip *chip,unsigned offset) +{ +/* +* Map back to global GPIO space and request muxing, the direction +* parameter does not matter for this controller. +*/ +int gpio = chip->base + offset; + +/* +* Do NOT check the return value at here. Since sometimes the gpio +* pin needn't to be configured in pinmux controller. So it's +* impossible to find the matched gpio range. +*/ +pinctrl_request_gpio (gpio); +return 0 ; +} +static int pl061_direction_input (struct gpio_chip *gc,unsigned offset) { struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@@ -251,6 +269,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)spin_lock_init (&chip->lock); + chip->gc.request = pl061_gpio_request; chip->gc.direction_input = pl061_direction_input; chip->gc.direction_output = pl061_direction_output; chip->gc.get = pl061_get_value;
Signature · 1 line
1.7.10.4
PATCH v7 8/15 gpio: pl061: bind pinctrl by gpio request
Quoted 8 lines · Haojian Zhuang
Add the
pl061_gpio_request()to request pinctrl. Create the logic between pl061 gpio driver and pinctrl (pinctrl-single) driver.While a gpio pin is requested, it will request pinctrl driver to set that pin with gpio function mode. So pinctrl driver should append .gpio_request_enable() in
pinmux_ops.Signed-off-by Haojian Zhuang <[email protected]>
(...)
Quoted 4 lines
drivers/gpio/gpio-pl061.c +4
-0+static int pl061_gpio_request (struct gpio_chip *chip,unsigned offset) +{ +/* +* Map back to global GPIO space and request muxing, the direction
drivers/gpio/gpio-pl061.c struct pl061_gpio { · line 78
Quoted 10 lines
drivers/gpio/gpio-pl061.c +10
-0+* parameter does not matter for this controller. +*/ +int gpio = chip->base + offset; + +/* +* Do NOT check the return value at here. Since sometimes the gpio +* pin needn't to be configured in pinmux controller. So it's +* impossible to find the matched gpio range. +*/ +pinctrl_request_gpio (gpio);
Handling of error code?
(Maybe I should add a __must_check on this function.)
Quoted 7 lines
drivers/gpio/gpio-pl061.c +3
-0+return 0 ; +} +static int pl061_direction_input (struct gpio_chip *gc,unsigned offset) { struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
drivers/gpio/gpio-pl061.c static int pl061_probe(struct amba_device *adev, const struct amba_id *id) · line 275
Quoted 7 lines
drivers/gpio/gpio-pl061.c +1
-0@@ -251,6 +269,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)spin_lock_init (&chip->lock); + chip->gc.request = pl061_gpio_request; chip->gc.direction_input = pl061_direction_input; chip->gc.direction_output = pl061_direction_output; chip->gc.get = pl061_get_value;
What happens on a platform that has a PL061 GPIO block but no pinctrl related to it?
But still has some other pinctrl driver in the platform ....
Right, it'll return -EPROBE_DEFER from pinctrl_request_gpio().
This may happen on for example a combined SPEAr kernel where some platforms have PL061 and others us a pin controller, so both will be enabled.
I think, add a field like this to struct pl061_gpio:
bool has_pinctrl_backend;
The only call that from pl061_gpio_request() if this is set:
if (pl061->has_pinctrl_backend)
ret = pinctrl_request_gpio(gpio);
Then assign it in some clever way. For DT I think the proper way would be so add a cross-binding to the pin controller, like:
gpio2: gpio at d8100000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
(...)
pinctrl = <&mr_pincontrol>;
};Then just check if you have this pinctrl binding set to figure out if has_pinctrl_backend should be true.
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 8/15 gpio: pl061: bind pinctrl by gpio request
Quoted 30 lines · Linus Walleij
Quoted 8 lines · Haojian Zhuang
Add the
pl061_gpio_request()to request pinctrl. Create the logic between pl061 gpio driver and pinctrl (pinctrl-single) driver.While a gpio pin is requested, it will request pinctrl driver to set that pin with gpio function mode. So pinctrl driver should append .gpio_request_enable() in
pinmux_ops.Signed-off-by Haojian Zhuang <[email protected]>(...)
Quoted 4 lines
drivers/gpio/gpio-pl061.c +4
-0+static int pl061_gpio_request (struct gpio_chip *chip,unsigned offset) +{ +/* +* Map back to global GPIO space and request muxing, the direction drivers/gpio/gpio-pl061.c struct pl061_gpio { · line 78
Quoted 10 lines
drivers/gpio/gpio-pl061.c +10
-0+* parameter does not matter for this controller. +*/ +int gpio = chip->base + offset; + +/* +* Do NOT check the return value at here. Since sometimes the gpio +* pin needn't to be configured in pinmux controller. So it's +* impossible to find the matched gpio range. +*/ +pinctrl_request_gpio (gpio);Handling of error code?
Quoted 2 lines
(Maybe I should add a
__must_checkon this function.)
My case is a little special. I don't want to check return value because some gpio pins don't have pinmux registers in Hisilicon SoC.
So pinctrl_request_gpio() will always return error for these special pins in Hisilicon SoC.
If we must check the return value, maybe we need append a dummy pinctrl driver for those special gpio pins. How do you think about it? Of course, I need to evaluate
whether it's possible to implement.
Quoted 28 lines
Quoted 7 lines
drivers/gpio/gpio-pl061.c +3
-0+return 0 ; +} +static int pl061_direction_input (struct gpio_chip *gc,unsigned offset) { struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);drivers/gpio/gpio-pl061.c static int pl061_probe(struct amba_device *adev, const struct amba_id *id) · line 275
Quoted 7 lines
drivers/gpio/gpio-pl061.c +1
-0@@ -251,6 +269,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)spin_lock_init (&chip->lock); + chip->gc.request = pl061_gpio_request; chip->gc.direction_input = pl061_direction_input; chip->gc.direction_output = pl061_direction_output; chip->gc.get = pl061_get_value;What happens on a platform that has a PL061 GPIO block but no pinctrl related to it?
But still has some other pinctrl driver in the platform ....
Right, it'll return -EPROBE_DEFER from
pinctrl_request_gpio().This may happen on for example a combined SPEAr kernel where some platforms have PL061 and others us a pin controller, so both will be enabled.
I think, add a field like this to struct
pl061_gpio:
Quoted 7 lines
bool
has_pinctrl_backend;The only call that from
pl061_gpio_request()if this is set:if (
pl061->has_pinctrl_backend)
ret =pinctrl_request_gpio(gpio);
I'm OK to append "has_pinctrl_backend". But if we append a dummy pinctrl driver, is it OK to SPEAr kernel? Do we still need has_pinctrl_backend?
Quoted 11 lines
Then assign it in some clever way. For DT I think the proper way would be so add a cross-binding to the pin controller, like:
gpio2: gpio at d8100000 { #gpio-cells = <2>; compatible = "arm,pl061", "arm,primecell"; (...) pinctrl = <&mr_pincontrol>; };
If we could append a dummy pinctrl driver, maybe we needn't to append pinctrl property into gpio node. What's your opinion?
Quoted 6 lines
Then just check if you have this pinctrl binding set to figure out if
has_pinctrl_backendshould be true.Yours,
Linus Walleij
Regards
Haojian
PATCH v7 8/15 gpio: pl061: bind pinctrl by gpio request
Quoted 11 lines · Haojian Zhuang
Quoted 6 lines
Quoted 1 line
+
pinctrl_request_gpio(gpio);Handling of error code?
(Maybe I should add a
__must_checkon this function.)My case is a little special. I don't want to check return value because some gpio pins don't have pinmux registers in Hisilicon SoC.
Sopinctrl_request_gpio()will always return error for these special pins in Hisilicon SoC.
Quoted 4 lines
If we must check the return value, maybe we need append a dummy pinctrl driver for those special gpio pins. How do you think about it? Of course, I need to evaluate
whether it's possible to implement.
Hm. A dummy pinctrl back-end is not very elegant.
It's better if the GPIO driver (gpio-pl061) keep track of the ranges that are connected to the pinctrl.
If the ranges are encoded in the device tree (as I guess you want to do in this case) then the GPIO driver need to check these ranges to see if it uses a pinctrl backend. Magic behind-the-scenes is very hard to understand for people reading this code later.
What about this:
In gpiolib.c, function gpiochip_add_pin_range(), we save a copy of each range in &chip->pin_ranges.
Add a function to gpiolib.c to check if a certain gpio is in the range of the current chip.
Then use that:
if (gpio_in_pinrange(gpio))
pinctrl_request_gpio(gpio);
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 8/15 gpio: pl061: bind pinctrl by gpio request
Quoted 37 lines · Linus Walleij
Quoted 11 lines · Haojian Zhuang
Quoted 6 lines
Quoted 1 line
+
pinctrl_request_gpio(gpio);Handling of error code?
(Maybe I should add a
__must_checkon this function.)My case is a little special. I don't want to check return value because some gpio pins don't have pinmux registers in Hisilicon SoC.
Sopinctrl_request_gpio()will always return error for these special pins in Hisilicon SoC.Quoted 4 lines
If we must check the return value, maybe we need append a dummy pinctrl driver for those special gpio pins. How do you think about it? Of course, I need to evaluate
whether it's possible to implement.Hm. A dummy pinctrl back-end is not very elegant.
It's better if the GPIO driver (gpio-pl061) keep track of the ranges that are connected to the pinctrl.
If the ranges are encoded in the device tree (as I guess you want to do in this case) then the GPIO driver need to check these ranges to see if it uses a pinctrl backend. Magic behind-the-scenes is very hard to understand for people reading this code later.
What about this:
In
gpiolib.c, functiongpiochip_add_pin_range(), we save a copy of each range in&chip->pin_ranges.Add a function to
gpiolib.cto check if a certain gpio is in the range of the current chip.
Quoted 7 lines
Then use that:
if (
gpio_in_pinrange(gpio))pinctrl_request_gpio(gpio);Yours,
Linus Walleij
It seems better. I'll update it.
Regards
Haojian
PATCH v7 8/15 gpio: pl061: bind pinctrl by gpio request
Quoted 5 lines · Haojian Zhuang
Quoted 5 lines
Add a function to
gpiolib.cto check if a certain gpio is in the range of the current chip.Then use that:
Quoted 7 lines
Quoted 5 lines
if (
gpio_in_pinrange(gpio))pinctrl_request_gpio(gpio);Yours,
Linus WalleijIt seems better. I'll update it.
Hm the function above will need to pass the chip as parameter as well, so a bit simplified.
Maybe it's better to add a function like gpio_check_pinctrl_backend(chip, gpio); that does the above two statements?
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 9/15 gpio: pl061: set initcall level to module init
In reply to Haojian ZhuangReplace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level.
--- drivers/gpio/gpio-pl061.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpio-pl061.c +1 -1
@@ -393,7 +393,7 @@ static int __init pl061_gpio_init(void) {return amba_driver_register (&pl061_gpio_driver); } -subsys_initcall (pl061_gpio_init); +module_init (pl061_gpio_init);MODULE_AUTHOR ("Baruch Siach <[email protected]>" );MODULE_DESCRIPTION ("PL061 GPIO driver" );
Signature · 1 line
1.7.10.4
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Quoted 5 lines · Haojian Zhuang
Replace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level.
Signed-off-by Haojian Zhuang <[email protected]>
On you platform maybe it works, but have you made sure that nobody else will be affected?
SPEAr of course, then these:
arch/arm/mach-realview/core.c: * GPIO on PL061 is active,
which is the properarch/arm/mach-socfpga/Kconfig: select GPIO_PL061 if GPIOLIB
Pawel, Dinh: are you OK with this change?
Yours,
Linus Walleij
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Quoted 12 lines · Linus Walleij
Quoted 5 lines · Haojian Zhuang
Replace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level.
Signed-off-by Haojian Zhuang <[email protected]>On you platform maybe it works, but have you made sure that nobody else will be affected?
Quoted 7 lines
SPEAr of course, then these:
arch/arm/mach-realview/core.c: * GPIO on PL061 is active,
which is the properarch/arm/mach-socfpga/Kconfig: selectGPIO_PL061if GPIOLIBPawel, Dinh: are you OK with this change?
Hm. Doesn't this make the MMCI probing depending on the module_init order? As in: wouldn't it make the mmci probe completely fail (not even defer it) if it was called before the pl061? In that case even your, Linus, hack with inverting the CD status wouldn't work...
Pawel
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Hi Linus,
Quoted 13 lines · Pawel Moll
Quoted 12 lines · Linus Walleij
Quoted 5 lines · Haojian Zhuang
Replace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level.
Signed-off-by Haojian Zhuang <[email protected]>On you platform maybe it works, but have you made sure that nobody else will be affected?
Quoted 7 lines
Quoted 7 lines
SPEAr of course, then these:
arch/arm/mach-realview/core.c: * GPIO on PL061 is active,
which is the properarch/arm/mach-socfpga/Kconfig: selectGPIO_PL061if GPIOLIBPawel, Dinh: are you OK with this change?
Still works ok on mach-socfpga.
Dinh
Quoted 11 lines
Hm. Doesn't this make the MMCI probing depending on the
module_initorder? As in: wouldn't it make the mmci probe completely fail (not even defer it) if it was called before the pl061? In that case even your, Linus, hack with inverting the CD status wouldn't work...Pawel
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Quoted 3 lines · Dinh Nguyen
Quoted 1 line
Quoted 1 line
Pawel, Dinh: are you OK with this change?
Still works ok on mach-socfpga.
Thanks! Adding your Tested-by tag, OK?
Yours,
Linus Walleij
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Hi Linus,
Quoted 7 lines · Linus Walleij
Quoted 3 lines · Dinh Nguyen
Quoted 1 line
Quoted 1 line
Pawel, Dinh: are you OK with this change?
Still works ok on mach-socfpga.
Thanks! Adding your Tested-by tag, OK?
Yep, thanks.
Dinh
Quoted 4 lines
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 9/15 gpio: pl061: set initcall level to module init
In reply to Pawel MollQuoted 19 lines · Pawel Moll
Quoted 18 lines · Linus Walleij
Quoted 5 lines · Haojian Zhuang
Replace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level.
Signed-off-by Haojian Zhuang <[email protected]>On you platform maybe it works, but have you made sure that nobody else will be affected?
SPEAr of course, then these:
arch/arm/mach-realview/core.c: * GPIO on PL061 is active,
which is the properarch/arm/mach-socfpga/Kconfig: selectGPIO_PL061if GPIOLIB
Quoted 11 lines
Quoted 1 line
Pawel, Dinh: are you OK with this change?
Hm. Doesn't this make the MMCI probing depending on the
module_initorder? As in: wouldn't it make the mmci probe completely fail (not even defer it) if it was called before the pl061? In that case even your, Linus, hack with inverting the CD status wouldn't work...Pawel
The sequence of module probe is pinctrl --> gpio --> mmc. So the dependance of mmc on gpio isn't broken.
Regards
Haojian
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Quoted 2 lines · Haojian Zhuang
The sequence of module probe is pinctrl --> gpio --> mmc. So the dependance of mmc on gpio isn't broken.
I don't think you can guarantee the "gpio --> mmc" sequence if both drivers use module_init (the order could be completely random, generally it depends on what Kbuild is doing), but if gpio_request() behaves as Linus said, the sequence in the problematic scenario would be "pinctrl --> mmc --> EPROBE_DEFER --> gpio --> mmc" which is fine (subject to mmci driver fix, but it's a separate issue).
Pawe?
PATCH v7 9/15 gpio: pl061: set initcall level to module init
In reply to Pawel MollQuoted 4 lines · Pawel Moll
Hm. Doesn't this make the MMCI probing depending on the
module_initorder? As in: wouldn't it make the mmci probe completely fail (not even defer it) if it was called before the pl061? In that case even your, Linus, hack with inverting the CD status wouldn't work...
According to Haojian it works, but for sure the MMCI driver *should* (on the eternal list of SHOULDDO) bail out and return any -EPROBE_DEFER up to the AMBA bus core properly so it
will be tried again later if this happens.
AFAICT gpio_request() will return -EPROBE_DEFER if the GPIO cannot be located.
Yours,
Linus Walleij
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Quoted 2 lines · Linus Walleij
AFAICT
gpio_request()will return -EPROBE_DEFER if the GPIO cannot be located.
If it does, I withdraw all my objections.
Cheers!
Pawe?
PATCH v7 9/15 gpio: pl061: set initcall level to module init
In reply to Linus WalleijQuoted 9 lines · Linus Walleij
Quoted 4 lines · Pawel Moll
Hm. Doesn't this make the MMCI probing depending on the
module_initorder? As in: wouldn't it make the mmci probe completely fail (not even defer it) if it was called before the pl061? In that case even your, Linus, hack with inverting the CD status wouldn't work...According to Haojian it works, but for sure the MMCI driver *should* (on the eternal list of SHOULDDO) bail out and return any
Rather than talking about what should and should not, why not look at the code - it only takes a few moments to check what the behaviour would be. And it is correct - errors are correctly propagated out of the probe function.
That's hardly surprising given who's supposed to be the maintainer of that driver.
PATCH v7 9/15 gpio: pl061: set initcall level to module init
Quoted 8 lines · Russell King - ARM Linux
Quoted 7 lines · Linus Walleij
Quoted 4 lines · Pawel Moll
Hm. Doesn't this make the MMCI probing depending on the
module_initorder? As in: wouldn't it make the mmci probe completely fail (not even defer it) if it was called before the pl061? In that case even your, Linus, hack with inverting the CD status wouldn't work...
Quoted 7 lines
Quoted 2 lines
According to Haojian it works, but for sure the MMCI driver *should* (on the eternal list of SHOULDDO) bail out and return any
Rather than talking about what should and should not, why not look at the code - it only takes a few moments to check what the behaviour would be. And it is correct - errors are correctly propagated out of the probe function.
OK good!
Quoted 2 lines
That's hardly surprising given who's supposed to be the maintainer of that driver.
Aouh that hurt! ;-)
Thanks Russell,
Linus Walleij
PATCH v7 9/15 gpio: pl061: set initcall level to module init
In reply to Haojian ZhuangQuoted 5 lines · Haojian Zhuang
Replace subsys initcall by module initcall level. Since pinctrl driver is already launched before gpio driver. It's unnecessary to set gpio driver in subsys init call level.
Signed-off-by Haojian Zhuang <[email protected]>
OK some consensus that this works, and moving initcalls to module_init() should be encouraged, so applied this and thrown at linux-next for testing. No pain no gain.
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 10/15 pinctrl: single: create new gpio function range
In reply to Haojian ZhuangSince gpio driver could create gpio range in DTS, it could invokes pinctrl_request_gpio(). In the pinctrl-single driver, it needs to configure pins with gpio function mode.
A new gpio function range should be created in DTS file in below.
pinctrl-single,gpio-range = <phandle pin_offset nr_pins gpio_func>;
range: gpio-range {
#pinctrl-single,gpio-range-cells = <3>;
};The difference between gpio-ranges property in gpio driver and pinctrl-single,gpio-range property in pinctrl-single driver.
1. gpio-ranges = <phandle gpio_offset_in_chip pin_offset nr_pins>
gpio-ranges = < &pmx0 0 89 1 &pmx0 1 89 1 &pmx0 2 90 1 &pmx0 3 90 1 &pmx0 4 91 1 &pmx0 5 92 1>;
2. gpio driver could get pin offset from gpio-ranges property. pinctrl-single driver could get gpio function mode from gpio_func that is stored in @gpiofuncs list in struct pcs_device. This new pinctrl-single,gpio-range is used as complement for gpio-ranges property in gpio driver.
--- drivers/pinctrl/pinctrl-single.c | 73 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-)
drivers/pinctrl/pinctrl-single.c +71 -2
@@ -77,6 +77,20 @@ struct pcs_function { };/** +* struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function +* @offset: offset base of pins +* @npins: number pins with the same mux value of gpio function +* @gpiofunc: mux value of gpio function +* @node: list node +*/ +struct pcs_gpiofunc_range { +unsigned offset; +unsigned npins; +unsigned gpiofunc; +struct list_head node; +}; + +/** * struct pcs_data - wrapper for data needed by pinctrl framework * @pa: pindesc array * @cur: index to current element
@@ -123,6 +137,7 @@ struct pcs_name {* @ftree: function index radix tree * @pingroups: list of pingroups * @functions: list of functions +* @gpiofuncs: list of gpio functions * @ngroups: number of pingroups * @nfuncs: number of functions * @desc: pin controller descriptor
@@ -148,6 +163,7 @@ struct pcs_device {struct radix_tree_root ftree;struct list_head pingroups;struct list_head functions; +struct list_head gpiofuncs;unsigned ngroups;unsigned nfuncs;struct pinctrl_desc desc;
@@ -403,9 +419,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, }static int pcs_request_gpio (struct pinctrl_dev *pctldev, -struct pinctrl_gpio_range *range,unsigned offset) +struct pinctrl_gpio_range *range,unsigned pin) { -return -ENOTSUPP ; +struct pcs_device *pcs =pinctrl_dev_get_drvdata (pctldev); +struct pcs_gpiofunc_range *frange =NULL ; +struct list_head *pos, *tmp; +int mux_bytes =0 ; +unsigned data; + +list_for_each_safe (pos, tmp, &pcs->gpiofuncs) { + frange = list_entry(pos, struct pcs_gpiofunc_range, node); +if (pin >= frange->offset + frange->npins + || pin < frange->offset) +continue ; + mux_bytes = pcs->width /BITS_PER_BYTE ; + data = pcs->read (pcs->base + pin * mux_bytes) & ~pcs->fmask; + data |= frange->gpiofunc; + pcs->write (data, pcs->base + pin * mux_bytes); +break ; + } +return 0 ; }static struct pinmux_ops pcs_pinmux_ops = {
@@ -879,6 +912,37 @@ static void pcs_free_resources(struct pcs_device *pcs)static struct of_device_id pcs_of_match[]; +static int pcs_add_gpio_func (struct device_node *node,struct pcs_device *pcs) +{ +const char *propname ="pinctrl-single,gpio-range" ; +const char *cellname ="#pinctrl-single,gpio-range-cells" ; +struct of_phandle_args gpiospec; +struct pcs_gpiofunc_range *range; +int ret, i; + +for (i =0 ; ; i++) { + ret =of_parse_phandle_with_args (node, propname, cellname, + i, &gpiospec); +/* Do not treat it as error. Only treat it as end condition. */ +if (ret) { + ret =0 ; +break ; + } + range =devm_kzalloc (pcs->dev,sizeof (*range),GFP_KERNEL ); +if (!range) { + ret = -ENOMEM ; +break ; + } + range->offset = gpiospec.args[0 ]; + range->npins = gpiospec.args[1 ]; + range->gpiofunc = gpiospec.args[2 ]; +mutex_lock (&pcs->mutex); +list_add_tail (&range->node, &pcs->gpiofuncs); +mutex_unlock (&pcs->mutex); + } +return ret; +} +static int pcs_probe (struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;
@@ -900,6 +964,7 @@ static int pcs_probe(struct platform_device *pdev)mutex_init (&pcs->mutex);INIT_LIST_HEAD (&pcs->pingroups);INIT_LIST_HEAD (&pcs->functions); +INIT_LIST_HEAD (&pcs->gpiofuncs);PCS_GET_PROP_U32 ("pinctrl-single,register-width" , &pcs->width,"register width not specified\n" );
@@ -975,6 +1040,10 @@ static int pcs_probe(struct platform_device *pdev) goto free; } + ret =pcs_add_gpio_func (np, pcs); +if (ret <0 ) + goto free; +dev_info (pcs->dev,"%i pins at pa %p size %u\n" , pcs->desc.npins, pcs->base, pcs->size);
Signature · 1 line
1.7.10.4
Haojian Zhuang
maintainerPATCH v7 11/15 pinctrl: generic: add slew rate config parameter
In reply to Haojian ZhuangAdd PIN_CONFIG_SLEW_RATE parameter into pinconf-generic driver.
--- drivers/pinctrl/pinconf-generic.c | 1 + include/linux/pinctrl/pinconf-generic.h | 4 ++++ 2 files changed, 5 insertions(+)
drivers/pinctrl/pinconf-generic.c +1 -0
@@ -45,6 +45,7 @@ struct pin_config_item conf_items[] = {PCONFDUMP (PIN_CONFIG_INPUT_SCHMITT ,"input schmitt trigger" ,NULL ),PCONFDUMP (PIN_CONFIG_INPUT_DEBOUNCE ,"input debounce" ,"time units" ),PCONFDUMP (PIN_CONFIG_POWER_SOURCE ,"pin power source" ,"selector" ), +PCONFDUMP (PIN_CONFIG_SLEW_RATE ,"slew rate" ,NULL ), PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"), };
include/linux/pinctrl/pinconf-generic.h +4 -0
@@ -58,6 +58,9 @@* @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power * supplies, the argument to this parameter (on a custom format) tells * the driver which alternative power source to use. +* @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to +* this parameter (on a custom format) tells the driver which alternative +* slew rate to use. * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power * operation, if several modes of operation are supported these can be * passed in the argument on a custom form, else just use argument 1
@@ -78,6 +81,7 @@ enum pin_config_param {PIN_CONFIG_INPUT_SCHMITT ,PIN_CONFIG_INPUT_DEBOUNCE ,PIN_CONFIG_POWER_SOURCE , +PIN_CONFIG_SLEW_RATE ,PIN_CONFIG_LOW_POWER_MODE , PIN_CONFIG_END = 0x7FFF, };
Signature · 1 line
1.7.10.4
PATCH v7 11/15 pinctrl: generic: add slew rate config parameter
Quoted 3 lines · Haojian Zhuang
Add
PIN_CONFIG_SLEW_RATEparameter into pinconf-generic driver.Signed-off-by Haojian Zhuang <[email protected]>
Aha you need this.
Patch applied!
Yours,
Linus Walleij
Haojian Zhuang
maintainerPATCH v7 12/15 pinctrl: generic: dump pin configuration
In reply to Haojian ZhuangAdd the support of dumping pin configuration.
--- drivers/pinctrl/pinconf-generic.c | 12 ++++++++++++ drivers/pinctrl/pinconf.h | 8 ++++++++ 2 files changed, 20 insertions(+)
drivers/pinctrl/pinconf-generic.c +12 -0
@@ -119,4 +119,16 @@ void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, } } +void pinconf_generic_dump_config (struct pinctrl_dev *pctldev, +struct seq_file *s,unsigned long config) +{ +int i; + +for (i =0 ; i <ARRAY_SIZE (conf_items); i++) { +if (pinconf_to_config_param (config) != conf_items[i].param) +continue ; +seq_printf (s,"%s: 0x%x" , conf_items[i].display, +pinconf_to_config_argument (config)); + } +}#endif
drivers/pinctrl/pinconf.h +8 -0
@@ -98,6 +98,8 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,void pinconf_generic_dump_group (struct pinctrl_dev *pctldev,struct seq_file *s,const char *gname); +void pinconf_generic_dump_config (struct pinctrl_dev *pctldev, +struct seq_file *s,unsigned long config);#else static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
@@ -114,4 +116,10 @@ static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, return; } +static void pinconf_generic_dump_config (struct pinctrl_dev *pctldev, +struct seq_file *s, +unsigned long config) +{ +return ; +}#endif
Signature · 1 line
1.7.10.4
Haojian Zhuang
maintainerPATCH v7 13/15 pinctrl: single: set function mask as optional
In reply to Haojian ZhuangSince Hisilicon's pin controller is divided into two parts. One is the function mux, and the other is pin configuration. These two parts are in the different memory regions. So make pinctrl-single,function-mask as optional property. Then we can define pingroups without valid function mux that is only used for pin configuration.
--- drivers/pinctrl/pinctrl-single.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
drivers/pinctrl/pinctrl-single.c +22 -4
@@ -350,6 +350,9 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,int i; pcs =pinctrl_dev_get_drvdata (pctldev); +/* If function mask is null, needn't enable it. */ +if (!pcs->fmask) +return 0 ; func =radix_tree_lookup (&pcs->ftree, fselector);if (!func)return -EINVAL ;
@@ -384,6 +387,10 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,int i; pcs =pinctrl_dev_get_drvdata (pctldev); +/* If function mask is null, needn't disable it. */ +if (!pcs->fmask) +return ; + func =radix_tree_lookup (&pcs->ftree, fselector);if (!func) { dev_err(pcs->dev, "%s could not find function%i\n",
@@ -427,6 +434,10 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,int mux_bytes =0 ;unsigned data; +/* If function mask is null, return directly. */ +if (!pcs->fmask) +return -ENOTSUPP ; +list_for_each_safe (pos, tmp, &pcs->gpiofuncs) { frange = list_entry(pos, struct pcs_gpiofunc_range, node); if (pin >= frange->offset + frange->npins
@@ -969,10 +980,17 @@ static int pcs_probe(struct platform_device *pdev)PCS_GET_PROP_U32 ("pinctrl-single,register-width" , &pcs->width,"register width not specified\n" ); -PCS_GET_PROP_U32 ("pinctrl-single,function-mask" , &pcs->fmask, -"function register mask not specified\n" ); - pcs->fshift =ffs (pcs->fmask) -1 ; - pcs->fmax = pcs->fmask >> pcs->fshift; + ret =of_property_read_u32 (np,"pinctrl-single,function-mask" , + &pcs->fmask); +if (!ret) { + pcs->fshift =ffs (pcs->fmask) -1 ; + pcs->fmax = pcs->fmask >> pcs->fshift; + }else { +/* If mask property doesn't exist, function mux is invalid. */ + pcs->fmask =0 ; + pcs->fshift =0 ; + pcs->fmax =0 ; + } ret =of_property_read_u32 (np,"pinctrl-single,function-off" , &pcs->foff);
Signature · 1 line
1.7.10.4
Haojian Zhuang
maintainerPATCH v7 14/15 pinctrl: single: support generic pinconf
In reply to Haojian ZhuangSupport the operation of generic pinconf. The supported config arguments are INPUT_SCHMITT, INPUT_SCHMITT_DISABLE, POWER_SOURCE, BIAS_DISABLE, BIAS_PULLUP, BIAS_PULLDOWN, SLEW_RATE.
--- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/pinctrl-single.c | 339 +++++++++++++++++++++++++++++++++++++- 2 files changed, 333 insertions(+), 7 deletions(-)
drivers/pinctrl/Kconfig +1 -0
@@ -143,6 +143,7 @@ config PINCTRL_SINGLE depends on OF select PINMUX select PINCONF + select GENERIC_PINCONF help This selects the device tree based generic pinctrl driver.
drivers/pinctrl/pinctrl-single.c +332 -7
475 lines not on this page · raw message
Signature · 1 line
1.7.10.4
Tony Lindgren
maintainerPATCH v7 14/15 pinctrl: single: support generic pinconf
Hi,
Quoted 4 lines · Haojian Zhuang
drivers/pinctrl/pinctrl-single.c +4
-0+static int pcs_parse_pinconf (struct pcs_device *pcs,struct device_node *np, +struct pcs_function *func, +struct pinctrl_map **map) +
drivers/pinctrl/pinctrl-single.c static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset) · line 949
Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +10
-0+{ +struct pinctrl_map *m = *map; +int i =0 , nconfs =0 ; +unsigned long *settings =NULL , *s =NULL ; +struct pcs_conf_vals *conf =NULL ; +struct pcs_conf_type prop2[] = { + {"pinctrl-single,power-source" ,PIN_CONFIG_POWER_SOURCE , }, + {"pinctrl-single,slew-rate" ,PIN_CONFIG_SLEW_RATE , }, + {"pinctrl-single,input-schmitt" ,PIN_CONFIG_INPUT_SCHMITT , }, + };
The PIN_CONFIG_POWER_SOURCE should be split to PIN_CONFIG_POWER_ENABLE and PIN_CONFIG_POWER_SOURCE. If you only have one bit for it, I guess then you can just use PIN_CONFIG_POWER_ENABLE and make PIN_CONFIG_POWER_SOURCE a NOP.
I also suggest we standardize on PIN_CONFIG_*_ENABLE on the naming instead of PIN_CONFIG_*_DISABLE. Many of these features enable some input logic, and by default they should be off to save power.
drivers/pinctrl/pinctrl-single.c static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset) · line 956
Quoted 7 lines
drivers/pinctrl/pinctrl-single.c +7
-0+struct pcs_conf_type prop3[] = { + {"pinctrl-single,bias-disable" ,PIN_CONFIG_BIAS_DISABLE , }, + {"pinctrl-single,bias-pullup" ,PIN_CONFIG_BIAS_PULL_UP , }, + {"pinctrl-single,bias-pulldown" ,PIN_CONFIG_BIAS_PULL_DOWN , }, + {"pinctrl-single,input-schmitt-disable" , +PIN_CONFIG_INPUT_SCHMITT_DISABLE , }, + };
I'm not aware of cases where we need both INPUT_SCHMITT and INPUT_SCHMITT_DISABLE, so we may just want to have INPUT_SCHMITT_ENABLE if that works for you.
Other than that, looks good to me. I'll update my patches here and do some tests against my pinctrl-single,bits testcase.
Regards,
Tony
Haojian Zhuang
maintainerPATCH v7 14/15 pinctrl: single: support generic pinconf
Quoted 14 lines · Tony Lindgren
Hi,
Quoted 11 lines · Haojian Zhuang
drivers/pinctrl/pinctrl-single.c +11
-0+static int pcs_parse_pinconf (struct pcs_device *pcs,struct device_node *np, +struct pcs_function *func, +struct pinctrl_map **map) + +{ +struct pinctrl_map *m = *map; +int i =0 , nconfs =0 ; +unsigned long *settings =NULL , *s =NULL ; +struct pcs_conf_vals *conf =NULL ; +struct pcs_conf_type prop2[] = { + {"pinctrl-single,power-source" ,PIN_CONFIG_POWER_SOURCE , },
Quoted 9 lines
drivers/pinctrl/pinctrl-single.c static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset) · line 949
Quoted 3 lines
drivers/pinctrl/pinctrl-single.c +3
-0+ { "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, }, + { "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, }, + };The
PIN_CONFIG_POWER_SOURCEshould be split toPIN_CONFIG_POWER_ENABLEandPIN_CONFIG_POWER_SOURCE. If you only have one bit for it, I guess then you can just usePIN_CONFIG_POWER_ENABLEand makePIN_CONFIG_POWER_SOURCEa NOP.
In Hisilicon Hi3620 SoC, 4bits are used for power source. b0000 is 2mA, b0001 is 4mA, .... b1111 is 8mA.
There's no power enable bit. In Marvell silicon, it's also same.
Quoted 4 lines
I also suggest we standardize on PIN_CONFIG_*_ENABLE on the naming instead of PIN_CONFIG_*_DISABLE. Many of these features enable some input logic, and by default they should be off to save power.
In Hisilicon Hi3620 SoC, there's no bias enable or disable bit. They could only configure pull up or
pull down. We can think that no-pullup and no-pulldown is bias disable. If we define BIAS_ENABLE,
both pullup & pulldown meet the definition. It's a problem.
Quoted 11 lines
drivers/pinctrl/pinctrl-single.c static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset) · line 956
Quoted 7 lines
drivers/pinctrl/pinctrl-single.c +7
-0+struct pcs_conf_type prop3[] = { + {"pinctrl-single,bias-disable" ,PIN_CONFIG_BIAS_DISABLE , }, + {"pinctrl-single,bias-pullup" ,PIN_CONFIG_BIAS_PULL_UP , }, + {"pinctrl-single,bias-pulldown" ,PIN_CONFIG_BIAS_PULL_DOWN , }, + {"pinctrl-single,input-schmitt-disable" , +PIN_CONFIG_INPUT_SCHMITT_DISABLE , }, + };I'm not aware of cases where we need both
INPUT_SCHMITTandINPUT_SCHMITT_DISABLE, so we may just want to haveINPUT_SCHMITT_ENABLEif that works for you.
Because marvell silicon coul configure two input schmitt type (rise edge or fall edge).
Could we always use DISABLE as our standard? It seems that this defintion could be compatible
with most silicons.
Quoted 6 lines
Other than that, looks good to me. I'll update my patches here and do some tests against my pinctrl-single,bits testcase.
Regards,
Tony
Thanks
Haojian
Tony Lindgren
maintainerPATCH v7 14/15 pinctrl: single: support generic pinconf
Quoted 25 lines · Haojian Zhuang
Quoted 14 lines · Tony Lindgren
Hi,
Quoted 11 lines · Haojian Zhuang
drivers/pinctrl/pinctrl-single.c +11
-0+static int pcs_parse_pinconf (struct pcs_device *pcs,struct device_node *np, +struct pcs_function *func, +struct pinctrl_map **map) + +{ +struct pinctrl_map *m = *map; +int i =0 , nconfs =0 ; +unsigned long *settings =NULL , *s =NULL ; +struct pcs_conf_vals *conf =NULL ; +struct pcs_conf_type prop2[] = { + {"pinctrl-single,power-source" ,PIN_CONFIG_POWER_SOURCE , },Quoted 9 lines
drivers/pinctrl/pinctrl-single.c static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset) · line 949
Quoted 3 lines
drivers/pinctrl/pinctrl-single.c +3
-0+ { "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, }, + { "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, }, + };The
PIN_CONFIG_POWER_SOURCEshould be split toPIN_CONFIG_POWER_ENABLEandPIN_CONFIG_POWER_SOURCE. If you only have one bit for it, I guess then you can just usePIN_CONFIG_POWER_ENABLEand makePIN_CONFIG_POWER_SOURCEa NOP.
Quoted 3 lines
In Hisilicon Hi3620 SoC, 4bits are used for power source. b0000 is 2mA, b0001 is 4mA, .... b1111 is 8mA.
There's no power enable bit. In Marvell silicon, it's also same.
Yeah I figured from your earlier mails. Anyways, from client driver point of view, PIN_CONFIG_POWER_ENABLE should be just a NOP in your case?
This way the same client device driver can work on other platforms that might also use ENABLE. It's probably unsafe to attempt to handle any ENABLE bits automatically as the sequence to change POWER_SOURCE and then ENABLE might be hardware specific.
Then regarding the various values: We probably need a new pinconf generic function to set the POWER_SOURCE as it need to be passed a value too?
Regards,
Tony
Haojian Zhuang
maintainerPATCH v7 15/15 ARM: hs: enable hi4511 with device tree
In reply to Haojian ZhuangEnable Hisilicon Hi4511 development platform with device tree support.
--- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/hi3620.dtsi | 556 +++++++++++++++++++++++++++++ arch/arm/boot/dts/hi4511.dts | 772 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1329 insertions(+) create mode 100644 arch/arm/boot/dts/hi3620.dtsi create mode 100644 arch/arm/boot/dts/hi4511.dts
arch/arm/boot/dts/Makefile +1 -0
@@ -48,6 +48,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos5440-ssdk5440.dtb dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \ ecx-2000.dtb +dtb-$(CONFIG_ARCH_HS) += hi4511.dtb dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \ integratorcp.dtb dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
arch/arm/boot/dts/hi3620.dtsi new file +556 -0
556 lines not on this page · raw message
arch/arm/boot/dts/hi4511.dts new file +772 -0
772 lines not on this page · raw message
Signature · 1 line
1.7.10.4
v7 cover support pinconf in pinctrl single driver
In reply to Haojian ZhuangQuoted 11 lines · Haojian Zhuang
Changelog:
v7:
1. Discard the method of adding gpio range from pinctrl-single driver. Use gpiolib driver to support gpio range from DTS instead.
2. Add gpio request function to claim pin in gpio pl061 driver.
3. Adjust the initcall level in gpio pl061 driver.
4. Allocate gpio number from lowest gpio number to highest. The original implementation is inverted. It's hard to use since it inverted the sequence of gpio number.
5. Remove the support of pxa910 temporarily since gpio pxa driver need to be updated for supporting this solution
Linus, I'll let you make decisions on this patch series since it is mostly pinctrl related.
g.
Haojian Zhuang
maintainerv7 cover support pinconf in pinctrl single driver
Quoted 13 lines · Grant Likely
Quoted 11 lines · Haojian Zhuang
Changelog:
v7:
1. Discard the method of adding gpio range from pinctrl-single driver. Use gpiolib driver to support gpio range from DTS instead.
2. Add gpio request function to claim pin in gpio pl061 driver.
3. Adjust the initcall level in gpio pl061 driver.
4. Allocate gpio number from lowest gpio number to highest. The original implementation is inverted. It's hard to use since it inverted the sequence of gpio number.
5. Remove the support of pxa910 temporarily since gpio pxa driver need to be updated for supporting this solution
Quoted 4 lines
Linus, I'll let you make decisions on this patch series since it is mostly pinctrl related.
g.
Since Tony has some opinions on pinctrl, I'll update them and send the v8 patches right now.
Thanks
Haojian