blob: fe92ba151b893fd2feae74003a38a2a610160366 [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
49static int read_write_reg(unsigned long reg, unsigned long reg_width,
50 unsigned long field_width, unsigned long in_pos,
51 unsigned long value, int do_write)
52{
53 unsigned long data, mask, pos;
54
55 data = 0;
56 mask = (1 << field_width) - 1;
57 pos = reg_width - ((in_pos + 1) * field_width);
58
59#ifdef DEBUG
60 pr_info("%s, addr = %lx, value = %ld, pos = %ld, "
61 "r_width = %ld, f_width = %ld\n",
62 do_write ? "write" : "read", reg, value, pos,
63 reg_width, field_width);
64#endif
65
66 switch (reg_width) {
67 case 8:
68 data = ctrl_inb(reg);
69 break;
70 case 16:
71 data = ctrl_inw(reg);
72 break;
73 case 32:
74 data = ctrl_inl(reg);
75 break;
76 }
77
78 if (!do_write)
79 return (data >> pos) & mask;
80
81 data &= ~(mask << pos);
82 data |= value << pos;
83
84 switch (reg_width) {
85 case 8:
86 ctrl_outb(data, reg);
87 break;
88 case 16:
89 ctrl_outw(data, reg);
90 break;
91 case 32:
92 ctrl_outl(data, reg);
93 break;
94 }
95 return 0;
96}
97
Magnus Damm18801be2008-12-25 18:17:09 +090098static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
Magnus Damm2967dab2008-10-08 20:41:43 +090099{
Magnus Damm18801be2008-12-25 18:17:09 +0900100 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
Magnus Damm2967dab2008-10-08 20:41:43 +0900101 struct pinmux_data_reg *data_reg;
102 int k, n;
103
Magnus Damm18801be2008-12-25 18:17:09 +0900104 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
Magnus Damm2967dab2008-10-08 20:41:43 +0900105 return -1;
106
107 k = 0;
108 while (1) {
109 data_reg = gpioc->data_regs + k;
110
111 if (!data_reg->reg_width)
112 break;
113
114 for (n = 0; n < data_reg->reg_width; n++) {
Magnus Damm18801be2008-12-25 18:17:09 +0900115 if (data_reg->enum_ids[n] == gpiop->enum_id) {
116 gpiop->flags &= ~PINMUX_FLAG_DREG;
117 gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
118 gpiop->flags &= ~PINMUX_FLAG_DBIT;
119 gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
Magnus Damm2967dab2008-10-08 20:41:43 +0900120 return 0;
Magnus Damm2967dab2008-10-08 20:41:43 +0900121 }
122 }
123 k++;
124 }
125
Magnus Damm18801be2008-12-25 18:17:09 +0900126 BUG();
127
Magnus Damm2967dab2008-10-08 20:41:43 +0900128 return -1;
129}
130
Magnus Damm18801be2008-12-25 18:17:09 +0900131static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
132 struct pinmux_data_reg **drp, int *bitp)
133{
134 struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
135 int k, n;
136
137 if (!enum_in_range(gpiop->enum_id, &gpioc->data))
138 return -1;
139
140 k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
141 n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
142 *drp = gpioc->data_regs + k;
143 *bitp = n;
144 return 0;
145}
146
Magnus Damm2967dab2008-10-08 20:41:43 +0900147static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
148 struct pinmux_cfg_reg **crp, int *indexp,
149 unsigned long **cntp)
150{
151 struct pinmux_cfg_reg *config_reg;
152 unsigned long r_width, f_width;
153 int k, n;
154
155 k = 0;
156 while (1) {
157 config_reg = gpioc->cfg_regs + k;
158
159 r_width = config_reg->reg_width;
160 f_width = config_reg->field_width;
161
162 if (!r_width)
163 break;
164 for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) {
165 if (config_reg->enum_ids[n] == enum_id) {
166 *crp = config_reg;
167 *indexp = n;
168 *cntp = &config_reg->cnt[n / (1 << f_width)];
169 return 0;
170 }
171 }
172 k++;
173 }
174
175 return -1;
176}
177
178static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
179 int pos, pinmux_enum_t *enum_idp)
180{
181 pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
182 pinmux_enum_t *data = gpioc->gpio_data;
183 int k;
184
185 if (!enum_in_range(enum_id, &gpioc->data)) {
186 if (!enum_in_range(enum_id, &gpioc->mark)) {
187 pr_err("non data/mark enum_id for gpio %d\n", gpio);
188 return -1;
189 }
190 }
191
192 if (pos) {
193 *enum_idp = data[pos + 1];
194 return pos + 1;
195 }
196
197 for (k = 0; k < gpioc->gpio_data_size; k++) {
198 if (data[k] == enum_id) {
199 *enum_idp = data[k + 1];
200 return k + 1;
201 }
202 }
203
204 pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
205 return -1;
206}
207
208static int write_config_reg(struct pinmux_info *gpioc,
209 struct pinmux_cfg_reg *crp,
210 int index)
211{
212 unsigned long ncomb, pos, value;
213
214 ncomb = 1 << crp->field_width;
215 pos = index / ncomb;
216 value = index % ncomb;
217
218 return read_write_reg(crp->reg, crp->reg_width,
219 crp->field_width, pos, value, 1);
220}
221
222static int check_config_reg(struct pinmux_info *gpioc,
223 struct pinmux_cfg_reg *crp,
224 int index)
225{
226 unsigned long ncomb, pos, value;
227
228 ncomb = 1 << crp->field_width;
229 pos = index / ncomb;
230 value = index % ncomb;
231
232 if (read_write_reg(crp->reg, crp->reg_width,
233 crp->field_width, pos, 0, 0) == value)
234 return 0;
235
236 return -1;
237}
238
239enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
240
241int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
242 int pinmux_type, int cfg_mode)
243{
244 struct pinmux_cfg_reg *cr = NULL;
245 pinmux_enum_t enum_id;
246 struct pinmux_range *range;
247 int in_range, pos, index;
248 unsigned long *cntp;
249
250 switch (pinmux_type) {
251
252 case PINMUX_TYPE_FUNCTION:
253 range = NULL;
254 break;
255
256 case PINMUX_TYPE_OUTPUT:
257 range = &gpioc->output;
258 break;
259
260 case PINMUX_TYPE_INPUT:
261 range = &gpioc->input;
262 break;
263
264 case PINMUX_TYPE_INPUT_PULLUP:
265 range = &gpioc->input_pu;
266 break;
267
268 case PINMUX_TYPE_INPUT_PULLDOWN:
269 range = &gpioc->input_pd;
270 break;
271
272 default:
273 goto out_err;
274 }
275
276 pos = 0;
277 enum_id = 0;
278 index = 0;
279 while (1) {
280 pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
281 if (pos <= 0)
282 goto out_err;
283
284 if (!enum_id)
285 break;
286
287 in_range = enum_in_range(enum_id, &gpioc->function);
Magnus Damm42eed422008-10-22 18:29:17 +0900288 if (!in_range && range) {
Magnus Damm2967dab2008-10-08 20:41:43 +0900289 in_range = enum_in_range(enum_id, range);
290
Magnus Damm42eed422008-10-22 18:29:17 +0900291 if (in_range && enum_id == range->force)
292 continue;
293 }
294
Magnus Damm2967dab2008-10-08 20:41:43 +0900295 if (!in_range)
296 continue;
297
298 if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
299 goto out_err;
300
301 switch (cfg_mode) {
302 case GPIO_CFG_DRYRUN:
303 if (!*cntp || !check_config_reg(gpioc, cr, index))
304 continue;
305 break;
306
307 case GPIO_CFG_REQ:
308 if (write_config_reg(gpioc, cr, index) != 0)
309 goto out_err;
310 *cntp = *cntp + 1;
311 break;
312
313 case GPIO_CFG_FREE:
314 *cntp = *cntp - 1;
315 break;
316 }
317 }
318
319 return 0;
320 out_err:
321 return -1;
322}
323
324static DEFINE_SPINLOCK(gpio_lock);
325
326int __gpio_request(unsigned gpio)
327{
328 struct pinmux_info *gpioc = gpio_controller(gpio);
329 struct pinmux_data_reg *dummy;
330 unsigned long flags;
331 int i, ret, pinmux_type;
332
333 ret = -EINVAL;
334
335 if (!gpioc)
336 goto err_out;
337
338 spin_lock_irqsave(&gpio_lock, flags);
339
340 if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
341 goto err_unlock;
342
343 /* setup pin function here if no data is associated with pin */
344
345 if (get_data_reg(gpioc, gpio, &dummy, &i) != 0)
346 pinmux_type = PINMUX_TYPE_FUNCTION;
347 else
348 pinmux_type = PINMUX_TYPE_GPIO;
349
350 if (pinmux_type == PINMUX_TYPE_FUNCTION) {
351 if (pinmux_config_gpio(gpioc, gpio,
352 pinmux_type,
353 GPIO_CFG_DRYRUN) != 0)
354 goto err_unlock;
355
356 if (pinmux_config_gpio(gpioc, gpio,
357 pinmux_type,
358 GPIO_CFG_REQ) != 0)
359 BUG();
360 }
361
Magnus Damm18801be2008-12-25 18:17:09 +0900362 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
363 gpioc->gpios[gpio].flags |= pinmux_type;
Magnus Damm2967dab2008-10-08 20:41:43 +0900364
365 ret = 0;
366 err_unlock:
367 spin_unlock_irqrestore(&gpio_lock, flags);
368 err_out:
369 return ret;
370}
371EXPORT_SYMBOL(__gpio_request);
372
373void gpio_free(unsigned gpio)
374{
375 struct pinmux_info *gpioc = gpio_controller(gpio);
376 unsigned long flags;
377 int pinmux_type;
378
379 if (!gpioc)
380 return;
381
382 spin_lock_irqsave(&gpio_lock, flags);
383
384 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
385 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
Magnus Damm18801be2008-12-25 18:17:09 +0900386 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
387 gpioc->gpios[gpio].flags |= PINMUX_TYPE_NONE;
Magnus Damm2967dab2008-10-08 20:41:43 +0900388
389 spin_unlock_irqrestore(&gpio_lock, flags);
390}
391EXPORT_SYMBOL(gpio_free);
392
393static int pinmux_direction(struct pinmux_info *gpioc,
394 unsigned gpio, int new_pinmux_type)
395{
396 int ret, pinmux_type;
397
398 ret = -EINVAL;
399 pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
400
401 switch (pinmux_type) {
402 case PINMUX_TYPE_GPIO:
403 break;
404 case PINMUX_TYPE_OUTPUT:
405 case PINMUX_TYPE_INPUT:
406 case PINMUX_TYPE_INPUT_PULLUP:
407 case PINMUX_TYPE_INPUT_PULLDOWN:
408 pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
409 break;
410 default:
411 goto err_out;
412 }
413
414 if (pinmux_config_gpio(gpioc, gpio,
415 new_pinmux_type,
416 GPIO_CFG_DRYRUN) != 0)
417 goto err_out;
418
419 if (pinmux_config_gpio(gpioc, gpio,
420 new_pinmux_type,
421 GPIO_CFG_REQ) != 0)
422 BUG();
423
Magnus Damm18801be2008-12-25 18:17:09 +0900424 gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
425 gpioc->gpios[gpio].flags |= new_pinmux_type;
Magnus Damm2967dab2008-10-08 20:41:43 +0900426
427 ret = 0;
428 err_out:
429 return ret;
430}
431
432int gpio_direction_input(unsigned gpio)
433{
434 struct pinmux_info *gpioc = gpio_controller(gpio);
435 unsigned long flags;
436 int ret = -EINVAL;
437
438 if (!gpioc)
439 goto err_out;
440
441 spin_lock_irqsave(&gpio_lock, flags);
442 ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT);
443 spin_unlock_irqrestore(&gpio_lock, flags);
444 err_out:
445 return ret;
446}
447EXPORT_SYMBOL(gpio_direction_input);
448
449static int __gpio_get_set_value(struct pinmux_info *gpioc,
450 unsigned gpio, int value,
451 int do_write)
452{
453 struct pinmux_data_reg *dr = NULL;
454 int bit = 0;
455
456 if (get_data_reg(gpioc, gpio, &dr, &bit) != 0)
457 BUG();
458 else
459 value = read_write_reg(dr->reg, dr->reg_width,
Magnus Dammed0b2ef2008-10-21 21:31:07 +0900460 1, bit, !!value, do_write);
Magnus Damm2967dab2008-10-08 20:41:43 +0900461
462 return value;
463}
464
465int gpio_direction_output(unsigned gpio, int value)
466{
467 struct pinmux_info *gpioc = gpio_controller(gpio);
468 unsigned long flags;
469 int ret = -EINVAL;
470
471 if (!gpioc)
472 goto err_out;
473
474 spin_lock_irqsave(&gpio_lock, flags);
475 __gpio_get_set_value(gpioc, gpio, value, 1);
476 ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT);
477 spin_unlock_irqrestore(&gpio_lock, flags);
478 err_out:
479 return ret;
480}
481EXPORT_SYMBOL(gpio_direction_output);
482
483int gpio_get_value(unsigned gpio)
484{
485 struct pinmux_info *gpioc = gpio_controller(gpio);
486 unsigned long flags;
487 int value = 0;
488
489 if (!gpioc)
490 BUG();
491 else {
492 spin_lock_irqsave(&gpio_lock, flags);
493 value = __gpio_get_set_value(gpioc, gpio, 0, 0);
494 spin_unlock_irqrestore(&gpio_lock, flags);
495 }
496
497 return value;
498}
499EXPORT_SYMBOL(gpio_get_value);
500
501void gpio_set_value(unsigned gpio, int value)
502{
503 struct pinmux_info *gpioc = gpio_controller(gpio);
504 unsigned long flags;
505
506 if (!gpioc)
507 BUG();
508 else {
509 spin_lock_irqsave(&gpio_lock, flags);
510 __gpio_get_set_value(gpioc, gpio, value, 1);
511 spin_unlock_irqrestore(&gpio_lock, flags);
512 }
513}
514EXPORT_SYMBOL(gpio_set_value);
515
516int register_pinmux(struct pinmux_info *pip)
517{
Magnus Damm18801be2008-12-25 18:17:09 +0900518 int k;
519
Magnus Damm2967dab2008-10-08 20:41:43 +0900520 registered_gpio = pip;
521 pr_info("pinmux: %s handling gpio %d -> %d\n",
522 pip->name, pip->first_gpio, pip->last_gpio);
523
Magnus Damm18801be2008-12-25 18:17:09 +0900524 for (k = pip->first_gpio; k <= pip->last_gpio; k++)
525 setup_data_reg(pip, k);
526
Magnus Damm2967dab2008-10-08 20:41:43 +0900527 return 0;
528}