sde_io_util.c 19 KB

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