diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/pio.c')
-rw-r--r-- | arch/avr32/mach-at32ap/pio.c | 63 |
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 */ |
53 | static DEFINE_SPINLOCK(pio_lock); | ||
53 | 54 | ||
54 | void __init at32_select_periph(unsigned int pin, unsigned int periph, | 55 | void __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 | */ | ||
154 | void 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. */ |
138 | void __init at32_reserve_pin(unsigned int pin) | 170 | void __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 | ||
384 | static struct platform_driver pio_driver = { | 416 | static 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 | ||
391 | static int __init pio_init(void) | 422 | static 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 | } |
395 | postcore_initcall(pio_init); | 426 | postcore_initcall(pio_init); |
396 | 427 | ||