diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-01-10 03:34:14 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-01-11 04:40:23 -0500 |
commit | fb36a7b07dbf565014ed624a1bfd24d807f56b85 (patch) | |
tree | 272c84cee68c85d9986598232008674fa962fac2 | |
parent | d6093367bc743bc6679ab75a89cd3dd93476a755 (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.c | 176 |
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 | ||
149 | static const unsigned int uniphier_conf_drv_strengths_1bit[] = {4, 8}; | ||
150 | static const unsigned int uniphier_conf_drv_strengths_2bit[] = {8, 12, 16, 20}; | ||
151 | static const unsigned int uniphier_conf_drv_strengths_3bit[] = {4, 5, 7, 9, 11, | ||
152 | 12, 14, 16}; | ||
153 | static const unsigned int uniphier_conf_drv_strengths_fixed4[] = {4}; | ||
154 | static const unsigned int uniphier_conf_drv_strengths_fixed5[] = {5}; | ||
155 | static const unsigned int uniphier_conf_drv_strengths_fixed8[] = {8}; | ||
156 | |||
157 | static 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 | |||
149 | static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev, | 214 | static 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, ®, &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, ®, &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); |