blob: 09a274c9d0b72a5b336478280d4c5d9df5ec2df5 [file] [log] [blame]
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001/*
2 * Atmel PIO2 Port Multiplexer support
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/debugfs.h>
13#include <linux/fs.h>
14#include <linux/platform_device.h>
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +010015#include <linux/irq.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070016
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +010017#include <asm/gpio.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070018#include <asm/io.h>
19
Haavard Skinnemoen3663b732008-08-05 13:57:38 +020020#include <mach/portmux.h>
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070021
22#include "pio.h"
23
24#define MAX_NR_PIO_DEVICES 8
25
26struct pio_device {
David Brownellb98348b2008-02-04 22:28:28 -080027 struct gpio_chip chip;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070028 void __iomem *regs;
29 const struct platform_device *pdev;
30 struct clk *clk;
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010031 u32 pinmux_mask;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +010032 char name[8];
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070033};
34
35static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
36
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010037static struct pio_device *gpio_to_pio(unsigned int gpio)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070038{
39 struct pio_device *pio;
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010040 unsigned int index;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070041
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010042 index = gpio >> 5;
43 if (index >= MAX_NR_PIO_DEVICES)
44 return NULL;
45 pio = &pio_dev[index];
46 if (!pio->regs)
47 return NULL;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070048
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010049 return pio;
50}
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070051
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010052/* Pin multiplexing API */
Julien Maycaf18f12008-09-24 10:30:47 +020053static DEFINE_SPINLOCK(pio_lock);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010054
Julien Maycaf18f12008-09-24 10:30:47 +020055void __init at32_select_periph(unsigned int port, u32 pin_mask,
56 unsigned int periph, unsigned long flags)
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010057{
58 struct pio_device *pio;
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010059
Julien Maycaf18f12008-09-24 10:30:47 +020060 /* assign and verify pio */
61 pio = gpio_to_pio(port);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010062 if (unlikely(!pio)) {
Julien Maycaf18f12008-09-24 10:30:47 +020063 printk(KERN_WARNING "pio: invalid port %u\n", port);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010064 goto fail;
65 }
66
Julien Maycaf18f12008-09-24 10:30:47 +020067 /* Test if any of the requested pins is already muxed */
68 spin_lock(&pio_lock);
69 if (unlikely(pio->pinmux_mask & pin_mask)) {
70 printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n",
71 pio->name, pin_mask, pio->pinmux_mask & pin_mask);
72 spin_unlock(&pio_lock);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010073 goto fail;
74 }
75
Julien Maycaf18f12008-09-24 10:30:47 +020076 pio->pinmux_mask |= pin_mask;
77
78 /* enable pull ups */
79 pio_writel(pio, PUER, pin_mask);
80
81 /* select either peripheral A or B */
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010082 if (periph)
Julien Maycaf18f12008-09-24 10:30:47 +020083 pio_writel(pio, BSR, pin_mask);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070084 else
Julien Maycaf18f12008-09-24 10:30:47 +020085 pio_writel(pio, ASR, pin_mask);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010086
Julien Maycaf18f12008-09-24 10:30:47 +020087 /* enable peripheral control */
88 pio_writel(pio, PDR, pin_mask);
89
90 /* Disable pull ups if not requested. */
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010091 if (!(flags & AT32_GPIOF_PULLUP))
Julien Maycaf18f12008-09-24 10:30:47 +020092 pio_writel(pio, PUDR, pin_mask);
93
94 spin_unlock(&pio_lock);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +010095
96 return;
97
98fail:
99 dump_stack();
100}
101
102void __init at32_select_gpio(unsigned int pin, unsigned long flags)
103{
104 struct pio_device *pio;
105 unsigned int pin_index = pin & 0x1f;
106 u32 mask = 1 << pin_index;
107
108 pio = gpio_to_pio(pin);
109 if (unlikely(!pio)) {
110 printk("pio: invalid pin %u\n", pin);
111 goto fail;
112 }
113
114 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
115 printk("%s: pin %u is busy\n", pio->name, pin_index);
116 goto fail;
117 }
118
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100119 if (flags & AT32_GPIOF_OUTPUT) {
120 if (flags & AT32_GPIOF_HIGH)
121 pio_writel(pio, SODR, mask);
122 else
123 pio_writel(pio, CODR, mask);
Matteo Vit7808fa42007-08-09 14:55:34 +0200124 if (flags & AT32_GPIOF_MULTIDRV)
125 pio_writel(pio, MDER, mask);
126 else
127 pio_writel(pio, MDDR, mask);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100128 pio_writel(pio, PUDR, mask);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +0100129 pio_writel(pio, OER, mask);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100130 } else {
131 if (flags & AT32_GPIOF_PULLUP)
132 pio_writel(pio, PUER, mask);
133 else
134 pio_writel(pio, PUDR, mask);
135 if (flags & AT32_GPIOF_DEGLITCH)
136 pio_writel(pio, IFER, mask);
137 else
138 pio_writel(pio, IFDR, mask);
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +0100139 pio_writel(pio, ODR, mask);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100140 }
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +0100141
142 pio_writel(pio, PER, mask);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100143
Haavard Skinnemoenc3e2a792006-12-04 13:46:52 +0100144 return;
145
146fail:
147 dump_stack();
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700148}
149
Haavard Skinnemoenece26782008-09-19 17:13:28 +0200150/*
151 * Undo a previous pin reservation. Will not affect the hardware
152 * configuration.
153 */
154void at32_deselect_pin(unsigned int pin)
155{
156 struct pio_device *pio;
157 unsigned int pin_index = pin & 0x1f;
158
159 pio = gpio_to_pio(pin);
160 if (unlikely(!pio)) {
161 printk("pio: invalid pin %u\n", pin);
162 dump_stack();
163 return;
164 }
165
166 clear_bit(pin_index, &pio->pinmux_mask);
167}
168
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100169/* Reserve a pin, preventing anyone else from changing its configuration. */
Alex Raimondiadde42b2008-11-04 23:37:10 +0100170void __init at32_reserve_pin(unsigned int port, u32 pin_mask)
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100171{
172 struct pio_device *pio;
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100173
Alex Raimondiadde42b2008-11-04 23:37:10 +0100174 /* assign and verify pio */
175 pio = gpio_to_pio(port);
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100176 if (unlikely(!pio)) {
Alex Raimondiadde42b2008-11-04 23:37:10 +0100177 printk(KERN_WARNING "pio: invalid port %u\n", port);
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100178 goto fail;
179 }
180
Alex Raimondiadde42b2008-11-04 23:37:10 +0100181 /* Test if any of the requested pins is already muxed */
182 spin_lock(&pio_lock);
183 if (unlikely(pio->pinmux_mask & pin_mask)) {
184 printk(KERN_WARNING "%s: pin(s) busy (req. 0x%x, busy 0x%x)\n",
185 pio->name, pin_mask, pio->pinmux_mask & pin_mask);
186 spin_unlock(&pio_lock);
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100187 goto fail;
188 }
189
Alex Raimondiadde42b2008-11-04 23:37:10 +0100190 /* Reserve pins */
191 pio->pinmux_mask |= pin_mask;
192 spin_unlock(&pio_lock);
Haavard Skinnemoene7f70b82007-01-30 11:01:23 +0100193 return;
194
195fail:
196 dump_stack();
197}
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100198
199/*--------------------------------------------------------------------------*/
200
201/* GPIO API */
202
David Brownellb98348b2008-02-04 22:28:28 -0800203static int direction_input(struct gpio_chip *chip, unsigned offset)
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100204{
David Brownellb98348b2008-02-04 22:28:28 -0800205 struct pio_device *pio = container_of(chip, struct pio_device, chip);
206 u32 mask = 1 << offset;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100207
David Brownellb98348b2008-02-04 22:28:28 -0800208 if (!(pio_readl(pio, PSR) & mask))
209 return -EINVAL;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100210
David Brownellb98348b2008-02-04 22:28:28 -0800211 pio_writel(pio, ODR, mask);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100212 return 0;
213}
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100214
David Brownellb98348b2008-02-04 22:28:28 -0800215static int gpio_get(struct gpio_chip *chip, unsigned offset)
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100216{
David Brownellb98348b2008-02-04 22:28:28 -0800217 struct pio_device *pio = container_of(chip, struct pio_device, chip);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100218
David Brownellb98348b2008-02-04 22:28:28 -0800219 return (pio_readl(pio, PDSR) >> offset) & 1;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100220}
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100221
David Brownellb98348b2008-02-04 22:28:28 -0800222static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
223
224static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100225{
David Brownellb98348b2008-02-04 22:28:28 -0800226 struct pio_device *pio = container_of(chip, struct pio_device, chip);
227 u32 mask = 1 << offset;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100228
David Brownellb98348b2008-02-04 22:28:28 -0800229 if (!(pio_readl(pio, PSR) & mask))
230 return -EINVAL;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100231
David Brownellb98348b2008-02-04 22:28:28 -0800232 gpio_set(chip, offset, value);
233 pio_writel(pio, OER, mask);
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100234 return 0;
235}
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100236
David Brownellb98348b2008-02-04 22:28:28 -0800237static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100238{
David Brownellb98348b2008-02-04 22:28:28 -0800239 struct pio_device *pio = container_of(chip, struct pio_device, chip);
240 u32 mask = 1 << offset;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100241
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100242 if (value)
243 pio_writel(pio, SODR, mask);
244 else
245 pio_writel(pio, CODR, mask);
246}
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100247
248/*--------------------------------------------------------------------------*/
249
250/* GPIO IRQ support */
251
252static void gpio_irq_mask(unsigned irq)
253{
254 unsigned gpio = irq_to_gpio(irq);
255 struct pio_device *pio = &pio_dev[gpio >> 5];
256
257 pio_writel(pio, IDR, 1 << (gpio & 0x1f));
258}
259
260static void gpio_irq_unmask(unsigned irq)
261{
262 unsigned gpio = irq_to_gpio(irq);
263 struct pio_device *pio = &pio_dev[gpio >> 5];
264
265 pio_writel(pio, IER, 1 << (gpio & 0x1f));
266}
267
268static int gpio_irq_type(unsigned irq, unsigned type)
269{
270 if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE)
271 return -EINVAL;
272
273 return 0;
274}
275
276static struct irq_chip gpio_irqchip = {
277 .name = "gpio",
278 .mask = gpio_irq_mask,
279 .unmask = gpio_irq_unmask,
280 .set_type = gpio_irq_type,
281};
282
283static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
284{
285 struct pio_device *pio = get_irq_chip_data(irq);
286 unsigned gpio_irq;
287
288 gpio_irq = (unsigned) get_irq_data(irq);
289 for (;;) {
290 u32 isr;
291 struct irq_desc *d;
292
293 /* ack pending GPIO interrupts */
294 isr = pio_readl(pio, ISR) & pio_readl(pio, IMR);
295 if (!isr)
296 break;
297 do {
298 int i;
299
300 i = ffs(isr) - 1;
301 isr &= ~(1 << i);
302
303 i += gpio_irq;
304 d = &irq_desc[i];
305
306 d->handle_irq(i, d);
307 } while (isr);
308 }
309}
310
311static void __init
312gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
313{
314 unsigned i;
315
316 set_irq_chip_data(irq, pio);
317 set_irq_data(irq, (void *) gpio_irq);
318
319 for (i = 0; i < 32; i++, gpio_irq++) {
320 set_irq_chip_data(gpio_irq, pio);
321 set_irq_chip_and_handler(gpio_irq, &gpio_irqchip,
322 handle_simple_irq);
323 }
324
325 set_irq_chained_handler(irq, gpio_irq_handler);
326}
327
328/*--------------------------------------------------------------------------*/
329
David Brownellb98348b2008-02-04 22:28:28 -0800330#ifdef CONFIG_DEBUG_FS
331
332#include <linux/seq_file.h>
333
334/*
335 * This shows more info than the generic gpio dump code:
336 * pullups, deglitching, open drain drive.
337 */
338static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
339{
340 struct pio_device *pio = container_of(chip, struct pio_device, chip);
341 u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
342 unsigned i;
343 u32 mask;
344 char bank;
345
346 psr = pio_readl(pio, PSR);
347 osr = pio_readl(pio, OSR);
348 imr = pio_readl(pio, IMR);
349 pdsr = pio_readl(pio, PDSR);
350 pusr = pio_readl(pio, PUSR);
351 ifsr = pio_readl(pio, IFSR);
352 mdsr = pio_readl(pio, MDSR);
353
354 bank = 'A' + pio->pdev->id;
355
356 for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
357 const char *label;
358
359 label = gpiochip_is_requested(chip, i);
David Brownellaafafdd2008-06-10 13:55:52 +0200360 if (!label && (imr & mask))
361 label = "[irq]";
David Brownellb98348b2008-02-04 22:28:28 -0800362 if (!label)
363 continue;
364
365 seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
366 chip->base + i, bank, i,
367 label,
368 (osr & mask) ? "out" : "in ",
369 (mask & pdsr) ? "hi" : "lo",
370 (mask & pusr) ? " " : "up");
371 if (ifsr & mask)
372 seq_printf(s, " deglitch");
373 if ((osr & mdsr) & mask)
374 seq_printf(s, " open-drain");
375 if (imr & mask)
376 seq_printf(s, " irq-%d edge-both",
377 gpio_to_irq(chip->base + i));
378 seq_printf(s, "\n");
379 }
380}
381
382#else
383#define pio_bank_show NULL
384#endif
385
386
387/*--------------------------------------------------------------------------*/
388
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700389static int __init pio_probe(struct platform_device *pdev)
390{
391 struct pio_device *pio = NULL;
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100392 int irq = platform_get_irq(pdev, 0);
393 int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32;
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700394
395 BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
396 pio = &pio_dev[pdev->id];
397 BUG_ON(!pio->regs);
398
David Brownellb98348b2008-02-04 22:28:28 -0800399 pio->chip.label = pio->name;
400 pio->chip.base = pdev->id * 32;
401 pio->chip.ngpio = 32;
David Brownelld8f388d2008-07-25 01:46:07 -0700402 pio->chip.dev = &pdev->dev;
403 pio->chip.owner = THIS_MODULE;
David Brownellb98348b2008-02-04 22:28:28 -0800404
405 pio->chip.direction_input = direction_input;
406 pio->chip.get = gpio_get;
407 pio->chip.direction_output = direction_output;
408 pio->chip.set = gpio_set;
409 pio->chip.dbg_show = pio_bank_show;
410
411 gpiochip_add(&pio->chip);
412
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100413 gpio_irq_setup(pio, irq, gpio_irq_base);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700414
415 platform_set_drvdata(pdev, pio);
416
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100417 printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n",
418 pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700419
420 return 0;
421}
422
423static struct platform_driver pio_driver = {
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700424 .driver = {
425 .name = "pio",
426 },
427};
428
429static int __init pio_init(void)
430{
Uwe Kleine-Königd6634db2008-09-21 23:52:07 +0200431 return platform_driver_probe(&pio_driver, pio_probe);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700432}
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100433postcore_initcall(pio_init);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700434
435void __init at32_init_pio(struct platform_device *pdev)
436{
437 struct resource *regs;
438 struct pio_device *pio;
439
440 if (pdev->id > MAX_NR_PIO_DEVICES) {
441 dev_err(&pdev->dev, "only %d PIO devices supported\n",
442 MAX_NR_PIO_DEVICES);
443 return;
444 }
445
446 pio = &pio_dev[pdev->id];
447 snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id);
448
449 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
450 if (!regs) {
451 dev_err(&pdev->dev, "no mmio resource defined\n");
452 return;
453 }
454
455 pio->clk = clk_get(&pdev->dev, "mck");
456 if (IS_ERR(pio->clk))
457 /*
458 * This is a fatal error, but if we continue we might
459 * be so lucky that we manage to initialize the
460 * console and display this message...
461 */
462 dev_err(&pdev->dev, "no mck clock defined\n");
463 else
464 clk_enable(pio->clk);
465
466 pio->pdev = pdev;
467 pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
468
Haavard Skinnemoen6a4e5222007-02-05 16:57:13 +0100469 /* start with irqs disabled and acked */
470 pio_writel(pio, IDR, ~0UL);
471 (void) pio_readl(pio, ISR);
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700472}