1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4 * Copyright 2016-2022 HabanaLabs, Ltd.
5 * All Rights Reserved.
6 */
7
8 #include "goyaP.h"
9
goya_set_pll_profile(struct hl_device * hdev,enum hl_pll_frequency freq)10 void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
11 {
12 struct goya_device *goya = hdev->asic_specific;
13
14 if (!hdev->pdev)
15 return;
16
17 switch (freq) {
18 case PLL_HIGH:
19 hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, hdev->high_pll);
20 hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, hdev->high_pll);
21 hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, hdev->high_pll);
22 break;
23 case PLL_LOW:
24 hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, GOYA_PLL_FREQ_LOW);
25 hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, GOYA_PLL_FREQ_LOW);
26 hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, GOYA_PLL_FREQ_LOW);
27 break;
28 case PLL_LAST:
29 hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, goya->mme_clk);
30 hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, goya->tpc_clk);
31 hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, goya->ic_clk);
32 break;
33 default:
34 dev_err(hdev->dev, "unknown frequency setting\n");
35 }
36 }
37
mme_clk_show(struct device * dev,struct device_attribute * attr,char * buf)38 static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
39 char *buf)
40 {
41 struct hl_device *hdev = dev_get_drvdata(dev);
42 long value;
43
44 if (!hl_device_operational(hdev, NULL))
45 return -ENODEV;
46
47 value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, false);
48
49 if (value < 0)
50 return value;
51
52 return sprintf(buf, "%lu\n", value);
53 }
54
mme_clk_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)55 static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
56 const char *buf, size_t count)
57 {
58 struct hl_device *hdev = dev_get_drvdata(dev);
59 struct goya_device *goya = hdev->asic_specific;
60 int rc;
61 long value;
62
63 if (!hl_device_operational(hdev, NULL)) {
64 count = -ENODEV;
65 goto fail;
66 }
67
68 if (goya->pm_mng_profile == PM_AUTO) {
69 count = -EPERM;
70 goto fail;
71 }
72
73 rc = kstrtoul(buf, 0, &value);
74
75 if (rc) {
76 count = -EINVAL;
77 goto fail;
78 }
79
80 hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, value);
81 goya->mme_clk = value;
82
83 fail:
84 return count;
85 }
86
tpc_clk_show(struct device * dev,struct device_attribute * attr,char * buf)87 static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
88 char *buf)
89 {
90 struct hl_device *hdev = dev_get_drvdata(dev);
91 long value;
92
93 if (!hl_device_operational(hdev, NULL))
94 return -ENODEV;
95
96 value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, false);
97
98 if (value < 0)
99 return value;
100
101 return sprintf(buf, "%lu\n", value);
102 }
103
tpc_clk_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)104 static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
105 const char *buf, size_t count)
106 {
107 struct hl_device *hdev = dev_get_drvdata(dev);
108 struct goya_device *goya = hdev->asic_specific;
109 int rc;
110 long value;
111
112 if (!hl_device_operational(hdev, NULL)) {
113 count = -ENODEV;
114 goto fail;
115 }
116
117 if (goya->pm_mng_profile == PM_AUTO) {
118 count = -EPERM;
119 goto fail;
120 }
121
122 rc = kstrtoul(buf, 0, &value);
123
124 if (rc) {
125 count = -EINVAL;
126 goto fail;
127 }
128
129 hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, value);
130 goya->tpc_clk = value;
131
132 fail:
133 return count;
134 }
135
ic_clk_show(struct device * dev,struct device_attribute * attr,char * buf)136 static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
137 char *buf)
138 {
139 struct hl_device *hdev = dev_get_drvdata(dev);
140 long value;
141
142 if (!hl_device_operational(hdev, NULL))
143 return -ENODEV;
144
145 value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, false);
146
147 if (value < 0)
148 return value;
149
150 return sprintf(buf, "%lu\n", value);
151 }
152
ic_clk_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)153 static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
154 const char *buf, size_t count)
155 {
156 struct hl_device *hdev = dev_get_drvdata(dev);
157 struct goya_device *goya = hdev->asic_specific;
158 int rc;
159 long value;
160
161 if (!hl_device_operational(hdev, NULL)) {
162 count = -ENODEV;
163 goto fail;
164 }
165
166 if (goya->pm_mng_profile == PM_AUTO) {
167 count = -EPERM;
168 goto fail;
169 }
170
171 rc = kstrtoul(buf, 0, &value);
172
173 if (rc) {
174 count = -EINVAL;
175 goto fail;
176 }
177
178 hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, value);
179 goya->ic_clk = value;
180
181 fail:
182 return count;
183 }
184
mme_clk_curr_show(struct device * dev,struct device_attribute * attr,char * buf)185 static ssize_t mme_clk_curr_show(struct device *dev,
186 struct device_attribute *attr, char *buf)
187 {
188 struct hl_device *hdev = dev_get_drvdata(dev);
189 long value;
190
191 if (!hl_device_operational(hdev, NULL))
192 return -ENODEV;
193
194 value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, true);
195
196 if (value < 0)
197 return value;
198
199 return sprintf(buf, "%lu\n", value);
200 }
201
tpc_clk_curr_show(struct device * dev,struct device_attribute * attr,char * buf)202 static ssize_t tpc_clk_curr_show(struct device *dev,
203 struct device_attribute *attr, char *buf)
204 {
205 struct hl_device *hdev = dev_get_drvdata(dev);
206 long value;
207
208 if (!hl_device_operational(hdev, NULL))
209 return -ENODEV;
210
211 value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, true);
212
213 if (value < 0)
214 return value;
215
216 return sprintf(buf, "%lu\n", value);
217 }
218
ic_clk_curr_show(struct device * dev,struct device_attribute * attr,char * buf)219 static ssize_t ic_clk_curr_show(struct device *dev,
220 struct device_attribute *attr, char *buf)
221 {
222 struct hl_device *hdev = dev_get_drvdata(dev);
223 long value;
224
225 if (!hl_device_operational(hdev, NULL))
226 return -ENODEV;
227
228 value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, true);
229
230 if (value < 0)
231 return value;
232
233 return sprintf(buf, "%lu\n", value);
234 }
235
pm_mng_profile_show(struct device * dev,struct device_attribute * attr,char * buf)236 static ssize_t pm_mng_profile_show(struct device *dev,
237 struct device_attribute *attr, char *buf)
238 {
239 struct hl_device *hdev = dev_get_drvdata(dev);
240 struct goya_device *goya = hdev->asic_specific;
241
242 if (!hl_device_operational(hdev, NULL))
243 return -ENODEV;
244
245 return sprintf(buf, "%s\n",
246 (goya->pm_mng_profile == PM_AUTO) ? "auto" :
247 (goya->pm_mng_profile == PM_MANUAL) ? "manual" :
248 "unknown");
249 }
250
pm_mng_profile_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)251 static ssize_t pm_mng_profile_store(struct device *dev,
252 struct device_attribute *attr, const char *buf, size_t count)
253 {
254 struct hl_device *hdev = dev_get_drvdata(dev);
255 struct goya_device *goya = hdev->asic_specific;
256
257 if (!hl_device_operational(hdev, NULL)) {
258 count = -ENODEV;
259 goto out;
260 }
261
262 mutex_lock(&hdev->fpriv_list_lock);
263
264 if (hdev->is_compute_ctx_active) {
265 dev_err(hdev->dev,
266 "Can't change PM profile while compute context is opened on the device\n");
267 count = -EPERM;
268 goto unlock_mutex;
269 }
270
271 if (strncmp("auto", buf, strlen("auto")) == 0) {
272 /* Make sure we are in LOW PLL when changing modes */
273 if (goya->pm_mng_profile == PM_MANUAL) {
274 goya->curr_pll_profile = PLL_HIGH;
275 goya->pm_mng_profile = PM_AUTO;
276 goya_set_frequency(hdev, PLL_LOW);
277 }
278 } else if (strncmp("manual", buf, strlen("manual")) == 0) {
279 if (goya->pm_mng_profile == PM_AUTO) {
280 /* Must release the lock because the work thread also
281 * takes this lock. But before we release it, set
282 * the mode to manual so nothing will change if a user
283 * suddenly opens the device
284 */
285 goya->pm_mng_profile = PM_MANUAL;
286
287 mutex_unlock(&hdev->fpriv_list_lock);
288
289 /* Flush the current work so we can return to the user
290 * knowing that he is the only one changing frequencies
291 */
292 if (goya->goya_work)
293 flush_delayed_work(&goya->goya_work->work_freq);
294
295 return count;
296 }
297 } else {
298 dev_err(hdev->dev, "value should be auto or manual\n");
299 count = -EINVAL;
300 }
301
302 unlock_mutex:
303 mutex_unlock(&hdev->fpriv_list_lock);
304 out:
305 return count;
306 }
307
high_pll_show(struct device * dev,struct device_attribute * attr,char * buf)308 static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
309 char *buf)
310 {
311 struct hl_device *hdev = dev_get_drvdata(dev);
312
313 if (!hl_device_operational(hdev, NULL))
314 return -ENODEV;
315
316 return sprintf(buf, "%u\n", hdev->high_pll);
317 }
318
high_pll_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)319 static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
320 const char *buf, size_t count)
321 {
322 struct hl_device *hdev = dev_get_drvdata(dev);
323 long value;
324 int rc;
325
326 if (!hl_device_operational(hdev, NULL)) {
327 count = -ENODEV;
328 goto out;
329 }
330
331 rc = kstrtoul(buf, 0, &value);
332
333 if (rc) {
334 count = -EINVAL;
335 goto out;
336 }
337
338 hdev->high_pll = value;
339
340 out:
341 return count;
342 }
343
344 static DEVICE_ATTR_RW(high_pll);
345 static DEVICE_ATTR_RW(ic_clk);
346 static DEVICE_ATTR_RO(ic_clk_curr);
347 static DEVICE_ATTR_RW(mme_clk);
348 static DEVICE_ATTR_RO(mme_clk_curr);
349 static DEVICE_ATTR_RW(pm_mng_profile);
350 static DEVICE_ATTR_RW(tpc_clk);
351 static DEVICE_ATTR_RO(tpc_clk_curr);
352
353 static struct attribute *goya_clk_dev_attrs[] = {
354 &dev_attr_high_pll.attr,
355 &dev_attr_ic_clk.attr,
356 &dev_attr_ic_clk_curr.attr,
357 &dev_attr_mme_clk.attr,
358 &dev_attr_mme_clk_curr.attr,
359 &dev_attr_pm_mng_profile.attr,
360 &dev_attr_tpc_clk.attr,
361 &dev_attr_tpc_clk_curr.attr,
362 NULL,
363 };
364
infineon_ver_show(struct device * dev,struct device_attribute * attr,char * buf)365 static ssize_t infineon_ver_show(struct device *dev, struct device_attribute *attr, char *buf)
366 {
367 struct hl_device *hdev = dev_get_drvdata(dev);
368 struct cpucp_info *cpucp_info;
369
370 cpucp_info = &hdev->asic_prop.cpucp_info;
371
372 return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));
373 }
374
375 static DEVICE_ATTR_RO(infineon_ver);
376
377 static struct attribute *goya_vrm_dev_attrs[] = {
378 &dev_attr_infineon_ver.attr,
379 NULL,
380 };
381
goya_add_device_attr(struct hl_device * hdev,struct attribute_group * dev_clk_attr_grp,struct attribute_group * dev_vrm_attr_grp)382 void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp,
383 struct attribute_group *dev_vrm_attr_grp)
384 {
385 dev_clk_attr_grp->attrs = goya_clk_dev_attrs;
386 dev_vrm_attr_grp->attrs = goya_vrm_dev_attrs;
387 }
388