18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Sonics Silicon Backplane 38c2ecf20Sopenharmony_ci * Broadcom MIPS core driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2005, Broadcom Corporation 68c2ecf20Sopenharmony_ci * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "ssb_private.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/ssb/ssb.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/mtd/physmap.h> 168c2ecf20Sopenharmony_ci#include <linux/serial.h> 178c2ecf20Sopenharmony_ci#include <linux/serial_core.h> 188c2ecf20Sopenharmony_ci#include <linux/serial_reg.h> 198c2ecf20Sopenharmony_ci#include <linux/time.h> 208c2ecf20Sopenharmony_ci#ifdef CONFIG_BCM47XX 218c2ecf20Sopenharmony_ci#include <linux/bcm47xx_nvram.h> 228c2ecf20Sopenharmony_ci#endif 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic const char * const part_probes[] = { "bcm47xxpart", NULL }; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic struct physmap_flash_data ssb_pflash_data = { 278c2ecf20Sopenharmony_ci .part_probe_types = part_probes, 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic struct resource ssb_pflash_resource = { 318c2ecf20Sopenharmony_ci .name = "ssb_pflash", 328c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct platform_device ssb_pflash_dev = { 368c2ecf20Sopenharmony_ci .name = "physmap-flash", 378c2ecf20Sopenharmony_ci .dev = { 388c2ecf20Sopenharmony_ci .platform_data = &ssb_pflash_data, 398c2ecf20Sopenharmony_ci }, 408c2ecf20Sopenharmony_ci .resource = &ssb_pflash_resource, 418c2ecf20Sopenharmony_ci .num_resources = 1, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic inline u32 mips_read32(struct ssb_mipscore *mcore, 458c2ecf20Sopenharmony_ci u16 offset) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci return ssb_read32(mcore->dev, offset); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic inline void mips_write32(struct ssb_mipscore *mcore, 518c2ecf20Sopenharmony_ci u16 offset, 528c2ecf20Sopenharmony_ci u32 value) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci ssb_write32(mcore->dev, offset, value); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic const u32 ipsflag_irq_mask[] = { 588c2ecf20Sopenharmony_ci 0, 598c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ1, 608c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ2, 618c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ3, 628c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ4, 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic const u32 ipsflag_irq_shift[] = { 668c2ecf20Sopenharmony_ci 0, 678c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ1_SHIFT, 688c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ2_SHIFT, 698c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ3_SHIFT, 708c2ecf20Sopenharmony_ci SSB_IPSFLAG_IRQ4_SHIFT, 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic inline u32 ssb_irqflag(struct ssb_device *dev) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); 768c2ecf20Sopenharmony_ci if (tpsflag) 778c2ecf20Sopenharmony_ci return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; 788c2ecf20Sopenharmony_ci else 798c2ecf20Sopenharmony_ci /* not irq supported */ 808c2ecf20Sopenharmony_ci return 0x3f; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci struct ssb_bus *bus = rdev->bus; 868c2ecf20Sopenharmony_ci int i; 878c2ecf20Sopenharmony_ci for (i = 0; i < bus->nr_devices; i++) { 888c2ecf20Sopenharmony_ci struct ssb_device *dev; 898c2ecf20Sopenharmony_ci dev = &(bus->devices[i]); 908c2ecf20Sopenharmony_ci if (ssb_irqflag(dev) == irqflag) 918c2ecf20Sopenharmony_ci return dev; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci return NULL; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* Get the MIPS IRQ assignment for a specified device. 978c2ecf20Sopenharmony_ci * If unassigned, 0 is returned. 988c2ecf20Sopenharmony_ci * If disabled, 5 is returned. 998c2ecf20Sopenharmony_ci * If not supported, 6 is returned. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_ciunsigned int ssb_mips_irq(struct ssb_device *dev) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci struct ssb_bus *bus = dev->bus; 1048c2ecf20Sopenharmony_ci struct ssb_device *mdev = bus->mipscore.dev; 1058c2ecf20Sopenharmony_ci u32 irqflag; 1068c2ecf20Sopenharmony_ci u32 ipsflag; 1078c2ecf20Sopenharmony_ci u32 tmp; 1088c2ecf20Sopenharmony_ci unsigned int irq; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci irqflag = ssb_irqflag(dev); 1118c2ecf20Sopenharmony_ci if (irqflag == 0x3f) 1128c2ecf20Sopenharmony_ci return 6; 1138c2ecf20Sopenharmony_ci ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); 1148c2ecf20Sopenharmony_ci for (irq = 1; irq <= 4; irq++) { 1158c2ecf20Sopenharmony_ci tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); 1168c2ecf20Sopenharmony_ci if (tmp == irqflag) 1178c2ecf20Sopenharmony_ci break; 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci if (irq == 5) { 1208c2ecf20Sopenharmony_ci if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) 1218c2ecf20Sopenharmony_ci irq = 0; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return irq; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic void clear_irq(struct ssb_bus *bus, unsigned int irq) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci struct ssb_device *dev = bus->mipscore.dev; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* Clear the IRQ in the MIPScore backplane registers */ 1328c2ecf20Sopenharmony_ci if (irq == 0) { 1338c2ecf20Sopenharmony_ci ssb_write32(dev, SSB_INTVEC, 0); 1348c2ecf20Sopenharmony_ci } else { 1358c2ecf20Sopenharmony_ci ssb_write32(dev, SSB_IPSFLAG, 1368c2ecf20Sopenharmony_ci ssb_read32(dev, SSB_IPSFLAG) | 1378c2ecf20Sopenharmony_ci ipsflag_irq_mask[irq]); 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic void set_irq(struct ssb_device *dev, unsigned int irq) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci unsigned int oldirq = ssb_mips_irq(dev); 1448c2ecf20Sopenharmony_ci struct ssb_bus *bus = dev->bus; 1458c2ecf20Sopenharmony_ci struct ssb_device *mdev = bus->mipscore.dev; 1468c2ecf20Sopenharmony_ci u32 irqflag = ssb_irqflag(dev); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci BUG_ON(oldirq == 6); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci dev->irq = irq + 2; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* clear the old irq */ 1538c2ecf20Sopenharmony_ci if (oldirq == 0) 1548c2ecf20Sopenharmony_ci ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); 1558c2ecf20Sopenharmony_ci else if (oldirq != 5) 1568c2ecf20Sopenharmony_ci clear_irq(bus, oldirq); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* assign the new one */ 1598c2ecf20Sopenharmony_ci if (irq == 0) { 1608c2ecf20Sopenharmony_ci ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); 1618c2ecf20Sopenharmony_ci } else { 1628c2ecf20Sopenharmony_ci u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); 1638c2ecf20Sopenharmony_ci if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { 1648c2ecf20Sopenharmony_ci u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; 1658c2ecf20Sopenharmony_ci struct ssb_device *olddev = find_device(dev, oldipsflag); 1668c2ecf20Sopenharmony_ci if (olddev) 1678c2ecf20Sopenharmony_ci set_irq(olddev, 0); 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci irqflag <<= ipsflag_irq_shift[irq]; 1708c2ecf20Sopenharmony_ci irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); 1718c2ecf20Sopenharmony_ci ssb_write32(mdev, SSB_IPSFLAG, irqflag); 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "set_irq: core 0x%04x, irq %d => %d\n", 1748c2ecf20Sopenharmony_ci dev->id.coreid, oldirq+2, irq+2); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void print_irq(struct ssb_device *dev, unsigned int irq) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; 1808c2ecf20Sopenharmony_ci dev_dbg(dev->dev, 1818c2ecf20Sopenharmony_ci "core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", 1828c2ecf20Sopenharmony_ci dev->id.coreid, 1838c2ecf20Sopenharmony_ci irq_name[0], irq == 0 ? "*" : " ", 1848c2ecf20Sopenharmony_ci irq_name[1], irq == 1 ? "*" : " ", 1858c2ecf20Sopenharmony_ci irq_name[2], irq == 2 ? "*" : " ", 1868c2ecf20Sopenharmony_ci irq_name[3], irq == 3 ? "*" : " ", 1878c2ecf20Sopenharmony_ci irq_name[4], irq == 4 ? "*" : " ", 1888c2ecf20Sopenharmony_ci irq_name[5], irq == 5 ? "*" : " ", 1898c2ecf20Sopenharmony_ci irq_name[6], irq == 6 ? "*" : " "); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic void dump_irq(struct ssb_bus *bus) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci int i; 1958c2ecf20Sopenharmony_ci for (i = 0; i < bus->nr_devices; i++) { 1968c2ecf20Sopenharmony_ci struct ssb_device *dev; 1978c2ecf20Sopenharmony_ci dev = &(bus->devices[i]); 1988c2ecf20Sopenharmony_ci print_irq(dev, ssb_mips_irq(dev)); 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic void ssb_mips_serial_init(struct ssb_mipscore *mcore) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci struct ssb_bus *bus = mcore->dev->bus; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (ssb_extif_available(&bus->extif)) 2078c2ecf20Sopenharmony_ci mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); 2088c2ecf20Sopenharmony_ci else if (ssb_chipco_available(&bus->chipco)) 2098c2ecf20Sopenharmony_ci mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); 2108c2ecf20Sopenharmony_ci else 2118c2ecf20Sopenharmony_ci mcore->nr_serial_ports = 0; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic void ssb_mips_flash_detect(struct ssb_mipscore *mcore) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct ssb_bus *bus = mcore->dev->bus; 2178c2ecf20Sopenharmony_ci struct ssb_sflash *sflash = &mcore->sflash; 2188c2ecf20Sopenharmony_ci struct ssb_pflash *pflash = &mcore->pflash; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* When there is no chipcommon on the bus there is 4MB flash */ 2218c2ecf20Sopenharmony_ci if (!ssb_chipco_available(&bus->chipco)) { 2228c2ecf20Sopenharmony_ci pflash->present = true; 2238c2ecf20Sopenharmony_ci pflash->buswidth = 2; 2248c2ecf20Sopenharmony_ci pflash->window = SSB_FLASH1; 2258c2ecf20Sopenharmony_ci pflash->window_size = SSB_FLASH1_SZ; 2268c2ecf20Sopenharmony_ci goto ssb_pflash; 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* There is ChipCommon, so use it to read info about flash */ 2308c2ecf20Sopenharmony_ci switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { 2318c2ecf20Sopenharmony_ci case SSB_CHIPCO_FLASHT_STSER: 2328c2ecf20Sopenharmony_ci case SSB_CHIPCO_FLASHT_ATSER: 2338c2ecf20Sopenharmony_ci dev_dbg(mcore->dev->dev, "Found serial flash\n"); 2348c2ecf20Sopenharmony_ci ssb_sflash_init(&bus->chipco); 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci case SSB_CHIPCO_FLASHT_PARA: 2378c2ecf20Sopenharmony_ci dev_dbg(mcore->dev->dev, "Found parallel flash\n"); 2388c2ecf20Sopenharmony_ci pflash->present = true; 2398c2ecf20Sopenharmony_ci pflash->window = SSB_FLASH2; 2408c2ecf20Sopenharmony_ci pflash->window_size = SSB_FLASH2_SZ; 2418c2ecf20Sopenharmony_ci if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) 2428c2ecf20Sopenharmony_ci & SSB_CHIPCO_CFG_DS16) == 0) 2438c2ecf20Sopenharmony_ci pflash->buswidth = 1; 2448c2ecf20Sopenharmony_ci else 2458c2ecf20Sopenharmony_ci pflash->buswidth = 2; 2468c2ecf20Sopenharmony_ci break; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cissb_pflash: 2508c2ecf20Sopenharmony_ci if (sflash->present) { 2518c2ecf20Sopenharmony_ci#ifdef CONFIG_BCM47XX 2528c2ecf20Sopenharmony_ci bcm47xx_nvram_init_from_mem(sflash->window, sflash->size); 2538c2ecf20Sopenharmony_ci#endif 2548c2ecf20Sopenharmony_ci } else if (pflash->present) { 2558c2ecf20Sopenharmony_ci#ifdef CONFIG_BCM47XX 2568c2ecf20Sopenharmony_ci bcm47xx_nvram_init_from_mem(pflash->window, pflash->window_size); 2578c2ecf20Sopenharmony_ci#endif 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci ssb_pflash_data.width = pflash->buswidth; 2608c2ecf20Sopenharmony_ci ssb_pflash_resource.start = pflash->window; 2618c2ecf20Sopenharmony_ci ssb_pflash_resource.end = pflash->window + pflash->window_size; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciu32 ssb_cpu_clock(struct ssb_mipscore *mcore) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct ssb_bus *bus = mcore->dev->bus; 2688c2ecf20Sopenharmony_ci u32 pll_type, n, m, rate = 0; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) 2718c2ecf20Sopenharmony_ci return ssb_pmu_get_cpu_clock(&bus->chipco); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (ssb_extif_available(&bus->extif)) { 2748c2ecf20Sopenharmony_ci ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); 2758c2ecf20Sopenharmony_ci } else if (ssb_chipco_available(&bus->chipco)) { 2768c2ecf20Sopenharmony_ci ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); 2778c2ecf20Sopenharmony_ci } else 2788c2ecf20Sopenharmony_ci return 0; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { 2818c2ecf20Sopenharmony_ci rate = 200000000; 2828c2ecf20Sopenharmony_ci } else { 2838c2ecf20Sopenharmony_ci rate = ssb_calc_clock_rate(pll_type, n, m); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (pll_type == SSB_PLLTYPE_6) { 2878c2ecf20Sopenharmony_ci rate *= 2; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return rate; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_civoid ssb_mipscore_init(struct ssb_mipscore *mcore) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci struct ssb_bus *bus; 2968c2ecf20Sopenharmony_ci struct ssb_device *dev; 2978c2ecf20Sopenharmony_ci unsigned long hz, ns; 2988c2ecf20Sopenharmony_ci unsigned int irq, i; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (!mcore->dev) 3018c2ecf20Sopenharmony_ci return; /* We don't have a MIPS core */ 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci dev_dbg(mcore->dev->dev, "Initializing MIPS core...\n"); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci bus = mcore->dev->bus; 3068c2ecf20Sopenharmony_ci hz = ssb_clockspeed(bus); 3078c2ecf20Sopenharmony_ci if (!hz) 3088c2ecf20Sopenharmony_ci hz = 100000000; 3098c2ecf20Sopenharmony_ci ns = 1000000000 / hz; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (ssb_extif_available(&bus->extif)) 3128c2ecf20Sopenharmony_ci ssb_extif_timing_init(&bus->extif, ns); 3138c2ecf20Sopenharmony_ci else if (ssb_chipco_available(&bus->chipco)) 3148c2ecf20Sopenharmony_ci ssb_chipco_timing_init(&bus->chipco, ns); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ 3178c2ecf20Sopenharmony_ci for (irq = 2, i = 0; i < bus->nr_devices; i++) { 3188c2ecf20Sopenharmony_ci int mips_irq; 3198c2ecf20Sopenharmony_ci dev = &(bus->devices[i]); 3208c2ecf20Sopenharmony_ci mips_irq = ssb_mips_irq(dev); 3218c2ecf20Sopenharmony_ci if (mips_irq > 4) 3228c2ecf20Sopenharmony_ci dev->irq = 0; 3238c2ecf20Sopenharmony_ci else 3248c2ecf20Sopenharmony_ci dev->irq = mips_irq + 2; 3258c2ecf20Sopenharmony_ci if (dev->irq > 5) 3268c2ecf20Sopenharmony_ci continue; 3278c2ecf20Sopenharmony_ci switch (dev->id.coreid) { 3288c2ecf20Sopenharmony_ci case SSB_DEV_USB11_HOST: 3298c2ecf20Sopenharmony_ci /* shouldn't need a separate irq line for non-4710, most of them have a proper 3308c2ecf20Sopenharmony_ci * external usb controller on the pci */ 3318c2ecf20Sopenharmony_ci if ((bus->chip_id == 0x4710) && (irq <= 4)) { 3328c2ecf20Sopenharmony_ci set_irq(dev, irq++); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci case SSB_DEV_PCI: 3368c2ecf20Sopenharmony_ci case SSB_DEV_ETHERNET: 3378c2ecf20Sopenharmony_ci case SSB_DEV_ETHERNET_GBIT: 3388c2ecf20Sopenharmony_ci case SSB_DEV_80211: 3398c2ecf20Sopenharmony_ci case SSB_DEV_USB20_HOST: 3408c2ecf20Sopenharmony_ci /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ 3418c2ecf20Sopenharmony_ci if (irq <= 4) { 3428c2ecf20Sopenharmony_ci set_irq(dev, irq++); 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci fallthrough; 3468c2ecf20Sopenharmony_ci case SSB_DEV_EXTIF: 3478c2ecf20Sopenharmony_ci set_irq(dev, 0); 3488c2ecf20Sopenharmony_ci break; 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci dev_dbg(mcore->dev->dev, "after irq reconfiguration\n"); 3528c2ecf20Sopenharmony_ci dump_irq(bus); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci ssb_mips_serial_init(mcore); 3558c2ecf20Sopenharmony_ci ssb_mips_flash_detect(mcore); 3568c2ecf20Sopenharmony_ci} 357