aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-02-14 19:33:38 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-03-15 08:33:39 -0400
commit63d573835f835aab4c44d0e0342cf5976fb14b35 (patch)
treed5998a6c0cb914d85c246b0464b2b7e7db959d2a /drivers/pinctrl
parent247127f90ba1fcc234008e00e937537a89eef9ca (diff)
sh-pfc: Add support for sparse pin numbers
The PFC driver assumes that the value of the GPIO_PORTxxx enumeration names are equal to the port number. This isn't true when the port number space is sparse, as with the SH73A0. Fix the issue by adding support for pin numbers ranges specified through SoC data. When no range is specified the driver considers that the PFC implements a single contiguous range for all pins. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Acked-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/sh-pfc/core.c19
-rw-r--r--drivers/pinctrl/sh-pfc/core.h2
-rw-r--r--drivers/pinctrl/sh-pfc/gpio.c37
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c58
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h2
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
81struct sh_pfc_pin *sh_pfc_get_pin(struct sh_pfc *pfc, unsigned int pin) 81struct 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
86static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) 103static 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
220int sh_pfc_register_gpiochip(struct sh_pfc *pfc) 220int 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 */
297static int sh_pfc_map_gpios(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) 297static 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
321static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) 340static 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)
347int sh_pfc_register_pinctrl(struct sh_pfc *pfc) 366int 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