ARM: shmobile: r8a7779 pinmux platform device cleanup
[deliverable/linux.git] / drivers / pinctrl / sh-pfc / core.c
CommitLineData
2967dab1 1/*
b3c185a7 2 * SuperH Pin Function Controller support.
2967dab1
MD
3 *
4 * Copyright (C) 2008 Magnus Damm
b3c185a7 5 * Copyright (C) 2009 - 2012 Paul Mundt
2967dab1
MD
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
c6193eac
LP
11
12#define DRV_NAME "sh-pfc"
b72421d8 13
90efde22 14#include <linux/bitops.h>
2967dab1 15#include <linux/err.h>
90efde22 16#include <linux/errno.h>
2967dab1 17#include <linux/io.h>
b0e10211 18#include <linux/ioport.h>
90efde22
LP
19#include <linux/kernel.h>
20#include <linux/module.h>
ca5481c6 21#include <linux/pinctrl/machine.h>
c6193eac 22#include <linux/platform_device.h>
90efde22 23#include <linux/slab.h>
b0e10211 24
f9165132
LP
25#include "core.h"
26
973931ae 27static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev)
b0e10211
MD
28{
29 struct resource *res;
30 int k;
31
bee9f22b
LP
32 if (pdev->num_resources == 0)
33 return -EINVAL;
b0e10211 34
56dc04af 35 pfc->window = devm_kzalloc(pfc->dev, pdev->num_resources *
1724acfd 36 sizeof(*pfc->window), GFP_NOWAIT);
b3c185a7 37 if (!pfc->window)
1724acfd 38 return -ENOMEM;
b0e10211 39
56dc04af 40 pfc->num_windows = pdev->num_resources;
973931ae 41
56dc04af 42 for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) {
b0e10211 43 WARN_ON(resource_type(res) != IORESOURCE_MEM);
b3c185a7
PM
44 pfc->window[k].phys = res->start;
45 pfc->window[k].size = resource_size(res);
c9fa88e2
LP
46 pfc->window[k].virt = devm_ioremap_nocache(pfc->dev, res->start,
47 resource_size(res));
48 if (!pfc->window[k].virt)
1724acfd 49 return -ENOMEM;
b0e10211
MD
50 }
51
52 return 0;
b0e10211
MD
53}
54
e51d5343
LP
55static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc,
56 unsigned long address)
b0e10211 57{
4aeacd5b 58 struct sh_pfc_window *window;
bee9f22b 59 unsigned int i;
b0e10211
MD
60
61 /* scan through physical windows and convert address */
bee9f22b
LP
62 for (i = 0; i < pfc->num_windows; i++) {
63 window = pfc->window + i;
b0e10211
MD
64
65 if (address < window->phys)
66 continue;
67
68 if (address >= (window->phys + window->size))
69 continue;
70
71 return window->virt + (address - window->phys);
72 }
73
bee9f22b 74 BUG();
1960d580 75 return NULL;
b0e10211 76}
2967dab1 77
1a0039dc 78int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
934cb02b 79{
63d57383
LP
80 unsigned int offset;
81 unsigned int i;
82
83 if (pfc->info->ranges == NULL)
1a0039dc 84 return pin;
63d57383
LP
85
86 for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) {
87 const struct pinmux_range *range = &pfc->info->ranges[i];
88
89 if (pin <= range->end)
90 return pin >= range->begin
1a0039dc 91 ? offset + pin - range->begin : -1;
63d57383
LP
92
93 offset += range->end - range->begin + 1;
94 }
95
b705c054 96 return -EINVAL;
934cb02b
LP
97}
98
cd3c1bee
LP
99static int sh_pfc_enum_in_range(pinmux_enum_t enum_id,
100 const struct pinmux_range *r)
2967dab1
MD
101{
102 if (enum_id < r->begin)
103 return 0;
104
105 if (enum_id > r->end)
106 return 0;
107
108 return 1;
109}
110
41f1219f
LP
111unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
112 unsigned long reg_width)
3292094e
MD
113{
114 switch (reg_width) {
115 case 8:
b0e10211 116 return ioread8(mapped_reg);
3292094e 117 case 16:
b0e10211 118 return ioread16(mapped_reg);
3292094e 119 case 32:
b0e10211 120 return ioread32(mapped_reg);
3292094e
MD
121 }
122
123 BUG();
124 return 0;
125}
126
41f1219f
LP
127void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
128 unsigned long data)
3292094e
MD
129{
130 switch (reg_width) {
131 case 8:
b0e10211 132 iowrite8(data, mapped_reg);
3292094e
MD
133 return;
134 case 16:
b0e10211 135 iowrite16(data, mapped_reg);
3292094e
MD
136 return;
137 case 32:
b0e10211 138 iowrite32(data, mapped_reg);
3292094e
MD
139 return;
140 }
141
142 BUG();
143}
144
4aeacd5b 145static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
cd3c1bee 146 const struct pinmux_cfg_reg *crp,
4aeacd5b
LP
147 unsigned long in_pos,
148 void __iomem **mapped_regp,
149 unsigned long *maskp,
150 unsigned long *posp)
2967dab1 151{
f78a26f5
MD
152 int k;
153
4aeacd5b 154 *mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg);
2967dab1 155
f78a26f5
MD
156 if (crp->field_width) {
157 *maskp = (1 << crp->field_width) - 1;
158 *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
159 } else {
160 *maskp = (1 << crp->var_field_width[in_pos]) - 1;
161 *posp = crp->reg_width;
162 for (k = 0; k <= in_pos; k++)
163 *posp -= crp->var_field_width[k];
164 }
18925e11
MD
165}
166
4aeacd5b 167static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
cd3c1bee 168 const struct pinmux_cfg_reg *crp,
4aeacd5b 169 unsigned long field, unsigned long value)
0fc64cc0 170{
18925e11 171 void __iomem *mapped_reg;
e499ada8 172 unsigned long mask, pos, data;
0fc64cc0 173
4aeacd5b 174 sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
2967dab1 175
9a643c9a
LP
176 dev_dbg(pfc->dev, "write_reg addr = %lx, value = %ld, field = %ld, "
177 "r_width = %ld, f_width = %ld\n",
178 crp->reg, value, field, crp->reg_width, crp->field_width);
0fc64cc0
MD
179
180 mask = ~(mask << pos);
181 value = value << pos;
2967dab1 182
4aeacd5b 183 data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
e499ada8
MD
184 data &= mask;
185 data |= value;
186
19bb7fe3 187 if (pfc->info->unlock_reg)
4aeacd5b 188 sh_pfc_write_raw_reg(
19bb7fe3 189 sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
4aeacd5b 190 ~data);
e499ada8 191
4aeacd5b 192 sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
2967dab1
MD
193}
194
4aeacd5b 195static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
cd3c1bee 196 const struct pinmux_cfg_reg **crp, int *fieldp,
861601de 197 int *valuep)
2967dab1 198{
cd3c1bee 199 const struct pinmux_cfg_reg *config_reg;
f78a26f5
MD
200 unsigned long r_width, f_width, curr_width, ncomb;
201 int k, m, n, pos, bit_pos;
2967dab1
MD
202
203 k = 0;
204 while (1) {
19bb7fe3 205 config_reg = pfc->info->cfg_regs + k;
2967dab1
MD
206
207 r_width = config_reg->reg_width;
208 f_width = config_reg->field_width;
209
210 if (!r_width)
211 break;
f78a26f5
MD
212
213 pos = 0;
214 m = 0;
215 for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
216 if (f_width)
217 curr_width = f_width;
218 else
219 curr_width = config_reg->var_field_width[m];
220
221 ncomb = 1 << curr_width;
222 for (n = 0; n < ncomb; n++) {
223 if (config_reg->enum_ids[pos + n] == enum_id) {
224 *crp = config_reg;
225 *fieldp = m;
226 *valuep = n;
f78a26f5
MD
227 return 0;
228 }
2967dab1 229 }
f78a26f5
MD
230 pos += ncomb;
231 m++;
2967dab1
MD
232 }
233 k++;
234 }
235
b705c054 236 return -EINVAL;
2967dab1
MD
237}
238
a68fdca9
LP
239static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, pinmux_enum_t mark, int pos,
240 pinmux_enum_t *enum_idp)
2967dab1 241{
cd3c1bee 242 const pinmux_enum_t *data = pfc->info->gpio_data;
2967dab1
MD
243 int k;
244
2967dab1
MD
245 if (pos) {
246 *enum_idp = data[pos + 1];
247 return pos + 1;
248 }
249
19bb7fe3 250 for (k = 0; k < pfc->info->gpio_data_size; k++) {
a68fdca9 251 if (data[k] == mark) {
2967dab1
MD
252 *enum_idp = data[k + 1];
253 return k + 1;
254 }
255 }
256
9a643c9a
LP
257 dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
258 mark);
b705c054 259 return -EINVAL;
2967dab1
MD
260}
261
861601de 262int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
2967dab1 263{
cd3c1bee 264 const struct pinmux_cfg_reg *cr = NULL;
2967dab1 265 pinmux_enum_t enum_id;
cd3c1bee 266 const struct pinmux_range *range;
ad4a07ff 267 int in_range, pos, field, value;
b705c054 268 int ret;
2967dab1
MD
269
270 switch (pinmux_type) {
e3c47051 271 case PINMUX_TYPE_GPIO:
2967dab1
MD
272 case PINMUX_TYPE_FUNCTION:
273 range = NULL;
274 break;
275
276 case PINMUX_TYPE_OUTPUT:
19bb7fe3 277 range = &pfc->info->output;
2967dab1
MD
278 break;
279
280 case PINMUX_TYPE_INPUT:
19bb7fe3 281 range = &pfc->info->input;
2967dab1
MD
282 break;
283
284 case PINMUX_TYPE_INPUT_PULLUP:
19bb7fe3 285 range = &pfc->info->input_pu;
2967dab1
MD
286 break;
287
288 case PINMUX_TYPE_INPUT_PULLDOWN:
19bb7fe3 289 range = &pfc->info->input_pd;
2967dab1
MD
290 break;
291
292 default:
b705c054 293 return -EINVAL;
2967dab1
MD
294 }
295
296 pos = 0;
297 enum_id = 0;
ad4a07ff
MD
298 field = 0;
299 value = 0;
e3c47051
LP
300
301 /* Iterate over all the configuration fields we need to update. */
2967dab1 302 while (1) {
a68fdca9 303 pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
b705c054
LP
304 if (pos < 0)
305 return pos;
2967dab1
MD
306
307 if (!enum_id)
308 break;
309
e3c47051
LP
310 /* Check if the configuration field selects a function. If it
311 * doesn't, skip the field if it's not applicable to the
312 * requested pinmux type.
313 */
19bb7fe3 314 in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
50dd3145 315 if (!in_range) {
e3c47051
LP
316 if (pinmux_type == PINMUX_TYPE_FUNCTION) {
317 /* Functions are allowed to modify all
318 * fields.
319 */
320 in_range = 1;
321 } else if (pinmux_type != PINMUX_TYPE_GPIO) {
322 /* Input/output types can only modify fields
323 * that correspond to their respective ranges.
50dd3145 324 */
4aeacd5b 325 in_range = sh_pfc_enum_in_range(enum_id, range);
50dd3145
MD
326
327 /*
328 * special case pass through for fixed
329 * input-only or output-only pins without
330 * function enum register association.
331 */
332 if (in_range && enum_id == range->force)
333 continue;
50dd3145 334 }
e3c47051 335 /* GPIOs are only allowed to modify function fields. */
42eed42b
MD
336 }
337
2967dab1
MD
338 if (!in_range)
339 continue;
340
b705c054
LP
341 ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
342 if (ret < 0)
343 return ret;
2967dab1 344
861601de 345 sh_pfc_write_config_reg(pfc, cr, field, value);
2967dab1
MD
346 }
347
348 return 0;
2967dab1
MD
349}
350
c6193eac 351static int sh_pfc_probe(struct platform_device *pdev)
2967dab1 352{
cd3c1bee 353 const struct sh_pfc_soc_info *info;
c6193eac 354 struct sh_pfc *pfc;
0fc64cc0 355 int ret;
2967dab1 356
19bb7fe3
LP
357 info = pdev->id_entry->driver_data
358 ? (void *)pdev->id_entry->driver_data : pdev->dev.platform_data;
359 if (info == NULL)
c6193eac 360 return -ENODEV;
2967dab1 361
8c43fcc7 362 pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
c6193eac
LP
363 if (pfc == NULL)
364 return -ENOMEM;
d4e62d00 365
19bb7fe3 366 pfc->info = info;
c6193eac
LP
367 pfc->dev = &pdev->dev;
368
973931ae 369 ret = sh_pfc_ioremap(pfc, pdev);
c6193eac 370 if (unlikely(ret < 0))
b0e10211
MD
371 return ret;
372
c6193eac 373 spin_lock_init(&pfc->lock);
69edbba0 374
ca5481c6 375 pinctrl_provide_dummies();
b0e10211 376
ca5481c6
PM
377 /*
378 * Initialize pinctrl bindings first
379 */
c6193eac 380 ret = sh_pfc_register_pinctrl(pfc);
f9492fda 381 if (unlikely(ret != 0))
c9fa88e2 382 return ret;
ca5481c6 383
6f6a4a68 384#ifdef CONFIG_GPIO_SH_PFC
ca5481c6
PM
385 /*
386 * Then the GPIO chip
387 */
c6193eac 388 ret = sh_pfc_register_gpiochip(pfc);
6f6a4a68 389 if (unlikely(ret != 0)) {
ca5481c6
PM
390 /*
391 * If the GPIO chip fails to come up we still leave the
392 * PFC state as it is, given that there are already
393 * extant users of it that have succeeded by this point.
394 */
9a643c9a 395 dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
b3c185a7 396 }
6f6a4a68 397#endif
b72421d8 398
c6193eac
LP
399 platform_set_drvdata(pdev, pfc);
400
9a643c9a 401 dev_info(pfc->dev, "%s support registered\n", info->name);
ca5481c6 402
b3c185a7 403 return 0;
b72421d8 404}
6f6a4a68 405
c6193eac
LP
406static int sh_pfc_remove(struct platform_device *pdev)
407{
408 struct sh_pfc *pfc = platform_get_drvdata(pdev);
409
410#ifdef CONFIG_GPIO_SH_PFC
411 sh_pfc_unregister_gpiochip(pfc);
412#endif
413 sh_pfc_unregister_pinctrl(pfc);
414
c6193eac
LP
415 platform_set_drvdata(pdev, NULL);
416
417 return 0;
418}
419
420static const struct platform_device_id sh_pfc_id_table[] = {
c98f6c21
MD
421#ifdef CONFIG_PINCTRL_PFC_R8A73A4
422 { "pfc-r8a73a4", (kernel_ulong_t)&r8a73a4_pinmux_info },
423#endif
d5b1521a
LP
424#ifdef CONFIG_PINCTRL_PFC_R8A7740
425 { "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
881023d2 426#endif
87f8c988
KM
427#ifdef CONFIG_PINCTRL_PFC_R8A7778
428 { "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info },
429#endif
881023d2
LP
430#ifdef CONFIG_PINCTRL_PFC_R8A7779
431 { "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
6e5469a6 432#endif
58c229e1
KM
433#ifdef CONFIG_PINCTRL_PFC_R8A7790
434 { "pfc-r8a7790", (kernel_ulong_t)&r8a7790_pinmux_info },
435#endif
ccda552e
LP
436#ifdef CONFIG_PINCTRL_PFC_SH7203
437 { "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
438#endif
a8d42fc4
LP
439#ifdef CONFIG_PINCTRL_PFC_SH7264
440 { "pfc-sh7264", (kernel_ulong_t)&sh7264_pinmux_info },
441#endif
f5e811f2
LP
442#ifdef CONFIG_PINCTRL_PFC_SH7269
443 { "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
444#endif
6e5469a6
LP
445#ifdef CONFIG_PINCTRL_PFC_SH7372
446 { "pfc-sh7372", (kernel_ulong_t)&sh7372_pinmux_info },
5d5166dc
LP
447#endif
448#ifdef CONFIG_PINCTRL_PFC_SH73A0
449 { "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
74cad605
LP
450#endif
451#ifdef CONFIG_PINCTRL_PFC_SH7720
452 { "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
f5e25ae5
LP
453#endif
454#ifdef CONFIG_PINCTRL_PFC_SH7722
455 { "pfc-sh7722", (kernel_ulong_t)&sh7722_pinmux_info },
d05afa0a
LP
456#endif
457#ifdef CONFIG_PINCTRL_PFC_SH7723
458 { "pfc-sh7723", (kernel_ulong_t)&sh7723_pinmux_info },
0ff25bab
LP
459#endif
460#ifdef CONFIG_PINCTRL_PFC_SH7724
461 { "pfc-sh7724", (kernel_ulong_t)&sh7724_pinmux_info },
ac1ebc21
LP
462#endif
463#ifdef CONFIG_PINCTRL_PFC_SH7734
464 { "pfc-sh7734", (kernel_ulong_t)&sh7734_pinmux_info },
0bb92677
LP
465#endif
466#ifdef CONFIG_PINCTRL_PFC_SH7757
467 { "pfc-sh7757", (kernel_ulong_t)&sh7757_pinmux_info },
a56398e9
LP
468#endif
469#ifdef CONFIG_PINCTRL_PFC_SH7785
470 { "pfc-sh7785", (kernel_ulong_t)&sh7785_pinmux_info },
d2a31bdd
LP
471#endif
472#ifdef CONFIG_PINCTRL_PFC_SH7786
473 { "pfc-sh7786", (kernel_ulong_t)&sh7786_pinmux_info },
d5d9a818
LP
474#endif
475#ifdef CONFIG_PINCTRL_PFC_SHX3
476 { "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
d5b1521a 477#endif
c6193eac
LP
478 { "sh-pfc", 0 },
479 { },
480};
481MODULE_DEVICE_TABLE(platform, sh_pfc_id_table);
482
483static struct platform_driver sh_pfc_driver = {
484 .probe = sh_pfc_probe,
485 .remove = sh_pfc_remove,
486 .id_table = sh_pfc_id_table,
487 .driver = {
488 .name = DRV_NAME,
489 .owner = THIS_MODULE,
490 },
491};
492
40ee6fce
LP
493static int __init sh_pfc_init(void)
494{
495 return platform_driver_register(&sh_pfc_driver);
c6193eac 496}
40ee6fce 497postcore_initcall(sh_pfc_init);
c6193eac
LP
498
499static void __exit sh_pfc_exit(void)
500{
501 platform_driver_unregister(&sh_pfc_driver);
502}
503module_exit(sh_pfc_exit);
504
6f6a4a68
LP
505MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
506MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
507MODULE_LICENSE("GPL v2");
This page took 0.297223 seconds and 5 git commands to generate.