]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/bcma/driver_mips.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
[karo-tx-linux.git] / drivers / bcma / driver_mips.c
index 792daad28cbc6fa883a2e20911b33dbe840a49ba..9a7f0e3ab5a33fbb012a5c2f74145cc47c346dcd 100644 (file)
 
 #include <linux/bcma/bcma.h>
 
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/time.h>
 
+static const char *part_probes[] = { "bcm47xxpart", NULL };
+
+static struct physmap_flash_data bcma_pflash_data = {
+       .part_probe_types       = part_probes,
+};
+
+static struct resource bcma_pflash_resource = {
+       .name   = "bcma_pflash",
+       .flags  = IORESOURCE_MEM,
+};
+
+struct platform_device bcma_pflash_dev = {
+       .name           = "physmap-flash",
+       .dev            = {
+               .platform_data  = &bcma_pflash_data,
+       },
+       .resource       = &bcma_pflash_resource,
+       .num_resources  = 1,
+};
+
 /* The 47162a0 hangs when reading MIPS DMP registers registers */
 static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
 {
@@ -74,28 +96,41 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
                return dev->core_index;
        flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
 
-       return flag & 0x1F;
+       if (flag)
+               return flag & 0x1F;
+       else
+               return 0x3f;
 }
 
 /* Get the MIPS IRQ assignment for a specified device.
  * If unassigned, 0 is returned.
+ * If disabled, 5 is returned.
+ * If not supported, 6 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;
        unsigned int irq;
 
        irqflag = bcma_core_mips_irqflag(dev);
+       if (irqflag == 0x3f)
+               return 6;
 
-       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 5;
+}
+
+unsigned int bcma_core_irq(struct bcma_device *dev)
+{
+       unsigned int mips_irq = bcma_core_mips_irq(dev);
+       return mips_irq <= 4 ? mips_irq + 2 : 0;
 }
-EXPORT_SYMBOL(bcma_core_mips_irq);
+EXPORT_SYMBOL(bcma_core_irq);
 
 static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
 {
@@ -114,7 +149,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
                bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
                            bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
                            ~(1 << irqflag));
-       else
+       else if (oldirq != 5)
                bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
 
        /* assign the new one */
@@ -123,9 +158,9 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
                            bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
                            (1 << irqflag));
        } else {
-               u32 oldirqflag = bcma_read32(mdev,
-                                            BCMA_MIPS_MIPS74K_INTMASK(irq));
-               if (oldirqflag) {
+               u32 irqinitmask = bcma_read32(mdev,
+                                             BCMA_MIPS_MIPS74K_INTMASK(irq));
+               if (irqinitmask) {
                        struct bcma_device *core;
 
                        /* backplane irq line is in use, find out who uses
@@ -133,7 +168,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
                         */
                        list_for_each_entry(core, &bus->cores, list) {
                                if ((1 << bcma_core_mips_irqflag(core)) ==
-                                   oldirqflag) {
+                                   irqinitmask) {
                                        bcma_core_mips_set_irq(core, 0);
                                        break;
                                }
@@ -143,15 +178,31 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
                             1 << irqflag);
        }
 
-       bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
-                 dev->id.id, oldirq + 2, irq + 2);
+       bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
+                  dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
+}
+
+static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
+                                       u16 coreid, u8 unit)
+{
+       struct bcma_device *core;
+
+       core = bcma_find_core_unit(bus, coreid, unit);
+       if (!core) {
+               bcma_warn(bus,
+                         "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
+                         coreid, unit);
+               return;
+       }
+
+       bcma_core_mips_set_irq(core, irq);
 }
 
 static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
 {
        int i;
        static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
-       printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
+       printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
        for (i = 0; i <= 6; i++)
                printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
        printk("\n");
@@ -182,6 +233,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
 {
        struct bcma_bus *bus = mcore->core->bus;
        struct bcma_drv_cc *cc = &bus->drv_cc;
+       struct bcma_pflash *pflash = &cc->pflash;
 
        switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
        case BCMA_CC_FLASHT_STSER:
@@ -191,15 +243,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
                break;
        case BCMA_CC_FLASHT_PARA:
                bcma_debug(bus, "Found parallel flash\n");
-               cc->pflash.present = true;
-               cc->pflash.window = BCMA_SOC_FLASH2;
-               cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
+               pflash->present = true;
+               pflash->window = BCMA_SOC_FLASH2;
+               pflash->window_size = BCMA_SOC_FLASH2_SZ;
 
                if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
                     BCMA_CC_FLASH_CFG_DS) == 0)
