diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-tegra.c')
| -rw-r--r-- | drivers/pinctrl/pinctrl-tegra.c | 89 | 
1 files changed, 66 insertions, 23 deletions
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index a2e93a2b5ff..2d43bff74f5 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -39,6 +39,7 @@ struct tegra_pmx {  	struct pinctrl_dev *pctl;  	const struct tegra_pinctrl_soc_data *soc; +	const char **group_pins;  	int nbanks;  	void __iomem **regs; @@ -294,17 +295,11 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,  {  	struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);  	const struct tegra_pingroup *g; -	u32 val;  	g = &pmx->soc->groups[group];  	if (WARN_ON(g->mux_reg < 0))  		return; - -	val = pmx_readl(pmx, g->mux_bank, g->mux_reg); -	val &= ~(0x3 << g->mux_bit); -	val |= g->func_safe << g->mux_bit; -	pmx_writel(pmx, val, g->mux_bank, g->mux_reg);  }  static const struct pinmux_ops tegra_pinmux_ops = { @@ -335,32 +330,32 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,  		*width = 1;  		break;  	case TEGRA_PINCONF_PARAM_ENABLE_INPUT: -		*bank = g->einput_bank; -		*reg = g->einput_reg; +		*bank = g->mux_bank; +		*reg = g->mux_reg;  		*bit = g->einput_bit;  		*width = 1;  		break;  	case TEGRA_PINCONF_PARAM_OPEN_DRAIN: -		*bank = g->odrain_bank; -		*reg = g->odrain_reg; +		*bank = g->mux_bank; +		*reg = g->mux_reg;  		*bit = g->odrain_bit;  		*width = 1;  		break;  	case TEGRA_PINCONF_PARAM_LOCK: -		*bank = g->lock_bank; -		*reg = g->lock_reg; +		*bank = g->mux_bank; +		*reg = g->mux_reg;  		*bit = g->lock_bit;  		*width = 1;  		break;  	case TEGRA_PINCONF_PARAM_IORESET: -		*bank = g->ioreset_bank; -		*reg = g->ioreset_reg; +		*bank = g->mux_bank; +		*reg = g->mux_reg;  		*bit = g->ioreset_bit;  		*width = 1;  		break;  	case TEGRA_PINCONF_PARAM_RCV_SEL: -		*bank = g->rcv_sel_bank; -		*reg = g->rcv_sel_reg; +		*bank = g->mux_bank; +		*reg = g->mux_reg;  		*bit = g->rcv_sel_bit;  		*width = 1;  		break; @@ -407,8 +402,8 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,  		*width = g->slwr_width;  		break;  	case TEGRA_PINCONF_PARAM_DRIVE_TYPE: -		*bank = g->drvtype_bank; -		*reg = g->drvtype_reg; +		*bank = g->drv_bank; +		*reg = g->drv_reg;  		*bit = g->drvtype_bit;  		*width = 2;  		break; @@ -417,11 +412,22 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,  		return -ENOTSUPP;  	} -	if (*reg < 0) { -		if (report_err) +	if (*reg < 0 || *bit > 31) { +		if (report_err) { +			const char *prop = "unknown"; +			int i; + +			for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { +				if (cfg_params[i].param == param) { +					prop = cfg_params[i].property; +					break; +				} +			} +  			dev_err(pmx->dev, -				"Config param %04x not supported on group %s\n", -				param, g->name); +				"Config param %04x (%s) not supported on group %s\n", +				param, prop, g->name); +		}  		return -ENOTSUPP;  	} @@ -620,6 +626,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev,  	struct tegra_pmx *pmx;  	struct resource *res;  	int i; +	const char **group_pins; +	int fn, gn, gfn;  	pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);  	if (!pmx) { @@ -629,6 +637,41 @@ int tegra_pinctrl_probe(struct platform_device *pdev,  	pmx->dev = &pdev->dev;  	pmx->soc = soc_data; +	/* +	 * Each mux group will appear in 4 functions' list of groups. +	 * This over-allocates slightly, since not all groups are mux groups. +	 */ +	pmx->group_pins = devm_kzalloc(&pdev->dev, +		soc_data->ngroups * 4 * sizeof(*pmx->group_pins), +		GFP_KERNEL); +	if (!pmx->group_pins) +		return -ENOMEM; + +	group_pins = pmx->group_pins; +	for (fn = 0; fn < soc_data->nfunctions; fn++) { +		struct tegra_function *func = &soc_data->functions[fn]; + +		func->groups = group_pins; + +		for (gn = 0; gn < soc_data->ngroups; gn++) { +			const struct tegra_pingroup *g = &soc_data->groups[gn]; + +			if (g->mux_reg == -1) +				continue; + +			for (gfn = 0; gfn < 4; gfn++) +				if (g->funcs[gfn] == fn) +					break; +			if (gfn == 4) +				continue; + +			BUG_ON(group_pins - pmx->group_pins >= +				soc_data->ngroups * 4); +			*group_pins++ = g->name; +			func->ngroups++; +		} +	} +  	tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;  	tegra_pinctrl_desc.name = dev_name(&pdev->dev);  	tegra_pinctrl_desc.pins = pmx->soc->pins; @@ -645,7 +688,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,  				 GFP_KERNEL);  	if (!pmx->regs) {  		dev_err(&pdev->dev, "Can't alloc regs pointer\n"); -		return -ENODEV; +		return -ENOMEM;  	}  	for (i = 0; i < pmx->nbanks; i++) {  | 
