From patchwork Sat Jun 21 10:32:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King X-Patchwork-Id: 4393681 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 21D62BEEAA for ; Sat, 21 Jun 2014 10:32:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3AE3A202FF for ; Sat, 21 Jun 2014 10:32:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2BE4620340 for ; Sat, 21 Jun 2014 10:32:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755157AbaFUKcc (ORCPT ); Sat, 21 Jun 2014 06:32:32 -0400 Received: from gw-1.arm.linux.org.uk ([78.32.30.217]:37767 "EHLO pandora.arm.linux.org.uk" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755129AbaFUKcc (ORCPT ); Sat, 21 Jun 2014 06:32:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=pandora; h=Date:Sender:Message-Id:Subject:Cc:To:From; bh=lxHtUs9eB1ne3QXNbzchJQUIb5pRaPlUHg4BvI2/01Q=; b=ThvYbp5jbUIbAldN7iZSnW7oAWoWcQcXliJffGPI/Ju9gm3UTPaOgpJ4+rQ62+y8NE6tFl6PGhSKx8OutxtDHEwz1+YHG84C88CgSH76KcSJti5RxTBWKxauktaqV8CW763h+53VE4MxU/f2hjtP7sdwqvOX24t+wJS6mLVQhJs=; Received: from e0022681537dd.dyn.arm.linux.org.uk ([2001:4d48:ad52:3201:222:68ff:fe15:37dd]:48355 helo=rmk-PC.arm.linux.org.uk) by pandora.arm.linux.org.uk with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.76) (envelope-from ) id 1WyIaz-0002cB-CV; Sat, 21 Jun 2014 11:32:29 +0100 Received: from rmk by rmk-PC.arm.linux.org.uk with local (Exim 4.76) (envelope-from ) id 1WyIay-0008KP-Mm; Sat, 21 Jun 2014 11:32:28 +0100 From: Russell King To: Mark Brown , Andrew Lunn , Jason Cooper Cc: linux-spi@vger.kernel.org Subject: [PATCH] SPI: spi-orion: add runtime PM support Message-Id: Date: Sat, 21 Jun 2014 11:32:28 +0100 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_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 Add trivial runtime PM support. This will only be of benefit on SoCs where the clock to the SPI interface can be shut down. Signed-off-by: Russell King --- Patch generated against v3.15 drivers/spi/spi-orion.c | 71 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 24844984ef36..0c229f9fec9c 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,9 @@ #define DRIVER_NAME "orion_spi" +/* Runtime PM autosuspend timeout: PM is fairly light on this driver */ +#define SPI_AUTOSUSPEND_TIMEOUT 200 + #define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/ #define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */ @@ -277,6 +281,18 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) return xfer->len - count; } +static int orion_spi_prepare_transfer(struct spi_master *master) +{ + int ret = pm_runtime_get_sync(master->dev.parent); + return ret < 0 ? ret : 0; +} + +static int orion_spi_unprepare_transfer(struct spi_master *master) +{ + pm_runtime_mark_last_busy(master->dev.parent); + pm_runtime_put_autosuspend(master->dev.parent); + return 0; +} static int orion_spi_transfer_one_message(struct spi_master *master, struct spi_message *m) @@ -367,6 +383,8 @@ static int orion_spi_probe(struct platform_device *pdev) /* we support only mode 0, and no options */ master->mode_bits = SPI_CPHA | SPI_CPOL; + master->prepare_transfer_hardware = orion_spi_prepare_transfer; + master->unprepare_transfer_hardware = orion_spi_unprepare_transfer; master->transfer_one_message = orion_spi_transfer_one_message; master->num_chipselect = ORION_NUM_CHIPSELECTS; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); @@ -397,16 +415,26 @@ static int orion_spi_probe(struct platform_device *pdev) goto out_rel_clk; } + pm_runtime_set_active(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_enable(&pdev->dev); + if (orion_spi_reset(spi) < 0) - goto out_rel_clk; + goto out_rel_pm; + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); master->dev.of_node = pdev->dev.of_node; - status = devm_spi_register_master(&pdev->dev, master); + status = spi_register_master(master); if (status < 0) - goto out_rel_clk; + goto out_rel_pm; return status; +out_rel_pm: + pm_runtime_disable(&pdev->dev); out_rel_clk: clk_disable_unprepare(spi->clk); out: @@ -417,19 +445,45 @@ static int orion_spi_probe(struct platform_device *pdev) static int orion_spi_remove(struct platform_device *pdev) { - struct spi_master *master; - struct orion_spi *spi; - - master = platform_get_drvdata(pdev); - spi = spi_master_get_devdata(master); + struct spi_master *master = platform_get_drvdata(pdev); + struct orion_spi *spi = spi_master_get_devdata(master); + pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(spi->clk); + spi_unregister_master(master); + pm_runtime_disable(&pdev->dev); + return 0; } MODULE_ALIAS("platform:" DRIVER_NAME); +#ifdef CONFIG_PM_RUNTIME +static int orion_spi_runtime_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct orion_spi *spi = spi_master_get_devdata(master); + + clk_disable_unprepare(spi->clk); + return 0; +} + +static int orion_spi_runtime_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct orion_spi *spi = spi_master_get_devdata(master); + + return clk_prepare_enable(spi->clk); +} +#endif + +static const struct dev_pm_ops orion_spi_pm_ops = { + SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend, + orion_spi_runtime_resume, + NULL) +}; + static const struct of_device_id orion_spi_of_match_table[] = { { .compatible = "marvell,orion-spi", }, {} @@ -440,6 +494,7 @@ static struct platform_driver orion_spi_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .pm = &orion_spi_pm_ops, .of_match_table = of_match_ptr(orion_spi_of_match_table), }, .probe = orion_spi_probe,