From patchwork Mon Jul 13 12:39:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Hunter X-Patchwork-Id: 6779041 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 19B769F2E8 for ; Mon, 13 Jul 2015 12:44:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1587920528 for ; Mon, 13 Jul 2015 12:44:09 +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 F25F82051C for ; Mon, 13 Jul 2015 12:44:07 +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 1ZEd3l-0008Bp-Dp; Mon, 13 Jul 2015 12:42:13 +0000 Received: from hqemgate14.nvidia.com ([216.228.121.143]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZEd2m-0006Ds-Nt for linux-arm-kernel@lists.infradead.org; Mon, 13 Jul 2015 12:41:13 +0000 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com id ; Mon, 13 Jul 2015 05:41:18 -0700 Received: from hqemhub02.nvidia.com ([172.20.12.94]) by hqnvupgp08.nvidia.com (PGP Universal service); Mon, 13 Jul 2015 05:40:54 -0700 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Mon, 13 Jul 2015 05:40:54 -0700 Received: from jonathanh-lm.nvidia.com (172.20.144.16) by hqemhub02.nvidia.com (172.20.150.31) with Microsoft SMTP Server (TLS) id 8.3.342.0; Mon, 13 Jul 2015 05:40:53 -0700 From: Jon Hunter To: Stephen Warren , Thierry Reding , Alexandre Courbot , Philipp Zabel , Peter De Schrijver , Prashant Gaikwad , =?UTF-8?q?Terje=20Bergstr=C3=B6m?= , Hans de Goede , Tejun Heo Subject: [PATCH V3 10/19] drm/tegra: dc: Prepare for generic PM domains Date: Mon, 13 Jul 2015 13:39:48 +0100 Message-ID: <1436791197-32358-11-git-send-email-jonathanh@nvidia.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1436791197-32358-1-git-send-email-jonathanh@nvidia.com> References: <1436791197-32358-1-git-send-email-jonathanh@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150713_054112_809826_F24C4265 X-CRM114-Status: GOOD ( 19.86 ) X-Spam-Score: -8.3 (--------) 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: devicetree@vger.kernel.org, Ulf Hansson , Vince Hsu , Kevin Hilman , linux-pm@vger.kernel.org, "Rafael J. Wysocki" , Jon Hunter , linux-tegra@vger.kernel.org, linux-arm-kernel@lists.infradead.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 Add support to the tegra dc driver for generic PM domains. However, to ensure backward compatibility with older device tree blobs ensure that the driver can work with or without generic PM domains. In order to migrate to generic PM domain infrastructure the necessary changes are: 1. If the "power-domains" property is present in the DT device node then generic PM domains is supported and pm_runtime_enable() should be called for the device. Furthermore, the enabling and disabling of the power-domain is handled via calling pm_runtime_get/put, respectively. 2. To ensure that clocks are managed consistently when generic PM domains are used and are not used, drivers should be migrated to use the tegra_powergate_power_on_legacy() and tegra_powergate_power_off_legacy() functions instead of the current tegra_powergate_sequence_power_up() and tegra_powergate_power_off(). The purpose of the tegra_powergate_power_on_legacy() and tegra_powergate_power_off_legacy() APIs is to mimick the behaviour of the tegra generic power-domain code, such that if generic power domains are not supported the functionality is the same. 3. The main difference between the tegra_powergate_sequence_power_up() API and the tegra_powergate_power_on_legacy() is that the clock used to enable the powergate is not kept enabled when using the tegra_powergate_power_on_legacy() API. Therefore, drivers must enable the clocks they need after calling tegra_powergate_power_on_legacy() and disable these clocks before calling tegra_powergate_power_off_legacy(). Helper functions have been added to the dc driver for handling power on and off the power-domains with and without generic PM domain support. Signed-off-by: Jon Hunter --- drivers/gpu/drm/tegra/dc.c | 94 +++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index a287e4fec865..a5b2475a7b9c 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -1880,6 +1881,49 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc) return 0; } +static void tegra_dc_power_off(struct tegra_dc *dc) +{ + if (!dc->soc->has_powergate) + reset_control_assert(dc->rst); + + clk_disable_unprepare(dc->clk); + + if (dc->soc->has_powergate) { + if (pm_runtime_enabled(dc->dev)) + pm_runtime_put_sync(dc->dev); + else + tegra_powergate_power_off_legacy(dc->powergate, + dc->clk, dc->rst); + } +} + +static int tegra_dc_power_on(struct tegra_dc *dc) +{ + int err; + + if (dc->soc->has_powergate) { + if (pm_runtime_enabled(dc->dev)) + err = pm_runtime_get_sync(dc->dev); + else + err = tegra_powergate_power_on_legacy(dc->powergate, + dc->clk, dc->rst); + if (err < 0) { + dev_err(dc->dev, "failed to power partition: %d\n", + err); + return err; + } + } + + err = clk_prepare_enable(dc->clk); + if (err < 0) + dev_err(dc->dev, "failed to enable clock: %d\n", err); + + if (!dc->soc->has_powergate) + reset_control_deassert(dc->rst); + + return err; +} + static int tegra_dc_probe(struct platform_device *pdev) { unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; @@ -1917,35 +1961,6 @@ static int tegra_dc_probe(struct platform_device *pdev) return PTR_ERR(dc->rst); } - if (dc->soc->has_powergate) { - if (dc->pipe == 0) - dc->powergate = TEGRA_POWERGATE_DIS; - else - dc->powergate = TEGRA_POWERGATE_DISB; - - err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk, - dc->rst); - if (err < 0) { - dev_err(&pdev->dev, "failed to power partition: %d\n", - err); - return err; - } - } else { - err = clk_prepare_enable(dc->clk); - if (err < 0) { - dev_err(&pdev->dev, "failed to enable clock: %d\n", - err); - return err; - } - - err = reset_control_deassert(dc->rst); - if (err < 0) { - dev_err(&pdev->dev, "failed to deassert reset: %d\n", - err); - return err; - } - } - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); dc->regs = devm_ioremap_resource(&pdev->dev, regs); if (IS_ERR(dc->regs)) @@ -1961,6 +1976,20 @@ static int tegra_dc_probe(struct platform_device *pdev) dc->client.ops = &dc_client_ops; dc->client.dev = &pdev->dev; + if (dc->soc->has_powergate) { + if (dc->pipe == 0) + dc->powergate = TEGRA_POWERGATE_DIS; + else + dc->powergate = TEGRA_POWERGATE_DISB; + + if (of_property_read_bool(pdev->dev.of_node, "power-domains")) + pm_runtime_enable(&pdev->dev); + } + + err = tegra_dc_power_on(dc); + if (err < 0) + return err; + err = tegra_dc_rgb_probe(dc); if (err < 0 && err != -ENODEV) { dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err); @@ -2003,12 +2032,7 @@ static int tegra_dc_remove(struct platform_device *pdev) return err; } - reset_control_assert(dc->rst); - - if (dc->soc->has_powergate) - tegra_powergate_power_off(dc->powergate); - - clk_disable_unprepare(dc->clk); + tegra_dc_power_off(dc); return 0; }