blob: c900ab15cceb395bdc06f5941bfc87b62d1993cc [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
Oded Gabbaya28ce422019-02-28 10:46:12 +020012#define SET_CLK_PKT_TIMEOUT 1000000 /* 1s */
13#define SET_PWR_PKT_TIMEOUT 1000000 /* 1s */
Oded Gabbayd91389b2019-02-16 00:39:19 +020014
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)
Oded Gabbay8c844872019-02-28 10:46:24 +020024 pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FREQUENCY_CURR_GET <<
25 ARMCP_PKT_CTL_OPCODE_SHIFT);
Oded Gabbayd91389b2019-02-16 00:39:19 +020026 else
Oded Gabbay8c844872019-02-28 10:46:24 +020027 pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FREQUENCY_GET <<
28 ARMCP_PKT_CTL_OPCODE_SHIFT);
29 pkt.pll_index = __cpu_to_le32(pll_index);
Oded Gabbayd91389b2019-02-16 00:39:19 +020030
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
Oded Gabbay8c844872019-02-28 10:46:24 +020051 pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FREQUENCY_SET <<
52 ARMCP_PKT_CTL_OPCODE_SHIFT);
53 pkt.pll_index = __cpu_to_le32(pll_index);
54 pkt.value = __cpu_to_le64(freq);
Oded Gabbayd91389b2019-02-16 00:39:19 +020055
56 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
57 SET_CLK_PKT_TIMEOUT, NULL);
58
59 if (rc)
60 dev_err(hdev->dev,
61 "Failed to set frequency to PLL %d, error %d\n",
62 pll_index, rc);
63}
64
65u64 hl_get_max_power(struct hl_device *hdev)
66{
67 struct armcp_packet pkt;
68 long result;
69 int rc;
70
71 memset(&pkt, 0, sizeof(pkt));
72
Oded Gabbay8c844872019-02-28 10:46:24 +020073 pkt.ctl = __cpu_to_le32(ARMCP_PACKET_MAX_POWER_GET <<
74 ARMCP_PKT_CTL_OPCODE_SHIFT);
Oded Gabbayd91389b2019-02-16 00:39:19 +020075
76 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
77 SET_PWR_PKT_TIMEOUT, &result);
78
79 if (rc) {
80 dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
81 result = rc;
82 }
83
84 return result;
85}
86
87void hl_set_max_power(struct hl_device *hdev, u64 value)
88{
89 struct armcp_packet pkt;
90 int rc;
91
92 memset(&pkt, 0, sizeof(pkt));
93
Oded Gabbay8c844872019-02-28 10:46:24 +020094 pkt.ctl = __cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET <<
95 ARMCP_PKT_CTL_OPCODE_SHIFT);
96 pkt.value = __cpu_to_le64(value);
Oded Gabbayd91389b2019-02-16 00:39:19 +020097
98 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
99 SET_PWR_PKT_TIMEOUT, NULL);
100
101 if (rc)
102 dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
103}
104
105static ssize_t pm_mng_profile_show(struct device *dev,
106 struct device_attribute *attr, char *buf)
107{
108 struct hl_device *hdev = dev_get_drvdata(dev);
109
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200110 if (hl_device_disabled_or_in_reset(hdev))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200111 return -ENODEV;
112
113 return sprintf(buf, "%s\n",
114 (hdev->pm_mng_profile == PM_AUTO) ? "auto" :
115 (hdev->pm_mng_profile == PM_MANUAL) ? "manual" :
116 "unknown");
117}
118
119static ssize_t pm_mng_profile_store(struct device *dev,
120 struct device_attribute *attr, const char *buf, size_t count)
121{
122 struct hl_device *hdev = dev_get_drvdata(dev);
123
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200124 if (hl_device_disabled_or_in_reset(hdev)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200125 count = -ENODEV;
126 goto out;
127 }
128
129 mutex_lock(&hdev->fd_open_cnt_lock);
130
131 if (atomic_read(&hdev->fd_open_cnt) > 0) {
132 dev_err(hdev->dev,
133 "Can't change PM profile while user process is opened on the device\n");
134 count = -EPERM;
135 goto unlock_mutex;
136 }
137
138 if (strncmp("auto", buf, strlen("auto")) == 0) {
139 /* Make sure we are in LOW PLL when changing modes */
140 if (hdev->pm_mng_profile == PM_MANUAL) {
141 atomic_set(&hdev->curr_pll_profile, PLL_HIGH);
142 hl_device_set_frequency(hdev, PLL_LOW);
143 hdev->pm_mng_profile = PM_AUTO;
144 }
145 } else if (strncmp("manual", buf, strlen("manual")) == 0) {
146 /* Make sure we are in LOW PLL when changing modes */
147 if (hdev->pm_mng_profile == PM_AUTO) {
148 flush_delayed_work(&hdev->work_freq);
149 hdev->pm_mng_profile = PM_MANUAL;
150 }
151 } else {
152 dev_err(hdev->dev, "value should be auto or manual\n");
153 count = -EINVAL;
154 goto unlock_mutex;
155 }
156
157unlock_mutex:
158 mutex_unlock(&hdev->fd_open_cnt_lock);
159out:
160 return count;
161}
162
163static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
164 char *buf)
165{
166 struct hl_device *hdev = dev_get_drvdata(dev);
167
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200168 if (hl_device_disabled_or_in_reset(hdev))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200169 return -ENODEV;
170
171 return sprintf(buf, "%u\n", hdev->high_pll);
172}
173
174static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
175 const char *buf, size_t count)
176{
177 struct hl_device *hdev = dev_get_drvdata(dev);
178 long value;
179 int rc;
180
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200181 if (hl_device_disabled_or_in_reset(hdev)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200182 count = -ENODEV;
183 goto out;
184 }
185
186 rc = kstrtoul(buf, 0, &value);
187
188 if (rc) {
189 count = -EINVAL;
190 goto out;
191 }
192
193 hdev->high_pll = value;
194
195out:
196 return count;
197}
198
199static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
200 char *buf)
201{
202 struct hl_device *hdev = dev_get_drvdata(dev);
203
204 return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
205}
206
207static ssize_t armcp_kernel_ver_show(struct device *dev,
208 struct device_attribute *attr, char *buf)
209{
210 struct hl_device *hdev = dev_get_drvdata(dev);
211
212 return sprintf(buf, "%s", hdev->asic_prop.armcp_info.kernel_version);
213}
214
215static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
216 char *buf)
217{
218 struct hl_device *hdev = dev_get_drvdata(dev);
219
220 return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.armcp_version);
221}
222
223static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
224 char *buf)
225{
226 struct hl_device *hdev = dev_get_drvdata(dev);
227
228 return sprintf(buf, "0x%08x\n",
229 hdev->asic_prop.armcp_info.cpld_version);
230}
231
232static ssize_t infineon_ver_show(struct device *dev,
233 struct device_attribute *attr, char *buf)
234{
235 struct hl_device *hdev = dev_get_drvdata(dev);
236
237 return sprintf(buf, "0x%04x\n",
238 hdev->asic_prop.armcp_info.infineon_version);
239}
240
241static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
242 char *buf)
243{
244 struct hl_device *hdev = dev_get_drvdata(dev);
245
246 return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.fuse_version);
247}
248
249static ssize_t thermal_ver_show(struct device *dev,
250 struct device_attribute *attr, char *buf)
251{
252 struct hl_device *hdev = dev_get_drvdata(dev);
253
254 return sprintf(buf, "%s", hdev->asic_prop.armcp_info.thermal_version);
255}
256
257static ssize_t preboot_btl_ver_show(struct device *dev,
258 struct device_attribute *attr, char *buf)
259{
260 struct hl_device *hdev = dev_get_drvdata(dev);
261
262 return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
263}
264
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200265static ssize_t soft_reset_store(struct device *dev,
266 struct device_attribute *attr, const char *buf,
267 size_t count)
268{
269 struct hl_device *hdev = dev_get_drvdata(dev);
270 long value;
271 int rc;
272
273 rc = kstrtoul(buf, 0, &value);
274
275 if (rc) {
276 count = -EINVAL;
277 goto out;
278 }
279
280 hl_device_reset(hdev, false, false);
281
282out:
283 return count;
284}
285
286static ssize_t hard_reset_store(struct device *dev,
287 struct device_attribute *attr,
288 const char *buf, size_t count)
289{
290 struct hl_device *hdev = dev_get_drvdata(dev);
291 long value;
292 int rc;
293
294 rc = kstrtoul(buf, 0, &value);
295
296 if (rc) {
297 count = -EINVAL;
298 goto out;
299 }
300
301 hl_device_reset(hdev, true, false);
302
303out:
304 return count;
305}
306
Oded Gabbayd91389b2019-02-16 00:39:19 +0200307static ssize_t device_type_show(struct device *dev,
308 struct device_attribute *attr, char *buf)
309{
310 struct hl_device *hdev = dev_get_drvdata(dev);
311 char *str;
312
313 switch (hdev->asic_type) {
314 case ASIC_GOYA:
315 str = "GOYA";
316 break;
317 default:
318 dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
319 hdev->asic_type);
320 return -EINVAL;
321 }
322
323 return sprintf(buf, "%s\n", str);
324}
325
326static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
327 char *buf)
328{
329 struct hl_device *hdev = dev_get_drvdata(dev);
330
331 /* Use dummy, fixed address for simulator */
332 if (!hdev->pdev)
333 return sprintf(buf, "0000:%02d:00.0\n", hdev->id);
334
335 return sprintf(buf, "%04x:%02x:%02x.%x\n",
336 pci_domain_nr(hdev->pdev->bus),
337 hdev->pdev->bus->number,
338 PCI_SLOT(hdev->pdev->devfn),
339 PCI_FUNC(hdev->pdev->devfn));
340}
341
342static ssize_t status_show(struct device *dev, struct device_attribute *attr,
343 char *buf)
344{
345 struct hl_device *hdev = dev_get_drvdata(dev);
346 char *str;
347
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200348 if (atomic_read(&hdev->in_reset))
349 str = "In reset";
350 else if (hdev->disabled)
Oded Gabbayd91389b2019-02-16 00:39:19 +0200351 str = "Malfunction";
352 else
353 str = "Operational";
354
355 return sprintf(buf, "%s\n", str);
356}
357
358static ssize_t write_open_cnt_show(struct device *dev,
359 struct device_attribute *attr, char *buf)
360{
361 struct hl_device *hdev = dev_get_drvdata(dev);
362
363 return sprintf(buf, "%d\n", hdev->user_ctx ? 1 : 0);
364}
365
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200366static ssize_t soft_reset_cnt_show(struct device *dev,
367 struct device_attribute *attr, char *buf)
368{
369 struct hl_device *hdev = dev_get_drvdata(dev);
370
371 return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
372}
373
374static ssize_t hard_reset_cnt_show(struct device *dev,
375 struct device_attribute *attr, char *buf)
376{
377 struct hl_device *hdev = dev_get_drvdata(dev);
378
379 return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
380}
381
Oded Gabbayd91389b2019-02-16 00:39:19 +0200382static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
383 char *buf)
384{
385 struct hl_device *hdev = dev_get_drvdata(dev);
386 long val;
387
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200388 if (hl_device_disabled_or_in_reset(hdev))
Oded Gabbayd91389b2019-02-16 00:39:19 +0200389 return -ENODEV;
390
391 val = hl_get_max_power(hdev);
392
393 return sprintf(buf, "%lu\n", val);
394}
395
396static ssize_t max_power_store(struct device *dev,
397 struct device_attribute *attr, const char *buf, size_t count)
398{
399 struct hl_device *hdev = dev_get_drvdata(dev);
400 unsigned long value;
401 int rc;
402
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200403 if (hl_device_disabled_or_in_reset(hdev)) {
Oded Gabbayd91389b2019-02-16 00:39:19 +0200404 count = -ENODEV;
405 goto out;
406 }
407
408 rc = kstrtoul(buf, 0, &value);
409
410 if (rc) {
411 count = -EINVAL;
412 goto out;
413 }
414
415 hdev->max_power = value;
416 hl_set_max_power(hdev, value);
417
418out:
419 return count;
420}
421
422static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
423 struct bin_attribute *attr, char *buf, loff_t offset,
424 size_t max_size)
425{
426 struct device *dev = container_of(kobj, struct device, kobj);
427 struct hl_device *hdev = dev_get_drvdata(dev);
428 char *data;
429 int rc;
430
431 if (!max_size)
432 return -EINVAL;
433
434 data = kzalloc(max_size, GFP_KERNEL);
435 if (!data)
436 return -ENOMEM;
437
438 rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
439 if (rc)
440 goto out;
441
442 memcpy(buf, data, max_size);
443
444out:
445 kfree(data);
446
447 return max_size;
448}
449
450static DEVICE_ATTR_RO(armcp_kernel_ver);
451static DEVICE_ATTR_RO(armcp_ver);
452static DEVICE_ATTR_RO(cpld_ver);
453static DEVICE_ATTR_RO(device_type);
454static DEVICE_ATTR_RO(fuse_ver);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200455static DEVICE_ATTR_WO(hard_reset);
456static DEVICE_ATTR_RO(hard_reset_cnt);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200457static DEVICE_ATTR_RW(high_pll);
458static DEVICE_ATTR_RO(infineon_ver);
459static DEVICE_ATTR_RW(max_power);
460static DEVICE_ATTR_RO(pci_addr);
461static DEVICE_ATTR_RW(pm_mng_profile);
462static DEVICE_ATTR_RO(preboot_btl_ver);
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200463static DEVICE_ATTR_WO(soft_reset);
464static DEVICE_ATTR_RO(soft_reset_cnt);
Oded Gabbayd91389b2019-02-16 00:39:19 +0200465static DEVICE_ATTR_RO(status);
466static DEVICE_ATTR_RO(thermal_ver);
467static DEVICE_ATTR_RO(uboot_ver);
468static DEVICE_ATTR_RO(write_open_cnt);
469
470static struct bin_attribute bin_attr_eeprom = {
471 .attr = {.name = "eeprom", .mode = (0444)},
472 .size = PAGE_SIZE,
473 .read = eeprom_read_handler
474};
475
476static struct attribute *hl_dev_attrs[] = {
477 &dev_attr_armcp_kernel_ver.attr,
478 &dev_attr_armcp_ver.attr,
479 &dev_attr_cpld_ver.attr,
480 &dev_attr_device_type.attr,
481 &dev_attr_fuse_ver.attr,
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200482 &dev_attr_hard_reset.attr,
483 &dev_attr_hard_reset_cnt.attr,
Oded Gabbayd91389b2019-02-16 00:39:19 +0200484 &dev_attr_high_pll.attr,
485 &dev_attr_infineon_ver.attr,
486 &dev_attr_max_power.attr,
487 &dev_attr_pci_addr.attr,
488 &dev_attr_pm_mng_profile.attr,
489 &dev_attr_preboot_btl_ver.attr,
Oded Gabbayf8c8c7d52019-02-16 00:39:20 +0200490 &dev_attr_soft_reset.attr,
491 &dev_attr_soft_reset_cnt.attr,
Oded Gabbayd91389b2019-02-16 00:39:19 +0200492 &dev_attr_status.attr,
493 &dev_attr_thermal_ver.attr,
494 &dev_attr_uboot_ver.attr,
495 &dev_attr_write_open_cnt.attr,
496 NULL,
497};
498
499static struct bin_attribute *hl_dev_bin_attrs[] = {
500 &bin_attr_eeprom,
501 NULL
502};
503
504static struct attribute_group hl_dev_attr_group = {
505 .attrs = hl_dev_attrs,
506 .bin_attrs = hl_dev_bin_attrs,
507};
508
509static struct attribute_group hl_dev_clks_attr_group;
510
511static const struct attribute_group *hl_dev_attr_groups[] = {
512 &hl_dev_attr_group,
513 &hl_dev_clks_attr_group,
514 NULL,
515};
516
517int hl_sysfs_init(struct hl_device *hdev)
518{
519 int rc;
520
521 hdev->pm_mng_profile = PM_AUTO;
522 hdev->max_power = hdev->asic_prop.max_power_default;
523
524 hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
525
526 rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
527 if (rc) {
528 dev_err(hdev->dev,
529 "Failed to add groups to device, error %d\n", rc);
530 return rc;
531 }
532
533 return 0;
534}
535
536void hl_sysfs_fini(struct hl_device *hdev)
537{
538 device_remove_groups(hdev->dev, hl_dev_attr_groups);
539}