struct pinctrl_gpio_range gpio_range;
raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
+ /* Protect FSEL registers */
+ spinlock_t fsel_lock;
};
/* pins are just named GPIO0..GPIO53 */
struct bcm2835_pinctrl *pc, unsigned pin,
enum bcm2835_fsel fsel)
{
- u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
- enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
+ u32 val;
+ enum bcm2835_fsel cur;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pc->fsel_lock, flags);
+ val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
+ cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin,
- bcm2835_functions[cur]);
+ bcm2835_functions[cur]);
if (cur == fsel)
- return;
+ goto unlock;
if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) {
/* always transition through GPIO_IN */
dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin,
bcm2835_functions[fsel]);
bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
+
+unlock:
+ spin_unlock_irqrestore(&pc->fsel_lock, flags);
}
static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
pc->gpio_chip = *pdata->gpio_chip;
pc->gpio_chip.parent = dev;
+ spin_lock_init(&pc->fsel_lock);
for (i = 0; i < BCM2835_NUM_BANKS; i++) {
unsigned long events;
unsigned offset;