Merge tag 'firewire-update' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[platform/kernel/linux-starfive.git] / drivers / opp / core.c
index 9ff0538..be7a7d3 100644 (file)
@@ -2103,6 +2103,75 @@ put_table:
 }
 
 /**
+ * dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP
+ * @dev:               device for which we do this operation
+ * @freq:              OPP frequency to adjust voltage of
+ * @u_volt:            new OPP target voltage
+ * @u_volt_min:                new OPP min voltage
+ * @u_volt_max:                new OPP max voltage
+ *
+ * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ */
+int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
+                             unsigned long u_volt, unsigned long u_volt_min,
+                             unsigned long u_volt_max)
+
+{
+       struct opp_table *opp_table;
+       struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV);
+       int r = 0;
+
+       /* Find the opp_table */
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               r = PTR_ERR(opp_table);
+               dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+               return r;
+       }
+
+       mutex_lock(&opp_table->lock);
+
+       /* Do we have the frequency? */
+       list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
+               if (tmp_opp->rate == freq) {
+                       opp = tmp_opp;
+                       break;
+               }
+       }
+
+       if (IS_ERR(opp)) {
+               r = PTR_ERR(opp);
+               goto adjust_unlock;
+       }
+
+       /* Is update really needed? */
+       if (opp->supplies->u_volt == u_volt)
+               goto adjust_unlock;
+
+       opp->supplies->u_volt = u_volt;
+       opp->supplies->u_volt_min = u_volt_min;
+       opp->supplies->u_volt_max = u_volt_max;
+
+       dev_pm_opp_get(opp);
+       mutex_unlock(&opp_table->lock);
+
+       /* Notify the voltage change of the OPP */
+       blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE,
+                                    opp);
+
+       dev_pm_opp_put(opp);
+       goto adjust_put_table;
+
+adjust_unlock:
+       mutex_unlock(&opp_table->lock);
+adjust_put_table:
+       dev_pm_opp_put_opp_table(opp_table);
+       return r;
+}
+
+/**
  * dev_pm_opp_enable() - Enable a specific OPP
  * @dev:       device for which we do this operation
  * @freq:      OPP frequency to enable