1 /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation.
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.
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.
14 #include <linux/clk.h>
15 #include <linux/clk/clk-conf.h>
16 #include <linux/err.h>
17 #include <linux/delay.h>
19 #include "dpu_io_util.h"
21 void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
25 for (i = num_clk - 1; i >= 0; i--) {
27 clk_put(clk_arry[i].clk);
28 clk_arry[i].clk = NULL;
32 int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
36 for (i = 0; i < num_clk; i++) {
37 clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
38 rc = PTR_ERR_OR_ZERO(clk_arry[i].clk);
40 DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
41 __builtin_return_address(0), __func__,
42 clk_arry[i].clk_name, rc);
50 for (i--; i >= 0; i--) {
52 clk_put(clk_arry[i].clk);
53 clk_arry[i].clk = NULL;
59 int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
63 for (i = 0; i < num_clk; i++) {
64 if (clk_arry[i].clk) {
65 if (clk_arry[i].type != DSS_CLK_AHB) {
66 DEV_DBG("%pS->%s: '%s' rate %ld\n",
67 __builtin_return_address(0), __func__,
70 rc = clk_set_rate(clk_arry[i].clk,
73 DEV_ERR("%pS->%s: %s failed. rc=%d\n",
74 __builtin_return_address(0),
76 clk_arry[i].clk_name, rc);
81 DEV_ERR("%pS->%s: '%s' is not available\n",
82 __builtin_return_address(0), __func__,
83 clk_arry[i].clk_name);
92 int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
97 for (i = 0; i < num_clk; i++) {
98 DEV_DBG("%pS->%s: enable '%s'\n",
99 __builtin_return_address(0), __func__,
100 clk_arry[i].clk_name);
101 if (clk_arry[i].clk) {
102 rc = clk_prepare_enable(clk_arry[i].clk);
104 DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
105 __builtin_return_address(0),
107 clk_arry[i].clk_name, rc);
109 DEV_ERR("%pS->%s: '%s' is not available\n",
110 __builtin_return_address(0), __func__,
111 clk_arry[i].clk_name);
116 msm_dss_enable_clk(&clk_arry[i],
122 for (i = num_clk - 1; i >= 0; i--) {
123 DEV_DBG("%pS->%s: disable '%s'\n",
124 __builtin_return_address(0), __func__,
125 clk_arry[i].clk_name);
128 clk_disable_unprepare(clk_arry[i].clk);
130 DEV_ERR("%pS->%s: '%s' is not available\n",
131 __builtin_return_address(0), __func__,
132 clk_arry[i].clk_name);
139 int msm_dss_parse_clock(struct platform_device *pdev,
140 struct dss_module_power *mp)
143 const char *clock_name;
150 num_clk = of_property_count_strings(pdev->dev.of_node, "clock-names");
152 pr_debug("clocks are not defined\n");
156 mp->clk_config = devm_kcalloc(&pdev->dev,
157 num_clk, sizeof(struct dss_clk),
162 for (i = 0; i < num_clk; i++) {
163 rc = of_property_read_string_index(pdev->dev.of_node,
167 dev_err(&pdev->dev, "Failed to get clock name for %d\n",
171 strlcpy(mp->clk_config[i].clk_name, clock_name,
172 sizeof(mp->clk_config[i].clk_name));
174 mp->clk_config[i].type = DSS_CLK_AHB;
177 rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, num_clk);
179 dev_err(&pdev->dev, "Failed to get clock refs %d\n", rc);
183 rc = of_clk_set_defaults(pdev->dev.of_node, false);
185 dev_err(&pdev->dev, "Failed to set clock defaults %d\n", rc);
189 for (i = 0; i < num_clk; i++) {
190 u32 rate = clk_get_rate(mp->clk_config[i].clk);
193 mp->clk_config[i].rate = rate;
194 mp->clk_config[i].type = DSS_CLK_PCLK;
197 mp->num_clk = num_clk;
201 msm_dss_put_clk(mp->clk_config, num_clk);