0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/delay.h>
0020 #include <linux/io.h>
0021 #include <linux/err.h>
0022 #include <linux/export.h>
0023 #include <linux/debugfs.h>
0024 #include <linux/slab.h>
0025 #include <linux/clk.h>
0026
0027 #include "common.h"
0028
0029 #include "prm-regbits-34xx.h"
0030 #include "prm-regbits-44xx.h"
0031 #include "prm44xx.h"
0032 #include "prcm44xx.h"
0033 #include "prminst44xx.h"
0034 #include "control.h"
0035
0036 #include "voltage.h"
0037 #include "powerdomain.h"
0038
0039 #include "vc.h"
0040 #include "vp.h"
0041
0042 static LIST_HEAD(voltdm_list);
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
0053 {
0054 if (!voltdm || IS_ERR(voltdm)) {
0055 pr_warn("%s: VDD specified does not exist!\n", __func__);
0056 return 0;
0057 }
0058
0059 return voltdm->nominal_volt;
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 int voltdm_scale(struct voltagedomain *voltdm,
0071 unsigned long target_volt)
0072 {
0073 int ret, i;
0074 unsigned long volt = 0;
0075
0076 if (!voltdm || IS_ERR(voltdm)) {
0077 pr_warn("%s: VDD specified does not exist!\n", __func__);
0078 return -EINVAL;
0079 }
0080
0081 if (!voltdm->scale) {
0082 pr_err("%s: No voltage scale API registered for vdd_%s\n",
0083 __func__, voltdm->name);
0084 return -ENODATA;
0085 }
0086
0087 if (!voltdm->volt_data) {
0088 pr_err("%s: No voltage data defined for vdd_%s\n",
0089 __func__, voltdm->name);
0090 return -ENODATA;
0091 }
0092
0093
0094 for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
0095 if (voltdm->volt_data[i].volt_nominal >= target_volt) {
0096 volt = voltdm->volt_data[i].volt_nominal;
0097 break;
0098 }
0099 }
0100
0101 if (!volt) {
0102 pr_warn("%s: not scaling. OPP voltage for %lu, not found.\n",
0103 __func__, target_volt);
0104 return -EINVAL;
0105 }
0106
0107 ret = voltdm->scale(voltdm, volt);
0108 if (!ret)
0109 voltdm->nominal_volt = volt;
0110
0111 return ret;
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 void voltdm_reset(struct voltagedomain *voltdm)
0124 {
0125 unsigned long target_volt;
0126
0127 if (!voltdm || IS_ERR(voltdm)) {
0128 pr_warn("%s: VDD specified does not exist!\n", __func__);
0129 return;
0130 }
0131
0132 target_volt = voltdm_get_voltage(voltdm);
0133 if (!target_volt) {
0134 pr_err("%s: unable to find current voltage for vdd_%s\n",
0135 __func__, voltdm->name);
0136 return;
0137 }
0138
0139 voltdm_scale(voltdm, target_volt);
0140 }
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
0155 struct omap_volt_data **volt_data)
0156 {
0157 if (!voltdm || IS_ERR(voltdm)) {
0158 pr_warn("%s: VDD specified does not exist!\n", __func__);
0159 return;
0160 }
0161
0162 *volt_data = voltdm->volt_data;
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
0181 unsigned long volt)
0182 {
0183 int i;
0184
0185 if (!voltdm || IS_ERR(voltdm)) {
0186 pr_warn("%s: VDD specified does not exist!\n", __func__);
0187 return ERR_PTR(-EINVAL);
0188 }
0189
0190 if (!voltdm->volt_data) {
0191 pr_warn("%s: voltage table does not exist for vdd_%s\n",
0192 __func__, voltdm->name);
0193 return ERR_PTR(-ENODATA);
0194 }
0195
0196 for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
0197 if (voltdm->volt_data[i].volt_nominal == volt)
0198 return &voltdm->volt_data[i];
0199 }
0200
0201 pr_notice("%s: Unable to match the current voltage with the voltage table for vdd_%s\n",
0202 __func__, voltdm->name);
0203
0204 return ERR_PTR(-ENODATA);
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
0217 struct omap_voltdm_pmic *pmic)
0218 {
0219 if (!voltdm || IS_ERR(voltdm)) {
0220 pr_warn("%s: VDD specified does not exist!\n", __func__);
0221 return -EINVAL;
0222 }
0223
0224 voltdm->pmic = pmic;
0225
0226 return 0;
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236 int __init omap_voltage_late_init(void)
0237 {
0238 struct voltagedomain *voltdm;
0239
0240 if (list_empty(&voltdm_list)) {
0241 pr_err("%s: Voltage driver support not added\n",
0242 __func__);
0243 return -EINVAL;
0244 }
0245
0246 list_for_each_entry(voltdm, &voltdm_list, node) {
0247 struct clk *sys_ck;
0248
0249 if (!voltdm->scalable)
0250 continue;
0251
0252 sys_ck = clk_get(NULL, voltdm->sys_clk.name);
0253 if (IS_ERR(sys_ck)) {
0254 pr_warn("%s: Could not get sys clk.\n", __func__);
0255 return -EINVAL;
0256 }
0257 voltdm->sys_clk.rate = clk_get_rate(sys_ck);
0258 WARN_ON(!voltdm->sys_clk.rate);
0259 clk_put(sys_ck);
0260
0261 if (voltdm->vc) {
0262 voltdm->scale = omap_vc_bypass_scale;
0263 omap_vc_init_channel(voltdm);
0264 }
0265
0266 if (voltdm->vp) {
0267 voltdm->scale = omap_vp_forceupdate_scale;
0268 omap_vp_init(voltdm);
0269 }
0270 }
0271
0272 return 0;
0273 }
0274
0275 static struct voltagedomain *_voltdm_lookup(const char *name)
0276 {
0277 struct voltagedomain *voltdm, *temp_voltdm;
0278
0279 voltdm = NULL;
0280
0281 list_for_each_entry(temp_voltdm, &voltdm_list, node) {
0282 if (!strcmp(name, temp_voltdm->name)) {
0283 voltdm = temp_voltdm;
0284 break;
0285 }
0286 }
0287
0288 return voltdm;
0289 }
0290
0291 static int _voltdm_register(struct voltagedomain *voltdm)
0292 {
0293 if (!voltdm || !voltdm->name)
0294 return -EINVAL;
0295
0296 list_add(&voltdm->node, &voltdm_list);
0297
0298 pr_debug("voltagedomain: registered %s\n", voltdm->name);
0299
0300 return 0;
0301 }
0302
0303
0304
0305
0306
0307
0308
0309
0310 struct voltagedomain *voltdm_lookup(const char *name)
0311 {
0312 struct voltagedomain *voltdm ;
0313
0314 if (!name)
0315 return NULL;
0316
0317 voltdm = _voltdm_lookup(name);
0318
0319 return voltdm;
0320 }
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 void voltdm_init(struct voltagedomain **voltdms)
0332 {
0333 struct voltagedomain **v;
0334
0335 if (voltdms) {
0336 for (v = voltdms; *v; v++)
0337 _voltdm_register(*v);
0338 }
0339 }