blob: 20481fd9ed20ca90804f72aa97b1c36f1538e59b [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
107 if (hdev->disabled)
108 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
121 if (hdev->disabled) {
122 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
165 if (hdev->disabled)
166 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
178 if (hdev->disabled) {
179 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
262static ssize_t device_type_show(struct device *dev,
263 struct device_attribute *attr, char *buf)
264{
265 struct hl_device *hdev = dev_get_drvdata(dev);
266 char *str;
267
268 switch (hdev->asic_type) {
269 case ASIC_GOYA:
270 str = "GOYA";
271 break;
272 default:
273 dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
274 hdev->asic_type);
275 return -EINVAL;
276 }
277
278 return sprintf(buf, "%s\n", str);
279}
280
281static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
282 char *buf)
283{
284 struct hl_device *hdev = dev_get_drvdata(dev);
285
286 /* Use dummy, fixed address for simulator */
287 if (!hdev->pdev)
288 return sprintf(buf, "0000:%02d:00.0\n", hdev->id);
289
290 return sprintf(buf, "%04x:%02x:%02x.%x\n",
291 pci_domain_nr(hdev->pdev->bus),
292 hdev->pdev->bus->number,
293 PCI_SLOT(hdev->pdev->devfn),
294 PCI_FUNC(hdev->pdev->devfn));
295}
296
297static ssize_t status_show(struct device *dev, struct device_attribute *attr,
298 char *buf)
299{
300 struct hl_device *hdev = dev_get_drvdata(dev);
301 char *str;
302
303 if (hdev->disabled)
304 str = "Malfunction";
305 else
306 str = "Operational";
307
308 return sprintf(buf, "%s\n", str);
309}
310
311static ssize_t write_open_cnt_show(struct device *dev,
312 struct device_attribute *attr, char *buf)
313{
314 struct hl_device *hdev = dev_get_drvdata(dev);
315
316 return sprintf(buf, "%d\n", hdev->user_ctx ? 1 : 0);
317}
318
319static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
320 char *buf)
321{
322 struct hl_device *hdev = dev_get_drvdata(dev);
323 long val;
324
325 if (hdev->disabled)
326 return -ENODEV;
327
328 val = hl_get_max_power(hdev);
329
330 return sprintf(buf, "%lu\n", val);
331}
332
333static ssize_t max_power_store(struct device *dev,
334 struct device_attribute *attr, const char *buf, size_t count)
335{
336 struct hl_device *hdev = dev_get_drvdata(dev);
337 unsigned long value;
338 int rc;
339
340 if (hdev->disabled) {
341 count = -ENODEV;
342 goto out;
343 }
344
345 rc = kstrtoul(buf, 0, &value);
346
347 if (rc) {
348 count = -EINVAL;
349 goto out;
350 }
351
352 hdev->max_power = value;
353 hl_set_max_power(hdev, value);
354
355out:
356 return count;
357}
358
359static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
360 struct bin_attribute *attr, char *buf, loff_t offset,
361 size_t max_size)
362{
363 struct device *dev = container_of(kobj, struct device, kobj);
364 struct hl_device *hdev = dev_get_drvdata(dev);
365 char *data;
366 int rc;
367
368 if (!max_size)
369 return -EINVAL;
370
371 data = kzalloc(max_size, GFP_KERNEL);
372 if (!data)
373 return -ENOMEM;
374
375 rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
376 if (rc)
377 goto out;
378
379 memcpy(buf, data, max_size);
380
381out:
382 kfree(data);
383
384 return max_size;
385}
386
387static DEVICE_ATTR_RO(armcp_kernel_ver);
388static DEVICE_ATTR_RO(armcp_ver);
389static DEVICE_ATTR_RO(cpld_ver);
390static DEVICE_ATTR_RO(device_type);
391static DEVICE_ATTR_RO(fuse_ver);
392static DEVICE_ATTR_RW(high_pll);
393static DEVICE_ATTR_RO(infineon_ver);
394static DEVICE_ATTR_RW(max_power);
395static DEVICE_ATTR_RO(pci_addr);
396static DEVICE_ATTR_RW(pm_mng_profile);
397static DEVICE_ATTR_RO(preboot_btl_ver);
398static DEVICE_ATTR_RO(status);
399static DEVICE_ATTR_RO(thermal_ver);
400static DEVICE_ATTR_RO(uboot_ver);
401static DEVICE_ATTR_RO(write_open_cnt);
402
403static struct bin_attribute bin_attr_eeprom = {
404 .attr = {.name = "eeprom", .mode = (0444)},
405 .size = PAGE_SIZE,
406 .read = eeprom_read_handler
407};
408
409static struct attribute *hl_dev_attrs[] = {
410 &dev_attr_armcp_kernel_ver.attr,
411 &dev_attr_armcp_ver.attr,
412 &dev_attr_cpld_ver.attr,
413 &dev_attr_device_type.attr,
414 &dev_attr_fuse_ver.attr,
415 &dev_attr_high_pll.attr,
416 &dev_attr_infineon_ver.attr,
417 &dev_attr_max_power.attr,
418 &dev_attr_pci_addr.attr,
419 &dev_attr_pm_mng_profile.attr,
420 &dev_attr_preboot_btl_ver.attr,
421 &dev_attr_status.attr,
422 &dev_attr_thermal_ver.attr,
423 &dev_attr_uboot_ver.attr,
424 &dev_attr_write_open_cnt.attr,
425 NULL,
426};
427
428static struct bin_attribute *hl_dev_bin_attrs[] = {
429 &bin_attr_eeprom,
430 NULL
431};
432
433static struct attribute_group hl_dev_attr_group = {
434 .attrs = hl_dev_attrs,
435 .bin_attrs = hl_dev_bin_attrs,
436};
437
438static struct attribute_group hl_dev_clks_attr_group;
439
440static const struct attribute_group *hl_dev_attr_groups[] = {
441 &hl_dev_attr_group,
442 &hl_dev_clks_attr_group,
443 NULL,
444};
445
446int hl_sysfs_init(struct hl_device *hdev)
447{
448 int rc;
449
450 hdev->pm_mng_profile = PM_AUTO;
451 hdev->max_power = hdev->asic_prop.max_power_default;
452
453 hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
454
455 rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
456 if (rc) {
457 dev_err(hdev->dev,
458 "Failed to add groups to device, error %d\n", rc);
459 return rc;
460 }
461
462 return 0;
463}
464
465void hl_sysfs_fini(struct hl_device *hdev)
466{
467 device_remove_groups(hdev->dev, hl_dev_attr_groups);
468}