Skip to content
Snippets Groups Projects
Commit 21bd073f authored by Yaniv Gardi's avatar Yaniv Gardi Committed by Gerrit - the friendly Code Review server
Browse files

phy: extend APIs of the generic phy framework


This change adds a few more APIs to the phy_ops structure:
advertise_quirks - API for setting the phy quirks
suspend - API for the implementation of phy suspend sequence
resume - API for the implementation of phy resume sequence

Change-Id: I44dd77f2603d20acb02ccb0cc0d20ade884f97c2
Signed-off-by: default avatarYaniv Gardi <ygardi@codeaurora.org>
parent 0618eb24
Branches
Tags
No related merge requests found
...@@ -61,9 +61,9 @@ struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops, ...@@ -61,9 +61,9 @@ struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
The PHY drivers can use one of the above 2 APIs to create the PHY by passing The PHY drivers can use one of the above 2 APIs to create the PHY by passing
the device pointer, phy ops and init_data. the device pointer, phy ops and init_data.
phy_ops is a set of function pointers for performing PHY operations such as phy_ops is a set of function pointers for performing PHY operations such as
init, exit, power_on and power_off. *init_data* is mandatory to get a reference init, exit, power_on and power_off, , suspend, resume and advertise_quirks.
to the PHY in the case of non-dt boot. See section *Board File Initialization* *init_data* is mandatory to get a reference to the PHY in the case of non-dt
on how init_data should be used. boot. See section *Board File Initialization* on how init_data should be used.
Inorder to dereference the private data (in phy_ops), the phy provider driver Inorder to dereference the private data (in phy_ops), the phy provider driver
can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
......
...@@ -276,6 +276,64 @@ int phy_power_off(struct phy *phy) ...@@ -276,6 +276,64 @@ int phy_power_off(struct phy *phy)
} }
EXPORT_SYMBOL_GPL(phy_power_off); EXPORT_SYMBOL_GPL(phy_power_off);
int phy_suspend(struct phy *phy)
{
int ret = 0;
if (!phy->ops->suspend)
return -ENOTSUPP;
mutex_lock(&phy->mutex);
if (--phy->resume_count == 0) {
ret = phy->ops->suspend(phy);
if (ret) {
dev_err(&phy->dev, "phy suspend failed --> %d\n", ret);
/* reverting the resume_count since suspend failed */
phy->resume_count++;
goto out;
}
}
out:
mutex_unlock(&phy->mutex);
return ret;
}
EXPORT_SYMBOL(phy_suspend);
int phy_resume(struct phy *phy)
{
int ret = 0;
if (!phy->ops->resume)
return -ENOTSUPP;
mutex_lock(&phy->mutex);
if (phy->resume_count++ == 0) {
ret = phy->ops->resume(phy);
if (ret) {
dev_err(&phy->dev, "phy resume failed --> %d\n", ret);
/* reverting the resume_count since resume failed */
phy->resume_count--;
goto out;
}
}
out:
mutex_unlock(&phy->mutex);
return ret;
}
EXPORT_SYMBOL(phy_resume);
void phy_advertise_quirks(struct phy *phy)
{
if (phy->ops->advertise_quirks) {
mutex_lock(&phy->mutex);
phy->ops->advertise_quirks(phy);
mutex_unlock(&phy->mutex);
}
}
EXPORT_SYMBOL(phy_advertise_quirks);
/** /**
* _of_phy_get() - lookup and obtain a reference to a phy by phandle * _of_phy_get() - lookup and obtain a reference to a phy by phandle
* @np: device_node for which to get the phy * @np: device_node for which to get the phy
......
...@@ -27,6 +27,14 @@ struct phy; ...@@ -27,6 +27,14 @@ struct phy;
* @exit: operation to be performed while exiting * @exit: operation to be performed while exiting
* @power_on: powering on the phy * @power_on: powering on the phy
* @power_off: powering off the phy * @power_off: powering off the phy
* @advertise_quirks: setting specific phy quirks. this api is for an
internal use of the device driver, and its
purpose is to exteriorize the driver's phy quirks
according to phy version (or other parameters),
so further behaviour of the driver's phy is based
on those quirks.
* @suspend: suspending the phy
* @resume: resuming the phy
* @owner: the module owner containing the ops * @owner: the module owner containing the ops
*/ */
struct phy_ops { struct phy_ops {
...@@ -34,6 +42,9 @@ struct phy_ops { ...@@ -34,6 +42,9 @@ struct phy_ops {
int (*exit)(struct phy *phy); int (*exit)(struct phy *phy);
int (*power_on)(struct phy *phy); int (*power_on)(struct phy *phy);
int (*power_off)(struct phy *phy); int (*power_off)(struct phy *phy);
void (*advertise_quirks)(struct phy *phy);
int (*suspend)(struct phy *phy);
int (*resume)(struct phy *phy);
struct module *owner; struct module *owner;
}; };
...@@ -55,6 +66,8 @@ struct phy_attrs { ...@@ -55,6 +66,8 @@ struct phy_attrs {
* @init_count: used to protect when the PHY is used by multiple consumers * @init_count: used to protect when the PHY is used by multiple consumers
* @power_count: used to protect when the PHY is used by multiple consumers * @power_count: used to protect when the PHY is used by multiple consumers
* @phy_attrs: used to specify PHY specific attributes * @phy_attrs: used to specify PHY specific attributes
* @resume_count: used to protect when the PHY is used by multiple consumers
* that resume and suspend it
*/ */
struct phy { struct phy {
struct device dev; struct device dev;
...@@ -65,6 +78,7 @@ struct phy { ...@@ -65,6 +78,7 @@ struct phy {
int init_count; int init_count;
int power_count; int power_count;
struct phy_attrs attrs; struct phy_attrs attrs;
int resume_count;
}; };
/** /**
...@@ -137,6 +151,10 @@ int phy_init(struct phy *phy); ...@@ -137,6 +151,10 @@ int phy_init(struct phy *phy);
int phy_exit(struct phy *phy); int phy_exit(struct phy *phy);
int phy_power_on(struct phy *phy); int phy_power_on(struct phy *phy);
int phy_power_off(struct phy *phy); int phy_power_off(struct phy *phy);
void phy_advertise_quirks(struct phy *phy);
int phy_suspend(struct phy *phy);
int phy_resume(struct phy *phy);
static inline int phy_get_bus_width(struct phy *phy) static inline int phy_get_bus_width(struct phy *phy)
{ {
return phy->attrs.bus_width; return phy->attrs.bus_width;
...@@ -248,6 +266,21 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width) ...@@ -248,6 +266,21 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width)
return; return;
} }
static inline void phy_advertise_quirks(struct phy *phy)
{
return;
}
static inline int phy_suspend(struct phy *phy)
{
return -ENOSYS;
}
static inline int phy_resume(struct phy *phy)
{
return -ENOSYS;
}
static inline struct phy *phy_get(struct device *dev, const char *string) static inline struct phy *phy_get(struct device *dev, const char *string)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment