From: fenglinw-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org To: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org, Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>, Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: collinsd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org, aghayal-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org, wruan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org, kgunda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org, Fenglin Wu <fenglinw-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> Subject: [PATCH V1] pinctrl: qcom: spmi-gpio: Add support for qcom,gpios-disallowed property Date: Wed, 19 Jul 2017 15:17:07 +0800 [thread overview] Message-ID: <20170719071804.3816-1-fenglinw@codeaurora.org> (raw) From: Fenglin Wu <fenglinw-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> Add support for qcom,gpios-disallowed property which is used to exclude PMIC GPIOs not owned by the APSS processor from the pinctrl device. Signed-off-by: Fenglin Wu <fenglinw-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> --- .../devicetree/bindings/pinctrl/qcom,pmic-gpio.txt | 12 ++ drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 202 +++++++++++++++++---- 2 files changed, 176 insertions(+), 38 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt index 8d893a8..435efe8 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt @@ -43,6 +43,17 @@ PMIC's from Qualcomm. the first cell will be used to define gpio number and the second denotes the flags for this gpio +- qcom,gpios-disallowed: + Usage: optional + Value type: <prop-encoded-array> + Definition: Array of the GPIO hardware numbers corresponding to GPIOs + which the APSS processor is not allowed to configure. + The hardware numbers are indexed from 1. + The interrupt resources for these GPIOs must not be defined + in "interrupts" and "interrupt-names" properties. + GPIOs defined in this array won't be registered as pins + in the pinctrl device or gpios in the gpio chip. + Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for a general description of GPIO and interrupt bindings. @@ -206,6 +217,7 @@ Example: gpio-controller; #gpio-cells = <2>; + qcom,gpios-disallowed = <1 20>; pm8921_gpio_keys: gpio-keys { volume-keys { diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 664b641..74821af 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -96,6 +96,7 @@ * struct pmic_gpio_pad - keep current GPIO settings * @base: Address base in SPMI device. * @irq: IRQ number which this GPIO generate. + * @gpio_idx: The index in GPIO's hardware number space (1-based) * @is_enabled: Set to false when GPIO should be put in high Z state. * @out_value: Cached pin output value * @have_buffer: Set to true if GPIO output could be configured in push-pull, @@ -112,6 +113,7 @@ struct pmic_gpio_pad { u16 base; int irq; + int gpio_idx; bool is_enabled; bool out_value; bool have_buffer; @@ -130,6 +132,7 @@ struct pmic_gpio_state { struct regmap *map; struct pinctrl_dev *ctrl; struct gpio_chip chip; + const char **gpio_groups; }; static const struct pinconf_generic_params pmic_gpio_bindings[] = { @@ -231,7 +234,9 @@ static int pmic_gpio_get_function_groups(struct pinctrl_dev *pctldev, const char *const **groups, unsigned *const num_qgroups) { - *groups = pmic_gpio_groups; + struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev); + + *groups = state->gpio_groups; *num_qgroups = pctldev->desc->npins; return 0; } @@ -455,7 +460,7 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev, pad = pctldev->desc->pins[pin].drv_data; - seq_printf(s, " gpio%-2d:", pin + PMIC_GPIO_PHYSICAL_OFFSET); + seq_printf(s, " gpio%-2d:", pad->gpio_idx); val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL); @@ -546,13 +551,29 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip, const struct of_phandle_args *gpio_desc, u32 *flags) { + int i; + struct pmic_gpio_state *state = gpiochip_get_data(chip); + struct pinctrl_desc *desc = state->ctrl->desc; + struct pmic_gpio_pad *pad; + if (chip->of_gpio_n_cells < 2) return -EINVAL; if (flags) *flags = gpio_desc->args[1]; - return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET; + for (i = 0; i < chip->ngpio; i++) { + pad = desc->pins[i].drv_data; + if (pad->gpio_idx == gpio_desc->args[0]) { + dev_dbg(state->dev, "gpio%-2d xlate to pin%-2d\n", + gpio_desc->args[0], i); + return i; + } + } + + dev_err(state->dev, "Couldn't find pin for gpio %d\n", + gpio_desc->args[0]); + return -ENODEV; } static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin) @@ -688,43 +709,124 @@ static int pmic_gpio_probe(struct platform_device *pdev) struct pinctrl_desc *pctrldesc; struct pmic_gpio_pad *pad, *pads; struct pmic_gpio_state *state; - int ret, npins, i; - u32 reg; + int ret, npins, ngpios, i, j, pin_idx; + int disallowed_count = 0; + u32 reg[2], start, size; + u32 *disallowed = NULL; - ret = of_property_read_u32(dev->of_node, "reg", ®); + ret = of_property_read_u32_array(dev->of_node, "reg", reg, 2); if (ret < 0) { - dev_err(dev, "missing base address"); + dev_err(dev, "reg property reading failed\n"); return ret; } + start = reg[0]; + size = reg[1]; + + ngpios = size / PMIC_GPIO_ADDRESS_RANGE; + if (ngpios == 0) { + dev_err(dev, "no gpios assigned\n"); + return -ENODEV; + } - npins = platform_irq_count(pdev); - if (!npins) + if (ngpios > ARRAY_SIZE(pmic_gpio_groups)) { + dev_err(dev, "reg property defines %d gpios, but only %d are allowed\n", + ngpios, (int)ARRAY_SIZE(pmic_gpio_groups)); return -EINVAL; - if (npins < 0) - return npins; + } + + if (of_find_property(dev->of_node, "qcom,gpios-disallowed", + &disallowed_count)) { + disallowed_count /= sizeof(u32); + if (disallowed_count == 0) { + dev_err(dev, "No data in gpios-disallowed\n"); + return -EINVAL; + } - BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups)); + disallowed = kcalloc(disallowed_count, sizeof(u32), GFP_KERNEL); + if (disallowed == NULL) + return -ENOMEM; + + ret = of_property_read_u32_array(dev->of_node, + "qcom,gpios-disallowed", + disallowed, disallowed_count); + if (ret < 0) { + dev_err(dev, "qcom,gpios-disallowed property reading failed, ret=%d\n", + ret); + goto err_free; + } + + for (i = 0; i < disallowed_count; i++) { + if (disallowed[i] >= ngpios + PMIC_GPIO_PHYSICAL_OFFSET + || disallowed[i] < PMIC_GPIO_PHYSICAL_OFFSET) { + dev_err(dev, "invalid gpio = %d specified in qcom,gpios-disallowed, supported values: %d to %d\n", + disallowed[i], + PMIC_GPIO_PHYSICAL_OFFSET, + ngpios - 1 + PMIC_GPIO_PHYSICAL_OFFSET); + ret = -EINVAL; + goto err_free; + } + for (j = 0; j < i; j++) { + if (disallowed[i] == disallowed[j]) { + dev_err(dev, "duplicate gpio = %d listed in qcom,gpios-disallowed\n", + disallowed[i]); + ret = -EINVAL; + goto err_free; + } + } + dev_dbg(dev, "gpio %d NOT supported\n", disallowed[i]); + } + } else { + disallowed_count = 0; + } + + npins = ngpios - disallowed_count; + if (npins <= 0) { + dev_err(dev, "No pins assigned\n"); + ret = -ENODEV; + goto err_free; + } + if (platform_irq_count(pdev) != npins) { + dev_err(dev, "%d IRQs defined but %d expected\n", + platform_irq_count(pdev), npins); + ret = -EINVAL; + goto err_free; + } state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; + if (!state) { + ret = -ENOMEM; + goto err_free; + } platform_set_drvdata(pdev, state); state->dev = &pdev->dev; state->map = dev_get_regmap(dev->parent, NULL); + state->gpio_groups = devm_kcalloc(dev, sizeof(*state->gpio_groups), + npins, GFP_KERNEL); + if (!state->gpio_groups) { + ret = -ENOMEM; + goto err_free; + } + pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL); - if (!pindesc) - return -ENOMEM; + if (!pindesc) { + ret = -ENOMEM; + goto err_free; + } pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL); - if (!pads) - return -ENOMEM; + if (!pads) { + ret = -ENOMEM; + goto err_free; + } pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL); - if (!pctrldesc) - return -ENOMEM; + if (!pctrldesc) { + ret = -ENOMEM; + goto err_free; + } pctrldesc->pctlops = &pmic_gpio_pinctrl_ops; pctrldesc->pmxops = &pmic_gpio_pinmux_ops; @@ -738,22 +840,42 @@ static int pmic_gpio_probe(struct platform_device *pdev) #ifdef CONFIG_DEBUG_FS pctrldesc->custom_conf_items = pmic_conf_items; #endif + for (pin_idx = 0, i = 0; i < ngpios; i++) { + for (j = 0; j < disallowed_count; j++) { + if (i + PMIC_GPIO_PHYSICAL_OFFSET == disallowed[j]) + break; + } + if (j != disallowed_count) + continue; - for (i = 0; i < npins; i++, pindesc++) { - pad = &pads[i]; + pad = &pads[pin_idx]; pindesc->drv_data = pad; - pindesc->number = i; + pindesc->number = pin_idx; pindesc->name = pmic_gpio_groups[i]; - pad->irq = platform_get_irq(pdev, i); - if (pad->irq < 0) - return pad->irq; + pad->gpio_idx = i + PMIC_GPIO_PHYSICAL_OFFSET; + pad->irq = platform_get_irq(pdev, pin_idx); + if (pad->irq < 0) { + dev_err(state->dev, + "failed to get irq for gpio %d (pin %d), ret=%d\n", + pad->gpio_idx, pin_idx, pad->irq); + ret = pad->irq; + goto err_free; + } + /* Every pin is a group */ + state->gpio_groups[pin_idx] = pmic_gpio_groups[i]; - pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE; + pad->base = start + i * PMIC_GPIO_ADDRESS_RANGE; ret = pmic_gpio_populate(state, pad); - if (ret < 0) - return ret; + if (ret < 0) { + dev_err(state->dev, + "failed to populate gpio %d, ret=%d\n", + i, ret); + goto err_free; + } + pindesc++; + pin_idx++; } state->chip = pmic_gpio_gpio_template; @@ -765,25 +887,29 @@ static int pmic_gpio_probe(struct platform_device *pdev) state->chip.can_sleep = false; state->ctrl = devm_pinctrl_register(dev, pctrldesc, state); - if (IS_ERR(state->ctrl)) - return PTR_ERR(state->ctrl); + if (IS_ERR(state->ctrl)) { + ret = PTR_ERR(state->ctrl); + dev_err(state->dev, "failed to register pinctrl device, ret=%d\n", + ret); + goto err_free; + } ret = gpiochip_add_data(&state->chip, state); if (ret) { - dev_err(state->dev, "can't add gpio chip\n"); - return ret; + dev_err(state->dev, "can't add gpio chip, ret=%d\n", ret); + goto err_free; } ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins); if (ret) { - dev_err(dev, "failed to add pin range\n"); - goto err_range; + dev_err(dev, "failed to add pin range\n, ret=%d\n", ret); + gpiochip_remove(&state->chip); + goto err_free; } - return 0; +err_free: + kfree(disallowed); -err_range: - gpiochip_remove(&state->chip); return ret; } -- Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project. -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: fenglinw@codeaurora.org To: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, Linus Walleij <linus.walleij@linaro.org>, Rob Herring <robh+dt@kernel.org>, Mark Rutland <mark.rutland@arm.com>, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org Cc: collinsd@codeaurora.org, aghayal@codeaurora.org, wruan@codeaurora.org, kgunda@codeaurora.org, Fenglin Wu <fenglinw@codeaurora.org> Subject: [PATCH V1] pinctrl: qcom: spmi-gpio: Add support for qcom,gpios-disallowed property Date: Wed, 19 Jul 2017 15:17:07 +0800 [thread overview] Message-ID: <20170719071804.3816-1-fenglinw@codeaurora.org> (raw) From: Fenglin Wu <fenglinw@codeaurora.org> Add support for qcom,gpios-disallowed property which is used to exclude PMIC GPIOs not owned by the APSS processor from the pinctrl device. Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org> --- .../devicetree/bindings/pinctrl/qcom,pmic-gpio.txt | 12 ++ drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 202 +++++++++++++++++---- 2 files changed, 176 insertions(+), 38 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt index 8d893a8..435efe8 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt @@ -43,6 +43,17 @@ PMIC's from Qualcomm. the first cell will be used to define gpio number and the second denotes the flags for this gpio +- qcom,gpios-disallowed: + Usage: optional + Value type: <prop-encoded-array> + Definition: Array of the GPIO hardware numbers corresponding to GPIOs + which the APSS processor is not allowed to configure. + The hardware numbers are indexed from 1. + The interrupt resources for these GPIOs must not be defined + in "interrupts" and "interrupt-names" properties. + GPIOs defined in this array won't be registered as pins + in the pinctrl device or gpios in the gpio chip. + Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for a general description of GPIO and interrupt bindings. @@ -206,6 +217,7 @@ Example: gpio-controller; #gpio-cells = <2>; + qcom,gpios-disallowed = <1 20>; pm8921_gpio_keys: gpio-keys { volume-keys { diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 664b641..74821af 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -96,6 +96,7 @@ * struct pmic_gpio_pad - keep current GPIO settings * @base: Address base in SPMI device. * @irq: IRQ number which this GPIO generate. + * @gpio_idx: The index in GPIO's hardware number space (1-based) * @is_enabled: Set to false when GPIO should be put in high Z state. * @out_value: Cached pin output value * @have_buffer: Set to true if GPIO output could be configured in push-pull, @@ -112,6 +113,7 @@ struct pmic_gpio_pad { u16 base; int irq; + int gpio_idx; bool is_enabled; bool out_value; bool have_buffer; @@ -130,6 +132,7 @@ struct pmic_gpio_state { struct regmap *map; struct pinctrl_dev *ctrl; struct gpio_chip chip; + const char **gpio_groups; }; static const struct pinconf_generic_params pmic_gpio_bindings[] = { @@ -231,7 +234,9 @@ static int pmic_gpio_get_function_groups(struct pinctrl_dev *pctldev, const char *const **groups, unsigned *const num_qgroups) { - *groups = pmic_gpio_groups; + struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev); + + *groups = state->gpio_groups; *num_qgroups = pctldev->desc->npins; return 0; } @@ -455,7 +460,7 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev, pad = pctldev->desc->pins[pin].drv_data; - seq_printf(s, " gpio%-2d:", pin + PMIC_GPIO_PHYSICAL_OFFSET); + seq_printf(s, " gpio%-2d:", pad->gpio_idx); val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL); @@ -546,13 +551,29 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip, const struct of_phandle_args *gpio_desc, u32 *flags) { + int i; + struct pmic_gpio_state *state = gpiochip_get_data(chip); + struct pinctrl_desc *desc = state->ctrl->desc; + struct pmic_gpio_pad *pad; + if (chip->of_gpio_n_cells < 2) return -EINVAL; if (flags) *flags = gpio_desc->args[1]; - return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET; + for (i = 0; i < chip->ngpio; i++) { + pad = desc->pins[i].drv_data; + if (pad->gpio_idx == gpio_desc->args[0]) { + dev_dbg(state->dev, "gpio%-2d xlate to pin%-2d\n", + gpio_desc->args[0], i); + return i; + } + } + + dev_err(state->dev, "Couldn't find pin for gpio %d\n", + gpio_desc->args[0]); + return -ENODEV; } static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin) @@ -688,43 +709,124 @@ static int pmic_gpio_probe(struct platform_device *pdev) struct pinctrl_desc *pctrldesc; struct pmic_gpio_pad *pad, *pads; struct pmic_gpio_state *state; - int ret, npins, i; - u32 reg; + int ret, npins, ngpios, i, j, pin_idx; + int disallowed_count = 0; + u32 reg[2], start, size; + u32 *disallowed = NULL; - ret = of_property_read_u32(dev->of_node, "reg", ®); + ret = of_property_read_u32_array(dev->of_node, "reg", reg, 2); if (ret < 0) { - dev_err(dev, "missing base address"); + dev_err(dev, "reg property reading failed\n"); return ret; } + start = reg[0]; + size = reg[1]; + + ngpios = size / PMIC_GPIO_ADDRESS_RANGE; + if (ngpios == 0) { + dev_err(dev, "no gpios assigned\n"); + return -ENODEV; + } - npins = platform_irq_count(pdev); - if (!npins) + if (ngpios > ARRAY_SIZE(pmic_gpio_groups)) { + dev_err(dev, "reg property defines %d gpios, but only %d are allowed\n", + ngpios, (int)ARRAY_SIZE(pmic_gpio_groups)); return -EINVAL; - if (npins < 0) - return npins; + } + + if (of_find_property(dev->of_node, "qcom,gpios-disallowed", + &disallowed_count)) { + disallowed_count /= sizeof(u32); + if (disallowed_count == 0) { + dev_err(dev, "No data in gpios-disallowed\n"); + return -EINVAL; + } - BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups)); + disallowed = kcalloc(disallowed_count, sizeof(u32), GFP_KERNEL); + if (disallowed == NULL) + return -ENOMEM; + + ret = of_property_read_u32_array(dev->of_node, + "qcom,gpios-disallowed", + disallowed, disallowed_count); + if (ret < 0) { + dev_err(dev, "qcom,gpios-disallowed property reading failed, ret=%d\n", + ret); + goto err_free; + } + + for (i = 0; i < disallowed_count; i++) { + if (disallowed[i] >= ngpios + PMIC_GPIO_PHYSICAL_OFFSET + || disallowed[i] < PMIC_GPIO_PHYSICAL_OFFSET) { + dev_err(dev, "invalid gpio = %d specified in qcom,gpios-disallowed, supported values: %d to %d\n", + disallowed[i], + PMIC_GPIO_PHYSICAL_OFFSET, + ngpios - 1 + PMIC_GPIO_PHYSICAL_OFFSET); + ret = -EINVAL; + goto err_free; + } + for (j = 0; j < i; j++) { + if (disallowed[i] == disallowed[j]) { + dev_err(dev, "duplicate gpio = %d listed in qcom,gpios-disallowed\n", + disallowed[i]); + ret = -EINVAL; + goto err_free; + } + } + dev_dbg(dev, "gpio %d NOT supported\n", disallowed[i]); + } + } else { + disallowed_count = 0; + } + + npins = ngpios - disallowed_count; + if (npins <= 0) { + dev_err(dev, "No pins assigned\n"); + ret = -ENODEV; + goto err_free; + } + if (platform_irq_count(pdev) != npins) { + dev_err(dev, "%d IRQs defined but %d expected\n", + platform_irq_count(pdev), npins); + ret = -EINVAL; + goto err_free; + } state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; + if (!state) { + ret = -ENOMEM; + goto err_free; + } platform_set_drvdata(pdev, state); state->dev = &pdev->dev; state->map = dev_get_regmap(dev->parent, NULL); + state->gpio_groups = devm_kcalloc(dev, sizeof(*state->gpio_groups), + npins, GFP_KERNEL); + if (!state->gpio_groups) { + ret = -ENOMEM; + goto err_free; + } + pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL); - if (!pindesc) - return -ENOMEM; + if (!pindesc) { + ret = -ENOMEM; + goto err_free; + } pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL); - if (!pads) - return -ENOMEM; + if (!pads) { + ret = -ENOMEM; + goto err_free; + } pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL); - if (!pctrldesc) - return -ENOMEM; + if (!pctrldesc) { + ret = -ENOMEM; + goto err_free; + } pctrldesc->pctlops = &pmic_gpio_pinctrl_ops; pctrldesc->pmxops = &pmic_gpio_pinmux_ops; @@ -738,22 +840,42 @@ static int pmic_gpio_probe(struct platform_device *pdev) #ifdef CONFIG_DEBUG_FS pctrldesc->custom_conf_items = pmic_conf_items; #endif + for (pin_idx = 0, i = 0; i < ngpios; i++) { + for (j = 0; j < disallowed_count; j++) { + if (i + PMIC_GPIO_PHYSICAL_OFFSET == disallowed[j]) + break; + } + if (j != disallowed_count) + continue; - for (i = 0; i < npins; i++, pindesc++) { - pad = &pads[i]; + pad = &pads[pin_idx]; pindesc->drv_data = pad; - pindesc->number = i; + pindesc->number = pin_idx; pindesc->name = pmic_gpio_groups[i]; - pad->irq = platform_get_irq(pdev, i); - if (pad->irq < 0) - return pad->irq; + pad->gpio_idx = i + PMIC_GPIO_PHYSICAL_OFFSET; + pad->irq = platform_get_irq(pdev, pin_idx); + if (pad->irq < 0) { + dev_err(state->dev, + "failed to get irq for gpio %d (pin %d), ret=%d\n", + pad->gpio_idx, pin_idx, pad->irq); + ret = pad->irq; + goto err_free; + } + /* Every pin is a group */ + state->gpio_groups[pin_idx] = pmic_gpio_groups[i]; - pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE; + pad->base = start + i * PMIC_GPIO_ADDRESS_RANGE; ret = pmic_gpio_populate(state, pad); - if (ret < 0) - return ret; + if (ret < 0) { + dev_err(state->dev, + "failed to populate gpio %d, ret=%d\n", + i, ret); + goto err_free; + } + pindesc++; + pin_idx++; } state->chip = pmic_gpio_gpio_template; @@ -765,25 +887,29 @@ static int pmic_gpio_probe(struct platform_device *pdev) state->chip.can_sleep = false; state->ctrl = devm_pinctrl_register(dev, pctrldesc, state); - if (IS_ERR(state->ctrl)) - return PTR_ERR(state->ctrl); + if (IS_ERR(state->ctrl)) { + ret = PTR_ERR(state->ctrl); + dev_err(state->dev, "failed to register pinctrl device, ret=%d\n", + ret); + goto err_free; + } ret = gpiochip_add_data(&state->chip, state); if (ret) { - dev_err(state->dev, "can't add gpio chip\n"); - return ret; + dev_err(state->dev, "can't add gpio chip, ret=%d\n", ret); + goto err_free; } ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins); if (ret) { - dev_err(dev, "failed to add pin range\n"); - goto err_range; + dev_err(dev, "failed to add pin range\n, ret=%d\n", ret); + gpiochip_remove(&state->chip); + goto err_free; } - return 0; +err_free: + kfree(disallowed); -err_range: - gpiochip_remove(&state->chip); return ret; } -- Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
next reply other threads:[~2017-07-19 7:17 UTC|newest] Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-07-19 7:17 fenglinw-sgV2jX0FEOL9JmXXK+q4OQ [this message] 2017-07-19 7:17 ` [PATCH V1] pinctrl: qcom: spmi-gpio: Add support for qcom,gpios-disallowed property fenglinw 2017-07-24 19:09 ` Rob Herring 2017-07-25 1:05 ` Fenglin Wu 2017-07-25 1:05 ` Fenglin Wu [not found] ` <4bb5757c-44b0-c760-2d70-df0e607de0d7-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 2017-07-25 1:11 ` Fenglin Wu 2017-08-28 14:54 ` Shawn Guo 2017-08-29 1:03 ` Fenglin Wu 2017-08-29 1:51 ` Shawn Guo 2017-08-29 2:04 ` Fenglin Wu
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20170719071804.3816-1-fenglinw@codeaurora.org \ --to=fenglinw-sgv2jx0feol9jmxxk+q4oq@public.gmane.org \ --cc=aghayal-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \ --cc=bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \ --cc=collinsd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \ --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=kgunda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \ --cc=linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \ --cc=linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \ --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \ --cc=wruan-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.