twl6030.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2010
  4. * Texas Instruments, <www.ti.com>
  5. */
  6. #include <config.h>
  7. #include <linux/delay.h>
  8. #include <twl6030.h>
  9. static struct twl6030_data *twl;
  10. static struct twl6030_data twl6030_info = {
  11. .chip_type = chip_TWL6030,
  12. .adc_rbase = GPCH0_LSB,
  13. .adc_ctrl = CTRL_P2,
  14. .adc_enable = CTRL_P2_SP2,
  15. .vbat_mult = TWL6030_VBAT_MULT,
  16. .vbat_shift = TWL6030_VBAT_SHIFT,
  17. };
  18. static struct twl6030_data twl6032_info = {
  19. .chip_type = chip_TWL6032,
  20. .adc_rbase = TWL6032_GPCH0_LSB,
  21. .adc_ctrl = TWL6032_CTRL_P1,
  22. .adc_enable = CTRL_P1_SP1,
  23. .vbat_mult = TWL6032_VBAT_MULT,
  24. .vbat_shift = TWL6032_VBAT_SHIFT,
  25. };
  26. static int twl6030_gpadc_read_channel(u8 channel_no)
  27. {
  28. u8 lsb = 0;
  29. u8 msb = 0;
  30. int ret = 0;
  31. ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
  32. twl->adc_rbase + channel_no * 2, &lsb);
  33. if (ret)
  34. return ret;
  35. ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
  36. twl->adc_rbase + 1 + channel_no * 2, &msb);
  37. if (ret)
  38. return ret;
  39. return (msb << 8) | lsb;
  40. }
  41. static int twl6030_gpadc_sw2_trigger(void)
  42. {
  43. u8 val;
  44. int ret = 0;
  45. ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
  46. twl->adc_ctrl, twl->adc_enable);
  47. if (ret)
  48. return ret;
  49. /* Waiting until the SW1 conversion ends*/
  50. val = CTRL_P2_BUSY;
  51. while (!((val & CTRL_P2_EOCP2) && (!(val & CTRL_P2_BUSY)))) {
  52. ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
  53. twl->adc_ctrl, &val);
  54. if (ret)
  55. return ret;
  56. udelay(1000);
  57. }
  58. return 0;
  59. }
  60. void twl6030_power_off(void)
  61. {
  62. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_PHOENIX_DEV_ON,
  63. TWL6030_PHOENIX_APP_DEVOFF | TWL6030_PHOENIX_CON_DEVOFF |
  64. TWL6030_PHOENIX_MOD_DEVOFF);
  65. }
  66. void twl6030_stop_usb_charging(void)
  67. {
  68. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0);
  69. return;
  70. }
  71. void twl6030_start_usb_charging(void)
  72. {
  73. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  74. CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500);
  75. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  76. CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE);
  77. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  78. CONTROLLER_INT_MASK, MBAT_TEMP);
  79. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  80. CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG);
  81. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  82. CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0);
  83. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  84. CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400);
  85. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM);
  86. /* Enable USB charging */
  87. twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
  88. CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER);
  89. return;
  90. }
  91. int twl6030_get_battery_current(void)
  92. {
  93. int battery_current = 0;
  94. u8 msb = 0;
  95. u8 lsb = 0;
  96. twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb);
  97. twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb);
  98. battery_current = ((msb << 8) | lsb);
  99. /* convert 10 bit signed number to 16 bit signed number */
  100. if (battery_current >= 0x2000)
  101. battery_current = (battery_current - 0x4000);
  102. battery_current = battery_current * 3000 / 4096;
  103. printf("Battery Current: %d mA\n", battery_current);
  104. return battery_current;
  105. }
  106. int twl6030_get_battery_voltage(void)
  107. {
  108. int battery_volt = 0;
  109. int ret = 0;
  110. u8 vbatch;
  111. if (twl->chip_type == chip_TWL6030) {
  112. vbatch = TWL6030_GPADC_VBAT_CHNL;
  113. } else {
  114. ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
  115. TWL6032_GPSELECT_ISB,
  116. TWL6032_GPADC_VBAT_CHNL);
  117. if (ret)
  118. return ret;
  119. vbatch = 0;
  120. }
  121. /* Start GPADC SW conversion */
  122. ret = twl6030_gpadc_sw2_trigger();
  123. if (ret) {
  124. printf("Failed to convert battery voltage\n");
  125. return ret;
  126. }
  127. /* measure Vbat voltage */
  128. battery_volt = twl6030_gpadc_read_channel(vbatch);
  129. if (battery_volt < 0) {
  130. printf("Failed to read battery voltage\n");
  131. return ret;
  132. }
  133. battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift;
  134. printf("Battery Voltage: %d mV\n", battery_volt);
  135. return battery_volt;
  136. }
  137. void twl6030_init_battery_charging(void)
  138. {
  139. u8 val = 0;
  140. int battery_volt = 0;
  141. int ret = 0;
  142. ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val);
  143. if (ret) {
  144. puts("twl6030_init_battery_charging(): could not determine chip!\n");
  145. return;
  146. }
  147. if (val == 0x30) {
  148. twl = &twl6030_info;
  149. } else if (val == 0x32) {
  150. twl = &twl6032_info;
  151. } else {
  152. puts("twl6030_init_battery_charging(): unsupported chip type\n");
  153. return;
  154. }
  155. /* Enable VBAT measurement */
  156. if (twl->chip_type == chip_TWL6030) {
  157. twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS);
  158. twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
  159. TWL6030_GPADC_CTRL,
  160. GPADC_CTRL_SCALER_DIV4);
  161. } else {
  162. twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
  163. TWL6032_GPADC_CTRL2,
  164. GPADC_CTRL2_CH18_SCALER_EN);
  165. }
  166. /* Enable GPADC module */
  167. ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS);
  168. if (ret) {
  169. printf("Failed to enable GPADC\n");
  170. return;
  171. }
  172. battery_volt = twl6030_get_battery_voltage();
  173. if (battery_volt < 0)
  174. return;
  175. if (battery_volt < 3000)
  176. printf("Main battery voltage too low!\n");
  177. /* Check for the presence of USB charger */
  178. twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val);
  179. /* check for battery presence indirectly via Fuel gauge */
  180. if ((val & VBUS_DET) && (battery_volt < 3300))
  181. twl6030_start_usb_charging();
  182. return;
  183. }
  184. void twl6030_power_mmc_init(int dev_index)
  185. {
  186. u8 value = 0;
  187. if (dev_index == 0) {
  188. /* 3.0V voltage output for VMMC */
  189. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_VOLTAGE,
  190. TWL6030_CFG_VOLTAGE_30);
  191. /* Enable P1 output for VMMC */
  192. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_STATE,
  193. TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON);
  194. } else if (dev_index == 1) {
  195. twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_PH_STS_BOOT,
  196. &value);
  197. /* BOOT2 indicates 1.8V/2.8V VAUX1 for eMMC */
  198. if (value & TWL6030_PH_STS_BOOT2) {
  199. /* 1.8V voltage output for VAUX1 */
  200. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE,
  201. TWL6030_CFG_VOLTAGE_18);
  202. } else {
  203. /* 2.8V voltage output for VAUX1 */
  204. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE,
  205. TWL6030_CFG_VOLTAGE_28);
  206. }
  207. /* Enable P1 output for VAUX */
  208. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_STATE,
  209. TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON);
  210. }
  211. }
  212. void twl6030_usb_device_settings()
  213. {
  214. u8 value = 0;
  215. /* 3.3V voltage output for VUSB */
  216. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_VOLTAGE,
  217. TWL6030_CFG_VOLTAGE_33);
  218. /* Enable P1 output for VUSB */
  219. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_STATE,
  220. TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON);
  221. /* Select the input supply for VUSB regulator */
  222. twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_MISC2, &value);
  223. value |= TWL6030_MISC2_VUSB_IN_VSYS;
  224. value &= ~TWL6030_MISC2_VUSB_IN_PMID;
  225. twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value);
  226. }
  227. #if CONFIG_IS_ENABLED(DM_I2C)
  228. int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
  229. {
  230. struct udevice *dev;
  231. int ret;
  232. ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
  233. if (ret) {
  234. pr_err("unable to get I2C bus. ret %d\n", ret);
  235. return ret;
  236. }
  237. ret = dm_i2c_reg_write(dev, reg, val);
  238. if (ret) {
  239. pr_err("writing to twl6030 failed. ret %d\n", ret);
  240. return ret;
  241. }
  242. return 0;
  243. }
  244. int twl6030_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp)
  245. {
  246. struct udevice *dev;
  247. int ret;
  248. ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
  249. if (ret) {
  250. pr_err("unable to get I2C bus. ret %d\n", ret);
  251. return ret;
  252. }
  253. ret = dm_i2c_reg_read(dev, reg);
  254. if (ret < 0) {
  255. pr_err("reading from twl6030 failed. ret %d\n", ret);
  256. return ret;
  257. }
  258. *valp = (u8)ret;
  259. return 0;
  260. }
  261. #endif