diff options
| -rw-r--r-- | Documentation/pinctrl.txt | 4 | ||||
| -rw-r--r-- | drivers/pinctrl/core.c | 2 | ||||
| -rw-r--r-- | drivers/pinctrl/core.h | 2 | ||||
| -rw-r--r-- | drivers/pinctrl/pinmux.c | 67 | 
4 files changed, 29 insertions, 46 deletions
| diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 3b4ee5328868..a1cd2f9428d7 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -1193,4 +1193,6 @@ foo_switch()  	...  } -The above has to be done from process context. +The above has to be done from process context. The reservation of the pins +will be done when the state is activated, so in effect one specific pin +can be used by different functions at different times on a running system. diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 2e39c04fc16b..cec6072cd7c1 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -563,6 +563,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)  		return -EPROBE_DEFER;  	} +	setting->dev_name = map->dev_name; +  	switch (map->type) {  	case PIN_MAP_TYPE_MUX_GROUP:  		ret = pinmux_map_to_setting(map, setting); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 1f40ff68a8c4..12f5694f3d5d 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -105,12 +105,14 @@ struct pinctrl_setting_configs {   * @type: the type of setting   * @pctldev: pin control device handling to be programmed. Not used for   *   PIN_MAP_TYPE_DUMMY_STATE. + * @dev_name: the name of the device using this state   * @data: Data specific to the setting type   */  struct pinctrl_setting {  	struct list_head node;  	enum pinctrl_map_type type;  	struct pinctrl_dev *pctldev; +	const char *dev_name;  	union {  		struct pinctrl_setting_mux mux;  		struct pinctrl_setting_configs configs; diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 9301a7a95eff..0ef01ee2835f 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,  {  	struct pinctrl_dev *pctldev = setting->pctldev;  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops; -	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;  	char const * const *groups;  	unsigned num_groups;  	int ret;  	const char *group;  	int i; -	const unsigned *pins; -	unsigned num_pins;  	if (!pmxops) {  		dev_err(pctldev->dev, "does not support mux function\n"); @@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,  	}  	setting->data.mux.group = ret; -	ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins, -				      &num_pins); -	if (ret) { -		dev_err(pctldev->dev, -			"could not get pins for device %s group selector %d\n", -			pinctrl_dev_get_name(pctldev), setting->data.mux.group); -			return -ENODEV; -	} - -	/* Try to allocate all pins in this group, one by one */ -	for (i = 0; i < num_pins; i++) { -		ret = pin_request(pctldev, pins[i], map->dev_name, NULL); -		if (ret) { -			dev_err(pctldev->dev, -				"could not request pin %d on device %s\n", -				pins[i], pinctrl_dev_get_name(pctldev)); -			/* On error release all taken pins */ -			i--; /* this pin just failed */ -			for (; i >= 0; i--) -				pin_free(pctldev, pins[i], NULL); -			return -ENODEV; -		} -	} -  	return 0;  }  void pinmux_free_setting(struct pinctrl_setting const *setting)  { -	struct pinctrl_dev *pctldev = setting->pctldev; -	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; -	const unsigned *pins; -	unsigned num_pins; -	int ret; -	int i; - -	ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, -				      &pins, &num_pins); -	if (ret) { -		dev_err(pctldev->dev, -			"could not get pins for device %s group selector %d\n", -			pinctrl_dev_get_name(pctldev), setting->data.mux.group); -		return; -	} - -	for (i = 0; i < num_pins; i++) -		pin_free(pctldev, pins[i], NULL); +	/* This function is currently unused */  }  int pinmux_enable_setting(struct pinctrl_setting const *setting) @@ -446,6 +402,22 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)  		num_pins = 0;  	} +	/* Try to allocate all pins in this group, one by one */ +	for (i = 0; i < num_pins; i++) { +		ret = pin_request(pctldev, pins[i], setting->dev_name, NULL); +		if (ret) { +			dev_err(pctldev->dev, +				"could not request pin %d on device %s\n", +				pins[i], pinctrl_dev_get_name(pctldev)); +			/* On error release all taken pins */ +			i--; /* this pin just failed */ +			for (; i >= 0; i--) +				pin_free(pctldev, pins[i], NULL); +			return -ENODEV; +		} +	} + +	/* Now that we have acquired the pins, encode the mux setting */  	for (i = 0; i < num_pins; i++) {  		desc = pin_desc_get(pctldev, pins[i]);  		if (desc == NULL) { @@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)  		num_pins = 0;  	} +	/* Flag the descs that no setting is active */  	for (i = 0; i < num_pins; i++) {  		desc = pin_desc_get(pctldev, pins[i]);  		if (desc == NULL) { @@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)  		desc->mux_setting = NULL;  	} +	/* And release the pins */ +	for (i = 0; i < num_pins; i++) +		pin_free(pctldev, pins[i], NULL); +  	if (ops->disable)  		ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);  } | 
