Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Broadcom specific AMBA
0003  * Broadcom MIPS32 74K core driver
0004  *
0005  * Copyright 2009, Broadcom Corporation
0006  * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
0007  * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
0008  * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
0009  *
0010  * Licensed under the GNU/GPL. See COPYING for details.
0011  */
0012 
0013 #include "bcma_private.h"
0014 
0015 #include <linux/bcma/bcma.h>
0016 
0017 #include <linux/serial.h>
0018 #include <linux/serial_core.h>
0019 #include <linux/serial_reg.h>
0020 #include <linux/time.h>
0021 #ifdef CONFIG_BCM47XX
0022 #include <linux/bcm47xx_nvram.h>
0023 #endif
0024 
0025 enum bcma_boot_dev {
0026     BCMA_BOOT_DEV_UNK = 0,
0027     BCMA_BOOT_DEV_ROM,
0028     BCMA_BOOT_DEV_PARALLEL,
0029     BCMA_BOOT_DEV_SERIAL,
0030     BCMA_BOOT_DEV_NAND,
0031 };
0032 
0033 /* The 47162a0 hangs when reading MIPS DMP registers registers */
0034 static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
0035 {
0036     return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
0037            dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
0038 }
0039 
0040 /* The 5357b0 hangs when reading USB20H DMP registers */
0041 static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
0042 {
0043     return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
0044         dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
0045            dev->bus->chipinfo.pkg == 11 &&
0046            dev->id.id == BCMA_CORE_USB20_HOST;
0047 }
0048 
0049 static inline u32 mips_read32(struct bcma_drv_mips *mcore,
0050                   u16 offset)
0051 {
0052     return bcma_read32(mcore->core, offset);
0053 }
0054 
0055 static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
0056 {
0057     u32 flag;
0058 
0059     if (bcma_core_mips_bcm47162a0_quirk(dev))
0060         return dev->core_index;
0061     if (bcma_core_mips_bcm5357b0_quirk(dev))
0062         return dev->core_index;
0063     flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
0064 
0065     if (flag)
0066         return flag & 0x1F;
0067     else
0068         return 0x3f;
0069 }
0070 
0071 /* Get the MIPS IRQ assignment for a specified device.
0072  * If unassigned, 0 is returned.
0073  * If disabled, 5 is returned.
0074  * If not supported, 6 is returned.
0075  */
0076 unsigned int bcma_core_mips_irq(struct bcma_device *dev)
0077 {
0078     struct bcma_device *mdev = dev->bus->drv_mips.core;
0079     u32 irqflag;
0080     unsigned int irq;
0081 
0082     irqflag = bcma_core_mips_irqflag(dev);
0083     if (irqflag == 0x3f)
0084         return 6;
0085 
0086     for (irq = 0; irq <= 4; irq++)
0087         if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
0088             (1 << irqflag))
0089             return irq;
0090 
0091     return 5;
0092 }
0093 
0094 static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
0095 {
0096     unsigned int oldirq = bcma_core_mips_irq(dev);
0097     struct bcma_bus *bus = dev->bus;
0098     struct bcma_device *mdev = bus->drv_mips.core;
0099     u32 irqflag;
0100 
0101     irqflag = bcma_core_mips_irqflag(dev);
0102     BUG_ON(oldirq == 6);
0103 
0104     dev->irq = irq + 2;
0105 
0106     /* clear the old irq */
0107     if (oldirq == 0)
0108         bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
0109                 bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
0110                 ~(1 << irqflag));
0111     else if (oldirq != 5)
0112         bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
0113 
0114     /* assign the new one */
0115     if (irq == 0) {
0116         bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
0117                 bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
0118                 (1 << irqflag));
0119     } else {
0120         u32 irqinitmask = bcma_read32(mdev,
0121                           BCMA_MIPS_MIPS74K_INTMASK(irq));
0122         if (irqinitmask) {
0123             struct bcma_device *core;
0124 
0125             /* backplane irq line is in use, find out who uses
0126              * it and set user to irq 0
0127              */
0128             list_for_each_entry(core, &bus->cores, list) {
0129                 if ((1 << bcma_core_mips_irqflag(core)) ==
0130                     irqinitmask) {
0131                     bcma_core_mips_set_irq(core, 0);
0132                     break;
0133                 }
0134             }
0135         }
0136         bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
0137                  1 << irqflag);
0138     }
0139 
0140     bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
0141            dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
0142 }
0143 
0144 static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
0145                     u16 coreid, u8 unit)
0146 {
0147     struct bcma_device *core;
0148 
0149     core = bcma_find_core_unit(bus, coreid, unit);
0150     if (!core) {
0151         bcma_warn(bus,
0152               "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
0153               coreid, unit);
0154         return;
0155     }
0156 
0157     bcma_core_mips_set_irq(core, irq);
0158 }
0159 
0160 static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
0161 {
0162     int i;
0163     static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
0164     char interrupts[25];
0165     char *ints = interrupts;
0166 
0167     for (i = 0; i < ARRAY_SIZE(irq_name); i++)
0168         ints += sprintf(ints, " %s%c",
0169                 irq_name[i], i == irq ? '*' : ' ');
0170 
0171     bcma_debug(dev->bus, "core 0x%04x, irq:%s\n", dev->id.id, interrupts);
0172 }
0173 
0174 static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
0175 {
0176     struct bcma_device *core;
0177 
0178     list_for_each_entry(core, &bus->cores, list) {
0179         bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
0180     }
0181 }
0182 
0183 u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
0184 {
0185     struct bcma_bus *bus = mcore->core->bus;
0186 
0187     if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
0188         return bcma_pmu_get_cpu_clock(&bus->drv_cc);
0189 
0190     bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
0191     return 0;
0192 }
0193 EXPORT_SYMBOL(bcma_cpu_clock);
0194 
0195 static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus)
0196 {
0197     struct bcma_drv_cc *cc = &bus->drv_cc;
0198     u8 cc_rev = cc->core->id.rev;
0199 
0200     if (cc_rev == 42) {
0201         struct bcma_device *core;
0202 
0203         core = bcma_find_core(bus, BCMA_CORE_NS_ROM);
0204         if (core) {
0205             switch (bcma_aread32(core, BCMA_IOST) &
0206                 BCMA_NS_ROM_IOST_BOOT_DEV_MASK) {
0207             case BCMA_NS_ROM_IOST_BOOT_DEV_NOR:
0208                 return BCMA_BOOT_DEV_SERIAL;
0209             case BCMA_NS_ROM_IOST_BOOT_DEV_NAND:
0210                 return BCMA_BOOT_DEV_NAND;
0211             case BCMA_NS_ROM_IOST_BOOT_DEV_ROM:
0212             default:
0213                 return BCMA_BOOT_DEV_ROM;
0214             }
0215         }
0216     } else {
0217         if (cc_rev == 38) {
0218             if (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)
0219                 return BCMA_BOOT_DEV_NAND;
0220             else if (cc->status & BIT(5))
0221                 return BCMA_BOOT_DEV_ROM;
0222         }
0223 
0224         if ((cc->capabilities & BCMA_CC_CAP_FLASHT) ==
0225             BCMA_CC_FLASHT_PARA)
0226             return BCMA_BOOT_DEV_PARALLEL;
0227         else
0228             return BCMA_BOOT_DEV_SERIAL;
0229     }
0230 
0231     return BCMA_BOOT_DEV_SERIAL;
0232 }
0233 
0234 static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore)
0235 {
0236     struct bcma_bus *bus = mcore->core->bus;
0237     enum bcma_boot_dev boot_dev;
0238 
0239     /* Determine flash type this SoC boots from */
0240     boot_dev = bcma_boot_dev(bus);
0241     switch (boot_dev) {
0242     case BCMA_BOOT_DEV_PARALLEL:
0243     case BCMA_BOOT_DEV_SERIAL:
0244 #ifdef CONFIG_BCM47XX
0245         bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH2,
0246                         BCMA_SOC_FLASH2_SZ);
0247 #endif
0248         break;
0249     case BCMA_BOOT_DEV_NAND:
0250 #ifdef CONFIG_BCM47XX
0251         bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH1,
0252                         BCMA_SOC_FLASH1_SZ);
0253 #endif
0254         break;
0255     default:
0256         break;
0257     }
0258 }
0259 
0260 void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
0261 {
0262     struct bcma_bus *bus = mcore->core->bus;
0263 
0264     if (mcore->early_setup_done)
0265         return;
0266 
0267     bcma_chipco_serial_init(&bus->drv_cc);
0268     bcma_core_mips_nvram_init(mcore);
0269 
0270     mcore->early_setup_done = true;
0271 }
0272 
0273 static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
0274 {
0275     struct bcma_device *cpu, *pcie, *i2s;
0276 
0277     /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
0278      * (IRQ flags > 7 are ignored when setting the interrupt masks)
0279      */
0280     if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
0281         bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
0282         return;
0283 
0284     cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
0285     pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
0286     i2s = bcma_find_core(bus, BCMA_CORE_I2S);
0287     if (cpu && pcie && i2s &&
0288         bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
0289         bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
0290         bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
0291         bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
0292         bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
0293         bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
0294         bcma_debug(bus,
0295                "Moved i2s interrupt to oob line 7 instead of 8\n");
0296     }
0297 }
0298 
0299 void bcma_core_mips_init(struct bcma_drv_mips *mcore)
0300 {
0301     struct bcma_bus *bus;
0302     struct bcma_device *core;
0303     bus = mcore->core->bus;
0304 
0305     if (mcore->setup_done)
0306         return;
0307 
0308     bcma_debug(bus, "Initializing MIPS core...\n");
0309 
0310     bcma_core_mips_early_init(mcore);
0311 
0312     bcma_fix_i2s_irqflag(bus);
0313 
0314     switch (bus->chipinfo.id) {
0315     case BCMA_CHIP_ID_BCM4716:
0316     case BCMA_CHIP_ID_BCM4748:
0317         bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
0318         bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
0319         bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
0320         bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
0321         bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
0322         bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
0323         break;
0324     case BCMA_CHIP_ID_BCM5356:
0325     case BCMA_CHIP_ID_BCM47162:
0326     case BCMA_CHIP_ID_BCM53572:
0327         bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
0328         bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
0329         bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
0330         break;
0331     case BCMA_CHIP_ID_BCM5357:
0332     case BCMA_CHIP_ID_BCM4749:
0333         bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
0334         bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
0335         bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
0336         bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
0337         bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
0338         break;
0339     case BCMA_CHIP_ID_BCM4706:
0340         bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
0341         bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
0342                         0);
0343         bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
0344         bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
0345         bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
0346                         0);
0347         break;
0348     default:
0349         list_for_each_entry(core, &bus->cores, list) {
0350             core->irq = bcma_core_irq(core, 0);
0351         }
0352         bcma_err(bus,
0353              "Unknown device (0x%x) found, can not configure IRQs\n",
0354              bus->chipinfo.id);
0355     }
0356     bcma_debug(bus, "IRQ reconfiguration done\n");
0357     bcma_core_mips_dump_irq(bus);
0358 
0359     mcore->setup_done = true;
0360 }