hi6421-regulator.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Device driver for regulators in Hi6421 IC
  4. //
  5. // Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
  6. // http://www.hisilicon.com
  7. // Copyright (c) <2013-2014> Linaro Ltd.
  8. // http://www.linaro.org
  9. //
  10. // Author: Guodong Xu <guodong.xu@linaro.org>
  11. #include <linux/slab.h>
  12. #include <linux/device.h>
  13. #include <linux/module.h>
  14. #include <linux/err.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/of.h>
  17. #include <linux/regmap.h>
  18. #include <linux/regulator/driver.h>
  19. #include <linux/regulator/machine.h>
  20. #include <linux/regulator/of_regulator.h>
  21. #include <linux/mfd/hi6421-pmic.h>
  22. /*
  23. * struct hi6421_regulator_pdata - Hi6421 regulator data of platform device
  24. * @lock: mutex to serialize regulator enable
  25. */
  26. struct hi6421_regulator_pdata {
  27. struct mutex lock;
  28. };
  29. /*
  30. * struct hi6421_regulator_info - hi6421 regulator information
  31. * @desc: regulator description
  32. * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
  33. * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
  34. */
  35. struct hi6421_regulator_info {
  36. struct regulator_desc desc;
  37. u8 mode_mask;
  38. u32 eco_microamp;
  39. };
  40. /* HI6421 regulators */
  41. enum hi6421_regulator_id {
  42. HI6421_LDO0,
  43. HI6421_LDO1,
  44. HI6421_LDO2,
  45. HI6421_LDO3,
  46. HI6421_LDO4,
  47. HI6421_LDO5,
  48. HI6421_LDO6,
  49. HI6421_LDO7,
  50. HI6421_LDO8,
  51. HI6421_LDO9,
  52. HI6421_LDO10,
  53. HI6421_LDO11,
  54. HI6421_LDO12,
  55. HI6421_LDO13,
  56. HI6421_LDO14,
  57. HI6421_LDO15,
  58. HI6421_LDO16,
  59. HI6421_LDO17,
  60. HI6421_LDO18,
  61. HI6421_LDO19,
  62. HI6421_LDO20,
  63. HI6421_LDOAUDIO,
  64. HI6421_BUCK0,
  65. HI6421_BUCK1,
  66. HI6421_BUCK2,
  67. HI6421_BUCK3,
  68. HI6421_BUCK4,
  69. HI6421_BUCK5,
  70. HI6421_NUM_REGULATORS,
  71. };
  72. /* LDO 0, 4~7, 9~14, 16~20 have same voltage table. */
  73. static const unsigned int ldo_0_voltages[] = {
  74. 1500000, 1800000, 2400000, 2500000,
  75. 2600000, 2700000, 2850000, 3000000,
  76. };
  77. /* LDO 8, 15 have same voltage table. */
  78. static const unsigned int ldo_8_voltages[] = {
  79. 1500000, 1800000, 2400000, 2600000,
  80. 2700000, 2850000, 3000000, 3300000,
  81. };
  82. /* Ranges are sorted in ascending order. */
  83. static const struct regulator_linear_range ldo_audio_volt_range[] = {
  84. REGULATOR_LINEAR_RANGE(2800000, 0, 3, 50000),
  85. REGULATOR_LINEAR_RANGE(3000000, 4, 7, 100000),
  86. };
  87. static const unsigned int buck_3_voltages[] = {
  88. 950000, 1050000, 1100000, 1117000,
  89. 1134000, 1150000, 1167000, 1200000,
  90. };
  91. static const unsigned int buck_4_voltages[] = {
  92. 1150000, 1200000, 1250000, 1350000,
  93. 1700000, 1800000, 1900000, 2000000,
  94. };
  95. static const unsigned int buck_5_voltages[] = {
  96. 1150000, 1200000, 1250000, 1350000,
  97. 1600000, 1700000, 1800000, 1900000,
  98. };
  99. static const struct regulator_ops hi6421_ldo_ops;
  100. static const struct regulator_ops hi6421_ldo_linear_ops;
  101. static const struct regulator_ops hi6421_ldo_linear_range_ops;
  102. static const struct regulator_ops hi6421_buck012_ops;
  103. static const struct regulator_ops hi6421_buck345_ops;
  104. #define HI6421_LDO_ENABLE_TIME (350)
  105. /*
  106. * _id - LDO id name string
  107. * _match - of match name string
  108. * v_table - voltage table
  109. * vreg - voltage select register
  110. * vmask - voltage select mask
  111. * ereg - enable register
  112. * emask - enable mask
  113. * odelay - off/on delay time in uS
  114. * ecomask - eco mode mask
  115. * ecoamp - eco mode load uppler limit in uA
  116. */
  117. #define HI6421_LDO(_id, _match, v_table, vreg, vmask, ereg, emask, \
  118. odelay, ecomask, ecoamp) \
  119. [HI6421_##_id] = { \
  120. .desc = { \
  121. .name = #_id, \
  122. .of_match = of_match_ptr(#_match), \
  123. .regulators_node = of_match_ptr("regulators"), \
  124. .ops = &hi6421_ldo_ops, \
  125. .type = REGULATOR_VOLTAGE, \
  126. .id = HI6421_##_id, \
  127. .owner = THIS_MODULE, \
  128. .n_voltages = ARRAY_SIZE(v_table), \
  129. .volt_table = v_table, \
  130. .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
  131. .vsel_mask = vmask, \
  132. .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
  133. .enable_mask = emask, \
  134. .enable_time = HI6421_LDO_ENABLE_TIME, \
  135. .off_on_delay = odelay, \
  136. }, \
  137. .mode_mask = ecomask, \
  138. .eco_microamp = ecoamp, \
  139. }
  140. /* HI6421 LDO1~3 are linear voltage regulators at fixed uV_step
  141. *
  142. * _id - LDO id name string
  143. * _match - of match name string
  144. * _min_uV - minimum voltage supported in uV
  145. * n_volt - number of votages available
  146. * vstep - voltage increase in each linear step in uV
  147. * vreg - voltage select register
  148. * vmask - voltage select mask
  149. * ereg - enable register
  150. * emask - enable mask
  151. * odelay - off/on delay time in uS
  152. * ecomask - eco mode mask
  153. * ecoamp - eco mode load uppler limit in uA
  154. */
  155. #define HI6421_LDO_LINEAR(_id, _match, _min_uV, n_volt, vstep, vreg, vmask,\
  156. ereg, emask, odelay, ecomask, ecoamp) \
  157. [HI6421_##_id] = { \
  158. .desc = { \
  159. .name = #_id, \
  160. .of_match = of_match_ptr(#_match), \
  161. .regulators_node = of_match_ptr("regulators"), \
  162. .ops = &hi6421_ldo_linear_ops, \
  163. .type = REGULATOR_VOLTAGE, \
  164. .id = HI6421_##_id, \
  165. .owner = THIS_MODULE, \
  166. .min_uV = _min_uV, \
  167. .n_voltages = n_volt, \
  168. .uV_step = vstep, \
  169. .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
  170. .vsel_mask = vmask, \
  171. .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
  172. .enable_mask = emask, \
  173. .enable_time = HI6421_LDO_ENABLE_TIME, \
  174. .off_on_delay = odelay, \
  175. }, \
  176. .mode_mask = ecomask, \
  177. .eco_microamp = ecoamp, \
  178. }
  179. /* HI6421 LDOAUDIO is a linear voltage regulator with two 4-step ranges
  180. *
  181. * _id - LDO id name string
  182. * _match - of match name string
  183. * n_volt - number of votages available
  184. * volt_ranges - array of regulator_linear_range
  185. * vstep - voltage increase in each linear step in uV
  186. * vreg - voltage select register
  187. * vmask - voltage select mask
  188. * ereg - enable register
  189. * emask - enable mask
  190. * odelay - off/on delay time in uS
  191. * ecomask - eco mode mask
  192. * ecoamp - eco mode load uppler limit in uA
  193. */
  194. #define HI6421_LDO_LINEAR_RANGE(_id, _match, n_volt, volt_ranges, vreg, vmask,\
  195. ereg, emask, odelay, ecomask, ecoamp) \
  196. [HI6421_##_id] = { \
  197. .desc = { \
  198. .name = #_id, \
  199. .of_match = of_match_ptr(#_match), \
  200. .regulators_node = of_match_ptr("regulators"), \
  201. .ops = &hi6421_ldo_linear_range_ops, \
  202. .type = REGULATOR_VOLTAGE, \
  203. .id = HI6421_##_id, \
  204. .owner = THIS_MODULE, \
  205. .n_voltages = n_volt, \
  206. .linear_ranges = volt_ranges, \
  207. .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
  208. .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
  209. .vsel_mask = vmask, \
  210. .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
  211. .enable_mask = emask, \
  212. .enable_time = HI6421_LDO_ENABLE_TIME, \
  213. .off_on_delay = odelay, \
  214. }, \
  215. .mode_mask = ecomask, \
  216. .eco_microamp = ecoamp, \
  217. }
  218. /* HI6421 BUCK0/1/2 are linear voltage regulators at fixed uV_step
  219. *
  220. * _id - BUCK0/1/2 id name string
  221. * _match - of match name string
  222. * vreg - voltage select register
  223. * vmask - voltage select mask
  224. * ereg - enable register
  225. * emask - enable mask
  226. * sleepmask - mask of sleep mode
  227. * etime - enable time
  228. * odelay - off/on delay time in uS
  229. */
  230. #define HI6421_BUCK012(_id, _match, vreg, vmask, ereg, emask, sleepmask,\
  231. etime, odelay) \
  232. [HI6421_##_id] = { \
  233. .desc = { \
  234. .name = #_id, \
  235. .of_match = of_match_ptr(#_match), \
  236. .regulators_node = of_match_ptr("regulators"), \
  237. .ops = &hi6421_buck012_ops, \
  238. .type = REGULATOR_VOLTAGE, \
  239. .id = HI6421_##_id, \
  240. .owner = THIS_MODULE, \
  241. .min_uV = 700000, \
  242. .n_voltages = 128, \
  243. .uV_step = 7086, \
  244. .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
  245. .vsel_mask = vmask, \
  246. .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
  247. .enable_mask = emask, \
  248. .enable_time = etime, \
  249. .off_on_delay = odelay, \
  250. }, \
  251. .mode_mask = sleepmask, \
  252. }
  253. /* HI6421 BUCK3/4/5 share similar configurations as LDOs, with exception
  254. * that it supports SLEEP mode, so has different .ops.
  255. *
  256. * _id - LDO id name string
  257. * _match - of match name string
  258. * v_table - voltage table
  259. * vreg - voltage select register
  260. * vmask - voltage select mask
  261. * ereg - enable register
  262. * emask - enable mask
  263. * odelay - off/on delay time in uS
  264. * sleepmask - mask of sleep mode
  265. */
  266. #define HI6421_BUCK345(_id, _match, v_table, vreg, vmask, ereg, emask, \
  267. odelay, sleepmask) \
  268. [HI6421_##_id] = { \
  269. .desc = { \
  270. .name = #_id, \
  271. .of_match = of_match_ptr(#_match), \
  272. .regulators_node = of_match_ptr("regulators"), \
  273. .ops = &hi6421_buck345_ops, \
  274. .type = REGULATOR_VOLTAGE, \
  275. .id = HI6421_##_id, \
  276. .owner = THIS_MODULE, \
  277. .n_voltages = ARRAY_SIZE(v_table), \
  278. .volt_table = v_table, \
  279. .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
  280. .vsel_mask = vmask, \
  281. .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
  282. .enable_mask = emask, \
  283. .enable_time = HI6421_LDO_ENABLE_TIME, \
  284. .off_on_delay = odelay, \
  285. }, \
  286. .mode_mask = sleepmask, \
  287. }
  288. /* HI6421 regulator information */
  289. static struct hi6421_regulator_info
  290. hi6421_regulator_info[HI6421_NUM_REGULATORS] = {
  291. HI6421_LDO(LDO0, hi6421_vout0, ldo_0_voltages, 0x20, 0x07, 0x20, 0x10,
  292. 10000, 0x20, 8000),
  293. HI6421_LDO_LINEAR(LDO1, hi6421_vout1, 1700000, 4, 100000, 0x21, 0x03,
  294. 0x21, 0x10, 10000, 0x20, 5000),
  295. HI6421_LDO_LINEAR(LDO2, hi6421_vout2, 1050000, 8, 50000, 0x22, 0x07,
  296. 0x22, 0x10, 20000, 0x20, 8000),
  297. HI6421_LDO_LINEAR(LDO3, hi6421_vout3, 1050000, 8, 50000, 0x23, 0x07,
  298. 0x23, 0x10, 20000, 0x20, 8000),
  299. HI6421_LDO(LDO4, hi6421_vout4, ldo_0_voltages, 0x24, 0x07, 0x24, 0x10,
  300. 20000, 0x20, 8000),
  301. HI6421_LDO(LDO5, hi6421_vout5, ldo_0_voltages, 0x25, 0x07, 0x25, 0x10,
  302. 20000, 0x20, 8000),
  303. HI6421_LDO(LDO6, hi6421_vout6, ldo_0_voltages, 0x26, 0x07, 0x26, 0x10,
  304. 20000, 0x20, 8000),
  305. HI6421_LDO(LDO7, hi6421_vout7, ldo_0_voltages, 0x27, 0x07, 0x27, 0x10,
  306. 20000, 0x20, 5000),
  307. HI6421_LDO(LDO8, hi6421_vout8, ldo_8_voltages, 0x28, 0x07, 0x28, 0x10,
  308. 20000, 0x20, 8000),
  309. HI6421_LDO(LDO9, hi6421_vout9, ldo_0_voltages, 0x29, 0x07, 0x29, 0x10,
  310. 40000, 0x20, 8000),
  311. HI6421_LDO(LDO10, hi6421_vout10, ldo_0_voltages, 0x2a, 0x07, 0x2a, 0x10,
  312. 40000, 0x20, 8000),
  313. HI6421_LDO(LDO11, hi6421_vout11, ldo_0_voltages, 0x2b, 0x07, 0x2b, 0x10,
  314. 40000, 0x20, 8000),
  315. HI6421_LDO(LDO12, hi6421_vout12, ldo_0_voltages, 0x2c, 0x07, 0x2c, 0x10,
  316. 40000, 0x20, 8000),
  317. HI6421_LDO(LDO13, hi6421_vout13, ldo_0_voltages, 0x2d, 0x07, 0x2d, 0x10,
  318. 40000, 0x20, 8000),
  319. HI6421_LDO(LDO14, hi6421_vout14, ldo_0_voltages, 0x2e, 0x07, 0x2e, 0x10,
  320. 40000, 0x20, 8000),
  321. HI6421_LDO(LDO15, hi6421_vout15, ldo_8_voltages, 0x2f, 0x07, 0x2f, 0x10,
  322. 40000, 0x20, 8000),
  323. HI6421_LDO(LDO16, hi6421_vout16, ldo_0_voltages, 0x30, 0x07, 0x30, 0x10,
  324. 40000, 0x20, 8000),
  325. HI6421_LDO(LDO17, hi6421_vout17, ldo_0_voltages, 0x31, 0x07, 0x31, 0x10,
  326. 40000, 0x20, 8000),
  327. HI6421_LDO(LDO18, hi6421_vout18, ldo_0_voltages, 0x32, 0x07, 0x32, 0x10,
  328. 40000, 0x20, 8000),
  329. HI6421_LDO(LDO19, hi6421_vout19, ldo_0_voltages, 0x33, 0x07, 0x33, 0x10,
  330. 40000, 0x20, 8000),
  331. HI6421_LDO(LDO20, hi6421_vout20, ldo_0_voltages, 0x34, 0x07, 0x34, 0x10,
  332. 40000, 0x20, 8000),
  333. HI6421_LDO_LINEAR_RANGE(LDOAUDIO, hi6421_vout_audio, 8,
  334. ldo_audio_volt_range, 0x36, 0x70, 0x36, 0x01,
  335. 40000, 0x02, 5000),
  336. HI6421_BUCK012(BUCK0, hi6421_buck0, 0x0d, 0x7f, 0x0c, 0x01, 0x10, 400,
  337. 20000),
  338. HI6421_BUCK012(BUCK1, hi6421_buck1, 0x0f, 0x7f, 0x0e, 0x01, 0x10, 400,
  339. 20000),
  340. HI6421_BUCK012(BUCK2, hi6421_buck2, 0x11, 0x7f, 0x10, 0x01, 0x10, 350,
  341. 100),
  342. HI6421_BUCK345(BUCK3, hi6421_buck3, buck_3_voltages, 0x13, 0x07, 0x12,
  343. 0x01, 20000, 0x10),
  344. HI6421_BUCK345(BUCK4, hi6421_buck4, buck_4_voltages, 0x15, 0x07, 0x14,
  345. 0x01, 20000, 0x10),
  346. HI6421_BUCK345(BUCK5, hi6421_buck5, buck_5_voltages, 0x17, 0x07, 0x16,
  347. 0x01, 20000, 0x10),
  348. };
  349. static int hi6421_regulator_enable(struct regulator_dev *rdev)
  350. {
  351. struct hi6421_regulator_pdata *pdata = rdev_get_drvdata(rdev);
  352. /* hi6421 spec requires regulator enablement must be serialized:
  353. * - Because when BUCK, LDO switching from off to on, it will have
  354. * a huge instantaneous current; so you can not turn on two or
  355. * more LDO or BUCKs simultaneously, or it may burn the chip.
  356. */
  357. mutex_lock(&pdata->lock);
  358. /* call regulator regmap helper */
  359. regulator_enable_regmap(rdev);
  360. mutex_unlock(&pdata->lock);
  361. return 0;
  362. }
  363. static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev)
  364. {
  365. struct hi6421_regulator_info *info;
  366. unsigned int reg_val;
  367. info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
  368. regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
  369. if (reg_val & info->mode_mask)
  370. return REGULATOR_MODE_IDLE;
  371. return REGULATOR_MODE_NORMAL;
  372. }
  373. static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev)
  374. {
  375. struct hi6421_regulator_info *info;
  376. unsigned int reg_val;
  377. info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
  378. regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
  379. if (reg_val & info->mode_mask)
  380. return REGULATOR_MODE_STANDBY;
  381. return REGULATOR_MODE_NORMAL;
  382. }
  383. static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev,
  384. unsigned int mode)
  385. {
  386. struct hi6421_regulator_info *info;
  387. unsigned int new_mode;
  388. info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
  389. switch (mode) {
  390. case REGULATOR_MODE_NORMAL:
  391. new_mode = 0;
  392. break;
  393. case REGULATOR_MODE_IDLE:
  394. new_mode = info->mode_mask;
  395. break;
  396. default:
  397. return -EINVAL;
  398. }
  399. /* set mode */
  400. regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  401. info->mode_mask, new_mode);
  402. return 0;
  403. }
  404. static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev,
  405. unsigned int mode)
  406. {
  407. struct hi6421_regulator_info *info;
  408. unsigned int new_mode;
  409. info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
  410. switch (mode) {
  411. case REGULATOR_MODE_NORMAL:
  412. new_mode = 0;
  413. break;
  414. case REGULATOR_MODE_STANDBY:
  415. new_mode = info->mode_mask;
  416. break;
  417. default:
  418. return -EINVAL;
  419. }
  420. /* set mode */
  421. regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  422. info->mode_mask, new_mode);
  423. return 0;
  424. }
  425. static unsigned int
  426. hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
  427. int input_uV, int output_uV, int load_uA)
  428. {
  429. struct hi6421_regulator_info *info;
  430. info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
  431. if (load_uA > info->eco_microamp)
  432. return REGULATOR_MODE_NORMAL;
  433. return REGULATOR_MODE_IDLE;
  434. }
  435. static const struct regulator_ops hi6421_ldo_ops = {
  436. .is_enabled = regulator_is_enabled_regmap,
  437. .enable = hi6421_regulator_enable,
  438. .disable = regulator_disable_regmap,
  439. .list_voltage = regulator_list_voltage_table,
  440. .map_voltage = regulator_map_voltage_ascend,
  441. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  442. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  443. .get_mode = hi6421_regulator_ldo_get_mode,
  444. .set_mode = hi6421_regulator_ldo_set_mode,
  445. .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode,
  446. };
  447. static const struct regulator_ops hi6421_ldo_linear_ops = {
  448. .is_enabled = regulator_is_enabled_regmap,
  449. .enable = hi6421_regulator_enable,
  450. .disable = regulator_disable_regmap,
  451. .list_voltage = regulator_list_voltage_linear,
  452. .map_voltage = regulator_map_voltage_linear,
  453. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  454. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  455. .get_mode = hi6421_regulator_ldo_get_mode,
  456. .set_mode = hi6421_regulator_ldo_set_mode,
  457. .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode,
  458. };
  459. static const struct regulator_ops hi6421_ldo_linear_range_ops = {
  460. .is_enabled = regulator_is_enabled_regmap,
  461. .enable = hi6421_regulator_enable,
  462. .disable = regulator_disable_regmap,
  463. .list_voltage = regulator_list_voltage_linear_range,
  464. .map_voltage = regulator_map_voltage_linear_range,
  465. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  466. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  467. .get_mode = hi6421_regulator_ldo_get_mode,
  468. .set_mode = hi6421_regulator_ldo_set_mode,
  469. .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode,
  470. };
  471. static const struct regulator_ops hi6421_buck012_ops = {
  472. .is_enabled = regulator_is_enabled_regmap,
  473. .enable = hi6421_regulator_enable,
  474. .disable = regulator_disable_regmap,
  475. .list_voltage = regulator_list_voltage_linear,
  476. .map_voltage = regulator_map_voltage_linear,
  477. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  478. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  479. .get_mode = hi6421_regulator_buck_get_mode,
  480. .set_mode = hi6421_regulator_buck_set_mode,
  481. };
  482. static const struct regulator_ops hi6421_buck345_ops = {
  483. .is_enabled = regulator_is_enabled_regmap,
  484. .enable = hi6421_regulator_enable,
  485. .disable = regulator_disable_regmap,
  486. .list_voltage = regulator_list_voltage_table,
  487. .map_voltage = regulator_map_voltage_ascend,
  488. .get_voltage_sel = regulator_get_voltage_sel_regmap,
  489. .set_voltage_sel = regulator_set_voltage_sel_regmap,
  490. .get_mode = hi6421_regulator_buck_get_mode,
  491. .set_mode = hi6421_regulator_buck_set_mode,
  492. };
  493. static int hi6421_regulator_probe(struct platform_device *pdev)
  494. {
  495. struct hi6421_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
  496. struct hi6421_regulator_pdata *pdata;
  497. struct hi6421_regulator_info *info;
  498. struct regulator_config config = { };
  499. struct regulator_dev *rdev;
  500. int i;
  501. pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  502. if (!pdata)
  503. return -ENOMEM;
  504. mutex_init(&pdata->lock);
  505. for (i = 0; i < ARRAY_SIZE(hi6421_regulator_info); i++) {
  506. /* assign per-regulator data */
  507. info = &hi6421_regulator_info[i];
  508. config.dev = pdev->dev.parent;
  509. config.driver_data = pdata;
  510. config.regmap = pmic->regmap;
  511. rdev = devm_regulator_register(&pdev->dev, &info->desc,
  512. &config);
  513. if (IS_ERR(rdev)) {
  514. dev_err(&pdev->dev, "failed to register regulator %s\n",
  515. info->desc.name);
  516. return PTR_ERR(rdev);
  517. }
  518. }
  519. return 0;
  520. }
  521. static const struct platform_device_id hi6421_regulator_table[] = {
  522. { .name = "hi6421-regulator" },
  523. {},
  524. };
  525. MODULE_DEVICE_TABLE(platform, hi6421_regulator_table);
  526. static struct platform_driver hi6421_regulator_driver = {
  527. .id_table = hi6421_regulator_table,
  528. .driver = {
  529. .name = "hi6421-regulator",
  530. },
  531. .probe = hi6421_regulator_probe,
  532. };
  533. module_platform_driver(hi6421_regulator_driver);
  534. MODULE_AUTHOR("Guodong Xu <guodong.xu@linaro.org>");
  535. MODULE_DESCRIPTION("Hi6421 regulator driver");
  536. MODULE_LICENSE("GPL v2");