diff options
Diffstat (limited to 'drivers/phy/phy-core.c')
-rw-r--r-- | drivers/phy/phy-core.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 645c867c1257..6c738376daff 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -162,6 +162,9 @@ int phy_init(struct phy *phy) | |||
162 | { | 162 | { |
163 | int ret; | 163 | int ret; |
164 | 164 | ||
165 | if (!phy) | ||
166 | return 0; | ||
167 | |||
165 | ret = phy_pm_runtime_get_sync(phy); | 168 | ret = phy_pm_runtime_get_sync(phy); |
166 | if (ret < 0 && ret != -ENOTSUPP) | 169 | if (ret < 0 && ret != -ENOTSUPP) |
167 | return ret; | 170 | return ret; |
@@ -173,6 +176,8 @@ int phy_init(struct phy *phy) | |||
173 | dev_err(&phy->dev, "phy init failed --> %d\n", ret); | 176 | dev_err(&phy->dev, "phy init failed --> %d\n", ret); |
174 | goto out; | 177 | goto out; |
175 | } | 178 | } |
179 | } else { | ||
180 | ret = 0; /* Override possible ret == -ENOTSUPP */ | ||
176 | } | 181 | } |
177 | ++phy->init_count; | 182 | ++phy->init_count; |
178 | 183 | ||
@@ -187,6 +192,9 @@ int phy_exit(struct phy *phy) | |||
187 | { | 192 | { |
188 | int ret; | 193 | int ret; |
189 | 194 | ||
195 | if (!phy) | ||
196 | return 0; | ||
197 | |||
190 | ret = phy_pm_runtime_get_sync(phy); | 198 | ret = phy_pm_runtime_get_sync(phy); |
191 | if (ret < 0 && ret != -ENOTSUPP) | 199 | if (ret < 0 && ret != -ENOTSUPP) |
192 | return ret; | 200 | return ret; |
@@ -212,6 +220,9 @@ int phy_power_on(struct phy *phy) | |||
212 | { | 220 | { |
213 | int ret; | 221 | int ret; |
214 | 222 | ||
223 | if (!phy) | ||
224 | return 0; | ||
225 | |||
215 | ret = phy_pm_runtime_get_sync(phy); | 226 | ret = phy_pm_runtime_get_sync(phy); |
216 | if (ret < 0 && ret != -ENOTSUPP) | 227 | if (ret < 0 && ret != -ENOTSUPP) |
217 | return ret; | 228 | return ret; |
@@ -223,6 +234,8 @@ int phy_power_on(struct phy *phy) | |||
223 | dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); | 234 | dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); |
224 | goto out; | 235 | goto out; |
225 | } | 236 | } |
237 | } else { | ||
238 | ret = 0; /* Override possible ret == -ENOTSUPP */ | ||
226 | } | 239 | } |
227 | ++phy->power_count; | 240 | ++phy->power_count; |
228 | mutex_unlock(&phy->mutex); | 241 | mutex_unlock(&phy->mutex); |
@@ -240,6 +253,9 @@ int phy_power_off(struct phy *phy) | |||
240 | { | 253 | { |
241 | int ret; | 254 | int ret; |
242 | 255 | ||
256 | if (!phy) | ||
257 | return 0; | ||
258 | |||
243 | mutex_lock(&phy->mutex); | 259 | mutex_lock(&phy->mutex); |
244 | if (phy->power_count == 1 && phy->ops->power_off) { | 260 | if (phy->power_count == 1 && phy->ops->power_off) { |
245 | ret = phy->ops->power_off(phy); | 261 | ret = phy->ops->power_off(phy); |
@@ -308,7 +324,7 @@ err0: | |||
308 | */ | 324 | */ |
309 | void phy_put(struct phy *phy) | 325 | void phy_put(struct phy *phy) |
310 | { | 326 | { |
311 | if (IS_ERR(phy)) | 327 | if (!phy || IS_ERR(phy)) |
312 | return; | 328 | return; |
313 | 329 | ||
314 | module_put(phy->ops->owner); | 330 | module_put(phy->ops->owner); |
@@ -328,6 +344,9 @@ void devm_phy_put(struct device *dev, struct phy *phy) | |||
328 | { | 344 | { |
329 | int r; | 345 | int r; |
330 | 346 | ||
347 | if (!phy) | ||
348 | return; | ||
349 | |||
331 | r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); | 350 | r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); |
332 | dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); | 351 | dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); |
333 | } | 352 | } |
@@ -389,17 +408,11 @@ struct phy *phy_get(struct device *dev, const char *string) | |||
389 | index = of_property_match_string(dev->of_node, "phy-names", | 408 | index = of_property_match_string(dev->of_node, "phy-names", |
390 | string); | 409 | string); |
391 | phy = of_phy_get(dev, index); | 410 | phy = of_phy_get(dev, index); |
392 | if (IS_ERR(phy)) { | ||
393 | dev_err(dev, "unable to find phy\n"); | ||
394 | return phy; | ||
395 | } | ||
396 | } else { | 411 | } else { |
397 | phy = phy_lookup(dev, string); | 412 | phy = phy_lookup(dev, string); |
398 | if (IS_ERR(phy)) { | ||
399 | dev_err(dev, "unable to find phy\n"); | ||
400 | return phy; | ||
401 | } | ||
402 | } | 413 | } |
414 | if (IS_ERR(phy)) | ||
415 | return phy; | ||
403 | 416 | ||
404 | if (!try_module_get(phy->ops->owner)) | 417 | if (!try_module_get(phy->ops->owner)) |
405 | return ERR_PTR(-EPROBE_DEFER); | 418 | return ERR_PTR(-EPROBE_DEFER); |
@@ -411,6 +424,27 @@ struct phy *phy_get(struct device *dev, const char *string) | |||
411 | EXPORT_SYMBOL_GPL(phy_get); | 424 | EXPORT_SYMBOL_GPL(phy_get); |
412 | 425 | ||
413 | /** | 426 | /** |
427 | * phy_optional_get() - lookup and obtain a reference to an optional phy. | ||
428 | * @dev: device that requests this phy | ||
429 | * @string: the phy name as given in the dt data or the name of the controller | ||
430 | * port for non-dt case | ||
431 | * | ||
432 | * Returns the phy driver, after getting a refcount to it; or | ||
433 | * NULL if there is no such phy. The caller is responsible for | ||
434 | * calling phy_put() to release that count. | ||
435 | */ | ||
436 | struct phy *phy_optional_get(struct device *dev, const char *string) | ||
437 | { | ||
438 | struct phy *phy = phy_get(dev, string); | ||
439 | |||
440 | if (PTR_ERR(phy) == -ENODEV) | ||
441 | phy = NULL; | ||
442 | |||
443 | return phy; | ||
444 | } | ||
445 | EXPORT_SYMBOL_GPL(phy_optional_get); | ||
446 | |||
447 | /** | ||
414 | * devm_phy_get() - lookup and obtain a reference to a phy. | 448 | * devm_phy_get() - lookup and obtain a reference to a phy. |
415 | * @dev: device that requests this phy | 449 | * @dev: device that requests this phy |
416 | * @string: the phy name as given in the dt data or phy device name | 450 | * @string: the phy name as given in the dt data or phy device name |
@@ -441,6 +475,30 @@ struct phy *devm_phy_get(struct device *dev, const char *string) | |||
441 | EXPORT_SYMBOL_GPL(devm_phy_get); | 475 | EXPORT_SYMBOL_GPL(devm_phy_get); |
442 | 476 | ||
443 | /** | 477 | /** |
478 | * devm_phy_optional_get() - lookup and obtain a reference to an optional phy. | ||
479 | * @dev: device that requests this phy | ||
480 | * @string: the phy name as given in the dt data or phy device name | ||
481 | * for non-dt case | ||
482 | * | ||
483 | * Gets the phy using phy_get(), and associates a device with it using | ||
484 | * devres. On driver detach, release function is invoked on the devres | ||
485 | * data, then, devres data is freed. This differs to devm_phy_get() in | ||
486 | * that if the phy does not exist, it is not considered an error and | ||
487 | * -ENODEV will not be returned. Instead the NULL phy is returned, | ||
488 | * which can be passed to all other phy consumer calls. | ||
489 | */ | ||
490 | struct phy *devm_phy_optional_get(struct device *dev, const char *string) | ||
491 | { | ||
492 | struct phy *phy = devm_phy_get(dev, string); | ||
493 | |||
494 | if (PTR_ERR(phy) == -ENODEV) | ||
495 | phy = NULL; | ||
496 | |||
497 | return phy; | ||
498 | } | ||
499 | EXPORT_SYMBOL_GPL(devm_phy_optional_get); | ||
500 | |||
501 | /** | ||
444 | * phy_create() - create a new phy | 502 | * phy_create() - create a new phy |
445 | * @dev: device that is creating the new phy | 503 | * @dev: device that is creating the new phy |
446 | * @ops: function pointers for performing phy operations | 504 | * @ops: function pointers for performing phy operations |