blob: 6d80e7e0885cdde7641615ec1b31bf066a6a7b0a [file] [log] [blame]
Oded Gabbayd91389b2019-02-16 00:39:19 +02001// SPDX-License-Identifier: GPL-2.0
2
3/*
4 * Copyright 2016-2019 HabanaLabs, Ltd.
5 * All Rights Reserved.
6 */
7
8#include "habanalabs.h"
9
10#include <linux/pci.h>
11
12#define SET_CLK_PKT_TIMEOUT 200000 /* 200ms */
13#define SET_PWR_PKT_TIMEOUT 400000 /* 400ms */
14
15long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
16{
17 struct armcp_packet pkt;
18 long result;
19 int rc;
20
21 memset(&pkt, 0, sizeof(pkt));
22
23 if (curr)
24 pkt.ctl = ARMCP_PACKET_FREQUENCY_CURR_GET <<
25 ARMCP_PKT_CTL_OPCODE_SHIFT;
26 else
27 pkt.ctl = ARMCP_PACKET_FREQUENCY_GET <<
28 ARMCP_PKT_CTL_OPCODE_SHIFT;
29 pkt.pll_index = pll_index;
30
31 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
32 SET_CLK_PKT_TIMEOUT, &result);
33
34 if (rc) {
35 dev_err(hdev->dev,
36 "Failed to get frequency of PLL %d, error %d\n",
37 pll_index, rc);
38 result = rc;
39 }
40
41 return result;
42}
43
44void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
45{
46 struct armcp_packet pkt;
47 int rc;
48
49 memset(&pkt, 0, sizeof(pkt));
50
51 pkt.ctl = ARMCP_PACKET_FREQUENCY_SET << ARMCP_PKT_CTL_OPCODE_SHIFT;
52 pkt.pll_index = pll_index;
53 pkt.value = freq;
54
55 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
56 SET_CLK_PKT_TIMEOUT, NULL);
57
58 if (rc)
59 dev_err(hdev->dev,
60 "Failed to set frequency to PLL %d, error %d\n",
61 pll_index, rc);
62}
63
64u64 hl_get_max_power(struct hl_device *hdev)
65{
66 struct armcp_packet pkt;
67 long result;
68 int rc;
69
70 memset(&pkt, 0, sizeof(pkt));
71
72 pkt.ctl = ARMCP_PACKET_MAX_POWER_GET << ARMCP_PKT_CTL_OPCODE_SHIFT;
73
74 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
75 SET_PWR_PKT_TIMEOUT, &result);
76
77 if (rc) {
78 dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
79 result = rc;
80 }
81
82 return result;
83}
84
85void hl_set_max_power(struct hl_device *hdev, u64 value)
86{
87 struct armcp_packet pkt;
88 int rc;
89
90 memset(&pkt, 0, sizeof(pkt));
91
92 pkt.ctl = ARMCP_PACKET_MAX_POWER_SET << ARMCP_PKT_CTL_OPCODE_SHIFT;
93 pkt.value = value;
94
95 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
96 SET_PWR_PKT_TIMEOUT, NULL);
97
98 if (rc)
99 dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
100}
101
102static ssize_t pm_mng_profile_show(struct device *dev,
103 struct device_attribute *attr, char *buf)
104{
105 struct hl_device *hdev = dev_get_drvdata(dev);
106
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200107 if (hl_device_disabled_or_in_reset(hdev))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200108 return -ENODEV;
109
110 return sprintf(buf, "%s\n",
111 (hdev->pm_mng_profile == PM_AUTO) ? "auto" :
112 (hdev->pm_mng_profile == PM_MANUAL) ? "manual" :
113 "unknown");
114}
115
116static ssize_t pm_mng_profile_store(struct device *dev,
117 struct device_attribute *attr, const char *buf, size_t count)
118{
119 struct hl_device *hdev = dev_get_drvdata(dev);
120
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200121 if (hl_device_disabled_or_in_reset(hdev)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200122 count = -ENODEV;
123 goto out;
124 }
125
126 mutex_lock(&hdev->fd_open_cnt_lock);
127
128 if (atomic_read(&hdev->fd_open_cnt) > 0) {
129 dev_err(hdev->dev,
130 "Can't change PM profile while user process is opened on the device\n");
131 count = -EPERM;
132 goto unlock_mutex;
133 }
134
135 if (strncmp("auto", buf, strlen("auto")) == 0) {
136 /* Make sure we are in LOW PLL when changing modes */
137 if (hdev->pm_mng_profile == PM_MANUAL) {
138 atomic_set(&hdev->curr_pll_profile, PLL_HIGH);
139 hl_device_set_frequency(hdev, PLL_LOW);
140 hdev->pm_mng_profile = PM_AUTO;
141 }
142 } else if (strncmp("manual", buf, strlen("manual")) == 0) {
143 /* Make sure we are in LOW PLL when changing modes */
144 if (hdev->pm_mng_profile == PM_AUTO) {
145 flush_delayed_work(&hdev->work_freq);
146 hdev->pm_mng_profile = PM_MANUAL;
147 }
148 } else {
149 dev_err(hdev->dev, "value should be auto or manual\n");
150 count = -EINVAL;
151 goto unlock_mutex;
152 }
153
154unlock_mutex:
155 mutex_unlock(&hdev->fd_open_cnt_lock);
156out:
157 return count;
158}
159
160static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
161 char *buf)
162{
163 struct hl_device *hdev = dev_get_drvdata(dev);
164
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200165 if (hl_device_disabled_or_in_reset(hdev))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200166 return -ENODEV;
167
168 return sprintf(buf, "%u\n", hdev->high_pll);
169}
170
171static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
172 const char *buf, size_t count)
173{
174 struct hl_device *hdev = dev_get_drvdata(dev);
175 long value;
176 int rc;
177
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200178 if (hl_device_disabled_or_in_reset(hdev)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200179 count = -ENODEV;
180 goto out;
181 }
182
183 rc = kstrtoul(buf, 0, &value);
184
185 if (rc) {
186 count = -EINVAL;
187 goto out;
188 }
189
190 hdev->high_pll = value;
191
192out:
193 return count;
194}
195
196static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
197 char *buf)
198{
199 struct hl_device *hdev = dev_get_drvdata(dev);
200
201 return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
202}
203
204static ssize_t armcp_kernel_ver_show(struct device *dev,
205 struct device_attribute *attr, char *buf)
206{
207 struct hl_device *hdev = dev_get_drvdata(dev);
208
209 return sprintf(buf, "%s", hdev->asic_prop.armcp_info.kernel_version);
210}
211
212static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
213 char *buf)
214{
215 struct hl_device *hdev = dev_get_drvdata(dev);
216
217 return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.armcp_version);
218}
219
220static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
221 char *buf)
222{
223 struct hl_device *hdev = dev_get_drvdata(dev);
224
225 return sprintf(buf, "0x%08x\n",
226 hdev->asic_prop.armcp_info.cpld_version);
227}
228
229static ssize_t infineon_ver_show(struct device *dev,
230 struct device_attribute *attr, char *buf)
231{
232 struct hl_device *hdev = dev_get_drvdata(dev);
233
234 return sprintf(buf, "0x%04x\n",
235 hdev->asic_prop.armcp_info.infineon_version);
236}
237
238static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
239 char *buf)
240{
241 struct hl_device *hdev = dev_get_drvdata(dev);
242
243 return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.fuse_version);
244}
245
246static ssize_t thermal_ver_show(struct device *dev,
247 struct device_attribute *attr, char *buf)
248{
249 struct hl_device *hdev = dev_get_drvdata(dev);
250
251 return sprintf(buf, "%s", hdev->asic_prop.armcp_info.thermal_version);
252}
253
254static ssize_t preboot_btl_ver_show(struct device *dev,
255 struct device_attribute *attr, char *buf)
256{
257 struct hl_device *hdev = dev_get_drvdata(dev);
258
259 return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
260}
261
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200262static ssize_t soft_reset_store(struct device *dev,
263 struct device_attribute *attr, const char *buf,
264 size_t count)
265{
266 struct hl_device *hdev = dev_get_drvdata(dev);
267 long value;
268 int rc;
269
270 rc = kstrtoul(buf, 0, &value);
271
272 if (rc) {
273 count = -EINVAL;
274 goto out;
275 }
276
277 hl_device_reset(hdev, false, false);
278
279out:
280 return count;
281}
282
283static ssize_t hard_reset_store(struct device *dev,
284 struct device_attribute *attr,
285 const char *buf, size_t count)
286{
287 struct hl_device *hdev = dev_get_drvdata(dev);
288 long value;
289 int rc;
290
291 rc = kstrtoul(buf, 0, &value);
292
293 if (rc) {
294 count = -EINVAL;
295 goto out;
296 }
297
298 hl_device_reset(hdev, true, false);
299
300out:
301 return count;
302}
303
Oded Gabbayd91389b2019-02-16 00:39:19 +0200304static ssize_t device_type_show(struct device *dev,
305 struct device_attribute *attr, char *buf)
306{
307 struct hl_device *hdev = dev_get_drvdata(dev);
308 char *str;
309
310 switch (hdev->asic_type) {
311 case ASIC_GOYA:
312 str = "GOYA";
313 break;
314 default:
315 dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
316 hdev->asic_type);
317 return -EINVAL;
318 }
319
320 return sprintf(buf, "%s\n", str);
321}
322
323static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
324 char *buf)
325{
326 struct hl_device *hdev = dev_get_drvdata(dev);
327
328 /* Use dummy, fixed address for simulator */
329 if (!hdev->pdev)
330 return sprintf(buf, "0000:%02d:00.0\n", hdev->id);
331
332 return sprintf(buf, "%04x:%02x:%02x.%x\n",
333 pci_domain_nr(hdev->pdev->bus),
334 hdev->pdev->bus->number,
335 PCI_SLOT(hdev->pdev->devfn),
336 PCI_FUNC(hdev->pdev->devfn));
337}
338
339static ssize_t status_show(struct device *dev, struct device_attribute *attr,
340 char *buf)
341{
342 struct hl_device *hdev = dev_get_drvdata(dev);
343 char *str;
344
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200345 if (atomic_read(&hdev->in_reset))
346 str = "In reset";
347 else if (hdev->disabled)
Oded Gabbayd91389b2019-02-16 00:39:19 +0200348 str = "Malfunction";
349 else
350 str = "Operational";
351
352 return sprintf(buf, "%s\n", str);
353}
354
355static ssize_t write_open_cnt_show(struct device *dev,
356 struct device_attribute *attr, char *buf)
357{
358 struct hl_device *hdev = dev_get_drvdata(dev);
359
360 return sprintf(buf, "%d\n", hdev->user_ctx ? 1 : 0);
361}
362
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200363static ssize_t soft_reset_cnt_show(struct device *dev,
364 struct device_attribute *attr, char *buf)
365{
366 struct hl_device *hdev = dev_get_drvdata(dev);
367
368 return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
369}
370
371static ssize_t hard_reset_cnt_show(struct device *dev,
372 struct device_attribute *attr, char *buf)
373{
374 struct hl_device *hdev = dev_get_drvdata(dev);
375
376 return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
377}
378
Oded Gabbayd91389b2019-02-16 00:39:19 +0200379static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
380 char *buf)
381{
382 struct hl_device *hdev = dev_get_drvdata(dev);
383 long val;
384
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200385 if (hl_device_disabled_or_in_reset(hdev))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200386 return -ENODEV;
387
388 val = hl_get_max_power(hdev);
389
390 return sprintf(buf, "%lu\n", val);
391}
392
393static ssize_t max_power_store(struct device *dev,
394 struct device_attribute *attr, const char *buf, size_t count)
395{
396 struct hl_device *hdev = dev_get_drvdata(dev);
397 unsigned long value;
398 int rc;
399
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200400 if (hl_device_disabled_or_in_reset(hdev)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200401 count = -ENODEV;
402 goto out;
403 }
404
405 rc = kstrtoul(buf, 0, &value);
406
407 if (rc) {
408 count = -EINVAL;
409 goto out;
410 }
411
412 hdev->max_power = value;
413 hl_set_max_power(hdev, value);
414
415out:
416 return count;
417}
418
419static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
420 struct bin_attribute *attr, char *buf, loff_t offset,
421 size_t max_size)
422{
423 struct device *dev = container_of(kobj, struct device, kobj);
424 struct hl_device *hdev = dev_get_drvdata(dev);
425 char *data;
426 int rc;
427
428 if (!max_size)
429 return -EINVAL;
430
431 data = kzalloc(max_size, GFP_KERNEL);
432 if (!data)
433 return -ENOMEM;
434
435 rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
436 if (rc)
437 goto out;
438
439 memcpy(buf, data, max_size);
440
441out:
442 kfree(data);
443
444 return max_size;
445}
446
447static DEVICE_ATTR_RO(armcp_kernel_ver);
448static DEVICE_ATTR_RO(armcp_ver);
449static DEVICE_ATTR_RO(cpld_ver);
450static DEVICE_ATTR_RO(device_type);
451static DEVICE_ATTR_RO(fuse_ver);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200452static DEVICE_ATTR_WO(hard_reset);
453static DEVICE_ATTR_RO(hard_reset_cnt);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200454static DEVICE_ATTR_RW(high_pll);
455static DEVICE_ATTR_RO(infineon_ver);
456static DEVICE_ATTR_RW(max_power);
457static DEVICE_ATTR_RO(pci_addr);
458static DEVICE_ATTR_RW(pm_mng_profile);
459static DEVICE_ATTR_RO(preboot_btl_ver);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200460static DEVICE_ATTR_WO(soft_reset);
461static DEVICE_ATTR_RO(soft_reset_cnt);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200462static DEVICE_ATTR_RO(status);
463static DEVICE_ATTR_RO(thermal_ver);
464static DEVICE_ATTR_RO(uboot_ver);
465static DEVICE_ATTR_RO(write_open_cnt);
466
467static struct bin_attribute bin_attr_eeprom = {
468 .attr = {.name = "eeprom", .mode = (0444)},
469 .size = PAGE_SIZE,
470 .read = eeprom_read_handler
471};
472
473static struct attribute *hl_dev_attrs[] = {
474 &dev_attr_armcp_kernel_ver.attr,
475 &dev_attr_armcp_ver.attr,
476 &dev_attr_cpld_ver.attr,
477 &dev_attr_device_type.attr,
478 &dev_attr_fuse_ver.attr,
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200479 &dev_attr_hard_reset.attr,
480 &dev_attr_hard_reset_cnt.attr,
Oded Gabbayd91389b2019-02-16 00:39:19 +0200481 &dev_attr_high_pll.attr,
482 &dev_attr_infineon_ver.attr,
483 &dev_attr_max_power.attr,
484 &dev_attr_pci_addr.attr,
485 &dev_attr_pm_mng_profile.attr,
486 &dev_attr_preboot_btl_ver.attr,
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200487 &dev_attr_soft_reset.attr,
488 &dev_attr_soft_reset_cnt.attr,
Oded Gabbayd91389b2019-02-16 00:39:19 +0200489 &dev_attr_status.attr,
490 &dev_attr_thermal_ver.attr,
491 &dev_attr_uboot_ver.attr,
492 &dev_attr_write_open_cnt.attr,
493 NULL,
494};
495
496static struct bin_attribute *hl_dev_bin_attrs[] = {
497 &bin_attr_eeprom,
498 NULL
499};
500
501static struct attribute_group hl_dev_attr_group = {
502 .attrs = hl_dev_attrs,
503 .bin_attrs = hl_dev_bin_attrs,
504};
505
506static struct attribute_group hl_dev_clks_attr_group;
507
508static const struct attribute_group *hl_dev_attr_groups[] = {
509 &hl_dev_attr_group,
510 &hl_dev_clks_attr_group,
511 NULL,
512};
513
514int hl_sysfs_init(struct hl_device *hdev)
515{
516 int rc;
517
518 hdev->pm_mng_profile = PM_AUTO;
519 hdev->max_power = hdev->asic_prop.max_power_default;
520
521 hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
522
523 rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
524 if (rc) {
525 dev_err(hdev->dev,
526 "Failed to add groups to device, error %d\n", rc);
527 return rc;
528 }
529
530 return 0;
531}
532
533void hl_sysfs_fini(struct hl_device *hdev)
534{
535 device_remove_groups(hdev->dev, hl_dev_attr_groups);
536}