Merge tag 'arc-5.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[linux-2.6-microblaze.git] / drivers / misc / habanalabs / goya / goya_hwmgr.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Copyright 2016-2019 HabanaLabs, Ltd.
5  * All Rights Reserved.
6  */
7
8 #include "goyaP.h"
9
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         switch (freq) {
15         case PLL_HIGH:
16                 hl_set_frequency(hdev, MME_PLL, hdev->high_pll);
17                 hl_set_frequency(hdev, TPC_PLL, hdev->high_pll);
18                 hl_set_frequency(hdev, IC_PLL, hdev->high_pll);
19                 break;
20         case PLL_LOW:
21                 hl_set_frequency(hdev, MME_PLL, GOYA_PLL_FREQ_LOW);
22                 hl_set_frequency(hdev, TPC_PLL, GOYA_PLL_FREQ_LOW);
23                 hl_set_frequency(hdev, IC_PLL, GOYA_PLL_FREQ_LOW);
24                 break;
25         case PLL_LAST:
26                 hl_set_frequency(hdev, MME_PLL, goya->mme_clk);
27                 hl_set_frequency(hdev, TPC_PLL, goya->tpc_clk);
28                 hl_set_frequency(hdev, IC_PLL, goya->ic_clk);
29                 break;
30         default:
31                 dev_err(hdev->dev, "unknown frequency setting\n");
32         }
33 }
34
35 int 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, 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, 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
66 static 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, MME_PLL, false);
76
77         if (value < 0)
78                 return value;
79
80         return sprintf(buf, "%lu\n", value);
81 }
82
83 static 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, MME_PLL, value);
109         goya->mme_clk = value;
110
111 fail:
112         return count;
113 }
114
115 static 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, TPC_PLL, false);
125
126         if (value < 0)
127                 return value;
128
129         return sprintf(buf, "%lu\n", value);
130 }
131
132 static 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, TPC_PLL, value);
158         goya->tpc_clk = value;
159
160 fail:
161         return count;
162 }
163
164 static 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, IC_PLL, false);
174
175         if (value < 0)
176                 return value;
177
178         return sprintf(buf, "%lu\n", value);
179 }
180
181 static 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, IC_PLL, value);
207         goya->ic_clk = value;
208
209 fail:
210         return count;
211 }
212
213 static 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, MME_PLL, true);
223
224         if (value < 0)
225                 return value;
226
227         return sprintf(buf, "%lu\n", value);
228 }
229
230 static 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, TPC_PLL, true);
240
241         if (value < 0)
242                 return value;
243
244         return sprintf(buf, "%lu\n", value);
245 }
246
247 static 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, IC_PLL, true);
257
258         if (value < 0)
259                 return value;
260
261         return sprintf(buf, "%lu\n", value);
262 }
263
264 static 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
278 static 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                 /* Make sure we are in LOW PLL when changing modes */
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                         /* Must release the lock because the work thread also
307                          * takes this lock. But before we release it, set
308                          * the mode to manual so nothing will change if a user
309                          * suddenly opens the device
310                          */
311                         hdev->pm_mng_profile = PM_MANUAL;
312
313                         mutex_unlock(&hdev->fpriv_list_lock);
314
315                         /* Flush the current work so we can return to the user
316                          * knowing that he is the only one changing frequencies
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
327 unlock_mutex:
328         mutex_unlock(&hdev->fpriv_list_lock);
329 out:
330         return count;
331 }
332
333 static 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
344 static 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
365 out:
366         return count;
367 }
368
369 static DEVICE_ATTR_RW(high_pll);
370 static DEVICE_ATTR_RW(ic_clk);
371 static DEVICE_ATTR_RO(ic_clk_curr);
372 static DEVICE_ATTR_RW(mme_clk);
373 static DEVICE_ATTR_RO(mme_clk_curr);
374 static DEVICE_ATTR_RW(pm_mng_profile);
375 static DEVICE_ATTR_RW(tpc_clk);
376 static DEVICE_ATTR_RO(tpc_clk_curr);
377
378 static 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
390 void 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 }