blob: 76b47749affe3744a76b82ab1dc90a45cae826d1 [file] [log] [blame]
Oded Gabbayd91389b2019-02-16 00:39:19 +02001// SPDX-License-Identifier: GPL-2.0
2
3/*
Oded Gabbay5b90e592021-11-30 23:08:21 +02004 * Copyright 2016-2021 HabanaLabs, Ltd.
Oded Gabbayd91389b2019-02-16 00:39:19 +02005 * All Rights Reserved.
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:
Bharat Jauhari285c0fa2021-03-25 18:15:40 +020016 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);
Oded Gabbayd91389b2019-02-16 00:39:19 +020019 break;
20 case PLL_LOW:
Bharat Jauhari285c0fa2021-03-25 18:15:40 +020021 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);
Oded Gabbayd91389b2019-02-16 00:39:19 +020024 break;
25 case PLL_LAST:
Bharat Jauhari285c0fa2021-03-25 18:15:40 +020026 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);
Oded Gabbayd91389b2019-02-16 00:39:19 +020029 break;
30 default:
31 dev_err(hdev->dev, "unknown frequency setting\n");
32 }
33}
34
35static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
36 char *buf)
37{
38 struct hl_device *hdev = dev_get_drvdata(dev);
39 long value;
40
Ofir Bitton66a76402020-10-05 14:40:10 +030041 if (!hl_device_operational(hdev, NULL))
Oded Gabbayd91389b2019-02-16 00:39:19 +020042 return -ENODEV;
43
Bharat Jauhari285c0fa2021-03-25 18:15:40 +020044 value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, false);
Oded Gabbayd91389b2019-02-16 00:39:19 +020045
46 if (value < 0)
47 return value;
48
49 return sprintf(buf, "%lu\n", value);
50}
51
52static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
53 const char *buf, size_t count)
54{
55 struct hl_device *hdev = dev_get_drvdata(dev);
56 struct goya_device *goya = hdev->asic_specific;
57 int rc;
58 long value;
59
Ofir Bitton66a76402020-10-05 14:40:10 +030060 if (!hl_device_operational(hdev, NULL)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +020061 count = -ENODEV;
62 goto fail;
63 }
64
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +030065 if (goya->pm_mng_profile == PM_AUTO) {
Oded Gabbayd91389b2019-02-16 00:39:19 +020066 count = -EPERM;
67 goto fail;
68 }
69
70 rc = kstrtoul(buf, 0, &value);
71
72 if (rc) {
73 count = -EINVAL;
74 goto fail;
75 }
76
Bharat Jauhari285c0fa2021-03-25 18:15:40 +020077 hl_set_frequency(hdev, HL_GOYA_MME_PLL, value);
Oded Gabbayd91389b2019-02-16 00:39:19 +020078 goya->mme_clk = value;
79
80fail:
81 return count;
82}
83
84static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
85 char *buf)
86{
87 struct hl_device *hdev = dev_get_drvdata(dev);
88 long value;
89
Ofir Bitton66a76402020-10-05 14:40:10 +030090 if (!hl_device_operational(hdev, NULL))
Oded Gabbayd91389b2019-02-16 00:39:19 +020091 return -ENODEV;
92
Bharat Jauhari285c0fa2021-03-25 18:15:40 +020093 value = hl_get_frequency(hdev, HL_GOYA_TPC_PLL, false);
Oded Gabbayd91389b2019-02-16 00:39:19 +020094
95 if (value < 0)
96 return value;
97
98 return sprintf(buf, "%lu\n", value);
99}
100
101static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
102 const char *buf, size_t count)
103{
104 struct hl_device *hdev = dev_get_drvdata(dev);
105 struct goya_device *goya = hdev->asic_specific;
106 int rc;
107 long value;
108
Ofir Bitton66a76402020-10-05 14:40:10 +0300109 if (!hl_device_operational(hdev, NULL)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200110 count = -ENODEV;
111 goto fail;
112 }
113
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300114 if (goya->pm_mng_profile == PM_AUTO) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200115 count = -EPERM;
116 goto fail;
117 }
118
119 rc = kstrtoul(buf, 0, &value);
120
121 if (rc) {
122 count = -EINVAL;
123 goto fail;
124 }
125
Bharat Jauhari285c0fa2021-03-25 18:15:40 +0200126 hl_set_frequency(hdev, HL_GOYA_TPC_PLL, value);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200127 goya->tpc_clk = value;
128
129fail:
130 return count;
131}
132
133static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
134 char *buf)
135{
136 struct hl_device *hdev = dev_get_drvdata(dev);
137 long value;
138
Ofir Bitton66a76402020-10-05 14:40:10 +0300139 if (!hl_device_operational(hdev, NULL))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200140 return -ENODEV;
141
Bharat Jauhari285c0fa2021-03-25 18:15:40 +0200142 value = hl_get_frequency(hdev, HL_GOYA_IC_PLL, false);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200143
144 if (value < 0)
145 return value;
146
147 return sprintf(buf, "%lu\n", value);
148}
149
150static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
151 const char *buf, size_t count)
152{
153 struct hl_device *hdev = dev_get_drvdata(dev);
154 struct goya_device *goya = hdev->asic_specific;
155 int rc;
156 long value;
157
Ofir Bitton66a76402020-10-05 14:40:10 +0300158 if (!hl_device_operational(hdev, NULL)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200159 count = -ENODEV;
160 goto fail;
161 }
162
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300163 if (goya->pm_mng_profile == PM_AUTO) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200164 count = -EPERM;
165 goto fail;
166 }
167
168 rc = kstrtoul(buf, 0, &value);
169
170 if (rc) {
171 count = -EINVAL;
172 goto fail;
173 }
174
Bharat Jauhari285c0fa2021-03-25 18:15:40 +0200175 hl_set_frequency(hdev, HL_GOYA_IC_PLL, value);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200176 goya->ic_clk = value;
177
178fail:
179 return count;
180}
181
182static ssize_t mme_clk_curr_show(struct device *dev,
183 struct device_attribute *attr, char *buf)
184{
185 struct hl_device *hdev = dev_get_drvdata(dev);
186 long value;
187
Ofir Bitton66a76402020-10-05 14:40:10 +0300188 if (!hl_device_operational(hdev, NULL))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200189 return -ENODEV;
190
Bharat Jauhari285c0fa2021-03-25 18:15:40 +0200191 value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, true);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200192
193 if (value < 0)
194 return value;
195
196 return sprintf(buf, "%lu\n", value);
197}
198
199static ssize_t tpc_clk_curr_show(struct device *dev,
200 struct device_attribute *attr, char *buf)
201{
202 struct hl_device *hdev = dev_get_drvdata(dev);
203 long value;
204
Ofir Bitton66a76402020-10-05 14:40:10 +0300205 if (!hl_device_operational(hdev, NULL))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200206 return -ENODEV;
207
Bharat Jauhari285c0fa2021-03-25 18:15:40 +0200208 value = hl_get_frequency(hdev, HL_GOYA_TPC_PLL, true);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200209
210 if (value < 0)
211 return value;
212
213 return sprintf(buf, "%lu\n", value);
214}
215
216static ssize_t ic_clk_curr_show(struct device *dev,
217 struct device_attribute *attr, char *buf)
218{
219 struct hl_device *hdev = dev_get_drvdata(dev);
220 long value;
221
Ofir Bitton66a76402020-10-05 14:40:10 +0300222 if (!hl_device_operational(hdev, NULL))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200223 return -ENODEV;
224
Bharat Jauhari285c0fa2021-03-25 18:15:40 +0200225 value = hl_get_frequency(hdev, HL_GOYA_IC_PLL, true);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200226
227 if (value < 0)
228 return value;
229
230 return sprintf(buf, "%lu\n", value);
231}
232
Oded Gabbay209257f2019-07-04 11:57:12 +0300233static ssize_t pm_mng_profile_show(struct device *dev,
234 struct device_attribute *attr, char *buf)
235{
236 struct hl_device *hdev = dev_get_drvdata(dev);
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300237 struct goya_device *goya = hdev->asic_specific;
Oded Gabbay209257f2019-07-04 11:57:12 +0300238
Ofir Bitton66a76402020-10-05 14:40:10 +0300239 if (!hl_device_operational(hdev, NULL))
Oded Gabbay209257f2019-07-04 11:57:12 +0300240 return -ENODEV;
241
242 return sprintf(buf, "%s\n",
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300243 (goya->pm_mng_profile == PM_AUTO) ? "auto" :
244 (goya->pm_mng_profile == PM_MANUAL) ? "manual" :
Oded Gabbay209257f2019-07-04 11:57:12 +0300245 "unknown");
246}
247
248static ssize_t pm_mng_profile_store(struct device *dev,
249 struct device_attribute *attr, const char *buf, size_t count)
250{
251 struct hl_device *hdev = dev_get_drvdata(dev);
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300252 struct goya_device *goya = hdev->asic_specific;
Oded Gabbay209257f2019-07-04 11:57:12 +0300253
Ofir Bitton66a76402020-10-05 14:40:10 +0300254 if (!hl_device_operational(hdev, NULL)) {
Oded Gabbay209257f2019-07-04 11:57:12 +0300255 count = -ENODEV;
256 goto out;
257 }
258
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300259 mutex_lock(&hdev->fpriv_list_lock);
Oded Gabbay209257f2019-07-04 11:57:12 +0300260
Oded Gabbay5b90e592021-11-30 23:08:21 +0200261 if (hdev->is_compute_ctx_active) {
Oded Gabbay209257f2019-07-04 11:57:12 +0300262 dev_err(hdev->dev,
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300263 "Can't change PM profile while compute context is opened on the device\n");
Oded Gabbay209257f2019-07-04 11:57:12 +0300264 count = -EPERM;
265 goto unlock_mutex;
266 }
267
268 if (strncmp("auto", buf, strlen("auto")) == 0) {
269 /* Make sure we are in LOW PLL when changing modes */
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300270 if (goya->pm_mng_profile == PM_MANUAL) {
271 goya->curr_pll_profile = PLL_HIGH;
272 goya->pm_mng_profile = PM_AUTO;
273 goya_set_frequency(hdev, PLL_LOW);
Oded Gabbay209257f2019-07-04 11:57:12 +0300274 }
275 } else if (strncmp("manual", buf, strlen("manual")) == 0) {
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300276 if (goya->pm_mng_profile == PM_AUTO) {
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300277 /* Must release the lock because the work thread also
278 * takes this lock. But before we release it, set
279 * the mode to manual so nothing will change if a user
280 * suddenly opens the device
281 */
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300282 goya->pm_mng_profile = PM_MANUAL;
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300283
284 mutex_unlock(&hdev->fpriv_list_lock);
285
286 /* Flush the current work so we can return to the user
287 * knowing that he is the only one changing frequencies
288 */
Rajaravi Krishna Kattad8eb50f2021-08-05 10:24:16 +0300289 if (goya->goya_work)
290 flush_delayed_work(&goya->goya_work->work_freq);
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300291
292 return count;
Oded Gabbay209257f2019-07-04 11:57:12 +0300293 }
294 } else {
295 dev_err(hdev->dev, "value should be auto or manual\n");
296 count = -EINVAL;
Oded Gabbay209257f2019-07-04 11:57:12 +0300297 }
298
299unlock_mutex:
Oded Gabbayeb7caf82019-07-30 11:56:09 +0300300 mutex_unlock(&hdev->fpriv_list_lock);
Oded Gabbay209257f2019-07-04 11:57:12 +0300301out:
302 return count;
303}
304
305static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
306 char *buf)
307{
308 struct hl_device *hdev = dev_get_drvdata(dev);
309
Ofir Bitton66a76402020-10-05 14:40:10 +0300310 if (!hl_device_operational(hdev, NULL))
Oded Gabbay209257f2019-07-04 11:57:12 +0300311 return -ENODEV;
312
313 return sprintf(buf, "%u\n", hdev->high_pll);
314}
315
316static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
317 const char *buf, size_t count)
318{
319 struct hl_device *hdev = dev_get_drvdata(dev);
320 long value;
321 int rc;
322
Ofir Bitton66a76402020-10-05 14:40:10 +0300323 if (!hl_device_operational(hdev, NULL)) {
Oded Gabbay209257f2019-07-04 11:57:12 +0300324 count = -ENODEV;
325 goto out;
326 }
327
328 rc = kstrtoul(buf, 0, &value);
329
330 if (rc) {
331 count = -EINVAL;
332 goto out;
333 }
334
335 hdev->high_pll = value;
336
337out:
338 return count;
339}
340
341static DEVICE_ATTR_RW(high_pll);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200342static DEVICE_ATTR_RW(ic_clk);
343static DEVICE_ATTR_RO(ic_clk_curr);
344static DEVICE_ATTR_RW(mme_clk);
345static DEVICE_ATTR_RO(mme_clk_curr);
Oded Gabbay209257f2019-07-04 11:57:12 +0300346static DEVICE_ATTR_RW(pm_mng_profile);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200347static DEVICE_ATTR_RW(tpc_clk);
348static DEVICE_ATTR_RO(tpc_clk_curr);
349
350static struct attribute *goya_dev_attrs[] = {
Oded Gabbay209257f2019-07-04 11:57:12 +0300351 &dev_attr_high_pll.attr,
Oded Gabbayd91389b2019-02-16 00:39:19 +0200352 &dev_attr_ic_clk.attr,
353 &dev_attr_ic_clk_curr.attr,
354 &dev_attr_mme_clk.attr,
355 &dev_attr_mme_clk_curr.attr,
Oded Gabbay209257f2019-07-04 11:57:12 +0300356 &dev_attr_pm_mng_profile.attr,
Oded Gabbayd91389b2019-02-16 00:39:19 +0200357 &dev_attr_tpc_clk.attr,
358 &dev_attr_tpc_clk_curr.attr,
359 NULL,
360};
361
362void goya_add_device_attr(struct hl_device *hdev,
363 struct attribute_group *dev_attr_grp)
364{
365 dev_attr_grp->attrs = goya_dev_attrs;
366}