diff options
-rw-r--r-- | drivers/pinctrl/sh-pfc/core.c | 19 | ||||
-rw-r--r-- | drivers/pinctrl/sh-pfc/core.h | 2 | ||||
-rw-r--r-- | drivers/pinctrl/sh-pfc/gpio.c | 37 | ||||
-rw-r--r-- | drivers/pinctrl/sh-pfc/pinctrl.c | 58 | ||||
-rw-r--r-- | drivers/pinctrl/sh-pfc/sh_pfc.h | 2 |
5 files changed, 91 insertions, 27 deletions
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 667db99fb510..798248261f30 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c | |||
@@ -80,7 +80,24 @@ static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, | |||
80 | 80 | ||
81 | struct sh_pfc_pin *sh_pfc_get_pin(struct sh_pfc *pfc, unsigned int pin) | 81 | struct sh_pfc_pin *sh_pfc_get_pin(struct sh_pfc *pfc, unsigned int pin) |
82 | { | 82 | { |
83 | return &pfc->info->pins[pin]; | 83 | unsigned int offset; |
84 | unsigned int i; | ||
85 | |||
86 | if (pfc->info->ranges == NULL) | ||
87 | return &pfc->info->pins[pin]; | ||
88 | |||
89 | for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) { | ||
90 | const struct pinmux_range *range = &pfc->info->ranges[i]; | ||
91 | |||
92 | if (pin <= range->end) | ||
93 | return pin >= range->begin | ||
94 | ? &pfc->info->pins[offset + pin - range->begin] | ||
95 | : NULL; | ||
96 | |||
97 | offset += range->end - range->begin + 1; | ||
98 | } | ||
99 | |||
100 | return NULL; | ||
84 | } | 101 | } |
85 | 102 | ||
86 | static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) | 103 | static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) |
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index 6ea3d4f3d05e..b8b3e872cc19 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h | |||
@@ -32,6 +32,8 @@ struct sh_pfc { | |||
32 | unsigned int num_windows; | 32 | unsigned int num_windows; |
33 | struct sh_pfc_window *window; | 33 | struct sh_pfc_window *window; |
34 | 34 | ||
35 | unsigned int nr_pins; | ||
36 | |||
35 | struct sh_pfc_chip *gpio; | 37 | struct sh_pfc_chip *gpio; |
36 | struct sh_pfc_chip *func; | 38 | struct sh_pfc_chip *func; |
37 | 39 | ||
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 32a9c7870a16..806e2dd62137 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c | |||
@@ -45,7 +45,7 @@ static int gpio_pin_request(struct gpio_chip *gc, unsigned offset) | |||
45 | struct sh_pfc *pfc = gpio_to_pfc(gc); | 45 | struct sh_pfc *pfc = gpio_to_pfc(gc); |
46 | struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, offset); | 46 | struct sh_pfc_pin *pin = sh_pfc_get_pin(pfc, offset); |
47 | 47 | ||
48 | if (pin->enum_id == 0) | 48 | if (pin == NULL || pin->enum_id == 0) |
49 | return -EINVAL; | 49 | return -EINVAL; |
50 | 50 | ||
51 | return pinctrl_request_gpio(offset); | 51 | return pinctrl_request_gpio(offset); |
@@ -127,7 +127,7 @@ static void gpio_pin_setup(struct sh_pfc_chip *chip) | |||
127 | gc->dev = pfc->dev; | 127 | gc->dev = pfc->dev; |
128 | gc->owner = THIS_MODULE; | 128 | gc->owner = THIS_MODULE; |
129 | gc->base = 0; | 129 | gc->base = 0; |
130 | gc->ngpio = pfc->info->nr_pins; | 130 | gc->ngpio = pfc->nr_pins; |
131 | } | 131 | } |
132 | 132 | ||
133 | /* ----------------------------------------------------------------------------- | 133 | /* ----------------------------------------------------------------------------- |
@@ -184,7 +184,7 @@ static void gpio_function_setup(struct sh_pfc_chip *chip) | |||
184 | 184 | ||
185 | gc->label = pfc->info->name; | 185 | gc->label = pfc->info->name; |
186 | gc->owner = THIS_MODULE; | 186 | gc->owner = THIS_MODULE; |
187 | gc->base = pfc->info->nr_pins; | 187 | gc->base = pfc->nr_pins; |
188 | gc->ngpio = pfc->info->nr_func_gpios; | 188 | gc->ngpio = pfc->info->nr_func_gpios; |
189 | } | 189 | } |
190 | 190 | ||
@@ -219,20 +219,43 @@ sh_pfc_add_gpiochip(struct sh_pfc *pfc, void(*setup)(struct sh_pfc_chip *)) | |||
219 | 219 | ||
220 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc) | 220 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc) |
221 | { | 221 | { |
222 | const struct pinmux_range *ranges; | ||
223 | struct pinmux_range def_range; | ||
222 | struct sh_pfc_chip *chip; | 224 | struct sh_pfc_chip *chip; |
225 | unsigned int nr_ranges; | ||
226 | unsigned int i; | ||
223 | int ret; | 227 | int ret; |
224 | 228 | ||
229 | /* Register the real GPIOs chip. */ | ||
225 | chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup); | 230 | chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup); |
226 | if (IS_ERR(chip)) | 231 | if (IS_ERR(chip)) |
227 | return PTR_ERR(chip); | 232 | return PTR_ERR(chip); |
228 | 233 | ||
229 | pfc->gpio = chip; | 234 | pfc->gpio = chip; |
230 | 235 | ||
231 | ret = gpiochip_add_pin_range(&chip->gpio_chip, dev_name(pfc->dev), 0, 0, | 236 | /* Register the GPIO to pin mappings. */ |
232 | chip->gpio_chip.ngpio); | 237 | if (pfc->info->ranges == NULL) { |
233 | if (ret < 0) | 238 | def_range.begin = 0; |
234 | return ret; | 239 | def_range.end = pfc->info->nr_pins - 1; |
240 | ranges = &def_range; | ||
241 | nr_ranges = 1; | ||
242 | } else { | ||
243 | ranges = pfc->info->ranges; | ||
244 | nr_ranges = pfc->info->nr_ranges; | ||
245 | } | ||
246 | |||
247 | for (i = 0; i < nr_ranges; ++i) { | ||
248 | const struct pinmux_range *range = &ranges[i]; | ||
249 | |||
250 | ret = gpiochip_add_pin_range(&chip->gpio_chip, | ||
251 | dev_name(pfc->dev), | ||
252 | range->begin, range->begin, | ||
253 | range->end - range->begin + 1); | ||
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | } | ||
235 | 257 | ||
258 | /* Register the function GPIOs chip. */ | ||
236 | chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup); | 259 | chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup); |
237 | if (IS_ERR(chip)) | 260 | if (IS_ERR(chip)) |
238 | return PTR_ERR(chip); | 261 | return PTR_ERR(chip); |
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index a60c317d988a..c9e9a1d95230 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c | |||
@@ -293,29 +293,48 @@ static const struct pinconf_ops sh_pfc_pinconf_ops = { | |||
293 | .pin_config_dbg_show = sh_pfc_pinconf_dbg_show, | 293 | .pin_config_dbg_show = sh_pfc_pinconf_dbg_show, |
294 | }; | 294 | }; |
295 | 295 | ||
296 | /* pinmux ranges -> pinctrl pin descs */ | 296 | /* PFC ranges -> pinctrl pin descs */ |
297 | static int sh_pfc_map_gpios(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | 297 | static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) |
298 | { | 298 | { |
299 | int i; | 299 | const struct pinmux_range *ranges; |
300 | 300 | struct pinmux_range def_range; | |
301 | pmx->nr_pads = pfc->info->nr_pins; | 301 | unsigned int nr_ranges; |
302 | unsigned int nr_pins; | ||
303 | unsigned int i; | ||
304 | |||
305 | if (pfc->info->ranges == NULL) { | ||
306 | def_range.begin = 0; | ||
307 | def_range.end = pfc->info->nr_pins - 1; | ||
308 | ranges = &def_range; | ||
309 | nr_ranges = 1; | ||
310 | } else { | ||
311 | ranges = pfc->info->ranges; | ||
312 | nr_ranges = pfc->info->nr_ranges; | ||
313 | } | ||
302 | 314 | ||
303 | pmx->pads = devm_kzalloc(pfc->dev, sizeof(*pmx->pads) * pmx->nr_pads, | 315 | pmx->pads = devm_kzalloc(pfc->dev, |
316 | sizeof(*pmx->pads) * pfc->info->nr_pins, | ||
304 | GFP_KERNEL); | 317 | GFP_KERNEL); |
305 | if (unlikely(!pmx->pads)) { | 318 | if (unlikely(!pmx->pads)) |
306 | pmx->nr_pads = 0; | ||
307 | return -ENOMEM; | 319 | return -ENOMEM; |
308 | } | ||
309 | 320 | ||
310 | for (i = 0; i < pmx->nr_pads; i++) { | 321 | for (i = 0, nr_pins = 0; i < nr_ranges; ++i) { |
311 | struct pinctrl_pin_desc *pin = pmx->pads + i; | 322 | const struct pinmux_range *range = &ranges[i]; |
312 | struct sh_pfc_pin *gpio = pfc->info->pins + i; | 323 | unsigned int number; |
324 | |||
325 | for (number = range->begin; number <= range->end; | ||
326 | number++, nr_pins++) { | ||
327 | struct pinctrl_pin_desc *pin = &pmx->pads[nr_pins]; | ||
328 | struct sh_pfc_pin *info = &pfc->info->pins[nr_pins]; | ||
313 | 329 | ||
314 | pin->number = i; | 330 | pin->number = number; |
315 | pin->name = gpio->name; | 331 | pin->name = info->name; |
332 | } | ||
316 | } | 333 | } |
317 | 334 | ||
318 | return 0; | 335 | pfc->nr_pins = ranges[nr_ranges-1].end + 1; |
336 | |||
337 | return nr_ranges; | ||
319 | } | 338 | } |
320 | 339 | ||
321 | static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | 340 | static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) |
@@ -347,6 +366,7 @@ static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | |||
347 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc) | 366 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc) |
348 | { | 367 | { |
349 | struct sh_pfc_pinctrl *pmx; | 368 | struct sh_pfc_pinctrl *pmx; |
369 | int nr_ranges; | ||
350 | int ret; | 370 | int ret; |
351 | 371 | ||
352 | pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL); | 372 | pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL); |
@@ -356,9 +376,9 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc) | |||
356 | pmx->pfc = pfc; | 376 | pmx->pfc = pfc; |
357 | pfc->pinctrl = pmx; | 377 | pfc->pinctrl = pmx; |
358 | 378 | ||
359 | ret = sh_pfc_map_gpios(pfc, pmx); | 379 | nr_ranges = sh_pfc_map_pins(pfc, pmx); |
360 | if (unlikely(ret != 0)) | 380 | if (unlikely(nr_ranges < 0)) |
361 | return ret; | 381 | return nr_ranges; |
362 | 382 | ||
363 | ret = sh_pfc_map_functions(pfc, pmx); | 383 | ret = sh_pfc_map_functions(pfc, pmx); |
364 | if (unlikely(ret != 0)) | 384 | if (unlikely(ret != 0)) |
@@ -370,7 +390,7 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc) | |||
370 | pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops; | 390 | pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops; |
371 | pmx->pctl_desc.confops = &sh_pfc_pinconf_ops; | 391 | pmx->pctl_desc.confops = &sh_pfc_pinconf_ops; |
372 | pmx->pctl_desc.pins = pmx->pads; | 392 | pmx->pctl_desc.pins = pmx->pads; |
373 | pmx->pctl_desc.npins = pmx->nr_pads; | 393 | pmx->pctl_desc.npins = pfc->info->nr_pins; |
374 | 394 | ||
375 | pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx); | 395 | pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx); |
376 | if (IS_ERR(pmx->pctl)) | 396 | if (IS_ERR(pmx->pctl)) |
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 43c858d98321..dbcaa600ccc6 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h | |||
@@ -111,6 +111,8 @@ struct sh_pfc_soc_info { | |||
111 | 111 | ||
112 | struct sh_pfc_pin *pins; | 112 | struct sh_pfc_pin *pins; |
113 | unsigned int nr_pins; | 113 | unsigned int nr_pins; |
114 | const struct pinmux_range *ranges; | ||
115 | unsigned int nr_ranges; | ||
114 | struct pinmux_func *func_gpios; | 116 | struct pinmux_func *func_gpios; |
115 | unsigned int nr_func_gpios; | 117 | unsigned int nr_func_gpios; |
116 | 118 | ||