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