diff options
Diffstat (limited to 'arch/mips/pci/pci-alchemy.c')
| -rw-r--r-- | arch/mips/pci/pci-alchemy.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index d1faece21b6a..6bfee0f71803 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Alchemy PCI host mode support. * @@ -7,6 +8,7 @@ * Support for all devices (greater than 16) added by David Gathright. */ +#include <linux/clk.h> #include <linux/export.h> #include <linux/types.h> #include <linux/pci.h> @@ -15,6 +17,7 @@ #include <linux/init.h> #include <linux/syscore_ops.h> #include <linux/vmalloc.h> +#include <linux/dma-map-ops.h> /* for dma_default_coherent */ #include <asm/mach-au1x00/au1000.h> #include <asm/tlbmisc.h> @@ -49,7 +52,7 @@ struct alchemy_pci_context { static struct alchemy_pci_context *__alchemy_pci_ctx; -/* IO/MEM resources for PCI. Keep the memres in sync with __fixup_bigphys_addr +/* IO/MEM resources for PCI. Keep the memres in sync with fixup_bigphys_addr * in arch/mips/alchemy/common/setup.c */ static struct resource alchemy_pci_def_memres = { @@ -74,7 +77,7 @@ static void mod_wired_entry(int entry, unsigned long entrylo0, unsigned long old_ctx; /* Save old context and create impossible VPN2 value */ - old_ctx = read_c0_entryhi() & 0xff; + old_ctx = read_c0_entryhi() & MIPS_ENTRYHI_ASID; old_pagemask = read_c0_pagemask(); write_c0_index(entry); write_c0_pagemask(pagemask); @@ -301,7 +304,7 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int assert) } /* save PCI controller register contents. */ -static int alchemy_pci_suspend(void) +static int alchemy_pci_suspend(void *data) { struct alchemy_pci_context *ctx = __alchemy_pci_ctx; if (!ctx) @@ -323,7 +326,7 @@ static int alchemy_pci_suspend(void) return 0; } -static void alchemy_pci_resume(void) +static void alchemy_pci_resume(void *data) { struct alchemy_pci_context *ctx = __alchemy_pci_ctx; if (!ctx) @@ -351,9 +354,13 @@ static void alchemy_pci_resume(void) alchemy_pci_wired_entry(ctx); /* install it */ } -static struct syscore_ops alchemy_pci_pmops = { - .suspend = alchemy_pci_suspend, - .resume = alchemy_pci_resume, +static const struct syscore_ops alchemy_pci_syscore_ops = { + .suspend = alchemy_pci_suspend, + .resume = alchemy_pci_resume, +}; + +static struct syscore alchemy_pci_syscore = { + .ops = &alchemy_pci_syscore_ops, }; static int alchemy_pci_probe(struct platform_device *pdev) @@ -363,6 +370,7 @@ static int alchemy_pci_probe(struct platform_device *pdev) void __iomem *virt_io; unsigned long val; struct resource *r; + struct clk *c; int ret; /* need at least PCI IRQ mapping table */ @@ -392,11 +400,24 @@ static int alchemy_pci_probe(struct platform_device *pdev) goto out1; } - ctx->regs = ioremap_nocache(r->start, resource_size(r)); + c = clk_get(&pdev->dev, "pci_clko"); + if (IS_ERR(c)) { + dev_err(&pdev->dev, "unable to find PCI clock\n"); + ret = PTR_ERR(c); + goto out2; + } + + ret = clk_prepare_enable(c); + if (ret) { + dev_err(&pdev->dev, "cannot enable PCI clock\n"); + goto out6; + } + + ctx->regs = ioremap(r->start, resource_size(r)); if (!ctx->regs) { dev_err(&pdev->dev, "cannot map pci regs\n"); ret = -ENODEV; - goto out2; + goto out5; } /* map parts of the PCI IO area */ @@ -411,17 +432,15 @@ static int alchemy_pci_probe(struct platform_device *pdev) } ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io; -#ifdef CONFIG_DMA_NONCOHERENT /* Au1500 revisions older than AD have borked coherent PCI */ - if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) && - (read_c0_prid() < 0x01030202)) { + if (alchemy_get_cputype() == ALCHEMY_CPU_AU1500 && + read_c0_prid() < 0x01030202 && !dma_default_coherent) { val = __raw_readl(ctx->regs + PCI_REG_CONFIG); val |= PCI_CONFIG_NC; __raw_writel(val, ctx->regs + PCI_REG_CONFIG); wmb(); dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n"); } -#endif if (pd->board_map_irq) ctx->board_map_irq = pd->board_map_irq; @@ -438,7 +457,7 @@ static int alchemy_pci_probe(struct platform_device *pdev) /* we can't ioremap the entire pci config space because it's too large, * nor can we dynamically ioremap it because some drivers use the - * PCI config routines from within atomic contex and that becomes a + * PCI config routines from within atomic context and that becomes a * problem in get_vm_area(). Instead we use one wired TLB entry to * handle all config accesses for all busses. */ @@ -463,15 +482,22 @@ static int alchemy_pci_probe(struct platform_device *pdev) __alchemy_pci_ctx = ctx; platform_set_drvdata(pdev, ctx); - register_syscore_ops(&alchemy_pci_pmops); + register_syscore(&alchemy_pci_syscore); register_pci_controller(&ctx->alchemy_pci_ctrl); + dev_info(&pdev->dev, "PCI controller at %ld MHz\n", + clk_get_rate(c) / 1000000); + return 0; out4: iounmap(virt_io); out3: iounmap(ctx->regs); +out5: + clk_disable_unprepare(c); +out6: + clk_put(c); out2: release_mem_region(r->start, resource_size(r)); out1: @@ -484,7 +510,6 @@ static struct platform_driver alchemy_pcictl_driver = { .probe = alchemy_pci_probe, .driver = { .name = "alchemy-pci", - .owner = THIS_MODULE, }, }; @@ -501,7 +526,7 @@ static int __init alchemy_pci_init(void) arch_initcall(alchemy_pci_init); -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct alchemy_pci_context *ctx = dev->sysdata; if (ctx && ctx->board_map_irq) |
