blob: 2495d6c1c154fd8bb908ac4d695196a0df0e2143 [file] [log] [blame]
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +09001/*
2 * Pinmuxed GPIO support for SuperH.
3 * Copy from linux kernel driver/sh/pfc.c
4 *
5 * Copyright (C) 2008 Magnus Damm
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 */
11
Tom Riniabb9a042024-05-18 20:20:43 -060012#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070014#include <malloc.h>
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +090015#include <asm/bitops.h>
16#include <asm/io.h>
17#include <sh_pfc.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060019#include <linux/bug.h>
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +090020
21static struct pinmux_info *gpioc;
22
23#define pfc_phys_to_virt(p, a) ((void *)a)
24
25static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
26{
27 if (enum_id < r->begin)
28 return 0;
29
30 if (enum_id > r->end)
31 return 0;
32
33 return 1;
34}
35
36static unsigned long gpio_read_raw_reg(void *mapped_reg,
37 unsigned long reg_width)
38{
39 switch (reg_width) {
40
41 case 8:
42 return readb(mapped_reg);
43 case 16:
44 return readw(mapped_reg);
45 case 32:
46 return readl(mapped_reg);
47 }
48
49 BUG();
50 return 0;
51}
52
53static void gpio_write_raw_reg(void *mapped_reg,
54 unsigned long reg_width,
55 unsigned long data)
56{
57 switch (reg_width) {
58 case 8:
59 writeb(data, mapped_reg);
60 return;
61 case 16:
62 writew(data, mapped_reg);
63 return;
64 case 32:
65 writel(data, mapped_reg);
66 return;
67 }
68
69 BUG();
70}
71
72static int gpio_read_bit(struct pinmux_data_reg *dr,
Kouei Abe86299172017-05-13 15:48:04 +020073 unsigned long offset,
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +090074 unsigned long in_pos)
75{
76 unsigned long pos;
77
78 pos = dr->reg_width - (in_pos + 1);
79
Kouei Abe86299172017-05-13 15:48:04 +020080 debug("read_bit: addr = %lx, pos = %ld, r_width = %ld\n",
81 dr->reg + offset, pos, dr->reg_width);
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +090082
Kouei Abe86299172017-05-13 15:48:04 +020083 return (gpio_read_raw_reg(dr->mapped_reg + offset,
84 dr->reg_width) >> pos) & 1;
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +090085}
86
87static void gpio_write_bit(struct pinmux_data_reg *dr,
88 unsigned long in_pos, unsigned long value)
89{
90 unsigned long pos;
91
92 pos = dr->reg_width - (in_pos + 1);
93
94 debug("write_bit addr = %lx, value = %d, pos = %ld, "
95 "r_width = %ld\n",
96 dr->reg, !!value, pos, dr->reg_width);
97
98 if (value)
99 __set_bit(pos, &dr->reg_shadow);
100 else
101 __clear_bit(pos, &dr->reg_shadow);
102
103 gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
104}
105
106static void config_reg_helper(struct pinmux_info *gpioc,
107 struct pinmux_cfg_reg *crp,
108 unsigned long in_pos,
109#if 0
110 void __iomem **mapped_regp,
111#else
112 void **mapped_regp,
113#endif
114 unsigned long *maskp,
115 unsigned long *posp)
116{
117 int k;
118
119 *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
120
121 if (crp->field_width) {
122 *maskp = (1 << crp->field_width) - 1;
123 *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
124 } else {
125 *maskp = (1 << crp->var_field_width[in_pos]) - 1;
126 *posp = crp->reg_width;
127 for (k = 0; k <= in_pos; k++)
Marek Vasutd1bc9322023-01-26 21:01:35 +0100128 *posp -= abs(crp->var_field_width[k]);
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +0900129 }
130}
131
132static int read_config_reg(struct pinmux_info *gpioc,
133 struct pinmux_cfg_reg *crp,
134 unsigned long field)
135{
136 void *mapped_reg;
137
138 unsigned long mask, pos;
139
140 config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
141
142 debug("read_reg: addr = %lx, field = %ld, "
143 "r_width = %ld, f_width = %ld\n",
144 crp->reg, field, crp->reg_width, crp->field_width);
145
146 return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
147}
148
149static void write_config_reg(struct pinmux_info *gpioc,
150 struct pinmux_cfg_reg *crp,
151 unsigned long field, unsigned long value)
152{
153 void *mapped_reg;
154 unsigned long mask, pos, data;
155
156 config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
157
158 debug("write_reg addr = %lx, value = %ld, field = %ld, "
159 "r_width = %ld, f_width = %ld\n",
160 crp->reg, value, field, crp->reg_width, crp->field_width);
161
162 mask = ~(mask << pos);
163 value = value << pos;
164
165 data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
166 data &= mask;
167 data |= value;
168
169 if (gpioc->unlock_reg)
170 gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
171 32, ~data);
172
173 gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
174}
175
176static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
177{
178 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
179 struct pinmux_data_reg *data_reg;
180 int k, n;
181
182 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
183 return -1;
184
185 k = 0;
186 while (1) {
187 data_reg = gpioc->data_regs + k;
188
189 if (!data_reg->reg_width)
190 break;
191
192 data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
193
194 for (n = 0; n < data_reg->reg_width; n++) {
195 if (data_reg->enum_ids[n] == gpiop->enum_id) {
196 gpiop->flags &= ~PINMUX_FLAG_DREG;
197 gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
198 gpiop->flags &= ~PINMUX_FLAG_DBIT;
199 gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
200 return 0;
201 }
202 }
203 k++;
204 }
205
206 BUG();
207
208 return -1;
209}
210
211static void setup_data_regs(struct pinmux_info *gpioc)
212{
213 struct pinmux_data_reg *drp;
214 int k;
215
216 for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++)
217 setup_data_reg(gpioc, k);
218
219 k = 0;
220 while (1) {
221 drp = gpioc->data_regs + k;
222
223 if (!drp->reg_width)
224 break;
225
226 drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
227 drp->reg_width);
228 k++;
229 }
230}
231
232static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
233 struct pinmux_data_reg **drp, int *bitp)
234{
235 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
236 int k, n;
237
238 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
239 return -1;
240
241 k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
242 n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
243 *drp = gpioc->data_regs + k;
244 *bitp = n;
245 return 0;
246}
247
248static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
249 struct pinmux_cfg_reg **crp,
250 int *fieldp, int *valuep,
251 unsigned long **cntp)
252{
253 struct pinmux_cfg_reg *config_reg;
254 unsigned long r_width, f_width, curr_width, ncomb;
255 int k, m, n, pos, bit_pos;
256
257 k = 0;
258 while (1) {
259 config_reg = gpioc->cfg_regs + k;
260
261 r_width = config_reg->reg_width;
262 f_width = config_reg->field_width;
263
264 if (!r_width)
265 break;
266
267 pos = 0;
268 m = 0;
269 for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
270 if (f_width)
271 curr_width = f_width;
272 else
273 curr_width = config_reg->var_field_width[m];
274
275 ncomb = 1 << curr_width;
276 for (n = 0; n < ncomb; n++) {
277 if (config_reg->enum_ids[pos + n] == enum_id) {
278 *crp = config_reg;
279 *fieldp = m;
280 *valuep = n;
281 *cntp = &config_reg->cnt[m];
282 return 0;
283 }
284 }
285 pos += ncomb;
286 m++;
287 }
288 k++;
289 }
290
291 return -1;
292}
293
294static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
295 int pos, pinmux_enum_t *enum_idp)
296{
297 pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
298 pinmux_enum_t *data = gpioc->gpio_data;
299 int k;
300
301 if (!enum_in_range(enum_id, &gpioc->data)) {
302 if (!enum_in_range(enum_id, &gpioc->mark)) {
303 debug("non data/mark enum_id for gpio %d\n", gpio);
304 return -1;
305 }
306 }
307
308 if (pos) {
309 *enum_idp = data[pos + 1];
310 return pos + 1;
311 }
312
313 for (k = 0; k < gpioc->gpio_data_size; k++) {
314 if (data[k] == enum_id) {
315 *enum_idp = data[k + 1];
316 return k + 1;
317 }
318 }
319
320 debug("cannot locate data/mark enum_id for gpio %d\n", gpio);
321 return -1;
322}
323
324enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
325
326static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
327 int pinmux_type, int cfg_mode)
328{
329 struct pinmux_cfg_reg *cr = NULL;
330 pinmux_enum_t enum_id;
331 struct pinmux_range *range;
332 int in_range, pos, field, value;
333 unsigned long *cntp;
334
335 switch (pinmux_type) {
336
337 case PINMUX_TYPE_FUNCTION:
338 range = NULL;
339 break;
340
341 case PINMUX_TYPE_OUTPUT:
342 range = &gpioc->output;
343 break;
344
345 case PINMUX_TYPE_INPUT:
346 range = &gpioc->input;
347 break;
348
349 case PINMUX_TYPE_INPUT_PULLUP:
350 range = &gpioc->input_pu;
351 break;
352
353 case PINMUX_TYPE_INPUT_PULLDOWN:
354 range = &gpioc->input_pd;
355 break;
356
357 default:
358 goto out_err;
359 }
360
361 pos = 0;
362 enum_id = 0;
363 field = 0;
364 value = 0;
365 while (1) {
366 pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
367 if (pos <= 0)
368 goto out_err;
369
370 if (!enum_id)
371 break;
372
373 /* first check if this is a function enum */
374 in_range = enum_in_range(enum_id, &gpioc->function);
375 if (!in_range) {
376 /* not a function enum */
377 if (range) {
378 /*
379 * other range exists, so this pin is
380 * a regular GPIO pin that now is being
381 * bound to a specific direction.
382 *
383 * for this case we only allow function enums
384 * and the enums that match the other range.
385 */
386 in_range = enum_in_range(enum_id, range);
387
388 /*
389 * special case pass through for fixed
390 * input-only or output-only pins without
391 * function enum register association.
392 */
393 if (in_range && enum_id == range->force)
394 continue;
395 } else {
396 /*
397 * no other range exists, so this pin
398 * must then be of the function type.
399 *
400 * allow function type pins to select
401 * any combination of function/in/out
402 * in their MARK lists.
403 */
404 in_range = 1;
405 }
406 }
407
408 if (!in_range)
409 continue;
410
411 if (get_config_reg(gpioc, enum_id, &cr,
412 &field, &value, &cntp) != 0)
413 goto out_err;
414
415 switch (cfg_mode) {
416 case GPIO_CFG_DRYRUN:
417 if (!*cntp ||
418 (read_config_reg(gpioc, cr, field) != value))
419 continue;
420 break;
421
422 case GPIO_CFG_REQ:
423 write_config_reg(gpioc, cr, field, value);
424 *cntp = *cntp + 1;
425 break;
426
427 case GPIO_CFG_FREE:
428 *cntp = *cntp - 1;
429 break;
430 }
431 }
432
433 return 0;
434 out_err:
435 return -1;
436}
437
438#if 0
439static DEFINE_SPINLOCK(gpio_lock);
440static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip)
441{
442 return container_of(chip, struct pinmux_info, chip);
443}
444#endif
445
446static int sh_gpio_request(unsigned offset)
447{
448 struct pinmux_data_reg *dummy;
449 int i, ret, pinmux_type;
450
451 ret = -1;
452
453 if (!gpioc)
454 goto err_out;
455
456 if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
457 goto err_out;
458
459 /* setup pin function here if no data is associated with pin */
460
461 if (get_data_reg(gpioc, offset, &dummy, &i) != 0)
462 pinmux_type = PINMUX_TYPE_FUNCTION;
463 else
464 pinmux_type = PINMUX_TYPE_GPIO;
465
466 if (pinmux_type == PINMUX_TYPE_FUNCTION) {
467 if (pinmux_config_gpio(gpioc, offset,
468 pinmux_type,
469 GPIO_CFG_DRYRUN) != 0)
470 goto err_out;
471
472 if (pinmux_config_gpio(gpioc, offset,
473 pinmux_type,
474 GPIO_CFG_REQ) != 0)
475 BUG();
476 }
477
478 gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
479 gpioc->gpios[offset].flags |= pinmux_type;
480
481 ret = 0;
482err_out:
483 return ret;
484}
485
486static void sh_gpio_free(unsigned offset)
487{
488 int pinmux_type;
489
490 if (!gpioc)
491 return;
492
493 pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE;
494 pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE);
495 gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
496 gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE;
497}
498
499static int pinmux_direction(struct pinmux_info *gpioc,
500 unsigned gpio, int new_pinmux_type)
501{
502 int pinmux_type;
503 int ret = -1;
504
505 if (!gpioc)
506 goto err_out;
507
508 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
509
510 switch (pinmux_type) {
511 case PINMUX_TYPE_GPIO:
512 break;
513 case PINMUX_TYPE_OUTPUT:
514 case PINMUX_TYPE_INPUT:
515 case PINMUX_TYPE_INPUT_PULLUP:
516 case PINMUX_TYPE_INPUT_PULLDOWN:
517 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
518 break;
519 default:
520 goto err_out;
521 }
522
523 if (pinmux_config_gpio(gpioc, gpio,
524 new_pinmux_type,
525 GPIO_CFG_DRYRUN) != 0)
526 goto err_out;
527
528 if (pinmux_config_gpio(gpioc, gpio,
529 new_pinmux_type,
530 GPIO_CFG_REQ) != 0)
531 BUG();
532
533 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
534 gpioc->gpios[gpio].flags |= new_pinmux_type;
535
536 ret = 0;
537 err_out:
538 return ret;
539}
540
541static int sh_gpio_direction_input(unsigned offset)
542{
543 return pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT);
544}
545
546static void sh_gpio_set_value(struct pinmux_info *gpioc,
547 unsigned gpio, int value)
548{
549 struct pinmux_data_reg *dr = NULL;
550 int bit = 0;
551
552 if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
553 BUG();
554 else
555 gpio_write_bit(dr, bit, value);
556}
557
558static int sh_gpio_direction_output(unsigned offset, int value)
559{
560 sh_gpio_set_value(gpioc, offset, value);
561 return pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT);
562}
563
564static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
565{
566 struct pinmux_data_reg *dr = NULL;
Kouei Abe86299172017-05-13 15:48:04 +0200567 int bit = 0, offset = 0;
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +0900568
569 if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
570 return -1;
Marek Vasut8c0f3bb2023-02-28 07:25:52 +0100571
LUU HOAI9b68f5d2023-02-28 22:34:40 +0100572 if (IS_ENABLED(CONFIG_RCAR_64) &&
Marek Vasut8c0f3bb2023-02-28 07:25:52 +0100573 ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_INPUT))
Kouei Abe86299172017-05-13 15:48:04 +0200574 offset += 4;
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +0900575
Kouei Abe86299172017-05-13 15:48:04 +0200576 return gpio_read_bit(dr, offset, bit);
Nobuhiro Iwamatsu99b1b762012-06-21 11:26:38 +0900577}
578
579static int sh_gpio_get(unsigned offset)
580{
581 return sh_gpio_get_value(gpioc, offset);
582}
583
584static void sh_gpio_set(unsigned offset, int value)
585{
586 sh_gpio_set_value(gpioc, offset, value);
587}
588
589int register_pinmux(struct pinmux_info *pip)
590{
591 if (pip != NULL) {
592 gpioc = pip;
593 debug("%s deregistering\n", pip->name);
594 setup_data_regs(gpioc);
595 }
596 return 0;
597}
598
599int unregister_pinmux(struct pinmux_info *pip)
600{
601 debug("%s deregistering\n", pip->name);
602 if (gpioc != pip)
603 return -1;
604
605 gpioc = NULL;
606 return 0;
607}
608
609int gpio_request(unsigned gpio, const char *label)
610{
611 sh_gpio_request(gpio);
612 return 0;
613}
614
615int gpio_free(unsigned gpio)
616{
617 sh_gpio_free(gpio);
618 return 0;
619}
620
621int gpio_direction_input(unsigned gpio)
622{
623 return sh_gpio_direction_input(gpio);
624}
625
626int gpio_direction_output(unsigned gpio, int value)
627{
628 return sh_gpio_direction_output(gpio, value);
629}
630
631void gpio_set_value(unsigned gpio, int value)
632{
633 sh_gpio_set(gpio, value);
634}
635
636int gpio_get_value(unsigned gpio)
637{
638 return sh_gpio_get(gpio);
639}