diff --git a/Documentation/phy.txt b/Documentation/phy.txt
index ebff6ee52441edbca95a0ebc8b20cd49ac218d3d..3ea6ee7f7fdac5c0dba015f290a95146b7c66739 100644
--- a/Documentation/phy.txt
+++ b/Documentation/phy.txt
@@ -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 device pointer, phy ops and init_data.
 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
-to the PHY in the case of non-dt boot. See section *Board File Initialization*
-on how init_data should be used.
+init, exit, power_on and power_off, , suspend, resume and advertise_quirks.
+*init_data* is mandatory to get a reference to the PHY in the case of non-dt
+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
 can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index c64a2f3b2d624fb9d8c266b979416d6b53ed5b9f..107d16c40f7d871447af0a9dc8c572258eebc160 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -276,6 +276,64 @@ int phy_power_off(struct phy *phy)
 }
 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
  * @np: device_node for which to get the phy
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 2760744cb2a75ff59e3d172a6dd864ef42b32106..43cfdcf39fa4dbf5b411ca6499c4cc7a19635038 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -27,6 +27,14 @@ struct phy;
  * @exit: operation to be performed while exiting
  * @power_on: powering on 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
  */
 struct phy_ops {
@@ -34,6 +42,9 @@ struct phy_ops {
 	int	(*exit)(struct phy *phy);
 	int	(*power_on)(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;
 };
 
@@ -55,6 +66,8 @@ struct phy_attrs {
  * @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
  * @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 device		dev;
@@ -65,6 +78,7 @@ struct phy {
 	int			init_count;
 	int			power_count;
 	struct phy_attrs	attrs;
+	int			resume_count;
 };
 
 /**
@@ -137,6 +151,10 @@ 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);
+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)
 {
 	return phy->attrs.bus_width;
@@ -248,6 +266,21 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width)
 	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)
 {
 	return ERR_PTR(-ENOSYS);