From 864c6c22e9a5742b0f43c983b6c405d52817bacd Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Wed, 16 Nov 2011 15:42:28 +0100 Subject: MIPS: Alchemy: Fix PCI PM Move PCI Controller PM to syscore_ops since the platform_driver PM methods are called way too late on resume and far too early on suspend (after and before PCI device resume/suspend). This also allows to simplify wired entry management a bit. Signed-off-by: Manuel Lauss Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3007/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-alchemy.c | 137 ++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 70 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index b5ce041cdaf..b5eddf533c0 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,12 @@ struct alchemy_pci_context { int (*board_pci_idsel)(unsigned int devsel, int assert); }; +/* for syscore_ops. There's only one PCI controller on Alchemy chips, so this + * should suffice for now. + */ +static struct alchemy_pci_context *__alchemy_pci_ctx; + + /* IO/MEM resources for PCI. Keep the memres in sync with __fixup_bigphys_addr * in arch/mips/alchemy/common/setup.c */ @@ -99,18 +106,6 @@ static int config_access(unsigned char access_type, struct pci_bus *bus, return -1; } - /* YAMON on all db1xxx boards wipes the TLB and writes zero to C0_wired - * on resume, clearing our wired entry. Unfortunately the ->resume() - * callback is called way way way too late (and ->suspend() too early) - * to have them destroy and recreate it. Instead just test if c0_wired - * is now lower than the index we retrieved before suspending and then - * recreate the entry if necessary. Of course this is totally bonkers - * and breaks as soon as someone else adds another wired entry somewhere - * else. Anyone have any ideas how to handle this better? - */ - if (unlikely(read_c0_wired() < ctx->wired_entry)) - alchemy_pci_wired_entry(ctx); - local_irq_save(flags); r = __raw_readl(ctx->regs + PCI_REG_STATCMD) & 0x0000ffff; r |= PCI_STATCMD_STATUS(0x2000); @@ -304,6 +299,62 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int assert) return 1; /* success */ } +/* save PCI controller register contents. */ +static int alchemy_pci_suspend(void) +{ + struct alchemy_pci_context *ctx = __alchemy_pci_ctx; + if (!ctx) + return 0; + + ctx->pm[0] = __raw_readl(ctx->regs + PCI_REG_CMEM); + ctx->pm[1] = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff; + ctx->pm[2] = __raw_readl(ctx->regs + PCI_REG_B2BMASK_CCH); + ctx->pm[3] = __raw_readl(ctx->regs + PCI_REG_B2BBASE0_VID); + ctx->pm[4] = __raw_readl(ctx->regs + PCI_REG_B2BBASE1_SID); + ctx->pm[5] = __raw_readl(ctx->regs + PCI_REG_MWMASK_DEV); + ctx->pm[6] = __raw_readl(ctx->regs + PCI_REG_MWBASE_REV_CCL); + ctx->pm[7] = __raw_readl(ctx->regs + PCI_REG_ID); + ctx->pm[8] = __raw_readl(ctx->regs + PCI_REG_CLASSREV); + ctx->pm[9] = __raw_readl(ctx->regs + PCI_REG_PARAM); + ctx->pm[10] = __raw_readl(ctx->regs + PCI_REG_MBAR); + ctx->pm[11] = __raw_readl(ctx->regs + PCI_REG_TIMEOUT); + + return 0; +} + +static void alchemy_pci_resume(void) +{ + struct alchemy_pci_context *ctx = __alchemy_pci_ctx; + if (!ctx) + return; + + __raw_writel(ctx->pm[0], ctx->regs + PCI_REG_CMEM); + __raw_writel(ctx->pm[2], ctx->regs + PCI_REG_B2BMASK_CCH); + __raw_writel(ctx->pm[3], ctx->regs + PCI_REG_B2BBASE0_VID); + __raw_writel(ctx->pm[4], ctx->regs + PCI_REG_B2BBASE1_SID); + __raw_writel(ctx->pm[5], ctx->regs + PCI_REG_MWMASK_DEV); + __raw_writel(ctx->pm[6], ctx->regs + PCI_REG_MWBASE_REV_CCL); + __raw_writel(ctx->pm[7], ctx->regs + PCI_REG_ID); + __raw_writel(ctx->pm[8], ctx->regs + PCI_REG_CLASSREV); + __raw_writel(ctx->pm[9], ctx->regs + PCI_REG_PARAM); + __raw_writel(ctx->pm[10], ctx->regs + PCI_REG_MBAR); + __raw_writel(ctx->pm[11], ctx->regs + PCI_REG_TIMEOUT); + wmb(); + __raw_writel(ctx->pm[1], ctx->regs + PCI_REG_CONFIG); + wmb(); + + /* YAMON on all db1xxx boards wipes the TLB and writes zero to C0_wired + * on resume, making it necessary to recreate it as soon as possible. + */ + ctx->wired_entry = 8191; /* impossibly high value */ + alchemy_pci_wired_entry(ctx); /* install it */ +} + +static struct syscore_ops alchemy_pci_pmops = { + .suspend = alchemy_pci_suspend, + .resume = alchemy_pci_resume, +}; + static int __devinit alchemy_pci_probe(struct platform_device *pdev) { struct alchemy_pci_platdata *pd = pdev->dev.platform_data; @@ -396,7 +447,8 @@ static int __devinit alchemy_pci_probe(struct platform_device *pdev) ret = -ENOMEM; goto out4; } - ctx->wired_entry = 8192; /* impossibly high value */ + ctx->wired_entry = 8191; /* impossibly high value */ + alchemy_pci_wired_entry(ctx); /* install it */ set_io_port_base((unsigned long)ctx->alchemy_pci_ctrl.io_map_base); @@ -408,7 +460,9 @@ static int __devinit alchemy_pci_probe(struct platform_device *pdev) __raw_writel(val, ctx->regs + PCI_REG_CONFIG); wmb(); + __alchemy_pci_ctx = ctx; platform_set_drvdata(pdev, ctx); + register_syscore_ops(&alchemy_pci_pmops); register_pci_controller(&ctx->alchemy_pci_ctrl); return 0; @@ -425,68 +479,11 @@ out: return ret; } - -#ifdef CONFIG_PM -/* save PCI controller register contents. */ -static int alchemy_pci_suspend(struct device *dev) -{ - struct alchemy_pci_context *ctx = dev_get_drvdata(dev); - - ctx->pm[0] = __raw_readl(ctx->regs + PCI_REG_CMEM); - ctx->pm[1] = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff; - ctx->pm[2] = __raw_readl(ctx->regs + PCI_REG_B2BMASK_CCH); - ctx->pm[3] = __raw_readl(ctx->regs + PCI_REG_B2BBASE0_VID); - ctx->pm[4] = __raw_readl(ctx->regs + PCI_REG_B2BBASE1_SID); - ctx->pm[5] = __raw_readl(ctx->regs + PCI_REG_MWMASK_DEV); - ctx->pm[6] = __raw_readl(ctx->regs + PCI_REG_MWBASE_REV_CCL); - ctx->pm[7] = __raw_readl(ctx->regs + PCI_REG_ID); - ctx->pm[8] = __raw_readl(ctx->regs + PCI_REG_CLASSREV); - ctx->pm[9] = __raw_readl(ctx->regs + PCI_REG_PARAM); - ctx->pm[10] = __raw_readl(ctx->regs + PCI_REG_MBAR); - ctx->pm[11] = __raw_readl(ctx->regs + PCI_REG_TIMEOUT); - - return 0; -} - -static int alchemy_pci_resume(struct device *dev) -{ - struct alchemy_pci_context *ctx = dev_get_drvdata(dev); - - __raw_writel(ctx->pm[0], ctx->regs + PCI_REG_CMEM); - __raw_writel(ctx->pm[2], ctx->regs + PCI_REG_B2BMASK_CCH); - __raw_writel(ctx->pm[3], ctx->regs + PCI_REG_B2BBASE0_VID); - __raw_writel(ctx->pm[4], ctx->regs + PCI_REG_B2BBASE1_SID); - __raw_writel(ctx->pm[5], ctx->regs + PCI_REG_MWMASK_DEV); - __raw_writel(ctx->pm[6], ctx->regs + PCI_REG_MWBASE_REV_CCL); - __raw_writel(ctx->pm[7], ctx->regs + PCI_REG_ID); - __raw_writel(ctx->pm[8], ctx->regs + PCI_REG_CLASSREV); - __raw_writel(ctx->pm[9], ctx->regs + PCI_REG_PARAM); - __raw_writel(ctx->pm[10], ctx->regs + PCI_REG_MBAR); - __raw_writel(ctx->pm[11], ctx->regs + PCI_REG_TIMEOUT); - wmb(); - __raw_writel(ctx->pm[1], ctx->regs + PCI_REG_CONFIG); - wmb(); - - return 0; -} - -static const struct dev_pm_ops alchemy_pci_pmops = { - .suspend = alchemy_pci_suspend, - .resume = alchemy_pci_resume, -}; - -#define ALCHEMY_PCICTL_PM (&alchemy_pci_pmops) - -#else -#define ALCHEMY_PCICTL_PM NULL -#endif - static struct platform_driver alchemy_pcictl_driver = { .probe = alchemy_pci_probe, .driver = { .name = "alchemy-pci", .owner = THIS_MODULE, - .pm = ALCHEMY_PCICTL_PM, }, }; -- cgit v1.2.3-70-g09d2 From ab75dc02c151c9d2a2fd446334d740b097a3b9db Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 17 Nov 2011 15:07:31 +0000 Subject: MIPS: Fix up inconsistency in panic() string argument. Panic() invokes printk() to add a \n internally, so panic arguments should not themselves end in \n. Panic invocations in arch/mips and elsewhere are inconsistently sometimes terminating in \n, sometimes not. Signed-off-by: Ralf Baechle --- arch/mips/ar7/platform.c | 2 +- arch/mips/ar7/setup.c | 2 +- arch/mips/ath79/setup.c | 2 +- arch/mips/bcm47xx/setup.c | 4 ++-- arch/mips/cavium-octeon/setup.c | 6 +++--- arch/mips/cavium-octeon/smp.c | 2 +- arch/mips/jz4740/board-qi_lb60.c | 2 +- arch/mips/kernel/smtc.c | 4 ++-- arch/mips/kernel/traps.c | 4 ++-- arch/mips/lantiq/clk.c | 4 ++-- arch/mips/lantiq/irq.c | 12 ++++++------ arch/mips/lantiq/xway/dma.c | 6 +++--- arch/mips/lantiq/xway/ebu.c | 6 +++--- arch/mips/lantiq/xway/pmu.c | 8 ++++---- arch/mips/lantiq/xway/reset.c | 6 +++--- arch/mips/mm/c-octeon.c | 2 +- arch/mips/pci/msi-octeon.c | 2 +- arch/mips/pmc-sierra/msp71xx/msp_setup.c | 2 +- arch/mips/sgi-ip27/ip27-irq.c | 4 ++-- 19 files changed, 40 insertions(+), 40 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 33ffecf6a6d..60102392af0 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -536,7 +536,7 @@ static int __init ar7_register_uarts(void) bus_clk = clk_get(NULL, "bus"); if (IS_ERR(bus_clk)) - panic("unable to get bus clk\n"); + panic("unable to get bus clk"); uart_port.type = PORT_AR7; uart_port.uartclk = clk_get_rate(bus_clk) / 2; diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c index f20b53e597c..9a357fffcfb 100644 --- a/arch/mips/ar7/setup.c +++ b/arch/mips/ar7/setup.c @@ -96,7 +96,7 @@ void __init plat_mem_setup(void) io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000); if (!io_base) - panic("Can't remap IO base!\n"); + panic("Can't remap IO base!"); set_io_port_base(io_base); prom_meminit(); diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 159b42f106b..1cf60e1d9dd 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -134,7 +134,7 @@ static void __init ath79_detect_sys_type(void) break; default: - panic("ath79: unknown SoC, id:0x%08x\n", id); + panic("ath79: unknown SoC, id:0x%08x", id); } sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 1cfdda03546..aab6b0c40a7 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -289,7 +289,7 @@ static void __init bcm47xx_register_ssb(void) err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE, bcm47xx_get_invariants); if (err) - panic("Failed to initialize SSB bus (err %d)\n", err); + panic("Failed to initialize SSB bus (err %d)", err); mcore = &bcm47xx_bus.ssb.mipscore; if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { @@ -314,7 +314,7 @@ static void __init bcm47xx_register_bcma(void) err = bcma_host_soc_register(&bcm47xx_bus.bcma); if (err) - panic("Failed to initialize BCMA bus (err %d)\n", err); + panic("Failed to initialize BCMA bus (err %d)", err); } #endif diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 2d9028f1474..853bac4f25b 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -767,11 +767,11 @@ void prom_free_prom_memory(void) : "=r" (insn) : : "$31", "memory"); if ((insn >> 26) != 0x33) - panic("No PREF instruction at Core-14449 probe point.\n"); + panic("No PREF instruction at Core-14449 probe point."); if (((insn >> 16) & 0x1f) != 28) panic("Core-14449 WAR not in place (%04x).\n" - "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).\n", insn); + "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).", insn); } #ifdef CONFIG_CAVIUM_DECODE_RSL cvmx_interrupt_rsl_enable(); @@ -779,7 +779,7 @@ void prom_free_prom_memory(void) /* Add an interrupt handler for general failures. */ if (request_irq(OCTEON_IRQ_RML, octeon_rlm_interrupt, IRQF_SHARED, "RML/RSL", octeon_rlm_interrupt)) { - panic("Unable to request_irq(OCTEON_IRQ_RML)\n"); + panic("Unable to request_irq(OCTEON_IRQ_RML)"); } #endif } diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index efcfff4d462..b1535fe409d 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -210,7 +210,7 @@ void octeon_prepare_cpus(unsigned int max_cpus) if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_PERCPU | IRQF_NO_THREAD, "SMP-IPI", mailbox_interrupt)) { - panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n"); + panic("Cannot request_irq(OCTEON_IRQ_MBOX0)"); } } diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index c3b04be3fb2..639e3ce6c26 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -488,7 +488,7 @@ static int __init qi_lb60_board_setup(void) board_gpio_setup(); if (qi_lb60_init_platform_devices()) - panic("Failed to initialize platform devices\n"); + panic("Failed to initialize platform devices"); return 0; } diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index f0895e70e28..b1eea63cc98 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -559,7 +559,7 @@ void smtc_prepare_cpus(int cpus) pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL); if (pipi == NULL) - panic("kmalloc of IPI message buffers failed\n"); + panic("kmalloc of IPI message buffers failed"); else printk("IPI buffer pool of %d buffers\n", nipi); for (i = 0; i < nipi; i++) { @@ -813,7 +813,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) if (pipi == NULL) { bust_spinlocks(1); mips_mt_regdump(dvpe()); - panic("IPI Msg. Buffers Depleted\n"); + panic("IPI Msg. Buffers Depleted"); } pipi->type = type; pipi->arg = (void *)action; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 5c8a49d5505..363c4764b81 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -400,7 +400,7 @@ void __noreturn die(const char *str, struct pt_regs *regs) panic("Fatal exception in interrupt"); if (panic_on_oops) { - printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + printk(KERN_EMERG "Fatal exception: panic in 5 seconds"); ssleep(5); panic("Fatal exception"); } @@ -1150,7 +1150,7 @@ asmlinkage void do_mt(struct pt_regs *regs) asmlinkage void do_dsp(struct pt_regs *regs) { if (cpu_has_dsp) - panic("Unexpected DSP exception\n"); + panic("Unexpected DSP exception"); force_sig(SIGILL, current); } diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index 77ed70fc2fe..412814fdd3e 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -134,11 +134,11 @@ void __init plat_time_init(void) struct clk *clk; if (insert_resource(&iomem_resource, <q_cgu_resource) < 0) - panic("Failed to insert cgu memory\n"); + panic("Failed to insert cgu memory"); if (request_mem_region(ltq_cgu_resource.start, resource_size(<q_cgu_resource), "cgu") < 0) - panic("Failed to request cgu memory\n"); + panic("Failed to request cgu memory"); ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start, resource_size(<q_cgu_resource)); diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index f9737bb3c5a..51fa0a4ba55 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -249,28 +249,28 @@ void __init arch_init_irq(void) int i; if (insert_resource(&iomem_resource, <q_icu_resource) < 0) - panic("Failed to insert icu memory\n"); + panic("Failed to insert icu memory"); if (request_mem_region(ltq_icu_resource.start, resource_size(<q_icu_resource), "icu") < 0) - panic("Failed to request icu memory\n"); + panic("Failed to request icu memory"); ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start, resource_size(<q_icu_resource)); if (!ltq_icu_membase) - panic("Failed to remap icu memory\n"); + panic("Failed to remap icu memory"); if (insert_resource(&iomem_resource, <q_eiu_resource) < 0) - panic("Failed to insert eiu memory\n"); + panic("Failed to insert eiu memory"); if (request_mem_region(ltq_eiu_resource.start, resource_size(<q_eiu_resource), "eiu") < 0) - panic("Failed to request eiu memory\n"); + panic("Failed to request eiu memory"); ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start, resource_size(<q_eiu_resource)); if (!ltq_eiu_membase) - panic("Failed to remap eiu memory\n"); + panic("Failed to remap eiu memory"); /* make sure all irqs are turned off by default */ for (i = 0; i < 5; i++) diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c index cbb6ae5747b..b210e936c7c 100644 --- a/arch/mips/lantiq/xway/dma.c +++ b/arch/mips/lantiq/xway/dma.c @@ -222,17 +222,17 @@ ltq_dma_init(void) /* insert and request the memory region */ if (insert_resource(&iomem_resource, <q_dma_resource) < 0) - panic("Failed to insert dma memory\n"); + panic("Failed to insert dma memory"); if (request_mem_region(ltq_dma_resource.start, resource_size(<q_dma_resource), "dma") < 0) - panic("Failed to request dma memory\n"); + panic("Failed to request dma memory"); /* remap dma register range */ ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start, resource_size(<q_dma_resource)); if (!ltq_dma_membase) - panic("Failed to remap dma memory\n"); + panic("Failed to remap dma memory"); /* power up and reset the dma engine */ ltq_pmu_enable(PMU_DMA); diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c index 033b3184c7a..862e3e83068 100644 --- a/arch/mips/lantiq/xway/ebu.c +++ b/arch/mips/lantiq/xway/ebu.c @@ -32,17 +32,17 @@ static int __init lantiq_ebu_init(void) { /* insert and request the memory region */ if (insert_resource(&iomem_resource, <q_ebu_resource) < 0) - panic("Failed to insert ebu memory\n"); + panic("Failed to insert ebu memory"); if (request_mem_region(ltq_ebu_resource.start, resource_size(<q_ebu_resource), "ebu") < 0) - panic("Failed to request ebu memory\n"); + panic("Failed to request ebu memory"); /* remap ebu register range */ ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start, resource_size(<q_ebu_resource)); if (!ltq_ebu_membase) - panic("Failed to remap ebu memory\n"); + panic("Failed to remap ebu memory"); /* make sure to unprotect the memory region where flash is located */ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0); diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c index 39f0d2641cb..fe85361e032 100644 --- a/arch/mips/lantiq/xway/pmu.c +++ b/arch/mips/lantiq/xway/pmu.c @@ -40,7 +40,7 @@ void ltq_pmu_enable(unsigned int module) do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module)); if (!err) - panic("activating PMU module failed!\n"); + panic("activating PMU module failed!"); } EXPORT_SYMBOL(ltq_pmu_enable); @@ -53,16 +53,16 @@ EXPORT_SYMBOL(ltq_pmu_disable); int __init ltq_pmu_init(void) { if (insert_resource(&iomem_resource, <q_pmu_resource) < 0) - panic("Failed to insert pmu memory\n"); + panic("Failed to insert pmu memory"); if (request_mem_region(ltq_pmu_resource.start, resource_size(<q_pmu_resource), "pmu") < 0) - panic("Failed to request pmu memory\n"); + panic("Failed to request pmu memory"); ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start, resource_size(<q_pmu_resource)); if (!ltq_pmu_membase) - panic("Failed to remap pmu memory\n"); + panic("Failed to remap pmu memory"); return 0; } diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 3d41f0bb5bf..8b66bd87f0c 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -69,17 +69,17 @@ static int __init mips_reboot_setup(void) { /* insert and request the memory region */ if (insert_resource(&iomem_resource, <q_rcu_resource) < 0) - panic("Failed to insert rcu memory\n"); + panic("Failed to insert rcu memory"); if (request_mem_region(ltq_rcu_resource.start, resource_size(<q_rcu_resource), "rcu") < 0) - panic("Failed to request rcu memory\n"); + panic("Failed to request rcu memory"); /* remap rcu register range */ ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start, resource_size(<q_rcu_resource)); if (!ltq_rcu_membase) - panic("Failed to remap rcu memory\n"); + panic("Failed to remap rcu memory"); _machine_restart = ltq_machine_restart; _machine_halt = ltq_machine_halt; diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index daa81f7284a..cf7895db073 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -223,7 +223,7 @@ static void __cpuinit probe_octeon(void) break; default: - panic("Unsupported Cavium Networks CPU type\n"); + panic("Unsupported Cavium Networks CPU type"); break; } diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 5d530f89d87..d37be36dc65 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -162,7 +162,7 @@ msi_irq_allocated: msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; break; default: - panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n"); + panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type"); } msg.data = irq - OCTEON_IRQ_MSI_BIT0; diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c index 655308a4e1c..7a834b2f8a5 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_setup.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c @@ -209,7 +209,7 @@ void __init prom_init(void) default: /* we don't recognize the machine */ mips_machtype = MACH_UNKNOWN; - panic("***Bogosity factor five***, exiting\n"); + panic("***Bogosity factor five***, exiting"); break; } diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index f90dce315e0..ec3782d3189 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -73,7 +73,7 @@ static inline int alloc_level(int cpu, int irq) level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); if (level >= LEVELS_PER_SLICE) - panic("Cpu %d flooded with devices\n", cpu); + panic("Cpu %d flooded with devices", cpu); __set_bit(level, hub->irq_alloc_mask); si->level_to_irq[level] = irq; @@ -96,7 +96,7 @@ static inline int find_level(cpuid_t *cpunum, int irq) } } - panic("Could not identify cpu/level for irq %d\n", irq); + panic("Could not identify cpu/level for irq %d", irq); } /* -- cgit v1.2.3-70-g09d2 From 3d18c98367eac23555ea4887c4f570423474eeaf Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 28 Nov 2011 16:11:28 +0000 Subject: MIPS: Fix Jazz 64-bit build error. Move add_wired_entry to its own header file from where it will be always included. Patch up other users of add_wired_entry to also include the header as needed. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pgtable-32.h | 6 ------ arch/mips/include/asm/tlbmisc.h | 10 ++++++++++ arch/mips/jazz/irq.c | 1 + arch/mips/jazz/setup.c | 1 + arch/mips/mm/tlb-r3k.c | 1 + arch/mips/mm/tlb-r4k.c | 1 + arch/mips/pci/pci-alchemy.c | 1 + 7 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 arch/mips/include/asm/tlbmisc.h (limited to 'arch/mips/pci') diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index 8a153d2fa62..469390656c3 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -18,12 +18,6 @@ #include -/* - * - add_wired_entry() add a fixed TLB entry, and move wired register - */ -extern void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask); - /* * - add_temporary_entry() add a temporary TLB entry. We use TLB entries * starting at the top and working down. This is for populating the diff --git a/arch/mips/include/asm/tlbmisc.h b/arch/mips/include/asm/tlbmisc.h new file mode 100644 index 00000000000..3a452282cba --- /dev/null +++ b/arch/mips/include/asm/tlbmisc.h @@ -0,0 +1,10 @@ +#ifndef __ASM_TLBMISC_H +#define __ASM_TLBMISC_H + +/* + * - add_wired_entry() add a fixed TLB entry, and move wired register + */ +extern void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + +#endif /* __ASM_TLBMISC_H */ diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index ca9bd206914..99ab86ffa4c 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -20,6 +20,7 @@ #include #include #include +#include static DEFINE_RAW_SPINLOCK(r4030_lock); diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index 0d0f054a02f..820e926dacb 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c @@ -21,6 +21,7 @@ #include #include #include +#include extern asmlinkage void jazz_handle_int(void); diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 87bb85d8d53..ed1fa460f84 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 0d394e0e883..d163455552b 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -19,6 +19,7 @@ #include #include #include +#include extern void build_tlb_refill_handler(void); diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index b5eddf533c0..ec125bed721 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -17,6 +17,7 @@ #include #include +#include #ifdef CONFIG_DEBUG_PCI #define DBG(x...) printk(KERN_DEBUG x) -- cgit v1.2.3-70-g09d2 From 4ff40d5a7668cfadcfc37c3982caea940ba60d8d Mon Sep 17 00:00:00 2001 From: Rene Bolldorf Date: Thu, 17 Nov 2011 14:25:09 +0000 Subject: MIPS: Initial PCI support for Atheros 724x SoCs. [ralf@linux-mips.org: Fixed the odd formatting of all break statements.] Signed-off-by: Rene Bolldorf Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/3019/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ath79/pci-ath724x.h | 21 +++ arch/mips/pci/Makefile | 1 + arch/mips/pci/pci-ath724x.c | 174 +++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 arch/mips/include/asm/mach-ath79/pci-ath724x.h create mode 100644 arch/mips/pci/pci-ath724x.c (limited to 'arch/mips/pci') diff --git a/arch/mips/include/asm/mach-ath79/pci-ath724x.h b/arch/mips/include/asm/mach-ath79/pci-ath724x.h new file mode 100644 index 00000000000..454885fa30c --- /dev/null +++ b/arch/mips/include/asm/mach-ath79/pci-ath724x.h @@ -0,0 +1,21 @@ +/* + * Atheros 724x PCI support + * + * Copyright (C) 2011 RenĂ© Bolldorf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_ATH79_PCI_ATH724X_H +#define __ASM_MACH_ATH79_PCI_ATH724X_H + +struct ath724x_pci_data { + int irq; + void *pdata; +}; + +void ath724x_pci_add_data(struct ath724x_pci_data *data, int size); + +#endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */ diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index bb82cbdbc62..19cfe044e7d 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ ops-bcm63xx.o obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o +obj-$(CONFIG_SOC_AR724X) += pci-ath724x.o # # These are still pretty much in the old state, watch, go blind. diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c new file mode 100644 index 00000000000..a4dd24a4130 --- /dev/null +++ b/arch/mips/pci/pci-ath724x.c @@ -0,0 +1,174 @@ +/* + * Atheros 724x PCI support + * + * Copyright (C) 2011 RenĂ© Bolldorf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include + +#define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) +#define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) + +#define ATH724X_PCI_DEV_BASE 0x14000000 +#define ATH724X_PCI_MEM_BASE 0x10000000 +#define ATH724X_PCI_MEM_SIZE 0x08000000 + +static DEFINE_SPINLOCK(ath724x_pci_lock); +static struct ath724x_pci_data *pci_data; +static int pci_data_size; + +static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t *value) +{ + unsigned long flags, addr, tval, mask; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&ath724x_pci_lock, flags); + + switch (size) { + case 1: + addr = where & ~3; + mask = 0xff000000 >> ((where % 4) * 8); + tval = reg_read(ATH724X_PCI_DEV_BASE + addr); + tval = tval & ~mask; + *value = (tval >> ((4 - (where % 4))*8)); + break; + case 2: + addr = where & ~3; + mask = 0xffff0000 >> ((where % 4)*8); + tval = reg_read(ATH724X_PCI_DEV_BASE + addr); + tval = tval & ~mask; + *value = (tval >> ((4 - (where % 4))*8)); + break; + case 4: + *value = reg_read(ATH724X_PCI_DEV_BASE + where); + break; + default: + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t value) +{ + unsigned long flags, tval, addr, mask; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&ath724x_pci_lock, flags); + + switch (size) { + case 1: + addr = (ATH724X_PCI_DEV_BASE + where) & ~3; + mask = 0xff000000 >> ((where % 4)*8); + tval = reg_read(addr); + tval = tval & ~mask; + tval |= (value << ((4 - (where % 4))*8)) & mask; + reg_write(addr, tval); + break; + case 2: + addr = (ATH724X_PCI_DEV_BASE + where) & ~3; + mask = 0xffff0000 >> ((where % 4)*8); + tval = reg_read(addr); + tval = tval & ~mask; + tval |= (value << ((4 - (where % 4))*8)) & mask; + reg_write(addr, tval); + break; + case 4: + reg_write((ATH724X_PCI_DEV_BASE + where), value); + break; + default: + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops ath724x_pci_ops = { + .read = ath724x_pci_read, + .write = ath724x_pci_write, +}; + +static struct resource ath724x_io_resource = { + .name = "PCI IO space", + .start = 0, + .end = 0, + .flags = IORESOURCE_IO, +}; + +static struct resource ath724x_mem_resource = { + .name = "PCI memory space", + .start = ATH724X_PCI_MEM_BASE, + .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller ath724x_pci_controller = { + .pci_ops = &ath724x_pci_ops, + .io_resource = &ath724x_io_resource, + .mem_resource = &ath724x_mem_resource, +}; + +void ath724x_pci_add_data(struct ath724x_pci_data *data, int size) +{ + pci_data = data; + pci_data_size = size; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) +{ + unsigned int devfn = dev->devfn; + int irq = -1; + + if (devfn > pci_data_size - 1) + return irq; + + irq = pci_data[devfn].irq; + + return irq; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + unsigned int devfn = dev->devfn; + + if (devfn > pci_data_size - 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + dev->dev.platform_data = pci_data[devfn].pdata; + + return PCIBIOS_SUCCESSFUL; +} + +static int __init ath724x_pcibios_init(void) +{ + register_pci_controller(&ath724x_pci_controller); + + return PCIBIOS_SUCCESSFUL; +} + +arch_initcall(ath724x_pcibios_init); -- cgit v1.2.3-70-g09d2 From 04712f3ff6e3a42ef658b55b0f99478f4f0682e3 Mon Sep 17 00:00:00 2001 From: Maxime Bizon Date: Fri, 4 Nov 2011 19:09:35 +0100 Subject: MIPS: BCM63XX: Add support for bcm6368 CPU. Signed-off-by: Maxime Bizon Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2892/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/Kconfig | 4 + arch/mips/bcm63xx/clk.c | 70 +++++++++++++- arch/mips/bcm63xx/cpu.c | 79 ++++++++++++---- arch/mips/bcm63xx/dev-uart.c | 2 +- arch/mips/bcm63xx/irq.c | 24 ++++- arch/mips/bcm63xx/prom.c | 7 +- arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 99 ++++++++++++++++++++ arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 + arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 109 +++++++++++++++++++++- arch/mips/include/asm/mach-bcm63xx/ioremap.h | 4 + arch/mips/pci/pci-bcm63xx.c | 4 +- 11 files changed, 377 insertions(+), 27 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index fb177d6df06..6b1b9ad8d85 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -20,6 +20,10 @@ config BCM63XX_CPU_6348 config BCM63XX_CPU_6358 bool "support 6358 CPU" select HW_HAS_PCI + +config BCM63XX_CPU_6368 + bool "support 6368 CPU" + select HW_HAS_PCI endmenu source "arch/mips/bcm63xx/boards/Kconfig" diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index 2c68ee9ccee..9d57c71b7b5 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -112,6 +113,34 @@ static struct clk clk_ephy = { .set = ephy_set, }; +/* + * Ethernet switch clock + */ +static void enetsw_set(struct clk *clk, int enable) +{ + if (!BCMCPU_IS_6368()) + return; + bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN | + CKCTL_6368_SWPKT_USB_EN | + CKCTL_6368_SWPKT_SAR_EN, enable); + if (enable) { + u32 val; + + /* reset switch core afer clock change */ + val = bcm_perf_readl(PERF_SOFTRESET_6368_REG); + val &= ~SOFTRESET_6368_ENETSW_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + msleep(10); + val |= SOFTRESET_6368_ENETSW_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + msleep(10); + } +} + +static struct clk clk_enetsw = { + .set = enetsw_set, +}; + /* * PCM clock */ @@ -131,9 +160,10 @@ static struct clk clk_pcm = { */ static void usbh_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6348()) - return; - bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + if (BCMCPU_IS_6348()) + bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + else if (BCMCPU_IS_6368()) + bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable); } static struct clk clk_usbh = { @@ -161,6 +191,36 @@ static struct clk clk_spi = { .set = spi_set, }; +/* + * XTM clock + */ +static void xtm_set(struct clk *clk, int enable) +{ + if (!BCMCPU_IS_6368()) + return; + + bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN | + CKCTL_6368_SWPKT_SAR_EN, enable); + + if (enable) { + u32 val; + + /* reset sar core afer clock change */ + val = bcm_perf_readl(PERF_SOFTRESET_6368_REG); + val &= ~SOFTRESET_6368_SAR_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + mdelay(1); + val |= SOFTRESET_6368_SAR_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6368_REG); + mdelay(1); + } +} + + +static struct clk clk_xtm = { + .set = xtm_set, +}; + /* * Internal peripheral clock */ @@ -204,12 +264,16 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_enet0; if (!strcmp(id, "enet1")) return &clk_enet1; + if (!strcmp(id, "enetsw")) + return &clk_enetsw; if (!strcmp(id, "ephy")) return &clk_ephy; if (!strcmp(id, "usbh")) return &clk_usbh; if (!strcmp(id, "spi")) return &clk_spi; + if (!strcmp(id, "xtm")) + return &clk_xtm; if (!strcmp(id, "periph")) return &clk_periph; if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 8bd5133eafd..80941687b9d 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -63,6 +63,15 @@ static const int bcm6358_irqs[] = { }; +static const unsigned long bcm6368_regs_base[] = { + __GEN_CPU_REGS_TABLE(6368) +}; + +static const int bcm6368_irqs[] = { + __GEN_CPU_IRQ_TABLE(6368) + +}; + u16 __bcm63xx_get_cpu_id(void) { return bcm63xx_cpu_id; @@ -89,20 +98,19 @@ unsigned int bcm63xx_get_memory_size(void) static unsigned int detect_cpu_clock(void) { - unsigned int tmp, n1 = 0, n2 = 0, m1 = 0; - - /* BCM6338 has a fixed 240 Mhz frequency */ - if (BCMCPU_IS_6338()) + switch (bcm63xx_get_cpu_id()) { + case BCM6338_CPU_ID: + /* BCM6338 has a fixed 240 Mhz frequency */ return 240000000; - /* BCM6345 has a fixed 140Mhz frequency */ - if (BCMCPU_IS_6345()) + case BCM6345_CPU_ID: + /* BCM6345 has a fixed 140Mhz frequency */ return 140000000; - /* - * frequency depends on PLL configuration: - */ - if (BCMCPU_IS_6348()) { + case BCM6348_CPU_ID: + { + unsigned int tmp, n1, n2, m1; + /* 16MHz * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) */ tmp = bcm_perf_readl(PERF_MIPSPLLCTL_REG); n1 = (tmp & MIPSPLLCTL_N1_MASK) >> MIPSPLLCTL_N1_SHIFT; @@ -111,17 +119,47 @@ static unsigned int detect_cpu_clock(void) n1 += 1; n2 += 2; m1 += 1; + return (16 * 1000000 * n1 * n2) / m1; } - if (BCMCPU_IS_6358()) { + case BCM6358_CPU_ID: + { + unsigned int tmp, n1, n2, m1; + /* 16MHz * N1 * N2 / M1_CPU */ tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_REG); n1 = (tmp & DMIPSPLLCFG_N1_MASK) >> DMIPSPLLCFG_N1_SHIFT; n2 = (tmp & DMIPSPLLCFG_N2_MASK) >> DMIPSPLLCFG_N2_SHIFT; m1 = (tmp & DMIPSPLLCFG_M1_MASK) >> DMIPSPLLCFG_M1_SHIFT; + return (16 * 1000000 * n1 * n2) / m1; } - return (16 * 1000000 * n1 * n2) / m1; + case BCM6368_CPU_ID: + { + unsigned int tmp, p1, p2, ndiv, m1; + + /* (64MHz / P1) * P2 * NDIV / M1_CPU */ + tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_6368_REG); + + p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> + DMIPSPLLCFG_6368_P1_SHIFT; + + p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> + DMIPSPLLCFG_6368_P2_SHIFT; + + ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >> + DMIPSPLLCFG_6368_NDIV_SHIFT; + + tmp = bcm_ddr_readl(DDR_DMIPSPLLDIV_6368_REG); + m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> + DMIPSPLLDIV_6368_MDIV_SHIFT; + + return (((64 * 1000000) / p1) * p2 * ndiv) / m1; + } + + default: + BUG(); + } } /* @@ -143,7 +181,7 @@ static unsigned int detect_memory_size(void) banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; } - if (BCMCPU_IS_6358()) { + if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { val = bcm_memc_readl(MEMC_CFG_REG); rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; @@ -188,9 +226,18 @@ void __init bcm63xx_cpu_init(void) bcm63xx_irqs = bcm6345_irqs; break; case CPU_BMIPS4350: - expected_cpu_id = BCM6358_CPU_ID; - bcm63xx_regs_base = bcm6358_regs_base; - bcm63xx_irqs = bcm6358_irqs; + switch (read_c0_prid() & 0xf0) { + case 0x10: + expected_cpu_id = BCM6358_CPU_ID; + bcm63xx_regs_base = bcm6358_regs_base; + bcm63xx_irqs = bcm6358_irqs; + break; + case 0x30: + expected_cpu_id = BCM6368_CPU_ID; + bcm63xx_regs_base = bcm6368_regs_base; + bcm63xx_irqs = bcm6368_irqs; + break; + } break; } diff --git a/arch/mips/bcm63xx/dev-uart.c b/arch/mips/bcm63xx/dev-uart.c index c2963da0253..d6e42c60832 100644 --- a/arch/mips/bcm63xx/dev-uart.c +++ b/arch/mips/bcm63xx/dev-uart.c @@ -54,7 +54,7 @@ int __init bcm63xx_uart_register(unsigned int id) if (id >= ARRAY_SIZE(bcm63xx_uart_devices)) return -ENODEV; - if (id == 1 && !BCMCPU_IS_6358()) + if (id == 1 && (!BCMCPU_IS_6358() && !BCMCPU_IS_6368())) return -ENODEV; if (id == 0) { diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index 9f538846b3f..9a216a451d9 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -71,6 +71,17 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358 #define ext_irq_cfg_reg2 0 #endif +#ifdef CONFIG_BCM63XX_CPU_6368 +#define irq_stat_reg PERF_IRQSTAT_6368_REG +#define irq_mask_reg PERF_IRQMASK_6368_REG +#define irq_bits 64 +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE) +#define ext_irq_count 6 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6368 +#define ext_irq_cfg_reg2 PERF_EXTIRQ_CFG_REG2_6368 +#endif #if irq_bits == 32 #define dispatch_internal __dispatch_internal @@ -134,6 +145,17 @@ static void bcm63xx_init_irq(void) ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; break; + case BCM6368_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6368_REG; + irq_mask_addr += PERF_IRQMASK_6368_REG; + irq_bits = 64; + ext_irq_count = 6; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368; + ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368; + break; default: BUG(); } @@ -406,7 +428,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); } - if (BCMCPU_IS_6338() || BCMCPU_IS_6358()) { + if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) { if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE(irq); else diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index be252efa075..99d7f405cbe 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -32,9 +32,12 @@ void __init prom_init(void) mask = CKCTL_6345_ALL_SAFE_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_ALL_SAFE_EN; - else - /* BCMCPU_IS_6358() */ + else if (BCMCPU_IS_6358()) mask = CKCTL_6358_ALL_SAFE_EN; + else if (BCMCPU_IS_6368()) + mask = CKCTL_6368_ALL_SAFE_EN; + else + mask = 0; reg = bcm_perf_readl(PERF_CKCTL_REG); reg &= ~mask; diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 46f03322e2c..23403a32c15 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -13,6 +13,7 @@ #define BCM6345_CPU_ID 0x6345 #define BCM6348_CPU_ID 0x6348 #define BCM6358_CPU_ID 0x6358 +#define BCM6368_CPU_ID 0x6368 void __init bcm63xx_cpu_init(void); u16 __bcm63xx_get_cpu_id(void); @@ -71,6 +72,19 @@ unsigned int bcm63xx_get_cpu_freq(void); # define BCMCPU_IS_6358() (0) #endif +#ifdef CONFIG_BCM63XX_CPU_6368 +# ifdef bcm63xx_get_cpu_id +# undef bcm63xx_get_cpu_id +# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id() +# define BCMCPU_RUNTIME_DETECT +# else +# define bcm63xx_get_cpu_id() BCM6368_CPU_ID +# endif +# define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID) +#else +# define BCMCPU_IS_6368() (0) +#endif + #ifndef bcm63xx_get_cpu_id #error "No CPU support configured" #endif @@ -307,6 +321,47 @@ enum bcm63xx_regs_set { #define BCM_6358_PCMDMAS_BASE (0xfffe1a00) +/* + * 6368 register sets base address + */ +#define BCM_6368_DSL_LMEM_BASE (0xdeadbeef) +#define BCM_6368_PERF_BASE (0xb0000000) +#define BCM_6368_TIMER_BASE (0xb0000040) +#define BCM_6368_WDT_BASE (0xb000005c) +#define BCM_6368_UART0_BASE (0xb0000100) +#define BCM_6368_UART1_BASE (0xb0000120) +#define BCM_6368_GPIO_BASE (0xb0000080) +#define BCM_6368_SPI_BASE (0xdeadbeef) +#define BCM_6368_SPI2_BASE (0xb0000800) +#define BCM_6368_UDC0_BASE (0xdeadbeef) +#define BCM_6368_OHCI0_BASE (0xb0001600) +#define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef) +#define BCM_6368_USBH_PRIV_BASE (0xb0001700) +#define BCM_6368_MPI_BASE (0xb0001000) +#define BCM_6368_PCMCIA_BASE (0xb0001054) +#define BCM_6368_SDRAM_REGS_BASE (0xdeadbeef) +#define BCM_6368_M2M_BASE (0xdeadbeef) +#define BCM_6368_DSL_BASE (0xdeadbeef) +#define BCM_6368_ENET0_BASE (0xdeadbeef) +#define BCM_6368_ENET1_BASE (0xdeadbeef) +#define BCM_6368_ENETDMA_BASE (0xb0006800) +#define BCM_6368_ENETDMAC_BASE (0xb0006a00) +#define BCM_6368_ENETDMAS_BASE (0xb0006c00) +#define BCM_6368_ENETSW_BASE (0xb0f00000) +#define BCM_6368_EHCI0_BASE (0xb0001500) +#define BCM_6368_SDRAM_BASE (0xdeadbeef) +#define BCM_6368_MEMC_BASE (0xb0001200) +#define BCM_6368_DDR_BASE (0xb0001280) +#define BCM_6368_ATM_BASE (0xdeadbeef) +#define BCM_6368_XTM_BASE (0xb0001800) +#define BCM_6368_XTMDMA_BASE (0xb0005000) +#define BCM_6368_XTMDMAC_BASE (0xb0005200) +#define BCM_6368_XTMDMAS_BASE (0xb0005400) +#define BCM_6368_PCM_BASE (0xb0004000) +#define BCM_6368_PCMDMA_BASE (0xb0005800) +#define BCM_6368_PCMDMAC_BASE (0xb0005a00) +#define BCM_6368_PCMDMAS_BASE (0xb0005c00) + extern const unsigned long *bcm63xx_regs_base; @@ -410,6 +465,9 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) #ifdef CONFIG_BCM63XX_CPU_6358 __GEN_RSET(6358) #endif +#ifdef CONFIG_BCM63XX_CPU_6368 + __GEN_RSET(6368) +#endif #endif /* unreached */ return 0; @@ -574,6 +632,47 @@ enum bcm63xx_irq { #define BCM_6358_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27) #define BCM_6358_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28) +/* + * 6368 irqs + */ +#define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) + +#define BCM_6368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6368_UART0_IRQ (IRQ_INTERNAL_BASE + 2) +#define BCM_6368_UART1_IRQ (IRQ_INTERNAL_BASE + 3) +#define BCM_6368_DSL_IRQ (IRQ_INTERNAL_BASE + 4) +#define BCM_6368_ENET0_IRQ 0 +#define BCM_6368_ENET1_IRQ 0 +#define BCM_6368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 15) +#define BCM_6368_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5) +#define BCM_6368_EHCI0_IRQ (IRQ_INTERNAL_BASE + 7) +#define BCM_6368_PCMCIA_IRQ 0 +#define BCM_6368_ENET0_RXDMA_IRQ 0 +#define BCM_6368_ENET0_TXDMA_IRQ 0 +#define BCM_6368_ENET1_RXDMA_IRQ 0 +#define BCM_6368_ENET1_TXDMA_IRQ 0 +#define BCM_6368_PCI_IRQ (IRQ_INTERNAL_BASE + 13) +#define BCM_6368_ATM_IRQ 0 +#define BCM_6368_ENETSW_RXDMA0_IRQ (BCM_6368_HIGH_IRQ_BASE + 0) +#define BCM_6368_ENETSW_RXDMA1_IRQ (BCM_6368_HIGH_IRQ_BASE + 1) +#define BCM_6368_ENETSW_RXDMA2_IRQ (BCM_6368_HIGH_IRQ_BASE + 2) +#define BCM_6368_ENETSW_RXDMA3_IRQ (BCM_6368_HIGH_IRQ_BASE + 3) +#define BCM_6368_ENETSW_TXDMA0_IRQ (BCM_6368_HIGH_IRQ_BASE + 4) +#define BCM_6368_ENETSW_TXDMA1_IRQ (BCM_6368_HIGH_IRQ_BASE + 5) +#define BCM_6368_ENETSW_TXDMA2_IRQ (BCM_6368_HIGH_IRQ_BASE + 6) +#define BCM_6368_ENETSW_TXDMA3_IRQ (BCM_6368_HIGH_IRQ_BASE + 7) +#define BCM_6368_XTM_IRQ (IRQ_INTERNAL_BASE + 11) +#define BCM_6368_XTM_DMA0_IRQ (BCM_6368_HIGH_IRQ_BASE + 8) + +#define BCM_6368_PCM_DMA0_IRQ (BCM_6368_HIGH_IRQ_BASE + 30) +#define BCM_6368_PCM_DMA1_IRQ (BCM_6368_HIGH_IRQ_BASE + 31) +#define BCM_6368_EXT_IRQ0 (IRQ_INTERNAL_BASE + 20) +#define BCM_6368_EXT_IRQ1 (IRQ_INTERNAL_BASE + 21) +#define BCM_6368_EXT_IRQ2 (IRQ_INTERNAL_BASE + 22) +#define BCM_6368_EXT_IRQ3 (IRQ_INTERNAL_BASE + 23) +#define BCM_6368_EXT_IRQ4 (IRQ_INTERNAL_BASE + 24) +#define BCM_6368_EXT_IRQ5 (IRQ_INTERNAL_BASE + 25) + extern const int *bcm63xx_irqs; #define __GEN_CPU_IRQ_TABLE(__cpu) \ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h index 3999ec0aa7f..3d5de96d403 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h @@ -14,6 +14,8 @@ static inline unsigned long bcm63xx_gpio_count(void) return 8; case BCM6345_CPU_ID: return 16; + case BCM6368_CPU_ID: + return 38; case BCM6348_CPU_ID: default: return 37; diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 2b3a2d6bdb0..50057507c4e 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -83,6 +83,37 @@ CKCTL_6358_USBSU_EN | \ CKCTL_6358_EPHY_EN) +#define CKCTL_6368_VDSL_QPROC_EN (1 << 2) +#define CKCTL_6368_VDSL_AFE_EN (1 << 3) +#define CKCTL_6368_VDSL_BONDING_EN (1 << 4) +#define CKCTL_6368_VDSL_EN (1 << 5) +#define CKCTL_6368_PHYMIPS_EN (1 << 6) +#define CKCTL_6368_SWPKT_USB_EN (1 << 7) +#define CKCTL_6368_SWPKT_SAR_EN (1 << 8) +#define CKCTL_6368_SPI_CLK_EN (1 << 9) +#define CKCTL_6368_USBD_CLK_EN (1 << 10) +#define CKCTL_6368_SAR_CLK_EN (1 << 11) +#define CKCTL_6368_ROBOSW_CLK_EN (1 << 12) +#define CKCTL_6368_UTOPIA_CLK_EN (1 << 13) +#define CKCTL_6368_PCM_CLK_EN (1 << 14) +#define CKCTL_6368_USBH_CLK_EN (1 << 15) +#define CKCTL_6368_DISABLE_GLESS_EN (1 << 16) +#define CKCTL_6368_NAND_CLK_EN (1 << 17) +#define CKCTL_6368_IPSEC_CLK_EN (1 << 17) + +#define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \ + CKCTL_6368_SWPKT_SAR_EN | \ + CKCTL_6368_SPI_CLK_EN | \ + CKCTL_6368_USBD_CLK_EN | \ + CKCTL_6368_SAR_CLK_EN | \ + CKCTL_6368_ROBOSW_CLK_EN | \ + CKCTL_6368_UTOPIA_CLK_EN | \ + CKCTL_6368_PCM_CLK_EN | \ + CKCTL_6368_USBH_CLK_EN | \ + CKCTL_6368_DISABLE_GLESS_EN | \ + CKCTL_6368_NAND_CLK_EN | \ + CKCTL_6368_IPSEC_CLK_EN) + /* System PLL Control register */ #define PERF_SYS_PLL_CTL_REG 0x8 #define SYS_PLL_SOFT_RESET 0x1 @@ -92,17 +123,22 @@ #define PERF_IRQMASK_6345_REG 0xc #define PERF_IRQMASK_6348_REG 0xc #define PERF_IRQMASK_6358_REG 0xc +#define PERF_IRQMASK_6368_REG 0x20 /* Interrupt Status register */ #define PERF_IRQSTAT_6338_REG 0x10 #define PERF_IRQSTAT_6345_REG 0x10 #define PERF_IRQSTAT_6348_REG 0x10 #define PERF_IRQSTAT_6358_REG 0x10 +#define PERF_IRQSTAT_6368_REG 0x28 /* External Interrupt Configuration register */ #define PERF_EXTIRQ_CFG_REG_6338 0x14 #define PERF_EXTIRQ_CFG_REG_6348 0x14 #define PERF_EXTIRQ_CFG_REG_6358 0x14 +#define PERF_EXTIRQ_CFG_REG_6368 0x18 + +#define PERF_EXTIRQ_CFG_REG2_6368 0x1c /* for 6348 only */ #define EXTIRQ_CFG_SENSE_6348(x) (1 << (x)) @@ -126,6 +162,7 @@ /* Soft Reset register */ #define PERF_SOFTRESET_REG 0x28 +#define PERF_SOFTRESET_6368_REG 0x10 #define SOFTRESET_6338_SPI_MASK (1 << 0) #define SOFTRESET_6338_ENET_MASK (1 << 2) @@ -166,6 +203,15 @@ SOFTRESET_6348_ACLC_MASK | \ SOFTRESET_6348_ADSLMIPSPLL_MASK) +#define SOFTRESET_6368_SPI_MASK (1 << 0) +#define SOFTRESET_6368_MPI_MASK (1 << 3) +#define SOFTRESET_6368_EPHY_MASK (1 << 6) +#define SOFTRESET_6368_SAR_MASK (1 << 7) +#define SOFTRESET_6368_ENETSW_MASK (1 << 10) +#define SOFTRESET_6368_USBS_MASK (1 << 11) +#define SOFTRESET_6368_USBH_MASK (1 << 12) +#define SOFTRESET_6368_PCM_MASK (1 << 13) + /* MIPS PLL control register */ #define PERF_MIPSPLLCTL_REG 0x34 #define MIPSPLLCTL_N1_SHIFT 20 @@ -421,6 +467,44 @@ #define GPIO_MODE_6358_SERIAL_LED (1 << 10) #define GPIO_MODE_6358_UTOPIA (1 << 12) +#define GPIO_MODE_6368_ANALOG_AFE_0 (1 << 0) +#define GPIO_MODE_6368_ANALOG_AFE_1 (1 << 1) +#define GPIO_MODE_6368_SYS_IRQ (1 << 2) +#define GPIO_MODE_6368_SERIAL_LED_DATA (1 << 3) +#define GPIO_MODE_6368_SERIAL_LED_CLK (1 << 4) +#define GPIO_MODE_6368_INET_LED (1 << 5) +#define GPIO_MODE_6368_EPHY0_LED (1 << 6) +#define GPIO_MODE_6368_EPHY1_LED (1 << 7) +#define GPIO_MODE_6368_EPHY2_LED (1 << 8) +#define GPIO_MODE_6368_EPHY3_LED (1 << 9) +#define GPIO_MODE_6368_ROBOSW_LED_DAT (1 << 10) +#define GPIO_MODE_6368_ROBOSW_LED_CLK (1 << 11) +#define GPIO_MODE_6368_ROBOSW_LED0 (1 << 12) +#define GPIO_MODE_6368_ROBOSW_LED1 (1 << 13) +#define GPIO_MODE_6368_USBD_LED (1 << 14) +#define GPIO_MODE_6368_NTR_PULSE (1 << 15) +#define GPIO_MODE_6368_PCI_REQ1 (1 << 16) +#define GPIO_MODE_6368_PCI_GNT1 (1 << 17) +#define GPIO_MODE_6368_PCI_INTB (1 << 18) +#define GPIO_MODE_6368_PCI_REQ0 (1 << 19) +#define GPIO_MODE_6368_PCI_GNT0 (1 << 20) +#define GPIO_MODE_6368_PCMCIA_CD1 (1 << 22) +#define GPIO_MODE_6368_PCMCIA_CD2 (1 << 23) +#define GPIO_MODE_6368_PCMCIA_VS1 (1 << 24) +#define GPIO_MODE_6368_PCMCIA_VS2 (1 << 25) +#define GPIO_MODE_6368_EBI_CS2 (1 << 26) +#define GPIO_MODE_6368_EBI_CS3 (1 << 27) +#define GPIO_MODE_6368_SPI_SSN2 (1 << 28) +#define GPIO_MODE_6368_SPI_SSN3 (1 << 29) +#define GPIO_MODE_6368_SPI_SSN4 (1 << 30) +#define GPIO_MODE_6368_SPI_SSN5 (1 << 31) + + +#define GPIO_BASEMODE_6368_REG 0x38 +#define GPIO_BASEMODE_6368_UART2 0x1 +#define GPIO_BASEMODE_6368_GPIO 0x0 +#define GPIO_BASEMODE_6368_MASK 0x7 +/* those bits must be kept as read in gpio basemode register*/ /************************************************************************* * _REG relative to RSET_ENET @@ -631,7 +715,9 @@ * _REG relative to RSET_USBH_PRIV *************************************************************************/ -#define USBH_PRIV_SWAP_REG 0x0 +#define USBH_PRIV_SWAP_6358_REG 0x0 +#define USBH_PRIV_SWAP_6368_REG 0x1c + #define USBH_PRIV_SWAP_EHCI_ENDN_SHIFT 4 #define USBH_PRIV_SWAP_EHCI_ENDN_MASK (1 << USBH_PRIV_SWAP_EHCI_ENDN_SHIFT) #define USBH_PRIV_SWAP_EHCI_DATA_SHIFT 3 @@ -641,7 +727,13 @@ #define USBH_PRIV_SWAP_OHCI_DATA_SHIFT 0 #define USBH_PRIV_SWAP_OHCI_DATA_MASK (1 << USBH_PRIV_SWAP_OHCI_DATA_SHIFT) -#define USBH_PRIV_TEST_REG 0x24 +#define USBH_PRIV_TEST_6358_REG 0x24 +#define USBH_PRIV_TEST_6368_REG 0x14 + +#define USBH_PRIV_SETUP_6368_REG 0x28 +#define USBH_PRIV_SETUP_IOC_SHIFT 4 +#define USBH_PRIV_SETUP_IOC_MASK (1 << USBH_PRIV_SETUP_IOC_SHIFT) + /************************************************************************* @@ -837,6 +929,19 @@ #define DMIPSPLLCFG_N2_SHIFT 29 #define DMIPSPLLCFG_N2_MASK (0x7 << DMIPSPLLCFG_N2_SHIFT) +#define DDR_DMIPSPLLCFG_6368_REG 0x20 +#define DMIPSPLLCFG_6368_P1_SHIFT 0 +#define DMIPSPLLCFG_6368_P1_MASK (0xf << DMIPSPLLCFG_6368_P1_SHIFT) +#define DMIPSPLLCFG_6368_P2_SHIFT 4 +#define DMIPSPLLCFG_6368_P2_MASK (0xf << DMIPSPLLCFG_6368_P2_SHIFT) +#define DMIPSPLLCFG_6368_NDIV_SHIFT 16 +#define DMIPSPLLCFG_6368_NDIV_MASK (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT) + +#define DDR_DMIPSPLLDIV_6368_REG 0x24 +#define DMIPSPLLDIV_6368_MDIV_SHIFT 0 +#define DMIPSPLLDIV_6368_MDIV_MASK (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT) + + /************************************************************************* * _REG relative to RSET_M2M *************************************************************************/ diff --git a/arch/mips/include/asm/mach-bcm63xx/ioremap.h b/arch/mips/include/asm/mach-bcm63xx/ioremap.h index e3fe04dc50b..ef94ba73646 100644 --- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h +++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h @@ -18,6 +18,10 @@ static inline int is_bcm63xx_internal_registers(phys_t offset) if (offset >= 0xfff00000) return 1; break; + case BCM6368_CPU_ID: + if (offset >= 0xb0000000 && offset < 0xb1000000) + return 1; + break; } return 0; } diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c index 82e0fde1dba..39eb7c417e2 100644 --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -99,7 +99,7 @@ static int __init bcm63xx_pci_init(void) unsigned int mem_size; u32 val; - if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358()) + if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368()) return -ENODEV; if (!bcm63xx_pci_enabled) @@ -159,7 +159,7 @@ static int __init bcm63xx_pci_init(void) /* setup PCI to local bus access, used by PCI device to target * local RAM while bus mastering */ bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); - if (BCMCPU_IS_6358()) + if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) val = MPI_SP0_REMAP_ENABLE_MASK; else val = 0; -- cgit v1.2.3-70-g09d2 From 8b5690f8847490c1e3ea47266819833a13621253 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 22 Nov 2011 14:38:03 +0000 Subject: MIPS: irq: Remove IRQF_DISABLED Since commit [e58aa3d2: genirq: Run irq handlers with interrupts disabled], We run all interrupt handlers with interrupts disabled and we even check and yell when an interrupt handler returns with interrupts enabled (see commit [b738a50a: genirq: Warn when handler enables interrupts]). So now this flag is a NOOP and can be removed. [ralf@linux-mips.org: Fixed up conflicts in arch/mips/alchemy/common/dbdma.c, arch/mips/cavium-octeon/smp.c and arch/mips/kernel/perf_event.c.] Signed-off-by: Yong Zhang To: linux-kernel@vger.kernel.org Cc: tglx@linutronix.de linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2835/ Signed-off-by: Ralf Baechle --- arch/mips/alchemy/common/dbdma.c | 3 +-- arch/mips/alchemy/common/time.c | 2 +- arch/mips/alchemy/devboards/db1200/platform.c | 4 ++-- arch/mips/dec/setup.c | 1 - arch/mips/include/asm/mach-generic/floppy.h | 2 +- arch/mips/include/asm/mach-jazz/floppy.h | 2 +- arch/mips/jazz/irq.c | 2 +- arch/mips/kernel/cevt-bcm1480.c | 2 +- arch/mips/kernel/cevt-ds1287.c | 2 +- arch/mips/kernel/cevt-gt641xx.c | 2 +- arch/mips/kernel/cevt-r4k.c | 2 +- arch/mips/kernel/cevt-sb1250.c | 2 +- arch/mips/kernel/cevt-txx9.c | 2 +- arch/mips/kernel/i8253.c | 2 +- arch/mips/kernel/rtlx.c | 1 - arch/mips/kernel/smtc.c | 2 +- arch/mips/lantiq/irq.c | 1 - arch/mips/loongson/common/cs5536/cs5536_mfgpt.c | 2 +- arch/mips/mti-malta/malta-int.c | 4 ++-- arch/mips/pci/ops-pmcmsp.c | 2 +- arch/mips/pci/ops-tx3927.c | 2 +- arch/mips/pci/pci-tx4927.c | 2 +- arch/mips/pci/pci-tx4938.c | 2 +- arch/mips/pci/pci-tx4939.c | 2 +- arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c | 2 +- arch/mips/pmc-sierra/msp71xx/msp_smp.c | 4 ++-- arch/mips/pnx8550/common/int.c | 4 ++-- arch/mips/pnx8550/common/time.c | 4 ++-- arch/mips/sgi-ip22/ip22-int.c | 10 +++++----- arch/mips/sgi-ip27/ip27-irq.c | 2 +- arch/mips/sgi-ip27/ip27-timer.c | 2 +- arch/mips/sgi-ip32/ip32-irq.c | 2 -- arch/mips/sni/irq.c | 2 +- arch/mips/sni/time.c | 2 +- arch/mips/txx9/generic/pci.c | 2 +- 35 files changed, 40 insertions(+), 46 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index 0e63ee487d6..9ba407b4fc9 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c @@ -1019,8 +1019,7 @@ static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable) dbdma_gptr->ddma_inten = 0xffff; au_sync(); - ret = request_irq(irq, dbdma_interrupt, IRQF_DISABLED, "dbdma", - (void *)dbdma_gptr); + ret = request_irq(irq, dbdma_interrupt, 0, "dbdma", (void *)dbdma_gptr); if (ret) printk(KERN_ERR "Cannot grab DBDMA interrupt!\n"); else { diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c index d5da6adbf63..146a5fa8036 100644 --- a/arch/mips/alchemy/common/time.c +++ b/arch/mips/alchemy/common/time.c @@ -92,7 +92,7 @@ static struct clock_event_device au1x_rtcmatch2_clockdev = { static struct irqaction au1x_rtcmatch2_irqaction = { .handler = au1x_rtcmatch2_irq, - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .name = "timer", .dev_id = &au1x_rtcmatch2_clockdev, }; diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c index c61867c93c4..78459c17c62 100644 --- a/arch/mips/alchemy/devboards/db1200/platform.c +++ b/arch/mips/alchemy/devboards/db1200/platform.c @@ -276,12 +276,12 @@ static int db1200_mmc_cd_setup(void *mmc_host, int en) if (en) { ret = request_irq(DB1200_SD0_INSERT_INT, db1200_mmc_cd, - IRQF_DISABLED, "sd_insert", mmc_host); + 0, "sd_insert", mmc_host); if (ret) goto out; ret = request_irq(DB1200_SD0_EJECT_INT, db1200_mmc_cd, - IRQF_DISABLED, "sd_eject", mmc_host); + 0, "sd_eject", mmc_host); if (ret) { free_irq(DB1200_SD0_INSERT_INT, mmc_host); goto out; diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index f7b7ba6d5c4..b874accd878 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -110,7 +110,6 @@ static struct irqaction fpuirq = { }; static struct irqaction busirq = { - .flags = IRQF_DISABLED, .name = "bus error", .flags = IRQF_NO_THREAD, }; diff --git a/arch/mips/include/asm/mach-generic/floppy.h b/arch/mips/include/asm/mach-generic/floppy.h index 001a8ce17c1..a38f4d43e5e 100644 --- a/arch/mips/include/asm/mach-generic/floppy.h +++ b/arch/mips/include/asm/mach-generic/floppy.h @@ -98,7 +98,7 @@ static inline void fd_disable_irq(void) static inline int fd_request_irq(void) { return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + 0, "floppy", NULL); } static inline void fd_free_irq(void) diff --git a/arch/mips/include/asm/mach-jazz/floppy.h b/arch/mips/include/asm/mach-jazz/floppy.h index 56e9ca6ae42..88b5acb7514 100644 --- a/arch/mips/include/asm/mach-jazz/floppy.h +++ b/arch/mips/include/asm/mach-jazz/floppy.h @@ -90,7 +90,7 @@ static inline void fd_disable_irq(void) static inline int fd_request_irq(void) { return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + 0, "floppy", NULL); } static inline void fd_free_irq(void) diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index ca9bd206914..0f4a14752a7 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -133,7 +133,7 @@ static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id) static struct irqaction r4030_timer_irqaction = { .handler = r4030_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .name = "R4030 timer", }; diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 36c3898b76d..69bbfae183b 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -145,7 +145,7 @@ void __cpuinit sb1480_clockevent_init(void) bcm1480_unmask_irq(cpu, irq); action->handler = sibyte_counter_handler; - action->flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER; + action->flags = IRQF_PERCPU | IRQF_TIMER; action->name = name; action->dev_id = cd; diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index 939157e397b..ed648cb5a69 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -108,7 +108,7 @@ static irqreturn_t ds1287_interrupt(int irq, void *dev_id) static struct irqaction ds1287_irqaction = { .handler = ds1287_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "ds1287", }; diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index 339f3639b90..831b47585b7 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -114,7 +114,7 @@ static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id) static struct irqaction gt641xx_timer0_irqaction = { .handler = gt641xx_timer0_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "gt641xx_timer0", }; diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index e2d8e199be3..51095dd9599 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -84,7 +84,7 @@ out: struct irqaction c0_compare_irqaction = { .handler = c0_compare_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "timer", }; diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index 590c54f28a8..e73439fd685 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -144,7 +144,7 @@ void __cpuinit sb1250_clockevent_init(void) sb1250_unmask_irq(cpu, irq); action->handler = sibyte_counter_handler; - action->flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER; + action->flags = IRQF_PERCPU | IRQF_TIMER; action->name = name; action->dev_id = cd; diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index f0ab92a1b05..e5c30b1d086 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c @@ -146,7 +146,7 @@ static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id) static struct irqaction txx9tmr_irq = { .handler = txx9tmr_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "txx9tmr", .dev_id = &txx9_clock_event_device, }; diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c index 7047bff35ea..c5bc344fc74 100644 --- a/arch/mips/kernel/i8253.c +++ b/arch/mips/kernel/i8253.c @@ -19,7 +19,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) static struct irqaction irq0 = { .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, + .flags = IRQF_NOBALANCING | IRQF_TIMER, .name = "timer" }; diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 933166f44a6..a9d801dec6b 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -473,7 +473,6 @@ static const struct file_operations rtlx_fops = { static struct irqaction rtlx_irq = { .handler = rtlx_interrupt, - .flags = IRQF_DISABLED, .name = "RTLX", }; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index f0895e70e28..17c9412b5f4 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -1130,7 +1130,7 @@ static void ipi_irq_dispatch(void) static struct irqaction irq_ipi = { .handler = ipi_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "SMTC_IPI" }; diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index f9737bb3c5a..3c56179b4ca 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -240,7 +240,6 @@ out: static struct irqaction cascade = { .handler = no_action, - .flags = IRQF_DISABLED, .name = "cascade", }; diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c index 0cb1b9760e3..5d1f48fa1a5 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c @@ -111,7 +111,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) static struct irqaction irq5 = { .handler = timer_interrupt, - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, + .flags = IRQF_NOBALANCING | IRQF_TIMER, .name = "timer" }; diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index d53ff91b277..a588b5cef8d 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -322,13 +322,13 @@ static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) static struct irqaction irq_resched = { .handler = ipi_resched_interrupt, - .flags = IRQF_DISABLED|IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "IPI_resched" }; static struct irqaction irq_call = { .handler = ipi_call_interrupt, - .flags = IRQF_DISABLED|IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "IPI_call" }; #endif /* CONFIG_MIPS_MT_SMP */ diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 8fbfbf2b931..389bf669d56 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -405,7 +405,7 @@ int msp_pcibios_config_access(unsigned char access_type, if (pciirqflag == 0) { ret = request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */ bpci_interrupt, - IRQF_SHARED | IRQF_DISABLED, + IRQF_SHARED, "PMC MSP PCI Host", preg); if (ret != 0) diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index 6a3bdb5ffa8..02d64f77e96 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c @@ -225,7 +225,7 @@ void __init tx3927_setup_pcierr_irq(void) { if (request_irq(TXX9_IRQ_BASE + TX3927_IR_PCI, tx3927_pcierr_interrupt, - IRQF_DISABLED, "PCI error", + 0, "PCI error", (void *)TX3927_PCIC_REG)) printk(KERN_WARNING "Failed to request irq for PCIERR\n"); } diff --git a/arch/mips/pci/pci-tx4927.c b/arch/mips/pci/pci-tx4927.c index a5807406a7f..a032ae0a533 100644 --- a/arch/mips/pci/pci-tx4927.c +++ b/arch/mips/pci/pci-tx4927.c @@ -85,7 +85,7 @@ void __init tx4927_setup_pcierr_irq(void) { if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR, tx4927_pcierr_interrupt, - IRQF_DISABLED, "PCI error", + 0, "PCI error", (void *)TX4927_PCIC_REG)) printk(KERN_WARNING "Failed to request irq for PCIERR\n"); } diff --git a/arch/mips/pci/pci-tx4938.c b/arch/mips/pci/pci-tx4938.c index 20e45f30b2e..141bba56248 100644 --- a/arch/mips/pci/pci-tx4938.c +++ b/arch/mips/pci/pci-tx4938.c @@ -136,7 +136,7 @@ void __init tx4938_setup_pcierr_irq(void) { if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR, tx4927_pcierr_interrupt, - IRQF_DISABLED, "PCI error", + 0, "PCI error", (void *)TX4927_PCIC_REG)) printk(KERN_WARNING "Failed to request irq for PCIERR\n"); } diff --git a/arch/mips/pci/pci-tx4939.c b/arch/mips/pci/pci-tx4939.c index 9ef840693ba..c10fbf2a19d 100644 --- a/arch/mips/pci/pci-tx4939.c +++ b/arch/mips/pci/pci-tx4939.c @@ -101,7 +101,7 @@ void __init tx4939_setup_pcierr_irq(void) { if (request_irq(TXX9_IRQ_BASE + TX4939_IR_PCIERR, tx4927_pcierr_interrupt, - IRQF_DISABLED, "PCI error", + 0, "PCI error", (void *)TX4939_PCIC_REG)) pr_warning("Failed to request irq for PCIERR\n"); } diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c index c841f083a7f..bb57ed9ea2b 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c @@ -149,7 +149,7 @@ static int msp_hwbutton_register(struct hwbutton_interrupt *hirq) CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq); *CIC_EXT_CFG_REG = cic_ext; - return request_irq(hirq->irq, hwbutton_handler, IRQF_DISABLED, + return request_irq(hirq->irq, hwbutton_handler, 0, hirq->name, hirq); } diff --git a/arch/mips/pmc-sierra/msp71xx/msp_smp.c b/arch/mips/pmc-sierra/msp71xx/msp_smp.c index bec17901ff0..10170580a2d 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_smp.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_smp.c @@ -51,13 +51,13 @@ static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) static struct irqaction irq_resched = { .handler = ipi_resched_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "IPI_resched" }; static struct irqaction irq_call = { .handler = ipi_call_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU, + .flags = IRQF_PERCPU, .name = "IPI_call" }; diff --git a/arch/mips/pnx8550/common/int.c b/arch/mips/pnx8550/common/int.c index 1ebe22bdadc..ec684b8c3f7 100644 --- a/arch/mips/pnx8550/common/int.c +++ b/arch/mips/pnx8550/common/int.c @@ -167,13 +167,13 @@ static struct irq_chip level_irq_type = { static struct irqaction gic_action = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_NO_THREAD, + .flags = IRQF_NO_THREAD, .name = "GIC", }; static struct irqaction timer_action = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .name = "Timer", }; diff --git a/arch/mips/pnx8550/common/time.c b/arch/mips/pnx8550/common/time.c index 8836c6203df..831d6b369e9 100644 --- a/arch/mips/pnx8550/common/time.c +++ b/arch/mips/pnx8550/common/time.c @@ -59,7 +59,7 @@ static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) static struct irqaction pnx8xxx_timer_irq = { .handler = pnx8xxx_timer_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "pnx8xxx_timer", }; @@ -72,7 +72,7 @@ static irqreturn_t monotonic_interrupt(int irq, void *dev_id) static struct irqaction monotonic_irqaction = { .handler = monotonic_interrupt, - .flags = IRQF_DISABLED | IRQF_TIMER, + .flags = IRQF_TIMER, .name = "Monotonic timer", }; diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index f72c336ea27..3f2b7633f94 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -155,32 +155,32 @@ static void __irq_entry indy_buserror_irq(void) static struct irqaction local0_cascade = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_NO_THREAD, + .flags = IRQF_NO_THREAD, .name = "local0 cascade", }; static struct irqaction local1_cascade = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_NO_THREAD, + .flags = IRQF_NO_THREAD, .name = "local1 cascade", }; static struct irqaction buserr = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_NO_THREAD, + .flags = IRQF_NO_THREAD, .name = "Bus Error", }; static struct irqaction map0_cascade = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_NO_THREAD, + .flags = IRQF_NO_THREAD, .name = "mapable0 cascade", }; #ifdef USE_LIO3_IRQ static struct irqaction map1_cascade = { .handler = no_action, - .flags = IRQF_DISABLED | IRQF_NO_THREAD, + .flags = IRQF_NO_THREAD, .name = "mapable1 cascade", }; #define SGI_INTERRUPTS SGINT_END diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index f90dce315e0..888eac1b831 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -116,7 +116,7 @@ static int ms1bit(unsigned long x) } /* - * This code is unnecessarily complex, because we do IRQF_DISABLED + * This code is unnecessarily complex, because we do * intr enabling. Basically, once we grab the set of intrs we need * to service, we must mask _all_ these interrupts; firstly, to make * sure the same intr does not intr again, causing recursion that diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index ef74f3267f9..13cfeab5052 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -91,7 +91,7 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) struct irqaction hub_rt_irqaction = { .handler = hub_rt_counter_handler, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "hub-rt", }; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index c65ea76d56c..a092860d519 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -113,13 +113,11 @@ extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id); static struct irqaction memerr_irq = { .handler = crime_memerr_intr, - .flags = IRQF_DISABLED, .name = "CRIME memory error", }; static struct irqaction cpuerr_irq = { .handler = crime_cpuerr_intr, - .flags = IRQF_DISABLED, .name = "CRIME CPU error", }; diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c index e8e72bb3a9a..5a4ec75382e 100644 --- a/arch/mips/sni/irq.c +++ b/arch/mips/sni/irq.c @@ -42,7 +42,7 @@ static irqreturn_t sni_isa_irq_handler(int dummy, void *p) struct irqaction sni_isa_irq = { .handler = sni_isa_irq_handler, .name = "ISA", - .flags = IRQF_SHARED | IRQF_DISABLED + .flags = IRQF_SHARED }; /* diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index ec0be14996a..494c9e7847a 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -68,7 +68,7 @@ static irqreturn_t a20r_interrupt(int irq, void *dev_id) static struct irqaction a20r_irqaction = { .handler = a20r_interrupt, - .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "a20r-timer", }; diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c index 85a87de17eb..682efb0c108 100644 --- a/arch/mips/txx9/generic/pci.c +++ b/arch/mips/txx9/generic/pci.c @@ -262,7 +262,7 @@ txx9_i8259_irq_setup(int irq) int err; init_i8259_irqs(); - err = request_irq(irq, &i8259_interrupt, IRQF_DISABLED|IRQF_SHARED, + err = request_irq(irq, &i8259_interrupt, IRQF_SHARED, "cascade(i8259)", (void *)(long)irq); if (!err) printk(KERN_INFO "PCI-ISA bridge PIC (irq %d)\n", irq); -- cgit v1.2.3-70-g09d2 From f32671a867523e830887983891d99d3ac4842ccf Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Tue, 23 Aug 2011 13:36:10 +0530 Subject: MIPS: Netlogic: Add basic MSI support for XLR/XLS Add basic support for MSI. Signed-off-by: Ganesan Ramalingam Signed-off-by: Jayachandran C To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2730/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/netlogic/xlr/msidef.h | 84 +++++++++++++++++++++++++++++ arch/mips/netlogic/xlr/irq.c | 5 ++ arch/mips/pci/pci-xlr.c | 51 +++++++++++++++++- 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 arch/mips/include/asm/netlogic/xlr/msidef.h (limited to 'arch/mips/pci') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d46f1da18a3..04ac89c6ab6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -776,6 +776,7 @@ config NLM_XLR_BOARD select CEVT_R4K select CSRC_R4K select IRQ_CPU + select ARCH_SUPPORTS_MSI select ZONE_DMA if 64BIT select SYNC_R4K select SYS_HAS_EARLY_PRINTK diff --git a/arch/mips/include/asm/netlogic/xlr/msidef.h b/arch/mips/include/asm/netlogic/xlr/msidef.h new file mode 100644 index 00000000000..7e39d40be4f --- /dev/null +++ b/arch/mips/include/asm/netlogic/xlr/msidef.h @@ -0,0 +1,84 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ASM_RMI_MSIDEF_H +#define ASM_RMI_MSIDEF_H + +/* + * Constants for Intel APIC based MSI messages. + * Adapted for the RMI XLR using identical defines + */ + +/* + * Shifts for MSI data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR_MASK 0x000000ff +#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & \ + MSI_DATA_VECTOR_MASK) + +#define MSI_DATA_DELIVERY_MODE_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for msi address + */ + +#define MSI_ADDR_BASE_HI 0 +#define MSI_ADDR_BASE_LO 0xfee00000 + +#define MSI_ADDR_DEST_MODE_SHIFT 2 +#define MSI_ADDR_DEST_MODE_PHYSICAL (0 << MSI_ADDR_DEST_MODE_SHIFT) +#define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + +#define MSI_ADDR_DEST_ID_SHIFT 12 +#define MSI_ADDR_DEST_ID_MASK 0x00ffff0 +#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \ + MSI_ADDR_DEST_ID_MASK) + +#endif /* ASM_RMI_MSIDEF_H */ diff --git a/arch/mips/netlogic/xlr/irq.c b/arch/mips/netlogic/xlr/irq.c index 521bb7377eb..fc822c8f081 100644 --- a/arch/mips/netlogic/xlr/irq.c +++ b/arch/mips/netlogic/xlr/irq.c @@ -38,9 +38,14 @@ #include #include #include +#include +#include +#include +#include #include +#include #include #include #include diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 38fece16c43..87404d0034d 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -36,12 +36,16 @@ #include #include #include +#include #include +#include +#include #include #include #include +#include #include #include #include @@ -150,7 +154,7 @@ struct pci_controller nlm_pci_controller = { .io_offset = 0x00000000UL, }; -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int get_irq_vector(const struct pci_dev *dev) { if (!nlm_chip_is_xls()) return PIC_PCIX_IRQ; /* for XLR just one IRQ*/ @@ -182,6 +186,51 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return 0; } +#ifdef CONFIG_PCI_MSI +void destroy_irq(unsigned int irq) +{ + /* nothing to do yet */ +} + +void arch_teardown_msi_irq(unsigned int irq) +{ + destroy_irq(irq); +} + +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +{ + struct msi_msg msg; + int irq, ret; + + irq = get_irq_vector(dev); + if (irq <= 0) + return 1; + + msg.address_hi = MSI_ADDR_BASE_HI; + msg.address_lo = MSI_ADDR_BASE_LO | + MSI_ADDR_DEST_MODE_PHYSICAL | + MSI_ADDR_REDIRECTION_CPU; + + msg.data = MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + MSI_DATA_DELIVERY_FIXED; + + ret = irq_set_msi_desc(irq, desc); + if (ret < 0) { + destroy_irq(irq); + return ret; + } + + write_msi_msg(irq, &msg); + return 0; +} +#endif + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return get_irq_vector(dev); +} + /* Do platform specific device initialization at pci_enable_device() time */ int pcibios_plat_dev_init(struct pci_dev *dev) { -- cgit v1.2.3-70-g09d2 From c3c8cfb979d1a3c514d6ef88204f05dcbd1934df Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Fri, 11 Nov 2011 17:07:40 +0530 Subject: MIPS: Netlogic: Use CPU_XLR instead of NLM_XLR The CPU_XLR config variable is sufficient for XLR compilation, the variable NLM_XLR can be removed. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2962/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 - arch/mips/netlogic/Kconfig | 3 --- arch/mips/netlogic/Platform | 4 ++-- arch/mips/pci/Makefile | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 04ac89c6ab6..58515fdf223 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -761,7 +761,6 @@ config NLM_XLR_BOARD depends on EXPERIMENTAL select BOOT_ELF32 select NLM_COMMON - select NLM_XLR select SYS_HAS_CPU_XLR select SYS_SUPPORTS_SMP select HW_HAS_PCI diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index a5ca743613f..75bec44b585 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -1,5 +1,2 @@ config NLM_COMMON bool - -config NLM_XLR - bool diff --git a/arch/mips/netlogic/Platform b/arch/mips/netlogic/Platform index 4fb6b8351c3..18aaf438ee4 100644 --- a/arch/mips/netlogic/Platform +++ b/arch/mips/netlogic/Platform @@ -7,10 +7,10 @@ cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/netlogic # # use mips64 if xlr is not available # -cflags-$(CONFIG_NLM_XLR) += $(call cc-option,-march=xlr,-march=mips64) +cflags-$(CONFIG_CPU_XLR) += $(call cc-option,-march=xlr,-march=mips64) # # NETLOGIC processor support # -platform-$(CONFIG_NLM_XLR) += netlogic/xlr +platform-$(CONFIG_CPU_XLR) += netlogic/xlr load-$(CONFIG_NLM_COMMON) += 0xffffffff80100000 diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index bb82cbdbc62..65ca05c776d 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -55,7 +55,7 @@ obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o -obj-$(CONFIG_NLM_XLR) += pci-xlr.o +obj-$(CONFIG_CPU_XLR) += pci-xlr.o ifdef CONFIG_PCI_MSI obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o -- cgit v1.2.3-70-g09d2 From 0c9654072a6e15aa3da9b314f0c5c01e90938268 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Fri, 11 Nov 2011 17:08:29 +0530 Subject: MIPS: Netlogic: Move code common with XLP to common/ - Move code that can be shared with XLP (irq.c, smp.c, time.c and xlr_console.c) to arch/mips/netlogic/common - Add asm/netlogic/haldefs.h and asm/netlogic/common.h for common and io functions shared with XLP - remove type 'nlm_reg_t *' and use uint64_t for mmio offsets - Move XLR specific code in smp.c to xlr/wakeup.c - Move XLR specific PCI code from irq.c to mips/pci/pci-xlr.c - Provide API for pic functions called from common/irq.c Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2964/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/common.h | 56 ++++++ arch/mips/include/asm/netlogic/haldefs.h | 142 ++++++++++++++ arch/mips/include/asm/netlogic/xlr/iomap.h | 22 --- arch/mips/include/asm/netlogic/xlr/pic.h | 69 +++++-- arch/mips/include/asm/netlogic/xlr/xlr.h | 11 -- arch/mips/netlogic/Makefile | 2 + arch/mips/netlogic/Platform | 2 +- arch/mips/netlogic/common/Makefile | 3 + arch/mips/netlogic/common/earlycons.c | 51 +++++ arch/mips/netlogic/common/irq.c | 230 ++++++++++++++++++++++ arch/mips/netlogic/common/smp.c | 188 ++++++++++++++++++ arch/mips/netlogic/common/time.c | 51 +++++ arch/mips/netlogic/xlr/Makefile | 5 +- arch/mips/netlogic/xlr/irq.c | 305 ----------------------------- arch/mips/netlogic/xlr/platform.c | 31 +-- arch/mips/netlogic/xlr/setup.c | 24 ++- arch/mips/netlogic/xlr/smp.c | 220 --------------------- arch/mips/netlogic/xlr/smpboot.S | 6 +- arch/mips/netlogic/xlr/time.c | 51 ----- arch/mips/netlogic/xlr/wakeup.c | 71 +++++++ arch/mips/netlogic/xlr/xlr_console.c | 46 ----- arch/mips/pci/pci-xlr.c | 77 ++++++++ 22 files changed, 960 insertions(+), 703 deletions(-) create mode 100644 arch/mips/include/asm/netlogic/common.h create mode 100644 arch/mips/include/asm/netlogic/haldefs.h create mode 100644 arch/mips/netlogic/Makefile create mode 100644 arch/mips/netlogic/common/Makefile create mode 100644 arch/mips/netlogic/common/earlycons.c create mode 100644 arch/mips/netlogic/common/irq.c create mode 100644 arch/mips/netlogic/common/smp.c create mode 100644 arch/mips/netlogic/common/time.c delete mode 100644 arch/mips/netlogic/xlr/irq.c delete mode 100644 arch/mips/netlogic/xlr/smp.c delete mode 100644 arch/mips/netlogic/xlr/time.c create mode 100644 arch/mips/netlogic/xlr/wakeup.c delete mode 100644 arch/mips/netlogic/xlr/xlr_console.c (limited to 'arch/mips/pci') diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h new file mode 100644 index 00000000000..e5bdf8c529f --- /dev/null +++ b/arch/mips/include/asm/netlogic/common.h @@ -0,0 +1,56 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NETLOGIC_COMMON_H_ +#define _NETLOGIC_COMMON_H_ + +/* + * Common SMP definitions + */ +struct irq_desc; +extern struct plat_smp_ops nlm_smp_ops; +extern char nlm_reset_entry[], nlm_reset_entry_end[]; +void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc); +void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc); +void nlm_smp_irq_init(void); +void prom_pre_boot_secondary_cpus(void); +int nlm_wakeup_secondary_cpus(u32 wakeup_mask); +void nlm_boot_smp_nmi(void); + +/* + * Misc. + */ +extern unsigned long nlm_common_ebase; +unsigned int nlm_get_cpu_frequency(void); +#endif /* _NETLOGIC_COMMON_H_ */ diff --git a/arch/mips/include/asm/netlogic/haldefs.h b/arch/mips/include/asm/netlogic/haldefs.h new file mode 100644 index 00000000000..e3264c19aab --- /dev/null +++ b/arch/mips/include/asm/netlogic/haldefs.h @@ -0,0 +1,142 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __NLM_HAL_HALDEFS_H__ +#define __NLM_HAL_HALDEFS_H__ + +/* + * This file contains platform specific memory mapped IO implementation + * and will provide a way to read 32/64 bit memory mapped registers in + * all ABIs + */ +/* + * For o32 compilation, we have to disable interrupts and enable KX bit to + * access 64 bit addresses or data. + * + * We need to disable interrupts because we save just the lower 32 bits of + * registers in interrupt handling. So if we get hit by an interrupt while + * using the upper 32 bits of a register, we lose. + */ +static inline uint32_t nlm_save_flags_kx(void) +{ + return change_c0_status(ST0_KX | ST0_IE, ST0_KX); +} + +static inline uint32_t nlm_save_flags_cop2(void) +{ + return change_c0_status(ST0_CU2 | ST0_IE, ST0_CU2); +} + +static inline void nlm_restore_flags(uint32_t sr) +{ + write_c0_status(sr); +} + +/* + * The n64 implementations are simple, the o32 implementations when they + * are added, will have to disable interrupts and enable KX before doing + * 64 bit ops. + */ +static inline uint32_t +nlm_read_reg(uint64_t base, uint32_t reg) +{ + volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg; + + return *addr; +} + +static inline void +nlm_write_reg(uint64_t base, uint32_t reg, uint32_t val) +{ + volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg; + + *addr = val; +} + +static inline uint64_t +nlm_read_reg64(uint64_t base, uint32_t reg) +{ + uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); + volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; + + return *ptr; +} + +static inline void +nlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val) +{ + uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); + volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; + + *ptr = val; +} + +/* + * Routines to store 32/64 bit values to 64 bit addresses, + * used when going thru XKPHYS to access registers + */ +static inline uint32_t +nlm_read_reg_xkphys(uint64_t base, uint32_t reg) +{ + return nlm_read_reg(base, reg); +} + +static inline void +nlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val) +{ + nlm_write_reg(base, reg, val); +} + +static inline uint64_t +nlm_read_reg64_xkphys(uint64_t base, uint32_t reg) +{ + return nlm_read_reg64(base, reg); +} + +static inline void +nlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val) +{ + nlm_write_reg64(base, reg, val); +} + +/* Location where IO base is mapped */ +extern uint64_t nlm_io_base; + +static inline uint64_t +nlm_mmio_base(uint32_t devoffset) +{ + return nlm_io_base + devoffset; +} + +#endif diff --git a/arch/mips/include/asm/netlogic/xlr/iomap.h b/arch/mips/include/asm/netlogic/xlr/iomap.h index 2e3a4dd5304..2e768f032e8 100644 --- a/arch/mips/include/asm/netlogic/xlr/iomap.h +++ b/arch/mips/include/asm/netlogic/xlr/iomap.h @@ -106,26 +106,4 @@ #define DEFAULT_HT_TYPE0_CFG_BASE 0x16000000 #define DEFAULT_HT_TYPE1_CFG_BASE 0x17000000 -#ifndef __ASSEMBLY__ -#include -#include - -typedef volatile __u32 nlm_reg_t; -extern unsigned long netlogic_io_base; - -/* FIXME read once in write_reg */ -#ifdef CONFIG_CPU_LITTLE_ENDIAN -#define netlogic_read_reg(base, offset) ((base)[(offset)]) -#define netlogic_write_reg(base, offset, value) ((base)[(offset)] = (value)) -#else -#define netlogic_read_reg(base, offset) (be32_to_cpu((base)[(offset)])) -#define netlogic_write_reg(base, offset, value) \ - ((base)[(offset)] = cpu_to_be32((value))) -#endif - -#define netlogic_read_reg_le32(base, offset) (le32_to_cpu((base)[(offset)])) -#define netlogic_write_reg_le32(base, offset, value) \ - ((base)[(offset)] = cpu_to_le32((value))) -#define netlogic_io_mmio(offset) ((nlm_reg_t *)(netlogic_io_base+(offset))) -#endif /* __ASSEMBLY__ */ #endif diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h index 5cceb746f08..868013e62f3 100644 --- a/arch/mips/include/asm/netlogic/xlr/pic.h +++ b/arch/mips/include/asm/netlogic/xlr/pic.h @@ -193,39 +193,72 @@ /* end XLS */ #ifndef __ASSEMBLY__ -static inline void pic_send_ipi(u32 ipi) + +#define PIC_IRQ_IS_EDGE_TRIGGERED(irq) (((irq) >= PIC_TIMER_0_IRQ) && \ + ((irq) <= PIC_TIMER_7_IRQ)) +#define PIC_IRQ_IS_IRT(irq) (((irq) >= PIC_IRT_FIRST_IRQ) && \ + ((irq) <= PIC_IRT_LAST_IRQ)) + +static inline int +nlm_irq_to_irt(int irq) { - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); + if (PIC_IRQ_IS_IRT(irq) == 0) + return -1; - netlogic_write_reg(mmio, PIC_IPI, ipi); + return PIC_IRQ_TO_INTR(irq); } -static inline u32 pic_read_control(void) +static inline int +nlm_irt_to_irq(int irt) { - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); - return netlogic_read_reg(mmio, PIC_CTRL); + return PIC_INTR_TO_IRQ(irt); } -static inline void pic_write_control(u32 control) +static inline void +nlm_pic_enable_irt(uint64_t base, int irt) { - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); + uint32_t reg; - netlogic_write_reg(mmio, PIC_CTRL, control); + reg = nlm_read_reg(base, PIC_IRT_1(irt)); + nlm_write_reg(base, PIC_IRT_1(irt), reg | (1u << 31)); } -static inline void pic_update_control(u32 control) +static inline void +nlm_pic_disable_irt(uint64_t base, int irt) { - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); + uint32_t reg; - netlogic_write_reg(mmio, PIC_CTRL, - (control | netlogic_read_reg(mmio, PIC_CTRL))); + reg = nlm_read_reg(base, PIC_IRT_1(irt)); + nlm_write_reg(base, PIC_IRT_1(irt), reg & ~(1u << 31)); } -#define PIC_IRQ_IS_EDGE_TRIGGERED(irq) (((irq) >= PIC_TIMER_0_IRQ) && \ - ((irq) <= PIC_TIMER_7_IRQ)) -#define PIC_IRQ_IS_IRT(irq) (((irq) >= PIC_IRT_FIRST_IRQ) && \ - ((irq) <= PIC_IRT_LAST_IRQ)) -#endif +static inline void +nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi) +{ + unsigned int tid, pid; + + tid = hwt & 0x3; + pid = (hwt >> 2) & 0x07; + nlm_write_reg(base, PIC_IPI, + (pid << 20) | (tid << 16) | (nmi << 8) | irq); +} + +static inline void +nlm_pic_ack(uint64_t base, int irt) +{ + nlm_write_reg(base, PIC_INT_ACK, 1u << irt); +} +static inline void +nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt) +{ + nlm_write_reg(base, PIC_IRT_0(irt), (1u << hwt)); + /* local scheduling, invalid, level by default */ + nlm_write_reg(base, PIC_IRT_1(irt), + (1 << 30) | (1 << 6) | irq); +} + +extern uint64_t nlm_pic_base; +#endif #endif /* _ASM_NLM_XLR_PIC_H */ diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h index 3e6372692a0..f4d3f7cb6d6 100644 --- a/arch/mips/include/asm/netlogic/xlr/xlr.h +++ b/arch/mips/include/asm/netlogic/xlr/xlr.h @@ -40,17 +40,6 @@ struct uart_port; unsigned int nlm_xlr_uart_in(struct uart_port *, int); void nlm_xlr_uart_out(struct uart_port *, int, int); -/* SMP support functions */ -struct irq_desc; -void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc); -void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc); -int nlm_wakeup_secondary_cpus(u32 wakeup_mask); -void nlm_smp_irq_init(void); -void nlm_boot_smp_nmi(void); -void prom_pre_boot_secondary_cpus(void); - -extern struct plat_smp_ops nlm_smp_ops; -extern unsigned long nlm_common_ebase; /* XLS B silicon "Rook" */ static inline unsigned int nlm_chip_is_xls_b(void) diff --git a/arch/mips/netlogic/Makefile b/arch/mips/netlogic/Makefile new file mode 100644 index 00000000000..797326da371 --- /dev/null +++ b/arch/mips/netlogic/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_NLM_COMMON) += common/ +obj-$(CONFIG_CPU_XLR) += xlr/ diff --git a/arch/mips/netlogic/Platform b/arch/mips/netlogic/Platform index 18aaf438ee4..7811b107689 100644 --- a/arch/mips/netlogic/Platform +++ b/arch/mips/netlogic/Platform @@ -12,5 +12,5 @@ cflags-$(CONFIG_CPU_XLR) += $(call cc-option,-march=xlr,-march=mips64) # # NETLOGIC processor support # -platform-$(CONFIG_CPU_XLR) += netlogic/xlr +platform-$(CONFIG_NLM_COMMON) += netlogic/ load-$(CONFIG_NLM_COMMON) += 0xffffffff80100000 diff --git a/arch/mips/netlogic/common/Makefile b/arch/mips/netlogic/common/Makefile new file mode 100644 index 00000000000..d4215783c3e --- /dev/null +++ b/arch/mips/netlogic/common/Makefile @@ -0,0 +1,3 @@ +obj-y += irq.o time.o +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_EARLY_PRINTK) += earlycons.o diff --git a/arch/mips/netlogic/common/earlycons.c b/arch/mips/netlogic/common/earlycons.c new file mode 100644 index 00000000000..28c8fa7a850 --- /dev/null +++ b/arch/mips/netlogic/common/earlycons.c @@ -0,0 +1,51 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +#include + +void prom_putchar(char c) +{ + uint64_t uartbase; + + uartbase = nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); + while (nlm_read_reg(uartbase, UART_LSR) == 0) + ; + nlm_write_reg(uartbase, UART_TX, c); +} diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c new file mode 100644 index 00000000000..dd0dd626cc8 --- /dev/null +++ b/arch/mips/netlogic/common/irq.c @@ -0,0 +1,230 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +/* + * These are the routines that handle all the low level interrupt stuff. + * Actions handled here are: initialization of the interrupt map, requesting of + * interrupt lines by handlers, dispatching if interrupts to handlers, probing + * for interrupt lines + */ + +/* Globals */ +static uint64_t nlm_irq_mask; +static DEFINE_SPINLOCK(nlm_pic_lock); + +static void xlp_pic_enable(struct irq_data *d) +{ + unsigned long flags; + int irt; + + irt = nlm_irq_to_irt(d->irq); + if (irt == -1) + return; + spin_lock_irqsave(&nlm_pic_lock, flags); + nlm_pic_enable_irt(nlm_pic_base, irt); + spin_unlock_irqrestore(&nlm_pic_lock, flags); +} + +static void xlp_pic_disable(struct irq_data *d) +{ + unsigned long flags; + int irt; + + irt = nlm_irq_to_irt(d->irq); + if (irt == -1) + return; + spin_lock_irqsave(&nlm_pic_lock, flags); + nlm_pic_disable_irt(nlm_pic_base, irt); + spin_unlock_irqrestore(&nlm_pic_lock, flags); +} + +static void xlp_pic_mask_ack(struct irq_data *d) +{ + uint64_t mask = 1ull << d->irq; + + write_c0_eirr(mask); /* ack by writing EIRR */ +} + +static void xlp_pic_unmask(struct irq_data *d) +{ + void *hd = irq_data_get_irq_handler_data(d); + int irt; + + irt = nlm_irq_to_irt(d->irq); + if (irt == -1) + return; + + if (hd) { + void (*extra_ack)(void *) = hd; + extra_ack(d); + } + /* Ack is a single write, no need to lock */ + nlm_pic_ack(nlm_pic_base, irt); +} + +static struct irq_chip xlp_pic = { + .name = "XLP-PIC", + .irq_enable = xlp_pic_enable, + .irq_disable = xlp_pic_disable, + .irq_mask_ack = xlp_pic_mask_ack, + .irq_unmask = xlp_pic_unmask, +}; + +static void cpuintr_disable(struct irq_data *d) +{ + uint64_t eimr; + uint64_t mask = 1ull << d->irq; + + eimr = read_c0_eimr(); + write_c0_eimr(eimr & ~mask); +} + +static void cpuintr_enable(struct irq_data *d) +{ + uint64_t eimr; + uint64_t mask = 1ull << d->irq; + + eimr = read_c0_eimr(); + write_c0_eimr(eimr | mask); +} + +static void cpuintr_ack(struct irq_data *d) +{ + uint64_t mask = 1ull << d->irq; + + write_c0_eirr(mask); +} + +static void cpuintr_nop(struct irq_data *d) +{ + WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq); +} + +/* + * Chip definition for CPU originated interrupts(timer, msg) and + * IPIs + */ +struct irq_chip nlm_cpu_intr = { + .name = "XLP-CPU-INTR", + .irq_enable = cpuintr_enable, + .irq_disable = cpuintr_disable, + .irq_mask = cpuintr_nop, + .irq_ack = cpuintr_nop, + .irq_eoi = cpuintr_ack, +}; + +void __init init_nlm_common_irqs(void) +{ + int i, irq, irt; + + for (i = 0; i < PIC_IRT_FIRST_IRQ; i++) + irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq); + + for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++) + irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq); + +#ifdef CONFIG_SMP + irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr, + nlm_smp_function_ipi_handler); + irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, + nlm_smp_resched_ipi_handler); + nlm_irq_mask |= + ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE)); +#endif + + for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) { + irt = nlm_irq_to_irt(irq); + if (irt == -1) + continue; + nlm_irq_mask |= (1ULL << irq); + nlm_pic_init_irt(nlm_pic_base, irt, irq, 0); + } + + nlm_irq_mask |= (1ULL << IRQ_TIMER); +} + +void __init arch_init_irq(void) +{ + /* Initialize the irq descriptors */ + init_nlm_common_irqs(); + + write_c0_eimr(nlm_irq_mask); +} + +void __cpuinit nlm_smp_irq_init(void) +{ + /* set interrupt mask for non-zero cpus */ + write_c0_eimr(nlm_irq_mask); +} + +asmlinkage void plat_irq_dispatch(void) +{ + uint64_t eirr; + int i; + + eirr = read_c0_eirr() & read_c0_eimr(); + if (eirr & (1 << IRQ_TIMER)) { + do_IRQ(IRQ_TIMER); + return; + } + + i = __ilog2_u64(eirr); + if (i == -1) + return; + + do_IRQ(i); +} diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c new file mode 100644 index 00000000000..3b32c834d14 --- /dev/null +++ b/arch/mips/netlogic/common/smp.c @@ -0,0 +1,188 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +void nlm_send_ipi_single(int logical_cpu, unsigned int action) +{ + int cpu = cpu_logical_map(logical_cpu); + + if (action & SMP_CALL_FUNCTION) + nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_FUNCTION, 0); + if (action & SMP_RESCHEDULE_YOURSELF) + nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_RESCHEDULE, 0); +} + +void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action) +{ + int cpu; + + for_each_cpu(cpu, mask) { + nlm_send_ipi_single(cpu, action); + } +} + +/* IRQ_IPI_SMP_FUNCTION Handler */ +void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc) +{ + smp_call_function_interrupt(); + write_c0_eirr(1ull << irq); +} + +/* IRQ_IPI_SMP_RESCHEDULE handler */ +void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc) +{ + scheduler_ipi(); + write_c0_eirr(1ull << irq); +} + +/* + * Called before going into mips code, early cpu init + */ +void nlm_early_init_secondary(int cpu) +{ + write_c0_ebase((uint32_t)nlm_common_ebase); +#ifdef NLM_XLP + if (cpu % 4 == 0) + xlp_mmu_init(); +#endif +} + +/* + * Code to run on secondary just after probing the CPU + */ +static void __cpuinit nlm_init_secondary(void) +{ + nlm_smp_irq_init(); +} + +void nlm_smp_finish(void) +{ +#ifdef notyet + nlm_common_msgring_cpu_init(); +#endif + local_irq_enable(); +} + +void nlm_cpus_done(void) +{ +} + +/* + * Boot all other cpus in the system, initialize them, and bring them into + * the boot function + */ +int nlm_cpu_unblock[NR_CPUS]; +int nlm_cpu_ready[NR_CPUS]; +unsigned long nlm_next_gp; +unsigned long nlm_next_sp; +cpumask_t phys_cpu_present_map; + +void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) +{ + unsigned long gp = (unsigned long)task_thread_info(idle); + unsigned long sp = (unsigned long)__KSTK_TOS(idle); + int cpu = cpu_logical_map(logical_cpu); + + nlm_next_sp = sp; + nlm_next_gp = gp; + + /* barrier */ + __sync(); + nlm_cpu_unblock[cpu] = 1; +} + +void __init nlm_smp_setup(void) +{ + unsigned int boot_cpu; + int num_cpus, i; + + boot_cpu = hard_smp_processor_id(); + cpus_clear(phys_cpu_present_map); + + cpu_set(boot_cpu, phys_cpu_present_map); + __cpu_number_map[boot_cpu] = 0; + __cpu_logical_map[0] = boot_cpu; + cpu_set(0, cpu_possible_map); + + num_cpus = 1; + for (i = 0; i < NR_CPUS; i++) { + /* + * nlm_cpu_ready array is not set for the boot_cpu, + * it is only set for ASPs (see smpboot.S) + */ + if (nlm_cpu_ready[i]) { + cpu_set(i, phys_cpu_present_map); + __cpu_number_map[i] = num_cpus; + __cpu_logical_map[num_cpus] = i; + cpu_set(num_cpus, cpu_possible_map); + ++num_cpus; + } + } + + pr_info("Phys CPU present map: %lx, possible map %lx\n", + (unsigned long)phys_cpu_present_map.bits[0], + (unsigned long)cpu_possible_map.bits[0]); + + pr_info("Detected %i Slave CPU(s)\n", num_cpus); +} + +void nlm_prepare_cpus(unsigned int max_cpus) +{ +} + +struct plat_smp_ops nlm_smp_ops = { + .send_ipi_single = nlm_send_ipi_single, + .send_ipi_mask = nlm_send_ipi_mask, + .init_secondary = nlm_init_secondary, + .smp_finish = nlm_smp_finish, + .cpus_done = nlm_cpus_done, + .boot_secondary = nlm_boot_secondary, + .smp_setup = nlm_smp_setup, + .prepare_cpus = nlm_prepare_cpus, +}; diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c new file mode 100644 index 00000000000..bd3e498157f --- /dev/null +++ b/arch/mips/netlogic/common/time.c @@ -0,0 +1,51 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +unsigned int __cpuinit get_c0_compare_int(void) +{ + return IRQ_TIMER; +} + +void __init plat_time_init(void) +{ + mips_hpt_frequency = nlm_get_cpu_frequency(); + pr_info("MIPS counter frequency [%ld]\n", + (unsigned long)mips_hpt_frequency); +} diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile index 29f1fd5ba80..df245c60454 100644 --- a/arch/mips/netlogic/xlr/Makefile +++ b/arch/mips/netlogic/xlr/Makefile @@ -1,3 +1,2 @@ -obj-y += setup.o platform.o irq.o setup.o time.o -obj-$(CONFIG_SMP) += smp.o smpboot.o -obj-$(CONFIG_EARLY_PRINTK) += xlr_console.o +obj-y += setup.o platform.o +obj-$(CONFIG_SMP) += smpboot.o wakeup.o diff --git a/arch/mips/netlogic/xlr/irq.c b/arch/mips/netlogic/xlr/irq.c deleted file mode 100644 index fc822c8f081..00000000000 --- a/arch/mips/netlogic/xlr/irq.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights - * reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the NetLogic - * license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -static u64 nlm_irq_mask; -static DEFINE_SPINLOCK(nlm_pic_lock); - -static void xlr_pic_enable(struct irq_data *d) -{ - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); - unsigned long flags; - nlm_reg_t reg; - int irq = d->irq; - - WARN(!PIC_IRQ_IS_IRT(irq), "Bad irq %d", irq); - - spin_lock_irqsave(&nlm_pic_lock, flags); - reg = netlogic_read_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE); - netlogic_write_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE, - reg | (1 << 6) | (1 << 30) | (1 << 31)); - spin_unlock_irqrestore(&nlm_pic_lock, flags); -} - -static void xlr_pic_mask(struct irq_data *d) -{ - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); - unsigned long flags; - nlm_reg_t reg; - int irq = d->irq; - - WARN(!PIC_IRQ_IS_IRT(irq), "Bad irq %d", irq); - - spin_lock_irqsave(&nlm_pic_lock, flags); - reg = netlogic_read_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE); - netlogic_write_reg(mmio, PIC_IRT_1_BASE + irq - PIC_IRQ_BASE, - reg | (1 << 6) | (1 << 30) | (0 << 31)); - spin_unlock_irqrestore(&nlm_pic_lock, flags); -} - -#ifdef CONFIG_PCI -/* Extra ACK needed for XLR on chip PCI controller */ -static void xlr_pci_ack(struct irq_data *d) -{ - nlm_reg_t *pci_mmio = netlogic_io_mmio(NETLOGIC_IO_PCIX_OFFSET); - - netlogic_read_reg(pci_mmio, (0x140 >> 2)); -} - -/* Extra ACK needed for XLS on chip PCIe controller */ -static void xls_pcie_ack(struct irq_data *d) -{ - nlm_reg_t *pcie_mmio_le = netlogic_io_mmio(NETLOGIC_IO_PCIE_1_OFFSET); - - switch (d->irq) { - case PIC_PCIE_LINK0_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x90 >> 2), 0xffffffff); - break; - case PIC_PCIE_LINK1_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x94 >> 2), 0xffffffff); - break; - case PIC_PCIE_LINK2_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x190 >> 2), 0xffffffff); - break; - case PIC_PCIE_LINK3_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x194 >> 2), 0xffffffff); - break; - } -} - -/* For XLS B silicon, the 3,4 PCI interrupts are different */ -static void xls_pcie_ack_b(struct irq_data *d) -{ - nlm_reg_t *pcie_mmio_le = netlogic_io_mmio(NETLOGIC_IO_PCIE_1_OFFSET); - - switch (d->irq) { - case PIC_PCIE_LINK0_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x90 >> 2), 0xffffffff); - break; - case PIC_PCIE_LINK1_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x94 >> 2), 0xffffffff); - break; - case PIC_PCIE_XLSB0_LINK2_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x190 >> 2), 0xffffffff); - break; - case PIC_PCIE_XLSB0_LINK3_IRQ: - netlogic_write_reg(pcie_mmio_le, (0x194 >> 2), 0xffffffff); - break; - } -} -#endif - -static void xlr_pic_ack(struct irq_data *d) -{ - unsigned long flags; - nlm_reg_t *mmio; - int irq = d->irq; - void *hd = irq_data_get_irq_handler_data(d); - - WARN(!PIC_IRQ_IS_IRT(irq), "Bad irq %d", irq); - - if (hd) { - void (*extra_ack)(void *) = hd; - extra_ack(d); - } - mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); - spin_lock_irqsave(&nlm_pic_lock, flags); - netlogic_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE))); - spin_unlock_irqrestore(&nlm_pic_lock, flags); -} - -/* - * This chip definition handles interrupts routed thru the XLR - * hardware PIC, currently IRQs 8-39 are mapped to hardware intr - * 0-31 wired the XLR PIC - */ -static struct irq_chip xlr_pic = { - .name = "XLR-PIC", - .irq_enable = xlr_pic_enable, - .irq_mask = xlr_pic_mask, - .irq_ack = xlr_pic_ack, -}; - -static void rsvd_irq_handler(struct irq_data *d) -{ - WARN(d->irq >= PIC_IRQ_BASE, "Bad irq %d", d->irq); -} - -/* - * Chip definition for CPU originated interrupts(timer, msg) and - * IPIs - */ -struct irq_chip nlm_cpu_intr = { - .name = "XLR-CPU-INTR", - .irq_enable = rsvd_irq_handler, - .irq_mask = rsvd_irq_handler, - .irq_ack = rsvd_irq_handler, -}; - -void __init init_xlr_irqs(void) -{ - nlm_reg_t *mmio = netlogic_io_mmio(NETLOGIC_IO_PIC_OFFSET); - uint32_t thread_mask = 1; - int level, i; - - pr_info("Interrupt thread mask [%x]\n", thread_mask); - for (i = 0; i < PIC_NUM_IRTS; i++) { - level = PIC_IRQ_IS_EDGE_TRIGGERED(i); - - /* Bind all PIC irqs to boot cpu */ - netlogic_write_reg(mmio, PIC_IRT_0_BASE + i, thread_mask); - - /* - * Use local scheduling and high polarity for all IRTs - * Invalidate all IRTs, by default - */ - netlogic_write_reg(mmio, PIC_IRT_1_BASE + i, - (level << 30) | (1 << 6) | (PIC_IRQ_BASE + i)); - } - - /* Make all IRQs as level triggered by default */ - for (i = 0; i < NR_IRQS; i++) { - if (PIC_IRQ_IS_IRT(i)) - irq_set_chip_and_handler(i, &xlr_pic, handle_level_irq); - else - irq_set_chip_and_handler(i, &nlm_cpu_intr, - handle_percpu_irq); - } -#ifdef CONFIG_SMP - irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr, - nlm_smp_function_ipi_handler); - irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr, - nlm_smp_resched_ipi_handler); - nlm_irq_mask |= - ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE)); -#endif - -#ifdef CONFIG_PCI - /* - * For PCI interrupts, we need to ack the PIC controller too, overload - * irq handler data to do this - */ - if (nlm_chip_is_xls()) { - if (nlm_chip_is_xls_b()) { - irq_set_handler_data(PIC_PCIE_LINK0_IRQ, - xls_pcie_ack_b); - irq_set_handler_data(PIC_PCIE_LINK1_IRQ, - xls_pcie_ack_b); - irq_set_handler_data(PIC_PCIE_XLSB0_LINK2_IRQ, - xls_pcie_ack_b); - irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, - xls_pcie_ack_b); - } else { - irq_set_handler_data(PIC_PCIE_LINK0_IRQ, xls_pcie_ack); - irq_set_handler_data(PIC_PCIE_LINK1_IRQ, xls_pcie_ack); - irq_set_handler_data(PIC_PCIE_LINK2_IRQ, xls_pcie_ack); - irq_set_handler_data(PIC_PCIE_LINK3_IRQ, xls_pcie_ack); - } - } else { - /* XLR PCI controller ACK */ - irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, xlr_pci_ack); - } -#endif - /* unmask all PIC related interrupts. If no handler is installed by the - * drivers, it'll just ack the interrupt and return - */ - for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) - nlm_irq_mask |= (1ULL << i); - - nlm_irq_mask |= (1ULL << IRQ_TIMER); -} - -void __init arch_init_irq(void) -{ - /* Initialize the irq descriptors */ - init_xlr_irqs(); - write_c0_eimr(nlm_irq_mask); -} - -void __cpuinit nlm_smp_irq_init(void) -{ - /* set interrupt mask for non-zero cpus */ - write_c0_eimr(nlm_irq_mask); -} - -asmlinkage void plat_irq_dispatch(void) -{ - uint64_t eirr; - int i; - - eirr = read_c0_eirr() & read_c0_eimr(); - if (!eirr) - return; - - /* no need of EIRR here, writing compare clears interrupt */ - if (eirr & (1 << IRQ_TIMER)) { - do_IRQ(IRQ_TIMER); - return; - } - - /* use dcltz: optimize below code */ - for (i = 63; i != -1; i--) { - if (eirr & (1ULL << i)) - break; - } - if (i == -1) { - pr_err("no interrupt !!\n"); - return; - } - - /* Ack eirr */ - write_c0_eirr(1ULL << i); - - do_IRQ(i); -} diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c index 609ec253464..eab64b45dff 100644 --- a/arch/mips/netlogic/xlr/platform.c +++ b/arch/mips/netlogic/xlr/platform.c @@ -15,18 +15,19 @@ #include #include +#include #include #include #include unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) { - nlm_reg_t *mmio; + uint64_t uartbase; unsigned int value; - /* XLR uart does not need any mapping of regs */ - mmio = (nlm_reg_t *)(p->membase + (offset << p->regshift)); - value = netlogic_read_reg(mmio, 0); + /* sign extend to 64 bits, if needed */ + uartbase = (uint64_t)(long)p->membase; + value = nlm_read_reg(uartbase, offset); /* See XLR/XLS errata */ if (offset == UART_MSR) @@ -39,10 +40,10 @@ unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) void nlm_xlr_uart_out(struct uart_port *p, int offset, int value) { - nlm_reg_t *mmio; + uint64_t uartbase; - /* XLR uart does not need any mapping of regs */ - mmio = (nlm_reg_t *)(p->membase + (offset << p->regshift)); + /* sign extend to 64 bits, if needed */ + uartbase = (uint64_t)(long)p->membase; /* See XLR/XLS errata */ if (offset == UART_MSR) @@ -50,7 +51,7 @@ void nlm_xlr_uart_out(struct uart_port *p, int offset, int value) else if (offset == UART_MCR) value ^= 0x3; - netlogic_write_reg(mmio, 0, value); + nlm_write_reg(uartbase, offset, value); } #define PORT(_irq) \ @@ -82,15 +83,15 @@ static struct platform_device uart_device = { static int __init nlm_uart_init(void) { - nlm_reg_t *mmio; + unsigned long uartbase; - mmio = netlogic_io_mmio(NETLOGIC_IO_UART_0_OFFSET); - xlr_uart_data[0].membase = (void __iomem *)mmio; - xlr_uart_data[0].mapbase = CPHYSADDR((unsigned long)mmio); + uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); + xlr_uart_data[0].membase = (void __iomem *)uartbase; + xlr_uart_data[0].mapbase = CPHYSADDR(uartbase); - mmio = netlogic_io_mmio(NETLOGIC_IO_UART_1_OFFSET); - xlr_uart_data[1].membase = (void __iomem *)mmio; - xlr_uart_data[1].mapbase = CPHYSADDR((unsigned long)mmio); + uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_1_OFFSET); + xlr_uart_data[1].membase = (void __iomem *)uartbase; + xlr_uart_data[1].mapbase = CPHYSADDR(uartbase); return platform_device_register(&uart_device); } diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index cee25ddd088..20c280ae7e9 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -39,26 +39,28 @@ #include #include #include -#include #include #include +#include +#include #include #include #include #include -unsigned long netlogic_io_base = (unsigned long)(DEFAULT_NETLOGIC_IO_BASE); +uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE; +uint64_t nlm_pic_base; unsigned long nlm_common_ebase = 0x0; struct psb_info nlm_prom_info; static void __init nlm_early_serial_setup(void) { struct uart_port s; - nlm_reg_t *uart_base; + unsigned long uart_base; - uart_base = netlogic_io_mmio(NETLOGIC_IO_UART_0_OFFSET); + uart_base = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); memset(&s, 0, sizeof(s)); s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; s.iotype = UPIO_MEM32; @@ -67,18 +69,18 @@ static void __init nlm_early_serial_setup(void) s.uartclk = PIC_CLKS_PER_SEC; s.serial_in = nlm_xlr_uart_in; s.serial_out = nlm_xlr_uart_out; - s.mapbase = (unsigned long)uart_base; + s.mapbase = uart_base; s.membase = (unsigned char __iomem *)uart_base; early_serial_setup(&s); } static void nlm_linux_exit(void) { - nlm_reg_t *mmio; + uint64_t gpiobase; - mmio = netlogic_io_mmio(NETLOGIC_IO_GPIO_OFFSET); + gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); /* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */ - netlogic_write_reg(mmio, NETLOGIC_GPIO_SWRESET_REG, 1); + nlm_write_reg(gpiobase, NETLOGIC_GPIO_SWRESET_REG, 1); for ( ; ; ) cpu_wait(); } @@ -96,6 +98,11 @@ const char *get_system_type(void) return "Netlogic XLR/XLS Series"; } +unsigned int nlm_get_cpu_frequency(void) +{ + return (unsigned int)nlm_prom_info.cpu_frequency; +} + void __init prom_free_prom_memory(void) { /* Nothing yet */ @@ -175,6 +182,7 @@ void __init prom_init(void) prom_infop = (struct psb_info *)(long)(int)fw_arg3; nlm_prom_info = *prom_infop; + nlm_pic_base = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET); nlm_early_serial_setup(); build_arcs_cmdline(argv); diff --git a/arch/mips/netlogic/xlr/smp.c b/arch/mips/netlogic/xlr/smp.c deleted file mode 100644 index 080284ded50..00000000000 --- a/arch/mips/netlogic/xlr/smp.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights - * reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the NetLogic - * license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -void core_send_ipi(int logical_cpu, unsigned int action) -{ - int cpu = cpu_logical_map(logical_cpu); - u32 tid = cpu & 0x3; - u32 pid = (cpu >> 2) & 0x07; - u32 ipi = (tid << 16) | (pid << 20); - - if (action & SMP_CALL_FUNCTION) - ipi |= IRQ_IPI_SMP_FUNCTION; - else if (action & SMP_RESCHEDULE_YOURSELF) - ipi |= IRQ_IPI_SMP_RESCHEDULE; - else - return; - - pic_send_ipi(ipi); -} - -void nlm_send_ipi_single(int cpu, unsigned int action) -{ - core_send_ipi(cpu, action); -} - -void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action) -{ - int cpu; - - for_each_cpu(cpu, mask) { - core_send_ipi(cpu, action); - } -} - -/* IRQ_IPI_SMP_FUNCTION Handler */ -void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc) -{ - smp_call_function_interrupt(); -} - -/* IRQ_IPI_SMP_RESCHEDULE handler */ -void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc) -{ - scheduler_ipi(); -} - -/* - * Called before going into mips code, early cpu init - */ -void nlm_early_init_secondary(void) -{ - write_c0_ebase((uint32_t)nlm_common_ebase); - /* TLB partition here later */ -} - -/* - * Code to run on secondary just after probing the CPU - */ -static void __cpuinit nlm_init_secondary(void) -{ - nlm_smp_irq_init(); -} - -void nlm_smp_finish(void) -{ -#ifdef notyet - nlm_common_msgring_cpu_init(); -#endif - local_irq_enable(); -} - -void nlm_cpus_done(void) -{ -} - -/* - * Boot all other cpus in the system, initialize them, and bring them into - * the boot function - */ -int nlm_cpu_unblock[NR_CPUS]; -int nlm_cpu_ready[NR_CPUS]; -unsigned long nlm_next_gp; -unsigned long nlm_next_sp; -cpumask_t phys_cpu_present_map; - -void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) -{ - unsigned long gp = (unsigned long)task_thread_info(idle); - unsigned long sp = (unsigned long)__KSTK_TOS(idle); - int cpu = cpu_logical_map(logical_cpu); - - nlm_next_sp = sp; - nlm_next_gp = gp; - - /* barrier */ - __sync(); - nlm_cpu_unblock[cpu] = 1; -} - -void __init nlm_smp_setup(void) -{ - unsigned int boot_cpu; - int num_cpus, i; - - boot_cpu = hard_smp_processor_id(); - cpus_clear(phys_cpu_present_map); - - cpu_set(boot_cpu, phys_cpu_present_map); - __cpu_number_map[boot_cpu] = 0; - __cpu_logical_map[0] = boot_cpu; - cpu_set(0, cpu_possible_map); - - num_cpus = 1; - for (i = 0; i < NR_CPUS; i++) { - /* - * BSP is not set in nlm_cpu_ready array, it is only for - * ASPs (goto see smpboot.S) - */ - if (nlm_cpu_ready[i]) { - cpu_set(i, phys_cpu_present_map); - __cpu_number_map[i] = num_cpus; - __cpu_logical_map[num_cpus] = i; - cpu_set(num_cpus, cpu_possible_map); - ++num_cpus; - } - } - - pr_info("Phys CPU present map: %lx, possible map %lx\n", - (unsigned long)phys_cpu_present_map.bits[0], - (unsigned long)cpu_possible_map.bits[0]); - - pr_info("Detected %i Slave CPU(s)\n", num_cpus); -} - -void nlm_prepare_cpus(unsigned int max_cpus) -{ -} - -struct plat_smp_ops nlm_smp_ops = { - .send_ipi_single = nlm_send_ipi_single, - .send_ipi_mask = nlm_send_ipi_mask, - .init_secondary = nlm_init_secondary, - .smp_finish = nlm_smp_finish, - .cpus_done = nlm_cpus_done, - .boot_secondary = nlm_boot_secondary, - .smp_setup = nlm_smp_setup, - .prepare_cpus = nlm_prepare_cpus, -}; - -unsigned long secondary_entry_point; - -int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) -{ - unsigned int tid, pid, ipi, i, boot_cpu; - void *reset_vec; - - secondary_entry_point = (unsigned long)prom_pre_boot_secondary_cpus; - reset_vec = (void *)CKSEG1ADDR(0x1fc00000); - memcpy(reset_vec, nlm_boot_smp_nmi, 0x80); - boot_cpu = hard_smp_processor_id(); - - for (i = 0; i < NR_CPUS; i++) { - if (i == boot_cpu) - continue; - if (wakeup_mask & (1u << i)) { - tid = i & 0x3; - pid = (i >> 2) & 0x7; - ipi = (tid << 16) | (pid << 20) | (1 << 8); - pic_send_ipi(ipi); - } - } - - return 0; -} diff --git a/arch/mips/netlogic/xlr/smpboot.S b/arch/mips/netlogic/xlr/smpboot.S index 8cb7889ce0c..7f1f6e6e295 100644 --- a/arch/mips/netlogic/xlr/smpboot.S +++ b/arch/mips/netlogic/xlr/smpboot.S @@ -75,12 +75,11 @@ NESTED(prom_pre_boot_secondary_cpus, 16, sp) jr t0 nop END(prom_pre_boot_secondary_cpus) - __FINIT /* * NMI code, used for CPU wakeup, copied to reset entry */ -NESTED(nlm_boot_smp_nmi, 0, sp) +EXPORT(nlm_reset_entry) .set push .set noat .set mips64 @@ -97,4 +96,5 @@ NESTED(nlm_boot_smp_nmi, 0, sp) jr k0 nop .set pop -END(nlm_boot_smp_nmi) +EXPORT(nlm_reset_entry_end) + __FINIT diff --git a/arch/mips/netlogic/xlr/time.c b/arch/mips/netlogic/xlr/time.c deleted file mode 100644 index 0d81b262593..00000000000 --- a/arch/mips/netlogic/xlr/time.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights - * reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the NetLogic - * license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include -#include -#include - -unsigned int __cpuinit get_c0_compare_int(void) -{ - return IRQ_TIMER; -} - -void __init plat_time_init(void) -{ - mips_hpt_frequency = nlm_prom_info.cpu_frequency; - pr_info("MIPS counter frequency [%ld]\n", - (unsigned long)mips_hpt_frequency); -} diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c new file mode 100644 index 00000000000..69143bb7f68 --- /dev/null +++ b/arch/mips/netlogic/xlr/wakeup.c @@ -0,0 +1,71 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +unsigned long secondary_entry_point; + +int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) +{ + unsigned int i, boot_cpu; + void *reset_vec; + + secondary_entry_point = (unsigned long)prom_pre_boot_secondary_cpus; + reset_vec = (void *)CKSEG1ADDR(0x1fc00000); + memcpy(reset_vec, (void *)nlm_reset_entry, + (nlm_reset_entry_end - nlm_reset_entry)); + boot_cpu = hard_smp_processor_id(); + + for (i = 0; i < NR_CPUS; i++) { + if (i == boot_cpu || (wakeup_mask & (1u << i)) == 0) + continue; + nlm_pic_send_ipi(nlm_pic_base, i, 1, 1); /* send NMI */ + } + + return 0; +} diff --git a/arch/mips/netlogic/xlr/xlr_console.c b/arch/mips/netlogic/xlr/xlr_console.c deleted file mode 100644 index 759df069220..00000000000 --- a/arch/mips/netlogic/xlr/xlr_console.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights - * reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the NetLogic - * license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -void prom_putchar(char c) -{ - nlm_reg_t *mmio; - - mmio = netlogic_io_mmio(NETLOGIC_IO_UART_0_OFFSET); - while (netlogic_read_reg(mmio, 0x5) == 0) - ; - netlogic_write_reg(mmio, 0x0, c); -} diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 87404d0034d..3d701a962ef 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -45,6 +45,8 @@ #include #include +#include + #include #include #include @@ -226,6 +228,56 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) } #endif +/* Extra ACK needed for XLR on chip PCI controller */ +static void xlr_pci_ack(struct irq_data *d) +{ + uint64_t pcibase = nlm_mmio_base(NETLOGIC_IO_PCIX_OFFSET); + + nlm_read_reg(pcibase, (0x140 >> 2)); +} + +/* Extra ACK needed for XLS on chip PCIe controller */ +static void xls_pcie_ack(struct irq_data *d) +{ + uint64_t pciebase_le = nlm_mmio_base(NETLOGIC_IO_PCIE_1_OFFSET); + + switch (d->irq) { + case PIC_PCIE_LINK0_IRQ: + nlm_write_reg(pciebase_le, (0x90 >> 2), 0xffffffff); + break; + case PIC_PCIE_LINK1_IRQ: + nlm_write_reg(pciebase_le, (0x94 >> 2), 0xffffffff); + break; + case PIC_PCIE_LINK2_IRQ: + nlm_write_reg(pciebase_le, (0x190 >> 2), 0xffffffff); + break; + case PIC_PCIE_LINK3_IRQ: + nlm_write_reg(pciebase_le, (0x194 >> 2), 0xffffffff); + break; + } +} + +/* For XLS B silicon, the 3,4 PCI interrupts are different */ +static void xls_pcie_ack_b(struct irq_data *d) +{ + uint64_t pciebase_le = nlm_mmio_base(NETLOGIC_IO_PCIE_1_OFFSET); + + switch (d->irq) { + case PIC_PCIE_LINK0_IRQ: + nlm_write_reg(pciebase_le, (0x90 >> 2), 0xffffffff); + break; + case PIC_PCIE_LINK1_IRQ: + nlm_write_reg(pciebase_le, (0x94 >> 2), 0xffffffff); + break; + case PIC_PCIE_XLSB0_LINK2_IRQ: + nlm_write_reg(pciebase_le, (0x190 >> 2), 0xffffffff); + break; + case PIC_PCIE_XLSB0_LINK3_IRQ: + nlm_write_reg(pciebase_le, (0x194 >> 2), 0xffffffff); + break; + } +} + int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { return get_irq_vector(dev); @@ -253,6 +305,31 @@ static int __init pcibios_init(void) pr_info("Registering XLR/XLS PCIX/PCIE Controller.\n"); register_pci_controller(&nlm_pci_controller); + /* + * For PCI interrupts, we need to ack the PCI controller too, overload + * irq handler data to do this + */ + if (nlm_chip_is_xls()) { + if (nlm_chip_is_xls_b()) { + irq_set_handler_data(PIC_PCIE_LINK0_IRQ, + xls_pcie_ack_b); + irq_set_handler_data(PIC_PCIE_LINK1_IRQ, + xls_pcie_ack_b); + irq_set_handler_data(PIC_PCIE_XLSB0_LINK2_IRQ, + xls_pcie_ack_b); + irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, + xls_pcie_ack_b); + } else { + irq_set_handler_data(PIC_PCIE_LINK0_IRQ, xls_pcie_ack); + irq_set_handler_data(PIC_PCIE_LINK1_IRQ, xls_pcie_ack); + irq_set_handler_data(PIC_PCIE_LINK2_IRQ, xls_pcie_ack); + irq_set_handler_data(PIC_PCIE_LINK3_IRQ, xls_pcie_ack); + } + } else { + /* XLR PCI controller ACK */ + irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, xlr_pci_ack); + } + return 0; } -- cgit v1.2.3-70-g09d2 From 53efc98ec63d3868dc85d9b134e93e2a76b79893 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 8 Dec 2011 12:26:28 +0000 Subject: MIPS: Octeon: Update PCI Latency timer and enable more error reporting. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2987/ Patchwork: https://patchwork.linux-mips.org/patch/3161/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-octeon.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c index ed1c54284b8..52a1ba70b3b 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c @@ -99,7 +99,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) */ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); /* Set latency timers for all devices */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); /* Enable reporting System errors and parity errors on all devices */ /* Enable parity checking and error reporting */ @@ -109,7 +109,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) if (dev->subordinate) { /* Set latency timers on sub bridges */ - pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 64); /* More bridge error detection */ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; @@ -121,14 +121,10 @@ int pcibios_plat_dev_init(struct pci_dev *dev) if (pos) { /* Update Device Control */ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); - /* Correctable Error Reporting */ - config |= PCI_EXP_DEVCTL_CERE; - /* Non-Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_NFERE; - /* Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_FERE; - /* Unsupported Request */ - config |= PCI_EXP_DEVCTL_URRE; + config |= PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */ + config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_FERE; /* Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_URRE; /* Unsupported Request */ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); } -- cgit v1.2.3-70-g09d2 From 595789a192f141fde48d8f9ed9d6071be2e52168 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 8 Dec 2011 12:32:57 +0000 Subject: MIPS: Octeon: Add support for OCTEON II PCIe OCTEON II SOCs have a different PCIe implementation than is present in OCTEON Plus. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2985/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pcie-octeon.c | 1349 ++++++++++++++++++++++++++++++++----------- 1 file changed, 1023 insertions(+), 326 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index 0583c463e5f..fdb4d558c0c 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2007, 2008 Cavium Networks + * Copyright (C) 2007, 2008, 2009, 2010, 2011 Cavium Networks */ #include #include @@ -11,15 +11,32 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include #include #include +#define MRRS_CN5XXX 0 /* 128 byte Max Read Request Size */ +#define MPS_CN5XXX 0 /* 128 byte Max Packet Size (Limit of most PCs) */ +#define MRRS_CN6XXX 3 /* 1024 byte Max Read Request Size */ +#define MPS_CN6XXX 0 /* 128 byte Max Packet Size (Limit of most PCs) */ + +/* Module parameter to disable PCI probing */ +static int pcie_disable; +module_param(pcie_disable, int, S_IRUGO); + +static int enable_pcie_14459_war; +static int enable_pcie_bus_num_war[2]; + union cvmx_pcie_address { uint64_t u64; struct { @@ -75,6 +92,8 @@ union cvmx_pcie_address { } mem; }; +static int cvmx_pcie_rc_initialize(int pcie_port); + #include /** @@ -154,12 +173,21 @@ static inline uint64_t cvmx_pcie_get_mem_size(int pcie_port) */ static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) { - union cvmx_pescx_cfg_rd pescx_cfg_rd; - pescx_cfg_rd.u64 = 0; - pescx_cfg_rd.s.addr = cfg_offset; - cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); - pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); - return pescx_cfg_rd.s.data; + if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { + union cvmx_pescx_cfg_rd pescx_cfg_rd; + pescx_cfg_rd.u64 = 0; + pescx_cfg_rd.s.addr = cfg_offset; + cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); + pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); + return pescx_cfg_rd.s.data; + } else { + union cvmx_pemx_cfg_rd pemx_cfg_rd; + pemx_cfg_rd.u64 = 0; + pemx_cfg_rd.s.addr = cfg_offset; + cvmx_write_csr(CVMX_PEMX_CFG_RD(pcie_port), pemx_cfg_rd.u64); + pemx_cfg_rd.u64 = cvmx_read_csr(CVMX_PEMX_CFG_RD(pcie_port)); + return pemx_cfg_rd.s.data; + } } /** @@ -173,11 +201,19 @@ static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val) { - union cvmx_pescx_cfg_wr pescx_cfg_wr; - pescx_cfg_wr.u64 = 0; - pescx_cfg_wr.s.addr = cfg_offset; - pescx_cfg_wr.s.data = val; - cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); + if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { + union cvmx_pescx_cfg_wr pescx_cfg_wr; + pescx_cfg_wr.u64 = 0; + pescx_cfg_wr.s.addr = cfg_offset; + pescx_cfg_wr.s.data = val; + cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); + } else { + union cvmx_pemx_cfg_wr pemx_cfg_wr; + pemx_cfg_wr.u64 = 0; + pemx_cfg_wr.s.addr = cfg_offset; + pemx_cfg_wr.s.data = val; + cvmx_write_csr(CVMX_PEMX_CFG_WR(pcie_port), pemx_cfg_wr.u64); + } } /** @@ -348,7 +384,6 @@ static void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) { union cvmx_pciercx_cfg030 pciercx_cfg030; - union cvmx_npei_ctl_status2 npei_ctl_status2; union cvmx_pciercx_cfg070 pciercx_cfg070; union cvmx_pciercx_cfg001 pciercx_cfg001; union cvmx_pciercx_cfg032 pciercx_cfg032; @@ -365,21 +400,21 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ - pciercx_cfg030.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); - /* - * Max payload size = 128 bytes for best Octeon DMA - * performance. - */ - pciercx_cfg030.s.mps = 0; + + pciercx_cfg030.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); + if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) { + pciercx_cfg030.s.mps = MPS_CN5XXX; + pciercx_cfg030.s.mrrs = MRRS_CN5XXX; + } else { + pciercx_cfg030.s.mps = MPS_CN6XXX; + pciercx_cfg030.s.mrrs = MRRS_CN6XXX; + } /* - * Max read request size = 128 bytes for best Octeon DMA - * performance. + * Enable relaxed order processing. This will allow devices to + * affect read response ordering. */ - pciercx_cfg030.s.mrrs = 0; - /* Enable relaxed ordering. */ pciercx_cfg030.s.ro_en = 1; - /* Enable no snoop. */ + /* Enable no snoop processing. Not used by Octeon */ pciercx_cfg030.s.ns_en = 1; /* Correctable error reporting enable. */ pciercx_cfg030.s.ce_en = 1; @@ -389,50 +424,67 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) pciercx_cfg030.s.fe_en = 1; /* Unsupported request reporting enable. */ pciercx_cfg030.s.ur_en = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), - pciercx_cfg030.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), pciercx_cfg030.u32); - /* - * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match - * PCIE*_CFG030[MPS] - * - * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not - * exceed PCIE*_CFG030[MRRS]. - */ - npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); - /* Max payload size = 128 bytes for best Octeon DMA performance */ - npei_ctl_status2.s.mps = 0; - /* Max read request size = 128 bytes for best Octeon DMA performance */ - npei_ctl_status2.s.mrrs = 0; - if (pcie_port) - npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ - else - npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ - cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); + + if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { + union cvmx_npei_ctl_status2 npei_ctl_status2; + /* + * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match + * PCIE*_CFG030[MPS]. Max Read Request Size + * (NPEI_CTL_STATUS2[MRRS]) must not exceed + * PCIE*_CFG030[MRRS] + */ + npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); + /* Max payload size = 128 bytes for best Octeon DMA performance */ + npei_ctl_status2.s.mps = MPS_CN5XXX; + /* Max read request size = 128 bytes for best Octeon DMA performance */ + npei_ctl_status2.s.mrrs = MRRS_CN5XXX; + if (pcie_port) + npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ + else + npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ + + cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); + } else { + /* + * Max Payload Size (DPI_SLI_PRTX_CFG[MPS]) must match + * PCIE*_CFG030[MPS]. Max Read Request Size + * (DPI_SLI_PRTX_CFG[MRRS]) must not exceed + * PCIE*_CFG030[MRRS]. + */ + union cvmx_dpi_sli_prtx_cfg prt_cfg; + union cvmx_sli_s2m_portx_ctl sli_s2m_portx_ctl; + prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port)); + prt_cfg.s.mps = MPS_CN6XXX; + prt_cfg.s.mrrs = MRRS_CN6XXX; + /* Max outstanding load request. */ + prt_cfg.s.molr = 32; + cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port), prt_cfg.u64); + + sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port)); + sli_s2m_portx_ctl.s.mrrs = MRRS_CN6XXX; + cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port), sli_s2m_portx_ctl.u64); + } /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ - pciercx_cfg070.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); + pciercx_cfg070.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), - pciercx_cfg070.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), pciercx_cfg070.u32); /* - * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should - * always be set. - * - * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error - * Message Enable (PCIE*_CFG001[SEE]) + * Access Enables (PCIE*_CFG001[MSAE,ME]) + * ME and MSAE should always be set. + * Interrupt Disable (PCIE*_CFG001[I_DIS]) + * System Error Message Enable (PCIE*_CFG001[SEE]) */ - pciercx_cfg001.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); + pciercx_cfg001.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); pciercx_cfg001.s.msae = 1; /* Memory space enable. */ pciercx_cfg001.s.me = 1; /* Bus master enable. */ pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ pciercx_cfg001.s.see = 1; /* SERR# enable */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), - pciercx_cfg001.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), pciercx_cfg001.u32); /* Advanced Error Recovery Message Enables */ /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ @@ -440,14 +492,11 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) /* Use CVMX_PCIERCX_CFG067 hardware default */ cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); - /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ - pciercx_cfg032.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); - pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), - pciercx_cfg032.u32); - /* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */ + /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), pciercx_cfg032.u32); /* * Link Width Mode (PCIERCn_CFG452[LME]) - Set during @@ -462,8 +511,8 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) pciercx_cfg006.s.pbnum = 1; pciercx_cfg006.s.sbnum = 1; pciercx_cfg006.s.subbnum = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), - pciercx_cfg006.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), pciercx_cfg006.u32); + /* * Memory-mapped I/O BAR (PCIERCn_CFG008) @@ -473,8 +522,8 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) pciercx_cfg008.u32 = 0; pciercx_cfg008.s.mb_addr = 0x100; pciercx_cfg008.s.ml_addr = 0; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), - pciercx_cfg008.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), pciercx_cfg008.u32); + /* * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) @@ -482,72 +531,51 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] */ - pciercx_cfg009.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); - pciercx_cfg010.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); - pciercx_cfg011.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); + pciercx_cfg009.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); + pciercx_cfg010.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); + pciercx_cfg011.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); pciercx_cfg009.s.lmem_base = 0x100; pciercx_cfg009.s.lmem_limit = 0; pciercx_cfg010.s.umem_base = 0x100; pciercx_cfg011.s.umem_limit = 0; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), - pciercx_cfg009.u32); - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), - pciercx_cfg010.u32); - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), - pciercx_cfg011.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), pciercx_cfg009.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), pciercx_cfg010.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), pciercx_cfg011.u32); /* * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) * PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) - */ - pciercx_cfg035.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); - /* System error on correctable error enable. */ - pciercx_cfg035.s.secee = 1; - /* System error on fatal error enable. */ - pciercx_cfg035.s.sefee = 1; - /* System error on non-fatal error enable. */ - pciercx_cfg035.s.senfee = 1; - /* PME interrupt enable. */ - pciercx_cfg035.s.pmeie = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), - pciercx_cfg035.u32); + */ + pciercx_cfg035.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); + pciercx_cfg035.s.secee = 1; /* System error on correctable error enable. */ + pciercx_cfg035.s.sefee = 1; /* System error on fatal error enable. */ + pciercx_cfg035.s.senfee = 1; /* System error on non-fatal error enable. */ + pciercx_cfg035.s.pmeie = 1; /* PME interrupt enable. */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), pciercx_cfg035.u32); /* * Advanced Error Recovery Interrupt Enables * (PCIERCn_CFG075[CERE,NFERE,FERE]) */ - pciercx_cfg075.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); - /* Correctable error reporting enable. */ - pciercx_cfg075.s.cere = 1; - /* Non-fatal error reporting enable. */ - pciercx_cfg075.s.nfere = 1; - /* Fatal error reporting enable. */ - pciercx_cfg075.s.fere = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), - pciercx_cfg075.u32); + pciercx_cfg075.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); + pciercx_cfg075.s.cere = 1; /* Correctable error reporting enable. */ + pciercx_cfg075.s.nfere = 1; /* Non-fatal error reporting enable. */ + pciercx_cfg075.s.fere = 1; /* Fatal error reporting enable. */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), pciercx_cfg075.u32); - /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], + /* + * HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], * PCIERCn_CFG034[DLLS_EN,CCINT_EN]) */ - pciercx_cfg034.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); - /* Hot-plug interrupt enable. */ - pciercx_cfg034.s.hpint_en = 1; - /* Data Link Layer state changed enable */ - pciercx_cfg034.s.dlls_en = 1; - /* Command completed interrupt enable. */ - pciercx_cfg034.s.ccint_en = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), - pciercx_cfg034.u32); + pciercx_cfg034.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); + pciercx_cfg034.s.hpint_en = 1; /* Hot-plug interrupt enable. */ + pciercx_cfg034.s.dlls_en = 1; /* Data Link Layer state changed enable */ + pciercx_cfg034.s.ccint_en = 1; /* Command completed interrupt enable. */ + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), pciercx_cfg034.u32); } /** - * Initialize a host mode PCIe link. This function takes a PCIe + * Initialize a host mode PCIe gen 1 link. This function takes a PCIe * port from reset to a link up state. Software can then begin * configuring the rest of the link. * @@ -555,7 +583,7 @@ static void __cvmx_pcie_rc_initialize_config_space(int pcie_port) * * Returns Zero on success */ -static int __cvmx_pcie_rc_initialize_link(int pcie_port) +static int __cvmx_pcie_rc_initialize_link_gen1(int pcie_port) { uint64_t start_cycle; union cvmx_pescx_ctl_status pescx_ctl_status; @@ -564,18 +592,15 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) union cvmx_pciercx_cfg448 pciercx_cfg448; /* Set the lane width */ - pciercx_cfg452.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); + pciercx_cfg452.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); - if (pescx_ctl_status.s.qlm_cfg == 0) { + if (pescx_ctl_status.s.qlm_cfg == 0) /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ pciercx_cfg452.s.lme = 0xf; - } else { + else /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ pciercx_cfg452.s.lme = 0x7; - } - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), - pciercx_cfg452.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), pciercx_cfg452.u32); /* * CN52XX pass 1.x has an errata where length mismatches on UR @@ -584,19 +609,15 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) */ if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { union cvmx_pciercx_cfg455 pciercx_cfg455; - pciercx_cfg455.u32 = - cvmx_pcie_cfgx_read(pcie_port, - CVMX_PCIERCX_CFG455(pcie_port)); + pciercx_cfg455.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG455(pcie_port)); pciercx_cfg455.s.m_cpl_len_err = 1; - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), - pciercx_cfg455.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), pciercx_cfg455.u32); } /* Lane swap needs to be manually enabled for CN52XX */ if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) { pescx_ctl_status.s.lane_swp = 1; - cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), - pescx_ctl_status.u64); + cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); } /* Bring up the link */ @@ -612,24 +633,18 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); /* Wait for the link to come up */ - cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port); start_cycle = cvmx_get_cycle(); do { - if (cvmx_get_cycle() - start_cycle > - 2 * cvmx_sysinfo_get()->cpu_clock_hz) { - cvmx_dprintf("PCIe: Port %d link timeout\n", - pcie_port); + if (cvmx_get_cycle() - start_cycle > 2 * octeon_get_clock_rate()) { + cvmx_dprintf("PCIe: Port %d link timeout\n", pcie_port); return -1; } cvmx_wait(10000); - pciercx_cfg032.u32 = - cvmx_pcie_cfgx_read(pcie_port, - CVMX_PCIERCX_CFG032(pcie_port)); + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); } while (pciercx_cfg032.s.dlla == 0); - /* Display the link status */ - cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, - pciercx_cfg032.s.nlw); + /* Clear all pending errors */ + cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM)); /* * Update the Replay Time Limit. Empirically, some PCIe @@ -639,8 +654,7 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) * our actual 256 byte MPS. The numbers below are directly * from the PCIe spec table 3-4. */ - pciercx_cfg448.u32 = - cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); + pciercx_cfg448.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); switch (pciercx_cfg032.s.nlw) { case 1: /* 1 lane */ pciercx_cfg448.s.rtl = 1677; @@ -655,21 +669,28 @@ static int __cvmx_pcie_rc_initialize_link(int pcie_port) pciercx_cfg448.s.rtl = 258; break; } - cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), - pciercx_cfg448.u32); + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), pciercx_cfg448.u32); return 0; } +static void __cvmx_increment_ba(union cvmx_sli_mem_access_subidx *pmas) +{ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + pmas->cn68xx.ba++; + else + pmas->cn63xx.ba++; +} + /** - * Initialize a PCIe port for use in host(RC) mode. It doesn't + * Initialize a PCIe gen 1 port for use in host(RC) mode. It doesn't * enumerate the bus. * * @pcie_port: PCIe port to initialize * * Returns Zero on success */ -static int cvmx_pcie_rc_initialize(int pcie_port) +static int __cvmx_pcie_rc_initialize_gen1(int pcie_port) { int i; int base; @@ -682,16 +703,17 @@ static int cvmx_pcie_rc_initialize(int pcie_port) union cvmx_npei_mem_access_subidx mem_access_subid; union cvmx_npei_dbg_data npei_dbg_data; union cvmx_pescx_ctl_status2 pescx_ctl_status2; + union cvmx_pciercx_cfg032 pciercx_cfg032; union cvmx_npei_bar1_indexx bar1_index; +retry: /* * Make sure we aren't trying to setup a target mode interface * in host mode. */ npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) { - cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called " - "on port0, but port0 is not in host mode\n"); + cvmx_dprintf("PCIe: Port %d in endpoint mode\n", pcie_port); return -1; } @@ -702,9 +724,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port) if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) { - cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() " - "called on port1, but port1 is " - "disabled\n"); + cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called on port1, but port1 is disabled\n"); return -1; } } @@ -733,7 +753,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port) * the board. As a workaround for this bug, we bring * both PCIe ports out of reset at the same time * instead of on separate calls. So for port 0, we - * bring both out of reset and do nothing on port 1. + * bring both out of reset and do nothing on port 1 */ if (pcie_port == 0) { ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); @@ -746,13 +766,10 @@ static int cvmx_pcie_rc_initialize(int pcie_port) if (ciu_soft_prst.s.soft_prst == 0) { /* Reset the ports */ ciu_soft_prst.s.soft_prst = 1; - cvmx_write_csr(CVMX_CIU_SOFT_PRST, - ciu_soft_prst.u64); - ciu_soft_prst.u64 = - cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); ciu_soft_prst.s.soft_prst = 1; - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, - ciu_soft_prst.u64); + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); /* Wait until pcie resets the ports. */ udelay(2000); } @@ -782,11 +799,9 @@ static int cvmx_pcie_rc_initialize(int pcie_port) /* Reset the port */ ciu_soft_prst.s.soft_prst = 1; if (pcie_port) - cvmx_write_csr(CVMX_CIU_SOFT_PRST1, - ciu_soft_prst.u64); + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); else - cvmx_write_csr(CVMX_CIU_SOFT_PRST, - ciu_soft_prst.u64); + cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); /* Wait until pcie resets the ports. */ udelay(2000); } @@ -808,25 +823,21 @@ static int cvmx_pcie_rc_initialize(int pcie_port) */ cvmx_wait(400000); - /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and - CN52XX, so we only probe it on newer chips */ - if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) - && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { + /* + * PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of + * CN56XX and CN52XX, so we only probe it on newer chips + */ + if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { /* Clear PCLK_RUN so we can check if the clock is running */ - pescx_ctl_status2.u64 = - cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); + pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); pescx_ctl_status2.s.pclk_run = 1; - cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), - pescx_ctl_status2.u64); - /* - * Now that we cleared PCLK_RUN, wait for it to be set - * again telling us the clock is running. + cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), pescx_ctl_status2.u64); + /* Now that we cleared PCLK_RUN, wait for it to be set + * again telling us the clock is running */ if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), - union cvmx_pescx_ctl_status2, - pclk_run, ==, 1, 10000)) { - cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", - pcie_port); + union cvmx_pescx_ctl_status2, pclk_run, ==, 1, 10000)) { + cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", pcie_port); return -1; } } @@ -836,30 +847,26 @@ static int cvmx_pcie_rc_initialize(int pcie_port) * the board probably hasn't wired the clocks up and the * interface should be skipped. */ - pescx_ctl_status2.u64 = - cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); + pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); if (pescx_ctl_status2.s.pcierst) { - cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", - pcie_port); + cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", pcie_port); return -1; } /* - * Check BIST2 status. If any bits are set skip this interface. This - * is an attempt to catch PCIE-813 on pass 1 parts. + * Check BIST2 status. If any bits are set skip this + * interface. This is an attempt to catch PCIE-813 on pass 1 + * parts. */ - pescx_bist_status2.u64 = - cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); + pescx_bist_status2.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); if (pescx_bist_status2.u64) { - cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this " - "port isn't hooked up, skipping.\n", + cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this port isn't hooked up, skipping.\n", pcie_port); return -1; } /* Check BIST status */ - pescx_bist_status.u64 = - cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); + pescx_bist_status.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); if (pescx_bist_status.u64) cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pescx_bist_status.u64)); @@ -868,50 +875,37 @@ static int cvmx_pcie_rc_initialize(int pcie_port) __cvmx_pcie_rc_initialize_config_space(pcie_port); /* Bring the link up */ - if (__cvmx_pcie_rc_initialize_link(pcie_port)) { - cvmx_dprintf - ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n"); + if (__cvmx_pcie_rc_initialize_link_gen1(pcie_port)) { + cvmx_dprintf("PCIe: Failed to initialize port %d, probably the slot is empty\n", + pcie_port); return -1; } /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); - /* Allow 16 words to combine */ - npei_mem_access_ctl.s.max_word = 0; - /* Wait up to 127 cycles for more data */ - npei_mem_access_ctl.s.timer = 127; + npei_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ + npei_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); /* Setup Mem access SubDIDs */ mem_access_subid.u64 = 0; - /* Port the request is sent to. */ - mem_access_subid.s.port = pcie_port; - /* Due to an errata on pass 1 chips, no merging is allowed. */ - mem_access_subid.s.nmerge = 1; - /* Endian-swap for Reads. */ - mem_access_subid.s.esr = 1; - /* Endian-swap for Writes. */ - mem_access_subid.s.esw = 1; - /* No Snoop for Reads. */ - mem_access_subid.s.nsr = 1; - /* No Snoop for Writes. */ - mem_access_subid.s.nsw = 1; - /* Disable Relaxed Ordering for Reads. */ - mem_access_subid.s.ror = 0; - /* Disable Relaxed Ordering for Writes. */ - mem_access_subid.s.row = 0; - /* PCIe Address Bits <63:34>. */ - mem_access_subid.s.ba = 0; + mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ + mem_access_subid.s.nmerge = 1; /* Due to an errata on pass 1 chips, no merging is allowed. */ + mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ + mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ + mem_access_subid.s.nsr = 0; /* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */ + mem_access_subid.s.nsw = 0; /* Enable Snoop for Writes. */ + mem_access_subid.s.ror = 0; /* Disable Relaxed Ordering for Reads. */ + mem_access_subid.s.row = 0; /* Disable Relaxed Ordering for Writes. */ + mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ /* * Setup mem access 12-15 for port 0, 16-19 for port 1, * supplying 36 bits of address space. */ for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) { - cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), - mem_access_subid.u64); - /* Set each SUBID to extend the addressable range */ - mem_access_subid.s.ba += 1; + cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64); + mem_access_subid.s.ba += 1; /* Set each SUBID to extend the addressable range */ } /* @@ -927,7 +921,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port) /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); - /* BAR1 follows BAR2 with a gap. */ + /* BAR1 follows BAR2 with a gap so it has the same address as for gen2. */ cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); bar1_index.u32 = 0; @@ -992,13 +986,473 @@ static int cvmx_pcie_rc_initialize(int pcie_port) npei_ctl_port.s.waitl_com = 0; cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); } + + /* + * Both pass 1 and pass 2 of CN52XX and CN56XX have an errata + * that causes TLP ordering to not be preserved after multiple + * PCIe port resets. This code detects this fault and corrects + * it by aligning the TLP counters properly. Another link + * reset is then performed. See PCIE-13340 + */ + if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || + OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) || + OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) || + OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { + union cvmx_npei_dbg_data dbg_data; + int old_in_fif_p_count; + int in_fif_p_count; + int out_p_count; + int in_p_offset = (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ? 4 : 1; + int i; + + /* + * Choose a write address of 1MB. It should be + * harmless as all bars haven't been setup. + */ + uint64_t write_address = (cvmx_pcie_get_mem_base_address(pcie_port) + 0x100000) | (1ull<<63); + + /* + * Make sure at least in_p_offset have been executed before we try and + * read in_fif_p_count + */ + i = in_p_offset; + while (i--) { + cvmx_write64_uint32(write_address, 0); + cvmx_wait(10000); + } + + /* + * Read the IN_FIF_P_COUNT from the debug + * select. IN_FIF_P_COUNT can be unstable sometimes so + * read it twice with a write between the reads. This + * way we can tell the value is good as it will + * increment by one due to the write + */ + cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd7fc : 0xcffc); + cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT); + do { + dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); + old_in_fif_p_count = dbg_data.s.data & 0xff; + cvmx_write64_uint32(write_address, 0); + cvmx_wait(10000); + dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); + in_fif_p_count = dbg_data.s.data & 0xff; + } while (in_fif_p_count != ((old_in_fif_p_count+1) & 0xff)); + + /* Update in_fif_p_count for it's offset with respect to out_p_count */ + in_fif_p_count = (in_fif_p_count + in_p_offset) & 0xff; + + /* Read the OUT_P_COUNT from the debug select */ + cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd00f : 0xc80f); + cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT); + dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); + out_p_count = (dbg_data.s.data>>1) & 0xff; + + /* Check that the two counters are aligned */ + if (out_p_count != in_fif_p_count) { + cvmx_dprintf("PCIe: Port %d aligning TLP counters as workaround to maintain ordering\n", pcie_port); + while (in_fif_p_count != 0) { + cvmx_write64_uint32(write_address, 0); + cvmx_wait(10000); + in_fif_p_count = (in_fif_p_count + 1) & 0xff; + } + /* + * The EBH5200 board swapped the PCIe reset + * lines on the board. This means we must + * bring both links down and up, which will + * cause the PCIe0 to need alignment + * again. Lots of messages will be displayed, + * but everything should work + */ + if ((cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) && + (pcie_port == 1)) + cvmx_pcie_rc_initialize(0); + /* Rety bringing this port up */ + goto retry; + } + } + + /* Display the link status */ + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, pciercx_cfg032.s.nlw); + return 0; } +/** + * Initialize a host mode PCIe gen 2 link. This function takes a PCIe + * port from reset to a link up state. Software can then begin + * configuring the rest of the link. + * + * @pcie_port: PCIe port to initialize + * + * Return Zero on success. + */ +static int __cvmx_pcie_rc_initialize_link_gen2(int pcie_port) +{ + uint64_t start_cycle; + union cvmx_pemx_ctl_status pem_ctl_status; + union cvmx_pciercx_cfg032 pciercx_cfg032; + union cvmx_pciercx_cfg448 pciercx_cfg448; -/* Above was cvmx-pcie.c, below original pcie.c */ + /* Bring up the link */ + pem_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port)); + pem_ctl_status.s.lnk_enb = 1; + cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pem_ctl_status.u64); + + /* Wait for the link to come up */ + start_cycle = cvmx_get_cycle(); + do { + if (cvmx_get_cycle() - start_cycle > octeon_get_clock_rate()) + return -1; + cvmx_wait(10000); + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + } while ((pciercx_cfg032.s.dlla == 0) || (pciercx_cfg032.s.lt == 1)); + + /* + * Update the Replay Time Limit. Empirically, some PCIe + * devices take a little longer to respond than expected under + * load. As a workaround for this we configure the Replay Time + * Limit to the value expected for a 512 byte MPS instead of + * our actual 256 byte MPS. The numbers below are directly + * from the PCIe spec table 3-4 + */ + pciercx_cfg448.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); + switch (pciercx_cfg032.s.nlw) { + case 1: /* 1 lane */ + pciercx_cfg448.s.rtl = 1677; + break; + case 2: /* 2 lanes */ + pciercx_cfg448.s.rtl = 867; + break; + case 4: /* 4 lanes */ + pciercx_cfg448.s.rtl = 462; + break; + case 8: /* 8 lanes */ + pciercx_cfg448.s.rtl = 258; + break; + } + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), pciercx_cfg448.u32); + + return 0; +} +/** + * Initialize a PCIe gen 2 port for use in host(RC) mode. It doesn't enumerate + * the bus. + * + * @pcie_port: PCIe port to initialize + * + * Returns Zero on success. + */ +static int __cvmx_pcie_rc_initialize_gen2(int pcie_port) +{ + int i; + union cvmx_ciu_soft_prst ciu_soft_prst; + union cvmx_mio_rst_ctlx mio_rst_ctl; + union cvmx_pemx_bar_ctl pemx_bar_ctl; + union cvmx_pemx_ctl_status pemx_ctl_status; + union cvmx_pemx_bist_status pemx_bist_status; + union cvmx_pemx_bist_status2 pemx_bist_status2; + union cvmx_pciercx_cfg032 pciercx_cfg032; + union cvmx_pciercx_cfg515 pciercx_cfg515; + union cvmx_sli_ctl_portx sli_ctl_portx; + union cvmx_sli_mem_access_ctl sli_mem_access_ctl; + union cvmx_sli_mem_access_subidx mem_access_subid; + union cvmx_sriox_status_reg sriox_status_reg; + union cvmx_pemx_bar1_indexx bar1_index; + + if (octeon_has_feature(OCTEON_FEATURE_SRIO)) { + /* Make sure this interface isn't SRIO */ + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) { + /* + * The CN66XX requires reading the + * MIO_QLMX_CFG register to figure out the + * port type. + */ + union cvmx_mio_qlmx_cfg qlmx_cfg; + qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(pcie_port)); + + if (qlmx_cfg.s.qlm_spd == 15) { + pr_notice("PCIe: Port %d is disabled, skipping.\n", pcie_port); + return -1; + } + + switch (qlmx_cfg.s.qlm_spd) { + case 0x1: /* SRIO 1x4 short */ + case 0x3: /* SRIO 1x4 long */ + case 0x4: /* SRIO 2x2 short */ + case 0x6: /* SRIO 2x2 long */ + pr_notice("PCIe: Port %d is SRIO, skipping.\n", pcie_port); + return -1; + case 0x9: /* SGMII */ + pr_notice("PCIe: Port %d is SGMII, skipping.\n", pcie_port); + return -1; + case 0xb: /* XAUI */ + pr_notice("PCIe: Port %d is XAUI, skipping.\n", pcie_port); + return -1; + case 0x0: /* PCIE gen2 */ + case 0x8: /* PCIE gen2 (alias) */ + case 0x2: /* PCIE gen1 */ + case 0xa: /* PCIE gen1 (alias) */ + break; + default: + pr_notice("PCIe: Port %d is unknown, skipping.\n", pcie_port); + return -1; + } + } else { + sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(pcie_port)); + if (sriox_status_reg.s.srio) { + pr_notice("PCIe: Port %d is SRIO, skipping.\n", pcie_port); + return -1; + } + } + } + +#if 0 + /* This code is so that the PCIe analyzer is able to see 63XX traffic */ + pr_notice("PCIE : init for pcie analyzer.\n"); + cvmx_helper_qlm_jtag_init(); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); + cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); + cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); + cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); + cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); + cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); + cvmx_helper_qlm_jtag_update(pcie_port); +#endif + + /* Make sure we aren't trying to setup a target mode interface in host mode */ + mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(pcie_port)); + if (!mio_rst_ctl.s.host_mode) { + pr_notice("PCIe: Port %d in endpoint mode.\n", pcie_port); + return -1; + } + + /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) { + if (pcie_port) { + union cvmx_ciu_qlm1 ciu_qlm; + ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); + ciu_qlm.s.txbypass = 1; + ciu_qlm.s.txdeemph = 5; + ciu_qlm.s.txmargin = 0x17; + cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); + } else { + union cvmx_ciu_qlm0 ciu_qlm; + ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); + ciu_qlm.s.txbypass = 1; + ciu_qlm.s.txdeemph = 5; + ciu_qlm.s.txmargin = 0x17; + cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); + } + } + /* Bring the PCIe out of reset */ + if (pcie_port) + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + else + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + /* + * After a chip reset the PCIe will also be in reset. If it + * isn't, most likely someone is trying to init it again + * without a proper PCIe reset + */ + if (ciu_soft_prst.s.soft_prst == 0) { + /* Reset the port */ + ciu_soft_prst.s.soft_prst = 1; + if (pcie_port) + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); + else + cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); + /* Wait until pcie resets the ports. */ + udelay(2000); + } + if (pcie_port) { + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); + ciu_soft_prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); + } else { + ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); + ciu_soft_prst.s.soft_prst = 0; + cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); + } + + /* Wait for PCIe reset to complete */ + udelay(1000); + + /* + * Check and make sure PCIe came out of reset. If it doesn't + * the board probably hasn't wired the clocks up and the + * interface should be skipped. + */ + if (CVMX_WAIT_FOR_FIELD64(CVMX_MIO_RST_CTLX(pcie_port), union cvmx_mio_rst_ctlx, rst_done, ==, 1, 10000)) { + pr_notice("PCIe: Port %d stuck in reset, skipping.\n", pcie_port); + return -1; + } + + /* Check BIST status */ + pemx_bist_status.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS(pcie_port)); + if (pemx_bist_status.u64) + pr_notice("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status.u64)); + pemx_bist_status2.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS2(pcie_port)); + /* Errata PCIE-14766 may cause the lower 6 bits to be randomly set on CN63XXp1 */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) + pemx_bist_status2.u64 &= ~0x3full; + if (pemx_bist_status2.u64) + pr_notice("PCIe: BIST2 FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status2.u64)); + + /* Initialize the config space CSRs */ + __cvmx_pcie_rc_initialize_config_space(pcie_port); + + /* Enable gen2 speed selection */ + pciercx_cfg515.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG515(pcie_port)); + pciercx_cfg515.s.dsc = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG515(pcie_port), pciercx_cfg515.u32); + + /* Bring the link up */ + if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) { + /* + * Some gen1 devices don't handle the gen 2 training + * correctly. Disable gen2 and try again with only + * gen1 + */ + union cvmx_pciercx_cfg031 pciercx_cfg031; + pciercx_cfg031.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG031(pcie_port)); + pciercx_cfg031.s.mls = 1; + cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG031(pcie_port), pciercx_cfg031.u32); + if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) { + pr_notice("PCIe: Link timeout on port %d, probably the slot is empty\n", pcie_port); + return -1; + } + } + + /* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ + sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL); + sli_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ + sli_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ + cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_mem_access_ctl.u64); + + /* Setup Mem access SubDIDs */ + mem_access_subid.u64 = 0; + mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ + mem_access_subid.s.nmerge = 0; /* Allow merging as it works on CN6XXX. */ + mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ + mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ + mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ + mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ + /* PCIe Adddress Bits <63:34>. */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + mem_access_subid.cn68xx.ba = 0; + else + mem_access_subid.cn63xx.ba = 0; + + /* + * Setup mem access 12-15 for port 0, 16-19 for port 1, + * supplying 36 bits of address space. + */ + for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) { + cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64); + /* Set each SUBID to extend the addressable range */ + __cvmx_increment_ba(&mem_access_subid); + } + + /* + * Disable the peer to peer forwarding register. This must be + * setup by the OS after it enumerates the bus and assigns + * addresses to the PCIe busses. + */ + for (i = 0; i < 4; i++) { + cvmx_write_csr(CVMX_PEMX_P2P_BARX_START(i, pcie_port), -1); + cvmx_write_csr(CVMX_PEMX_P2P_BARX_END(i, pcie_port), -1); + } + + /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ + cvmx_write_csr(CVMX_PEMX_P2N_BAR0_START(pcie_port), 0); + + /* + * Set Octeon's BAR2 to decode 0-2^41. Bar0 and Bar1 take + * precedence where they overlap. It also overlaps with the + * device addresses, so make sure the peer to peer forwarding + * is set right. + */ + cvmx_write_csr(CVMX_PEMX_P2N_BAR2_START(pcie_port), 0); + + /* + * Setup BAR2 attributes + * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) + * - PTLP_RO,CTLP_RO should normally be set (except for debug). + * - WAIT_COM=0 will likely work for all applications. + * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]) + */ + pemx_bar_ctl.u64 = cvmx_read_csr(CVMX_PEMX_BAR_CTL(pcie_port)); + pemx_bar_ctl.s.bar1_siz = 3; /* 256MB BAR1*/ + pemx_bar_ctl.s.bar2_enb = 1; + pemx_bar_ctl.s.bar2_esx = 1; + pemx_bar_ctl.s.bar2_cax = 0; + cvmx_write_csr(CVMX_PEMX_BAR_CTL(pcie_port), pemx_bar_ctl.u64); + sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port)); + sli_ctl_portx.s.ptlp_ro = 1; + sli_ctl_portx.s.ctlp_ro = 1; + sli_ctl_portx.s.wait_com = 0; + sli_ctl_portx.s.waitl_com = 0; + cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port), sli_ctl_portx.u64); + + /* BAR1 follows BAR2 */ + cvmx_write_csr(CVMX_PEMX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); + + bar1_index.u64 = 0; + bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); + bar1_index.s.ca = 1; /* Not Cached */ + bar1_index.s.end_swp = 1; /* Endian Swap mode */ + bar1_index.s.addr_v = 1; /* Valid entry */ + + for (i = 0; i < 16; i++) { + cvmx_write_csr(CVMX_PEMX_BAR1_INDEXX(i, pcie_port), bar1_index.u64); + /* 256MB / 16 >> 22 == 4 */ + bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); + } + + /* + * Allow config retries for 250ms. Count is based off the 5Ghz + * SERDES clock. + */ + pemx_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port)); + pemx_ctl_status.s.cfg_rtry = 250 * 5000000 / 0x10000; + cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pemx_ctl_status.u64); + + /* Display the link status */ + pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); + pr_notice("PCIe: Port %d link active, %d lanes, speed gen%d\n", pcie_port, pciercx_cfg032.s.nlw, pciercx_cfg032.s.ls); + + return 0; +} + +/** + * Initialize a PCIe port for use in host(RC) mode. It doesn't enumerate the bus. + * + * @pcie_port: PCIe port to initialize + * + * Returns Zero on success + */ +static int cvmx_pcie_rc_initialize(int pcie_port) +{ + int result; + if (octeon_has_feature(OCTEON_FEATURE_NPEI)) + result = __cvmx_pcie_rc_initialize_gen1(pcie_port); + else + result = __cvmx_pcie_rc_initialize_gen2(pcie_port); + return result; +} + +/* Above was cvmx-pcie.c, below original pcie.c */ + /** * Map a PCI device to the appropriate interrupt line * @@ -1027,11 +1481,12 @@ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, */ while (dev->bus && dev->bus->parent) dev = to_pci_dev(dev->bus->bridge); - /* If the root bus is number 0 and the PEX 8114 is the + /* + * If the root bus is number 0 and the PEX 8114 is the * root, assume we are behind the miswired bus. We * need to correct the swizzle level by two. Yuck. */ - if ((dev->bus->number == 0) && + if ((dev->bus->number == 1) && (dev->vendor == 0x10b5) && (dev->device == 0x8114)) { /* * The pin field is one based, not zero. We @@ -1048,39 +1503,73 @@ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, return pin - 1 + OCTEON_IRQ_PCI_INT0; } -/** +static void set_cfg_read_retry(u32 retry_cnt) +{ + union cvmx_pemx_ctl_status pemx_ctl; + pemx_ctl.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(1)); + pemx_ctl.s.cfg_rtry = retry_cnt; + cvmx_write_csr(CVMX_PEMX_CTL_STATUS(1), pemx_ctl.u64); +} + + +static u32 disable_cfg_read_retry(void) +{ + u32 retry_cnt; + + union cvmx_pemx_ctl_status pemx_ctl; + pemx_ctl.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(1)); + retry_cnt = pemx_ctl.s.cfg_rtry; + pemx_ctl.s.cfg_rtry = 0; + cvmx_write_csr(CVMX_PEMX_CTL_STATUS(1), pemx_ctl.u64); + return retry_cnt; +} + +static int is_cfg_retry(void) +{ + union cvmx_pemx_int_sum pemx_int_sum; + pemx_int_sum.u64 = cvmx_read_csr(CVMX_PEMX_INT_SUM(1)); + if (pemx_int_sum.s.crs_dr) + return 1; + return 0; +} + +/* * Read a value from configuration space * - * @bus: - * @devfn: - * @reg: - * @size: - * @val: - * Returns */ -static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, - unsigned int devfn, int reg, int size, - u32 *val) +static int octeon_pcie_read_config(unsigned int pcie_port, struct pci_bus *bus, + unsigned int devfn, int reg, int size, + u32 *val) { union octeon_cvmemctl cvmmemctl; union octeon_cvmemctl cvmmemctl_save; int bus_number = bus->number; + int cfg_retry = 0; + int retry_cnt = 0; + int max_retry_cnt = 10; + u32 cfg_retry_cnt = 0; + cvmmemctl_save.u64 = 0; + BUG_ON(pcie_port >= ARRAY_SIZE(enable_pcie_bus_num_war)); /* * For the top level bus make sure our hardware bus number - * matches the software one. + * matches the software one */ if (bus->parent == NULL) { - union cvmx_pciercx_cfg006 pciercx_cfg006; - pciercx_cfg006.u32 = cvmx_pcie_cfgx_read(pcie_port, - CVMX_PCIERCX_CFG006(pcie_port)); - if (pciercx_cfg006.s.pbnum != bus_number) { - pciercx_cfg006.s.pbnum = bus_number; - pciercx_cfg006.s.sbnum = bus_number; - pciercx_cfg006.s.subbnum = bus_number; - cvmx_pcie_cfgx_write(pcie_port, - CVMX_PCIERCX_CFG006(pcie_port), - pciercx_cfg006.u32); + if (enable_pcie_bus_num_war[pcie_port]) + bus_number = 0; + else { + union cvmx_pciercx_cfg006 pciercx_cfg006; + pciercx_cfg006.u32 = cvmx_pcie_cfgx_read(pcie_port, + CVMX_PCIERCX_CFG006(pcie_port)); + if (pciercx_cfg006.s.pbnum != bus_number) { + pciercx_cfg006.s.pbnum = bus_number; + pciercx_cfg006.s.sbnum = bus_number; + pciercx_cfg006.s.subbnum = bus_number; + cvmx_pcie_cfgx_write(pcie_port, + CVMX_PCIERCX_CFG006(pcie_port), + pciercx_cfg006.u32); + } } } @@ -1116,29 +1605,52 @@ static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, */ #if 1 /* Use this option if you aren't using either slot */ - if (bus_number == 1) + if (bus_number == 2) return PCIBIOS_FUNC_NOT_SUPPORTED; #elif 0 /* * Use this option if you are using the first slot but * not the second. */ - if ((bus_number == 1) && (devfn >> 3 != 2)) + if ((bus_number == 2) && (devfn >> 3 != 2)) return PCIBIOS_FUNC_NOT_SUPPORTED; #elif 0 /* * Use this option if you are using the second slot * but not the first. */ - if ((bus_number == 1) && (devfn >> 3 != 3)) + if ((bus_number == 2) && (devfn >> 3 != 3)) return PCIBIOS_FUNC_NOT_SUPPORTED; #elif 0 /* Use this opion if you are using both slots */ - if ((bus_number == 1) && + if ((bus_number == 2) && !((devfn == (2 << 3)) || (devfn == (3 << 3)))) return PCIBIOS_FUNC_NOT_SUPPORTED; #endif + /* The following #if gives a more complicated example. This is + the required checks for running a Nitrox CN16XX-NHBX in the + slot of the EBH5600. This card has a PLX PCIe bridge with + four Nitrox PLX parts behind it */ +#if 0 + /* PLX bridge with 4 ports */ + if ((bus_number == 4) && + !((devfn >> 3 >= 1) && (devfn >> 3 <= 4))) + return PCIBIOS_FUNC_NOT_SUPPORTED; + /* Nitrox behind PLX 1 */ + if ((bus_number == 5) && (devfn >> 3 != 0)) + return PCIBIOS_FUNC_NOT_SUPPORTED; + /* Nitrox behind PLX 2 */ + if ((bus_number == 6) && (devfn >> 3 != 0)) + return PCIBIOS_FUNC_NOT_SUPPORTED; + /* Nitrox behind PLX 3 */ + if ((bus_number == 7) && (devfn >> 3 != 0)) + return PCIBIOS_FUNC_NOT_SUPPORTED; + /* Nitrox behind PLX 4 */ + if ((bus_number == 8) && (devfn >> 3 != 0)) + return PCIBIOS_FUNC_NOT_SUPPORTED; +#endif + /* * Shorten the DID timeout so bus errors for PCIe * config reads from non existent devices happen @@ -1152,26 +1664,48 @@ static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, __write_64bit_c0_register($11, 7, cvmmemctl.u64); } - switch (size) { - case 4: - *val = cvmx_pcie_config_read32(pcie_port, bus_number, - devfn >> 3, devfn & 0x7, reg); + if ((OCTEON_IS_MODEL(OCTEON_CN63XX)) && (enable_pcie_14459_war)) + cfg_retry_cnt = disable_cfg_read_retry(); + + pr_debug("pcie_cfg_rd port=%d b=%d devfn=0x%03x reg=0x%03x" + " size=%d ", pcie_port, bus_number, devfn, reg, size); + do { + switch (size) { + case 4: + *val = cvmx_pcie_config_read32(pcie_port, bus_number, + devfn >> 3, devfn & 0x7, reg); break; - case 2: - *val = cvmx_pcie_config_read16(pcie_port, bus_number, - devfn >> 3, devfn & 0x7, reg); + case 2: + *val = cvmx_pcie_config_read16(pcie_port, bus_number, + devfn >> 3, devfn & 0x7, reg); break; - case 1: - *val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3, - devfn & 0x7, reg); + case 1: + *val = cvmx_pcie_config_read8(pcie_port, bus_number, + devfn >> 3, devfn & 0x7, reg); break; - default: - return PCIBIOS_FUNC_NOT_SUPPORTED; - } + default: + if (OCTEON_IS_MODEL(OCTEON_CN63XX)) + set_cfg_read_retry(cfg_retry_cnt); + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + if ((OCTEON_IS_MODEL(OCTEON_CN63XX)) && + (enable_pcie_14459_war)) { + cfg_retry = is_cfg_retry(); + retry_cnt++; + if (retry_cnt > max_retry_cnt) { + pr_err(" pcie cfg_read retries failed. retry_cnt=%d\n", + retry_cnt); + cfg_retry = 0; + } + } + } while (cfg_retry); + if ((OCTEON_IS_MODEL(OCTEON_CN63XX)) && (enable_pcie_14459_war)) + set_cfg_read_retry(cfg_retry_cnt); + pr_debug("val=%08x : tries=%02d\n", *val, retry_cnt); if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) - __write_64bit_c0_register($11, 7, cvmmemctl_save.u64); + write_c0_cvmmemctl(cvmmemctl_save.u64); return PCIBIOS_SUCCESSFUL; } @@ -1187,42 +1721,56 @@ static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn, return octeon_pcie_read_config(1, bus, devfn, reg, size, val); } +static int octeon_dummy_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + return PCIBIOS_FUNC_NOT_SUPPORTED; +} - -/** +/* * Write a value to PCI configuration space - * - * @bus: - * @devfn: - * @reg: - * @size: - * @val: - * Returns */ -static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus, - unsigned int devfn, int reg, - int size, u32 val) +static int octeon_pcie_write_config(unsigned int pcie_port, struct pci_bus *bus, + unsigned int devfn, int reg, + int size, u32 val) { int bus_number = bus->number; + BUG_ON(pcie_port >= ARRAY_SIZE(enable_pcie_bus_num_war)); + + if ((bus->parent == NULL) && (enable_pcie_bus_num_war[pcie_port])) + bus_number = 0; + + pr_debug("pcie_cfg_wr port=%d b=%d devfn=0x%03x" + " reg=0x%03x size=%d val=%08x\n", pcie_port, bus_number, devfn, + reg, size, val); + + switch (size) { case 4: cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3, devfn & 0x7, reg, val); - return PCIBIOS_SUCCESSFUL; + break; case 2: cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3, devfn & 0x7, reg, val); - return PCIBIOS_SUCCESSFUL; + break; case 1: cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3, devfn & 0x7, reg, val); - return PCIBIOS_SUCCESSFUL; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; } #if PCI_CONFIG_SPACE_DELAY + /* + * Delay on writes so that devices have time to come up. Some + * bridges need this to allow time for the secondary busses to + * work + */ udelay(PCI_CONFIG_SPACE_DELAY); #endif - return PCIBIOS_FUNC_NOT_SUPPORTED; + return PCIBIOS_SUCCESSFUL; } static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn, @@ -1237,6 +1785,12 @@ static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn, return octeon_pcie_write_config(1, bus, devfn, reg, size, val); } +static int octeon_dummy_write_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 val) +{ + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + static struct pci_ops octeon_pcie0_ops = { octeon_pcie0_read_config, octeon_pcie0_write_config, @@ -1279,6 +1833,35 @@ static struct pci_controller octeon_pcie1_controller = { .io_resource = &octeon_pcie1_io_resource, }; +static struct pci_ops octeon_dummy_ops = { + octeon_dummy_read_config, + octeon_dummy_write_config, +}; + +static struct resource octeon_dummy_mem_resource = { + .name = "Virtual PCIe MEM", + .flags = IORESOURCE_MEM, +}; + +static struct resource octeon_dummy_io_resource = { + .name = "Virtual PCIe IO", + .flags = IORESOURCE_IO, +}; + +static struct pci_controller octeon_dummy_controller = { + .pci_ops = &octeon_dummy_ops, + .mem_resource = &octeon_dummy_mem_resource, + .io_resource = &octeon_dummy_io_resource, +}; + +static int device_needs_bus_num_war(uint32_t deviceid) +{ +#define IDT_VENDOR_ID 0x111d + + if ((deviceid & 0xffff) == IDT_VENDOR_ID) + return 1; + return 0; +} /** * Initialize the Octeon PCIe controllers @@ -1287,19 +1870,27 @@ static struct pci_controller octeon_pcie1_controller = { */ static int __init octeon_pcie_setup(void) { - union cvmx_npei_ctl_status npei_ctl_status; int result; + int host_mode; + int srio_war15205 = 0, port; + union cvmx_sli_ctl_portx sli_ctl_portx; + union cvmx_sriox_status_reg sriox_status_reg; /* These chips don't have PCIe */ if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) return 0; + /* No PCIe simulation */ + if (octeon_is_simulation()) + return 0; + + /* Disable PCI if instructed on the command line */ + if (pcie_disable) + return 0; + /* Point pcibios_map_irq() to the PCIe version of it */ octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq; - /* Use the PCIe based DMA mappings */ - octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE; - /* * PCIe I/O range. It is based on port 0 but includes up until * port 1's end. @@ -1310,11 +1901,43 @@ static int __init octeon_pcie_setup(void) cvmx_pcie_get_io_base_address(1) - cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1; - npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); - if (npei_ctl_status.s.host_mode) { + /* + * Create a dummy PCIe controller to swallow up bus 0. IDT bridges + * don't work if the primary bus number is zero. Here we add a fake + * PCIe controller that the kernel will give bus 0. This allows + * us to not change the normal kernel bus enumeration + */ + octeon_dummy_controller.io_map_base = -1; + octeon_dummy_controller.mem_resource->start = (1ull<<48); + octeon_dummy_controller.mem_resource->end = (1ull<<48); + register_pci_controller(&octeon_dummy_controller); + + if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { + union cvmx_npei_ctl_status npei_ctl_status; + npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); + host_mode = npei_ctl_status.s.host_mode; + octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE; + } else { + union cvmx_mio_rst_ctlx mio_rst_ctl; + mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(0)); + host_mode = mio_rst_ctl.s.host_mode; + octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE2; + } + + if (host_mode) { pr_notice("PCIe: Initializing port 0\n"); + /* CN63XX pass 1_x/2.0 errata PCIe-15205 */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || + OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { + sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(0)); + if (sriox_status_reg.s.srio) { + srio_war15205 += 1; /* Port is SRIO */ + port = 0; + } + } result = cvmx_pcie_rc_initialize(0); if (result == 0) { + uint32_t device0; /* Memory offsets are physical addresses */ octeon_pcie0_controller.mem_offset = cvmx_pcie_get_mem_base_address(0); @@ -1343,60 +1966,134 @@ static int __init octeon_pcie_setup(void) octeon_pcie0_controller.io_resource->start = 4 << 10; octeon_pcie0_controller.io_resource->end = cvmx_pcie_get_io_size(0) - 1; + msleep(100); /* Some devices need extra time */ register_pci_controller(&octeon_pcie0_controller); + device0 = cvmx_pcie_config_read32(0, 0, 0, 0, 0); + enable_pcie_bus_num_war[0] = + device_needs_bus_num_war(device0); } } else { pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n"); + /* CN63XX pass 1_x/2.0 errata PCIe-15205 */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || + OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { + srio_war15205 += 1; + port = 0; + } } - /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { - union cvmx_npei_dbg_data npei_dbg_data; - npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); - if (npei_dbg_data.cn52xx.qlm0_link_width) - return 0; + if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { + host_mode = 1; + /* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX)) { + union cvmx_npei_dbg_data dbg_data; + dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); + if (dbg_data.cn52xx.qlm0_link_width) + host_mode = 0; + } + } else { + union cvmx_mio_rst_ctlx mio_rst_ctl; + mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(1)); + host_mode = mio_rst_ctl.s.host_mode; } - pr_notice("PCIe: Initializing port 1\n"); - result = cvmx_pcie_rc_initialize(1); - if (result == 0) { - /* Memory offsets are physical addresses */ - octeon_pcie1_controller.mem_offset = - cvmx_pcie_get_mem_base_address(1); - /* IO offsets are Mips virtual addresses */ - octeon_pcie1_controller.io_map_base = - CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1)); - octeon_pcie1_controller.io_offset = - cvmx_pcie_get_io_base_address(1) - - cvmx_pcie_get_io_base_address(0); - /* - * To keep things similar to PCI, we start device - * addresses at the same place as PCI uisng big bar - * support. This normally translates to 4GB-256MB, - * which is the same as most x86 PCs. - */ - octeon_pcie1_controller.mem_resource->start = - cvmx_pcie_get_mem_base_address(1) + (4ul << 30) - - (OCTEON_PCI_BAR1_HOLE_SIZE << 20); - octeon_pcie1_controller.mem_resource->end = - cvmx_pcie_get_mem_base_address(1) + - cvmx_pcie_get_mem_size(1) - 1; - /* - * Ports must be above 16KB for the ISA bus filtering - * in the PCI-X to PCI bridge. - */ - octeon_pcie1_controller.io_resource->start = - cvmx_pcie_get_io_base_address(1) - - cvmx_pcie_get_io_base_address(0); - octeon_pcie1_controller.io_resource->end = - octeon_pcie1_controller.io_resource->start + - cvmx_pcie_get_io_size(1) - 1; - register_pci_controller(&octeon_pcie1_controller); + if (host_mode) { + pr_notice("PCIe: Initializing port 1\n"); + /* CN63XX pass 1_x/2.0 errata PCIe-15205 */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || + OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { + sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(1)); + if (sriox_status_reg.s.srio) { + srio_war15205 += 1; /* Port is SRIO */ + port = 1; + } + } + result = cvmx_pcie_rc_initialize(1); + if (result == 0) { + uint32_t device0; + /* Memory offsets are physical addresses */ + octeon_pcie1_controller.mem_offset = + cvmx_pcie_get_mem_base_address(1); + /* + * To calculate the address for accessing the 2nd PCIe device, + * either 'io_map_base' (pci_iomap()), or 'mips_io_port_base' + * (ioport_map()) value is added to + * pci_resource_start(dev,bar)). The 'mips_io_port_base' is set + * only once based on first PCIe. Also changing 'io_map_base' + * based on first slot's value so that both the routines will + * work properly. + */ + octeon_pcie1_controller.io_map_base = + CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0)); + /* IO offsets are Mips virtual addresses */ + octeon_pcie1_controller.io_offset = + cvmx_pcie_get_io_base_address(1) - + cvmx_pcie_get_io_base_address(0); + /* + * To keep things similar to PCI, we start device + * addresses at the same place as PCI uisng big bar + * support. This normally translates to 4GB-256MB, + * which is the same as most x86 PCs. + */ + octeon_pcie1_controller.mem_resource->start = + cvmx_pcie_get_mem_base_address(1) + (4ul << 30) - + (OCTEON_PCI_BAR1_HOLE_SIZE << 20); + octeon_pcie1_controller.mem_resource->end = + cvmx_pcie_get_mem_base_address(1) + + cvmx_pcie_get_mem_size(1) - 1; + /* + * Ports must be above 16KB for the ISA bus filtering + * in the PCI-X to PCI bridge. + */ + octeon_pcie1_controller.io_resource->start = + cvmx_pcie_get_io_base_address(1) - + cvmx_pcie_get_io_base_address(0); + octeon_pcie1_controller.io_resource->end = + octeon_pcie1_controller.io_resource->start + + cvmx_pcie_get_io_size(1) - 1; + msleep(100); /* Some devices need extra time */ + register_pci_controller(&octeon_pcie1_controller); + device0 = cvmx_pcie_config_read32(1, 0, 0, 0, 0); + enable_pcie_bus_num_war[1] = + device_needs_bus_num_war(device0); + } + } else { + pr_notice("PCIe: Port 1 not in root complex mode, skipping.\n"); + /* CN63XX pass 1_x/2.0 errata PCIe-15205 */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || + OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { + srio_war15205 += 1; + port = 1; + } + } + + /* + * CN63XX pass 1_x/2.0 errata PCIe-15205 requires setting all + * of SRIO MACs SLI_CTL_PORT*[INT*_MAP] to similar value and + * all of PCIe Macs SLI_CTL_PORT*[INT*_MAP] to different value + * from the previous set values + */ + if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || + OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { + if (srio_war15205 == 1) { + sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(port)); + sli_ctl_portx.s.inta_map = 1; + sli_ctl_portx.s.intb_map = 1; + sli_ctl_portx.s.intc_map = 1; + sli_ctl_portx.s.intd_map = 1; + cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(port), sli_ctl_portx.u64); + + sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(!port)); + sli_ctl_portx.s.inta_map = 0; + sli_ctl_portx.s.intb_map = 0; + sli_ctl_portx.s.intc_map = 0; + sli_ctl_portx.s.intd_map = 0; + cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(!port), sli_ctl_portx.u64); + } } octeon_pci_dma_init(); return 0; } - arch_initcall(octeon_pcie_setup); -- cgit v1.2.3-70-g09d2 From c539ef7d355219c7b0e16cc302bf179fcad936b3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 11 Jan 2012 15:37:16 +0100 Subject: MIPS: Set default pci cache line size. On MIPS the generic PCI code has always defaulted to L1_CACHE_BYTES because the architecutre PCI code did not provide a better default. In particular on systems with S-caches or T-caches this was suboptimal. Provide a better default by setting pci_dfl_cache_line_size based on the size of the line size of the lowest level of the cache hierarchy. Signed-off-by: Ralf Baechle Patchwork: https://patchwork.linux-mips.org/patch/2982/ --- arch/mips/pci/pci.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 41af7fa2887..8ac0d484185 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -4,8 +4,11 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * - * Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2003, 04, 11 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2011 Wind River Systems, + * written by Ralf Baechle (ralf@linux-mips.org) */ +#include #include #include #include @@ -14,6 +17,8 @@ #include #include +#include + /* * Indicate whether we respect the PCI setup left by the firmware. * @@ -150,10 +155,32 @@ out: "Skipping PCI bus scan due to resource conflict\n"); } +static void __init pcibios_set_cache_line_size(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int lsize; + + /* + * Set PCI cacheline size to that of the highest level in the + * cache hierarchy. + */ + lsize = c->dcache.linesz; + lsize = c->scache.linesz ? : lsize; + lsize = c->tcache.linesz ? : lsize; + + BUG_ON(!lsize); + + pci_dfl_cache_line_size = lsize >> 2; + + pr_debug("PCI: pci_cache_line_size set to %d bytes\n", lsize); +} + static int __init pcibios_init(void) { struct pci_controller *hose; + pcibios_set_cache_line_size(); + /* Scan all of the recorded PCI controllers. */ for (hose = hose_head; hose; hose = hose->next) pcibios_scanbus(hose); -- cgit v1.2.3-70-g09d2