diff options
Diffstat (limited to 'drivers/pinctrl/pinmux.c')
| -rw-r--r-- | drivers/pinctrl/pinmux.c | 97 | 
1 files changed, 67 insertions, 30 deletions
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 4e62783a573..3d5ac73bd5a 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -33,22 +33,25 @@  int pinmux_check_ops(struct pinctrl_dev *pctldev)  {  	const struct pinmux_ops *ops = pctldev->desc->pmxops; +	unsigned nfuncs;  	unsigned selector = 0;  	/* Check that we implement required operations */ -	if (!ops->list_functions || +	if (!ops || +	    !ops->get_functions_count ||  	    !ops->get_function_name ||  	    !ops->get_function_groups || -	    !ops->enable || -	    !ops->disable) +	    !ops->enable) { +		dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");  		return -EINVAL; - +	}  	/* Check that all functions registered have names */ -	while (ops->list_functions(pctldev, selector) >= 0) { +	nfuncs = ops->get_functions_count(pctldev); +	while (selector < nfuncs) {  		const char *fname = ops->get_function_name(pctldev,  							   selector);  		if (!fname) { -			pr_err("pinmux ops has no name for function%u\n", +			dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",  				selector);  			return -EINVAL;  		} @@ -85,20 +88,23 @@ static int pin_request(struct pinctrl_dev *pctldev,  	const struct pinmux_ops *ops = pctldev->desc->pmxops;  	int status = -EINVAL; -	dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner); -  	desc = pin_desc_get(pctldev, pin);  	if (desc == NULL) {  		dev_err(pctldev->dev, -			"pin is not registered so it cannot be requested\n"); +			"pin %d is not registered so it cannot be requested\n", +			pin);  		goto out;  	} +	dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n", +		pin, desc->name, owner); +  	if (gpio_range) {  		/* There's no need to support multiple GPIO requests */  		if (desc->gpio_owner) {  			dev_err(pctldev->dev, -				"pin already requested\n"); +				"pin %s already requested by %s; cannot claim for %s\n", +				desc->name, desc->gpio_owner, owner);  			goto out;  		} @@ -106,7 +112,8 @@ static int pin_request(struct pinctrl_dev *pctldev,  	} else {  		if (desc->mux_usecount && strcmp(desc->mux_owner, owner)) {  			dev_err(pctldev->dev, -				"pin already requested\n"); +				"pin %s already requested by %s; cannot claim for %s\n", +				desc->name, desc->mux_owner, owner);  			goto out;  		} @@ -139,8 +146,7 @@ static int pin_request(struct pinctrl_dev *pctldev,  		status = 0;  	if (status) { -		dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", -		       pctldev->desc->name, pin); +		dev_err(pctldev->dev, "request() failed for pin %d\n", pin);  		module_put(pctldev->owner);  	} @@ -157,7 +163,7 @@ out_free_pin:  out:  	if (status)  		dev_err(pctldev->dev, "pin-%d (%s) status %d\n", -		       pin, owner, status); +			pin, owner, status);  	return status;  } @@ -287,10 +293,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,  					const char *function)  {  	const struct pinmux_ops *ops = pctldev->desc->pmxops; +	unsigned nfuncs = ops->get_functions_count(pctldev);  	unsigned selector = 0;  	/* See if this pctldev has this function */ -	while (ops->list_functions(pctldev, selector) >= 0) { +	while (selector < nfuncs) {  		const char *fname = ops->get_function_name(pctldev,  							   selector); @@ -319,18 +326,32 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,  	const unsigned *pins;  	unsigned num_pins; -	setting->data.mux.func = -		pinmux_func_name_to_selector(pctldev, map->data.mux.function); -	if (setting->data.mux.func < 0) -		return setting->data.mux.func; +	if (!pmxops) { +		dev_err(pctldev->dev, "does not support mux function\n"); +		return -EINVAL; +	} + +	ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function); +	if (ret < 0) { +		dev_err(pctldev->dev, "invalid function %s in map table\n", +			map->data.mux.function); +		return ret; +	} +	setting->data.mux.func = ret;  	ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,  					  &groups, &num_groups); -	if (ret < 0) +	if (ret < 0) { +		dev_err(pctldev->dev, "can't query groups for function %s\n", +			map->data.mux.function);  		return ret; -	if (!num_groups) +	} +	if (!num_groups) { +		dev_err(pctldev->dev, +			"function %s can't be selected on any group\n", +			map->data.mux.function);  		return -EINVAL; - +	}  	if (map->data.mux.group) {  		bool found = false;  		group = map->data.mux.group; @@ -340,15 +361,23 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,  				break;  			}  		} -		if (!found) +		if (!found) { +			dev_err(pctldev->dev, +				"invalid group \"%s\" for function \"%s\"\n", +				group, map->data.mux.function);  			return -EINVAL; +		}  	} else {  		group = groups[0];  	} -	setting->data.mux.group = pinctrl_get_group_selector(pctldev, group); -	if (setting->data.mux.group < 0) -		return setting->data.mux.group; +	ret = pinctrl_get_group_selector(pctldev, group); +	if (ret < 0) { +		dev_err(pctldev->dev, "invalid group %s in map table\n", +			map->data.mux.group); +		return ret; +	} +	setting->data.mux.group = ret;  	ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,  				      &num_pins); @@ -364,7 +393,7 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,  		ret = pin_request(pctldev, pins[i], map->dev_name, NULL);  		if (ret) {  			dev_err(pctldev->dev, -				"could not get request pin %d on device %s\n", +				"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 */ @@ -467,7 +496,8 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)  		desc->mux_setting = NULL;  	} -	ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group); +	if (ops->disable) +		ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);  }  #ifdef CONFIG_DEBUG_FS @@ -477,11 +507,15 @@ static int pinmux_functions_show(struct seq_file *s, void *what)  {  	struct pinctrl_dev *pctldev = s->private;  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops; +	unsigned nfuncs;  	unsigned func_selector = 0; -	mutex_lock(&pinctrl_mutex); +	if (!pmxops) +		return 0; -	while (pmxops->list_functions(pctldev, func_selector) >= 0) { +	mutex_lock(&pinctrl_mutex); +	nfuncs = pmxops->get_functions_count(pctldev); +	while (func_selector < nfuncs) {  		const char *func = pmxops->get_function_name(pctldev,  							  func_selector);  		const char * const *groups; @@ -515,6 +549,9 @@ static int pinmux_pins_show(struct seq_file *s, void *what)  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;  	unsigned i, pin; +	if (!pmxops) +		return 0; +  	seq_puts(s, "Pinmux settings per pin\n");  	seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");  |