pmic-cpcap.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * pmic-cpcap.c - CPCAP-specific functions for the OPP code
  4. *
  5. * Adapted from Motorola Mapphone Android Linux kernel
  6. * Copyright (C) 2011 Motorola, Inc.
  7. */
  8. #include <linux/err.h>
  9. #include <linux/io.h>
  10. #include <linux/kernel.h>
  11. #include "soc.h"
  12. #include "pm.h"
  13. #include "voltage.h"
  14. #include <linux/init.h>
  15. #include "vc.h"
  16. /**
  17. * omap_cpcap_vsel_to_vdc - convert CPCAP VSEL value to microvolts DC
  18. * @vsel: CPCAP VSEL value to convert
  19. *
  20. * Returns the microvolts DC that the CPCAP PMIC should generate when
  21. * programmed with @vsel.
  22. */
  23. static unsigned long omap_cpcap_vsel_to_uv(unsigned char vsel)
  24. {
  25. if (vsel > 0x44)
  26. vsel = 0x44;
  27. return (((vsel * 125) + 6000)) * 100;
  28. }
  29. /**
  30. * omap_cpcap_uv_to_vsel - convert microvolts DC to CPCAP VSEL value
  31. * @uv: microvolts DC to convert
  32. *
  33. * Returns the VSEL value necessary for the CPCAP PMIC to
  34. * generate an output voltage equal to or greater than @uv microvolts DC.
  35. */
  36. static unsigned char omap_cpcap_uv_to_vsel(unsigned long uv)
  37. {
  38. if (uv < 600000)
  39. uv = 600000;
  40. else if (uv > 1450000)
  41. uv = 1450000;
  42. return DIV_ROUND_UP(uv - 600000, 12500);
  43. }
  44. static struct omap_voltdm_pmic omap_cpcap_core = {
  45. .slew_rate = 4000,
  46. .step_size = 12500,
  47. .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
  48. .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
  49. .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
  50. .vddmin = 900000,
  51. .vddmax = 1350000,
  52. .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
  53. .i2c_slave_addr = 0x02,
  54. .volt_reg_addr = 0x00,
  55. .cmd_reg_addr = 0x01,
  56. .i2c_high_speed = false,
  57. .vsel_to_uv = omap_cpcap_vsel_to_uv,
  58. .uv_to_vsel = omap_cpcap_uv_to_vsel,
  59. };
  60. static struct omap_voltdm_pmic omap_cpcap_iva = {
  61. .slew_rate = 4000,
  62. .step_size = 12500,
  63. .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
  64. .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
  65. .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
  66. .vddmin = 900000,
  67. .vddmax = 1375000,
  68. .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
  69. .i2c_slave_addr = 0x44,
  70. .volt_reg_addr = 0x0,
  71. .cmd_reg_addr = 0x01,
  72. .i2c_high_speed = false,
  73. .vsel_to_uv = omap_cpcap_vsel_to_uv,
  74. .uv_to_vsel = omap_cpcap_uv_to_vsel,
  75. };
  76. /**
  77. * omap_max8952_vsel_to_vdc - convert MAX8952 VSEL value to microvolts DC
  78. * @vsel: MAX8952 VSEL value to convert
  79. *
  80. * Returns the microvolts DC that the MAX8952 Regulator should generate when
  81. * programmed with @vsel.
  82. */
  83. static unsigned long omap_max8952_vsel_to_uv(unsigned char vsel)
  84. {
  85. if (vsel > 0x3F)
  86. vsel = 0x3F;
  87. return (((vsel * 100) + 7700)) * 100;
  88. }
  89. /**
  90. * omap_max8952_uv_to_vsel - convert microvolts DC to MAX8952 VSEL value
  91. * @uv: microvolts DC to convert
  92. *
  93. * Returns the VSEL value necessary for the MAX8952 Regulator to
  94. * generate an output voltage equal to or greater than @uv microvolts DC.
  95. */
  96. static unsigned char omap_max8952_uv_to_vsel(unsigned long uv)
  97. {
  98. if (uv < 770000)
  99. uv = 770000;
  100. else if (uv > 1400000)
  101. uv = 1400000;
  102. return DIV_ROUND_UP(uv - 770000, 10000);
  103. }
  104. static struct omap_voltdm_pmic omap443x_max8952_mpu = {
  105. .slew_rate = 16000,
  106. .step_size = 10000,
  107. .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
  108. .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
  109. .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
  110. .vddmin = 900000,
  111. .vddmax = 1400000,
  112. .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
  113. .i2c_slave_addr = 0x60,
  114. .volt_reg_addr = 0x03,
  115. .cmd_reg_addr = 0x03,
  116. .i2c_high_speed = false,
  117. .vsel_to_uv = omap_max8952_vsel_to_uv,
  118. .uv_to_vsel = omap_max8952_uv_to_vsel,
  119. };
  120. /**
  121. * omap_fan5355_vsel_to_vdc - convert FAN535503 VSEL value to microvolts DC
  122. * @vsel: FAN535503 VSEL value to convert
  123. *
  124. * Returns the microvolts DC that the FAN535503 Regulator should generate when
  125. * programmed with @vsel.
  126. */
  127. static unsigned long omap_fan535503_vsel_to_uv(unsigned char vsel)
  128. {
  129. /* Extract bits[5:0] */
  130. vsel &= 0x3F;
  131. return (((vsel * 125) + 7500)) * 100;
  132. }
  133. /**
  134. * omap_fan535508_vsel_to_vdc - convert FAN535508 VSEL value to microvolts DC
  135. * @vsel: FAN535508 VSEL value to convert
  136. *
  137. * Returns the microvolts DC that the FAN535508 Regulator should generate when
  138. * programmed with @vsel.
  139. */
  140. static unsigned long omap_fan535508_vsel_to_uv(unsigned char vsel)
  141. {
  142. /* Extract bits[5:0] */
  143. vsel &= 0x3F;
  144. if (vsel > 0x37)
  145. vsel = 0x37;
  146. return (((vsel * 125) + 7500)) * 100;
  147. }
  148. /**
  149. * omap_fan535503_uv_to_vsel - convert microvolts DC to FAN535503 VSEL value
  150. * @uv: microvolts DC to convert
  151. *
  152. * Returns the VSEL value necessary for the MAX8952 Regulator to
  153. * generate an output voltage equal to or greater than @uv microvolts DC.
  154. */
  155. static unsigned char omap_fan535503_uv_to_vsel(unsigned long uv)
  156. {
  157. unsigned char vsel;
  158. if (uv < 750000)
  159. uv = 750000;
  160. else if (uv > 1537500)
  161. uv = 1537500;
  162. vsel = DIV_ROUND_UP(uv - 750000, 12500);
  163. return vsel | 0xC0;
  164. }
  165. /**
  166. * omap_fan535508_uv_to_vsel - convert microvolts DC to FAN535508 VSEL value
  167. * @uv: microvolts DC to convert
  168. *
  169. * Returns the VSEL value necessary for the MAX8952 Regulator to
  170. * generate an output voltage equal to or greater than @uv microvolts DC.
  171. */
  172. static unsigned char omap_fan535508_uv_to_vsel(unsigned long uv)
  173. {
  174. unsigned char vsel;
  175. if (uv < 750000)
  176. uv = 750000;
  177. else if (uv > 1437500)
  178. uv = 1437500;
  179. vsel = DIV_ROUND_UP(uv - 750000, 12500);
  180. return vsel | 0xC0;
  181. }
  182. /* fan5335-core */
  183. static struct omap_voltdm_pmic omap4_fan_core = {
  184. .slew_rate = 4000,
  185. .step_size = 12500,
  186. .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
  187. .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
  188. .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
  189. .vddmin = 850000,
  190. .vddmax = 1375000,
  191. .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
  192. .i2c_slave_addr = 0x4A,
  193. .i2c_high_speed = false,
  194. .volt_reg_addr = 0x01,
  195. .cmd_reg_addr = 0x01,
  196. .vsel_to_uv = omap_fan535508_vsel_to_uv,
  197. .uv_to_vsel = omap_fan535508_uv_to_vsel,
  198. };
  199. /* fan5335 iva */
  200. static struct omap_voltdm_pmic omap4_fan_iva = {
  201. .slew_rate = 4000,
  202. .step_size = 12500,
  203. .vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
  204. .vp_vstepmin = OMAP4_VP_VSTEPMIN_VSTEPMIN,
  205. .vp_vstepmax = OMAP4_VP_VSTEPMAX_VSTEPMAX,
  206. .vddmin = 850000,
  207. .vddmax = 1375000,
  208. .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
  209. .i2c_slave_addr = 0x48,
  210. .volt_reg_addr = 0x01,
  211. .cmd_reg_addr = 0x01,
  212. .i2c_high_speed = false,
  213. .vsel_to_uv = omap_fan535503_vsel_to_uv,
  214. .uv_to_vsel = omap_fan535503_uv_to_vsel,
  215. };
  216. int __init omap4_cpcap_init(void)
  217. {
  218. struct voltagedomain *voltdm;
  219. if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
  220. return -ENODEV;
  221. voltdm = voltdm_lookup("mpu");
  222. omap_voltage_register_pmic(voltdm, &omap443x_max8952_mpu);
  223. if (of_machine_is_compatible("motorola,droid-bionic")) {
  224. voltdm = voltdm_lookup("core");
  225. omap_voltage_register_pmic(voltdm, &omap_cpcap_core);
  226. voltdm = voltdm_lookup("iva");
  227. omap_voltage_register_pmic(voltdm, &omap_cpcap_iva);
  228. } else {
  229. voltdm = voltdm_lookup("core");
  230. omap_voltage_register_pmic(voltdm, &omap4_fan_core);
  231. voltdm = voltdm_lookup("iva");
  232. omap_voltage_register_pmic(voltdm, &omap4_fan_iva);
  233. }
  234. return 0;
  235. }
  236. static int __init cpcap_late_init(void)
  237. {
  238. omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
  239. return 0;
  240. }
  241. omap_late_initcall(cpcap_late_init);