From patchwork Wed Jan 8 05:01:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minghuan Lian X-Patchwork-Id: 3451621 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4A69A9F1C4 for ; Wed, 8 Jan 2014 05:02:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1592E20122 for ; Wed, 8 Jan 2014 05:02:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8AB5520109 for ; Wed, 8 Jan 2014 05:02:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751472AbaAHFCA (ORCPT ); Wed, 8 Jan 2014 00:02:00 -0500 Received: from co1ehsobe005.messaging.microsoft.com ([216.32.180.188]:50210 "EHLO co1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751104AbaAHFCA (ORCPT ); Wed, 8 Jan 2014 00:02:00 -0500 Received: from mail95-co1-R.bigfish.com (10.243.78.233) by CO1EHSOBE032.bigfish.com (10.243.66.97) with Microsoft SMTP Server id 14.1.225.22; Wed, 8 Jan 2014 05:01:59 +0000 Received: from mail95-co1 (localhost [127.0.0.1]) by mail95-co1-R.bigfish.com (Postfix) with ESMTP id C8046A028A; Wed, 8 Jan 2014 05:01:59 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: -1 X-BigFish: VS-1(zz154dIzz1f42h2148h208ch1ee6h1de0h1fdah2073h2146h1202h1e76h2189h1d1ah1d2ah1fc6hzz1de098h17326ah8275bh8275dh1de097h186068hz2dh2a8h839he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh2222h224fh1fb3h1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h2218h2216h226dh22d0h2327h2336h1155h) Received: from mail95-co1 (localhost.localdomain [127.0.0.1]) by mail95-co1 (MessageSwitch) id 1389157317736866_23141; Wed, 8 Jan 2014 05:01:57 +0000 (UTC) Received: from CO1EHSMHS020.bigfish.com (unknown [10.243.78.241]) by mail95-co1.bigfish.com (Postfix) with ESMTP id ADD794601DE; Wed, 8 Jan 2014 05:01:57 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by CO1EHSMHS020.bigfish.com (10.243.66.30) with Microsoft SMTP Server (TLS) id 14.16.227.3; Wed, 8 Jan 2014 05:01:57 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server (TLS) id 14.3.158.2; Wed, 8 Jan 2014 05:01:56 +0000 Received: from lmh.ap.freescale.net (lmh.ap.freescale.net [10.193.20.65]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s0851V2J018463; Tue, 7 Jan 2014 22:01:54 -0700 From: Minghuan Lian To: CC: Zang Roy-R61911 , Scott Wood , Kumar Gala , Bjorn Helgaas , , Minghuan Lian Subject: [PATCH 08/12][v4] pci: fsl: add PowerPC PCI driver Date: Wed, 8 Jan 2014 13:01:59 +0800 Message-ID: <1389157323-3088-8-git-send-email-Minghuan.Lian@freescale.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1389157323-3088-1-git-send-email-Minghuan.Lian@freescale.com> References: <1389157323-3088-1-git-send-email-Minghuan.Lian@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-FOPE-CONNECTOR: Id%0$Dn%FREESCALE.MAIL.ONMICROSOFT.COM$RO%1$TLS%0$FQDN%$TlsDn% Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY, UNRESOLVED_TEMPLATE autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 1. Implement fsl_arch_pci64_dma_offset() to return PowerPC PCI64 DMA offset 2. Implement fsl_arch_sys_to_pci() to convert pci_controller to fsl_pci 3. Implement fsl_arch_fake_pci_bus() to fake pci_controller and PCI bus. 4. Implement fsl_arch_pci_exclude_device() to call ppc_md.pci_exclude_device() 5. Implement fsl_arch_pci_sys_register() to initialize pci_controller according to fsl_pci, add register PCI controller to PowerPC PCI subsystem. 6. Implement fsl_arch_pci_sys_remove() to remove PCI controller from PowerPC PCI subsystem. 7. Add mpc83xx_pcie_check_link() because pci-fsl-common dose not support mpc83xx. Signed-off-by: Minghuan Lian --- change log: v4: no change v1-v3: Derived from http://patchwork.ozlabs.org/patch/278965/ Based on upstream master. Based on the discussion of RFC version here http://patchwork.ozlabs.org/patch/274487/ arch/powerpc/sysdev/fsl_pci.c | 142 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 0764385..38e8dca 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -62,7 +62,11 @@ static void quirk_fsl_pcie_early(struct pci_dev *dev) #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) #define MAX_PHYS_ADDR_BITS 40 -static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS; + +u64 fsl_arch_pci64_dma_offset(void) +{ + return 1ull << MAX_PHYS_ADDR_BITS; +} static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) { @@ -77,17 +81,44 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) if ((dev->bus == &pci_bus_type) && dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { set_dma_ops(dev, &dma_direct_ops); - set_dma_offset(dev, pci64_dma_offset); + set_dma_offset(dev, fsl_arch_pci64_dma_offset()); } *dev->dma_mask = dma_mask; return 0; } +struct fsl_pci *fsl_arch_sys_to_pci(void *sys) +{ + struct pci_controller *hose = sys; + struct fsl_pci *pci = hose->private_data; + + /* Update the first bus number */ + if (pci->first_busno != hose->first_busno) + pci->first_busno = hose->first_busno; + + return pci; +} + +struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr) +{ + static struct pci_bus bus; + static struct pci_controller hose; + + bus.number = busnr; + bus.sysdata = &hose; + hose.private_data = pci; + bus.ops = pci->ops; + + return &bus; +} + void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; + bool is_pcie, no_link; + int i; + struct fsl_pci *pci = fsl_arch_sys_to_pci(hose); /* The root complex bridge comes up with bogus resources, * we copy the PHB ones in. @@ -97,9 +128,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) * tricky. */ - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK); + is_pcie = pci->is_pcie; + no_link = !fsl_pci_check_link(pci); if (bus->parent == hose->bus && (is_pcie || no_link)) { for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) { @@ -121,6 +151,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus) } } +int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn) +{ + struct pci_controller *hose = pci->sys; + + if (!hose) + return PCIBIOS_SUCCESSFUL; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(hose, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +int fsl_arch_pci_sys_register(struct fsl_pci *pci) +{ + struct pci_controller *hose; + + pci_add_flags(PCI_REASSIGN_ALL_BUS); + hose = pcibios_alloc_controller(pci->dn); + if (!hose) + return -ENOMEM; + + /* set platform device as the parent */ + hose->private_data = pci; + hose->parent = pci->dev; + hose->first_busno = pci->first_busno; + hose->last_busno = pci->last_busno; + hose->ops = pci->ops; + +#ifdef CONFIG_PPC32 + /* On 32 bits, limit I/O space to 16MB */ + if (pci->pci_io_size > 0x01000000) + pci->pci_io_size = 0x01000000; + + /* 32 bits needs to map IOs here */ + hose->io_base_virt = ioremap(pci->io_base_phys + pci->io_resource.start, + pci->pci_io_size); + + /* Expect trouble if pci_addr is not 0 */ + if (fsl_pci_primary == pci->dn) + isa_io_base = (unsigned long)hose->io_base_virt; +#endif /* CONFIG_PPC32 */ + + hose->pci_io_size = pci->io_resource.start + pci->pci_io_size; + hose->io_base_phys = pci->io_base_phys; + hose->io_resource = pci->io_resource; + + memcpy(hose->mem_offset, pci->mem_offset, sizeof(hose->mem_offset)); + memcpy(hose->mem_resources, pci->mem_resources, + sizeof(hose->mem_resources)); + hose->dma_window_base_cur = pci->dma_window_base_cur; + hose->dma_window_size = pci->dma_window_size; + + pci->sys = hose; + + /* + * Install our own dma_set_mask handler to fixup dma_ops + * and dma_offset when memory is more than dma window size + */ + if (pci->is_pcie && memblock_end_of_DRAM() > hose->dma_window_size) + ppc_md.dma_set_mask = fsl_pci_dma_set_mask; + +#ifdef CONFIG_SWIOTLB + /* + * if we couldn't map all of DRAM via the dma windows + * we need SWIOTLB to handle buffers located outside of + * dma capable memory region + */ + if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur + + hose->dma_window_size) + ppc_swiotlb_enable = 1; +#endif + + mpc85xx_pci_err_probe(to_platform_device(pci->dev)); + return 0; +} + +void fsl_arch_pci_sys_remove(struct fsl_pci *pci) +{ + struct pci_controller *hose = pci->sys; + + if (!hose) + return; + + pcibios_free_controller(hose); +} + #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, @@ -261,6 +379,16 @@ static struct pci_ops mpc83xx_pcie_ops = { .write = mpc83xx_pcie_write_config, }; +static int mpc83xx_pcie_check_link(struct pci_controller *hose) +{ + u32 val = 0; + + early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val); + if (val < PCIE_LTSSM_L0) + return 1; + return 0; +} + static int __init mpc83xx_pcie_setup(struct pci_controller *hose, struct resource *reg) { @@ -295,7 +423,7 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose, out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0); out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0); - if (fsl_pcie_check_link(hose)) + if (mpc83xx_pcie_check_link(hose)) hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; return 0;