GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / arm / plat-stmp3xxx / pinmux.c
blob6d6b1a468eda765eb8425461398a5008db5f7e2e
1 /*
2 * Freescale STMP378X/STMP378X Pin Multiplexing
4 * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
6 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8 */
11 * The code contained herein is licensed under the GNU General Public
12 * License. You may obtain a copy of the GNU General Public License
13 * Version 2 or later at the following locations:
15 * http://www.opensource.org/licenses/gpl-license.html
16 * http://www.gnu.org/copyleft/gpl.html
18 #define DEBUG
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/sysdev.h>
23 #include <linux/string.h>
24 #include <linux/bitops.h>
25 #include <linux/irq.h>
27 #include <mach/hardware.h>
28 #include <mach/platform.h>
29 #include <mach/regs-pinctrl.h>
30 #include <mach/pins.h>
31 #include <mach/pinmux.h>
33 #define NR_BANKS ARRAY_SIZE(pinmux_banks)
34 static struct stmp3xxx_pinmux_bank pinmux_banks[] = {
35 [0] = {
36 .hw_muxsel = {
37 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL0,
38 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL1,
40 .hw_drive = {
41 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE0,
42 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE1,
43 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE2,
44 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE3,
46 .hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL0,
47 .functions = { 0x0, 0x1, 0x2, 0x3 },
48 .strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
50 .hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN0,
51 .hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT0,
52 .hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE0,
53 .irq = IRQ_GPIO0,
55 .pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ0,
56 .irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT0,
57 .irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL0,
58 .irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL0,
59 .irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN0,
61 [1] = {
62 .hw_muxsel = {
63 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL2,
64 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL3,
66 .hw_drive = {
67 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE4,
68 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE5,
69 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE6,
70 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE7,
72 .hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL1,
73 .functions = { 0x0, 0x1, 0x2, 0x3 },
74 .strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
76 .hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN1,
77 .hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT1,
78 .hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE1,
79 .irq = IRQ_GPIO1,
81 .pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ1,
82 .irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT1,
83 .irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL1,
84 .irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL1,
85 .irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN1,
87 [2] = {
88 .hw_muxsel = {
89 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL4,
90 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL5,
92 .hw_drive = {
93 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE8,
94 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE9,
95 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE10,
96 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE11,
98 .hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL2,
99 .functions = { 0x0, 0x1, 0x2, 0x3 },
100 .strengths = { 0x0, 0x1, 0x2, 0x1, 0x2 },
102 .hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN2,
103 .hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT2,
104 .hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE2,
105 .irq = IRQ_GPIO2,
107 .pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ2,
108 .irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT2,
109 .irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL2,
110 .irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL2,
111 .irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN2,
113 [3] = {
114 .hw_muxsel = {
115 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL6,
116 REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL7,
118 .hw_drive = {
119 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE12,
120 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE13,
121 REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE14,
122 NULL,
124 .hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL3,
125 .functions = {0x0, 0x1, 0x2, 0x3},
126 .strengths = {0x0, 0x1, 0x2, 0x3, 0xff},
130 static inline struct stmp3xxx_pinmux_bank *
131 stmp3xxx_pinmux_bank(unsigned id, unsigned *bank, unsigned *pin)
133 unsigned b, p;
135 b = STMP3XXX_PINID_TO_BANK(id);
136 p = STMP3XXX_PINID_TO_PINNUM(id);
137 BUG_ON(b >= NR_BANKS);
138 if (bank)
139 *bank = b;
140 if (pin)
141 *pin = p;
142 return &pinmux_banks[b];
145 /* Check if requested pin is owned by caller */
146 static int stmp3xxx_check_pin(unsigned id, const char *label)
148 unsigned pin;
149 struct stmp3xxx_pinmux_bank *pm = stmp3xxx_pinmux_bank(id, NULL, &pin);
151 if (!test_bit(pin, &pm->pin_map)) {
152 printk(KERN_WARNING
153 "%s: Accessing free pin %x, caller %s\n",
154 __func__, id, label);
156 return -EINVAL;
159 if (label && pm->pin_labels[pin] &&
160 strcmp(label, pm->pin_labels[pin])) {
161 printk(KERN_WARNING
162 "%s: Wrong pin owner %x, caller %s owner %s\n",
163 __func__, id, label, pm->pin_labels[pin]);
165 return -EINVAL;
167 return 0;
170 void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength,
171 const char *label)
173 struct stmp3xxx_pinmux_bank *pbank;
174 void __iomem *hwdrive;
175 u32 shift, val;
176 u32 bank, pin;
178 pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
179 pr_debug("%s: label %s bank %d pin %d strength %d\n", __func__, label,
180 bank, pin, strength);
182 hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
183 shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
184 val = pbank->strengths[strength];
185 if (val == 0xff) {
186 printk(KERN_WARNING
187 "%s: strength is not supported for bank %d, caller %s",
188 __func__, bank, label);
189 return;
192 if (stmp3xxx_check_pin(id, label))
193 return;
195 pr_debug("%s: writing 0x%x to 0x%p register\n", __func__,
196 val << shift, hwdrive);
197 stmp3xxx_clearl(HW_DRIVE_PINDRV_MASK << shift, hwdrive);
198 stmp3xxx_setl(val << shift, hwdrive);
201 void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage,
202 const char *label)
204 struct stmp3xxx_pinmux_bank *pbank;
205 void __iomem *hwdrive;
206 u32 shift;
207 u32 bank, pin;
209 pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
210 pr_debug("%s: label %s bank %d pin %d voltage %d\n", __func__, label,
211 bank, pin, voltage);
213 hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
214 shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
216 if (stmp3xxx_check_pin(id, label))
217 return;
219 pr_debug("%s: changing 0x%x bit in 0x%p register\n",
220 __func__, HW_DRIVE_PINV_MASK << shift, hwdrive);
221 if (voltage == PIN_1_8V)
222 stmp3xxx_clearl(HW_DRIVE_PINV_MASK << shift, hwdrive);
223 else
224 stmp3xxx_setl(HW_DRIVE_PINV_MASK << shift, hwdrive);
227 void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label)
229 struct stmp3xxx_pinmux_bank *pbank;
230 void __iomem *hwpull;
231 u32 bank, pin;
233 pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
234 pr_debug("%s: label %s bank %d pin %d enable %d\n", __func__, label,
235 bank, pin, enable);
237 hwpull = pbank->hw_pull;
239 if (stmp3xxx_check_pin(id, label))
240 return;
242 pr_debug("%s: changing 0x%x bit in 0x%p register\n",
243 __func__, 1 << pin, hwpull);
244 if (enable)
245 stmp3xxx_setl(1 << pin, hwpull);
246 else
247 stmp3xxx_clearl(1 << pin, hwpull);
250 int stmp3xxx_request_pin(unsigned id, enum pin_fun fun, const char *label)
252 struct stmp3xxx_pinmux_bank *pbank;
253 u32 bank, pin;
254 int ret = 0;
256 pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
257 pr_debug("%s: label %s bank %d pin %d fun %d\n", __func__, label,
258 bank, pin, fun);
260 if (test_bit(pin, &pbank->pin_map)) {
261 printk(KERN_WARNING
262 "%s: CONFLICT DETECTED pin %d:%d caller %s owner %s\n",
263 __func__, bank, pin, label, pbank->pin_labels[pin]);
264 return -EBUSY;
267 set_bit(pin, &pbank->pin_map);
268 pbank->pin_labels[pin] = label;
270 stmp3xxx_set_pin_type(id, fun);
272 return ret;
275 void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun)
277 struct stmp3xxx_pinmux_bank *pbank;
278 void __iomem *hwmux;
279 u32 shift, val;
280 u32 bank, pin;
282 pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
284 hwmux = pbank->hw_muxsel[pin / HW_MUXSEL_PIN_NUM];
285 shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
287 val = pbank->functions[fun];
288 shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
289 pr_debug("%s: writing 0x%x to 0x%p register\n",
290 __func__, val << shift, hwmux);
291 stmp3xxx_clearl(HW_MUXSEL_PINFUN_MASK << shift, hwmux);
292 stmp3xxx_setl(val << shift, hwmux);
295 void stmp3xxx_release_pin(unsigned id, const char *label)
297 struct stmp3xxx_pinmux_bank *pbank;
298 u32 bank, pin;
300 pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
301 pr_debug("%s: label %s bank %d pin %d\n", __func__, label, bank, pin);
303 if (stmp3xxx_check_pin(id, label))
304 return;
306 clear_bit(pin, &pbank->pin_map);
307 pbank->pin_labels[pin] = NULL;
310 int stmp3xxx_request_pin_group(struct pin_group *pin_group, const char *label)
312 struct pin_desc *pin;
313 int p;
314 int err = 0;
316 /* Allocate and configure pins */
317 for (p = 0; p < pin_group->nr_pins; p++) {
318 pr_debug("%s: #%d\n", __func__, p);
319 pin = &pin_group->pins[p];
321 err = stmp3xxx_request_pin(pin->id, pin->fun, label);
322 if (err)
323 goto out_err;
325 stmp3xxx_pin_strength(pin->id, pin->strength, label);
326 stmp3xxx_pin_voltage(pin->id, pin->voltage, label);
327 stmp3xxx_pin_pullup(pin->id, pin->pullup, label);
330 return 0;
332 out_err:
333 /* Release allocated pins in case of error */
334 while (--p >= 0) {
335 pr_debug("%s: releasing #%d\n", __func__, p);
336 stmp3xxx_release_pin(pin_group->pins[p].id, label);
338 return err;
340 EXPORT_SYMBOL(stmp3xxx_request_pin_group);
342 void stmp3xxx_release_pin_group(struct pin_group *pin_group, const char *label)
344 struct pin_desc *pin;
345 int p;
347 for (p = 0; p < pin_group->nr_pins; p++) {
348 pin = &pin_group->pins[p];
349 stmp3xxx_release_pin(pin->id, label);
352 EXPORT_SYMBOL(stmp3xxx_release_pin_group);
354 static int stmp3xxx_irq_to_gpio(int irq,
355 struct stmp3xxx_pinmux_bank **bank, unsigned *gpio)
357 struct stmp3xxx_pinmux_bank *pm;
359 for (pm = pinmux_banks; pm < pinmux_banks + NR_BANKS; pm++)
360 if (pm->virq <= irq && irq < pm->virq + 32) {
361 *bank = pm;
362 *gpio = irq - pm->virq;
363 return 0;
365 return -ENOENT;
368 static int stmp3xxx_set_irqtype(unsigned irq, unsigned type)
370 struct stmp3xxx_pinmux_bank *pm;
371 unsigned gpio;
372 int l, p;
374 stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
375 switch (type) {
376 case IRQ_TYPE_EDGE_RISING:
377 l = 0; p = 1; break;
378 case IRQ_TYPE_EDGE_FALLING:
379 l = 0; p = 0; break;
380 case IRQ_TYPE_LEVEL_HIGH:
381 l = 1; p = 1; break;
382 case IRQ_TYPE_LEVEL_LOW:
383 l = 1; p = 0; break;
384 default:
385 pr_debug("%s: Incorrect GPIO interrupt type 0x%x\n",
386 __func__, type);
387 return -ENXIO;
390 if (l)
391 stmp3xxx_setl(1 << gpio, pm->irqlevel);
392 else
393 stmp3xxx_clearl(1 << gpio, pm->irqlevel);
394 if (p)
395 stmp3xxx_setl(1 << gpio, pm->irqpolarity);
396 else
397 stmp3xxx_clearl(1 << gpio, pm->irqpolarity);
398 return 0;
401 static void stmp3xxx_pin_ack_irq(unsigned irq)
403 u32 stat;
404 struct stmp3xxx_pinmux_bank *pm;
405 unsigned gpio;
407 stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
408 stat = __raw_readl(pm->irqstat) & (1 << gpio);
409 stmp3xxx_clearl(stat, pm->irqstat);
412 static void stmp3xxx_pin_mask_irq(unsigned irq)
414 struct stmp3xxx_pinmux_bank *pm;
415 unsigned gpio;
417 stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
418 stmp3xxx_clearl(1 << gpio, pm->irqen);
419 stmp3xxx_clearl(1 << gpio, pm->pin2irq);
422 static void stmp3xxx_pin_unmask_irq(unsigned irq)
424 struct stmp3xxx_pinmux_bank *pm;
425 unsigned gpio;
427 stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
428 stmp3xxx_setl(1 << gpio, pm->irqen);
429 stmp3xxx_setl(1 << gpio, pm->pin2irq);
432 static inline
433 struct stmp3xxx_pinmux_bank *to_pinmux_bank(struct gpio_chip *chip)
435 return container_of(chip, struct stmp3xxx_pinmux_bank, chip);
438 static int stmp3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
440 struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
441 return pm->virq + offset;
444 static int stmp3xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
446 struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
447 unsigned v;
449 v = __raw_readl(pm->hw_gpio_in) & (1 << offset);
450 return v ? 1 : 0;
453 static void stmp3xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int v)
455 struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
457 if (v)
458 stmp3xxx_setl(1 << offset, pm->hw_gpio_out);
459 else
460 stmp3xxx_clearl(1 << offset, pm->hw_gpio_out);
463 static int stmp3xxx_gpio_output(struct gpio_chip *chip, unsigned offset, int v)
465 struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
467 stmp3xxx_setl(1 << offset, pm->hw_gpio_doe);
468 stmp3xxx_gpio_set(chip, offset, v);
469 return 0;
472 static int stmp3xxx_gpio_input(struct gpio_chip *chip, unsigned offset)
474 struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
476 stmp3xxx_clearl(1 << offset, pm->hw_gpio_doe);
477 return 0;
480 static int stmp3xxx_gpio_request(struct gpio_chip *chip, unsigned offset)
482 return stmp3xxx_request_pin(chip->base + offset, PIN_GPIO, "gpio");
485 static void stmp3xxx_gpio_free(struct gpio_chip *chip, unsigned offset)
487 stmp3xxx_release_pin(chip->base + offset, "gpio");
490 static void stmp3xxx_gpio_irq(u32 irq, struct irq_desc *desc)
492 struct stmp3xxx_pinmux_bank *pm = get_irq_data(irq);
493 int gpio_irq = pm->virq;
494 u32 stat = __raw_readl(pm->irqstat);
496 while (stat) {
497 if (stat & 1)
498 irq_desc[gpio_irq].handle_irq(gpio_irq,
499 &irq_desc[gpio_irq]);
500 gpio_irq++;
501 stat >>= 1;
505 static struct irq_chip gpio_irq_chip = {
506 .ack = stmp3xxx_pin_ack_irq,
507 .mask = stmp3xxx_pin_mask_irq,
508 .unmask = stmp3xxx_pin_unmask_irq,
509 .set_type = stmp3xxx_set_irqtype,
512 int __init stmp3xxx_pinmux_init(int virtual_irq_start)
514 int b, r = 0;
515 struct stmp3xxx_pinmux_bank *pm;
516 int virq;
518 for (b = 0; b < 3; b++) {
519 /* only banks 0,1,2 are allowed to GPIO */
520 pm = pinmux_banks + b;
521 pm->chip.base = 32 * b;
522 pm->chip.ngpio = 32;
523 pm->chip.owner = THIS_MODULE;
524 pm->chip.can_sleep = 1;
525 pm->chip.exported = 1;
526 pm->chip.to_irq = stmp3xxx_gpio_to_irq;
527 pm->chip.direction_input = stmp3xxx_gpio_input;
528 pm->chip.direction_output = stmp3xxx_gpio_output;
529 pm->chip.get = stmp3xxx_gpio_get;
530 pm->chip.set = stmp3xxx_gpio_set;
531 pm->chip.request = stmp3xxx_gpio_request;
532 pm->chip.free = stmp3xxx_gpio_free;
533 pm->virq = virtual_irq_start + b * 32;
535 for (virq = pm->virq; virq < pm->virq; virq++) {
536 gpio_irq_chip.mask(virq);
537 set_irq_chip(virq, &gpio_irq_chip);
538 set_irq_handler(virq, handle_level_irq);
539 set_irq_flags(virq, IRQF_VALID);
541 r = gpiochip_add(&pm->chip);
542 if (r < 0)
543 break;
544 set_irq_chained_handler(pm->irq, stmp3xxx_gpio_irq);
545 set_irq_data(pm->irq, pm);
547 return r;
550 MODULE_AUTHOR("Vladislav Buzov");
551 MODULE_LICENSE("GPL");