Merge branch 'soc' into pinmux-base
[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();
b0e10211 75}
2967dab1 76
1a0039dc 77int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
934cb02b 78{
63d57383
LP
79 unsigned int offset;
80 unsigned int i;
81
82 if (pfc->info->ranges == NULL)
1a0039dc 83 return pin;
63d57383
LP
84
85 for (i = 0, offset = 0; i < pfc->info->nr_ranges; ++i) {
86 const struct pinmux_range *range = &pfc->info->ranges[i];
87
88 if (pin <= range->end)
89 return pin >= range->begin
1a0039dc 90 ? offset + pin - range->begin : -1;
63d57383
LP
91
92 offset += range->end - range->begin + 1;
93 }
94
b705c054 95 return -EINVAL;
934cb02b
LP
96}
97
cd3c1bee
LP
98static int sh_pfc_enum_in_range(pinmux_enum_t enum_id,
99 const struct pinmux_range *r)
2967dab1
MD
100{
101 if (enum_id < r->begin)
102 return 0;
103
104 if (enum_id > r->end)
105 return 0;
106
107 return 1;
108}
109
41f1219f
LP
110unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg,
111 unsigned long reg_width)
3292094e
MD
112{
113 switch (reg_width) {
114 case 8:
b0e10211 115 return ioread8(mapped_reg);
3292094e 116 case 16:
b0e10211 117 return ioread16(mapped_reg);
3292094e 118 case 32:
b0e10211 119 return ioread32(mapped_reg);
3292094e
MD
120 }
121
122 BUG();
123 return 0;
124}
125
41f1219f
LP
126void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width,
127 unsigned long data)
3292094e
MD
128{
129 switch (reg_width) {
130 case 8:
b0e10211 131 iowrite8(data, mapped_reg);
3292094e
MD
132 return;
133 case 16:
b0e10211 134 iowrite16(data, mapped_reg);
3292094e
MD
135 return;
136 case 32:
b0e10211 137 iowrite32(data, mapped_reg);
3292094e
MD
138 return;
139 }
140
141 BUG();
142}
143
4aeacd5b 144static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
cd3c1bee 145 const struct pinmux_cfg_reg *crp,
4aeacd5b
LP
146 unsigned long in_pos,
147 void __iomem **mapped_regp,
148 unsigned long *maskp,
149 unsigned long *posp)
2967dab1 150{
f78a26f5
MD
151 int k;
152
4aeacd5b 153 *mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg);
2967dab1 154
f78a26f5
MD
155 if (crp->field_width) {
156 *maskp = (1 << crp->field_width) - 1;
157 *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
158 } else {
159 *maskp = (1 << crp->var_field_width[in_pos]) - 1;
160 *posp = crp->reg_width;
161 for (k = 0; k <= in_pos; k++)
162 *posp -= crp->var_field_width[k];
163 }
18925e11
MD
164}
165
4aeacd5b 166static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
cd3c1bee 167 const struct pinmux_cfg_reg *crp,
4aeacd5b 168 unsigned long field, unsigned long value)
0fc64cc0 169{
18925e11 170 void __iomem *mapped_reg;
e499ada8 171 unsigned long mask, pos, data;
0fc64cc0 172
4aeacd5b 173 sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
2967dab1 174
9a643c9a
LP
175 dev_dbg(pfc->dev, "write_reg addr = %lx, value = %ld, field = %ld, "
176 "r_width = %ld, f_width = %ld\n",
177 crp->reg, value, field, crp->reg_width, crp->field_width);
0fc64cc0
MD
178
179 mask = ~(mask << pos);
180 value = value << pos;
2967dab1 181
4aeacd5b 182 data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
e499ada8
MD
183 data &= mask;
184 data |= value;
185
19bb7fe3 186 if (pfc->info->unlock_reg)
4aeacd5b 187 sh_pfc_write_raw_reg(
19bb7fe3 188 sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
4aeacd5b 189 ~data);
e499ada8 190
4aeacd5b 191 sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
2967dab1
MD
192}
193
4aeacd5b 194static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
cd3c1bee 195 const struct pinmux_cfg_reg **crp, int *fieldp,
861601de 196 int *valuep)
2967dab1 197{
cd3c1bee 198 const struct pinmux_cfg_reg *config_reg;
f78a26f5
MD
199 unsigned long r_width, f_width, curr_width, ncomb;
200 int k, m, n, pos, bit_pos;
2967dab1
MD
201
202 k = 0;
203 while (1) {
19bb7fe3 204 config_reg = pfc->info->cfg_regs + k;
2967dab1
MD
205
206 r_width = config_reg->reg_width;
207 f_width = config_reg->field_width;
208
209 if (!r_width)
210 break;
f78a26f5
MD
211
212 pos = 0;
213 m = 0;
214 for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
215 if (f_width)
216 curr_width = f_width;
217 else
218 curr_width = config_reg->var_field_width[m];
219
220 ncomb = 1 << curr_width;
221 for (n = 0; n < ncomb; n++) {
222 if (config_reg->enum_ids[pos + n] == enum_id) {
223 *crp = config_reg;
224 *fieldp = m;
225 *valuep = n;
f78a26f5
MD
226 return 0;
227 }
2967dab1 228 }
f78a26f5
MD
229 pos += ncomb;
230 m++;
2967dab1
MD
231 }
232 k++;
233 }
234
b705c054 235 return -EINVAL;
2967dab1
MD
236}
237
a68fdca9
LP
238static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, pinmux_enum_t mark, int pos,
239 pinmux_enum_t *enum_idp)
2967dab1 240{
cd3c1bee 241 const pinmux_enum_t *data = pfc->info->gpio_data;
2967dab1
MD
242 int k;
243
2967dab1
MD
244 if (pos) {
245 *enum_idp = data[pos + 1];
246 return pos + 1;
247 }
248
19bb7fe3 249 for (k = 0; k < pfc->info->gpio_data_size; k++) {
a68fdca9 250 if (data[k] == mark) {
2967dab1
MD
251 *enum_idp = data[k + 1];
252 return k + 1;
253 }
254 }
255
9a643c9a
LP
256 dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
257 mark);
b705c054 258 return -EINVAL;
2967dab1
MD
259}
260
861601de 261int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
2967dab1 262{
cd3c1bee 263 const struct pinmux_cfg_reg *cr = NULL;
2967dab1 264 pinmux_enum_t enum_id;
cd3c1bee 265 const struct pinmux_range *range;
ad4a07ff 266 int in_range, pos, field, value;
b705c054 267 int ret;
2967dab1
MD
268
269 switch (pinmux_type) {
270
271 case PINMUX_TYPE_FUNCTION:
272 range = NULL;
273 break;
274
275 case PINMUX_TYPE_OUTPUT:
19bb7fe3 276 range = &pfc->info->output;
2967dab1
MD
277 break;
278
279 case PINMUX_TYPE_INPUT:
19bb7fe3 280 range = &pfc->info->input;
2967dab1
MD
281 break;
282
283 case PINMUX_TYPE_INPUT_PULLUP:
19bb7fe3 284 range = &pfc->info->input_pu;
2967dab1
MD
285 break;
286
287 case PINMUX_TYPE_INPUT_PULLDOWN:
19bb7fe3 288 range = &pfc->info->input_pd;
2967dab1
MD
289 break;
290
291 default:
b705c054 292 return -EINVAL;
2967dab1
MD
293 }
294
295 pos = 0;
296 enum_id = 0;
ad4a07ff
MD
297 field = 0;
298 value = 0;
2967dab1 299 while (1) {
a68fdca9 300 pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
b705c054
LP
301 if (pos < 0)
302 return pos;
2967dab1
MD
303
304 if (!enum_id)
305 break;
306
50dd3145 307 /* first check if this is a function enum */
19bb7fe3 308 in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
50dd3145
MD
309 if (!in_range) {
310 /* not a function enum */
311 if (range) {
312 /*
313 * other range exists, so this pin is
314 * a regular GPIO pin that now is being
315 * bound to a specific direction.
316 *
317 * for this case we only allow function enums
318 * and the enums that match the other range.
319 */
4aeacd5b 320 in_range = sh_pfc_enum_in_range(enum_id, range);
50dd3145
MD
321
322 /*
323 * special case pass through for fixed
324 * input-only or output-only pins without
325 * function enum register association.
326 */
327 if (in_range && enum_id == range->force)
328 continue;
329 } else {
330 /*
331 * no other range exists, so this pin
332 * must then be of the function type.
333 *
334 * allow function type pins to select
335 * any combination of function/in/out
336 * in their MARK lists.
337 */
338 in_range = 1;
339 }
42eed42b
MD
340 }
341
2967dab1
MD
342 if (!in_range)
343 continue;
344
b705c054
LP
345 ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
346 if (ret < 0)
347 return ret;
2967dab1 348
861601de 349 sh_pfc_write_config_reg(pfc, cr, field, value);
2967dab1
MD
350 }
351
352 return 0;
2967dab1
MD
353}
354
c6193eac 355static int sh_pfc_probe(struct platform_device *pdev)
2967dab1 356{
cd3c1bee 357 const struct sh_pfc_soc_info *info;
c6193eac 358 struct sh_pfc *pfc;
0fc64cc0 359 int ret;
2967dab1 360
19bb7fe3
LP
361 info = pdev->id_entry->driver_data
362 ? (void *)pdev->id_entry->driver_data : pdev->dev.platform_data;
363 if (info == NULL)
c6193eac 364 return -ENODEV;
2967dab1 365
8c43fcc7 366 pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
c6193eac
LP
367 if (pfc == NULL)
368 return -ENOMEM;
d4e62d00 369
19bb7fe3 370 pfc->info = info;
c6193eac
LP
371 pfc->dev = &pdev->dev;
372
973931ae 373 ret = sh_pfc_ioremap(pfc, pdev);
c6193eac 374 if (unlikely(ret < 0))
b0e10211
MD
375 return ret;
376
c6193eac 377 spin_lock_init(&pfc->lock);
69edbba0 378
ca5481c6 379 pinctrl_provide_dummies();
b0e10211 380
ca5481c6
PM
381 /*
382 * Initialize pinctrl bindings first
383 */
c6193eac 384 ret = sh_pfc_register_pinctrl(pfc);
f9492fda 385 if (unlikely(ret != 0))
c9fa88e2 386 return ret;
ca5481c6 387
6f6a4a68 388#ifdef CONFIG_GPIO_SH_PFC
ca5481c6
PM
389 /*
390 * Then the GPIO chip
391 */
c6193eac 392 ret = sh_pfc_register_gpiochip(pfc);
6f6a4a68 393 if (unlikely(ret != 0)) {
ca5481c6
PM
394 /*
395 * If the GPIO chip fails to come up we still leave the
396 * PFC state as it is, given that there are already
397 * extant users of it that have succeeded by this point.
398 */
9a643c9a 399 dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
b3c185a7 400 }
6f6a4a68 401#endif
b72421d8 402
c6193eac
LP
403 platform_set_drvdata(pdev, pfc);
404
9a643c9a 405 dev_info(pfc->dev, "%s support registered\n", info->name);
ca5481c6 406
b3c185a7 407 return 0;
b72421d8 408}
6f6a4a68 409
c6193eac
LP
410static int sh_pfc_remove(struct platform_device *pdev)
411{
412 struct sh_pfc *pfc = platform_get_drvdata(pdev);
413
414#ifdef CONFIG_GPIO_SH_PFC
415 sh_pfc_unregister_gpiochip(pfc);
416#endif
417 sh_pfc_unregister_pinctrl(pfc);
418
c6193eac
LP
419 platform_set_drvdata(pdev, NULL);
420
421 return 0;
422}
423
424static const struct platform_device_id sh_pfc_id_table[] = {
d5b1521a
LP
425#ifdef CONFIG_PINCTRL_PFC_R8A7740
426 { "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
881023d2
LP
427#endif
428#ifdef CONFIG_PINCTRL_PFC_R8A7779
429 { "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
6e5469a6 430#endif
ccda552e
LP
431#ifdef CONFIG_PINCTRL_PFC_SH7203
432 { "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
433#endif
a8d42fc4
LP
434#ifdef CONFIG_PINCTRL_PFC_SH7264
435 { "pfc-sh7264", (kernel_ulong_t)&sh7264_pinmux_info },
436#endif
f5e811f2
LP
437#ifdef CONFIG_PINCTRL_PFC_SH7269
438 { "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
439#endif
6e5469a6
LP
440#ifdef CONFIG_PINCTRL_PFC_SH7372
441 { "pfc-sh7372", (kernel_ulong_t)&sh7372_pinmux_info },
5d5166dc
LP
442#endif
443#ifdef CONFIG_PINCTRL_PFC_SH73A0
444 { "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
74cad605
LP
445#endif
446#ifdef CONFIG_PINCTRL_PFC_SH7720
447 { "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
f5e25ae5
LP
448#endif
449#ifdef CONFIG_PINCTRL_PFC_SH7722
450 { "pfc-sh7722", (kernel_ulong_t)&sh7722_pinmux_info },
d05afa0a
LP
451#endif
452#ifdef CONFIG_PINCTRL_PFC_SH7723
453 { "pfc-sh7723", (kernel_ulong_t)&sh7723_pinmux_info },
0ff25bab
LP
454#endif
455#ifdef CONFIG_PINCTRL_PFC_SH7724
456 { "pfc-sh7724", (kernel_ulong_t)&sh7724_pinmux_info },
ac1ebc21
LP
457#endif
458#ifdef CONFIG_PINCTRL_PFC_SH7734
459 { "pfc-sh7734", (kernel_ulong_t)&sh7734_pinmux_info },
0bb92677
LP
460#endif
461#ifdef CONFIG_PINCTRL_PFC_SH7757
462 { "pfc-sh7757", (kernel_ulong_t)&sh7757_pinmux_info },
a56398e9
LP
463#endif
464#ifdef CONFIG_PINCTRL_PFC_SH7785
465 { "pfc-sh7785", (kernel_ulong_t)&sh7785_pinmux_info },
d2a31bdd
LP
466#endif
467#ifdef CONFIG_PINCTRL_PFC_SH7786
468 { "pfc-sh7786", (kernel_ulong_t)&sh7786_pinmux_info },
d5d9a818
LP
469#endif
470#ifdef CONFIG_PINCTRL_PFC_SHX3
471 { "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
d5b1521a 472#endif
c6193eac
LP
473 { "sh-pfc", 0 },
474 { },
475};
476MODULE_DEVICE_TABLE(platform, sh_pfc_id_table);
477
478static struct platform_driver sh_pfc_driver = {
479 .probe = sh_pfc_probe,
480 .remove = sh_pfc_remove,
481 .id_table = sh_pfc_id_table,
482 .driver = {
483 .name = DRV_NAME,
484 .owner = THIS_MODULE,
485 },
486};
487
40ee6fce
LP
488static int __init sh_pfc_init(void)
489{
490 return platform_driver_register(&sh_pfc_driver);
c6193eac 491}
40ee6fce 492postcore_initcall(sh_pfc_init);
c6193eac
LP
493
494static void __exit sh_pfc_exit(void)
495{
496 platform_driver_unregister(&sh_pfc_driver);
497}
498module_exit(sh_pfc_exit);
499
6f6a4a68
LP
500MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
501MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
502MODULE_LICENSE("GPL v2");
This page took 0.270116 seconds and 5 git commands to generate.