|
@@ -158,3 +158,188 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,
|
|
|
|
|
|
*volt_data = voltdm->volt_data;
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_voltage_get_voltdata() - API to get the voltage table entry for a
|
|
|
+ * particular voltage
|
|
|
+ * @voltdm: pointer to the VDD whose voltage table has to be searched
|
|
|
+ * @volt: the voltage to be searched in the voltage table
|
|
|
+ *
|
|
|
+ * This API searches through the voltage table for the required voltage
|
|
|
+ * domain and tries to find a matching entry for the passed voltage volt.
|
|
|
+ * If a matching entry is found volt_data is populated with that entry.
|
|
|
+ * This API searches only through the non-compensated voltages int the
|
|
|
+ * voltage table.
|
|
|
+ * Returns pointer to the voltage table entry corresponding to volt on
|
|
|
+ * success. Returns -ENODATA if no voltage table exisits for the passed voltage
|
|
|
+ * domain or if there is no matching entry.
|
|
|
+ */
|
|
|
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
|
|
|
+ unsigned long volt)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!voltdm || IS_ERR(voltdm)) {
|
|
|
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!voltdm->volt_data) {
|
|
|
+ pr_warning("%s: voltage table does not exist for vdd_%s\n",
|
|
|
+ __func__, voltdm->name);
|
|
|
+ return ERR_PTR(-ENODATA);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
|
|
|
+ if (voltdm->volt_data[i].volt_nominal == volt)
|
|
|
+ return &voltdm->volt_data[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_notice("%s: Unable to match the current voltage with the voltage table for vdd_%s\n",
|
|
|
+ __func__, voltdm->name);
|
|
|
+
|
|
|
+ return ERR_PTR(-ENODATA);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_voltage_register_pmic() - API to register PMIC specific data
|
|
|
+ * @voltdm: pointer to the VDD for which the PMIC specific data is
|
|
|
+ * to be registered
|
|
|
+ * @pmic: the structure containing pmic info
|
|
|
+ *
|
|
|
+ * This API is to be called by the SOC/PMIC file to specify the
|
|
|
+ * pmic specific info as present in omap_voltdm_pmic structure.
|
|
|
+ */
|
|
|
+int omap_voltage_register_pmic(struct voltagedomain *voltdm,
|
|
|
+ struct omap_voltdm_pmic *pmic)
|
|
|
+{
|
|
|
+ if (!voltdm || IS_ERR(voltdm)) {
|
|
|
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ voltdm->pmic = pmic;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_change_voltscale_method() - API to change the voltage scaling method.
|
|
|
+ * @voltdm: pointer to the VDD whose voltage scaling method
|
|
|
+ * has to be changed.
|
|
|
+ * @voltscale_method: the method to be used for voltage scaling.
|
|
|
+ *
|
|
|
+ * This API can be used by the board files to change the method of voltage
|
|
|
+ * scaling between vpforceupdate and vcbypass. The parameter values are
|
|
|
+ * defined in voltage.h
|
|
|
+ */
|
|
|
+void omap_change_voltscale_method(struct voltagedomain *voltdm,
|
|
|
+ int voltscale_method)
|
|
|
+{
|
|
|
+ if (!voltdm || IS_ERR(voltdm)) {
|
|
|
+ pr_warning("%s: VDD specified does not exist!\n", __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (voltscale_method) {
|
|
|
+ case VOLTSCALE_VPFORCEUPDATE:
|
|
|
+ voltdm->scale = omap_vp_forceupdate_scale;
|
|
|
+ return;
|
|
|
+ case VOLTSCALE_VCBYPASS:
|
|
|
+ voltdm->scale = omap_vc_bypass_scale;
|
|
|
+ return;
|
|
|
+ default:
|
|
|
+ pr_warn("%s: Trying to change the method of voltage scaling to an unsupported one!\n",
|
|
|
+ __func__);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_voltage_late_init() - Init the various voltage parameters
|
|
|
+ *
|
|
|
+ * This API is to be called in the later stages of the
|
|
|
+ * system boot to init the voltage controller and
|
|
|
+ * voltage processors.
|
|
|
+ */
|
|
|
+int __init omap_voltage_late_init(void)
|
|
|
+{
|
|
|
+ struct voltagedomain *voltdm;
|
|
|
+
|
|
|
+ if (list_empty(&voltdm_list)) {
|
|
|
+ pr_err("%s: Voltage driver support not added\n",
|
|
|
+ __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ list_for_each_entry(voltdm, &voltdm_list, node) {
|
|
|
+ struct clk *sys_ck;
|
|
|
+
|
|
|
+ if (!voltdm->scalable)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ sys_ck = clk_get(NULL, voltdm->sys_clk.name);
|
|
|
+ if (IS_ERR(sys_ck)) {
|
|
|
+ pr_warning("%s: Could not get sys clk.\n", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ voltdm->sys_clk.rate = clk_get_rate(sys_ck);
|
|
|
+ WARN_ON(!voltdm->sys_clk.rate);
|
|
|
+ clk_put(sys_ck);
|
|
|
+
|
|
|
+ if (voltdm->vc) {
|
|
|
+ voltdm->scale = omap_vc_bypass_scale;
|
|
|
+ omap_vc_init_channel(voltdm);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (voltdm->vp) {
|
|
|
+ voltdm->scale = omap_vp_forceupdate_scale;
|
|
|
+ omap_vp_init(voltdm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct voltagedomain *_voltdm_lookup(const char *name)
|
|
|
+{
|
|
|
+ struct voltagedomain *voltdm, *temp_voltdm;
|
|
|
+
|
|
|
+ voltdm = NULL;
|
|
|
+
|
|
|
+ list_for_each_entry(temp_voltdm, &voltdm_list, node) {
|
|
|
+ if (!strcmp(name, temp_voltdm->name)) {
|
|
|
+ voltdm = temp_voltdm;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return voltdm;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
|
|
|
+ * @voltdm: struct voltagedomain * to add the powerdomain to
|
|
|
+ * @pwrdm: struct powerdomain * to associate with a voltagedomain
|
|
|
+ *
|
|
|
+ * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This
|
|
|
+ * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if
|
|
|
+ * presented with invalid pointers; -ENOMEM if memory could not be allocated;
|
|
|
+ * or 0 upon success.
|
|
|
+ */
|
|
|
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
|
|
|
+{
|
|
|
+ if (!voltdm || !pwrdm)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ pr_debug("voltagedomain: %s: associating powerdomain %s\n",
|
|
|
+ voltdm->name, pwrdm->name);
|
|
|
+
|
|
|
+ list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
|
|
|
+ * @voltdm: struct voltagedomain * to iterate over
|
|
|
+ * @fn: callback function *
|