diff options
author | Andrew Lunn <andrew@lunn.ch> | 2014-02-04 18:33:12 +0100 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-02-05 05:48:43 +0000 |
commit | 788a4d56ff378bff0b8e685d03a962b36903a149 (patch) | |
tree | d22d5b9e750448fb0d7695bf4c9360b326668a95 | |
parent | 04c2facad8fee66c981a51852806d8923336f362 (diff) | |
download | linux-rpi3-788a4d56ff378bff0b8e685d03a962b36903a149.tar.gz linux-rpi3-788a4d56ff378bff0b8e685d03a962b36903a149.tar.bz2 linux-rpi3-788a4d56ff378bff0b8e685d03a962b36903a149.zip |
drivers: phy: Add support for optional phys
Add devm_phy_optional_get and phy_optional_get, which should be used
when the phy is optional. They does not return an error when the phy
does not exist, rather they returns NULL, which is considered as a valid
phy, but results in NOPs when used with the consumer API.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r-- | Documentation/phy.txt | 20 | ||||
-rw-r--r-- | drivers/phy/phy-core.c | 45 | ||||
-rw-r--r-- | include/linux/phy/phy.h | 14 |
3 files changed, 72 insertions, 7 deletions
diff --git a/Documentation/phy.txt b/Documentation/phy.txt index 2e24b993e95f..ebff6ee52441 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt @@ -75,14 +75,20 @@ Before the controller can make use of the PHY, it has to get a reference to it. This framework provides the following APIs to get a reference to the PHY. struct phy *phy_get(struct device *dev, const char *string); +struct phy *phy_optional_get(struct device *dev, const char *string); struct phy *devm_phy_get(struct device *dev, const char *string); - -phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot, -the string arguments should contain the phy name as given in the dt data and -in the case of non-dt boot, it should contain the label of the PHY. -The only difference between the two APIs is that devm_phy_get associates the -device with the PHY using devres on successful PHY get. On driver detach, -release function is invoked on the the devres data and devres data is freed. +struct phy *devm_phy_optional_get(struct device *dev, const char *string); + +phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can +be used to get the PHY. In the case of dt boot, the string arguments +should contain the phy name as given in the dt data and in the case of +non-dt boot, it should contain the label of the PHY. The two +devm_phy_get associates the device with the PHY using devres on +successful PHY get. On driver detach, release function is invoked on +the the devres data and devres data is freed. phy_optional_get and +devm_phy_optional_get should be used when the phy is optional. These +two functions will never return -ENODEV, but instead returns NULL when +the phy cannot be found. It should be noted that NULL is a valid phy reference. All phy consumer calls on the NULL phy become NOPs. That is the release calls, diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index a9cdeee20d91..5f5b0f4be5be 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -426,6 +426,27 @@ struct phy *phy_get(struct device *dev, const char *string) EXPORT_SYMBOL_GPL(phy_get); /** + * phy_optional_get() - lookup and obtain a reference to an optional phy. + * @dev: device that requests this phy + * @string: the phy name as given in the dt data or the name of the controller + * port for non-dt case + * + * Returns the phy driver, after getting a refcount to it; or + * NULL if there is no such phy. The caller is responsible for + * calling phy_put() to release that count. + */ +struct phy *phy_optional_get(struct device *dev, const char *string) +{ + struct phy *phy = phy_get(dev, string); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + return phy; +} +EXPORT_SYMBOL_GPL(phy_optional_get); + +/** * devm_phy_get() - lookup and obtain a reference to a phy. * @dev: device that requests this phy * @string: the phy name as given in the dt data or phy device name @@ -456,6 +477,30 @@ struct phy *devm_phy_get(struct device *dev, const char *string) EXPORT_SYMBOL_GPL(devm_phy_get); /** + * devm_phy_optional_get() - lookup and obtain a reference to an optional phy. + * @dev: device that requests this phy + * @string: the phy name as given in the dt data or phy device name + * for non-dt case + * + * Gets the phy using phy_get(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres + * data, then, devres data is freed. This differs to devm_phy_get() in + * that if the phy does not exist, it is not considered an error and + * -ENODEV will not be returned. Instead the NULL phy is returned, + * which can be passed to all other phy consumer calls. + */ +struct phy *devm_phy_optional_get(struct device *dev, const char *string) +{ + struct phy *phy = devm_phy_get(dev, string); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + return phy; +} +EXPORT_SYMBOL_GPL(devm_phy_optional_get); + +/** * phy_create() - create a new phy * @dev: device that is creating the new phy * @ops: function pointers for performing phy operations diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index e273e5ac19c9..3f83459dbb20 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -146,7 +146,9 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width) phy->attrs.bus_width = bus_width; } struct phy *phy_get(struct device *dev, const char *string); +struct phy *phy_optional_get(struct device *dev, const char *string); struct phy *devm_phy_get(struct device *dev, const char *string); +struct phy *devm_phy_optional_get(struct device *dev, const char *string); void phy_put(struct phy *phy); void devm_phy_put(struct device *dev, struct phy *phy); struct phy *of_phy_simple_xlate(struct device *dev, @@ -232,11 +234,23 @@ static inline struct phy *phy_get(struct device *dev, const char *string) return ERR_PTR(-ENOSYS); } +static inline struct phy *phy_optional_get(struct device *dev, + const char *string) +{ + return ERR_PTR(-ENOSYS); +} + static inline struct phy *devm_phy_get(struct device *dev, const char *string) { return ERR_PTR(-ENOSYS); } +static inline struct phy *devm_phy_optional_get(struct device *dev, + const char *string) +{ + return ERR_PTR(-ENOSYS); +} + static inline void phy_put(struct phy *phy) { } |