openwrt/target/linux/brcm47xx/patches-3.3/501-bcma-add-gpio-driver.patch
Hauke Mehrtens 42952fd94f bcma: initialize sprom earlier
The chip common and the PCIe code are accessing the sprom struct which
is not filled when these cores are initialized. Fix this by adding an
early initialize and fill the sprom struct before accessing it in other
code.

SVN-Revision: 33600
2012-09-30 11:44:44 +00:00

141 lines
4.3 KiB
Diff

--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -70,6 +70,8 @@ void bcma_core_chipcommon_init(struct bc
(leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
}
+ spin_lock_init(&cc->gpio_lock);
+
cc->setup_done = true;
}
@@ -92,34 +94,81 @@ u32 bcma_chipco_irq_status(struct bcma_d
u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
{
- return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
+ unsigned long flags;
+ u32 res;
+
+ spin_lock_irqsave(&cc->gpio_lock, flags);
+ res = bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
+ spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+ return res;
}
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_in);
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;
}
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out);
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;
}
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen);
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;
}
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_intmask);
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;
}
+EXPORT_SYMBOL_GPL(bcma_chipco_gpio_polarity);
#ifdef CONFIG_BCMA_DRIVER_MIPS
void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -495,6 +495,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 */
@@ -525,13 +528,22 @@ void bcma_chipco_irq_mask(struct bcma_dr
u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask);
+#define BCMA_CC_GPIO_LINES 16
+
/* Chipcommon GPIO pin access. */
-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);
-u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
-u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
-u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
-u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
+extern u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask);
+extern u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value);
+extern u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
+extern u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask,
+ u32 value);
+extern u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask,
+ u32 value);
+extern u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask,
+ u32 value);
+static inline int bcma_chipco_gpio_count(void)
+{
+ return BCMA_CC_GPIO_LINES;
+}
/* PMU support */
extern void bcma_pmu_init(struct bcma_drv_cc *cc);