From patchwork Tue Sep 18 02:10:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongtao Jia X-Patchwork-Id: 184591 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 0E1222C012E for ; Tue, 18 Sep 2012 12:45:33 +1000 (EST) Received: from va3outboundpool.messaging.microsoft.com (va3ehsobe006.messaging.microsoft.com [216.32.180.16]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (Client CN "mail.global.frontbridge.com", Issuer "Microsoft Secure Server Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 6B0AC2C007F for ; Tue, 18 Sep 2012 12:45:08 +1000 (EST) Received: from mail216-va3-R.bigfish.com (10.7.14.243) by VA3EHSOBE009.bigfish.com (10.7.40.29) with Microsoft SMTP Server id 14.1.225.23; Tue, 18 Sep 2012 02:45:03 +0000 Received: from mail216-va3 (localhost [127.0.0.1]) by mail216-va3-R.bigfish.com (Postfix) with ESMTP id 041488401DE; Tue, 18 Sep 2012 02:45:03 +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: VS1(zzd6f1izz1202h1d1ah1d2ahzz8275bhz2dh2a8h668h839he5bhf0ah107ah1288h12a5h12a9h12bdh12e5h1155h) Received: from mail216-va3 (localhost.localdomain [127.0.0.1]) by mail216-va3 (MessageSwitch) id 1347936301359819_12336; Tue, 18 Sep 2012 02:45:01 +0000 (UTC) Received: from VA3EHSMHS005.bigfish.com (unknown [10.7.14.237]) by mail216-va3.bigfish.com (Postfix) with ESMTP id 4B72E1800B2; Tue, 18 Sep 2012 02:45:01 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS005.bigfish.com (10.7.99.15) with Microsoft SMTP Server (TLS) id 14.1.225.23; Tue, 18 Sep 2012 02:45:00 +0000 Received: from az84smr01.freescale.net (10.64.34.197) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server (TLS) id 14.2.309.3; Mon, 17 Sep 2012 21:44:59 -0500 Received: from rock.am.freescale.net (rock.ap.freescale.net [10.193.20.106]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id q8I2ipdY019104; Mon, 17 Sep 2012 19:44:52 -0700 From: Jia Hongtao To: , Subject: [PATCH][V4] powerpc/fsl-pci: Add pci inbound/outbound PM support Date: Tue, 18 Sep 2012 10:10:34 +0800 Message-ID: <1347934234-18223-1-git-send-email-B38951@freescale.com> X-Mailer: git-send-email 1.7.5.1 MIME-Version: 1.0 X-OriginatorOrg: freescale.com Cc: B07421@freescale.com, b38951@freescale.com X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Power supply for PCI inbound/outbound window registers is off when system go to deep-sleep state. We save the values of registers before suspend and restore to registers after resume. Signed-off-by: Jiang Yutang Signed-off-by: Jia Hongtao Signed-off-by: Li Yang --- Changes for V4: We just rebase the patch upon following patch: powerpc/fsl-pci: Unify pci/pcie initialization code arch/powerpc/include/asm/pci-bridge.h | 2 +- arch/powerpc/sysdev/fsl_pci.c | 121 +++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ac39e6a..823e000 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -89,9 +89,9 @@ struct pci_controller { #ifdef CONFIG_PPC64 unsigned long buid; +#endif /* CONFIG_PPC64 */ void *private_data; -#endif /* CONFIG_PPC64 */ }; /* These are used for config access before all the PCI probing diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index e577cb5..8c15177 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -887,12 +887,133 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_SUSPEND + +#define PCI_POW_PIW_OFFSET 0xc00 +#define PCI_POW_PIW_SIZE 0x200 +#define PCI_POW_NUMBER 5 + +static int fsl_pci_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct pci_controller *hose; + struct pci_outbound_window_regs *pci_saved_pow; + struct pci_inbound_window_regs *pci_saved_piw, *temp_piw; + struct resource pci_rsrc; + unsigned int i; + struct fsl_pci_private_data *sus_info; + + hose = pci_find_hose_for_OF_device(pdev->dev.of_node); + of_address_to_resource(pdev->dev.of_node, 0, &pci_rsrc); + + sus_info = kmalloc( + sizeof(struct fsl_pci_private_data), GFP_KERNEL); + if (!sus_info) + return -ENOMEM; + + hose->private_data = sus_info; + + sus_info->pci_pow = ioremap(pci_rsrc.start + PCI_POW_PIW_OFFSET, + PCI_POW_PIW_SIZE); + if (!sus_info->pci_pow) { + dev_err(&pdev->dev, "pci outbound/inbound windows ioremap error!\n"); + goto err1; + } + + sus_info->pci_piw = (struct pci_inbound_window_regs *) + ((void *)sus_info->pci_pow + PCI_POW_PIW_SIZE) - 1; + + if (of_device_is_compatible(pdev->dev.of_node, "fsl,qoriq-pcie-v2.2")) + sus_info->inbound_num = 4; + else + sus_info->inbound_num = 3; + + sus_info->saved_regs = kmalloc( + sizeof(struct pci_outbound_window_regs) * PCI_POW_NUMBER + + sizeof(struct pci_inbound_window_regs) * sus_info->inbound_num, + GFP_KERNEL); + if (!sus_info->saved_regs) + goto err2; + + pci_saved_pow = sus_info->saved_regs; + for (i = 0; i < PCI_POW_NUMBER; i++) { + pci_saved_pow[i].potar = in_be32(&sus_info->pci_pow[i].potar); + pci_saved_pow[i].potear = in_be32(&sus_info->pci_pow[i].potear); + pci_saved_pow[i].powbar = in_be32(&sus_info->pci_pow[i].powbar); + pci_saved_pow[i].powar = in_be32(&sus_info->pci_pow[i].powar); + } + + pci_saved_piw = (struct pci_inbound_window_regs *) + (pci_saved_pow + PCI_POW_NUMBER); + temp_piw = sus_info->pci_piw; + for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) { + pci_saved_piw[i].pitar = in_be32(&temp_piw->pitar); + pci_saved_piw[i].piwbar = in_be32(&temp_piw->piwbar); + pci_saved_piw[i].piwbear = in_be32(&temp_piw->piwbear); + pci_saved_piw[i].piwar = in_be32(&temp_piw->piwar); + } + + return 0; + +err2: + iounmap(sus_info->pci_pow); + +err1: + kfree(sus_info); + return -ENOMEM; +} + +static int fsl_pci_resume(struct platform_device *pdev) +{ + struct pci_controller *hose; + struct pci_outbound_window_regs *pci_saved_pow; + struct pci_inbound_window_regs *pci_saved_piw, *temp_piw; + unsigned int i; + struct fsl_pci_private_data *sus_info; + + hose = pci_find_hose_for_OF_device(pdev->dev.of_node); + sus_info = (struct fsl_pci_private_data *)hose->private_data; + + if (!sus_info->pci_pow || !sus_info->pci_piw || !sus_info->saved_regs) + return 0; + + pci_saved_pow = sus_info->saved_regs; + for (i = 0; i < PCI_POW_NUMBER; i++) { + out_be32(&sus_info->pci_pow[i].potar, pci_saved_pow[i].potar); + out_be32(&sus_info->pci_pow[i].potear, pci_saved_pow[i].potear); + out_be32(&sus_info->pci_pow[i].powbar, pci_saved_pow[i].powbar); + out_be32(&sus_info->pci_pow[i].powar, pci_saved_pow[i].powar); + } + + pci_saved_piw = (struct pci_inbound_window_regs *) + (pci_saved_pow + PCI_POW_NUMBER); + temp_piw = sus_info->pci_piw; + for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) { + out_be32(&temp_piw->pitar, pci_saved_piw[i].pitar); + out_be32(&temp_piw->piwbar, pci_saved_piw[i].piwbar); + out_be32(&temp_piw->piwbear, pci_saved_piw[i].piwbear); + out_be32(&temp_piw->piwar, pci_saved_piw[i].piwar); + } + iounmap(sus_info->pci_pow); + kfree(sus_info->saved_regs); + sus_info->saved_regs = NULL; + kfree(sus_info); + sus_info = NULL; + hose->private_data = NULL; + + return 0; +} +#endif + static struct platform_driver fsl_pci_driver = { .driver = { .name = "fsl-pci", .of_match_table = pci_ids, }, .probe = fsl_pci_probe, +#ifdef CONFIG_SUSPEND + .suspend = fsl_pci_suspend, + .resume = fsl_pci_resume, +#endif }; static int __init fsl_pci_init(void)