-                       cc->pflash.buswidth = 1;
+                       pflash->buswidth = 1;
                else
-                       cc->pflash.buswidth = 2;
+                       pflash->buswidth = 2;
+
+               bcma_pflash_data.width = pflash->buswidth;
+               bcma_pflash_resource.start = pflash->window;
+               bcma_pflash_resource.end = pflash->window + pflash->window_size;
+
                break;
        default:
                bcma_err(bus, "Flash type not supported\n");
@@ -227,6 +284,32 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
        mcore->early_setup_done = true;
 }
 
+static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
+{
+       struct bcma_device *cpu, *pcie, *i2s;
+
+       /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
+        * (IRQ flags > 7 are ignored when setting the interrupt masks)
+        */
+       if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
+           bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
+               return;
+
+       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 (cpu && pcie && i2s &&
+           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);
+               bcma_debug(bus,
+                          "Moved i2s interrupt to oob line 7 instead of 8\n");
+       }
+}
+
 void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 {
        struct bcma_bus *bus;
@@ -236,43 +319,55 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
        if (mcore->setup_done)
                return;
 
-       bcma_info(bus, "Initializing MIPS core...\n");
+       bcma_debug(bus, "Initializing MIPS core...\n");
 
        bcma_core_mips_early_init(mcore);
 
-       mcore->assigned_irqs = 1;
-
-       /* Assign IRQs to all cores on the bus */
-       list_for_each_entry(core, &bus->cores, list) {
-               int mips_irq;
-               if (core->irq)
-                       continue;
-
-               mips_irq = bcma_core_mips_irq(core);
-               if (mips_irq > 4)
-                       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:
-               case BCMA_CORE_ETHERNET:
-               case BCMA_CORE_ETHERNET_GBIT:
-               case BCMA_CORE_MAC_GBIT:
-               case BCMA_CORE_80211:
-               case BCMA_CORE_USB20_HOST:
-                       /* 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++);
-                       break;
+       bcma_fix_i2s_irqflag(bus);
+
+       switch (bus->chipinfo.id) {
+       case BCMA_CHIP_ID_BCM4716:
+       case BCMA_CHIP_ID_BCM4748:
+               bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
+               bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
+               bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
+               bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
+               bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
+               bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
+               break;
+       case BCMA_CHIP_ID_BCM5356:
+       case BCMA_CHIP_ID_BCM47162:
+       case BCMA_CHIP_ID_BCM53572:
+               bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
+               bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
+               bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
+               break;
+       case BCMA_CHIP_ID_BCM5357:
+       case BCMA_CHIP_ID_BCM4749:
+               bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
+               bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
+               bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
+               bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
+               bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
+               break;
+       case BCMA_CHIP_ID_BCM4706:
+               bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
+               bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
+                                           0);
+               bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
+               bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
+               bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
+                                           0);
+               break;
+       default:
+               list_for_each_entry(core, &bus->cores, list) {
+                       core->irq = bcma_core_irq(core);
                }
+               bcma_err(bus,
+                        "Unknown device (0x%x) found, can not configure IRQs\n",
+                        bus->chipinfo.id);
        }
-       bcma_info(bus, "IRQ reconfiguration done\n");
+       bcma_debug(bus, "IRQ reconfiguration done\n");
        bcma_core_mips_dump_irq(bus);
 
        mcore->setup_done = true;