1#include <linux/kernel.h> 2#include <linux/init.h> 3 4#include "common.h" 5 6#include "voltage.h" 7#include "vp.h" 8#include "prm-regbits-34xx.h" 9#include "prm-regbits-44xx.h" 10#include "prm44xx.h" 11 12static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt) 13{ 14 struct omap_vp_instance *vp = voltdm->vp; 15 u32 vpconfig; 16 char vsel; 17 18 vsel = voltdm->pmic->uv_to_vsel(volt); 19 20 vpconfig = voltdm->read(vp->vpconfig); 21 vpconfig &= ~(vp->common->vpconfig_initvoltage_mask | 22 vp->common->vpconfig_forceupdate | 23 vp->common->vpconfig_initvdd); 24 vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask); 25 voltdm->write(vpconfig, vp->vpconfig); 26 27 /* Trigger initVDD value copy to voltage processor */ 28 voltdm->write((vpconfig | vp->common->vpconfig_initvdd), 29 vp->vpconfig); 30 31 /* Clear initVDD copy trigger bit */ 32 voltdm->write(vpconfig, vp->vpconfig); 33 34 return vpconfig; 35} 36 37/* Generic voltage init functions */ 38void __init omap_vp_init(struct voltagedomain *voltdm) 39{ 40 struct omap_vp_instance *vp = voltdm->vp; 41 u32 val, sys_clk_rate, timeout, waittime; 42 u32 vddmin, vddmax, vstepmin, vstepmax; 43 44 if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { 45 pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name); 46 return; 47 } 48 49 if (!voltdm->read || !voltdm->write) { 50 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 51 __func__, voltdm->name); 52 return; 53 } 54 55 vp->enabled = false; 56 57 /* Divide to avoid overflow */ 58 sys_clk_rate = voltdm->sys_clk.rate / 1000; 59 60 timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000; 61 vddmin = max(voltdm->vp_param->vddmin, voltdm->pmic->vddmin); 62 vddmax = min(voltdm->vp_param->vddmax, voltdm->pmic->vddmax); 63 vddmin = voltdm->pmic->uv_to_vsel(vddmin); 64 vddmax = voltdm->pmic->uv_to_vsel(vddmax); 65 66 waittime = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate, 67 1000 * voltdm->pmic->slew_rate); 68 vstepmin = voltdm->pmic->vp_vstepmin; 69 vstepmax = voltdm->pmic->vp_vstepmax; 70 71 /* 72 * VP_CONFIG: error gain is not set here, it will be updated 73 * on each scale, based on OPP. 74 */ 75 val = (voltdm->pmic->vp_erroroffset << 76 __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) | 77 vp->common->vpconfig_timeouten; 78 voltdm->write(val, vp->vpconfig); 79 80 /* VSTEPMIN */ 81 val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) | 82 (vstepmin << vp->common->vstepmin_stepmin_shift); 83 voltdm->write(val, vp->vstepmin); 84 85 /* VSTEPMAX */ 86 val = (vstepmax << vp->common->vstepmax_stepmax_shift) | 87 (waittime << vp->common->vstepmax_smpswaittimemax_shift); 88 voltdm->write(val, vp->vstepmax); 89 90 /* VLIMITTO */ 91 val = (vddmax << vp->common->vlimitto_vddmax_shift) | 92 (vddmin << vp->common->vlimitto_vddmin_shift) | 93 (timeout << vp->common->vlimitto_timeout_shift); 94 voltdm->write(val, vp->vlimitto); 95} 96 97int omap_vp_update_errorgain(struct voltagedomain *voltdm, 98 unsigned long target_volt) 99{ 100 struct omap_volt_data *volt_data; 101 102 if (!voltdm->vp) 103 return -EINVAL; 104 105 /* Get volt_data corresponding to target_volt */ 106 volt_data = omap_voltage_get_voltdata(voltdm, target_volt); 107 if (IS_ERR(volt_data)) 108 return -EINVAL; 109 110 /* Setting vp errorgain based on the voltage */ 111 voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask, 112 volt_data->vp_errgain << 113 __ffs(voltdm->vp->common->vpconfig_errorgain_mask), 114 voltdm->vp->vpconfig); 115 116 return 0; 117} 118 119/* VP force update method of voltage scaling */ 120int omap_vp_forceupdate_scale(struct voltagedomain *voltdm, 121 unsigned long target_volt) 122{ 123 struct omap_vp_instance *vp = voltdm->vp; 124 u32 vpconfig; 125 u8 target_vsel, current_vsel; 126 int ret, timeout = 0; 127 128 ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, ¤t_vsel); 129 if (ret) 130 return ret; 131 132 /* 133 * Clear all pending TransactionDone interrupt/status. Typical latency 134 * is <3us 135 */ 136 while (timeout++ < VP_TRANXDONE_TIMEOUT) { 137 vp->common->ops->clear_txdone(vp->id); 138 if (!vp->common->ops->check_txdone(vp->id)) 139 break; 140 udelay(1); 141 } 142 if (timeout >= VP_TRANXDONE_TIMEOUT) { 143 pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted\n", 144 __func__, voltdm->name); 145 return -ETIMEDOUT; 146 } 147 148 vpconfig = _vp_set_init_voltage(voltdm, target_volt); 149 150 /* Force update of voltage */ 151 voltdm->write(vpconfig | vp->common->vpconfig_forceupdate, 152 voltdm->vp->vpconfig); 153 154 /* 155 * Wait for TransactionDone. Typical latency is <200us. 156 * Depends on SMPSWAITTIMEMIN/MAX and voltage change 157 */ 158 timeout = 0; 159 omap_test_timeout(vp->common->ops->check_txdone(vp->id), 160 VP_TRANXDONE_TIMEOUT, timeout); 161 if (timeout >= VP_TRANXDONE_TIMEOUT) 162 pr_err("%s: vdd_%s TRANXDONE timeout exceeded. TRANXDONE never got set after the voltage update\n", 163 __func__, voltdm->name); 164 165 omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel); 166 167 /* 168 * Disable TransactionDone interrupt , clear all status, clear 169 * control registers 170 */ 171 timeout = 0; 172 while (timeout++ < VP_TRANXDONE_TIMEOUT) { 173 vp->common->ops->clear_txdone(vp->id); 174 if (!vp->common->ops->check_txdone(vp->id)) 175 break; 176 udelay(1); 177 } 178 179 if (timeout >= VP_TRANXDONE_TIMEOUT) 180 pr_warn("%s: vdd_%s TRANXDONE timeout exceeded while trying to clear the TRANXDONE status\n", 181 __func__, voltdm->name); 182 183 /* Clear force bit */ 184 voltdm->write(vpconfig, vp->vpconfig); 185 186 return 0; 187} 188 189/** 190 * omap_vp_enable() - API to enable a particular VP 191 * @voltdm: pointer to the VDD whose VP is to be enabled. 192 * 193 * This API enables a particular voltage processor. Needed by the smartreflex 194 * class drivers. 195 */ 196void omap_vp_enable(struct voltagedomain *voltdm) 197{ 198 struct omap_vp_instance *vp; 199 u32 vpconfig, volt; 200 201 if (!voltdm || IS_ERR(voltdm)) { 202 pr_warn("%s: VDD specified does not exist!\n", __func__); 203 return; 204 } 205 206 vp = voltdm->vp; 207 if (!voltdm->read || !voltdm->write) { 208 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 209 __func__, voltdm->name); 210 return; 211 } 212 213 /* If VP is already enabled, do nothing. Return */ 214 if (vp->enabled) 215 return; 216 217 volt = voltdm_get_voltage(voltdm); 218 if (!volt) { 219 pr_warn("%s: unable to find current voltage for %s\n", 220 __func__, voltdm->name); 221 return; 222 } 223 224 vpconfig = _vp_set_init_voltage(voltdm, volt); 225 226 /* Enable VP */ 227 vpconfig |= vp->common->vpconfig_vpenable; 228 voltdm->write(vpconfig, vp->vpconfig); 229 230 vp->enabled = true; 231} 232 233/** 234 * omap_vp_disable() - API to disable a particular VP 235 * @voltdm: pointer to the VDD whose VP is to be disabled. 236 * 237 * This API disables a particular voltage processor. Needed by the smartreflex 238 * class drivers. 239 */ 240void omap_vp_disable(struct voltagedomain *voltdm) 241{ 242 struct omap_vp_instance *vp; 243 u32 vpconfig; 244 int timeout; 245 246 if (!voltdm || IS_ERR(voltdm)) { 247 pr_warn("%s: VDD specified does not exist!\n", __func__); 248 return; 249 } 250 251 vp = voltdm->vp; 252 if (!voltdm->read || !voltdm->write) { 253 pr_err("%s: No read/write API for accessing vdd_%s regs\n", 254 __func__, voltdm->name); 255 return; 256 } 257 258 /* If VP is already disabled, do nothing. Return */ 259 if (!vp->enabled) { 260 pr_warn("%s: Trying to disable VP for vdd_%s when it is already disabled\n", 261 __func__, voltdm->name); 262 return; 263 } 264 265 /* Disable VP */ 266 vpconfig = voltdm->read(vp->vpconfig); 267 vpconfig &= ~vp->common->vpconfig_vpenable; 268 voltdm->write(vpconfig, vp->vpconfig); 269 270 /* 271 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us 272 */ 273 omap_test_timeout((voltdm->read(vp->vstatus)), 274 VP_IDLE_TIMEOUT, timeout); 275 276 if (timeout >= VP_IDLE_TIMEOUT) 277 pr_warn("%s: vdd_%s idle timedout\n", __func__, voltdm->name); 278 279 vp->enabled = false; 280 281 return; 282} 283