da9052-regulator.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. * da9052-regulator.c: Regulator driver for DA9052
  3. *
  4. * Copyright(c) 2011 Dialog Semiconductor Ltd.
  5. *
  6. * Author: David Dajun Chen <dchen@diasemi.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. */
  14. #include <linux/module.h>
  15. #include <linux/moduleparam.h>
  16. #include <linux/init.h>
  17. #include <linux/err.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/regulator/driver.h>
  20. #include <linux/regulator/machine.h>
  21. #include <linux/mfd/da9052/da9052.h>
  22. #include <linux/mfd/da9052/reg.h>
  23. #include <linux/mfd/da9052/pdata.h>
  24. /* Buck step size */
  25. #define DA9052_BUCK_PERI_3uV_STEP 100000
  26. #define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24
  27. #define DA9052_CONST_3uV 3000000
  28. #define DA9052_MIN_UA 0
  29. #define DA9052_MAX_UA 3
  30. #define DA9052_CURRENT_RANGE 4
  31. /* Bit masks */
  32. #define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
  33. #define DA9052_BUCK_ILIM_MASK_ODD 0xc0
  34. /* DA9052 REGULATOR IDs */
  35. #define DA9052_ID_BUCK1 0
  36. #define DA9052_ID_BUCK2 1
  37. #define DA9052_ID_BUCK3 2
  38. #define DA9052_ID_BUCK4 3
  39. #define DA9052_ID_LDO1 4
  40. #define DA9052_ID_LDO2 5
  41. #define DA9052_ID_LDO3 6
  42. #define DA9052_ID_LDO4 7
  43. #define DA9052_ID_LDO5 8
  44. #define DA9052_ID_LDO6 9
  45. #define DA9052_ID_LDO7 10
  46. #define DA9052_ID_LDO8 11
  47. #define DA9052_ID_LDO9 12
  48. #define DA9052_ID_LDO10 13
  49. static const u32 da9052_current_limits[3][4] = {
  50. {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
  51. {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
  52. {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
  53. * BUCK-MEM and BUCK-PERI
  54. */
  55. };
  56. struct da9052_regulator_info {
  57. struct regulator_desc reg_desc;
  58. int step_uV;
  59. int min_uV;
  60. int max_uV;
  61. unsigned char volt_shift;
  62. unsigned char en_bit;
  63. unsigned char activate_bit;
  64. };
  65. struct da9052_regulator {
  66. struct da9052 *da9052;
  67. struct da9052_regulator_info *info;
  68. struct regulator_dev *rdev;
  69. };
  70. static int verify_range(struct da9052_regulator_info *info,
  71. int min_uV, int max_uV)
  72. {
  73. if (min_uV > info->max_uV || max_uV < info->min_uV)
  74. return -EINVAL;
  75. return 0;
  76. }
  77. static int da9052_regulator_enable(struct regulator_dev *rdev)
  78. {
  79. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  80. struct da9052_regulator_info *info = regulator->info;
  81. int offset = rdev_get_id(rdev);
  82. return da9052_reg_update(regulator->da9052,
  83. DA9052_BUCKCORE_REG + offset,
  84. 1 << info->en_bit, 1 << info->en_bit);
  85. }
  86. static int da9052_regulator_disable(struct regulator_dev *rdev)
  87. {
  88. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  89. struct da9052_regulator_info *info = regulator->info;
  90. int offset = rdev_get_id(rdev);
  91. return da9052_reg_update(regulator->da9052,
  92. DA9052_BUCKCORE_REG + offset,
  93. 1 << info->en_bit, 0);
  94. }
  95. static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
  96. {
  97. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  98. struct da9052_regulator_info *info = regulator->info;
  99. int offset = rdev_get_id(rdev);
  100. int ret;
  101. ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
  102. if (ret < 0)
  103. return ret;
  104. return ret & (1 << info->en_bit);
  105. }
  106. static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
  107. {
  108. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  109. int offset = rdev_get_id(rdev);
  110. int ret, row = 2;
  111. ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
  112. if (ret < 0)
  113. return ret;
  114. /* Determine the even or odd position of the buck current limit
  115. * register field
  116. */
  117. if (offset % 2 == 0)
  118. ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
  119. else
  120. ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
  121. /* Select the appropriate current limit range */
  122. if (regulator->da9052->chip_id == DA9052)
  123. row = 0;
  124. else if (offset == 0)
  125. row = 1;
  126. return da9052_current_limits[row][ret];
  127. }
  128. static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
  129. int max_uA)
  130. {
  131. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  132. int offset = rdev_get_id(rdev);
  133. int reg_val = 0;
  134. int i, row = 2;
  135. /* Select the appropriate current limit range */
  136. if (regulator->da9052->chip_id == DA9052)
  137. row = 0;
  138. else if (offset == 0)
  139. row = 1;
  140. if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
  141. max_uA < da9052_current_limits[row][DA9052_MIN_UA])
  142. return -EINVAL;
  143. for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
  144. if (min_uA <= da9052_current_limits[row][i]) {
  145. reg_val = i;
  146. break;
  147. }
  148. }
  149. /* Determine the even or odd position of the buck current limit
  150. * register field
  151. */
  152. if (offset % 2 == 0)
  153. return da9052_reg_update(regulator->da9052,
  154. DA9052_BUCKA_REG + offset/2,
  155. DA9052_BUCK_ILIM_MASK_EVEN,
  156. reg_val << 2);
  157. else
  158. return da9052_reg_update(regulator->da9052,
  159. DA9052_BUCKA_REG + offset/2,
  160. DA9052_BUCK_ILIM_MASK_ODD,
  161. reg_val << 6);
  162. }
  163. static int da9052_list_voltage(struct regulator_dev *rdev,
  164. unsigned int selector)
  165. {
  166. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  167. struct da9052_regulator_info *info = regulator->info;
  168. int id = rdev_get_id(rdev);
  169. int volt_uV;
  170. if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
  171. && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
  172. volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
  173. + info->min_uV);
  174. volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
  175. * (DA9052_BUCK_PERI_3uV_STEP);
  176. } else {
  177. volt_uV = (selector * info->step_uV) + info->min_uV;
  178. }
  179. if (volt_uV > info->max_uV)
  180. return -EINVAL;
  181. return volt_uV;
  182. }
  183. static int da9052_regulator_set_voltage(struct regulator_dev *rdev,
  184. int min_uV, int max_uV,
  185. unsigned int *selector)
  186. {
  187. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  188. struct da9052_regulator_info *info = regulator->info;
  189. int id = rdev_get_id(rdev);
  190. int ret;
  191. ret = verify_range(info, min_uV, max_uV);
  192. if (ret < 0)
  193. return ret;
  194. if (min_uV < info->min_uV)
  195. min_uV = info->min_uV;
  196. if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
  197. && (min_uV >= DA9052_CONST_3uV)) {
  198. *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
  199. DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
  200. DA9052_BUCK_PERI_3uV_STEP);
  201. } else {
  202. *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
  203. }
  204. ret = da9052_list_voltage(rdev, *selector);
  205. if (ret < 0)
  206. return ret;
  207. ret = da9052_reg_update(regulator->da9052,
  208. DA9052_BUCKCORE_REG + id,
  209. (1 << info->volt_shift) - 1, *selector);
  210. if (ret < 0)
  211. return ret;
  212. /* Some LDOs and DCDCs are DVC controlled which requires enabling of
  213. * the activate bit to implment the changes on the output.
  214. */
  215. switch (id) {
  216. case DA9052_ID_BUCK1:
  217. case DA9052_ID_BUCK2:
  218. case DA9052_ID_BUCK3:
  219. case DA9052_ID_LDO2:
  220. case DA9052_ID_LDO3:
  221. ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
  222. info->activate_bit, info->activate_bit);
  223. break;
  224. }
  225. return ret;
  226. }
  227. static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
  228. {
  229. struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
  230. struct da9052_regulator_info *info = regulator->info;
  231. int offset = rdev_get_id(rdev);
  232. int ret;
  233. ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
  234. if (ret < 0)
  235. return ret;
  236. ret &= ((1 << info->volt_shift) - 1);
  237. return ret;
  238. }
  239. static struct regulator_ops da9052_dcdc_ops = {
  240. .set_voltage = da9052_regulator_set_voltage,
  241. .get_current_limit = da9052_dcdc_get_current_limit,
  242. .set_current_limit = da9052_dcdc_set_current_limit,
  243. .list_voltage = da9052_list_voltage,
  244. .get_voltage_sel = da9052_get_regulator_voltage_sel,
  245. .is_enabled = da9052_regulator_is_enabled,
  246. .enable = da9052_regulator_enable,
  247. .disable = da9052_regulator_disable,
  248. };
  249. static struct regulator_ops da9052_ldo_ops = {
  250. .set_voltage = da9052_regulator_set_voltage,
  251. .list_voltage = da9052_list_voltage,
  252. .get_voltage_sel = da9052_get_regulator_voltage_sel,
  253. .is_enabled = da9052_regulator_is_enabled,
  254. .enable = da9052_regulator_enable,
  255. .disable = da9052_regulator_disable,
  256. };
  257. #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
  258. {\
  259. .reg_desc = {\
  260. .name = #_id,\
  261. .ops = &da9052_ldo_ops,\
  262. .type = REGULATOR_VOLTAGE,\
  263. .id = DA9052_ID_##_id,\
  264. .n_voltages = (max - min) / step + 1, \
  265. .owner = THIS_MODULE,\
  266. },\
  267. .min_uV = (min) * 1000,\
  268. .max_uV = (max) * 1000,\
  269. .step_uV = (step) * 1000,\
  270. .volt_shift = (sbits),\
  271. .en_bit = (ebits),\
  272. .activate_bit = (abits),\
  273. }
  274. #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
  275. {\
  276. .reg_desc = {\
  277. .name = #_id,\
  278. .ops = &da9052_dcdc_ops,\
  279. .type = REGULATOR_VOLTAGE,\
  280. .id = DA9052_ID_##_id,\
  281. .n_voltages = (max - min) / step + 1, \
  282. .owner = THIS_MODULE,\
  283. },\
  284. .min_uV = (min) * 1000,\
  285. .max_uV = (max) * 1000,\
  286. .step_uV = (step) * 1000,\
  287. .volt_shift = (sbits),\
  288. .en_bit = (ebits),\
  289. .activate_bit = (abits),\
  290. }
  291. static struct da9052_regulator_info da9052_regulator_info[] = {
  292. DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
  293. DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
  294. DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
  295. DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0),
  296. DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
  297. DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
  298. DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
  299. DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
  300. DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
  301. DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
  302. DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
  303. DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
  304. DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
  305. DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
  306. };
  307. static struct da9052_regulator_info da9053_regulator_info[] = {
  308. DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
  309. DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
  310. DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
  311. DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0),
  312. DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
  313. DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
  314. DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
  315. DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
  316. DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
  317. DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
  318. DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
  319. DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
  320. DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
  321. DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
  322. };
  323. static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
  324. int id)
  325. {
  326. struct da9052_regulator_info *info;
  327. int i;
  328. switch (chip_id) {
  329. case DA9052:
  330. for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
  331. info = &da9052_regulator_info[i];
  332. if (info->reg_desc.id == id)
  333. return info;
  334. }
  335. break;
  336. case DA9053_AA:
  337. case DA9053_BA:
  338. case DA9053_BB:
  339. for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
  340. info = &da9053_regulator_info[i];
  341. if (info->reg_desc.id == id)
  342. return info;
  343. }
  344. break;
  345. }
  346. return NULL;
  347. }
  348. static int __devinit da9052_regulator_probe(struct platform_device *pdev)
  349. {
  350. struct da9052_regulator *regulator;
  351. struct da9052 *da9052;
  352. struct da9052_pdata *pdata;
  353. int ret;
  354. regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
  355. GFP_KERNEL);
  356. if (!regulator)
  357. return -ENOMEM;
  358. da9052 = dev_get_drvdata(pdev->dev.parent);
  359. pdata = da9052->dev->platform_data;
  360. regulator->da9052 = da9052;
  361. regulator->info = find_regulator_info(regulator->da9052->chip_id,
  362. pdev->id);
  363. if (regulator->info == NULL) {
  364. dev_err(&pdev->dev, "invalid regulator ID specified\n");
  365. ret = -EINVAL;
  366. goto err;
  367. }
  368. regulator->rdev = regulator_register(&regulator->info->reg_desc,
  369. &pdev->dev,
  370. pdata->regulators[pdev->id],
  371. regulator, NULL);
  372. if (IS_ERR(regulator->rdev)) {
  373. dev_err(&pdev->dev, "failed to register regulator %s\n",
  374. regulator->info->reg_desc.name);
  375. ret = PTR_ERR(regulator->rdev);
  376. goto err;
  377. }
  378. platform_set_drvdata(pdev, regulator);
  379. return 0;
  380. err:
  381. devm_kfree(&pdev->dev, regulator);
  382. return ret;
  383. }
  384. static int __devexit da9052_regulator_remove(struct platform_device *pdev)
  385. {
  386. struct da9052_regulator *regulator = platform_get_drvdata(pdev);
  387. regulator_unregister(regulator->rdev);
  388. devm_kfree(&pdev->dev, regulator);
  389. return 0;
  390. }
  391. static struct platform_driver da9052_regulator_driver = {
  392. .probe = da9052_regulator_probe,
  393. .remove = __devexit_p(da9052_regulator_remove),
  394. .driver = {
  395. .name = "da9052-regulator",
  396. .owner = THIS_MODULE,
  397. },
  398. };
  399. static int __init da9052_regulator_init(void)
  400. {
  401. return platform_driver_register(&da9052_regulator_driver);
  402. }
  403. subsys_initcall(da9052_regulator_init);
  404. static void __exit da9052_regulator_exit(void)
  405. {
  406. platform_driver_unregister(&da9052_regulator_driver);
  407. }
  408. module_exit(da9052_regulator_exit);
  409. MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
  410. MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
  411. MODULE_LICENSE("GPL");
  412. MODULE_ALIAS("platform:da9052-regulator");