From patchwork Mon Aug 27 05:07:19 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 180122 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B77712C00D7 for ; Mon, 27 Aug 2012 15:08:01 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751882Ab2H0FHx (ORCPT ); Mon, 27 Aug 2012 01:07:53 -0400 Received: from service87.mimecast.com ([91.220.42.44]:33989 "EHLO service87.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751816Ab2H0FHa (ORCPT ); Mon, 27 Aug 2012 01:07:30 -0400 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Mon, 27 Aug 2012 06:07:28 +0100 Received: from localhost ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Mon, 27 Aug 2012 06:09:24 +0100 From: Viresh Kumar To: jgarzik@redhat.com Cc: linux-ide@vger.kernel.org, sshtylyov@mvista.com, spear-devel@list.st.com, viresh.linux@gmail.com, Viresh Kumar Subject: [PATCH V3 Resend 3/3] ata/ahci_platform: Add clock framework support Date: Mon, 27 Aug 2012 10:37:19 +0530 Message-Id: <26ddcaf1af37a0a40227d073e66e14e0cdb14769.1346042344.git.viresh.kumar@linaro.com> X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: References: In-Reply-To: References: X-OriginalArrivalTime: 27 Aug 2012 05:09:24.0779 (UTC) FILETIME=[202E37B0:01CD8412] X-MC-Unique: 112082706072800201 Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org From: Viresh Kumar On many architectures, drivers are supposed to prepare/unprepare & enable/disable functional clock of device. This patch adds clock support for ahci_platform. Signed-off-by: Viresh Kumar --- drivers/ata/ahci.h | 2 ++ drivers/ata/ahci_platform.c | 57 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 57eb1c2..838a262 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -35,6 +35,7 @@ #ifndef _AHCI_H #define _AHCI_H +#include #include /* Enclosure Management Control */ @@ -302,6 +303,7 @@ struct ahci_host_priv { u32 em_loc; /* enclosure management location */ u32 em_buf_sz; /* EM buffer size in byte */ u32 em_msg_type; /* EM message type */ + struct clk *clk; /* Only for platforms supporting clk */ }; extern int ahci_ignore_sss; diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 09728e0..90c2eb9 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -12,6 +12,7 @@ * any later version. */ +#include #include #include #include @@ -118,6 +119,17 @@ static int __init ahci_probe(struct platform_device *pdev) return -ENOMEM; } + hpriv->clk = clk_get(dev, NULL); + if (IS_ERR(hpriv->clk)) { + dev_err(dev, "can't get clock\n"); + } else { + rc = clk_prepare_enable(hpriv->clk); + if (rc) { + dev_err(dev, "clock prepare enable failed"); + goto free_clk; + } + } + /* * Some platforms might need to prepare for mmio region access, * which could be done in the following init call. So, the mmio @@ -127,7 +139,7 @@ static int __init ahci_probe(struct platform_device *pdev) if (pdata && pdata->init) { rc = pdata->init(dev, hpriv->mmio); if (rc) - return rc; + goto disable_unprepare_clk; } ahci_save_initial_config(dev, hpriv, @@ -153,7 +165,7 @@ static int __init ahci_probe(struct platform_device *pdev) host = ata_host_alloc_pinfo(dev, ppi, n_ports); if (!host) { rc = -ENOMEM; - goto err0; + goto pdata_exit; } host->private_data = hpriv; @@ -183,7 +195,7 @@ static int __init ahci_probe(struct platform_device *pdev) rc = ahci_reset_controller(host); if (rc) - goto err0; + goto pdata_exit; ahci_init_controller(host); ahci_print_info(host, "platform"); @@ -191,12 +203,18 @@ static int __init ahci_probe(struct platform_device *pdev) rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, &ahci_platform_sht); if (rc) - goto err0; + goto pdata_exit; return 0; -err0: +pdata_exit: if (pdata && pdata->exit) pdata->exit(dev); +disable_unprepare_clk: + if (!IS_ERR(hpriv->clk)) + clk_disable_unprepare(hpriv->clk); +free_clk: + if (!IS_ERR(hpriv->clk)) + clk_put(hpriv->clk); return rc; } @@ -205,12 +223,18 @@ static int __devexit ahci_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; ata_host_detach(host); if (pdata && pdata->exit) pdata->exit(dev); + if (!IS_ERR(hpriv->clk)) { + clk_disable_unprepare(hpriv->clk); + clk_put(hpriv->clk); + } + return 0; } @@ -245,6 +269,10 @@ static int ahci_suspend(struct device *dev) if (pdata && pdata->suspend) return pdata->suspend(dev); + + if (!IS_ERR(hpriv->clk)) + clk_disable_unprepare(hpriv->clk); + return 0; } @@ -252,18 +280,27 @@ static int ahci_resume(struct device *dev) { struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; int rc; + if (!IS_ERR(hpriv->clk)) { + rc = clk_prepare_enable(hpriv->clk); + if (rc) { + dev_err(dev, "clock prepare enable failed"); + return rc; + } + } + if (pdata && pdata->resume) { rc = pdata->resume(dev); if (rc) - return rc; + goto disable_unprepare_clk; } if (dev->power.power_state.event == PM_EVENT_SUSPEND) { rc = ahci_reset_controller(host); if (rc) - return rc; + goto disable_unprepare_clk; ahci_init_controller(host); } @@ -271,6 +308,12 @@ static int ahci_resume(struct device *dev) ata_host_resume(host); return 0; + +disable_unprepare_clk: + if (!IS_ERR(hpriv->clk)) + clk_disable_unprepare(hpriv->clk); + + return rc; } #endif