aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2018-01-10 03:34:14 -0500
committerLinus Walleij <linus.walleij@linaro.org>2018-01-11 04:40:23 -0500
commitfb36a7b07dbf565014ed624a1bfd24d807f56b85 (patch)
tree272c84cee68c85d9986598232008674fa962fac2
parentd6093367bc743bc6679ab75a89cd3dd93476a755 (diff)
pinctrl: uniphier: refactor drive strength get/set functions
There is code duplication between uniphier_conf_pin_drive_get() and uniphier_conf_pin_drive_set(). Factor out the common code into uniphier_conf_get_drvctrl_data(). Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-core.c176
1 files changed, 91 insertions, 85 deletions
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 26fda5c53e65..ec0f77afeaa4 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -146,6 +146,71 @@ static const struct pinctrl_ops uniphier_pctlops = {
146 .dt_free_map = pinctrl_utils_free_map, 146 .dt_free_map = pinctrl_utils_free_map,
147}; 147};
148 148
149static const unsigned int uniphier_conf_drv_strengths_1bit[] = {4, 8};
150static const unsigned int uniphier_conf_drv_strengths_2bit[] = {8, 12, 16, 20};
151static const unsigned int uniphier_conf_drv_strengths_3bit[] = {4, 5, 7, 9, 11,
152 12, 14, 16};
153static const unsigned int uniphier_conf_drv_strengths_fixed4[] = {4};
154static const unsigned int uniphier_conf_drv_strengths_fixed5[] = {5};
155static const unsigned int uniphier_conf_drv_strengths_fixed8[] = {8};
156
157static int uniphier_conf_get_drvctrl_data(struct pinctrl_dev *pctldev,
158 unsigned int pin, unsigned int *reg,
159 unsigned int *shift,
160 unsigned int *mask,
161 const unsigned int **strengths)
162{
163 const struct pin_desc *desc = pin_desc_get(pctldev, pin);
164 enum uniphier_pin_drv_type type =
165 uniphier_pin_get_drv_type(desc->drv_data);
166 unsigned int base = 0;
167 unsigned int stride = 0;
168 unsigned int width = 0;
169 unsigned int drvctrl;
170
171 switch (type) {
172 case UNIPHIER_PIN_DRV_1BIT:
173 *strengths = uniphier_conf_drv_strengths_1bit;
174 base = UNIPHIER_PINCTRL_DRVCTRL_BASE;
175 stride = 1;
176 width = 1;
177 break;
178 case UNIPHIER_PIN_DRV_2BIT:
179 *strengths = uniphier_conf_drv_strengths_2bit;
180 base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
181 stride = 2;
182 width = 2;
183 break;
184 case UNIPHIER_PIN_DRV_3BIT:
185 *strengths = uniphier_conf_drv_strengths_3bit;
186 base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
187 stride = 4;
188 width = 3;
189 break;
190 case UNIPHIER_PIN_DRV_FIXED4:
191 *strengths = uniphier_conf_drv_strengths_fixed4;
192 break;
193 case UNIPHIER_PIN_DRV_FIXED5:
194 *strengths = uniphier_conf_drv_strengths_fixed5;
195 break;
196 case UNIPHIER_PIN_DRV_FIXED8:
197 *strengths = uniphier_conf_drv_strengths_fixed8;
198 break;
199 default:
200 /* drive strength control is not supported for this pin */
201 return -EINVAL;
202 }
203
204 drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
205 drvctrl *= stride;
206
207 *reg = base + drvctrl / 32 * 4;
208 *shift = drvctrl % 32;
209 *mask = (1U << width) - 1;
210
211 return 0;
212}
213
149static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev, 214static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
150 unsigned int pin, 215 unsigned int pin,
151 enum pin_config_param param) 216 enum pin_config_param param)
@@ -201,59 +266,24 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
201 unsigned int pin, u32 *strength) 266 unsigned int pin, u32 *strength)
202{ 267{
203 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 268 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
204 const struct pin_desc *desc = pin_desc_get(pctldev, pin); 269 unsigned int reg, shift, mask, val;
205 enum uniphier_pin_drv_type type = 270 const unsigned int *strengths;
206 uniphier_pin_get_drv_type(desc->drv_data);
207 static const unsigned int strength_1bit[] = {4, 8};
208 static const unsigned int strength_2bit[] = {8, 12, 16, 20};
209 static const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12,
210 14, 16};
211 const unsigned int *supported_strength;
212 unsigned int drvctrl, reg, shift, mask, width, val;
213 int ret; 271 int ret;
214 272
215 switch (type) { 273 ret = uniphier_conf_get_drvctrl_data(pctldev, pin, &reg, &shift,
216 case UNIPHIER_PIN_DRV_1BIT: 274 &mask, &strengths);
217 supported_strength = strength_1bit;
218 reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
219 width = 1;
220 break;
221 case UNIPHIER_PIN_DRV_2BIT:
222 supported_strength = strength_2bit;
223 reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
224 width = 2;
225 break;
226 case UNIPHIER_PIN_DRV_3BIT:
227 supported_strength = strength_3bit;
228 reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
229 width = 4;
230 break;
231 case UNIPHIER_PIN_DRV_FIXED4:
232 *strength = 4;
233 return 0;
234 case UNIPHIER_PIN_DRV_FIXED5:
235 *strength = 5;
236 return 0;
237 case UNIPHIER_PIN_DRV_FIXED8:
238 *strength = 8;
239 return 0;
240 default:
241 /* drive strength control is not supported for this pin */
242 return -EINVAL;
243 }
244
245 drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
246 drvctrl *= width;
247
248 reg += drvctrl / 32 * 4;
249 shift = drvctrl % 32;
250 mask = (1U << width) - 1;
251
252 ret = regmap_read(priv->regmap, reg, &val);
253 if (ret) 275 if (ret)
254 return ret; 276 return ret;
255 277
256 *strength = supported_strength[(val >> shift) & mask]; 278 if (mask) {
279 ret = regmap_read(priv->regmap, reg, &val);
280 if (ret)
281 return ret;
282 } else {
283 val = 0;
284 }
285
286 *strength = strengths[(val >> shift) & mask];
257 287
258 return 0; 288 return 0;
259} 289}
@@ -398,40 +428,20 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
398{ 428{
399 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); 429 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
400 const struct pin_desc *desc = pin_desc_get(pctldev, pin); 430 const struct pin_desc *desc = pin_desc_get(pctldev, pin);
401 enum uniphier_pin_drv_type type = 431 unsigned int reg, shift, mask, val;
402 uniphier_pin_get_drv_type(desc->drv_data); 432 const unsigned int *strengths;
403 static const unsigned int strength_1bit[] = {4, 8, -1}; 433 int ret;
404 static const unsigned int strength_2bit[] = {8, 12, 16, 20, -1};
405 static const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14,
406 16, -1};
407 const unsigned int *supported_strength;
408 unsigned int drvctrl, reg, shift, mask, width, val;
409 434
410 switch (type) { 435 ret = uniphier_conf_get_drvctrl_data(pctldev, pin, &reg, &shift,
411 case UNIPHIER_PIN_DRV_1BIT: 436 &mask, &strengths);
412 supported_strength = strength_1bit; 437 if (ret) {
413 reg = UNIPHIER_PINCTRL_DRVCTRL_BASE; 438 dev_err(pctldev->dev, "cannot set drive strength for pin %s\n",
414 width = 1;
415 break;
416 case UNIPHIER_PIN_DRV_2BIT:
417 supported_strength = strength_2bit;
418 reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
419 width = 2;
420 break;
421 case UNIPHIER_PIN_DRV_3BIT:
422 supported_strength = strength_3bit;
423 reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
424 width = 4;
425 break;
426 default:
427 dev_err(pctldev->dev,
428 "cannot change drive strength for pin %s\n",
429 desc->name); 439 desc->name);
430 return -EINVAL; 440 return ret;
431 } 441 }
432 442
433 for (val = 0; supported_strength[val] > 0; val++) { 443 for (val = 0; val <= mask; val++) {
434 if (supported_strength[val] > strength) 444 if (strengths[val] > strength)
435 break; 445 break;
436 } 446 }
437 447
@@ -442,14 +452,10 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
442 return -EINVAL; 452 return -EINVAL;
443 } 453 }
444 454
445 val--; 455 if (!mask)
446 456 return 0;
447 drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
448 drvctrl *= width;
449 457
450 reg += drvctrl / 32 * 4; 458 val--;
451 shift = drvctrl % 32;
452 mask = (1U << width) - 1;
453 459
454 return regmap_update_bits(priv->regmap, reg, 460 return regmap_update_bits(priv->regmap, reg,
455 mask << shift, val << shift); 461 mask << shift, val << shift);