Commit caf18f19 authored by Julien May's avatar Julien May Committed by Haavard Skinnemoen

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: default avatarAlex Raimondi <mailinglist@miromico.ch>
Signed-off-by: default avatarHaavard Skinnemoen <haavard.skinnemoen@atmel.com>
parent 0d629501
......@@ -194,7 +194,7 @@ static int __init atngw100_init(void)
* PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus),
* but it's not available off-board.
*/
at32_select_periph(GPIO_PIN_PB(28), 0, AT32_GPIOF_PULLUP);
at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP);
at32_select_gpio(i2c_gpio_data.sda_pin,
AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
at32_select_gpio(i2c_gpio_data.scl_pin,
......
......@@ -232,7 +232,7 @@ static void __init atstk1002_setup_extdac(void)
goto err_set_clk;
}
at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0);
at73c213_data.dac_clk = gclk;
err_set_clk:
......
......@@ -94,7 +94,7 @@ static void __init atstk1003_setup_extdac(void)
goto err_set_clk;
}
at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0);
at73c213_data.dac_clk = gclk;
err_set_clk:
......
......@@ -99,7 +99,7 @@ static void __init atstk1004_setup_extdac(void)
goto err_set_clk;
}
at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0);
at73c213_data.dac_clk = gclk;
err_set_clk:
......
This diff is collapsed.
......@@ -21,8 +21,8 @@
#define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */
#define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */
void at32_select_periph(unsigned int pin, unsigned int periph,
unsigned long flags);
void at32_select_periph(unsigned int port, unsigned int pin,
unsigned int periph, unsigned long flags);
void at32_select_gpio(unsigned int pin, unsigned long flags);
void at32_deselect_pin(unsigned int pin);
void at32_reserve_pin(unsigned int pin);
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment