[PATCH v3 14/16] phy: Add notify_speed callback

From: Manu Gautam
Date: Tue Nov 21 2017 - 04:26:34 EST


QCOM USB PHYs can monitor resume/remote-wakeup event in
suspended state. However PHY driver must know current
operational speed of PHY in order to set correct polarity of
wakeup events for detection. E.g. QUSB2 PHY monitors DP/DM
signals depending on speed is LS or FS/HS to detect resume.
Similarly QMP USB3 PHY in SS mode should monitor RX
terminations attach/detach and LFPS events depending on
SSPHY is active or not.

Signed-off-by: Manu Gautam <mgautam@xxxxxxxxxxxxxx>
---
drivers/phy/phy-core.c | 30 ++++++++++++++++++++++++++++++
include/linux/phy/phy.h | 26 ++++++++++++++++++++++++++
2 files changed, 56 insertions(+)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b4964b0..03df2be 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -387,6 +387,36 @@ int phy_calibrate(struct phy *phy)
}
EXPORT_SYMBOL_GPL(phy_calibrate);

+int phy_notify_speed(struct phy *phy, enum phy_speed speed)
+{
+ int ret;
+
+ if (!phy || !phy->ops->notify_speed)
+ return 0;
+
+ mutex_lock(&phy->mutex);
+ ret = phy->ops->notify_speed(phy, speed);
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_notify_speed);
+
+enum phy_speed phy_get_speed(struct phy *phy)
+{
+ enum phy_speed ret;
+
+ if (!phy || !phy->ops->get_speed)
+ return PHY_SPEED_UNKNOWN;
+
+ mutex_lock(&phy->mutex);
+ ret = phy->ops->get_speed(phy);
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_get_speed);
+
/**
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
* @np: device_node for which to get the phy
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 4f8423a..9efd3cd 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -33,6 +33,14 @@ enum phy_mode {
PHY_MODE_UFS_HS_B,
};

+enum phy_speed {
+ PHY_SPEED_UNKNOWN,
+ PHY_SPEED_USB_LS,
+ PHY_SPEED_USB_FS,
+ PHY_SPEED_USB_HS,
+ PHY_SPEED_USB_SS,
+};
+
/**
* struct phy_ops - set of function pointers for performing phy operations
* @init: operation to be performed for initializing phy
@@ -42,6 +50,8 @@ enum phy_mode {
* @set_mode: set the mode of the phy
* @reset: resetting the phy
* @calibrate: calibrate the phy
+ * @notify_speed: notify phy driver of current speed of PHY
+ * @get_speed: get current operational speed of PHY
* @owner: the module owner containing the ops
*/
struct phy_ops {
@@ -52,6 +62,8 @@ struct phy_ops {
int (*set_mode)(struct phy *phy, enum phy_mode mode);
int (*reset)(struct phy *phy);
int (*calibrate)(struct phy *phy);
+ int (*notify_speed)(struct phy *phy, enum phy_speed speed);
+ enum phy_speed (*get_speed)(struct phy *phy);
struct module *owner;
};

@@ -146,6 +158,8 @@ static inline void *phy_get_drvdata(struct phy *phy)
int phy_set_mode(struct phy *phy, enum phy_mode mode);
int phy_reset(struct phy *phy);
int phy_calibrate(struct phy *phy);
+int phy_notify_speed(struct phy *phy, enum phy_speed speed);
+enum phy_speed phy_get_speed(struct phy *phy);
static inline int phy_get_bus_width(struct phy *phy)
{
return phy->attrs.bus_width;
@@ -274,6 +288,18 @@ static inline int phy_calibrate(struct phy *phy)
return -ENOSYS;
}

+static inline int phy_notify_speed(struct phy *phy, enum phy_speed speed)
+{
+ if (!phy)
+ return 0;
+ return -EINVAL;
+}
+
+static inline enum phy_speed phy_get_speed(struct phy *phy)
+{
+ return PHY_SPEED_UNKNOWN;
+}
+
static inline int phy_get_bus_width(struct phy *phy)
{
return -ENOSYS;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project