blob: 28013567372649897822affc496a25853ccff755 [file] [log] [blame]
Magnus Damm2967dab2008-10-08 20:41:43 +09001/*
2 * Pinmuxed GPIO support for SuperH.
3 *
4 * Copyright (C) 2008 Magnus Damm
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/errno.h>
12#include <linux/kernel.h>
13#include <linux/list.h>
14#include <linux/module.h>
15#include <linux/clk.h>
16#include <linux/err.h>
17#include <linux/io.h>
18#include <linux/irq.h>
19#include <linux/bitops.h>
20#include <linux/gpio.h>
21
22static struct pinmux_info *registered_gpio;
23
24static struct pinmux_info *gpio_controller(unsigned gpio)
25{
26 if (!registered_gpio)
27 return NULL;
28
29 if (gpio < registered_gpio->first_gpio)
30 return NULL;
31
32 if (gpio > registered_gpio->last_gpio)
33 return NULL;
34
35 return registered_gpio;
36}
37
38static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
39{
40 if (enum_id < r->begin)
41 return 0;
42
43 if (enum_id > r->end)
44 return 0;
45
46 return 1;
47}
48
Magnus Damm32920942008-12-25 18:17:26 +090049static unsigned long gpio_read_raw_reg(unsigned long reg,
50 unsigned long reg_width)
51{
52 switch (reg_width) {
53 case 8:
54 return ctrl_inb(reg);
55 case 16:
56 return ctrl_inw(reg);
57 case 32:
58 return ctrl_inl(reg);
59 }
60
61 BUG();
62 return 0;
63}
64
65static void gpio_write_raw_reg(unsigned long reg,
66 unsigned long reg_width,
67 unsigned long data)
68{
69 switch (reg_width) {
70 case 8:
71 ctrl_outb(data, reg);
72 return;
73 case 16:
74 ctrl_outw(data, reg);
75 return;
76 case 32:
77 ctrl_outl(data, reg);
78 return;
79 }
80
81 BUG();
82}
83
84static void gpio_write_bit(struct pinmux_data_reg *dr,
85 unsigned long in_pos, unsigned long value)
86{
87 unsigned long pos;
88
89 pos = dr->reg_width - (in_pos + 1);
90
91#ifdef DEBUG
92 pr_info("write_bit addr = %lx, value = %ld, pos = %ld, "
93 "r_width = %ld\n",
94 dr->reg, !!value, pos, dr->reg_width);
95#endif
96
97 if (value)
98 set_bit(pos, &dr->reg_shadow);
99 else
100 clear_bit(pos, &dr->reg_shadow);
101
102 gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
103}
104
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900105static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
106 unsigned long field_width, unsigned long in_pos)
Magnus Damm2967dab2008-10-08 20:41:43 +0900107{
108 unsigned long data, mask, pos;
109
110 data = 0;
111 mask = (1 << field_width) - 1;
112 pos = reg_width - ((in_pos + 1) * field_width);
113
114#ifdef DEBUG
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900115 pr_info("read_reg: addr = %lx, pos = %ld, "
Magnus Damm2967dab2008-10-08 20:41:43 +0900116 "r_width = %ld, f_width = %ld\n",
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900117 reg, pos, reg_width, field_width);
Magnus Damm2967dab2008-10-08 20:41:43 +0900118#endif
119
Magnus Damm32920942008-12-25 18:17:26 +0900120 data = gpio_read_raw_reg(reg, reg_width);
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900121 return (data >> pos) & mask;
122}
Magnus Damm2967dab2008-10-08 20:41:43 +0900123
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900124static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
125 unsigned long field_width, unsigned long in_pos,
126 unsigned long value)
127{
128 unsigned long mask, pos;
129
130 mask = (1 << field_width) - 1;
131 pos = reg_width - ((in_pos + 1) * field_width);
132
133#ifdef DEBUG
134 pr_info("write_reg addr = %lx, value = %ld, pos = %ld, "
135 "r_width = %ld, f_width = %ld\n",
136 reg, value, pos, reg_width, field_width);
137#endif
138
139 mask = ~(mask << pos);
140 value = value << pos;
Magnus Damm2967dab2008-10-08 20:41:43 +0900141
142 switch (reg_width) {
143 case 8:
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900144 ctrl_outb((ctrl_inb(reg) & mask) | value, reg);
Magnus Damm2967dab2008-10-08 20:41:43 +0900145 break;
146 case 16:
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900147 ctrl_outw((ctrl_inw(reg) & mask) | value, reg);
Magnus Damm2967dab2008-10-08 20:41:43 +0900148 break;
149 case 32:
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900150 ctrl_outl((ctrl_inl(reg) & mask) | value, reg);
Magnus Damm2967dab2008-10-08 20:41:43 +0900151 break;
152 }
Magnus Damm2967dab2008-10-08 20:41:43 +0900153}
154
Magnus Damm18801be2008-12-25 18:17:09 +0900155static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
Magnus Damm2967dab2008-10-08 20:41:43 +0900156{
Magnus Damm18801be2008-12-25 18:17:09 +0900157 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
Magnus Damm2967dab2008-10-08 20:41:43 +0900158 struct pinmux_data_reg *data_reg;
159 int k, n;
160
Magnus Damm18801be2008-12-25 18:17:09 +0900161 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
Magnus Damm2967dab2008-10-08 20:41:43 +0900162 return -1;
163
164 k = 0;
165 while (1) {
166 data_reg = gpioc->data_regs + k;
167
168 if (!data_reg->reg_width)
169 break;
170
171 for (n = 0; n < data_reg->reg_width; n++) {
Magnus Damm18801be2008-12-25 18:17:09 +0900172 if (data_reg->enum_ids[n] == gpiop->enum_id) {
173 gpiop->flags &= ~PINMUX_FLAG_DREG;
174 gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
175 gpiop->flags &= ~PINMUX_FLAG_DBIT;
176 gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
Magnus Damm2967dab2008-10-08 20:41:43 +0900177 return 0;
Magnus Damm2967dab2008-10-08 20:41:43 +0900178 }
179 }
180 k++;
181 }
182
Magnus Damm18801be2008-12-25 18:17:09 +0900183 BUG();
184
Magnus Damm2967dab2008-10-08 20:41:43 +0900185 return -1;
186}
187
Magnus Damm32920942008-12-25 18:17:26 +0900188static void setup_data_regs(struct pinmux_info *gpioc)
189{
190 struct pinmux_data_reg *drp;
191 int k;
192
193 for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++)
194 setup_data_reg(gpioc, k);
195
196 k = 0;
197 while (1) {
198 drp = gpioc->data_regs + k;
199
200 if (!drp->reg_width)
201 break;
202
203 drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
204 k++;
205 }
206}
207
Magnus Damm18801be2008-12-25 18:17:09 +0900208static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
209 struct pinmux_data_reg **drp, int *bitp)
210{
211 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
212 int k, n;
213
214 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
215 return -1;
216
217 k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
218 n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
219 *drp = gpioc->data_regs + k;
220 *bitp = n;
221 return 0;
222}
223
Magnus Damm2967dab2008-10-08 20:41:43 +0900224static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
225 struct pinmux_cfg_reg **crp, int *indexp,
226 unsigned long **cntp)
227{
228 struct pinmux_cfg_reg *config_reg;
229 unsigned long r_width, f_width;
230 int k, n;
231
232 k = 0;
233 while (1) {
234 config_reg = gpioc->cfg_regs + k;
235
236 r_width = config_reg->reg_width;
237 f_width = config_reg->field_width;
238
239 if (!r_width)
240 break;
241 for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) {
242 if (config_reg->enum_ids[n] == enum_id) {
243 *crp = config_reg;
244 *indexp = n;
245 *cntp = &config_reg->cnt[n / (1 << f_width)];
246 return 0;
247 }
248 }
249 k++;
250 }
251
252 return -1;
253}
254
255static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
256 int pos, pinmux_enum_t *enum_idp)
257{
258 pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
259 pinmux_enum_t *data = gpioc->gpio_data;
260 int k;
261
262 if (!enum_in_range(enum_id, &gpioc->data)) {
263 if (!enum_in_range(enum_id, &gpioc->mark)) {
264 pr_err("non data/mark enum_id for gpio %d\n", gpio);
265 return -1;
266 }
267 }
268
269 if (pos) {
270 *enum_idp = data[pos + 1];
271 return pos + 1;
272 }
273
274 for (k = 0; k < gpioc->gpio_data_size; k++) {
275 if (data[k] == enum_id) {
276 *enum_idp = data[k + 1];
277 return k + 1;
278 }
279 }
280
281 pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
282 return -1;
283}
284
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900285static void write_config_reg(struct pinmux_info *gpioc,
286 struct pinmux_cfg_reg *crp,
287 int index)
Magnus Damm2967dab2008-10-08 20:41:43 +0900288{
289 unsigned long ncomb, pos, value;
290
291 ncomb = 1 << crp->field_width;
292 pos = index / ncomb;
293 value = index % ncomb;
294
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900295 gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
Magnus Damm2967dab2008-10-08 20:41:43 +0900296}
297
298static int check_config_reg(struct pinmux_info *gpioc,
299 struct pinmux_cfg_reg *crp,
300 int index)
301{
302 unsigned long ncomb, pos, value;
303
304 ncomb = 1 << crp->field_width;
305 pos = index / ncomb;
306 value = index % ncomb;
307
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900308 if (gpio_read_reg(crp->reg, crp->reg_width,
309 crp->field_width, pos) == value)
Magnus Damm2967dab2008-10-08 20:41:43 +0900310 return 0;
311
312 return -1;
313}
314
315enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
316
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900317static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
318 int pinmux_type, int cfg_mode)
Magnus Damm2967dab2008-10-08 20:41:43 +0900319{
320 struct pinmux_cfg_reg *cr = NULL;
321 pinmux_enum_t enum_id;
322 struct pinmux_range *range;
323 int in_range, pos, index;
324 unsigned long *cntp;
325
326 switch (pinmux_type) {
327
328 case PINMUX_TYPE_FUNCTION:
329 range = NULL;
330 break;
331
332 case PINMUX_TYPE_OUTPUT:
333 range = &gpioc->output;
334 break;
335
336 case PINMUX_TYPE_INPUT:
337 range = &gpioc->input;
338 break;
339
340 case PINMUX_TYPE_INPUT_PULLUP:
341 range = &gpioc->input_pu;
342 break;
343
344 case PINMUX_TYPE_INPUT_PULLDOWN:
345 range = &gpioc->input_pd;
346 break;
347
348 default:
349 goto out_err;
350 }
351
352 pos = 0;
353 enum_id = 0;
354 index = 0;
355 while (1) {
356 pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
357 if (pos <= 0)
358 goto out_err;
359
360 if (!enum_id)
361 break;
362
363 in_range = enum_in_range(enum_id, &gpioc->function);
Magnus Damm42eed422008-10-22 18:29:17 +0900364 if (!in_range && range) {
Magnus Damm2967dab2008-10-08 20:41:43 +0900365 in_range = enum_in_range(enum_id, range);
366
Magnus Damm42eed422008-10-22 18:29:17 +0900367 if (in_range && enum_id == range->force)
368 continue;
369 }
370
Magnus Damm2967dab2008-10-08 20:41:43 +0900371 if (!in_range)
372 continue;
373
374 if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
375 goto out_err;
376
377 switch (cfg_mode) {
378 case GPIO_CFG_DRYRUN:
379 if (!*cntp || !check_config_reg(gpioc, cr, index))
380 continue;
381 break;
382
383 case GPIO_CFG_REQ:
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900384 write_config_reg(gpioc, cr, index);
Magnus Damm2967dab2008-10-08 20:41:43 +0900385 *cntp = *cntp + 1;
386 break;
387
388 case GPIO_CFG_FREE:
389 *cntp = *cntp - 1;
390 break;
391 }
392 }
393
394 return 0;
395 out_err:
396 return -1;
397}
398
399static DEFINE_SPINLOCK(gpio_lock);
400
401int __gpio_request(unsigned gpio)
402{
403 struct pinmux_info *gpioc = gpio_controller(gpio);
404 struct pinmux_data_reg *dummy;
405 unsigned long flags;
406 int i, ret, pinmux_type;
407
408 ret = -EINVAL;
409
410 if (!gpioc)
411 goto err_out;
412
413 spin_lock_irqsave(&gpio_lock, flags);
414
415 if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
416 goto err_unlock;
417
418 /* setup pin function here if no data is associated with pin */
419
420 if (get_data_reg(gpioc, gpio, &dummy, &i) != 0)
421 pinmux_type = PINMUX_TYPE_FUNCTION;
422 else
423 pinmux_type = PINMUX_TYPE_GPIO;
424
425 if (pinmux_type == PINMUX_TYPE_FUNCTION) {
426 if (pinmux_config_gpio(gpioc, gpio,
427 pinmux_type,
428 GPIO_CFG_DRYRUN) != 0)
429 goto err_unlock;
430
431 if (pinmux_config_gpio(gpioc, gpio,
432 pinmux_type,
433 GPIO_CFG_REQ) != 0)
434 BUG();
435 }
436
Magnus Damm18801be2008-12-25 18:17:09 +0900437 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
438 gpioc->gpios[gpio].flags |= pinmux_type;
Magnus Damm2967dab2008-10-08 20:41:43 +0900439
440 ret = 0;
441 err_unlock:
442 spin_unlock_irqrestore(&gpio_lock, flags);
443 err_out:
444 return ret;
445}
446EXPORT_SYMBOL(__gpio_request);
447
448void gpio_free(unsigned gpio)
449{
450 struct pinmux_info *gpioc = gpio_controller(gpio);
451 unsigned long flags;
452 int pinmux_type;
453
454 if (!gpioc)
455 return;
456
457 spin_lock_irqsave(&gpio_lock, flags);
458
459 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
460 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
Magnus Damm18801be2008-12-25 18:17:09 +0900461 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
462 gpioc->gpios[gpio].flags |= PINMUX_TYPE_NONE;
Magnus Damm2967dab2008-10-08 20:41:43 +0900463
464 spin_unlock_irqrestore(&gpio_lock, flags);
465}
466EXPORT_SYMBOL(gpio_free);
467
468static int pinmux_direction(struct pinmux_info *gpioc,
469 unsigned gpio, int new_pinmux_type)
470{
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900471 int pinmux_type;
472 int ret = -EINVAL;
Magnus Damm2967dab2008-10-08 20:41:43 +0900473
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900474 if (!gpioc)
475 goto err_out;
476
Magnus Damm2967dab2008-10-08 20:41:43 +0900477 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
478
479 switch (pinmux_type) {
480 case PINMUX_TYPE_GPIO:
481 break;
482 case PINMUX_TYPE_OUTPUT:
483 case PINMUX_TYPE_INPUT:
484 case PINMUX_TYPE_INPUT_PULLUP:
485 case PINMUX_TYPE_INPUT_PULLDOWN:
486 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
487 break;
488 default:
489 goto err_out;
490 }
491
492 if (pinmux_config_gpio(gpioc, gpio,
493 new_pinmux_type,
494 GPIO_CFG_DRYRUN) != 0)
495 goto err_out;
496
497 if (pinmux_config_gpio(gpioc, gpio,
498 new_pinmux_type,
499 GPIO_CFG_REQ) != 0)
500 BUG();
501
Magnus Damm18801be2008-12-25 18:17:09 +0900502 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
503 gpioc->gpios[gpio].flags |= new_pinmux_type;
Magnus Damm2967dab2008-10-08 20:41:43 +0900504
505 ret = 0;
506 err_out:
507 return ret;
508}
509
510int gpio_direction_input(unsigned gpio)
511{
512 struct pinmux_info *gpioc = gpio_controller(gpio);
513 unsigned long flags;
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900514 int ret;
Magnus Damm2967dab2008-10-08 20:41:43 +0900515
516 spin_lock_irqsave(&gpio_lock, flags);
517 ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT);
518 spin_unlock_irqrestore(&gpio_lock, flags);
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900519
Magnus Damm2967dab2008-10-08 20:41:43 +0900520 return ret;
521}
522EXPORT_SYMBOL(gpio_direction_input);
523
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900524static void __gpio_set_value(struct pinmux_info *gpioc,
525 unsigned gpio, int value)
Magnus Damm2967dab2008-10-08 20:41:43 +0900526{
527 struct pinmux_data_reg *dr = NULL;
528 int bit = 0;
529
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900530 if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
Magnus Damm2967dab2008-10-08 20:41:43 +0900531 BUG();
532 else
Magnus Damm32920942008-12-25 18:17:26 +0900533 gpio_write_bit(dr, bit, value);
Magnus Damm2967dab2008-10-08 20:41:43 +0900534}
535
536int gpio_direction_output(unsigned gpio, int value)
537{
538 struct pinmux_info *gpioc = gpio_controller(gpio);
539 unsigned long flags;
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900540 int ret;
Magnus Damm2967dab2008-10-08 20:41:43 +0900541
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900542 __gpio_set_value(gpioc, gpio, value);
Magnus Damm32920942008-12-25 18:17:26 +0900543 spin_lock_irqsave(&gpio_lock, flags);
Magnus Damm2967dab2008-10-08 20:41:43 +0900544 ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT);
545 spin_unlock_irqrestore(&gpio_lock, flags);
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900546
Magnus Damm2967dab2008-10-08 20:41:43 +0900547 return ret;
548}
549EXPORT_SYMBOL(gpio_direction_output);
550
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900551static int __gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
Magnus Damm2967dab2008-10-08 20:41:43 +0900552{
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900553 struct pinmux_data_reg *dr = NULL;
554 int bit = 0;
Magnus Damm2967dab2008-10-08 20:41:43 +0900555
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900556 if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) {
Magnus Damm2967dab2008-10-08 20:41:43 +0900557 BUG();
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900558 return 0;
Magnus Damm2967dab2008-10-08 20:41:43 +0900559 }
560
Magnus Damm0fc64cc2008-12-25 18:17:18 +0900561 return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
562}
563
564int gpio_get_value(unsigned gpio)
565{
566 return __gpio_get_value(gpio_controller(gpio), gpio);
Magnus Damm2967dab2008-10-08 20:41:43 +0900567}
568EXPORT_SYMBOL(gpio_get_value);
569
570void gpio_set_value(unsigned gpio, int value)
571{
Magnus Damm32920942008-12-25 18:17:26 +0900572 __gpio_set_value(gpio_controller(gpio), gpio, value);
Magnus Damm2967dab2008-10-08 20:41:43 +0900573}
574EXPORT_SYMBOL(gpio_set_value);
575
576int register_pinmux(struct pinmux_info *pip)
577{
578 registered_gpio = pip;
Magnus Damm32920942008-12-25 18:17:26 +0900579 setup_data_regs(pip);
Magnus Damm2967dab2008-10-08 20:41:43 +0900580 pr_info("pinmux: %s handling gpio %d -> %d\n",
581 pip->name, pip->first_gpio, pip->last_gpio);
582
Magnus Damm2967dab2008-10-08 20:41:43 +0900583 return 0;
584}