161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* 261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Sonics Silicon Backplane 361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Broadcom MIPS core driver 461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Copyright 2005, Broadcom Corporation 6eb032b9837a958e21ca000358a5bde5e17192ddbMichael Buesch * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * 861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * Licensed under the GNU/GPL. See COPYING for details. 961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch */ 1061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/ssb/ssb.h> 1261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/serial.h> 1461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/serial_core.h> 1561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/serial_reg.h> 1661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include <linux/time.h> 1761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 1861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch#include "ssb_private.h" 1961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline u32 mips_read32(struct ssb_mipscore *mcore, 2261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u16 offset) 2361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 2461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return ssb_read32(mcore->dev, offset); 2561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 2661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline void mips_write32(struct ssb_mipscore *mcore, 2861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u16 offset, 2961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 value) 3061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 3161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_write32(mcore->dev, offset, value); 3261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 3361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 3461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic const u32 ipsflag_irq_mask[] = { 3561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0, 3661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ1, 3761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ2, 3861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ3, 3961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ4, 4061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch}; 4161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 4261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic const u32 ipsflag_irq_shift[] = { 4361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 0, 4461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ1_SHIFT, 4561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ2_SHIFT, 4661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ3_SHIFT, 4761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch SSB_IPSFLAG_IRQ4_SHIFT, 4861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch}; 4961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 5061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic inline u32 ssb_irqflag(struct ssb_device *dev) 5161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 52ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); 53ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (tpsflag) 54ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; 55ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET else 56ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET /* not irq supported */ 57ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET return 0x3f; 58ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET} 59ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET 60ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTETstatic struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) 61ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET{ 62ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET struct ssb_bus *bus = rdev->bus; 63ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET int i; 64ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET for (i = 0; i < bus->nr_devices; i++) { 65ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET struct ssb_device *dev; 66ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET dev = &(bus->devices[i]); 67ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (ssb_irqflag(dev) == irqflag) 68ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET return dev; 69ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET } 70ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET return NULL; 7161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 7261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 7361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch/* Get the MIPS IRQ assignment for a specified device. 7461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * If unassigned, 0 is returned. 75ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET * If disabled, 5 is returned. 76ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET * If not supported, 6 is returned. 7761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch */ 7861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschunsigned int ssb_mips_irq(struct ssb_device *dev) 7961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 8061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = dev->bus; 81ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET struct ssb_device *mdev = bus->mipscore.dev; 8261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 irqflag; 8361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 ipsflag; 8461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 tmp; 8561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch unsigned int irq; 8661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 8761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch irqflag = ssb_irqflag(dev); 88ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (irqflag == 0x3f) 89ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET return 6; 9061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); 9161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch for (irq = 1; irq <= 4; irq++) { 9261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); 9361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (tmp == irqflag) 9461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch break; 9561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 96ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (irq == 5) { 97ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) 98ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET irq = 0; 99ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET } 10061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 10161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return irq; 10261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 10361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 10461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void clear_irq(struct ssb_bus *bus, unsigned int irq) 10561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 10661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_device *dev = bus->mipscore.dev; 10761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 10861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Clear the IRQ in the MIPScore backplane registers */ 10961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (irq == 0) { 11061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_write32(dev, SSB_INTVEC, 0); 11161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } else { 11261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_write32(dev, SSB_IPSFLAG, 11361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_read32(dev, SSB_IPSFLAG) | 11461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ipsflag_irq_mask[irq]); 11561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 11661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 11761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 11861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void set_irq(struct ssb_device *dev, unsigned int irq) 11961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 12061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch unsigned int oldirq = ssb_mips_irq(dev); 12161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = dev->bus; 12261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_device *mdev = bus->mipscore.dev; 12361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 irqflag = ssb_irqflag(dev); 12461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 125ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET BUG_ON(oldirq == 6); 126ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET 12761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch dev->irq = irq + 2; 12861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 12961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* clear the old irq */ 13061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (oldirq == 0) 13161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); 132ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET else if (oldirq != 5) 13361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch clear_irq(bus, oldirq); 13461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 13561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* assign the new one */ 1362633da237ba29875294f8680ebece5900ccdcc05Michael Buesch if (irq == 0) { 1372633da237ba29875294f8680ebece5900ccdcc05Michael Buesch ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); 1382633da237ba29875294f8680ebece5900ccdcc05Michael Buesch } else { 139ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); 140ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { 141ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; 142ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET struct ssb_device *olddev = find_device(dev, oldipsflag); 143ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (olddev) 144ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET set_irq(olddev, 0); 145ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET } 1462633da237ba29875294f8680ebece5900ccdcc05Michael Buesch irqflag <<= ipsflag_irq_shift[irq]; 147ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); 1482633da237ba29875294f8680ebece5900ccdcc05Michael Buesch ssb_write32(mdev, SSB_IPSFLAG, irqflag); 1492633da237ba29875294f8680ebece5900ccdcc05Michael Buesch } 150ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET ssb_dprintk(KERN_INFO PFX 151ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET "set_irq: core 0x%04x, irq %d => %d\n", 152ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET dev->id.coreid, oldirq+2, irq+2); 153ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET} 154ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET 155ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTETstatic void print_irq(struct ssb_device *dev, unsigned int irq) 156ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET{ 157ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET int i; 158ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; 159ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET ssb_dprintk(KERN_INFO PFX 160ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET "core 0x%04x, irq :", dev->id.coreid); 161ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET for (i = 0; i <= 6; i++) { 162ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); 163ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET } 164ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET ssb_dprintk("\n"); 165ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET} 166ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET 167ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTETstatic void dump_irq(struct ssb_bus *bus) 168ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET{ 169ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET int i; 170ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET for (i = 0; i < bus->nr_devices; i++) { 171ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET struct ssb_device *dev; 172ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET dev = &(bus->devices[i]); 173ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET print_irq(dev, ssb_mips_irq(dev)); 174ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET } 17561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 17661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 17761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void ssb_mips_serial_init(struct ssb_mipscore *mcore) 17861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 17961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = mcore->dev->bus; 18061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 18161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->extif.dev) 18261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); 18361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch else if (bus->chipco.dev) 18461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); 18561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch else 18661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->nr_serial_ports = 0; 18761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 18861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 18961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschstatic void ssb_mips_flash_detect(struct ssb_mipscore *mcore) 19061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 19161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = mcore->dev->bus; 19261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 19361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->flash_buswidth = 2; 19461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->chipco.dev) { 19561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->flash_window = 0x1c000000; 19661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->flash_window_size = 0x02000000; 19761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) 19861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch & SSB_CHIPCO_CFG_DS16) == 0) 19961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->flash_buswidth = 1; 20061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } else { 20161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->flash_window = 0x1fc00000; 20261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch mcore->flash_window_size = 0x00400000; 20361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 20461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 20561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 20661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschu32 ssb_cpu_clock(struct ssb_mipscore *mcore) 20761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 20861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_bus *bus = mcore->dev->bus; 20961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch u32 pll_type, n, m, rate = 0; 21061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 211d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) 212d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens return ssb_pmu_get_cpu_clock(&bus->chipco); 213d486a5b4996d2fffd10098725781f2c5690774bcHauke Mehrtens 21461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->extif.dev) { 21561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); 21661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } else if (bus->chipco.dev) { 21761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); 21861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } else 21961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return 0; 22061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 22161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { 22261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch rate = 200000000; 22361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } else { 22461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch rate = ssb_calc_clock_rate(pll_type, n, m); 22561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 22661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 22761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (pll_type == SSB_PLLTYPE_6) { 22861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch rate *= 2; 22961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 23061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 23161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return rate; 23261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 23361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 23461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Bueschvoid ssb_mipscore_init(struct ssb_mipscore *mcore) 23561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch{ 2367007d00caca268e1ba2bcaa6bed4a6456a96884bFelix Fietkau struct ssb_bus *bus; 23761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch struct ssb_device *dev; 23861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch unsigned long hz, ns; 23961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch unsigned int irq, i; 24061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 24161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!mcore->dev) 24261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch return; /* We don't have a MIPS core */ 24361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 24461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); 24561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 2467007d00caca268e1ba2bcaa6bed4a6456a96884bFelix Fietkau bus = mcore->dev->bus; 24761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch hz = ssb_clockspeed(bus); 24861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (!hz) 24961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch hz = 100000000; 25061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ns = 1000000000 / hz; 25161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 25261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (bus->extif.dev) 25361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_extif_timing_init(&bus->extif, ns); 25461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch else if (bus->chipco.dev) 25561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_chipco_timing_init(&bus->chipco, ns); 25661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 25761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ 25861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch for (irq = 2, i = 0; i < bus->nr_devices; i++) { 259ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET int mips_irq; 26061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch dev = &(bus->devices[i]); 261ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET mips_irq = ssb_mips_irq(dev); 262ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (mips_irq > 4) 263ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET dev->irq = 0; 264ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET else 265ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET dev->irq = mips_irq + 2; 266ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET if (dev->irq > 5) 267ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET continue; 26861e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch switch (dev->id.coreid) { 26961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch case SSB_DEV_USB11_HOST: 27061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* shouldn't need a separate irq line for non-4710, most of them have a proper 27161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch * external usb controller on the pci */ 27261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if ((bus->chip_id == 0x4710) && (irq <= 4)) { 27361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch set_irq(dev, irq++); 27461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 275ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET break; 27661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch case SSB_DEV_PCI: 27761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch case SSB_DEV_ETHERNET: 278aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch case SSB_DEV_ETHERNET_GBIT: 27961e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch case SSB_DEV_80211: 28061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch case SSB_DEV_USB20_HOST: 28161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ 28261e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch if (irq <= 4) { 28361e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch set_irq(dev, irq++); 28461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch break; 28561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 28683e34f03ee9b86b49bde4707a1fe03a1837e29beJochen Friedrich /* fallthrough */ 28783e34f03ee9b86b49bde4707a1fe03a1837e29beJochen Friedrich case SSB_DEV_EXTIF: 28883e34f03ee9b86b49bde4707a1fe03a1837e29beJochen Friedrich set_irq(dev, 0); 28983e34f03ee9b86b49bde4707a1fe03a1837e29beJochen Friedrich break; 29061e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 29161e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch } 292ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); 293ea4bbfd0048c53c24f72ef668b39f1247bc243c0Matthieu CASTET dump_irq(bus); 29461e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch 29561e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_mips_serial_init(mcore); 29661e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch ssb_mips_flash_detect(mcore); 29761e115a56d1aafd6e6a8a9fee8ac099a6128ac7bMichael Buesch} 298