Hi Hauke:
I think this addresses your concerns.
Changes since v2: Modified to not expose bcma_core_mips_irq; modified for
completeness.
The new function (bcma_core_irq) could probably be made a "static inline", and
simply retrieve the assigned
IRQ directly from the core (or just delete it and let the users reference the
core->irq value directly).
Also should consider whether to completely re-initialize the interrupt masks as
is done in the Broadcom SDK; e.g.,
Change to this:
if (!mcore->setup_done) {
for (mips_irq = 0; mips_irq <= 4; mips_irq++)
bcma_write32(mcore->core,
BCMA_MIPS_MIPS74K_INTMASK(mips_irq), 0);
mcore->assigned_irqs = 1;
}
And delete this (becomes unnecessary):
mips_irq = bcma_core_mips_irq(core);
if (mips_irq > 4)
core->irq = 0;
else
core->irq = mips_irq + 2;
Both approaches worked fine on my device.
Signed-off-by: Nathan Hintz <[email protected]>
--- /dev/null 2012-03-21 21:16:41.055325718 -0700
+++ target/linux/brcm47xx/patches-3.2/235-bcma-dont-expose-mips-irq.patch
2012-03-28 20:55:02.641147511 -0700
@@ -0,0 +1,76 @@
+--- a/include/linux/bcma/bcma.h
++++ b/include/linux/bcma/bcma.h
+@@ -295,6 +295,7 @@ extern struct bcma_device *bcma_find_cor
+ extern bool bcma_core_is_enabled(struct bcma_device *core);
+ extern void bcma_core_disable(struct bcma_device *core, u32 flags);
+ extern int bcma_core_enable(struct bcma_device *core, u32 flags);
++extern unsigned int bcma_core_irq(struct bcma_device *core);
+ extern void bcma_core_set_clockmode(struct bcma_device *core,
+ enum bcma_clkmode clkmode);
+ extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
+--- a/include/linux/bcma/bcma_driver_mips.h
++++ b/include/linux/bcma/bcma_driver_mips.h
+@@ -46,6 +46,4 @@ static inline void bcma_core_mips_init(s
+
+ extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
+
+-extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
+-
+ #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
+--- a/arch/mips/bcm47xx/gpio.c
++++ b/arch/mips/bcm47xx/gpio.c
+@@ -94,7 +94,7 @@ int gpio_to_irq(unsigned gpio)
+ #endif
+ #ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+- return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
++ return bcma_core_irq(bcm47xx_bus.bcma.bus.drv_cc.core);
+ #endif
+ }
+ return -EINVAL;
+--- a/arch/mips/bcm47xx/serial.c
++++ b/arch/mips/bcm47xx/serial.c
+@@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(voi
+
+ p->mapbase = (unsigned int) bcma_port->regs;
+ p->membase = (void *) bcma_port->regs;
+- p->irq = bcma_port->irq + 2;
++ p->irq = bcma_port->irq;
+ p->uartclk = bcma_port->baud_base;
+ p->regshift = bcma_port->reg_shift;
+ p->iotype = UPIO_MEM;
+--- a/drivers/bcma/driver_chipcommon.c
++++ b/drivers/bcma/driver_chipcommon.c
+@@ -147,7 +147,7 @@ void bcma_chipco_serial_init(struct bcma
+ return;
+ }
+
+- irq = bcma_core_mips_irq(cc->core);
++ irq = bcma_core_irq(cc->core);
+
+ /* Determine the registers of the UARTs */
+ cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
+--- a/drivers/bcma/driver_mips.c
++++ b/drivers/bcma/driver_mips.c
+@@ -81,7 +81,7 @@ static u32 bcma_core_mips_irqflag(struct
+ /* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ */
+-unsigned int bcma_core_mips_irq(struct bcma_device *dev)
++static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+ {
+ struct bcma_device *mdev = dev->bus->drv_mips.core;
+ u32 irqflag;
+@@ -96,7 +96,11 @@ unsigned int bcma_core_mips_irq(struct b
+
+ return 0;
+ }
+-EXPORT_SYMBOL(bcma_core_mips_irq);
++
++unsigned int bcma_core_irq(struct bcma_device *dev) {
++ return bcma_core_mips_irq(dev) + 2;
++}
++EXPORT_SYMBOL(bcma_core_irq);
+
+ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+ {
--- /dev/null 2012-03-21 21:16:41.055325718 -0700
+++ target/linux/brcm47xx/patches-3.2/237-bcma-fix-irq-assignment.patch
2012-03-29 21:05:49.189660716 -0700
@@ -0,0 +1,173 @@
+--- a/include/linux/bcma/bcma_driver_mips.h
++++ b/include/linux/bcma/bcma_driver_mips.h
+@@ -28,6 +28,7 @@
+ #define BCMA_MIPS_MIPS74K_GPIOEN 0x0048
+ #define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0
+
++#define BCMA_MIPS_OOBSELINA74 0x004
+ #define BCMA_MIPS_OOBSELOUTA30 0x100
+
+ struct bcma_device;
+--- a/drivers/bcma/driver_mips.c
++++ b/drivers/bcma/driver_mips.c
+@@ -65,6 +65,10 @@ static const u32 ipsflag_irq_shift[] = {
+ BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
+ };
+
++#define IRQ_FLAG_MASK 0x1F
++#define INVALID_IRQ_FLAG 0x3F
++#define IRQ_NOT_ASSIGNED 5
++#define IRQ_NOT_REQUIRED 6
+ static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
+ {
+ u32 flag;
+@@ -75,11 +79,11 @@ static u32 bcma_core_mips_irqflag(struct
+ return dev->core_index;
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
+
+- return flag & 0x1F;
++ return ((flag && ((flag & IRQ_FLAG_MASK) <= 7)) ? (flag &
IRQ_FLAG_MASK) : INVALID_IRQ_FLAG);
+ }
+
+ /* Get the MIPS IRQ assignment for a specified device.
+- * If unassigned, 0 is returned.
++ * If unassigned, 5 is returned; if no IRQ is required, 6 is returned
+ */
+ static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+ {
+@@ -88,21 +92,24 @@ static unsigned int bcma_core_mips_irq(s
+ unsigned int irq;
+
+ irqflag = bcma_core_mips_irqflag(dev);
++ if (irqflag == INVALID_IRQ_FLAG)
++ return IRQ_NOT_REQUIRED;
+
+- for (irq = 1; irq <= 4; irq++)
++ for (irq = 0; irq <= 4; irq++)
+ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
+ (1 << irqflag))
+ return irq;
+
+- return 0;
++ return IRQ_NOT_ASSIGNED;
+ }
+
+ unsigned int bcma_core_irq(struct bcma_device *dev) {
+- return bcma_core_mips_irq(dev) + 2;
++ unsigned int irq = bcma_core_mips_irq(dev);
++ return ((irq > 4) ? 0 : (irq + 2));
+ }
+ EXPORT_SYMBOL(bcma_core_irq);
+
+-static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
++static bool bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
+ {
+ unsigned int oldirq = bcma_core_mips_irq(dev);
+ struct bcma_bus *bus = dev->bus;
+@@ -110,7 +117,8 @@ static void bcma_core_mips_set_irq(struc
+ u32 irqflag;
+
+ irqflag = bcma_core_mips_irqflag(dev);
+- BUG_ON(oldirq == 6);
++ if (irqflag == INVALID_IRQ_FLAG)
++ return false;
+
+ dev->irq = irq + 2;
+
+@@ -119,8 +127,8 @@ static void bcma_core_mips_set_irq(struc
+ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
+ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
+ ~(1 << irqflag));
+- else
+- bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0);
++ else if (oldirq <= 4)
++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
+
+ /* assign the new one */
+ if (irq == 0) {
+@@ -149,7 +157,9 @@ static void bcma_core_mips_set_irq(struc
+ }
+
+ pr_info("set_irq: core 0x%04x, irq %d => %d\n",
+- dev->id.id, oldirq + 2, irq + 2);
++ dev->id.id, (oldirq > 4) ? 0 : (oldirq + 2), irq + 2);
++
++ return true;
+ }
+
+ static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int
irq)
+@@ -226,6 +236,27 @@ static void bcma_core_mips_flash_detect(
+ }
+ }
+
++static void bcma_fix_i2s_irqflag(struct bcma_bus *bus) {
++ struct bcma_device *cpu, *pcie, *i2s;
++
++ /* IRQ flags >= 8 are not honored in the IRQ masks (2010 Broadcom SDK)
*/
++ if (bus->chipinfo.id != 0x4716 &&
++ bus->chipinfo.id != 0x4748)
++ return;
++
++ if ((cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K)) &&
++ (pcie = bcma_find_core(bus, BCMA_CORE_PCIE)) &&
++ (i2s = bcma_find_core(bus, BCMA_CORE_I2S))) {
++ if (bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
++ bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
++ bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
++ bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
++ bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
++ bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
++ }
++ }
++}
++
+ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
+ {
+ struct bcma_bus *bus;
+@@ -234,12 +265,14 @@ void bcma_core_mips_init(struct bcma_drv
+
+ pr_info("Initializing MIPS core...\n");
+
++ bcma_fix_i2s_irqflag(bus);
++
+ if (!mcore->setup_done)
+ mcore->assigned_irqs = 1;
+
+ /* Assign IRQs to all cores on the bus */
+ list_for_each_entry_reverse(core, &bus->cores, list) {
+- int mips_irq;
++ unsigned int mips_irq;
+ if (core->irq)
+ continue;
+
+@@ -248,8 +281,7 @@ void bcma_core_mips_init(struct bcma_drv
+ core->irq = 0;
+ else
+ core->irq = mips_irq + 2;
+- if (core->irq > 5)
+- continue;
++
+ switch (core->id.id) {
+ case BCMA_CORE_PCI:
+ case BCMA_CORE_PCIE:
+@@ -261,9 +293,17 @@ void bcma_core_mips_init(struct bcma_drv
+ /* These devices get their own IRQ line if available,
+ * the rest goes on IRQ0
+ */
+- if (mcore->assigned_irqs <= 4)
+- bcma_core_mips_set_irq(core,
+- mcore->assigned_irqs++);
++ if (mcore->assigned_irqs <= 4) {
++ if (bcma_core_mips_set_irq(core,
++
mcore->assigned_irqs))
++ mcore->assigned_irqs++;
++ }
++ else
++ bcma_core_mips_set_irq(core, 0);
++ break;
++ case BCMA_CORE_CHIPCOMMON:
++ case BCMA_CORE_I2S:
++ bcma_core_mips_set_irq(core, 0);
+ break;
+ }
+ }
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel