diff options
Diffstat (limited to 'drivers/pinctrl/sh-pfc/core.c')
-rw-r--r-- | drivers/pinctrl/sh-pfc/core.c | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 96b02246796a..cb47bcee0aab 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c | |||
@@ -82,17 +82,14 @@ int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin) | |||
82 | unsigned int offset; | 82 | unsigned int offset; |
83 | unsigned int i; | 83 | unsigned int i; |
84 | 84 | ||
85 | if (pfc->info->ranges == NULL) | 85 | for (i = 0, offset = 0; i < pfc->nr_ranges; ++i) { |
86 | return pin; | 86 | const struct sh_pfc_pin_range *range = &pfc->ranges[i]; |
87 | |||
88 | for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) { | ||
89 | const struct pinmux_range *range = &pfc->info->ranges[i]; | ||
90 | 87 | ||
91 | if (pin <= range->end) | 88 | if (pin <= range->end) |
92 | return pin >= range->begin | 89 | return pin >= range->start |
93 | ? offset + pin - range->begin : -1; | 90 | ? offset + pin - range->start : -1; |
94 | 91 | ||
95 | offset += range->end - range->begin + 1; | 92 | offset += range->end - range->start + 1; |
96 | } | 93 | } |
97 | 94 | ||
98 | return -EINVAL; | 95 | return -EINVAL; |
@@ -341,6 +338,59 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type) | |||
341 | return 0; | 338 | return 0; |
342 | } | 339 | } |
343 | 340 | ||
341 | static int sh_pfc_init_ranges(struct sh_pfc *pfc) | ||
342 | { | ||
343 | struct sh_pfc_pin_range *range; | ||
344 | unsigned int nr_ranges; | ||
345 | unsigned int i; | ||
346 | |||
347 | if (pfc->info->pins[0].pin == (u16)-1) { | ||
348 | /* Pin number -1 denotes that the SoC doesn't report pin numbers | ||
349 | * in its pin arrays yet. Consider the pin numbers range as | ||
350 | * continuous and allocate a single range. | ||
351 | */ | ||
352 | pfc->nr_ranges = 1; | ||
353 | pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges), | ||
354 | GFP_KERNEL); | ||
355 | if (pfc->ranges == NULL) | ||
356 | return -ENOMEM; | ||
357 | |||
358 | pfc->ranges->start = 0; | ||
359 | pfc->ranges->end = pfc->info->nr_pins - 1; | ||
360 | pfc->nr_gpio_pins = pfc->info->nr_pins; | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /* Count, allocate and fill the ranges. */ | ||
366 | for (i = 1, nr_ranges = 1; i < pfc->info->nr_pins; ++i) { | ||
367 | if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1) | ||
368 | nr_ranges++; | ||
369 | } | ||
370 | |||
371 | pfc->nr_ranges = nr_ranges; | ||
372 | pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges, | ||
373 | GFP_KERNEL); | ||
374 | if (pfc->ranges == NULL) | ||
375 | return -ENOMEM; | ||
376 | |||
377 | range = pfc->ranges; | ||
378 | range->start = pfc->info->pins[0].pin; | ||
379 | |||
380 | for (i = 1; i < pfc->info->nr_pins; ++i) { | ||
381 | if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1) { | ||
382 | range->end = pfc->info->pins[i-1].pin; | ||
383 | range++; | ||
384 | range->start = pfc->info->pins[i].pin; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | range->end = pfc->info->pins[i-1].pin; | ||
389 | pfc->nr_gpio_pins = range->end + 1; | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
344 | #ifdef CONFIG_OF | 394 | #ifdef CONFIG_OF |
345 | static const struct of_device_id sh_pfc_of_table[] = { | 395 | static const struct of_device_id sh_pfc_of_table[] = { |
346 | #ifdef CONFIG_PINCTRL_PFC_R8A73A4 | 396 | #ifdef CONFIG_PINCTRL_PFC_R8A73A4 |
@@ -431,6 +481,10 @@ static int sh_pfc_probe(struct platform_device *pdev) | |||
431 | 481 | ||
432 | pinctrl_provide_dummies(); | 482 | pinctrl_provide_dummies(); |
433 | 483 | ||
484 | ret = sh_pfc_init_ranges(pfc); | ||
485 | if (ret < 0) | ||
486 | return ret; | ||
487 | |||
434 | /* | 488 | /* |
435 | * Initialize pinctrl bindings first | 489 | * Initialize pinctrl bindings first |
436 | */ | 490 | */ |