sde_io_util.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2012-2015, 2017-2021 The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/clk.h>
  6. #include <linux/err.h>
  7. #include <linux/io.h>
  8. #include <linux/regulator/consumer.h>
  9. #include <linux/soc/qcom/spmi-pmic-arb.h>
  10. #include <linux/pinctrl/qcom-pinctrl.h>
  11. #include <linux/delay.h>
  12. #include <linux/sde_io_util.h>
  13. #include <linux/sde_vm_event.h>
  14. #include "sde_dbg.h"
  15. #define MAX_I2C_CMDS 16
  16. void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug)
  17. {
  18. u32 in_val;
  19. if (!io || !io->base) {
  20. DEV_ERR("%pS->%s: invalid input\n",
  21. __builtin_return_address(0), __func__);
  22. return;
  23. }
  24. if (offset > io->len) {
  25. DEV_ERR("%pS->%s: offset out of range\n",
  26. __builtin_return_address(0), __func__);
  27. return;
  28. }
  29. writel_relaxed(value, io->base + offset);
  30. if (debug) {
  31. in_val = readl_relaxed(io->base + offset);
  32. DEV_DBG("[%08x] => %08x [%08x]\n",
  33. (u32)(unsigned long)(io->base + offset),
  34. value, in_val);
  35. }
  36. SDE_REG_LOG(SDE_REG_LOG_RSCC, value, offset);
  37. } /* dss_reg_w */
  38. EXPORT_SYMBOL(dss_reg_w);
  39. u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug)
  40. {
  41. u32 value;
  42. if (!io || !io->base) {
  43. DEV_ERR("%pS->%s: invalid input\n",
  44. __builtin_return_address(0), __func__);
  45. return -EINVAL;
  46. }
  47. if (offset > io->len) {
  48. DEV_ERR("%pS->%s: offset out of range\n",
  49. __builtin_return_address(0), __func__);
  50. return -EINVAL;
  51. }
  52. value = readl_relaxed(io->base + offset);
  53. if (debug)
  54. DEV_DBG("[%08x] <= %08x\n",
  55. (u32)(unsigned long)(io->base + offset), value);
  56. return value;
  57. } /* dss_reg_r */
  58. EXPORT_SYMBOL(dss_reg_r);
  59. void dss_reg_dump(void __iomem *base, u32 length, const char *prefix,
  60. u32 debug)
  61. {
  62. if (debug)
  63. print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
  64. (void *)base, length, false);
  65. } /* dss_reg_dump */
  66. EXPORT_SYMBOL(dss_reg_dump);
  67. static struct resource *msm_dss_get_res_byname(struct platform_device *pdev,
  68. unsigned int type, const char *name)
  69. {
  70. struct resource *res = NULL;
  71. res = platform_get_resource_byname(pdev, type, name);
  72. if (!res)
  73. DEV_ERR("%s: '%s' resource not found\n", __func__, name);
  74. return res;
  75. } /* msm_dss_get_res_byname */
  76. int msm_dss_ioremap_byname(struct platform_device *pdev,
  77. struct dss_io_data *io_data, const char *name)
  78. {
  79. struct resource *res = NULL;
  80. if (!pdev || !io_data) {
  81. DEV_ERR("%pS->%s: invalid input\n",
  82. __builtin_return_address(0), __func__);
  83. return -EINVAL;
  84. }
  85. res = msm_dss_get_res_byname(pdev, IORESOURCE_MEM, name);
  86. if (!res) {
  87. DEV_ERR("%pS->%s: '%s' msm_dss_get_res_byname failed\n",
  88. __builtin_return_address(0), __func__, name);
  89. return -ENODEV;
  90. }
  91. io_data->len = (u32)resource_size(res);
  92. io_data->base = ioremap(res->start, io_data->len);
  93. if (!io_data->base) {
  94. DEV_ERR("%pS->%s: '%s' ioremap failed\n",
  95. __builtin_return_address(0), __func__, name);
  96. return -EIO;
  97. }
  98. return 0;
  99. } /* msm_dss_ioremap_byname */
  100. EXPORT_SYMBOL(msm_dss_ioremap_byname);
  101. void msm_dss_iounmap(struct dss_io_data *io_data)
  102. {
  103. if (!io_data) {
  104. DEV_ERR("%pS->%s: invalid input\n",
  105. __builtin_return_address(0), __func__);
  106. return;
  107. }
  108. if (io_data->base) {
  109. iounmap(io_data->base);
  110. io_data->base = NULL;
  111. }
  112. io_data->len = 0;
  113. } /* msm_dss_iounmap */
  114. EXPORT_SYMBOL(msm_dss_iounmap);
  115. int msm_dss_get_gpio_io_mem(const int gpio_pin, struct list_head *mem_list)
  116. {
  117. struct msm_io_mem_entry *io_mem;
  118. struct resource res;
  119. bool gpio_pin_status = false;
  120. int rc = 0;
  121. if (!gpio_is_valid(gpio_pin))
  122. return -EINVAL;
  123. io_mem = kzalloc(sizeof(struct msm_io_mem_entry), GFP_KERNEL);
  124. if (!io_mem)
  125. return -ENOMEM;
  126. gpio_pin_status = msm_gpio_get_pin_address(gpio_pin, &res);
  127. if (!gpio_pin_status) {
  128. rc = -ENODEV;
  129. goto parse_fail;
  130. }
  131. io_mem->base = res.start;
  132. io_mem->size = resource_size(&res);
  133. list_add(&io_mem->list, mem_list);
  134. return 0;
  135. parse_fail:
  136. kfree(io_mem);
  137. return rc;
  138. }
  139. EXPORT_SYMBOL(msm_dss_get_gpio_io_mem);
  140. int msm_dss_get_pmic_io_mem(struct platform_device *pdev,
  141. struct list_head *mem_list)
  142. {
  143. struct list_head temp_head;
  144. struct msm_io_mem_entry *io_mem;
  145. struct resource *res = NULL;
  146. struct property *prop;
  147. const __be32 *cur;
  148. int rc = 0;
  149. u32 val;
  150. INIT_LIST_HEAD(&temp_head);
  151. res = kzalloc(sizeof(struct resource), GFP_KERNEL);
  152. if (!res)
  153. return -ENOMEM;
  154. of_property_for_each_u32(pdev->dev.of_node, "qcom,pmic-arb-address",
  155. prop, cur, val) {
  156. rc = spmi_pmic_arb_map_address(&pdev->dev, val, res);
  157. if (rc < 0) {
  158. DEV_ERR("%pS - failed to map pmic address, rc:%d\n",
  159. __func__, rc);
  160. goto parse_fail;
  161. }
  162. io_mem = kzalloc(sizeof(struct msm_io_mem_entry), GFP_KERNEL);
  163. if (!io_mem) {
  164. rc = -ENOMEM;
  165. goto parse_fail;
  166. }
  167. io_mem->base = res->start;
  168. io_mem->size = resource_size(res);
  169. list_add(&io_mem->list, &temp_head);
  170. }
  171. list_splice(&temp_head, mem_list);
  172. goto end;
  173. parse_fail:
  174. msm_dss_clean_io_mem(&temp_head);
  175. end:
  176. kfree(res);
  177. return rc;
  178. }
  179. EXPORT_SYMBOL(msm_dss_get_pmic_io_mem);
  180. int msm_dss_get_io_mem(struct platform_device *pdev, struct list_head *mem_list)
  181. {
  182. struct list_head temp_head;
  183. struct msm_io_mem_entry *io_mem;
  184. struct resource *res = NULL;
  185. const char *reg_name, *exclude_reg_name;
  186. int i, j, rc = 0;
  187. int num_entry, num_exclude_entry;
  188. INIT_LIST_HEAD(&temp_head);
  189. num_entry = of_property_count_strings(pdev->dev.of_node,
  190. "reg-names");
  191. if (num_entry < 0)
  192. num_entry = 0;
  193. /*
  194. * check the dt property to know whether the platform device wants
  195. * to exclude any reg ranges from the IO list
  196. */
  197. num_exclude_entry = of_property_count_strings(pdev->dev.of_node,
  198. "qcom,sde-vm-exclude-reg-names");
  199. if (num_exclude_entry < 0)
  200. num_exclude_entry = 0;
  201. for (i = 0; i < num_entry; i++) {
  202. bool exclude = false;
  203. of_property_read_string_index(pdev->dev.of_node,
  204. "reg-names", i, &reg_name);
  205. for (j = 0; j < num_exclude_entry; j++) {
  206. of_property_read_string_index(pdev->dev.of_node,
  207. "qcom,sde-vm-exclude-reg-names", j,
  208. &exclude_reg_name);
  209. if (!strcmp(reg_name, exclude_reg_name)) {
  210. exclude = true;
  211. break;
  212. }
  213. }
  214. if (exclude)
  215. continue;
  216. res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  217. reg_name);
  218. if (!res)
  219. break;
  220. io_mem = kzalloc(sizeof(*io_mem), GFP_KERNEL);
  221. if (!io_mem) {
  222. msm_dss_clean_io_mem(&temp_head);
  223. rc = -ENOMEM;
  224. goto parse_fail;
  225. }
  226. io_mem->base = res->start;
  227. io_mem->size = resource_size(res);
  228. list_add(&io_mem->list, &temp_head);
  229. }
  230. list_splice(&temp_head, mem_list);
  231. return 0;
  232. parse_fail:
  233. msm_dss_clean_io_mem(&temp_head);
  234. return rc;
  235. }
  236. EXPORT_SYMBOL(msm_dss_get_io_mem);
  237. void msm_dss_clean_io_mem(struct list_head *mem_list)
  238. {
  239. struct msm_io_mem_entry *pos, *tmp;
  240. list_for_each_entry_safe(pos, tmp, mem_list, list) {
  241. list_del(&pos->list);
  242. kfree(pos);
  243. }
  244. }
  245. EXPORT_SYMBOL(msm_dss_clean_io_mem);
  246. int msm_dss_get_io_irq(struct platform_device *pdev, struct list_head *irq_list,
  247. u32 label)
  248. {
  249. struct msm_io_irq_entry *io_irq;
  250. int irq;
  251. irq = platform_get_irq(pdev, 0);
  252. if (irq < 0) {
  253. pr_err("invalid IRQ\n");
  254. return irq;
  255. }
  256. io_irq = kzalloc(sizeof(*io_irq), GFP_KERNEL);
  257. if (!io_irq)
  258. return -ENOMEM;
  259. io_irq->label = label;
  260. io_irq->irq_num = irq;
  261. list_add(&io_irq->list, irq_list);
  262. return 0;
  263. }
  264. EXPORT_SYMBOL(msm_dss_get_io_irq);
  265. void msm_dss_clean_io_irq(struct list_head *irq_list)
  266. {
  267. struct msm_io_irq_entry *pos, *tmp;
  268. list_for_each_entry_safe(pos, tmp, irq_list, list) {
  269. list_del(&pos->list);
  270. kfree(pos);
  271. }
  272. }
  273. EXPORT_SYMBOL(msm_dss_clean_io_irq);
  274. int msm_dss_get_vreg(struct device *dev, struct dss_vreg *in_vreg,
  275. int num_vreg, int enable)
  276. {
  277. int i = 0, rc = 0;
  278. struct dss_vreg *curr_vreg = NULL;
  279. if (!in_vreg || !num_vreg)
  280. return rc;
  281. if (enable) {
  282. for (i = 0; i < num_vreg; i++) {
  283. curr_vreg = &in_vreg[i];
  284. curr_vreg->vreg = regulator_get(dev,
  285. curr_vreg->vreg_name);
  286. rc = PTR_ERR_OR_ZERO(curr_vreg->vreg);
  287. if (rc) {
  288. DEV_ERR("%pS->%s: %s get failed. rc=%d\n",
  289. __builtin_return_address(0), __func__,
  290. curr_vreg->vreg_name, rc);
  291. curr_vreg->vreg = NULL;
  292. goto vreg_get_fail;
  293. }
  294. }
  295. } else {
  296. for (i = num_vreg-1; i >= 0; i--) {
  297. curr_vreg = &in_vreg[i];
  298. if (curr_vreg->vreg) {
  299. regulator_put(curr_vreg->vreg);
  300. curr_vreg->vreg = NULL;
  301. }
  302. }
  303. }
  304. return 0;
  305. vreg_get_fail:
  306. for (i--; i >= 0; i--) {
  307. curr_vreg = &in_vreg[i];
  308. regulator_set_load(curr_vreg->vreg, 0);
  309. regulator_put(curr_vreg->vreg);
  310. curr_vreg->vreg = NULL;
  311. }
  312. return rc;
  313. } /* msm_dss_get_vreg */
  314. EXPORT_SYMBOL(msm_dss_get_vreg);
  315. static bool msm_dss_is_hw_controlled(struct dss_vreg in_vreg)
  316. {
  317. u32 mode = 0;
  318. char const *regulator_gdsc = "gdsc";
  319. /*
  320. * For gdsc-regulator devices only, REGULATOR_MODE_FAST specifies that
  321. * the GDSC is in HW controlled mode.
  322. */
  323. mode = regulator_get_mode(in_vreg.vreg);
  324. if (!strcmp(regulator_gdsc, in_vreg.vreg_name) &&
  325. mode == REGULATOR_MODE_FAST) {
  326. DEV_DBG("%pS->%s: %s is HW controlled\n",
  327. __builtin_return_address(0), __func__,
  328. in_vreg.vreg_name);
  329. return true;
  330. }
  331. return false;
  332. }
  333. int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable)
  334. {
  335. int i = 0, rc = 0;
  336. bool need_sleep;
  337. if (enable) {
  338. for (i = 0; i < num_vreg; i++) {
  339. rc = PTR_ERR_OR_ZERO(in_vreg[i].vreg);
  340. if (rc) {
  341. DEV_ERR("%pS->%s: %s regulator error. rc=%d\n",
  342. __builtin_return_address(0), __func__,
  343. in_vreg[i].vreg_name, rc);
  344. goto vreg_set_opt_mode_fail;
  345. }
  346. if (msm_dss_is_hw_controlled(in_vreg[i]))
  347. continue;
  348. need_sleep = !regulator_is_enabled(in_vreg[i].vreg);
  349. if (in_vreg[i].pre_on_sleep && need_sleep)
  350. usleep_range(in_vreg[i].pre_on_sleep * 1000,
  351. (in_vreg[i].pre_on_sleep * 1000) + 10);
  352. rc = regulator_set_load(in_vreg[i].vreg,
  353. in_vreg[i].enable_load);
  354. if (rc < 0) {
  355. DEV_ERR("%pS->%s: %s set opt m fail\n",
  356. __builtin_return_address(0), __func__,
  357. in_vreg[i].vreg_name);
  358. goto vreg_set_opt_mode_fail;
  359. }
  360. if (regulator_count_voltages(in_vreg[i].vreg) > 0)
  361. regulator_set_voltage(in_vreg[i].vreg,
  362. in_vreg[i].min_voltage,
  363. in_vreg[i].max_voltage);
  364. rc = regulator_enable(in_vreg[i].vreg);
  365. if (in_vreg[i].post_on_sleep && need_sleep)
  366. usleep_range(in_vreg[i].post_on_sleep * 1000,
  367. (in_vreg[i].post_on_sleep * 1000) + 10);
  368. if (rc < 0) {
  369. DEV_ERR("%pS->%s: %s enable failed\n",
  370. __builtin_return_address(0), __func__,
  371. in_vreg[i].vreg_name);
  372. goto disable_vreg;
  373. }
  374. }
  375. } else {
  376. for (i = num_vreg-1; i >= 0; i--) {
  377. if (msm_dss_is_hw_controlled(in_vreg[i]))
  378. continue;
  379. if (in_vreg[i].pre_off_sleep)
  380. usleep_range(in_vreg[i].pre_off_sleep * 1000,
  381. (in_vreg[i].pre_off_sleep * 1000) + 10);
  382. regulator_disable(in_vreg[i].vreg);
  383. if (in_vreg[i].post_off_sleep)
  384. usleep_range(in_vreg[i].post_off_sleep * 1000,
  385. (in_vreg[i].post_off_sleep * 1000) + 10);
  386. regulator_set_load(in_vreg[i].vreg,
  387. in_vreg[i].disable_load);
  388. if (regulator_count_voltages(in_vreg[i].vreg) > 0)
  389. regulator_set_voltage(in_vreg[i].vreg, 0,
  390. in_vreg[i].max_voltage);
  391. }
  392. }
  393. return rc;
  394. disable_vreg:
  395. regulator_set_load(in_vreg[i].vreg, in_vreg[i].disable_load);
  396. vreg_set_opt_mode_fail:
  397. for (i--; i >= 0; i--) {
  398. if (in_vreg[i].pre_off_sleep)
  399. usleep_range(in_vreg[i].pre_off_sleep * 1000,
  400. (in_vreg[i].pre_off_sleep * 1000) + 10);
  401. regulator_disable(in_vreg[i].vreg);
  402. if (in_vreg[i].post_off_sleep)
  403. usleep_range(in_vreg[i].post_off_sleep * 1000,
  404. (in_vreg[i].post_off_sleep * 1000) + 10);
  405. regulator_set_load(in_vreg[i].vreg,
  406. in_vreg[i].disable_load);
  407. }
  408. return rc;
  409. } /* msm_dss_enable_vreg */
  410. EXPORT_SYMBOL(msm_dss_enable_vreg);
  411. int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable)
  412. {
  413. int i = 0, rc = 0;
  414. if (enable) {
  415. for (i = 0; i < num_gpio; i++) {
  416. DEV_DBG("%pS->%s: %s enable\n",
  417. __builtin_return_address(0), __func__,
  418. in_gpio[i].gpio_name);
  419. rc = gpio_request(in_gpio[i].gpio,
  420. in_gpio[i].gpio_name);
  421. if (rc < 0) {
  422. DEV_ERR("%pS->%s: %s enable failed\n",
  423. __builtin_return_address(0), __func__,
  424. in_gpio[i].gpio_name);
  425. goto disable_gpio;
  426. }
  427. gpio_set_value(in_gpio[i].gpio, in_gpio[i].value);
  428. }
  429. } else {
  430. for (i = num_gpio-1; i >= 0; i--) {
  431. DEV_DBG("%pS->%s: %s disable\n",
  432. __builtin_return_address(0), __func__,
  433. in_gpio[i].gpio_name);
  434. if (in_gpio[i].gpio)
  435. gpio_free(in_gpio[i].gpio);
  436. }
  437. }
  438. return rc;
  439. disable_gpio:
  440. for (i--; i >= 0; i--)
  441. if (in_gpio[i].gpio)
  442. gpio_free(in_gpio[i].gpio);
  443. return rc;
  444. } /* msm_dss_enable_gpio */
  445. EXPORT_SYMBOL(msm_dss_enable_gpio);
  446. void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
  447. {
  448. int i;
  449. for (i = num_clk - 1; i >= 0; i--) {
  450. if (clk_arry[i].clk)
  451. clk_put(clk_arry[i].clk);
  452. clk_arry[i].clk = NULL;
  453. }
  454. } /* msm_dss_put_clk */
  455. EXPORT_SYMBOL(msm_dss_put_clk);
  456. int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
  457. {
  458. int i, rc = 0;
  459. for (i = 0; i < num_clk; i++) {
  460. clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
  461. rc = PTR_ERR_OR_ZERO(clk_arry[i].clk);
  462. if (rc) {
  463. DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
  464. __builtin_return_address(0), __func__,
  465. clk_arry[i].clk_name, rc);
  466. goto error;
  467. }
  468. }
  469. return rc;
  470. error:
  471. for (i--; i >= 0; i--) {
  472. if (clk_arry[i].clk)
  473. clk_put(clk_arry[i].clk);
  474. clk_arry[i].clk = NULL;
  475. }
  476. return rc;
  477. } /* msm_dss_get_clk */
  478. EXPORT_SYMBOL(msm_dss_get_clk);
  479. int msm_dss_mmrm_register(struct device *dev, struct dss_module_power *mp,
  480. int (*cb_fnc)(struct mmrm_client_notifier_data *data), void *phandle,
  481. bool *mmrm_enable)
  482. {
  483. int i, rc = 0;
  484. struct dss_clk *clk_array = mp->clk_config;
  485. int num_clk = mp->num_clk;
  486. *mmrm_enable = false;
  487. for (i = 0; i < num_clk; i++) {
  488. struct mmrm_client_desc desc;
  489. char *name = (char *)desc.client_info.desc.name;
  490. struct dss_clk_mmrm_cb *mmrm_cb_data;
  491. if (clk_array[i].type != DSS_CLK_MMRM)
  492. continue;
  493. desc.client_type = MMRM_CLIENT_CLOCK;
  494. desc.client_info.desc.client_domain =
  495. MMRM_CLIENT_DOMAIN_DISPLAY;
  496. desc.client_info.desc.client_id =
  497. clk_array[i].mmrm.clk_id;
  498. strlcpy(name, clk_array[i].clk_name,
  499. sizeof(desc.client_info.desc.name));
  500. desc.client_info.desc.clk = clk_array[i].clk;
  501. desc.priority = MMRM_CLIENT_PRIOR_LOW;
  502. /* init callback wait queue */
  503. init_waitqueue_head(&clk_array[i].mmrm.mmrm_cb_wq);
  504. /* register the callback */
  505. mmrm_cb_data = kzalloc(sizeof(*mmrm_cb_data), GFP_KERNEL);
  506. if (!mmrm_cb_data)
  507. return -ENOMEM;
  508. mmrm_cb_data->phandle = phandle;
  509. mmrm_cb_data->clk = &clk_array[i];
  510. clk_array[i].mmrm.mmrm_cb_data = mmrm_cb_data;
  511. desc.pvt_data = (void *)mmrm_cb_data;
  512. desc.notifier_callback_fn = cb_fnc;
  513. clk_array[i].mmrm.mmrm_client = mmrm_client_register(&desc);
  514. if (!clk_array[i].mmrm.mmrm_client) {
  515. DEV_ERR("mmrm register error\n");
  516. DEV_ERR("clk[%d] type:%d id:%d name:%s\n",
  517. i, desc.client_type,
  518. desc.client_info.desc.client_id,
  519. desc.client_info.desc.name);
  520. rc = -EINVAL;
  521. } else {
  522. *mmrm_enable = true;
  523. DEV_DBG("mmrm register id:%d name=%s prio:%d\n",
  524. desc.client_info.desc.client_id,
  525. desc.client_info.desc.name,
  526. desc.priority);
  527. }
  528. }
  529. return rc;
  530. } /* msm_dss_mmrm_register */
  531. EXPORT_SYMBOL(msm_dss_mmrm_register);
  532. void msm_dss_mmrm_deregister(struct device *dev,
  533. struct dss_module_power *mp)
  534. {
  535. int i, ret;
  536. struct dss_clk *clk_array = mp->clk_config;
  537. int num_clk = mp->num_clk;
  538. for (i = 0; i < num_clk; i++) {
  539. if (clk_array[i].type != DSS_CLK_MMRM)
  540. continue;
  541. ret = mmrm_client_deregister(
  542. clk_array[i].mmrm.mmrm_client);
  543. if (ret) {
  544. DEV_DBG("fail mmrm deregister ret:%d clk:%s\n",
  545. ret, clk_array[i].clk_name);
  546. continue;
  547. }
  548. kfree(clk_array[i].mmrm.mmrm_cb_data);
  549. DEV_DBG("msm dss mmrm deregister clk[%d] name=%s\n",
  550. i, clk_array[i].clk_name);
  551. }
  552. } /* msm_dss_mmrm_deregister */
  553. EXPORT_SYMBOL(msm_dss_mmrm_deregister);
  554. int msm_dss_single_clk_set_rate(struct dss_clk *clk)
  555. {
  556. int rc = 0;
  557. if (!clk) {
  558. DEV_ERR("invalid clk struct\n");
  559. return -EINVAL;
  560. }
  561. DEV_DBG("%pS->%s: set_rate '%s'\n",
  562. __builtin_return_address(0), __func__,
  563. clk->clk_name);
  564. /* When MMRM enabled, avoid setting the rate for the branch clock,
  565. * MMRM is always expecting the vote from the SRC clock only
  566. */
  567. if (!strcmp(clk->clk_name, "branch_clk"))
  568. return 0;
  569. if (clk->type != DSS_CLK_AHB &&
  570. clk->type != DSS_CLK_MMRM &&
  571. !clk->mmrm.flags) {
  572. rc = clk_set_rate(clk->clk, clk->rate);
  573. if (rc)
  574. DEV_ERR("%pS->%s: %s failed. rc=%d\n",
  575. __builtin_return_address(0),
  576. __func__,
  577. clk->clk_name, rc);
  578. } else if (clk->type == DSS_CLK_MMRM) {
  579. struct mmrm_client_data client_data;
  580. memset(&client_data, 0, sizeof(client_data));
  581. client_data.num_hw_blocks = 1;
  582. client_data.flags = clk->mmrm.flags;
  583. rc = mmrm_client_set_value(
  584. clk->mmrm.mmrm_client,
  585. &client_data,
  586. clk->rate);
  587. if (rc) {
  588. DEV_ERR("%pS->%s: %s mmrm setval fail rc:%d\n",
  589. __builtin_return_address(0),
  590. __func__,
  591. clk->clk_name, rc);
  592. } else if (clk->mmrm.mmrm_requested_clk &&
  593. (clk->rate <= clk->mmrm.mmrm_requested_clk)) {
  594. /* notify any pending clk request from mmrm cb,
  595. * new clk must be less or equal than callback
  596. * request, set requested clock to zero to
  597. * succeed mmrm callback
  598. */
  599. clk->mmrm.mmrm_requested_clk = 0;
  600. /* notify callback */
  601. wake_up_all(&clk->mmrm.mmrm_cb_wq);
  602. }
  603. }
  604. return rc;
  605. } /* msm_dss_single_clk_set_rate */
  606. EXPORT_SYMBOL(msm_dss_single_clk_set_rate);
  607. int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
  608. {
  609. int i, rc = 0;
  610. for (i = 0; i < num_clk; i++) {
  611. if (clk_arry[i].clk) {
  612. rc = msm_dss_single_clk_set_rate(&clk_arry[i]);
  613. if (rc)
  614. break;
  615. } else {
  616. DEV_ERR("%pS->%s: '%s' is not available\n",
  617. __builtin_return_address(0), __func__,
  618. clk_arry[i].clk_name);
  619. rc = -EPERM;
  620. break;
  621. }
  622. }
  623. return rc;
  624. } /* msm_dss_clk_set_rate */
  625. EXPORT_SYMBOL(msm_dss_clk_set_rate);
  626. int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
  627. {
  628. int i, rc = 0;
  629. if (enable) {
  630. for (i = 0; i < num_clk; i++) {
  631. DEV_DBG("%pS->%s: enable '%s'\n",
  632. __builtin_return_address(0), __func__,
  633. clk_arry[i].clk_name);
  634. if (clk_arry[i].clk) {
  635. rc = clk_prepare_enable(clk_arry[i].clk);
  636. if (rc)
  637. DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
  638. __builtin_return_address(0),
  639. __func__,
  640. clk_arry[i].clk_name, rc);
  641. } else {
  642. DEV_ERR("%pS->%s: '%s' is not available\n",
  643. __builtin_return_address(0), __func__,
  644. clk_arry[i].clk_name);
  645. rc = -EPERM;
  646. }
  647. if (rc) {
  648. msm_dss_enable_clk(clk_arry, i, false);
  649. break;
  650. }
  651. }
  652. } else {
  653. for (i = num_clk - 1; i >= 0; i--) {
  654. DEV_DBG("%pS->%s: disable '%s'\n",
  655. __builtin_return_address(0), __func__,
  656. clk_arry[i].clk_name);
  657. if (clk_arry[i].clk)
  658. clk_disable_unprepare(clk_arry[i].clk);
  659. else
  660. DEV_ERR("%pS->%s: '%s' is not available\n",
  661. __builtin_return_address(0), __func__,
  662. clk_arry[i].clk_name);
  663. }
  664. }
  665. return rc;
  666. } /* msm_dss_enable_clk */
  667. EXPORT_SYMBOL(msm_dss_enable_clk);
  668. int sde_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr,
  669. uint8_t reg_offset, uint8_t *read_buf)
  670. {
  671. struct i2c_msg msgs[2];
  672. int ret = -1;
  673. pr_debug("%s: reading from slave_addr=[%x] and offset=[%x]\n",
  674. __func__, slave_addr, reg_offset);
  675. msgs[0].addr = slave_addr >> 1;
  676. msgs[0].flags = 0;
  677. msgs[0].buf = &reg_offset;
  678. msgs[0].len = 1;
  679. msgs[1].addr = slave_addr >> 1;
  680. msgs[1].flags = I2C_M_RD;
  681. msgs[1].buf = read_buf;
  682. msgs[1].len = 1;
  683. ret = i2c_transfer(client->adapter, msgs, 2);
  684. if (ret < 1) {
  685. pr_err("%s: I2C READ FAILED=[%d]\n", __func__, ret);
  686. return -EACCES;
  687. }
  688. pr_debug("%s: i2c buf is [%x]\n", __func__, *read_buf);
  689. return 0;
  690. }
  691. EXPORT_SYMBOL(sde_i2c_byte_read);
  692. int sde_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr,
  693. uint8_t reg_offset, uint8_t *value)
  694. {
  695. struct i2c_msg msgs[1];
  696. uint8_t data[2];
  697. int status = -EACCES;
  698. pr_debug("%s: writing from slave_addr=[%x] and offset=[%x]\n",
  699. __func__, slave_addr, reg_offset);
  700. data[0] = reg_offset;
  701. data[1] = *value;
  702. msgs[0].addr = slave_addr >> 1;
  703. msgs[0].flags = 0;
  704. msgs[0].len = 2;
  705. msgs[0].buf = data;
  706. status = i2c_transfer(client->adapter, msgs, 1);
  707. if (status < 1) {
  708. pr_err("I2C WRITE FAILED=[%d]\n", status);
  709. return -EACCES;
  710. }
  711. pr_debug("%s: I2C write status=%x\n", __func__, status);
  712. return status;
  713. }
  714. EXPORT_SYMBOL(sde_i2c_byte_write);