axp209.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2012
  4. * Henrik Nordstrom <henrik@henriknordstrom.net>
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <asm/arch/pmic_bus.h>
  9. #include <axp_pmic.h>
  10. #include <linux/delay.h>
  11. #ifdef CONFIG_AXP_ALDO3_VOLT_SLOPE_08
  12. # define AXP209_VRC_SLOPE AXP209_VRC_LDO3_800uV_uS
  13. #endif
  14. #ifdef CONFIG_AXP_ALDO3_VOLT_SLOPE_16
  15. # define AXP209_VRC_SLOPE AXP209_VRC_LDO3_1600uV_uS
  16. #endif
  17. #if defined CONFIG_AXP_ALDO3_VOLT_SLOPE_NONE || !defined AXP209_VRC_SLOPE
  18. # define AXP209_VRC_SLOPE 0x00
  19. #endif
  20. static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
  21. {
  22. if (mvolt < min)
  23. mvolt = min;
  24. else if (mvolt > max)
  25. mvolt = max;
  26. return (mvolt - min) / div;
  27. }
  28. int axp_set_dcdc2(unsigned int mvolt)
  29. {
  30. int rc;
  31. u8 cfg, current;
  32. if (mvolt == 0)
  33. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  34. AXP209_OUTPUT_CTRL_DCDC2);
  35. rc = pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC2);
  36. if (rc)
  37. return rc;
  38. cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
  39. /* Do we really need to be this gentle? It has built-in voltage slope */
  40. while ((rc = pmic_bus_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
  41. current != cfg) {
  42. if (current < cfg)
  43. current++;
  44. else
  45. current--;
  46. rc = pmic_bus_write(AXP209_DCDC2_VOLTAGE, current);
  47. if (rc)
  48. break;
  49. }
  50. return rc;
  51. }
  52. int axp_set_dcdc3(unsigned int mvolt)
  53. {
  54. u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
  55. int rc;
  56. if (mvolt == 0)
  57. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  58. AXP209_OUTPUT_CTRL_DCDC3);
  59. rc = pmic_bus_write(AXP209_DCDC3_VOLTAGE, cfg);
  60. if (rc)
  61. return rc;
  62. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC3);
  63. }
  64. int axp_set_aldo2(unsigned int mvolt)
  65. {
  66. int rc;
  67. u8 cfg, reg;
  68. if (mvolt == 0)
  69. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  70. AXP209_OUTPUT_CTRL_LDO2);
  71. cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
  72. rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
  73. if (rc)
  74. return rc;
  75. reg |= AXP209_LDO24_LDO2_SET(reg, cfg);
  76. rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
  77. if (rc)
  78. return rc;
  79. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO2);
  80. }
  81. int axp_set_aldo3(unsigned int mvolt)
  82. {
  83. u8 cfg;
  84. int rc;
  85. if (mvolt == 0)
  86. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  87. AXP209_OUTPUT_CTRL_LDO3);
  88. /*
  89. * Some boards have trouble reaching the target voltage without causing
  90. * great inrush currents. To prevent this, boards can enable a certain
  91. * slope to ramp up voltage. Note, this only works when changing an
  92. * already active power rail. When toggling power on, the AXP ramps up
  93. * steeply at 0.0167 V/uS.
  94. */
  95. rc = pmic_bus_read(AXP209_VRC_DCDC2_LDO3, &cfg);
  96. cfg = AXP209_VRC_LDO3_SLOPE_SET(cfg, AXP209_VRC_SLOPE);
  97. rc |= pmic_bus_write(AXP209_VRC_DCDC2_LDO3, cfg);
  98. if (rc)
  99. return rc;
  100. #ifdef CONFIG_AXP_ALDO3_INRUSH_QUIRK
  101. /*
  102. * On some boards, LDO3 has a too big capacitor installed. When
  103. * turning on LDO3, this causes the AXP209 to shutdown on
  104. * voltages over 1.9 volt. As a workaround, we enable LDO3
  105. * first with the lowest possible voltage. If this still causes
  106. * high inrush currents, the voltage slope should be increased.
  107. */
  108. rc = pmic_bus_read(AXP209_OUTPUT_CTRL, &cfg);
  109. if (rc)
  110. return rc;
  111. if (!(cfg & AXP209_OUTPUT_CTRL_LDO3)) {
  112. rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, 0x0); /* 0.7 Volt */
  113. mdelay(1);
  114. rc |= pmic_bus_setbits(AXP209_OUTPUT_CTRL,
  115. AXP209_OUTPUT_CTRL_LDO3);
  116. if (rc)
  117. return rc;
  118. }
  119. #endif
  120. if (mvolt == -1) {
  121. cfg = AXP209_LDO3_VOLTAGE_FROM_LDO3IN;
  122. } else {
  123. cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
  124. cfg = AXP209_LDO3_VOLTAGE_SET(cfg);
  125. }
  126. rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, cfg);
  127. if (rc)
  128. return rc;
  129. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3);
  130. }
  131. int axp_set_aldo4(unsigned int mvolt)
  132. {
  133. int rc;
  134. static const unsigned int vindex[] = {
  135. 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
  136. 2700, 2800, 3000, 3100, 3200, 3300
  137. };
  138. u8 cfg, reg;
  139. if (mvolt == 0)
  140. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  141. AXP209_OUTPUT_CTRL_LDO4);
  142. /* Translate mvolt to register cfg value, requested <= selected */
  143. for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
  144. rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
  145. if (rc)
  146. return rc;
  147. reg |= AXP209_LDO24_LDO4_SET(reg, cfg);
  148. rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
  149. if (rc)
  150. return rc;
  151. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO4);
  152. }
  153. int axp_init(void)
  154. {
  155. u8 ver;
  156. int i, rc;
  157. rc = pmic_bus_init();
  158. if (rc)
  159. return rc;
  160. rc = pmic_bus_read(AXP209_CHIP_VERSION, &ver);
  161. if (rc)
  162. return rc;
  163. if ((ver & AXP209_CHIP_VERSION_MASK) != 0x1)
  164. return -EINVAL;
  165. /* Mask all interrupts */
  166. for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) {
  167. rc = pmic_bus_write(i, 0);
  168. if (rc)
  169. return rc;
  170. }
  171. /*
  172. * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
  173. * from android these are sometimes on.
  174. */
  175. rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
  176. if (rc)
  177. return rc;
  178. rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
  179. if (rc)
  180. return rc;
  181. rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT);
  182. if (rc)
  183. return rc;
  184. return 0;
  185. }
  186. int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  187. {
  188. pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF);
  189. /* infinite loop during shutdown */
  190. while (1) {}
  191. /* not reached */
  192. return 0;
  193. }