Skip to content

Commit

Permalink
bcma: add locking around GPIO register accesses
Browse files Browse the repository at this point in the history
The GPIOs are access through some registers in the chip common core.
We need locking around these GPIO accesses, all GPIOs are accessed
through the same registers and parallel writes will cause problems.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Patchwork: http://patchwork.linux-mips.org/patch/4585
Acked-by: Florian Fainelli <florian@openwrt.org>
  • Loading branch information
Hauke Mehrtens authored and John Crispin committed Nov 21, 2012
1 parent 0ef0165 commit ef85fb2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 5 deletions.
47 changes: 42 additions & 5 deletions drivers/bcma/driver_chipcommon.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
if (cc->setup_done)
return;

spin_lock_init(&cc->gpio_lock);

if (cc->core->id.rev >= 11)
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
Expand Down Expand Up @@ -84,28 +86,63 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)

u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
unsigned long flags;
u32 res;

spin_lock_irqsave(&cc->gpio_lock, flags);
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
spin_unlock_irqrestore(&cc->gpio_lock, flags);

return res;
}

u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
unsigned long flags;
u32 res;

spin_lock_irqsave(&cc->gpio_lock, flags);
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
spin_unlock_irqrestore(&cc->gpio_lock, flags);

return res;
}

u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
unsigned long flags;
u32 res;

spin_lock_irqsave(&cc->gpio_lock, flags);
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
spin_unlock_irqrestore(&cc->gpio_lock, flags);

return res;
}
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);

u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
unsigned long flags;
u32 res;

spin_lock_irqsave(&cc->gpio_lock, flags);
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
spin_unlock_irqrestore(&cc->gpio_lock, flags);

return res;
}

u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
{
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
unsigned long flags;
u32 res;

spin_lock_irqsave(&cc->gpio_lock, flags);
res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
spin_unlock_irqrestore(&cc->gpio_lock, flags);

return res;
}

#ifdef CONFIG_BCMA_DRIVER_MIPS
Expand Down
3 changes: 3 additions & 0 deletions include/linux/bcma/bcma_driver_chipcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,9 @@ struct bcma_drv_cc {
int nr_serial_ports;
struct bcma_serial_port serial_ports[4];
#endif /* CONFIG_BCMA_DRIVER_MIPS */

/* Lock for GPIO register access. */
spinlock_t gpio_lock;
};

/* Register access */
Expand Down

0 comments on commit ef85fb2

Please sign in to comment.