qcom_smd-regulator.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*
  2. * Copyright (c) 2015, Sony Mobile Communications AB.
  3. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/of.h>
  16. #include <linux/of_device.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/regulator/driver.h>
  19. #include <linux/regulator/machine.h>
  20. #include <linux/regulator/of_regulator.h>
  21. #include <linux/soc/qcom/smd-rpm.h>
  22. struct qcom_rpm_reg {
  23. struct device *dev;
  24. struct qcom_smd_rpm *rpm;
  25. u32 type;
  26. u32 id;
  27. struct regulator_desc desc;
  28. int is_enabled;
  29. int uV;
  30. };
  31. struct rpm_regulator_req {
  32. __le32 key;
  33. __le32 nbytes;
  34. __le32 value;
  35. };
  36. #define RPM_KEY_SWEN 0x6e657773 /* "swen" */
  37. #define RPM_KEY_UV 0x00007675 /* "uv" */
  38. #define RPM_KEY_MA 0x0000616d /* "ma" */
  39. static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
  40. struct rpm_regulator_req *req,
  41. size_t size)
  42. {
  43. return qcom_rpm_smd_write(vreg->rpm,
  44. QCOM_SMD_RPM_ACTIVE_STATE,
  45. vreg->type,
  46. vreg->id,
  47. req, size);
  48. }
  49. static int rpm_reg_enable(struct regulator_dev *rdev)
  50. {
  51. struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
  52. struct rpm_regulator_req req;
  53. int ret;
  54. req.key = cpu_to_le32(RPM_KEY_SWEN);
  55. req.nbytes = cpu_to_le32(sizeof(u32));
  56. req.value = cpu_to_le32(1);
  57. ret = rpm_reg_write_active(vreg, &req, sizeof(req));
  58. if (!ret)
  59. vreg->is_enabled = 1;
  60. return ret;
  61. }
  62. static int rpm_reg_is_enabled(struct regulator_dev *rdev)
  63. {
  64. struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
  65. return vreg->is_enabled;
  66. }
  67. static int rpm_reg_disable(struct regulator_dev *rdev)
  68. {
  69. struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
  70. struct rpm_regulator_req req;
  71. int ret;
  72. req.key = cpu_to_le32(RPM_KEY_SWEN);
  73. req.nbytes = cpu_to_le32(sizeof(u32));
  74. req.value = 0;
  75. ret = rpm_reg_write_active(vreg, &req, sizeof(req));
  76. if (!ret)
  77. vreg->is_enabled = 0;
  78. return ret;
  79. }
  80. static int rpm_reg_get_voltage(struct regulator_dev *rdev)
  81. {
  82. struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
  83. return vreg->uV;
  84. }
  85. static int rpm_reg_set_voltage(struct regulator_dev *rdev,
  86. int min_uV,
  87. int max_uV,
  88. unsigned *selector)
  89. {
  90. struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
  91. struct rpm_regulator_req req;
  92. int ret = 0;
  93. req.key = cpu_to_le32(RPM_KEY_UV);
  94. req.nbytes = cpu_to_le32(sizeof(u32));
  95. req.value = cpu_to_le32(min_uV);
  96. ret = rpm_reg_write_active(vreg, &req, sizeof(req));
  97. if (!ret)
  98. vreg->uV = min_uV;
  99. return ret;
  100. }
  101. static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
  102. {
  103. struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
  104. struct rpm_regulator_req req;
  105. req.key = cpu_to_le32(RPM_KEY_MA);
  106. req.nbytes = cpu_to_le32(sizeof(u32));
  107. req.value = cpu_to_le32(load_uA / 1000);
  108. return rpm_reg_write_active(vreg, &req, sizeof(req));
  109. }
  110. static const struct regulator_ops rpm_smps_ldo_ops = {
  111. .enable = rpm_reg_enable,
  112. .disable = rpm_reg_disable,
  113. .is_enabled = rpm_reg_is_enabled,
  114. .list_voltage = regulator_list_voltage_linear_range,
  115. .get_voltage = rpm_reg_get_voltage,
  116. .set_voltage = rpm_reg_set_voltage,
  117. .set_load = rpm_reg_set_load,
  118. };
  119. static const struct regulator_ops rpm_smps_ldo_ops_fixed = {
  120. .enable = rpm_reg_enable,
  121. .disable = rpm_reg_disable,
  122. .is_enabled = rpm_reg_is_enabled,
  123. .get_voltage = rpm_reg_get_voltage,
  124. .set_voltage = rpm_reg_set_voltage,
  125. .set_load = rpm_reg_set_load,
  126. };
  127. static const struct regulator_ops rpm_switch_ops = {
  128. .enable = rpm_reg_enable,
  129. .disable = rpm_reg_disable,
  130. .is_enabled = rpm_reg_is_enabled,
  131. };
  132. static const struct regulator_desc pma8084_hfsmps = {
  133. .linear_ranges = (struct regulator_linear_range[]) {
  134. REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
  135. REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
  136. },
  137. .n_linear_ranges = 2,
  138. .n_voltages = 159,
  139. .ops = &rpm_smps_ldo_ops,
  140. };
  141. static const struct regulator_desc pma8084_ftsmps = {
  142. .linear_ranges = (struct regulator_linear_range[]) {
  143. REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
  144. REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
  145. },
  146. .n_linear_ranges = 2,
  147. .n_voltages = 262,
  148. .ops = &rpm_smps_ldo_ops,
  149. };
  150. static const struct regulator_desc pma8084_pldo = {
  151. .linear_ranges = (struct regulator_linear_range[]) {
  152. REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
  153. REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
  154. REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
  155. },
  156. .n_linear_ranges = 3,
  157. .n_voltages = 164,
  158. .ops = &rpm_smps_ldo_ops,
  159. };
  160. static const struct regulator_desc pma8084_nldo = {
  161. .linear_ranges = (struct regulator_linear_range[]) {
  162. REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
  163. },
  164. .n_linear_ranges = 1,
  165. .n_voltages = 64,
  166. .ops = &rpm_smps_ldo_ops,
  167. };
  168. static const struct regulator_desc pma8084_switch = {
  169. .ops = &rpm_switch_ops,
  170. };
  171. static const struct regulator_desc pm8x41_hfsmps = {
  172. .linear_ranges = (struct regulator_linear_range[]) {
  173. REGULATOR_LINEAR_RANGE( 375000, 0, 95, 12500),
  174. REGULATOR_LINEAR_RANGE(1575000, 96, 158, 25000),
  175. },
  176. .n_linear_ranges = 2,
  177. .n_voltages = 159,
  178. .ops = &rpm_smps_ldo_ops,
  179. };
  180. static const struct regulator_desc pm8841_ftsmps = {
  181. .linear_ranges = (struct regulator_linear_range[]) {
  182. REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
  183. REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
  184. },
  185. .n_linear_ranges = 2,
  186. .n_voltages = 262,
  187. .ops = &rpm_smps_ldo_ops,
  188. };
  189. static const struct regulator_desc pm8941_boost = {
  190. .linear_ranges = (struct regulator_linear_range[]) {
  191. REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000),
  192. },
  193. .n_linear_ranges = 1,
  194. .n_voltages = 31,
  195. .ops = &rpm_smps_ldo_ops,
  196. };
  197. static const struct regulator_desc pm8941_pldo = {
  198. .linear_ranges = (struct regulator_linear_range[]) {
  199. REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
  200. REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
  201. REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
  202. },
  203. .n_linear_ranges = 3,
  204. .n_voltages = 164,
  205. .ops = &rpm_smps_ldo_ops,
  206. };
  207. static const struct regulator_desc pm8941_nldo = {
  208. .linear_ranges = (struct regulator_linear_range[]) {
  209. REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
  210. },
  211. .n_linear_ranges = 1,
  212. .n_voltages = 64,
  213. .ops = &rpm_smps_ldo_ops,
  214. };
  215. static const struct regulator_desc pm8941_lnldo = {
  216. .fixed_uV = 1740000,
  217. .n_voltages = 1,
  218. .ops = &rpm_smps_ldo_ops_fixed,
  219. };
  220. static const struct regulator_desc pm8941_switch = {
  221. .ops = &rpm_switch_ops,
  222. };
  223. static const struct regulator_desc pm8916_pldo = {
  224. .linear_ranges = (struct regulator_linear_range[]) {
  225. REGULATOR_LINEAR_RANGE(750000, 0, 208, 12500),
  226. },
  227. .n_linear_ranges = 1,
  228. .n_voltages = 209,
  229. .ops = &rpm_smps_ldo_ops,
  230. };
  231. static const struct regulator_desc pm8916_nldo = {
  232. .linear_ranges = (struct regulator_linear_range[]) {
  233. REGULATOR_LINEAR_RANGE(375000, 0, 93, 12500),
  234. },
  235. .n_linear_ranges = 1,
  236. .n_voltages = 94,
  237. .ops = &rpm_smps_ldo_ops,
  238. };
  239. static const struct regulator_desc pm8916_buck_lvo_smps = {
  240. .linear_ranges = (struct regulator_linear_range[]) {
  241. REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
  242. REGULATOR_LINEAR_RANGE(750000, 96, 127, 25000),
  243. },
  244. .n_linear_ranges = 2,
  245. .n_voltages = 128,
  246. .ops = &rpm_smps_ldo_ops,
  247. };
  248. static const struct regulator_desc pm8916_buck_hvo_smps = {
  249. .linear_ranges = (struct regulator_linear_range[]) {
  250. REGULATOR_LINEAR_RANGE(1550000, 0, 31, 25000),
  251. },
  252. .n_linear_ranges = 1,
  253. .n_voltages = 32,
  254. .ops = &rpm_smps_ldo_ops,
  255. };
  256. struct rpm_regulator_data {
  257. const char *name;
  258. u32 type;
  259. u32 id;
  260. const struct regulator_desc *desc;
  261. const char *supply;
  262. };
  263. static const struct rpm_regulator_data rpm_pm8841_regulators[] = {
  264. { "s1", QCOM_SMD_RPM_SMPB, 1, &pm8x41_hfsmps, "vdd_s1" },
  265. { "s2", QCOM_SMD_RPM_SMPB, 2, &pm8841_ftsmps, "vdd_s2" },
  266. { "s3", QCOM_SMD_RPM_SMPB, 3, &pm8x41_hfsmps, "vdd_s3" },
  267. { "s4", QCOM_SMD_RPM_SMPB, 4, &pm8841_ftsmps, "vdd_s4" },
  268. { "s5", QCOM_SMD_RPM_SMPB, 5, &pm8841_ftsmps, "vdd_s5" },
  269. { "s6", QCOM_SMD_RPM_SMPB, 6, &pm8841_ftsmps, "vdd_s6" },
  270. { "s7", QCOM_SMD_RPM_SMPB, 7, &pm8841_ftsmps, "vdd_s7" },
  271. { "s8", QCOM_SMD_RPM_SMPB, 8, &pm8841_ftsmps, "vdd_s8" },
  272. {}
  273. };
  274. static const struct rpm_regulator_data rpm_pm8916_regulators[] = {
  275. { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8916_buck_lvo_smps, "vdd_s1" },
  276. { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8916_buck_lvo_smps, "vdd_s2" },
  277. { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8916_buck_lvo_smps, "vdd_s3" },
  278. { "s4", QCOM_SMD_RPM_SMPA, 4, &pm8916_buck_hvo_smps, "vdd_s4" },
  279. { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8916_nldo, "vdd_l1_l2_l3" },
  280. { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8916_nldo, "vdd_l1_l2_l3" },
  281. { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8916_nldo, "vdd_l1_l2_l3" },
  282. { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8916_pldo, "vdd_l4_l5_l6" },
  283. { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8916_pldo, "vdd_l4_l5_l6" },
  284. { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8916_pldo, "vdd_l4_l5_l6" },
  285. { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8916_pldo, "vdd_l7" },
  286. { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18" },
  287. { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18" },
  288. { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  289. { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  290. { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  291. { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  292. { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  293. { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  294. { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  295. { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  296. { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
  297. {}
  298. };
  299. static const struct rpm_regulator_data rpm_pm8941_regulators[] = {
  300. { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8x41_hfsmps, "vdd_s1" },
  301. { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8x41_hfsmps, "vdd_s2" },
  302. { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8x41_hfsmps, "vdd_s3" },
  303. { "s4", QCOM_SMD_RPM_BOOST, 1, &pm8941_boost },
  304. { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8941_nldo, "vdd_l1_l3" },
  305. { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8941_nldo, "vdd_l2_lvs1_2_3" },
  306. { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8941_nldo, "vdd_l1_l3" },
  307. { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8941_nldo, "vdd_l4_l11" },
  308. { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8941_lnldo, "vdd_l5_l7" },
  309. { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
  310. { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8941_lnldo, "vdd_l5_l7" },
  311. { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
  312. { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
  313. { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
  314. { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8941_nldo, "vdd_l4_l11" },
  315. { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
  316. { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
  317. { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
  318. { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
  319. { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
  320. { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
  321. { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
  322. { "l19", QCOM_SMD_RPM_LDOA, 19, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
  323. { "l20", QCOM_SMD_RPM_LDOA, 20, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
  324. { "l21", QCOM_SMD_RPM_LDOA, 21, &pm8941_pldo, "vdd_l21" },
  325. { "l22", QCOM_SMD_RPM_LDOA, 22, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
  326. { "l23", QCOM_SMD_RPM_LDOA, 23, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
  327. { "l24", QCOM_SMD_RPM_LDOA, 24, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
  328. { "lvs1", QCOM_SMD_RPM_VSA, 1, &pm8941_switch, "vdd_l2_lvs1_2_3" },
  329. { "lvs2", QCOM_SMD_RPM_VSA, 2, &pm8941_switch, "vdd_l2_lvs1_2_3" },
  330. { "lvs3", QCOM_SMD_RPM_VSA, 3, &pm8941_switch, "vdd_l2_lvs1_2_3" },
  331. { "5vs1", QCOM_SMD_RPM_VSA, 4, &pm8941_switch, "vin_5vs" },
  332. { "5vs2", QCOM_SMD_RPM_VSA, 5, &pm8941_switch, "vin_5vs" },
  333. {}
  334. };
  335. static const struct rpm_regulator_data rpm_pma8084_regulators[] = {
  336. { "s1", QCOM_SMD_RPM_SMPA, 1, &pma8084_ftsmps, "vdd_s1" },
  337. { "s2", QCOM_SMD_RPM_SMPA, 2, &pma8084_ftsmps, "vdd_s2" },
  338. { "s3", QCOM_SMD_RPM_SMPA, 3, &pma8084_hfsmps, "vdd_s3" },
  339. { "s4", QCOM_SMD_RPM_SMPA, 4, &pma8084_hfsmps, "vdd_s4" },
  340. { "s5", QCOM_SMD_RPM_SMPA, 5, &pma8084_hfsmps, "vdd_s5" },
  341. { "s6", QCOM_SMD_RPM_SMPA, 6, &pma8084_ftsmps, "vdd_s6" },
  342. { "s7", QCOM_SMD_RPM_SMPA, 7, &pma8084_ftsmps, "vdd_s7" },
  343. { "s8", QCOM_SMD_RPM_SMPA, 8, &pma8084_ftsmps, "vdd_s8" },
  344. { "s9", QCOM_SMD_RPM_SMPA, 9, &pma8084_ftsmps, "vdd_s9" },
  345. { "s10", QCOM_SMD_RPM_SMPA, 10, &pma8084_ftsmps, "vdd_s10" },
  346. { "s11", QCOM_SMD_RPM_SMPA, 11, &pma8084_ftsmps, "vdd_s11" },
  347. { "s12", QCOM_SMD_RPM_SMPA, 12, &pma8084_ftsmps, "vdd_s12" },
  348. { "l1", QCOM_SMD_RPM_LDOA, 1, &pma8084_nldo, "vdd_l1_l11" },
  349. { "l2", QCOM_SMD_RPM_LDOA, 2, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
  350. { "l3", QCOM_SMD_RPM_LDOA, 3, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
  351. { "l4", QCOM_SMD_RPM_LDOA, 4, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
  352. { "l5", QCOM_SMD_RPM_LDOA, 5, &pma8084_pldo, "vdd_l5_l7" },
  353. { "l6", QCOM_SMD_RPM_LDOA, 6, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
  354. { "l7", QCOM_SMD_RPM_LDOA, 7, &pma8084_pldo, "vdd_l5_l7" },
  355. { "l8", QCOM_SMD_RPM_LDOA, 8, &pma8084_pldo, "vdd_l8" },
  356. { "l9", QCOM_SMD_RPM_LDOA, 9, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
  357. { "l10", QCOM_SMD_RPM_LDOA, 10, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
  358. { "l11", QCOM_SMD_RPM_LDOA, 11, &pma8084_nldo, "vdd_l1_l11" },
  359. { "l12", QCOM_SMD_RPM_LDOA, 12, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
  360. { "l13", QCOM_SMD_RPM_LDOA, 13, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
  361. { "l14", QCOM_SMD_RPM_LDOA, 14, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
  362. { "l15", QCOM_SMD_RPM_LDOA, 15, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
  363. { "l16", QCOM_SMD_RPM_LDOA, 16, &pma8084_pldo, "vdd_l16_l25" },
  364. { "l17", QCOM_SMD_RPM_LDOA, 17, &pma8084_pldo, "vdd_l17" },
  365. { "l18", QCOM_SMD_RPM_LDOA, 18, &pma8084_pldo, "vdd_l18" },
  366. { "l19", QCOM_SMD_RPM_LDOA, 19, &pma8084_pldo, "vdd_l19" },
  367. { "l20", QCOM_SMD_RPM_LDOA, 20, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
  368. { "l21", QCOM_SMD_RPM_LDOA, 21, &pma8084_pldo, "vdd_l21" },
  369. { "l22", QCOM_SMD_RPM_LDOA, 22, &pma8084_pldo, "vdd_l22" },
  370. { "l23", QCOM_SMD_RPM_LDOA, 23, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
  371. { "l24", QCOM_SMD_RPM_LDOA, 24, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
  372. { "l25", QCOM_SMD_RPM_LDOA, 25, &pma8084_pldo, "vdd_l16_l25" },
  373. { "l26", QCOM_SMD_RPM_LDOA, 26, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
  374. { "l27", QCOM_SMD_RPM_LDOA, 27, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
  375. { "lvs1", QCOM_SMD_RPM_VSA, 1, &pma8084_switch },
  376. { "lvs2", QCOM_SMD_RPM_VSA, 2, &pma8084_switch },
  377. { "lvs3", QCOM_SMD_RPM_VSA, 3, &pma8084_switch },
  378. { "lvs4", QCOM_SMD_RPM_VSA, 4, &pma8084_switch },
  379. { "5vs1", QCOM_SMD_RPM_VSA, 5, &pma8084_switch },
  380. {}
  381. };
  382. static const struct of_device_id rpm_of_match[] = {
  383. { .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
  384. { .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators },
  385. { .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
  386. { .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
  387. {}
  388. };
  389. MODULE_DEVICE_TABLE(of, rpm_of_match);
  390. static int rpm_reg_probe(struct platform_device *pdev)
  391. {
  392. const struct rpm_regulator_data *reg;
  393. const struct of_device_id *match;
  394. struct regulator_config config = { };
  395. struct regulator_dev *rdev;
  396. struct qcom_rpm_reg *vreg;
  397. struct qcom_smd_rpm *rpm;
  398. rpm = dev_get_drvdata(pdev->dev.parent);
  399. if (!rpm) {
  400. dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
  401. return -ENODEV;
  402. }
  403. match = of_match_device(rpm_of_match, &pdev->dev);
  404. for (reg = match->data; reg->name; reg++) {
  405. vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
  406. if (!vreg)
  407. return -ENOMEM;
  408. vreg->dev = &pdev->dev;
  409. vreg->type = reg->type;
  410. vreg->id = reg->id;
  411. vreg->rpm = rpm;
  412. memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc));
  413. vreg->desc.id = -1;
  414. vreg->desc.owner = THIS_MODULE;
  415. vreg->desc.type = REGULATOR_VOLTAGE;
  416. vreg->desc.name = reg->name;
  417. vreg->desc.supply_name = reg->supply;
  418. vreg->desc.of_match = reg->name;
  419. config.dev = &pdev->dev;
  420. config.driver_data = vreg;
  421. rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
  422. if (IS_ERR(rdev)) {
  423. dev_err(&pdev->dev, "failed to register %s\n", reg->name);
  424. return PTR_ERR(rdev);
  425. }
  426. }
  427. return 0;
  428. }
  429. static struct platform_driver rpm_reg_driver = {
  430. .probe = rpm_reg_probe,
  431. .driver = {
  432. .name = "qcom_rpm_smd_regulator",
  433. .of_match_table = rpm_of_match,
  434. },
  435. };
  436. static int __init rpm_reg_init(void)
  437. {
  438. return platform_driver_register(&rpm_reg_driver);
  439. }
  440. subsys_initcall(rpm_reg_init);
  441. static void __exit rpm_reg_exit(void)
  442. {
  443. platform_driver_unregister(&rpm_reg_driver);
  444. }
  445. module_exit(rpm_reg_exit)
  446. MODULE_DESCRIPTION("Qualcomm RPM regulator driver");
  447. MODULE_LICENSE("GPL v2");