1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
From 0fb08a02baf5114fd3bdbc5aa92d6a6cd6d5ef3f Mon Sep 17 00:00:00 2001
From: Manoharan Vijaya Raghavan <mraghava@codeaurora.org>
Date: Tue, 24 Jan 2017 20:58:46 +0530
Subject: ipq: scm: TZ don't need clock to be enabled/disabled for ipq
When SCM was made as a platform driver, clock management was
addedfor firmware calls. This is not required for IPQ.
Change-Id: I3d29fafe0266e51f708f2718bab03907078b0f4d
Signed-off-by: Manoharan Vijaya Raghavan <mraghava@codeaurora.org>
---
drivers/firmware/qcom_scm.c | 87 +++++++++++++++++++++++++++++----------------
1 file changed, 57 insertions(+), 30 deletions(-)
(limited to 'drivers/firmware/qcom_scm.c')
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -28,12 +28,15 @@
#include "qcom_scm.h"
+#define SCM_NOCLK 1
+
struct qcom_scm {
struct device *dev;
struct clk *core_clk;
struct clk *iface_clk;
struct clk *bus_clk;
struct reset_controller_dev reset;
+ int is_clkdisabled;
};
static struct qcom_scm *__scm;
@@ -42,6 +45,9 @@ static int qcom_scm_clk_enable(void)
{
int ret;
+ if (__scm->is_clkdisabled)
+ return 0;
+
ret = clk_prepare_enable(__scm->core_clk);
if (ret)
goto bail;
@@ -66,6 +72,9 @@ bail:
static void qcom_scm_clk_disable(void)
{
+ if (__scm->is_clkdisabled)
+ return;
+
clk_disable_unprepare(__scm->core_clk);
clk_disable_unprepare(__scm->iface_clk);
clk_disable_unprepare(__scm->bus_clk);
@@ -320,37 +329,61 @@ bool qcom_scm_is_available(void)
}
EXPORT_SYMBOL(qcom_scm_is_available);
+static const struct of_device_id qcom_scm_dt_match[] = {
+ { .compatible = "qcom,scm-apq8064",},
+ { .compatible = "qcom,scm-msm8660",},
+ { .compatible = "qcom,scm-msm8960",},
+ { .compatible = "qcom,scm-ipq807x", .data = (void *)SCM_NOCLK },
+ { .compatible = "qcom,scm-ipq806x", .data = (void *)SCM_NOCLK },
+ { .compatible = "qcom,scm-ipq40xx", .data = (void *)SCM_NOCLK },
+ { .compatible = "qcom,scm-msm8960",},
+ { .compatible = "qcom,scm-msm8960",},
+ { .compatible = "qcom,scm",},
+ {}
+};
+
static int qcom_scm_probe(struct platform_device *pdev)
{
struct qcom_scm *scm;
+ const struct of_device_id *id;
int ret;
scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
if (!scm)
return -ENOMEM;
- scm->core_clk = devm_clk_get(&pdev->dev, "core");
- if (IS_ERR(scm->core_clk)) {
- if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
- return PTR_ERR(scm->core_clk);
+ id = of_match_device(qcom_scm_dt_match, &pdev->dev);
+ if (id)
+ scm->is_clkdisabled = (unsigned int)id->data;
+ else
+ scm->is_clkdisabled = 0;
+
+ if (!(scm->is_clkdisabled)) {
+
+ scm->core_clk = devm_clk_get(&pdev->dev, "core");
+ if (IS_ERR(scm->core_clk)) {
+ if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
+ return PTR_ERR(scm->core_clk);
- scm->core_clk = NULL;
- }
-
- if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
- scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
- if (IS_ERR(scm->iface_clk)) {
- if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to acquire iface clk\n");
- return PTR_ERR(scm->iface_clk);
+ scm->core_clk = NULL;
}
- scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
- if (IS_ERR(scm->bus_clk)) {
- if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to acquire bus clk\n");
- return PTR_ERR(scm->bus_clk);
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
+ scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
+ if (IS_ERR(scm->iface_clk)) {
+ if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "failed to acquire iface clk\n");
+ return PTR_ERR(scm->iface_clk);
+ }
+
+ scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
+ if (IS_ERR(scm->bus_clk)) {
+ if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "failed to acquire bus clk\n");
+ return PTR_ERR(scm->bus_clk);
+ }
}
+
}
scm->reset.ops = &qcom_scm_pas_reset_ops;
@@ -358,10 +391,12 @@ static int qcom_scm_probe(struct platfor
scm->reset.of_node = pdev->dev.of_node;
reset_controller_register(&scm->reset);
- /* vote for max clk rate for highest performance */
- ret = clk_set_rate(scm->core_clk, INT_MAX);
- if (ret)
- return ret;
+ if (!(scm->is_clkdisabled)) {
+ /* vote for max clk rate for highest performance */
+ ret = clk_set_rate(scm->core_clk, INT_MAX);
+ if (ret)
+ return ret;
+ }
__scm = scm;
__scm->dev = &pdev->dev;
@@ -371,14 +406,6 @@ static int qcom_scm_probe(struct platfor
return 0;
}
-static const struct of_device_id qcom_scm_dt_match[] = {
- { .compatible = "qcom,scm-apq8064",},
- { .compatible = "qcom,scm-msm8660",},
- { .compatible = "qcom,scm-msm8960",},
- { .compatible = "qcom,scm",},
- {}
-};
-
static struct platform_driver qcom_scm_driver = {
.driver = {
.name = "qcom_scm",
|