msm-cdc-supply.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /*
  2. * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/of_irq.h>
  16. #include <linux/of_device.h>
  17. #include <linux/slab.h>
  18. #include "msm-cdc-supply.h"
  19. #include <linux/regulator/consumer.h>
  20. #define CODEC_DT_MAX_PROP_SIZE 40
  21. static int msm_cdc_dt_parse_vreg_info(struct device *dev,
  22. struct cdc_regulator *cdc_vreg,
  23. const char *name, bool is_ond)
  24. {
  25. char prop_name[CODEC_DT_MAX_PROP_SIZE];
  26. struct device_node *regulator_node = NULL;
  27. const __be32 *prop;
  28. int len, rc;
  29. u32 prop_val;
  30. /* Parse supply name */
  31. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply", name);
  32. regulator_node = of_parse_phandle(dev->of_node, prop_name, 0);
  33. if (!regulator_node) {
  34. dev_err(dev, "%s: Looking up %s property in node %s failed",
  35. __func__, prop_name, dev->of_node->full_name);
  36. rc = -EINVAL;
  37. goto done;
  38. }
  39. cdc_vreg->name = name;
  40. cdc_vreg->ondemand = is_ond;
  41. /* Parse supply - voltage */
  42. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-voltage", name);
  43. prop = of_get_property(dev->of_node, prop_name, &len);
  44. if (!prop || (len != (2 * sizeof(__be32)))) {
  45. dev_err(dev, "%s: %s %s property\n", __func__,
  46. prop ? "invalid format" : "no", prop_name);
  47. rc = -EINVAL;
  48. goto done;
  49. } else {
  50. cdc_vreg->min_uV = be32_to_cpup(&prop[0]);
  51. cdc_vreg->max_uV = be32_to_cpup(&prop[1]);
  52. }
  53. /* Parse supply - current */
  54. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-current", name);
  55. rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
  56. if (rc) {
  57. dev_err(dev, "%s: Looking up %s property in node %s failed",
  58. __func__, prop_name, dev->of_node->full_name);
  59. goto done;
  60. }
  61. cdc_vreg->optimum_uA = prop_val;
  62. dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n",
  63. __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
  64. cdc_vreg->optimum_uA, cdc_vreg->ondemand);
  65. done:
  66. return rc;
  67. }
  68. static int msm_cdc_parse_supplies(struct device *dev,
  69. struct cdc_regulator *cdc_reg,
  70. const char *sup_list, int sup_cnt,
  71. bool is_ond)
  72. {
  73. int idx, rc = 0;
  74. const char *name = NULL;
  75. for (idx = 0; idx < sup_cnt; idx++) {
  76. rc = of_property_read_string_index(dev->of_node, sup_list, idx,
  77. &name);
  78. if (rc) {
  79. dev_err(dev, "%s: read string %s[%d] error (%d)\n",
  80. __func__, sup_list, idx, rc);
  81. goto done;
  82. }
  83. dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
  84. __func__, name, sup_list);
  85. rc = msm_cdc_dt_parse_vreg_info(dev, &cdc_reg[idx], name,
  86. is_ond);
  87. if (rc) {
  88. dev_err(dev, "%s: parse %s vreg info failed (%d)\n",
  89. __func__, name, rc);
  90. goto done;
  91. }
  92. }
  93. done:
  94. return rc;
  95. }
  96. static int msm_cdc_check_supply_param(struct device *dev,
  97. struct cdc_regulator *cdc_vreg,
  98. int num_supplies)
  99. {
  100. if (!dev) {
  101. pr_err("%s: device is NULL\n", __func__);
  102. return -ENODEV;
  103. }
  104. if (!cdc_vreg || (num_supplies <= 0)) {
  105. dev_err(dev, "%s: supply check failed: vreg: %pK, num_supplies: %d\n",
  106. __func__, cdc_vreg, num_supplies);
  107. return -EINVAL;
  108. }
  109. return 0;
  110. }
  111. /*
  112. * msm_cdc_disable_static_supplies:
  113. * Disable codec static supplies
  114. *
  115. * @dev: pointer to codec device
  116. * @supplies: pointer to regulator bulk data
  117. * @cdc_vreg: pointer to platform regulator data
  118. * @num_supplies: number of supplies
  119. *
  120. * Return error code if supply disable is failed
  121. */
  122. int msm_cdc_disable_static_supplies(struct device *dev,
  123. struct regulator_bulk_data *supplies,
  124. struct cdc_regulator *cdc_vreg,
  125. int num_supplies)
  126. {
  127. int rc, i;
  128. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  129. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  130. __func__);
  131. return -EINVAL;
  132. }
  133. /* input parameter validation */
  134. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  135. if (rc)
  136. return rc;
  137. for (i = 0; i < num_supplies; i++) {
  138. if (cdc_vreg[i].ondemand)
  139. continue;
  140. rc = regulator_disable(supplies[i].consumer);
  141. if (rc)
  142. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  143. __func__, supplies[i].supply, rc);
  144. else
  145. dev_dbg(dev, "%s: disabled regulator %s\n",
  146. __func__, supplies[i].supply);
  147. }
  148. return rc;
  149. }
  150. EXPORT_SYMBOL(msm_cdc_disable_static_supplies);
  151. /*
  152. * msm_cdc_release_supplies:
  153. * Release codec power supplies
  154. *
  155. * @dev: pointer to codec device
  156. * @supplies: pointer to regulator bulk data
  157. * @cdc_vreg: pointer to platform regulator data
  158. * @num_supplies: number of supplies
  159. *
  160. * Return error code if supply disable is failed
  161. */
  162. int msm_cdc_release_supplies(struct device *dev,
  163. struct regulator_bulk_data *supplies,
  164. struct cdc_regulator *cdc_vreg,
  165. int num_supplies)
  166. {
  167. int rc = 0;
  168. int i;
  169. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  170. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  171. __func__);
  172. return -EINVAL;
  173. }
  174. /* input parameter validation */
  175. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  176. if (rc)
  177. return rc;
  178. msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg,
  179. num_supplies);
  180. for (i = 0; i < num_supplies; i++) {
  181. if (regulator_count_voltages(supplies[i].consumer) < 0)
  182. continue;
  183. regulator_set_voltage(supplies[i].consumer, 0,
  184. cdc_vreg[i].max_uV);
  185. regulator_set_load(supplies[i].consumer, 0);
  186. devm_regulator_put(supplies[i].consumer);
  187. supplies[i].consumer = NULL;
  188. }
  189. devm_kfree(dev, supplies);
  190. return rc;
  191. }
  192. EXPORT_SYMBOL(msm_cdc_release_supplies);
  193. /*
  194. * msm_cdc_enable_static_supplies:
  195. * Enable codec static supplies
  196. *
  197. * @dev: pointer to codec device
  198. * @supplies: pointer to regulator bulk data
  199. * @cdc_vreg: pointer to platform regulator data
  200. * @num_supplies: number of supplies
  201. *
  202. * Return error code if supply enable is failed
  203. */
  204. int msm_cdc_enable_static_supplies(struct device *dev,
  205. struct regulator_bulk_data *supplies,
  206. struct cdc_regulator *cdc_vreg,
  207. int num_supplies)
  208. {
  209. int rc, i;
  210. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  211. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  212. __func__);
  213. return -EINVAL;
  214. }
  215. /* input parameter validation */
  216. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  217. if (rc)
  218. return rc;
  219. for (i = 0; i < num_supplies; i++) {
  220. if (cdc_vreg[i].ondemand)
  221. continue;
  222. rc = regulator_enable(supplies[i].consumer);
  223. if (rc) {
  224. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  225. __func__, supplies[i].supply, rc);
  226. break;
  227. }
  228. }
  229. while (rc && i--)
  230. if (!cdc_vreg[i].ondemand)
  231. regulator_disable(supplies[i].consumer);
  232. return rc;
  233. }
  234. EXPORT_SYMBOL(msm_cdc_enable_static_supplies);
  235. /*
  236. * msm_cdc_init_supplies:
  237. * Initialize codec static supplies with regulator get
  238. *
  239. * @dev: pointer to codec device
  240. * @supplies: pointer to regulator bulk data
  241. * @cdc_vreg: pointer to platform regulator data
  242. * @num_supplies: number of supplies
  243. *
  244. * Return error code if supply init is failed
  245. */
  246. int msm_cdc_init_supplies(struct device *dev,
  247. struct regulator_bulk_data **supplies,
  248. struct cdc_regulator *cdc_vreg,
  249. int num_supplies)
  250. {
  251. struct regulator_bulk_data *vsup;
  252. int rc;
  253. int i;
  254. if (!dev || !cdc_vreg) {
  255. pr_err("%s: device pointer or dce_vreg is NULL\n",
  256. __func__);
  257. return -EINVAL;
  258. }
  259. /* input parameter validation */
  260. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  261. if (rc)
  262. return rc;
  263. vsup = devm_kcalloc(dev, num_supplies,
  264. sizeof(struct regulator_bulk_data),
  265. GFP_KERNEL);
  266. if (!vsup)
  267. return -ENOMEM;
  268. for (i = 0; i < num_supplies; i++) {
  269. if (!cdc_vreg[i].name) {
  270. dev_err(dev, "%s: supply name not defined\n",
  271. __func__);
  272. rc = -EINVAL;
  273. goto err_supply;
  274. }
  275. vsup[i].supply = cdc_vreg[i].name;
  276. }
  277. rc = devm_regulator_bulk_get(dev, num_supplies, vsup);
  278. if (rc) {
  279. dev_err(dev, "%s: failed to get supplies (%d)\n",
  280. __func__, rc);
  281. goto err_supply;
  282. }
  283. /* Set voltage and current on regulators */
  284. for (i = 0; i < num_supplies; i++) {
  285. if (regulator_count_voltages(vsup[i].consumer) < 0)
  286. continue;
  287. rc = regulator_set_voltage(vsup[i].consumer,
  288. cdc_vreg[i].min_uV,
  289. cdc_vreg[i].max_uV);
  290. if (rc) {
  291. dev_err(dev, "%s: set regulator voltage failed for %s, err:%d\n",
  292. __func__, vsup[i].supply, rc);
  293. goto err_set_supply;
  294. }
  295. rc = regulator_set_load(vsup[i].consumer,
  296. cdc_vreg[i].optimum_uA);
  297. if (rc < 0) {
  298. dev_err(dev, "%s: set regulator optimum mode failed for %s, err:%d\n",
  299. __func__, vsup[i].supply, rc);
  300. goto err_set_supply;
  301. }
  302. }
  303. *supplies = vsup;
  304. return 0;
  305. err_set_supply:
  306. for (i = 0; i < num_supplies; i++)
  307. devm_regulator_put(vsup[i].consumer);
  308. err_supply:
  309. devm_kfree(dev, vsup);
  310. return rc;
  311. }
  312. EXPORT_SYMBOL(msm_cdc_init_supplies);
  313. /*
  314. * msm_cdc_get_power_supplies:
  315. * Get codec power supplies from device tree.
  316. * Allocate memory to hold regulator data for
  317. * all power supplies.
  318. *
  319. * @dev: pointer to codec device
  320. * @cdc_vreg: pointer to codec regulator
  321. * @total_num_supplies: total number of supplies read from DT
  322. *
  323. * Return error code if supply disable is failed
  324. */
  325. int msm_cdc_get_power_supplies(struct device *dev,
  326. struct cdc_regulator **cdc_vreg,
  327. int *total_num_supplies)
  328. {
  329. const char *static_prop_name = "qcom,cdc-static-supplies";
  330. const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
  331. const char *cp_prop_name = "qcom,cdc-cp-supplies";
  332. int static_sup_cnt = 0;
  333. int ond_sup_cnt = 0;
  334. int cp_sup_cnt = 0;
  335. int num_supplies = 0;
  336. struct cdc_regulator *cdc_reg;
  337. int rc;
  338. if (!dev) {
  339. pr_err("%s: device pointer is NULL\n", __func__);
  340. return -EINVAL;
  341. }
  342. static_sup_cnt = of_property_count_strings(dev->of_node,
  343. static_prop_name);
  344. if (static_sup_cnt < 0) {
  345. dev_err(dev, "%s: Failed to get static supplies(%d)\n",
  346. __func__, static_sup_cnt);
  347. rc = static_sup_cnt;
  348. goto err_supply_cnt;
  349. }
  350. ond_sup_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
  351. if (ond_sup_cnt < 0)
  352. ond_sup_cnt = 0;
  353. cp_sup_cnt = of_property_count_strings(dev->of_node,
  354. cp_prop_name);
  355. if (cp_sup_cnt < 0)
  356. cp_sup_cnt = 0;
  357. num_supplies = static_sup_cnt + ond_sup_cnt + cp_sup_cnt;
  358. if (num_supplies <= 0) {
  359. dev_err(dev, "%s: supply count is 0 or negative\n", __func__);
  360. rc = -EINVAL;
  361. goto err_supply_cnt;
  362. }
  363. cdc_reg = devm_kcalloc(dev, num_supplies,
  364. sizeof(struct cdc_regulator),
  365. GFP_KERNEL);
  366. if (!cdc_reg) {
  367. rc = -ENOMEM;
  368. goto err_mem_alloc;
  369. }
  370. rc = msm_cdc_parse_supplies(dev, cdc_reg, static_prop_name,
  371. static_sup_cnt, false);
  372. if (rc) {
  373. dev_err(dev, "%s: failed to parse static supplies(%d)\n",
  374. __func__, rc);
  375. goto err_sup;
  376. }
  377. rc = msm_cdc_parse_supplies(dev, &cdc_reg[static_sup_cnt],
  378. ond_prop_name, ond_sup_cnt,
  379. true);
  380. if (rc) {
  381. dev_err(dev, "%s: failed to parse demand supplies(%d)\n",
  382. __func__, rc);
  383. goto err_sup;
  384. }
  385. rc = msm_cdc_parse_supplies(dev,
  386. &cdc_reg[static_sup_cnt + ond_sup_cnt],
  387. cp_prop_name, cp_sup_cnt, true);
  388. if (rc) {
  389. dev_err(dev, "%s: failed to parse cp supplies(%d)\n",
  390. __func__, rc);
  391. goto err_sup;
  392. }
  393. *cdc_vreg = cdc_reg;
  394. *total_num_supplies = num_supplies;
  395. return 0;
  396. err_sup:
  397. devm_kfree(dev, cdc_reg);
  398. err_supply_cnt:
  399. err_mem_alloc:
  400. return rc;
  401. }
  402. EXPORT_SYMBOL(msm_cdc_get_power_supplies);