habanalabs: remove asic callback set_pll_profile()
[linux-2.6-microblaze.git] / drivers / misc / habanalabs / goya / goya_hwmgr.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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_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
365 void goya_add_device_attr(struct hl_device *hdev,
366                         struct attribute_group *dev_attr_grp)
367 {
368         dev_attr_grp->attrs = goya_dev_attrs;
369 }