WIP FPC-III support
[linux/fpc-iii.git] / drivers / misc / habanalabs / goya / goya_hwmgr.c
blob3acb36a1a902ea7129b23b5de379de88430c554b
1 // SPDX-License-Identifier: GPL-2.0
3 /*
4 * Copyright 2016-2019 HabanaLabs, Ltd.
5 * All Rights Reserved.
6 */
8 #include "goyaP.h"
10 void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
12 struct goya_device *goya = hdev->asic_specific;
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");
35 int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
37 long value;
39 if (!hl_device_operational(hdev, NULL))
40 return -ENODEV;
42 value = hl_get_frequency(hdev, MME_PLL, false);
44 if (value < 0) {
45 dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n",
46 value);
47 return value;
50 *max_clk = (value / 1000 / 1000);
52 value = hl_get_frequency(hdev, MME_PLL, true);
54 if (value < 0) {
55 dev_err(hdev->dev,
56 "Failed to retrieve device current clock %ld\n",
57 value);
58 return value;
61 *cur_clk = (value / 1000 / 1000);
63 return 0;
66 static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
67 char *buf)
69 struct hl_device *hdev = dev_get_drvdata(dev);
70 long value;
72 if (!hl_device_operational(hdev, NULL))
73 return -ENODEV;
75 value = hl_get_frequency(hdev, MME_PLL, false);
77 if (value < 0)
78 return value;
80 return sprintf(buf, "%lu\n", value);
83 static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
84 const char *buf, size_t count)
86 struct hl_device *hdev = dev_get_drvdata(dev);
87 struct goya_device *goya = hdev->asic_specific;
88 int rc;
89 long value;
91 if (!hl_device_operational(hdev, NULL)) {
92 count = -ENODEV;
93 goto fail;
96 if (hdev->pm_mng_profile == PM_AUTO) {
97 count = -EPERM;
98 goto fail;
101 rc = kstrtoul(buf, 0, &value);
103 if (rc) {
104 count = -EINVAL;
105 goto fail;
108 hl_set_frequency(hdev, MME_PLL, value);
109 goya->mme_clk = value;
111 fail:
112 return count;
115 static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
116 char *buf)
118 struct hl_device *hdev = dev_get_drvdata(dev);
119 long value;
121 if (!hl_device_operational(hdev, NULL))
122 return -ENODEV;
124 value = hl_get_frequency(hdev, TPC_PLL, false);
126 if (value < 0)
127 return value;
129 return sprintf(buf, "%lu\n", value);
132 static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
133 const char *buf, size_t count)
135 struct hl_device *hdev = dev_get_drvdata(dev);
136 struct goya_device *goya = hdev->asic_specific;
137 int rc;
138 long value;
140 if (!hl_device_operational(hdev, NULL)) {
141 count = -ENODEV;
142 goto fail;
145 if (hdev->pm_mng_profile == PM_AUTO) {
146 count = -EPERM;
147 goto fail;
150 rc = kstrtoul(buf, 0, &value);
152 if (rc) {
153 count = -EINVAL;
154 goto fail;
157 hl_set_frequency(hdev, TPC_PLL, value);
158 goya->tpc_clk = value;
160 fail:
161 return count;
164 static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
165 char *buf)
167 struct hl_device *hdev = dev_get_drvdata(dev);
168 long value;
170 if (!hl_device_operational(hdev, NULL))
171 return -ENODEV;
173 value = hl_get_frequency(hdev, IC_PLL, false);
175 if (value < 0)
176 return value;
178 return sprintf(buf, "%lu\n", value);
181 static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
182 const char *buf, size_t count)
184 struct hl_device *hdev = dev_get_drvdata(dev);
185 struct goya_device *goya = hdev->asic_specific;
186 int rc;
187 long value;
189 if (!hl_device_operational(hdev, NULL)) {
190 count = -ENODEV;
191 goto fail;
194 if (hdev->pm_mng_profile == PM_AUTO) {
195 count = -EPERM;
196 goto fail;
199 rc = kstrtoul(buf, 0, &value);
201 if (rc) {
202 count = -EINVAL;
203 goto fail;
206 hl_set_frequency(hdev, IC_PLL, value);
207 goya->ic_clk = value;
209 fail:
210 return count;
213 static ssize_t mme_clk_curr_show(struct device *dev,
214 struct device_attribute *attr, char *buf)
216 struct hl_device *hdev = dev_get_drvdata(dev);
217 long value;
219 if (!hl_device_operational(hdev, NULL))
220 return -ENODEV;
222 value = hl_get_frequency(hdev, MME_PLL, true);
224 if (value < 0)
225 return value;
227 return sprintf(buf, "%lu\n", value);
230 static ssize_t tpc_clk_curr_show(struct device *dev,
231 struct device_attribute *attr, char *buf)
233 struct hl_device *hdev = dev_get_drvdata(dev);
234 long value;
236 if (!hl_device_operational(hdev, NULL))
237 return -ENODEV;
239 value = hl_get_frequency(hdev, TPC_PLL, true);
241 if (value < 0)
242 return value;
244 return sprintf(buf, "%lu\n", value);
247 static ssize_t ic_clk_curr_show(struct device *dev,
248 struct device_attribute *attr, char *buf)
250 struct hl_device *hdev = dev_get_drvdata(dev);
251 long value;
253 if (!hl_device_operational(hdev, NULL))
254 return -ENODEV;
256 value = hl_get_frequency(hdev, IC_PLL, true);
258 if (value < 0)
259 return value;
261 return sprintf(buf, "%lu\n", value);
264 static ssize_t pm_mng_profile_show(struct device *dev,
265 struct device_attribute *attr, char *buf)
267 struct hl_device *hdev = dev_get_drvdata(dev);
269 if (!hl_device_operational(hdev, NULL))
270 return -ENODEV;
272 return sprintf(buf, "%s\n",
273 (hdev->pm_mng_profile == PM_AUTO) ? "auto" :
274 (hdev->pm_mng_profile == PM_MANUAL) ? "manual" :
275 "unknown");
278 static ssize_t pm_mng_profile_store(struct device *dev,
279 struct device_attribute *attr, const char *buf, size_t count)
281 struct hl_device *hdev = dev_get_drvdata(dev);
283 if (!hl_device_operational(hdev, NULL)) {
284 count = -ENODEV;
285 goto out;
288 mutex_lock(&hdev->fpriv_list_lock);
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;
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);
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
311 hdev->pm_mng_profile = PM_MANUAL;
313 mutex_unlock(&hdev->fpriv_list_lock);
315 /* Flush the current work so we can return to the user
316 * knowing that he is the only one changing frequencies
318 flush_delayed_work(&hdev->work_freq);
320 return count;
322 } else {
323 dev_err(hdev->dev, "value should be auto or manual\n");
324 count = -EINVAL;
327 unlock_mutex:
328 mutex_unlock(&hdev->fpriv_list_lock);
329 out:
330 return count;
333 static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
334 char *buf)
336 struct hl_device *hdev = dev_get_drvdata(dev);
338 if (!hl_device_operational(hdev, NULL))
339 return -ENODEV;
341 return sprintf(buf, "%u\n", hdev->high_pll);
344 static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
345 const char *buf, size_t count)
347 struct hl_device *hdev = dev_get_drvdata(dev);
348 long value;
349 int rc;
351 if (!hl_device_operational(hdev, NULL)) {
352 count = -ENODEV;
353 goto out;
356 rc = kstrtoul(buf, 0, &value);
358 if (rc) {
359 count = -EINVAL;
360 goto out;
363 hdev->high_pll = value;
365 out:
366 return count;
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);
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,
390 void goya_add_device_attr(struct hl_device *hdev,
391 struct attribute_group *dev_attr_grp)
393 dev_attr_grp->attrs = goya_dev_attrs;