root/drivers/bcma/driver_mips.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bcma_core_mips_bcm47162a0_quirk
  2. bcma_core_mips_bcm5357b0_quirk
  3. mips_read32
  4. mips_write32
  5. bcma_core_mips_irqflag
  6. bcma_core_mips_irq
  7. bcma_core_mips_set_irq
  8. bcma_core_mips_set_irq_name
  9. bcma_core_mips_print_irq
  10. bcma_core_mips_dump_irq
  11. bcma_cpu_clock
  12. bcma_core_mips_nvram_init
  13. bcma_core_mips_early_init
  14. bcma_fix_i2s_irqflag
  15. bcma_core_mips_init

   1 /*
   2  * Broadcom specific AMBA
   3  * Broadcom MIPS32 74K core driver
   4  *
   5  * Copyright 2009, Broadcom Corporation
   6  * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
   7  * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
   8  * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
   9  *
  10  * Licensed under the GNU/GPL. See COPYING for details.
  11  */
  12 
  13 #include "bcma_private.h"
  14 
  15 #include <linux/bcma/bcma.h>
  16 
  17 #include <linux/serial.h>
  18 #include <linux/serial_core.h>
  19 #include <linux/serial_reg.h>
  20 #include <linux/time.h>
  21 #ifdef CONFIG_BCM47XX
  22 #include <linux/bcm47xx_nvram.h>
  23 #endif
  24 
  25 enum bcma_boot_dev {
  26         BCMA_BOOT_DEV_UNK = 0,
  27         BCMA_BOOT_DEV_ROM,
  28         BCMA_BOOT_DEV_PARALLEL,
  29         BCMA_BOOT_DEV_SERIAL,
  30         BCMA_BOOT_DEV_NAND,
  31 };
  32 
  33 /* The 47162a0 hangs when reading MIPS DMP registers registers */
  34 static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
  35 {
  36         return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
  37                dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
  38 }
  39 
  40 /* The 5357b0 hangs when reading USB20H DMP registers */
  41 static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
  42 {
  43         return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
  44                 dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
  45                dev->bus->chipinfo.pkg == 11 &&
  46                dev->id.id == BCMA_CORE_USB20_HOST;
  47 }
  48 
  49 static inline u32 mips_read32(struct bcma_drv_mips *mcore,
  50                               u16 offset)
  51 {
  52         return bcma_read32(mcore->core, offset);
  53 }
  54 
  55 static inline void mips_write32(struct bcma_drv_mips *mcore,
  56                                 u16 offset,
  57                                 u32 value)
  58 {
  59         bcma_write32(mcore->core, offset, value);
  60 }
  61 
  62 static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
  63 {
  64         u32 flag;
  65 
  66         if (bcma_core_mips_bcm47162a0_quirk(dev))
  67                 return dev->core_index;
  68         if (bcma_core_mips_bcm5357b0_quirk(dev))
  69                 return dev->core_index;
  70         flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
  71 
  72         if (flag)
  73                 return flag & 0x1F;
  74         else
  75                 return 0x3f;
  76 }
  77 
  78 /* Get the MIPS IRQ assignment for a specified device.
  79  * If unassigned, 0 is returned.
  80  * If disabled, 5 is returned.
  81  * If not supported, 6 is returned.
  82  */
  83 unsigned int bcma_core_mips_irq(struct bcma_device *dev)
  84 {
  85         struct bcma_device *mdev = dev->bus->drv_mips.core;
  86         u32 irqflag;
  87         unsigned int irq;
  88 
  89         irqflag = bcma_core_mips_irqflag(dev);
  90         if (irqflag == 0x3f)
  91                 return 6;
  92 
  93         for (irq = 0; irq <= 4; irq++)
  94                 if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
  95                     (1 << irqflag))
  96                         return irq;
  97 
  98         return 5;
  99 }
 100 
 101 static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
 102 {
 103         unsigned int oldirq = bcma_core_mips_irq(dev);
 104         struct bcma_bus *bus = dev->bus;
 105         struct bcma_device *mdev = bus->drv_mips.core;
 106         u32 irqflag;
 107 
 108         irqflag = bcma_core_mips_irqflag(dev);
 109         BUG_ON(oldirq == 6);
 110 
 111         dev->irq = irq + 2;
 112 
 113         /* clear the old irq */
 114         if (oldirq == 0)
 115                 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
 116                             bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
 117                             ~(1 << irqflag));
 118         else if (oldirq != 5)
 119                 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
 120 
 121         /* assign the new one */
 122         if (irq == 0) {
 123                 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
 124                             bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
 125                             (1 << irqflag));
 126         } else {
 127                 u32 irqinitmask = bcma_read32(mdev,
 128                                               BCMA_MIPS_MIPS74K_INTMASK(irq));
 129                 if (irqinitmask) {
 130                         struct bcma_device *core;
 131 
 132                         /* backplane irq line is in use, find out who uses
 133                          * it and set user to irq 0
 134                          */
 135                         list_for_each_entry(core, &bus->cores, list) {
 136                                 if ((1 << bcma_core_mips_irqflag(core)) ==
 137                                     irqinitmask) {
 138                                         bcma_core_mips_set_irq(core, 0);
 139                                         break;
 140                                 }
 141                         }
 142                 }
 143                 bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
 144                              1 << irqflag);
 145         }
 146 
 147         bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
 148                    dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
 149 }
 150 
 151 static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
 152                                         u16 coreid, u8 unit)
 153 {
 154         struct bcma_device *core;
 155 
 156         core = bcma_find_core_unit(bus, coreid, unit);
 157         if (!core) {
 158                 bcma_warn(bus,
 159                           "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
 160                           coreid, unit);
 161                 return;
 162         }
 163 
 164         bcma_core_mips_set_irq(core, irq);
 165 }
 166 
 167 static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
 168 {
 169         int i;
 170         static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
 171         char interrupts[25];
 172         char *ints = interrupts;
 173 
 174         for (i = 0; i < ARRAY_SIZE(irq_name); i++)
 175                 ints += sprintf(ints, " %s%c",
 176                                 irq_name[i], i == irq ? '*' : ' ');
 177 
 178         bcma_debug(dev->bus, "core 0x%04x, irq:%s\n", dev->id.id, interrupts);
 179 }
 180 
 181 static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
 182 {
 183         struct bcma_device *core;
 184 
 185         list_for_each_entry(core, &bus->cores, list) {
 186                 bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
 187         }
 188 }
 189 
 190 u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
 191 {
 192         struct bcma_bus *bus = mcore->core->bus;
 193 
 194         if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
 195                 return bcma_pmu_get_cpu_clock(&bus->drv_cc);
 196 
 197         bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
 198         return 0;
 199 }
 200 EXPORT_SYMBOL(bcma_cpu_clock);
 201 
 202 static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus)
 203 {
 204         struct bcma_drv_cc *cc = &bus->drv_cc;
 205         u8 cc_rev = cc->core->id.rev;
 206 
 207         if (cc_rev == 42) {
 208                 struct bcma_device *core;
 209 
 210                 core = bcma_find_core(bus, BCMA_CORE_NS_ROM);
 211                 if (core) {
 212                         switch (bcma_aread32(core, BCMA_IOST) &
 213                                 BCMA_NS_ROM_IOST_BOOT_DEV_MASK) {
 214                         case BCMA_NS_ROM_IOST_BOOT_DEV_NOR:
 215                                 return BCMA_BOOT_DEV_SERIAL;
 216                         case BCMA_NS_ROM_IOST_BOOT_DEV_NAND:
 217                                 return BCMA_BOOT_DEV_NAND;
 218                         case BCMA_NS_ROM_IOST_BOOT_DEV_ROM:
 219                         default:
 220                                 return BCMA_BOOT_DEV_ROM;
 221                         }
 222                 }
 223         } else {
 224                 if (cc_rev == 38) {
 225                         if (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)
 226                                 return BCMA_BOOT_DEV_NAND;
 227                         else if (cc->status & BIT(5))
 228                                 return BCMA_BOOT_DEV_ROM;
 229                 }
 230 
 231                 if ((cc->capabilities & BCMA_CC_CAP_FLASHT) ==
 232                     BCMA_CC_FLASHT_PARA)
 233                         return BCMA_BOOT_DEV_PARALLEL;
 234                 else
 235                         return BCMA_BOOT_DEV_SERIAL;
 236         }
 237 
 238         return BCMA_BOOT_DEV_SERIAL;
 239 }
 240 
 241 static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore)
 242 {
 243         struct bcma_bus *bus = mcore->core->bus;
 244         enum bcma_boot_dev boot_dev;
 245 
 246         /* Determine flash type this SoC boots from */
 247         boot_dev = bcma_boot_dev(bus);
 248         switch (boot_dev) {
 249         case BCMA_BOOT_DEV_PARALLEL:
 250         case BCMA_BOOT_DEV_SERIAL:
 251 #ifdef CONFIG_BCM47XX
 252                 bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH2,
 253                                             BCMA_SOC_FLASH2_SZ);
 254 #endif
 255                 break;
 256         case BCMA_BOOT_DEV_NAND:
 257 #ifdef CONFIG_BCM47XX
 258                 bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH1,
 259                                             BCMA_SOC_FLASH1_SZ);
 260 #endif
 261                 break;
 262         default:
 263                 break;
 264         }
 265 }
 266 
 267 void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
 268 {
 269         struct bcma_bus *bus = mcore->core->bus;
 270 
 271         if (mcore->early_setup_done)
 272                 return;
 273 
 274         bcma_chipco_serial_init(&bus->drv_cc);
 275         bcma_core_mips_nvram_init(mcore);
 276 
 277         mcore->early_setup_done = true;
 278 }
 279 
 280 static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
 281 {
 282         struct bcma_device *cpu, *pcie, *i2s;
 283 
 284         /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
 285          * (IRQ flags > 7 are ignored when setting the interrupt masks)
 286          */
 287         if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
 288             bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
 289                 return;
 290 
 291         cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 292         pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
 293         i2s = bcma_find_core(bus, BCMA_CORE_I2S);
 294         if (cpu && pcie && i2s &&
 295             bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
 296             bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
 297             bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
 298                 bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
 299                 bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
 300                 bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
 301                 bcma_debug(bus,
 302                            "Moved i2s interrupt to oob line 7 instead of 8\n");
 303         }
 304 }
 305 
 306 void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 307 {
 308         struct bcma_bus *bus;
 309         struct bcma_device *core;
 310         bus = mcore->core->bus;
 311 
 312         if (mcore->setup_done)
 313                 return;
 314 
 315         bcma_debug(bus, "Initializing MIPS core...\n");
 316 
 317         bcma_core_mips_early_init(mcore);
 318 
 319         bcma_fix_i2s_irqflag(bus);
 320 
 321         switch (bus->chipinfo.id) {
 322         case BCMA_CHIP_ID_BCM4716:
 323         case BCMA_CHIP_ID_BCM4748:
 324                 bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
 325                 bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
 326                 bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
 327                 bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
 328                 bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
 329                 bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
 330                 break;
 331         case BCMA_CHIP_ID_BCM5356:
 332         case BCMA_CHIP_ID_BCM47162:
 333         case BCMA_CHIP_ID_BCM53572:
 334                 bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
 335                 bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
 336                 bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
 337                 break;
 338         case BCMA_CHIP_ID_BCM5357:
 339         case BCMA_CHIP_ID_BCM4749:
 340                 bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
 341                 bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
 342                 bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
 343                 bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
 344                 bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
 345                 break;
 346         case BCMA_CHIP_ID_BCM4706:
 347                 bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
 348                 bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
 349                                             0);
 350                 bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
 351                 bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
 352                 bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
 353                                             0);
 354                 break;
 355         default:
 356                 list_for_each_entry(core, &bus->cores, list) {
 357                         core->irq = bcma_core_irq(core, 0);
 358                 }
 359                 bcma_err(bus,
 360                          "Unknown device (0x%x) found, can not configure IRQs\n",
 361                          bus->chipinfo.id);
 362         }
 363         bcma_debug(bus, "IRQ reconfiguration done\n");
 364         bcma_core_mips_dump_irq(bus);
 365 
 366         mcore->setup_done = true;
 367 }

/* [<][>][^][v][top][bottom][index][help] */