From ece2678c62ce13ef11a8b43526ccc5db8d711ed3 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 19 Sep 2008 17:13:28 +0200 Subject: avr32: Provide a way to deselect pins in the portmux Currently, setting up the portmux is completely one-shot: Once a pin is muxed, the portmux driver will complain loudly and refuse to do anything if you try to set up the same pin again. Sometimes, it may be necessary to change the configuration of a pin after it has been set up initially. This patch adds a way to undo the previous configuration, allowing the pin to be reconfigured. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'arch/avr32/mach-at32ap/pio.c') diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 405ee6bad4c..90ef538ae54 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -134,6 +134,25 @@ fail: dump_stack(); } +/* + * Undo a previous pin reservation. Will not affect the hardware + * configuration. + */ +void at32_deselect_pin(unsigned int pin) +{ + struct pio_device *pio; + unsigned int pin_index = pin & 0x1f; + + pio = gpio_to_pio(pin); + if (unlikely(!pio)) { + printk("pio: invalid pin %u\n", pin); + dump_stack(); + return; + } + + clear_bit(pin_index, &pio->pinmux_mask); +} + /* Reserve a pin, preventing anyone else from changing its configuration. */ void __init at32_reserve_pin(unsigned int pin) { -- cgit v1.2.3 From d6634db8fe1784d0a8e4e156970fec034708446e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 21 Sep 2008 23:52:07 +0200 Subject: avr32: Use platform_driver_probe for pio platform driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function of the pio platform driver lives in the init section and so a pio device that is created after the init section is discarded probably results in an oops. Even if this cannot happen, using platform_driver_probe is cleaner. (If this can happen and should be supported the probe function must live in the devinit section instead.) Signed-off-by: Uwe Kleine-König Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/avr32/mach-at32ap/pio.c') diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 90ef538ae54..ef2561e1539 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -401,7 +401,6 @@ static int __init pio_probe(struct platform_device *pdev) } static struct platform_driver pio_driver = { - .probe = pio_probe, .driver = { .name = "pio", }, @@ -409,7 +408,7 @@ static struct platform_driver pio_driver = { static int __init pio_init(void) { - return platform_driver_register(&pio_driver); + return platform_driver_probe(&pio_driver, pio_probe); } postcore_initcall(pio_init); -- cgit v1.2.3 From caf18f19eefc0cf5539b4e82b8aa8df6a78391a6 Mon Sep 17 00:00:00 2001 From: Julien May Date: Wed, 24 Sep 2008 10:30:47 +0200 Subject: avr32: Allow selecting multiple pins at once at32_select_periph() now takes an u32 bitmask rather than a single pin. This allows to set multiple pins at once. Signed-off-by: Alex Raimondi Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'arch/avr32/mach-at32ap/pio.c') diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index ef2561e1539..ed81a8bcb22 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) } /* Pin multiplexing API */ +static DEFINE_SPINLOCK(pio_lock); -void __init at32_select_periph(unsigned int pin, unsigned int periph, - unsigned long flags) +void __init at32_select_periph(unsigned int port, u32 pin_mask, + unsigned int periph, unsigned long flags) { struct pio_device *pio; - unsigned int pin_index = pin & 0x1f; - u32 mask = 1 << pin_index; - pio = gpio_to_pio(pin); + /* assign and verify pio */ + pio = gpio_to_pio(port); if (unlikely(!pio)) { - printk("pio: invalid pin %u\n", pin); + printk(KERN_WARNING "pio: invalid port %u\n", port); goto fail; } - if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask) - || gpiochip_is_requested(&pio->chip, pin_index))) { - printk("%s: pin %u is busy\n", pio->name, pin_index); + /* Test if any of the requested pins is already muxed */ + spin_lock(&pio_lock); + if (unlikely(pio->pinmux_mask & pin_mask)) { + printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n", + pio->name, pin_mask, pio->pinmux_mask & pin_mask); + spin_unlock(&pio_lock); goto fail; } - pio_writel(pio, PUER, mask); + pio->pinmux_mask |= pin_mask; + + /* enable pull ups */ + pio_writel(pio, PUER, pin_mask); + + /* select either peripheral A or B */ if (periph) - pio_writel(pio, BSR, mask); + pio_writel(pio, BSR, pin_mask); else - pio_writel(pio, ASR, mask); + pio_writel(pio, ASR, pin_mask); + + /* enable peripheral control */ + pio_writel(pio, PDR, pin_mask); - pio_writel(pio, PDR, mask); + /* Disable pull ups if not requested. */ if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); + pio_writel(pio, PUDR, pin_mask); + + spin_unlock(&pio_lock); return; -- cgit v1.2.3