summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/core.c')
-rw-r--r--drivers/pinctrl/core.c99
1 files changed, 65 insertions, 34 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index bbcdece83bf4..4bdbf6bb26e2 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -220,6 +220,9 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
/* Set owner */
pindesc->pctldev = pctldev;
+#ifdef CONFIG_PINMUX
+ mutex_init(&pindesc->mux_lock);
+#endif
/* Copy basic pin info */
if (pin->name) {
@@ -412,6 +415,10 @@ static int pinctrl_get_device_gpio_range(struct gpio_chip *gc,
* @pctldev: pin controller device to add the range to
* @range: the GPIO range to add
*
+ * DEPRECATED: Don't use this function in new code. See section 2 of
+ * Documentation/devicetree/bindings/gpio/gpio.txt on how to bind pinctrl and
+ * gpio drivers.
+ *
* This adds a range of GPIOs to be handled by a certain pin controller. Call
* this to register handled ranges after registering your pin controller.
*/
@@ -1102,8 +1109,8 @@ static struct pinctrl *create_pinctrl(struct device *dev,
* an -EPROBE_DEFER later, as that is the worst case.
*/
if (ret == -EPROBE_DEFER) {
- pinctrl_free(p, false);
mutex_unlock(&pinctrl_maps_mutex);
+ pinctrl_free(p, false);
return ERR_PTR(ret);
}
}
@@ -1249,6 +1256,20 @@ static void pinctrl_link_add(struct pinctrl_dev *pctldev,
DL_FLAG_AUTOREMOVE_CONSUMER);
}
+static void pinctrl_cond_disable_mux_setting(struct pinctrl_state *state,
+ struct pinctrl_setting *target_setting)
+{
+ struct pinctrl_setting *setting;
+
+ list_for_each_entry(setting, &state->settings, node) {
+ if (target_setting && (&setting->node == &target_setting->node))
+ break;
+
+ if (setting->type == PIN_MAP_TYPE_MUX_GROUP)
+ pinmux_disable_setting(setting);
+ }
+}
+
/**
* pinctrl_commit_state() - select/activate/program a pinctrl state to HW
* @p: the pinctrl handle for the device that requests configuration
@@ -1256,7 +1277,7 @@ static void pinctrl_link_add(struct pinctrl_dev *pctldev,
*/
static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
{
- struct pinctrl_setting *setting, *setting2;
+ struct pinctrl_setting *setting;
struct pinctrl_state *old_state = READ_ONCE(p->state);
int ret;
@@ -1267,11 +1288,7 @@ static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
* still owned by the new state will be re-acquired by the call
* to pinmux_enable_setting() in the loop below.
*/
- list_for_each_entry(setting, &old_state->settings, node) {
- if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
- continue;
- pinmux_disable_setting(setting);
- }
+ pinctrl_cond_disable_mux_setting(old_state, NULL);
}
p->state = NULL;
@@ -1315,7 +1332,7 @@ static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
}
if (ret < 0) {
- goto unapply_new_state;
+ goto unapply_mux_setting;
}
/* Do not link hogs (circular dependency) */
@@ -1327,23 +1344,23 @@ static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
return 0;
+unapply_mux_setting:
+ pinctrl_cond_disable_mux_setting(state, NULL);
+ goto restore_old_state;
+
unapply_new_state:
dev_err(p->dev, "Error applying setting, reverse things back\n");
- list_for_each_entry(setting2, &state->settings, node) {
- if (&setting2->node == &setting->node)
- break;
- /*
- * All we can do here is pinmux_disable_setting.
- * That means that some pins are muxed differently now
- * than they were before applying the setting (We can't
- * "unmux a pin"!), but it's not a big deal since the pins
- * are free to be muxed by another apply_setting.
- */
- if (setting2->type == PIN_MAP_TYPE_MUX_GROUP)
- pinmux_disable_setting(setting2);
- }
+ /*
+ * All we can do here is pinmux_disable_setting.
+ * That means that some pins are muxed differently now
+ * than they were before applying the setting (We can't
+ * "unmux a pin"!), but it's not a big deal since the pins
+ * are free to be muxed by another apply_setting.
+ */
+ pinctrl_cond_disable_mux_setting(state, setting);
+restore_old_state:
/* There's no infinite recursive loop here because p->state is NULL */
if (old_state)
pinctrl_select_state(p, old_state);
@@ -1666,13 +1683,23 @@ static int pinctrl_pins_show(struct seq_file *s, void *what)
seq_printf(s, "pin %d (%s) ", pin, desc->name);
#ifdef CONFIG_GPIOLIB
+ gdev = NULL;
gpio_num = -1;
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
- if ((pin >= range->pin_base) &&
- (pin < (range->pin_base + range->npins))) {
- gpio_num = range->base + (pin - range->pin_base);
- break;
+ if (range->pins != NULL) {
+ for (int i = 0; i < range->npins; ++i) {
+ if (range->pins[i] == pin) {
+ gpio_num = range->base + i;
+ break;
+ }
+ }
+ } else if ((pin >= range->pin_base) &&
+ (pin < (range->pin_base + range->npins))) {
+ gpio_num =
+ range->base + (pin - range->pin_base);
}
+ if (gpio_num != -1)
+ break;
}
if (gpio_num >= 0)
/*
@@ -1957,7 +1984,7 @@ static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
static void pinctrl_init_debugfs(void)
{
debugfs_root = debugfs_create_dir("pinctrl", NULL);
- if (IS_ERR(debugfs_root) || !debugfs_root) {
+ if (IS_ERR(debugfs_root)) {
pr_warn("failed to create debugfs directory\n");
debugfs_root = NULL;
return;
@@ -2076,6 +2103,14 @@ out_err:
return ERR_PTR(ret);
}
+static void pinctrl_uninit_controller(struct pinctrl_dev *pctldev, struct pinctrl_desc *pctldesc)
+{
+ pinctrl_free_pindescs(pctldev, pctldesc->pins,
+ pctldesc->npins);
+ mutex_destroy(&pctldev->mutex);
+ kfree(pctldev);
+}
+
static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
{
pctldev->p = create_pinctrl(pctldev->dev, pctldev);
@@ -2120,13 +2155,7 @@ int pinctrl_enable(struct pinctrl_dev *pctldev)
error = pinctrl_claim_hogs(pctldev);
if (error) {
- dev_err(pctldev->dev, "could not claim hogs: %i\n",
- error);
- pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
- pctldev->desc->npins);
- mutex_destroy(&pctldev->mutex);
- kfree(pctldev);
-
+ dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
return error;
}
@@ -2162,8 +2191,10 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
return pctldev;
error = pinctrl_enable(pctldev);
- if (error)
+ if (error) {
+ pinctrl_uninit_controller(pctldev, pctldesc);
return ERR_PTR(error);
+ }
return pctldev;
}