1// 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
12long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
13{
14	struct cpucp_packet pkt;
15	long result;
16	int rc;
17
18	memset(&pkt, 0, sizeof(pkt));
19
20	if (curr)
21		pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_CURR_GET <<
22						CPUCP_PKT_CTL_OPCODE_SHIFT);
23	else
24		pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET <<
25						CPUCP_PKT_CTL_OPCODE_SHIFT);
26	pkt.pll_index = cpu_to_le32(pll_index);
27
28	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
29						0, &result);
30
31	if (rc) {
32		dev_err(hdev->dev,
33			"Failed to get frequency of PLL %d, error %d\n",
34			pll_index, rc);
35		result = rc;
36	}
37
38	return result;
39}
40
41void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
42{
43	struct cpucp_packet pkt;
44	int rc;
45
46	memset(&pkt, 0, sizeof(pkt));
47
48	pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET <<
49					CPUCP_PKT_CTL_OPCODE_SHIFT);
50	pkt.pll_index = cpu_to_le32(pll_index);
51	pkt.value = cpu_to_le64(freq);
52
53	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
54						0, NULL);
55
56	if (rc)
57		dev_err(hdev->dev,
58			"Failed to set frequency to PLL %d, error %d\n",
59			pll_index, rc);
60}
61
62u64 hl_get_max_power(struct hl_device *hdev)
63{
64	struct cpucp_packet pkt;
65	long result;
66	int rc;
67
68	memset(&pkt, 0, sizeof(pkt));
69
70	pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_GET <<
71				CPUCP_PKT_CTL_OPCODE_SHIFT);
72
73	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
74						0, &result);
75
76	if (rc) {
77		dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
78		result = rc;
79	}
80
81	return result;
82}
83
84void hl_set_max_power(struct hl_device *hdev)
85{
86	struct cpucp_packet pkt;
87	int rc;
88
89	memset(&pkt, 0, sizeof(pkt));
90
91	pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_SET <<
92				CPUCP_PKT_CTL_OPCODE_SHIFT);
93	pkt.value = cpu_to_le64(hdev->max_power);
94
95	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
96						0, NULL);
97
98	if (rc)
99		dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
100}
101
102static ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
103				char *buf)
104{
105	struct hl_device *hdev = dev_get_drvdata(dev);
106
107	return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
108}
109
110static ssize_t armcp_kernel_ver_show(struct device *dev,
111				struct device_attribute *attr, char *buf)
112{
113	struct hl_device *hdev = dev_get_drvdata(dev);
114
115	return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);
116}
117
118static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
119				char *buf)
120{
121	struct hl_device *hdev = dev_get_drvdata(dev);
122
123	return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);
124}
125
126static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
127				char *buf)
128{
129	struct hl_device *hdev = dev_get_drvdata(dev);
130
131	return sprintf(buf, "0x%08x\n",
132			hdev->asic_prop.cpucp_info.cpld_version);
133}
134
135static ssize_t cpucp_kernel_ver_show(struct device *dev,
136				struct device_attribute *attr, char *buf)
137{
138	struct hl_device *hdev = dev_get_drvdata(dev);
139
140	return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);
141}
142
143static ssize_t cpucp_ver_show(struct device *dev, struct device_attribute *attr,
144				char *buf)
145{
146	struct hl_device *hdev = dev_get_drvdata(dev);
147
148	return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);
149}
150
151static ssize_t infineon_ver_show(struct device *dev,
152				struct device_attribute *attr, char *buf)
153{
154	struct hl_device *hdev = dev_get_drvdata(dev);
155
156	return sprintf(buf, "0x%04x\n",
157			hdev->asic_prop.cpucp_info.infineon_version);
158}
159
160static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
161				char *buf)
162{
163	struct hl_device *hdev = dev_get_drvdata(dev);
164
165	return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.fuse_version);
166}
167
168static ssize_t thermal_ver_show(struct device *dev,
169				struct device_attribute *attr, char *buf)
170{
171	struct hl_device *hdev = dev_get_drvdata(dev);
172
173	return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.thermal_version);
174}
175
176static ssize_t preboot_btl_ver_show(struct device *dev,
177				struct device_attribute *attr, char *buf)
178{
179	struct hl_device *hdev = dev_get_drvdata(dev);
180
181	return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
182}
183
184static ssize_t soft_reset_store(struct device *dev,
185				struct device_attribute *attr, const char *buf,
186				size_t count)
187{
188	struct hl_device *hdev = dev_get_drvdata(dev);
189	long value;
190	int rc;
191
192	rc = kstrtoul(buf, 0, &value);
193
194	if (rc) {
195		count = -EINVAL;
196		goto out;
197	}
198
199	if (!hdev->supports_soft_reset) {
200		dev_err(hdev->dev, "Device does not support soft-reset\n");
201		goto out;
202	}
203
204	dev_warn(hdev->dev, "Soft-Reset requested through sysfs\n");
205
206	hl_device_reset(hdev, false, false);
207
208out:
209	return count;
210}
211
212static ssize_t hard_reset_store(struct device *dev,
213				struct device_attribute *attr,
214				const char *buf, size_t count)
215{
216	struct hl_device *hdev = dev_get_drvdata(dev);
217	long value;
218	int rc;
219
220	rc = kstrtoul(buf, 0, &value);
221
222	if (rc) {
223		count = -EINVAL;
224		goto out;
225	}
226
227	dev_warn(hdev->dev, "Hard-Reset requested through sysfs\n");
228
229	hl_device_reset(hdev, true, false);
230
231out:
232	return count;
233}
234
235static ssize_t device_type_show(struct device *dev,
236		struct device_attribute *attr, char *buf)
237{
238	struct hl_device *hdev = dev_get_drvdata(dev);
239	char *str;
240
241	switch (hdev->asic_type) {
242	case ASIC_GOYA:
243		str = "GOYA";
244		break;
245	case ASIC_GAUDI:
246		str = "GAUDI";
247		break;
248	default:
249		dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
250				hdev->asic_type);
251		return -EINVAL;
252	}
253
254	return sprintf(buf, "%s\n", str);
255}
256
257static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
258				char *buf)
259{
260	struct hl_device *hdev = dev_get_drvdata(dev);
261
262	return sprintf(buf, "%04x:%02x:%02x.%x\n",
263			pci_domain_nr(hdev->pdev->bus),
264			hdev->pdev->bus->number,
265			PCI_SLOT(hdev->pdev->devfn),
266			PCI_FUNC(hdev->pdev->devfn));
267}
268
269static ssize_t status_show(struct device *dev, struct device_attribute *attr,
270				char *buf)
271{
272	struct hl_device *hdev = dev_get_drvdata(dev);
273	char *str;
274
275	if (atomic_read(&hdev->in_reset))
276		str = "In reset";
277	else if (hdev->disabled)
278		str = "Malfunction";
279	else
280		str = "Operational";
281
282	return sprintf(buf, "%s\n", str);
283}
284
285static ssize_t soft_reset_cnt_show(struct device *dev,
286		struct device_attribute *attr, char *buf)
287{
288	struct hl_device *hdev = dev_get_drvdata(dev);
289
290	return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
291}
292
293static ssize_t hard_reset_cnt_show(struct device *dev,
294		struct device_attribute *attr, char *buf)
295{
296	struct hl_device *hdev = dev_get_drvdata(dev);
297
298	return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
299}
300
301static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
302				char *buf)
303{
304	struct hl_device *hdev = dev_get_drvdata(dev);
305	long val;
306
307	if (hl_device_disabled_or_in_reset(hdev))
308		return -ENODEV;
309
310	val = hl_get_max_power(hdev);
311
312	return sprintf(buf, "%lu\n", val);
313}
314
315static ssize_t max_power_store(struct device *dev,
316		struct device_attribute *attr, const char *buf, size_t count)
317{
318	struct hl_device *hdev = dev_get_drvdata(dev);
319	unsigned long value;
320	int rc;
321
322	if (hl_device_disabled_or_in_reset(hdev)) {
323		count = -ENODEV;
324		goto out;
325	}
326
327	rc = kstrtoul(buf, 0, &value);
328
329	if (rc) {
330		count = -EINVAL;
331		goto out;
332	}
333
334	hdev->max_power = value;
335	hl_set_max_power(hdev);
336
337out:
338	return count;
339}
340
341static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
342			struct bin_attribute *attr, char *buf, loff_t offset,
343			size_t max_size)
344{
345	struct device *dev = container_of(kobj, struct device, kobj);
346	struct hl_device *hdev = dev_get_drvdata(dev);
347	char *data;
348	int rc;
349
350	if (hl_device_disabled_or_in_reset(hdev))
351		return -ENODEV;
352
353	if (!max_size)
354		return -EINVAL;
355
356	data = kzalloc(max_size, GFP_KERNEL);
357	if (!data)
358		return -ENOMEM;
359
360	rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
361	if (rc)
362		goto out;
363
364	memcpy(buf, data, max_size);
365
366out:
367	kfree(data);
368
369	return max_size;
370}
371
372static DEVICE_ATTR_RO(armcp_kernel_ver);
373static DEVICE_ATTR_RO(armcp_ver);
374static DEVICE_ATTR_RO(cpld_ver);
375static DEVICE_ATTR_RO(cpucp_kernel_ver);
376static DEVICE_ATTR_RO(cpucp_ver);
377static DEVICE_ATTR_RO(device_type);
378static DEVICE_ATTR_RO(fuse_ver);
379static DEVICE_ATTR_WO(hard_reset);
380static DEVICE_ATTR_RO(hard_reset_cnt);
381static DEVICE_ATTR_RO(infineon_ver);
382static DEVICE_ATTR_RW(max_power);
383static DEVICE_ATTR_RO(pci_addr);
384static DEVICE_ATTR_RO(preboot_btl_ver);
385static DEVICE_ATTR_WO(soft_reset);
386static DEVICE_ATTR_RO(soft_reset_cnt);
387static DEVICE_ATTR_RO(status);
388static DEVICE_ATTR_RO(thermal_ver);
389static DEVICE_ATTR_RO(uboot_ver);
390
391static struct bin_attribute bin_attr_eeprom = {
392	.attr = {.name = "eeprom", .mode = (0444)},
393	.size = PAGE_SIZE,
394	.read = eeprom_read_handler
395};
396
397static struct attribute *hl_dev_attrs[] = {
398	&dev_attr_armcp_kernel_ver.attr,
399	&dev_attr_armcp_ver.attr,
400	&dev_attr_cpld_ver.attr,
401	&dev_attr_cpucp_kernel_ver.attr,
402	&dev_attr_cpucp_ver.attr,
403	&dev_attr_device_type.attr,
404	&dev_attr_fuse_ver.attr,
405	&dev_attr_hard_reset.attr,
406	&dev_attr_hard_reset_cnt.attr,
407	&dev_attr_infineon_ver.attr,
408	&dev_attr_max_power.attr,
409	&dev_attr_pci_addr.attr,
410	&dev_attr_preboot_btl_ver.attr,
411	&dev_attr_soft_reset.attr,
412	&dev_attr_soft_reset_cnt.attr,
413	&dev_attr_status.attr,
414	&dev_attr_thermal_ver.attr,
415	&dev_attr_uboot_ver.attr,
416	NULL,
417};
418
419static struct bin_attribute *hl_dev_bin_attrs[] = {
420	&bin_attr_eeprom,
421	NULL
422};
423
424static struct attribute_group hl_dev_attr_group = {
425	.attrs = hl_dev_attrs,
426	.bin_attrs = hl_dev_bin_attrs,
427};
428
429static struct attribute_group hl_dev_clks_attr_group;
430
431static const struct attribute_group *hl_dev_attr_groups[] = {
432	&hl_dev_attr_group,
433	&hl_dev_clks_attr_group,
434	NULL,
435};
436
437int hl_sysfs_init(struct hl_device *hdev)
438{
439	int rc;
440
441	if (hdev->asic_type == ASIC_GOYA)
442		hdev->pm_mng_profile = PM_AUTO;
443	else
444		hdev->pm_mng_profile = PM_MANUAL;
445
446	hdev->max_power = hdev->asic_prop.max_power_default;
447
448	hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
449
450	rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
451	if (rc) {
452		dev_err(hdev->dev,
453			"Failed to add groups to device, error %d\n", rc);
454		return rc;
455	}
456
457	return 0;
458}
459
460void hl_sysfs_fini(struct hl_device *hdev)
461{
462	device_remove_groups(hdev->dev, hl_dev_attr_groups);
463}
464