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