From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751498AbdBMW0J (ORCPT ); Mon, 13 Feb 2017 17:26:09 -0500 Received: from smtp6-g21.free.fr ([212.27.42.6]:12636 "EHLO smtp6-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751333AbdBMW0I (ORCPT ); Mon, 13 Feb 2017 17:26:08 -0500 From: Alban To: linux-kernel@vger.kernel.org Cc: Alban Bedel , Kishon Vijay Abraham I Subject: [PATCH v5 1/3] phy: core: Add support for clock and reset to the phy core Date: Mon, 13 Feb 2017 23:25:44 +0100 Message-Id: <1487024746-32082-1-git-send-email-albeu@free.fr> X-Mailer: git-send-email 2.7.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alban Bedel Signed-off-by: Alban Bedel --- drivers/phy/phy-core.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/phy/phy.h | 4 ++++ 2 files changed, 52 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index a268f4d..e6c55af 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include static struct class *phy_class; static DEFINE_MUTEX(phy_provider_mutex); @@ -286,6 +288,12 @@ int phy_power_on(struct phy *phy) goto out; } + if (phy->clk) { + ret = clk_prepare_enable(phy->clk); + if (ret) + goto err_clk_enable; + } + ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) goto err_pm_sync; @@ -293,6 +301,11 @@ int phy_power_on(struct phy *phy) ret = 0; /* Override possible ret == -ENOTSUPP */ mutex_lock(&phy->mutex); + if (phy->power_count == 0 && phy->reset) { + ret = reset_control_deassert(phy->reset); + if (ret) + goto err_reset_deassert; + } if (phy->power_count == 0 && phy->ops->power_on) { ret = phy->ops->power_on(phy); if (ret < 0) { @@ -305,9 +318,15 @@ int phy_power_on(struct phy *phy) return 0; err_pwr_on: + if (phy->reset) + reset_control_assert(phy->reset); +err_reset_deassert: mutex_unlock(&phy->mutex); phy_pm_runtime_put_sync(phy); err_pm_sync: + if (phy->clk) + clk_disable_unprepare(phy->clk); +err_clk_enable: if (phy->pwr) regulator_disable(phy->pwr); out: @@ -331,10 +350,18 @@ int phy_power_off(struct phy *phy) return ret; } } + if (phy->power_count == 1 && phy->reset) { + ret = reset_control_assert(phy->reset); + if (ret < 0) + dev_warn(&phy->dev, + "phy reset assert failed --> %d\n", ret); + } --phy->power_count; mutex_unlock(&phy->mutex); phy_pm_runtime_put(phy); + if (phy->clk) + clk_disable_unprepare(phy->clk); if (phy->pwr) regulator_disable(phy->pwr); @@ -755,6 +782,24 @@ struct phy *phy_create(struct device *dev, struct device_node *node, phy->pwr = NULL; } + phy->clk = clk_get(dev, "phy"); + if (IS_ERR(phy->clk)) { + ret = PTR_ERR(phy->clk); + if (ret == -ENOENT) + phy->clk = NULL; + else + goto put_dev; + } + + phy->reset = reset_control_get(dev, "phy"); + if (IS_ERR(phy->reset)) { + ret = PTR_ERR(phy->reset); + if (ret == -ENOENT || ret == -ENOTSUPP) + phy->reset = NULL; + else + goto put_dev; + } + ret = device_add(&phy->dev); if (ret) goto put_dev; @@ -991,6 +1036,9 @@ static void phy_release(struct device *dev) phy = to_phy(dev); dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); + if (phy->reset) + reset_control_put(phy->reset); + clk_put(phy->clk); regulator_put(phy->pwr); ida_simple_remove(&phy_ida, phy->id); kfree(phy); diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 78bb0d7..cc67d33 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -21,6 +21,8 @@ #include struct phy; +struct clk; +struct reset_control; enum phy_mode { PHY_MODE_INVALID, @@ -77,6 +79,8 @@ struct phy { int power_count; struct phy_attrs attrs; struct regulator *pwr; + struct clk *clk; + struct reset_control *reset; }; /** -- 2.7.4