From patchwork Thu Jul 30 15:32:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shenwei Wang X-Patchwork-Id: 6903671 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5148BC05AC for ; Thu, 30 Jul 2015 15:35:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 40463205DB for ; Thu, 30 Jul 2015 15:35:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 195DA20361 for ; Thu, 30 Jul 2015 15:35:24 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZKppw-0001fg-De; Thu, 30 Jul 2015 15:33:36 +0000 Received: from mail-bl2on0112.outbound.protection.outlook.com ([65.55.169.112] helo=na01-bl2-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZKppp-0001Zk-Jg for linux-arm-kernel@lists.infradead.org; Thu, 30 Jul 2015 15:33:33 +0000 Received: from BL2PR03MB481.namprd03.prod.outlook.com (10.141.92.140) by BL2PR03MB451.namprd03.prod.outlook.com (10.141.92.16) with Microsoft SMTP Server (TLS) id 15.1.231.11; Thu, 30 Jul 2015 15:33:06 +0000 Received: from BN3PR0301CA0009.namprd03.prod.outlook.com (10.160.180.147) by BL2PR03MB481.namprd03.prod.outlook.com (10.141.92.140) with Microsoft SMTP Server (TLS) id 15.1.231.11; Thu, 30 Jul 2015 15:33:06 +0000 Received: from BY2FFO11FD013.protection.gbl (2a01:111:f400:7c0c::123) by BN3PR0301CA0009.outlook.office365.com (2a01:111:e400:4000::19) with Microsoft SMTP Server (TLS) id 15.1.225.19 via Frontend Transport; Thu, 30 Jul 2015 15:33:06 +0000 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; lists.infradead.org; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Received: from az84smr01.freescale.net (192.88.158.2) by BY2FFO11FD013.mail.protection.outlook.com (10.1.14.75) with Microsoft SMTP Server (TLS) id 15.1.231.11 via Frontend Transport; Thu, 30 Jul 2015 15:33:06 +0000 Received: from [az84smr01.freescale.net (B38339-11.am.freescale.net [10.81.93.199]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id t6UFWmbL031578; Thu, 30 Jul 2015 08:33:05 -0700 From: Shenwei Wang To: , Subject: [PATCH v5 1/1] Serial: imx: add dev_pm_ops to support suspend to ram/disk Date: Thu, 30 Jul 2015 10:32:36 -0500 Message-ID: <1438270356-7402-1-git-send-email-shenwei.wang@freescale.com> X-Mailer: git-send-email 2.5.0.rc2 X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD013; 1:dojO9zHHv3PsN2RRbAy/B+Dc0Xidz8ok3LXHzkPjN9iuzoLeWjAxGfG/lM2cdLgUKdVpaARnHYSbojOVvaAPE2IOvlKaDqTjj0m4nRkVZo12pZA3c0bAPrTvR4FWUekcj+5uWaU8fTP1VWdB1BrbjKpRuaEzLy9ozZE3MGJ54KVGvySL0Q4pchR90PSADgq630kDCCjZcBxrNRD2XKi60s47bHRAVoAbR0JTWb+neAMWhNX61dhqRztz9bqcOiFW4OzHttwRjFU/4jcdCpHOUseCCUB16G65QrtU7MN4CLqY6W2RN0MUm6Jf2KtCpv5v X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(2980300002)(339900001)(199003)(189002)(47776003)(87936001)(77096005)(33646002)(50986999)(92566002)(19580405001)(229853001)(19580395003)(6806004)(104016003)(85426001)(106466001)(105606002)(5001770100001)(48376002)(50226001)(36756003)(62966003)(189998001)(77156002)(5001920100001)(46102003)(50466002)(86362001)(5001960100002); DIR:OUT; SFP:1102; SCL:1; SRVR:BL2PR03MB481; H:az84smr01.freescale.net; FPR:; SPF:Fail; MLV:sfv; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB481; 2:2yfXXcoXKU8YZA89xi1NlD4WdBQwI0NGCfpKXugfz+9skLoijBs9Nzu1e9Gb9uycoy1xrvq4Kq5faBsJPKPOHFaDF9yOI5NUEGn7LJdl6qGrdVDhLL+tIDlnrJAv57RiF6rtdsoRXSeN9/JiTN+ptcN0HC08YNVazkiiHVIXfZg=; 3:Rsud0btDkKdFegRq3Kdx17k9b5Bpx9iuAiblZA9a1sD4bKUEYoH4TXaMf5JjaEhm+RT9/YPxi+gBBjEMMhTloDGf2YvwsIAUjCmi7695LOhzlWLOHRzMk7rC+IC0c5XRyFcElpwqu6hJsIPAsj8ua//PMwgyLhiFIhkT/g/CoQQCD1uGReQg55r+B6+GRPIjVceZkIofJxV2uIGqNx3UXqMemq8jz2MgdfwCVSFWmiA=; 25:2a7MnqYpm9Q87SvOvItpJz7dqYOj5B+k4zQKMuEDWpR2FsIHQKqgH/U8JFqnOsARO5Tkabz/TEi0FSW41NeEiAT5XOib8fjydX5Ef8oX9Sag6utZj0SmZo1PevTpJsZ4zWCE7YlM9Dsks2u1G0QIC4rDm5OtBPX1HOPBPeA1AF27zH2usAvgP7ybRtoODU35YiGx52UAcGKm6LouM9is1aZD3YsYDehACvactKqn+A1B+QaTWQL/hks1mlmZjgS6Au9ekk7XBg0byXQDOT51pQ== X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:; SRVR:BL2PR03MB481; UriScan:; BCL:0; PCL:0; RULEID:; SRVR:BL2PR03MB451; X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB481; 20:ghJ7YUaUuqUPsNvOX5x5PjzcXepSmmGI6sAvb5Uqb4604ufuL1m+vxGS+I3hPCXPE+EW0YjjysewOQO39YuuJJweFnzfVnq5hl6uf3h235okwWcv3DUkscHcLVgSFLkknwbRp2x0SHkLWm3bphw2h+9ulPpHLQfF3KXzSEqmZ7uYHnNIRLVp3uhDVXggRj4T/yqZce6KNEErGc2Dcwuf1Q89wkU7rNB2HexwrO8xfbn6EVWaXKFFtxeEam0uSNdx3xXvxJ3DpsSS361De0W4y6o/roRveOsiaPcoAvtJ3r2Bky+OOUrHqo95UDCs9kD7aS/zJTNaSIO8OB44OqJEILXFZH1sOTmVqcSLZ92pr50=; 4:+gWUMnnspMhtiEXIsGiTepTgHIqGOXcXemvypu7+cWKa3LjO16UmHuwlbnq/TKFYjKMTVTqGzEhHkqdAuDlek7Uzu8OYV/nIgau5ymO3XGRIb0rYO2nZEuZISCuY49693pcRtZaL2QOhOjZw5ETXQFsBZ8iNwPV20pDjDl8lV72Pej2KcYOOl4WFa/M3F5Nho67dZFuRfqmrWpogWFXS72hcAvQeOnA4IGeGiE5t7rDQPuU7IW5Ez3PHUZoRybg2TvJmw2J9hFePwhE6ocVQ0hDWk7+ihMGs3E6EdvWdrLY= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5005006)(3002001); SRVR:BL2PR03MB481; BCL:0; PCL:0; RULEID:; SRVR:BL2PR03MB481; X-Forefront-PRVS: 06530126A4 X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB481; 23:tNDKY0Hn5vTsmu/ezPP05kb5InCV7mJEKQU7GlfslNDDVwE7yGogEjUbbT/5bWjoxTH2HXahu7/1h2iuvJTUmk4DNM+An729Ne0pPnjmtG4PoKvwHmId5F3yh1pl3euQeTg63F0hBCIGBmZxSWM8e4UExp6LZ6J7yMHosuKWlLlob+lAExNNl+qR6hD+CK29Y6VQXJKdvOgHlFTo16fOwaEunaOXUP+wYRetsGYxTB+k3atiqBl2qOHwBKioFevhX0wItK9cGyGVUBwecLqLv6fgGxyJsVUiF7tlvi9Jh2E4+FZr/5SkC+ndjaibFKz4t0tk1KJZhBWIH7Dei0xYfquxADaGrSIsz540FhvS05V+kMe0YuXZO+uWV8pfIvFN1euDNIfVVKCuxCBYo4o+xznVYBAhEGpcxz6OBavmUcReyw3ymU45bURAg+cmHxuLn6ZkTVEMhASgmnKV82GfjRCprjbmy9+KYWITvvJXJW73SOh4RQQI1JD+sbl/hbhGXkcFdRFBKxjoK3qAlQ0TajquH4chfT5Dr820oYxgBh7vD7YM0Of6mbNYGuzJliKBwXbW0aGLRdGZZZViYXRWdiHSM8jPCqfMtnZmRm4ioAmYXII7AullVf2EIGSBOESAtKCeNggZ9OmsGHhZ8SUlky/R8U44Guu+u83W52cQGppO3KCPOkoJ/7g9BUEzxpfPO91SPknBA105u2syY3i2H2Fe8YSxdirNr545LGwa/b1WeGcaw1kfmdYiIfuc0ionaY3vaycZlT00D8Xvyi77lorlOymS1CgLaav3mP2DBGIOB7Kx8DUD8WHQ3JpIpSr9FuKfQQK8BXZyM4geDAib3jtpdOtK5hc63bV/Wa0lS3EStTs6IbGZIEc5UDie5qkS X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB481; 5:1PqsGxf5/ZCJY158pSa3yETKTORYo4jJpTvsavag5/qga4nofcxPDaVRSkBrpsHWh8fgOD+TNhjAs8a7eWmwBOxGa2GcsCl0b6/nfdtgYO15SrSHX7yMX5GAVKiSTEV4jIxQ+sCCC0AAIj0/zDzsHA==; 24:FbtnP3sHEnUQ1E58Oz6nTfue13jJut/Zm3RIYs3W9Fwd0CU6TxxCwP13cGB3al5mlasjukS6aDPrer67W284o++KRdom4sEvffLuvexWXZ4=; 20:I+sxtsnDyOhnvBqP9Ge2DHVdG202Q3PirG/NHg2I/ZaQSWNm3mI52rsgc2F1svyAAuqW4Qdo1cAMmNmvUKoI9Q== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Jul 2015 15:33:06.1164 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2PR03MB481 X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB451; 2:NZFRf3oNFuFe5Uo6AhEcdKkTcgO2E30Igm1/ebs6lWY9Kud926wxTtzCzLw0JF0YPs6ghHfVkCbtYZH3F+vyj+EP7Tha4+nbjuI/95/fyagouSZ8oQJy1PZU5Xs6tOlE7UIHflE+5varRu8UJ7fc5E5oknl/RAUMVhgFIGg/FN0=; 3:zNs6vOJD2S4YbQg5d/rdDx3Qtxcdwat3vPXMmju6GBcXVpvsZVwkXAlkrQ0fWYNHQiMKsdRZ8filcMieYT6yviW8CvDK/HmdYEokXloMpBp7VTiHAt7KeusKjNda+i+kez/gOFZ+Rb8oU6umedA51hxDVHaG0GfVy75AV57Ix9KQCctZK+ZdoVOvgJmJWflY/mI5wypO5lTvNJFQk4UtrvfWHha3AKqR1v4LNnlw1IA=; 25:6qIMzsYGpn5HHhr4aAot/chFuzx/BSEiKB+0NbS3o8iCkt9Q6K34fAdnGGNSn8i/LmOhM+M27rVlfRTXXoWJcdqCqJf47m+tWBlvSn+HIfXRhNb20Tk+KpbFqRCbLDgGmM+68Li8WdZDcLBfmA05D+8XrP9KD4V3SLLRm55z/zekZGKHJ9firKCet8FnxcQyjZuq9YaoB5sga7yAN3L0Lmt68mPPt69zCm3Gf+E1Vc1zAVWQaHm50+oA1A6HrNsPqr2L70I4gqrebyo9/+dXGg==; 23:fTE2QcOgWEFyRrcX2cLN5PSxKEq8v01nkV6BYQjMvDTVr3ANNgvZmzFDvtsVkDPaSyPo7kQoxB7GY+8+ISM/FUWZ8dwqlTsSuHp6+dtPwDw7FFP8SQhIed6SfXN94lszIS/9FdDit3Ju5DJMlnhb1zJu2VBjT6DotMR4WFQMTW9KQ2sgQN6wc/B6U5RuSfK6 X-OriginatorOrg: freescale.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150730_083329_902292_6E0A8D44 X-CRM114-Status: GOOD ( 19.67 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arm-kernel@lists.infradead.org, linux-serial@vger.kernel.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY 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 When system goes into low power states like SUSPEND_MEM and HIBERNATION, the hardware IP block may be powered off to reduce the power consumption. This power down may cause problems on some imx platforms, because the hardware settings are reset to its power on default values which may differ from the ones when it power off. This patch added the dev_pm_ops and implemented two callbacks: suspend_noirq and resume_noirq, which will save the necessory hardware parameters right before power down and recover them before system uses the hardware. Because added the dev_pm_ops, the old suspend/resume callbacks under platform_driver will not be called any more. Changed their prototypes and moved those two callbacks into dev_pm_ops too. Signed-off-by: Shenwei Wang --- Change log: PATCH v5 When clk_enable fails, the callback stop right there and propagate the error to its caller. PATCH v4 Added the return value check for clk_enable. Replace the number 0x1 with UCR2_SRST. PATCH v3 After added the dev_pm_ops, the old suspend/resume callbacks under platform_driver will not be called. Changed their prototypes and moved them into dev_pm_ops too. PATCH v2 Change pr_debug to dev_dbg per GregK's review feedback. drivers/tty/serial/imx.c | 126 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 32 deletions(-) -- 2.5.0.rc2 diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 2c90dc3..65a7ae2 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -216,6 +216,7 @@ struct imx_port { unsigned int tx_bytes; unsigned int dma_tx_nents; wait_queue_head_t dma_wait; + unsigned int saved_reg[10]; }; struct imx_port_ucrs { @@ -1811,36 +1812,6 @@ static struct uart_driver imx_reg = { .cons = IMX_CONSOLE, }; -static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) -{ - struct imx_port *sport = platform_get_drvdata(dev); - unsigned int val; - - /* enable wakeup from i.MX UART */ - val = readl(sport->port.membase + UCR3); - val |= UCR3_AWAKEN; - writel(val, sport->port.membase + UCR3); - - uart_suspend_port(&imx_reg, &sport->port); - - return 0; -} - -static int serial_imx_resume(struct platform_device *dev) -{ - struct imx_port *sport = platform_get_drvdata(dev); - unsigned int val; - - /* disable wakeup from i.MX UART */ - val = readl(sport->port.membase + UCR3); - val &= ~UCR3_AWAKEN; - writel(val, sport->port.membase + UCR3); - - uart_resume_port(&imx_reg, &sport->port); - - return 0; -} - #ifdef CONFIG_OF /* * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it @@ -1992,16 +1963,107 @@ static int serial_imx_remove(struct platform_device *pdev) return uart_remove_one_port(&imx_reg, &sport->port); } +static int imx_serial_port_suspend_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct imx_port *sport = platform_get_drvdata(pdev); + int ret; + + ret = clk_enable(sport->clk_ipg); + if (ret) + return ret; + + /* Save necessary regs */ + sport->saved_reg[0] = readl(sport->port.membase + UCR1); + sport->saved_reg[1] = readl(sport->port.membase + UCR2); + sport->saved_reg[2] = readl(sport->port.membase + UCR3); + sport->saved_reg[3] = readl(sport->port.membase + UCR4); + sport->saved_reg[4] = readl(sport->port.membase + UFCR); + sport->saved_reg[5] = readl(sport->port.membase + UESC); + sport->saved_reg[6] = readl(sport->port.membase + UTIM); + sport->saved_reg[7] = readl(sport->port.membase + UBIR); + sport->saved_reg[8] = readl(sport->port.membase + UBMR); + sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS); + + clk_disable(sport->clk_ipg); + + return 0; +} + +static int imx_serial_port_resume_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct imx_port *sport = platform_get_drvdata(pdev); + int ret; + + ret = clk_enable(sport->clk_ipg); + if (ret) + return ret; + + writel(sport->saved_reg[4], sport->port.membase + UFCR); + writel(sport->saved_reg[5], sport->port.membase + UESC); + writel(sport->saved_reg[6], sport->port.membase + UTIM); + writel(sport->saved_reg[7], sport->port.membase + UBIR); + writel(sport->saved_reg[8], sport->port.membase + UBMR); + writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS); + writel(sport->saved_reg[0], sport->port.membase + UCR1); + writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2); + writel(sport->saved_reg[2], sport->port.membase + UCR3); + writel(sport->saved_reg[3], sport->port.membase + UCR4); + + clk_disable(sport->clk_ipg); + + return 0; +} + +static int imx_serial_port_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct imx_port *sport = platform_get_drvdata(pdev); + unsigned int val; + + /* enable wakeup from i.MX UART */ + val = readl(sport->port.membase + UCR3); + val |= UCR3_AWAKEN; + writel(val, sport->port.membase + UCR3); + + uart_suspend_port(&imx_reg, &sport->port); + + return 0; +} + +static int imx_serial_port_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct imx_port *sport = platform_get_drvdata(pdev); + unsigned int val; + + /* disable wakeup from i.MX UART */ + val = readl(sport->port.membase + UCR3); + val &= ~UCR3_AWAKEN; + writel(val, sport->port.membase + UCR3); + + uart_resume_port(&imx_reg, &sport->port); + + return 0; +} + +static const struct dev_pm_ops imx_serial_port_pm_ops = { + .suspend_noirq = imx_serial_port_suspend_noirq, + .resume_noirq = imx_serial_port_resume_noirq, + .suspend = imx_serial_port_suspend, + .resume = imx_serial_port_resume, +}; + static struct platform_driver serial_imx_driver = { .probe = serial_imx_probe, .remove = serial_imx_remove, - .suspend = serial_imx_suspend, - .resume = serial_imx_resume, .id_table = imx_uart_devtype, .driver = { .name = "imx-uart", .of_match_table = imx_uart_dt_ids, + .pm = &imx_serial_port_pm_ops, }, };