summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-stm32.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-stm32.c')
-rw-r--r--drivers/pinctrl/pinctrl-stm32.c182
1 files changed, 100 insertions, 82 deletions
diff --git a/drivers/pinctrl/pinctrl-stm32.c b/drivers/pinctrl/pinctrl-stm32.c
index 7f04cea..cdaed51 100644
--- a/drivers/pinctrl/pinctrl-stm32.c
+++ b/drivers/pinctrl/pinctrl-stm32.c
@@ -87,110 +87,128 @@ static inline u32 stm32_gpio_get_alt(u32 function)
return 0;
}
-static int stm32_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *group)
+static int __stm32_pinctrl_set_state(struct device_d *dev, struct device_node *pins)
{
- struct stm32_pinctrl *pinctrl = to_stm32_pinctrl(pdev);
- struct device_node *pins;
int ret;
- ret = hwspinlock_lock_timeout(&pinctrl->hws, 10);
- if (ret == -ETIMEDOUT) {
- dev_err(pdev->dev, "hw spinlock timeout\n");
- return ret;
+ int num_pins = 0, i;
+ u32 slew_rate;
+ bool adjust_slew_rate = false;
+ enum stm32_pin_bias bias = -1;
+ enum stm32_pin_out_type out_type = -1;
+ enum { PIN_INPUT, PIN_OUTPUT_LOW, PIN_OUTPUT_HIGH } dir = -1;
+
+ of_get_property(pins, "pinmux", &num_pins);
+ num_pins /= sizeof(__be32);
+ if (!num_pins) {
+ dev_err(dev, "Invalid pinmux property in %s\n",
+ pins->full_name);
+ return -EINVAL;
}
- for_each_child_of_node(group, pins) {
- int num_pins = 0, i;
- u32 slew_rate;
- bool adjust_slew_rate = false;
- enum stm32_pin_bias bias = -1;
- enum stm32_pin_out_type out_type = -1;
- enum { PIN_INPUT, PIN_OUTPUT_LOW, PIN_OUTPUT_HIGH } dir = -1;
-
- of_get_property(pins, "pinmux", &num_pins);
- num_pins /= sizeof(__be32);
- if (!num_pins) {
- dev_err(pdev->dev, "Invalid pinmux property in %s\n",
- pins->full_name);
- return -EINVAL;
- }
-
- ret = of_property_read_u32(pins, "slew-rate", &slew_rate);
- if (!ret)
- adjust_slew_rate = true;
-
- if (of_get_property(pins, "bias-disable", NULL))
- bias = STM32_PIN_NO_BIAS;
- else if (of_get_property(pins, "bias-pull-up", NULL))
- bias = STM32_PIN_PULL_UP;
- else if (of_get_property(pins, "bias-pull-down", NULL))
- bias = STM32_PIN_PULL_DOWN;
+ ret = of_property_read_u32(pins, "slew-rate", &slew_rate);
+ if (!ret)
+ adjust_slew_rate = true;
+
+ if (of_get_property(pins, "bias-disable", NULL))
+ bias = STM32_PIN_NO_BIAS;
+ else if (of_get_property(pins, "bias-pull-up", NULL))
+ bias = STM32_PIN_PULL_UP;
+ else if (of_get_property(pins, "bias-pull-down", NULL))
+ bias = STM32_PIN_PULL_DOWN;
+
+ if (of_get_property(pins, "drive-push-pull", NULL))
+ out_type = STM32_PIN_OUT_PUSHPULL;
+ else if (of_get_property(pins, "drive-open-drain", NULL))
+ out_type = STM32_PIN_OUT_OPENDRAIN;
+
+ if (of_get_property(pins, "input-enable", NULL))
+ dir = PIN_INPUT;
+ else if (of_get_property(pins, "output-low", NULL))
+ dir = PIN_OUTPUT_LOW;
+ else if (of_get_property(pins, "output-high", NULL))
+ dir = PIN_OUTPUT_HIGH;
+
+ dev_dbg(dev, "%s: multiplexing %d pins\n", pins->full_name, num_pins);
+
+ for (i = 0; i < num_pins; i++) {
+ struct stm32_gpio_bank *bank = NULL;
+ u32 pinfunc, mode, alt;
+ unsigned func;
+ int offset;
+
+ ret = of_property_read_u32_index(pins, "pinmux",
+ i, &pinfunc);
+ if (ret)
+ return ret;
- if (of_get_property(pins, "drive-push-pull", NULL))
- out_type = STM32_PIN_OUT_PUSHPULL;
- else if (of_get_property(pins, "drive-open-drain", NULL))
- out_type = STM32_PIN_OUT_OPENDRAIN;
+ func = STM32_GET_PIN_FUNC(pinfunc);
+ offset = stm32_gpio_pin(STM32_GET_PIN_NO(pinfunc), &bank);
+ if (offset < 0)
+ return -ENODEV;
- if (of_get_property(pins, "input-enable", NULL))
- dir = PIN_INPUT;
- else if (of_get_property(pins, "output-low", NULL))
- dir = PIN_OUTPUT_LOW;
- else if (of_get_property(pins, "output-high", NULL))
- dir = PIN_OUTPUT_HIGH;
+ mode = stm32_gpio_get_mode(func);
+ alt = stm32_gpio_get_alt(func);
- dev_dbg(pdev->dev, "%s: multiplexing %d pins\n",
- pins->full_name, num_pins);
+ dev_dbg(dev, "configuring port %s pin %u with:\n\t"
+ "fn %u, mode %u, alt %u\n",
+ bank->name, offset, func, mode, alt);
- for (i = 0; i < num_pins; i++) {
- struct stm32_gpio_bank *bank = NULL;
- u32 pinfunc, mode, alt;
- unsigned func;
- int offset;
+ clk_enable(bank->clk);
- ret = of_property_read_u32_index(pins, "pinmux",
- i, &pinfunc);
- if (ret)
- return ret;
+ __stm32_pmx_set_mode(bank->base, offset, mode, alt);
- func = STM32_GET_PIN_FUNC(pinfunc);
- offset = stm32_gpio_pin(STM32_GET_PIN_NO(pinfunc), &bank);
- if (offset < 0)
- return -ENODEV;
+ if (adjust_slew_rate)
+ __stm32_pmx_set_speed(bank->base, offset, slew_rate);
- dev_dbg(pdev->dev, "configuring port %s pin %u with:\n\t"
- "fn %u, mode %u, alt %u\n",
- bank->name, offset, func, mode, alt);
+ if (bias != -1)
+ __stm32_pmx_set_bias(bank->base, offset, bias);
- mode = stm32_gpio_get_mode(func);
- alt = stm32_gpio_get_alt(func);
+ if (out_type != -1)
+ __stm32_pmx_set_output_type(bank->base, offset, out_type);
- clk_enable(bank->clk);
+ if (dir == PIN_INPUT)
+ __stm32_pmx_gpio_input(bank->base, offset);
+ else if (dir == PIN_OUTPUT_LOW)
+ __stm32_pmx_gpio_output(bank->base, offset, 0);
+ else if (dir == PIN_OUTPUT_HIGH)
+ __stm32_pmx_gpio_output(bank->base, offset, 1);
- __stm32_pmx_set_mode(bank->base, offset, mode, alt);
+ clk_disable(bank->clk);
+ }
- if (adjust_slew_rate)
- __stm32_pmx_set_speed(bank->base, offset, slew_rate);
+ return 0;
+}
- if (bias != -1)
- __stm32_pmx_set_bias(bank->base, offset, bias);
+static int stm32_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *np)
+{
+ struct stm32_pinctrl *pinctrl = to_stm32_pinctrl(pdev);
+ struct device_d *dev = pdev->dev;
+ struct device_node *pins;
+ void *prop;
+ int ret;
- if (out_type != -1)
- __stm32_pmx_set_output_type(bank->base, offset, out_type);
+ ret = hwspinlock_lock_timeout(&pinctrl->hws, 10);
+ if (ret == -ETIMEDOUT) {
+ dev_err(dev, "hw spinlock timeout\n");
+ return ret;
+ }
- if (dir == PIN_INPUT)
- __stm32_pmx_gpio_input(bank->base, offset);
- else if (dir == PIN_OUTPUT_LOW)
- __stm32_pmx_gpio_output(bank->base, offset, 0);
- else if (dir == PIN_OUTPUT_HIGH)
- __stm32_pmx_gpio_output(bank->base, offset, 1);
+ prop = of_find_property(np, "pinmux", NULL);
+ if (prop) {
+ ret = __stm32_pinctrl_set_state(dev, np);
+ goto out;
+ }
- clk_disable(bank->clk);
- }
+ for_each_child_of_node(np, pins) {
+ ret = __stm32_pinctrl_set_state(dev, pins);
+ if (ret)
+ goto out;
}
+out:
hwspinlock_unlock(&pinctrl->hws);
-
- return 0;
+ return ret;
}
/* GPIO functions */
@@ -401,7 +419,7 @@ static int stm32_pinctrl_probe(struct device_d *dev)
}
}
- dev_info(dev, "pinctrl/gpio driver registered\n");
+ dev_dbg(dev, "pinctrl/gpio driver registered\n");
return 0;
}