aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/pio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/mach-at32ap/pio.c')
-rw-r--r--arch/avr32/mach-at32ap/pio.c63
1 files changed, 47 insertions, 16 deletions
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 405ee6bad4ce..ed81a8bcb22d 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio)
50} 50}
51 51
52/* Pin multiplexing API */ 52/* Pin multiplexing API */
53static DEFINE_SPINLOCK(pio_lock);
53 54
54void __init at32_select_periph(unsigned int pin, unsigned int periph, 55void __init at32_select_periph(unsigned int port, u32 pin_mask,
55 unsigned long flags) 56 unsigned int periph, unsigned long flags)
56{ 57{
57 struct pio_device *pio; 58 struct pio_device *pio;
58 unsigned int pin_index = pin & 0x1f;
59 u32 mask = 1 << pin_index;
60 59
61 pio = gpio_to_pio(pin); 60 /* assign and verify pio */
61 pio = gpio_to_pio(port);
62 if (unlikely(!pio)) { 62 if (unlikely(!pio)) {
63 printk("pio: invalid pin %u\n", pin); 63 printk(KERN_WARNING "pio: invalid port %u\n", port);
64 goto fail; 64 goto fail;
65 } 65 }
66 66
67 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask) 67 /* Test if any of the requested pins is already muxed */
68 || gpiochip_is_requested(&pio->chip, pin_index))) { 68 spin_lock(&pio_lock);
69 printk("%s: pin %u is busy\n", pio->name, pin_index); 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);
70 goto fail; 73 goto fail;
71 } 74 }
72 75
73 pio_writel(pio, PUER, mask); 76 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 */
74 if (periph) 82 if (periph)
75 pio_writel(pio, BSR, mask); 83 pio_writel(pio, BSR, pin_mask);
76 else 84 else
77 pio_writel(pio, ASR, mask); 85 pio_writel(pio, ASR, pin_mask);
86
87 /* enable peripheral control */
88 pio_writel(pio, PDR, pin_mask);
78 89
79 pio_writel(pio, PDR, mask); 90 /* Disable pull ups if not requested. */
80 if (!(flags & AT32_GPIOF_PULLUP)) 91 if (!(flags & AT32_GPIOF_PULLUP))
81 pio_writel(pio, PUDR, mask); 92 pio_writel(pio, PUDR, pin_mask);
93
94 spin_unlock(&pio_lock);
82 95
83 return; 96 return;
84 97
@@ -134,6 +147,25 @@ fail:
134 dump_stack(); 147 dump_stack();
135} 148}
136 149
150/*
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
137/* Reserve a pin, preventing anyone else from changing its configuration. */ 169/* Reserve a pin, preventing anyone else from changing its configuration. */
138void __init at32_reserve_pin(unsigned int pin) 170void __init at32_reserve_pin(unsigned int pin)
139{ 171{
@@ -382,7 +414,6 @@ static int __init pio_probe(struct platform_device *pdev)
382} 414}
383 415
384static struct platform_driver pio_driver = { 416static struct platform_driver pio_driver = {
385 .probe = pio_probe,
386 .driver = { 417 .driver = {
387 .name = "pio", 418 .name = "pio",
388 }, 419 },
@@ -390,7 +421,7 @@ static struct platform_driver pio_driver = {
390 421
391static int __init pio_init(void) 422static int __init pio_init(void)
392{ 423{
393 return platform_driver_register(&pio_driver); 424 return platform_driver_probe(&pio_driver, pio_probe);
394} 425}
395postcore_initcall(pio_init); 426postcore_initcall(pio_init);
396 427