wm8400-regulator.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Regulator support for WM8400
  3. *
  4. * Copyright 2008 Wolfson Microelectronics PLC.
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of the
  11. * License, or (at your option) any later version.
  12. *
  13. */
  14. #include <linux/bug.h>
  15. #include <linux/err.h>
  16. #include <linux/kernel.h>
  17. #include <linux/regulator/driver.h>
  18. #include <linux/mfd/wm8400-private.h>
  19. static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
  20. {
  21. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  22. u16 val;
  23. val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
  24. return (val & WM8400_LDO1_ENA) != 0;
  25. }
  26. static int wm8400_ldo_enable(struct regulator_dev *dev)
  27. {
  28. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  29. return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
  30. WM8400_LDO1_ENA, WM8400_LDO1_ENA);
  31. }
  32. static int wm8400_ldo_disable(struct regulator_dev *dev)
  33. {
  34. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  35. return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
  36. WM8400_LDO1_ENA, 0);
  37. }
  38. static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
  39. {
  40. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  41. u16 val;
  42. val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
  43. val &= WM8400_LDO1_VSEL_MASK;
  44. if (val < 15)
  45. return 900000 + (val * 50000);
  46. else
  47. return 1600000 + ((val - 14) * 100000);
  48. }
  49. static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
  50. int min_uV, int max_uV)
  51. {
  52. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  53. u16 val;
  54. if (min_uV < 900000 || min_uV > 3300000)
  55. return -EINVAL;
  56. if (min_uV < 1700000) {
  57. /* Steps of 50mV from 900mV; */
  58. val = (min_uV - 850001) / 50000;
  59. if ((val * 50000) + 900000 > max_uV)
  60. return -EINVAL;
  61. BUG_ON((val * 50000) + 900000 < min_uV);
  62. } else {
  63. /* Steps of 100mV from 1700mV */
  64. val = ((min_uV - 1600001) / 100000);
  65. if ((val * 100000) + 1700000 > max_uV)
  66. return -EINVAL;
  67. BUG_ON((val * 100000) + 1700000 < min_uV);
  68. val += 0xf;
  69. }
  70. return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
  71. WM8400_LDO1_VSEL_MASK, val);
  72. }
  73. static struct regulator_ops wm8400_ldo_ops = {
  74. .is_enabled = wm8400_ldo_is_enabled,
  75. .enable = wm8400_ldo_enable,
  76. .disable = wm8400_ldo_disable,
  77. .get_voltage = wm8400_ldo_get_voltage,
  78. .set_voltage = wm8400_ldo_set_voltage,
  79. };
  80. static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
  81. {
  82. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  83. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  84. u16 val;
  85. val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
  86. return (val & WM8400_DC1_ENA) != 0;
  87. }
  88. static int wm8400_dcdc_enable(struct regulator_dev *dev)
  89. {
  90. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  91. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  92. return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  93. WM8400_DC1_ENA, WM8400_DC1_ENA);
  94. }
  95. static int wm8400_dcdc_disable(struct regulator_dev *dev)
  96. {
  97. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  98. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  99. return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  100. WM8400_DC1_ENA, 0);
  101. }
  102. static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
  103. {
  104. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  105. u16 val;
  106. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  107. val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
  108. val &= WM8400_DC1_VSEL_MASK;
  109. return 850000 + (25000 * val);
  110. }
  111. static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
  112. int min_uV, int max_uV)
  113. {
  114. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  115. u16 val;
  116. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  117. if (min_uV < 850000)
  118. return -EINVAL;
  119. val = (min_uV - 825001) / 25000;
  120. if (850000 + (25000 * val) > max_uV)
  121. return -EINVAL;
  122. BUG_ON(850000 + (25000 * val) < min_uV);
  123. return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  124. WM8400_DC1_VSEL_MASK, val);
  125. }
  126. static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
  127. {
  128. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  129. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  130. u16 data[2];
  131. int ret;
  132. ret = wm8400_block_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 2,
  133. data);
  134. if (ret != 0)
  135. return 0;
  136. /* Datasheet: hibernate */
  137. if (data[0] & WM8400_DC1_SLEEP)
  138. return REGULATOR_MODE_STANDBY;
  139. /* Datasheet: standby */
  140. if (!(data[0] & WM8400_DC1_ACTIVE))
  141. return REGULATOR_MODE_IDLE;
  142. /* Datasheet: active with or without force PWM */
  143. if (data[1] & WM8400_DC1_FRC_PWM)
  144. return REGULATOR_MODE_FAST;
  145. else
  146. return REGULATOR_MODE_NORMAL;
  147. }
  148. static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
  149. {
  150. struct wm8400 *wm8400 = rdev_get_drvdata(dev);
  151. int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  152. int ret;
  153. switch (mode) {
  154. case REGULATOR_MODE_FAST:
  155. /* Datasheet: active with force PWM */
  156. ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
  157. WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
  158. if (ret != 0)
  159. return ret;
  160. return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  161. WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
  162. WM8400_DC1_ACTIVE);
  163. case REGULATOR_MODE_NORMAL:
  164. /* Datasheet: active */
  165. ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
  166. WM8400_DC1_FRC_PWM, 0);
  167. if (ret != 0)
  168. return ret;
  169. return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  170. WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
  171. WM8400_DC1_ACTIVE);
  172. case REGULATOR_MODE_IDLE:
  173. /* Datasheet: standby */
  174. ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  175. WM8400_DC1_ACTIVE, 0);
  176. if (ret != 0)
  177. return ret;
  178. return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
  179. WM8400_DC1_SLEEP, 0);
  180. default:
  181. return -EINVAL;
  182. }
  183. }
  184. static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
  185. int input_uV, int output_uV,
  186. int load_uA)
  187. {
  188. return REGULATOR_MODE_NORMAL;
  189. }
  190. static struct regulator_ops wm8400_dcdc_ops = {
  191. .is_enabled = wm8400_dcdc_is_enabled,
  192. .enable = wm8400_dcdc_enable,
  193. .disable = wm8400_dcdc_disable,
  194. .get_voltage = wm8400_dcdc_get_voltage,
  195. .set_voltage = wm8400_dcdc_set_voltage,
  196. .get_mode = wm8400_dcdc_get_mode,
  197. .set_mode = wm8400_dcdc_set_mode,
  198. .get_optimum_mode = wm8400_dcdc_get_optimum_mode,
  199. };
  200. static struct regulator_desc regulators[] = {
  201. {
  202. .name = "LDO1",
  203. .id = WM8400_LDO1,
  204. .ops = &wm8400_ldo_ops,
  205. .type = REGULATOR_VOLTAGE,
  206. .owner = THIS_MODULE,
  207. },
  208. {
  209. .name = "LDO2",
  210. .id = WM8400_LDO2,
  211. .ops = &wm8400_ldo_ops,
  212. .type = REGULATOR_VOLTAGE,
  213. .owner = THIS_MODULE,
  214. },
  215. {
  216. .name = "LDO3",
  217. .id = WM8400_LDO3,
  218. .ops = &wm8400_ldo_ops,
  219. .type = REGULATOR_VOLTAGE,
  220. .owner = THIS_MODULE,
  221. },
  222. {
  223. .name = "LDO4",
  224. .id = WM8400_LDO4,
  225. .ops = &wm8400_ldo_ops,
  226. .type = REGULATOR_VOLTAGE,
  227. .owner = THIS_MODULE,
  228. },
  229. {
  230. .name = "DCDC1",
  231. .id = WM8400_DCDC1,
  232. .ops = &wm8400_dcdc_ops,
  233. .type = REGULATOR_VOLTAGE,
  234. .owner = THIS_MODULE,
  235. },
  236. {
  237. .name = "DCDC2",
  238. .id = WM8400_DCDC2,
  239. .ops = &wm8400_dcdc_ops,
  240. .type = REGULATOR_VOLTAGE,
  241. .owner = THIS_MODULE,
  242. },
  243. };
  244. static int __init wm8400_regulator_probe(struct platform_device *pdev)
  245. {
  246. struct regulator_dev *rdev;
  247. rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
  248. pdev->dev.driver_data);
  249. if (IS_ERR(rdev))
  250. return PTR_ERR(rdev);
  251. return 0;
  252. }
  253. static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
  254. {
  255. struct regulator_dev *rdev = platform_get_drvdata(pdev);
  256. regulator_unregister(rdev);
  257. return 0;
  258. }
  259. static struct platform_driver wm8400_regulator_driver = {
  260. .driver = {
  261. .name = "wm8400-regulator",
  262. },
  263. .probe = wm8400_regulator_probe,
  264. .remove = __devexit_p(wm8400_regulator_remove),
  265. };
  266. /**
  267. * wm8400_register_regulator - enable software control of a WM8400 regulator
  268. *
  269. * This function enables software control of a WM8400 regulator via
  270. * the regulator API. It is intended to be called from the
  271. * platform_init() callback of the WM8400 MFD driver.
  272. *
  273. * @param dev The WM8400 device to operate on.
  274. * @param reg The regulator to control.
  275. * @param initdata Regulator initdata for the regulator.
  276. */
  277. int wm8400_register_regulator(struct device *dev, int reg,
  278. struct regulator_init_data *initdata)
  279. {
  280. struct wm8400 *wm8400 = dev->driver_data;
  281. if (wm8400->regulators[reg].name)
  282. return -EBUSY;
  283. initdata->driver_data = wm8400;
  284. wm8400->regulators[reg].name = "wm8400-regulator";
  285. wm8400->regulators[reg].id = reg;
  286. wm8400->regulators[reg].dev.parent = dev;
  287. wm8400->regulators[reg].dev.driver_data = wm8400;
  288. wm8400->regulators[reg].dev.platform_data = initdata;
  289. return platform_device_register(&wm8400->regulators[reg]);
  290. }
  291. EXPORT_SYMBOL_GPL(wm8400_register_regulator);
  292. static int __init wm8400_regulator_init(void)
  293. {
  294. return platform_driver_register(&wm8400_regulator_driver);
  295. }
  296. module_init(wm8400_regulator_init);
  297. static void __exit wm8400_regulator_exit(void)
  298. {
  299. platform_driver_unregister(&wm8400_regulator_driver);
  300. }
  301. module_exit(wm8400_regulator_exit);
  302. MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  303. MODULE_DESCRIPTION("WM8400 regulator driver");
  304. MODULE_LICENSE("GPL");
  305. MODULE_ALIAS("platform:wm8400-regulator");