From patchwork Wed Jul 25 09:27:00 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongtao Jia X-Patchwork-Id: 173132 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 789F72C0109 for ; Wed, 25 Jul 2012 19:53:20 +1000 (EST) Received: from am1outboundpool.messaging.microsoft.com (am1ehsobe005.messaging.microsoft.com [213.199.154.208]) (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 534822C0377 for ; Wed, 25 Jul 2012 19:50:43 +1000 (EST) Received: from mail105-am1-R.bigfish.com (10.3.201.243) by AM1EHSOBE006.bigfish.com (10.3.204.26) with Microsoft SMTP Server id 14.1.225.23; Wed, 25 Jul 2012 09:50:39 +0000 Received: from mail105-am1 (localhost [127.0.0.1]) by mail105-am1-R.bigfish.com (Postfix) with ESMTP id A4C98402AB; Wed, 25 Jul 2012 09:50:39 +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: 0 X-BigFish: VS0(zzzz1202hzz8275bhz2dh2a8h668h839he5bhf0ah107ah) Received: from mail105-am1 (localhost.localdomain [127.0.0.1]) by mail105-am1 (MessageSwitch) id 1343209838317522_12534; Wed, 25 Jul 2012 09:50:38 +0000 (UTC) Received: from AM1EHSMHS007.bigfish.com (unknown [10.3.201.253]) by mail105-am1.bigfish.com (Postfix) with ESMTP id 413D83C0051; Wed, 25 Jul 2012 09:50:38 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by AM1EHSMHS007.bigfish.com (10.3.207.107) with Microsoft SMTP Server (TLS) id 14.1.225.23; Wed, 25 Jul 2012 09:50:38 +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.298.5; Wed, 25 Jul 2012 04:50:35 -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 q6P9oHNn002279; Wed, 25 Jul 2012 02:50:31 -0700 From: Jia Hongtao To: , , Subject: [PATCH V2 5/6] powerpc/fsl-pci: Add pci inbound/outbound PM support Date: Wed, 25 Jul 2012 17:27:00 +0800 Message-ID: <1343208421-5552-5-git-send-email-B38951@freescale.com> X-Mailer: git-send-email 1.7.5.1 In-Reply-To: <1343208421-5552-1-git-send-email-B38951@freescale.com> References: <1343208421-5552-1-git-send-email-B38951@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com Cc: 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 --- 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 b48fa7f..f0f00a7 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -90,9 +90,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 babeec6..f67e609 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -966,12 +966,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)