From patchwork Mon Dec 9 15:08:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 3311541 Return-Path: X-Original-To: patchwork-linux-arm@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 0D28DC0D4A for ; Mon, 9 Dec 2013 15:11:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9E1AF20268 for ; Mon, 9 Dec 2013 15:11:22 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1E5B12016C for ; Mon, 9 Dec 2013 15:11:21 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vq2TZ-0000gf-MK; Mon, 09 Dec 2013 15:10:25 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vq2TO-0007ka-1f; Mon, 09 Dec 2013 15:10:14 +0000 Received: from mga14.intel.com ([143.182.124.37]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vq2Sy-0007g5-RM for linux-arm-kernel@lists.infradead.org; Mon, 09 Dec 2013 15:09:51 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by azsmga102.ch.intel.com with ESMTP; 09 Dec 2013 07:09:04 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.93,858,1378882800"; d="scan'208";a="441039590" Received: from blue.fi.intel.com ([10.237.72.156]) by fmsmga001.fm.intel.com with ESMTP; 09 Dec 2013 07:09:02 -0800 From: Heikki Krogerus To: Kishon Vijay Abraham I Subject: [PATCH 2/5] phy: add support for indexed lookup Date: Mon, 9 Dec 2013 17:08:54 +0200 Message-Id: <1386601737-8735-3-git-send-email-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 1.8.5.1 In-Reply-To: <1386601737-8735-1-git-send-email-heikki.krogerus@linux.intel.com> References: <1386601737-8735-1-git-send-email-heikki.krogerus@linux.intel.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131209_100949_166210_A6075286 X-CRM114-Status: GOOD ( 25.59 ) X-Spam-Score: -6.9 (------) Cc: linux-samsung-soc@vger.kernel.org, linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 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 Removes the need for the consumer drivers requesting the phys to provide name for the phy. This should ease the use of the framework considerable when using only one phy, which is usually the case when except with USB, but it can also be useful with multiple phys. This will also reduce noise from the framework when there is no phy by changing warnings to debug messages. Signed-off-by: Heikki Krogerus --- drivers/phy/phy-core.c | 106 ++++++++++++++++++++++++++++++++++-------------- include/linux/phy/phy.h | 14 +++++++ 2 files changed, 89 insertions(+), 31 deletions(-) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 1102aef..99dc046 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -53,7 +53,8 @@ static int devm_phy_match(struct device *dev, void *res, void *match_data) return res == match_data; } -static struct phy *phy_lookup(struct device *device, const char *con_id) +static struct phy *phy_lookup(struct device *device, const char *con_id, + unsigned int idx) { unsigned int count; struct phy *phy; @@ -67,6 +68,10 @@ static struct phy *phy_lookup(struct device *device, const char *con_id) count = phy->init_data->num_consumers; consumers = phy->init_data->consumers; while (count--) { + /* index must always match exactly */ + if (!con_id) + if (idx != count) + continue; if (!strcmp(consumers->dev_name, dev_name(device)) && !strcmp(consumers->port, con_id)) { class_dev_iter_exit(&iter); @@ -242,7 +247,8 @@ EXPORT_SYMBOL_GPL(phy_power_off); /** * of_phy_get() - lookup and obtain a reference to a phy by phandle * @dev: device that requests this phy - * @index: the index of the phy + * @con_id: name of the phy from device's point of view + * @idx: the index of the phy if name is not used * * Returns the phy associated with the given phandle value, * after getting a refcount to it or -ENODEV if there is no such phy or @@ -250,12 +256,20 @@ EXPORT_SYMBOL_GPL(phy_power_off); * not yet loaded. This function uses of_xlate call back function provided * while registering the phy_provider to find the phy instance. */ -static struct phy *of_phy_get(struct device *dev, int index) +static struct phy *of_phy_get(struct device *dev, const char *con_id, + unsigned int idx) { int ret; struct phy_provider *phy_provider; struct phy *phy = NULL; struct of_phandle_args args; + int index; + + if (!con_id) + index = idx; + else + index = of_property_match_string(dev->of_node, "phy-names", + con_id); ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", index, &args); @@ -348,38 +362,36 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args EXPORT_SYMBOL_GPL(of_phy_simple_xlate); /** - * phy_get() - lookup and obtain a reference to a phy. + * phy_get_index() - obtain a phy based on index * @dev: device that requests this phy * @con_id: name of the phy from device's point of view + * @idx: index of the phy to obtain in the consumer * - * Returns the phy driver, after getting a refcount to it; or - * -ENODEV if there is no such phy. The caller is responsible for - * calling phy_put() to release that count. + * This variant of phy_get() allows to access PHYs other than the first + * defined one for functions that define several PHYs. */ -struct phy *phy_get(struct device *dev, const char *con_id) +struct phy *phy_get_index(struct device *dev, const char *con_id, + unsigned int idx) { - int index = 0; struct phy *phy = NULL; - if (con_id == NULL) { - dev_WARN(dev, "missing string\n"); - return ERR_PTR(-EINVAL); + if (dev->of_node) { + dev_dbg(dev, "using device tree for PHY lookup\n"); + phy = of_phy_get(dev, con_id, idx); } - if (dev->of_node) { - index = of_property_match_string(dev->of_node, "phy-names", - con_id); - phy = of_phy_get(dev, index); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } - } else { - phy = phy_lookup(dev, con_id); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } + /** + * Either we are not using DT, or their lookup did not return + * a result. In that case, use platform lookup as a fallback. + */ + if (!phy || IS_ERR(phy)) { + dev_dbg(dev, "using lookup tables for PHY lookup"); + phy = phy_lookup(dev, con_id, idx); + } + + if (IS_ERR(phy)) { + dev_dbg(dev, "unable to find phy\n"); + return phy; } if (!try_module_get(phy->ops->owner)) @@ -389,18 +401,20 @@ struct phy *phy_get(struct device *dev, const char *con_id) return phy; } -EXPORT_SYMBOL_GPL(phy_get); +EXPORT_SYMBOL_GPL(phy_get_index); /** - * devm_phy_get() - lookup and obtain a reference to a phy. + * devm_phy_get_index() - obtain a phy based on index * @dev: device that requests this phy * @con_id: name of the phy from device's point of view + * @idx: index of the phy to obtain in the consumer * - * Gets the phy using phy_get(), and associates a device with it using + * Gets the phy using phy_get_index(), and associates a device with it using * devres. On driver detach, release function is invoked on the devres data, * then, devres data is freed. */ -struct phy *devm_phy_get(struct device *dev, const char *con_id) +struct phy *devm_phy_get_index(struct device *dev, const char *con_id, + unsigned int idx) { struct phy **ptr, *phy; @@ -408,7 +422,7 @@ struct phy *devm_phy_get(struct device *dev, const char *con_id) if (!ptr) return ERR_PTR(-ENOMEM); - phy = phy_get(dev, con_id); + phy = phy_get_index(dev, con_id, idx); if (!IS_ERR(phy)) { *ptr = phy; devres_add(dev, ptr); @@ -418,6 +432,36 @@ struct phy *devm_phy_get(struct device *dev, const char *con_id) return phy; } +EXPORT_SYMBOL_GPL(devm_phy_get_index); + +/** + * phy_get() - lookup and obtain a reference to a phy. + * @dev: device that requests this phy + * @con_id: name of the phy from device's point of view + * + * Returns the phy driver, after getting a refcount to it; or + * -ENODEV if there is no such phy. The caller is responsible for + * calling phy_put() to release that count. + */ +struct phy *phy_get(struct device *dev, const char *con_id) +{ + return phy_get_index(dev, con_id, 0); +} +EXPORT_SYMBOL_GPL(phy_get); + +/** + * devm_phy_get() - lookup and obtain a reference to a phy. + * @dev: device that requests this phy + * @con_id: name of the phy from device's point of view + * + * Gets the phy using phy_get_index(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres data, + * then, devres data is freed. + */ +struct phy *devm_phy_get(struct device *dev, const char *con_id) +{ + return devm_phy_get_index(dev, con_id, 0); +} EXPORT_SYMBOL_GPL(devm_phy_get); /** diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index d67dcbf..43d1a23 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -127,6 +127,8 @@ int phy_init(struct phy *phy); int phy_exit(struct phy *phy); int phy_power_on(struct phy *phy); int phy_power_off(struct phy *phy); +struct phy *phy_get_index(struct device *, const char *, unsigned int); +struct phy *devm_phy_get_index(struct device *, const char *, unsigned int); struct phy *phy_get(struct device *dev, const char *con_id); struct phy *devm_phy_get(struct device *dev, const char *con_id); void phy_put(struct phy *phy); @@ -199,6 +201,18 @@ static inline int phy_power_off(struct phy *phy) return -ENOSYS; } +static inline struct phy *phy_get_index(struct device *dev, const char *id, + unsigned int idx) +{ + return ERR_PTR(-ENOSYS); +} + +static inline struct phy *devm_phy_get_index(struct device *dev, + const char *id, unsigned int idx) +{ + return ERR_PTR(-ENOSYS); +} + static inline struct phy *phy_get(struct device *dev, const char *con_id) { return ERR_PTR(-ENOSYS);