From patchwork Sun Jul 28 14:43:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 2834694 Return-Path: X-Original-To: patchwork-linux-omap@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 A8344C0319 for ; Sun, 28 Jul 2013 14:44:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C20162012B for ; Sun, 28 Jul 2013 14:44:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C6C302012F for ; Sun, 28 Jul 2013 14:44:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753773Ab3G1OoG (ORCPT ); Sun, 28 Jul 2013 10:44:06 -0400 Received: from cassiel.sirena.org.uk ([80.68.93.111]:59100 "EHLO cassiel.sirena.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753709Ab3G1OoE (ORCPT ); Sun, 28 Jul 2013 10:44:04 -0400 Received: from cpc11-sgyl31-2-0-cust68.sgyl.cable.virginmedia.com ([94.175.92.69] helo=finisterre) by cassiel.sirena.org.uk with esmtpsa (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1V3SCT-00080Z-G7; Sun, 28 Jul 2013 15:43:59 +0100 Received: from broonie by finisterre with local (Exim 4.80) (envelope-from ) id 1V3SCS-0001yx-Of; Sun, 28 Jul 2013 15:43:56 +0100 From: Mark Brown To: Eric Miao , Haojian Zhuang , Kukjin Kim , Stephen Warren , Linus Walleij Cc: linux-samsung-soc@vger.kernel.org, linux-tegra@vger.kernel.org, linux-omap@vger.kernel.org, linaro-kernel@lists.linaro.org, Mark Brown Date: Sun, 28 Jul 2013 15:43:16 +0100 Message-Id: <1375022606-7576-1-git-send-email-broonie@kernel.org> X-Mailer: git-send-email 1.8.3.2 X-SA-Exim-Connect-IP: 94.175.92.69 X-SA-Exim-Mail-From: broonie@sirena.org.uk X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-8.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Subject: [PATCH 01/11] spi: Provide core support for runtime PM during transfers X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:57:07 +0000) X-SA-Exim-Scanned: Yes (on cassiel.sirena.org.uk) Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mark Brown Most SPI drivers that implement runtime PM support use identical code to do so: they acquire a runtime PM lock in prepare_transfer_hardware() and then they release it in unprepare_transfer_hardware(). The variations in this are mostly missing error checking and the choice to use autosuspend. Since these runtime PM calls are normally the only thing in the prepare and unprepare callbacks and the autosuspend API transparently does the right thing on devices with autosuspend disabled factor all of this out into the core with a flag to enable the behaviour. Signed-off-by: Mark Brown Acked-by: Linus Walleij Reviewed-by: Stephen Warren --- drivers/spi/spi.c | 16 ++++++++++++++++ include/linux/spi/spi.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 46c3f56..61f71b9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work) master->unprepare_transfer_hardware(master)) dev_err(&master->dev, "failed to unprepare transfer hardware\n"); + if (master->auto_runtime_pm) { + pm_runtime_mark_last_busy(master->dev.parent); + pm_runtime_put_autosuspend(master->dev.parent); + } return; } @@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work) master->busy = true; spin_unlock_irqrestore(&master->queue_lock, flags); + if (!was_busy && master->auto_runtime_pm) { + ret = pm_runtime_get_sync(master->dev.parent); + if (ret < 0) { + dev_err(&master->dev, "Failed to power device: %d\n", + ret); + return; + } + } + if (!was_busy && master->prepare_transfer_hardware) { ret = master->prepare_transfer_hardware(master); if (ret) { dev_err(&master->dev, "failed to prepare transfer hardware\n"); + + if (master->auto_runtime_pm) + pm_runtime_put(master->dev.parent); return; } } diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index be40c97..d73059a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -256,6 +256,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @busy: message pump is busy * @running: message pump is running * @rt: whether this queue is set to run as a realtime task + * @auto_runtime_pm: the core should ensure a runtime PM reference is held + * while the hardware is prepared * @prepare_transfer_hardware: a message will soon arrive from the queue * so the subsystem requests the driver to prepare the transfer hardware * by issuing this call @@ -380,11 +382,13 @@ struct spi_master { bool busy; bool running; bool rt; + bool auto_runtime_pm; int (*prepare_transfer_hardware)(struct spi_master *master); int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); int (*unprepare_transfer_hardware)(struct spi_master *master); + /* gpio chip select */ int *cs_gpios; };