vp.c 8.6 KB

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