Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 12#define SET_CLK_PKT_TIMEOUT	1000000	/* 1s */
 13#define SET_PWR_PKT_TIMEOUT	1000000	/* 1s */
 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 = cpu_to_le32(ARMCP_PACKET_FREQUENCY_CURR_GET <<
 25						ARMCP_PKT_CTL_OPCODE_SHIFT);
 26	else
 27		pkt.ctl = cpu_to_le32(ARMCP_PACKET_FREQUENCY_GET <<
 28						ARMCP_PKT_CTL_OPCODE_SHIFT);
 29	pkt.pll_index = cpu_to_le32(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 = 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);
 55
 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
 73	pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_GET <<
 74				ARMCP_PKT_CTL_OPCODE_SHIFT);
 75
 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
 94	pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET <<
 95				ARMCP_PKT_CTL_OPCODE_SHIFT);
 96	pkt.value = cpu_to_le64(value);
 97
 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 uboot_ver_show(struct device *dev, struct device_attribute *attr,
106				char *buf)
107{
108	struct hl_device *hdev = dev_get_drvdata(dev);
109
110	return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
111}
112
113static ssize_t armcp_kernel_ver_show(struct device *dev,
114				struct device_attribute *attr, char *buf)
115{
116	struct hl_device *hdev = dev_get_drvdata(dev);
117
118	return sprintf(buf, "%s", hdev->asic_prop.armcp_info.kernel_version);
119}
120
121static ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
122				char *buf)
123{
124	struct hl_device *hdev = dev_get_drvdata(dev);
125
126	return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.armcp_version);
127}
128
129static ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
130				char *buf)
131{
132	struct hl_device *hdev = dev_get_drvdata(dev);
133
134	return sprintf(buf, "0x%08x\n",
135			hdev->asic_prop.armcp_info.cpld_version);
136}
137
138static ssize_t infineon_ver_show(struct device *dev,
139				struct device_attribute *attr, char *buf)
140{
141	struct hl_device *hdev = dev_get_drvdata(dev);
142
143	return sprintf(buf, "0x%04x\n",
144			hdev->asic_prop.armcp_info.infineon_version);
145}
146
147static ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
148				char *buf)
149{
150	struct hl_device *hdev = dev_get_drvdata(dev);
151
152	return sprintf(buf, "%s\n", hdev->asic_prop.armcp_info.fuse_version);
153}
154
155static ssize_t thermal_ver_show(struct device *dev,
156				struct device_attribute *attr, char *buf)
157{
158	struct hl_device *hdev = dev_get_drvdata(dev);
159
160	return sprintf(buf, "%s", hdev->asic_prop.armcp_info.thermal_version);
161}
162
163static ssize_t preboot_btl_ver_show(struct device *dev,
164				struct device_attribute *attr, char *buf)
165{
166	struct hl_device *hdev = dev_get_drvdata(dev);
167
168	return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
169}
170
171static ssize_t soft_reset_store(struct device *dev,
172				struct device_attribute *attr, const char *buf,
173				size_t count)
174{
175	struct hl_device *hdev = dev_get_drvdata(dev);
176	long value;
177	int rc;
178
179	rc = kstrtoul(buf, 0, &value);
180
181	if (rc) {
182		count = -EINVAL;
183		goto out;
184	}
185
186	hl_device_reset(hdev, false, false);
187
188out:
189	return count;
190}
191
192static ssize_t hard_reset_store(struct device *dev,
193				struct device_attribute *attr,
194				const char *buf, size_t count)
195{
196	struct hl_device *hdev = dev_get_drvdata(dev);
197	long value;
198	int rc;
199
200	rc = kstrtoul(buf, 0, &value);
201
202	if (rc) {
203		count = -EINVAL;
204		goto out;
205	}
206
207	hl_device_reset(hdev, true, false);
208
209out:
210	return count;
211}
212
213static ssize_t device_type_show(struct device *dev,
214		struct device_attribute *attr, char *buf)
215{
216	struct hl_device *hdev = dev_get_drvdata(dev);
217	char *str;
218
219	switch (hdev->asic_type) {
220	case ASIC_GOYA:
221		str = "GOYA";
222		break;
223	default:
224		dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
225				hdev->asic_type);
226		return -EINVAL;
227	}
228
229	return sprintf(buf, "%s\n", str);
230}
231
232static ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
233				char *buf)
234{
235	struct hl_device *hdev = dev_get_drvdata(dev);
236
237	return sprintf(buf, "%04x:%02x:%02x.%x\n",
238			pci_domain_nr(hdev->pdev->bus),
239			hdev->pdev->bus->number,
240			PCI_SLOT(hdev->pdev->devfn),
241			PCI_FUNC(hdev->pdev->devfn));
242}
243
244static ssize_t status_show(struct device *dev, struct device_attribute *attr,
245				char *buf)
246{
247	struct hl_device *hdev = dev_get_drvdata(dev);
248	char *str;
249
250	if (atomic_read(&hdev->in_reset))
251		str = "In reset";
252	else if (hdev->disabled)
253		str = "Malfunction";
254	else
255		str = "Operational";
256
257	return sprintf(buf, "%s\n", str);
258}
259
260static ssize_t soft_reset_cnt_show(struct device *dev,
261		struct device_attribute *attr, char *buf)
262{
263	struct hl_device *hdev = dev_get_drvdata(dev);
264
265	return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
266}
267
268static ssize_t hard_reset_cnt_show(struct device *dev,
269		struct device_attribute *attr, char *buf)
270{
271	struct hl_device *hdev = dev_get_drvdata(dev);
272
273	return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
274}
275
276static ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
277				char *buf)
278{
279	struct hl_device *hdev = dev_get_drvdata(dev);
280	long val;
281
282	if (hl_device_disabled_or_in_reset(hdev))
283		return -ENODEV;
284
285	val = hl_get_max_power(hdev);
286
287	return sprintf(buf, "%lu\n", val);
288}
289
290static ssize_t max_power_store(struct device *dev,
291		struct device_attribute *attr, const char *buf, size_t count)
292{
293	struct hl_device *hdev = dev_get_drvdata(dev);
294	unsigned long value;
295	int rc;
296
297	if (hl_device_disabled_or_in_reset(hdev)) {
298		count = -ENODEV;
299		goto out;
300	}
301
302	rc = kstrtoul(buf, 0, &value);
303
304	if (rc) {
305		count = -EINVAL;
306		goto out;
307	}
308
309	hdev->max_power = value;
310	hl_set_max_power(hdev, value);
311
312out:
313	return count;
314}
315
316static ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
317			struct bin_attribute *attr, char *buf, loff_t offset,
318			size_t max_size)
319{
320	struct device *dev = container_of(kobj, struct device, kobj);
321	struct hl_device *hdev = dev_get_drvdata(dev);
322	char *data;
323	int rc;
324
325	if (!max_size)
326		return -EINVAL;
327
328	data = kzalloc(max_size, GFP_KERNEL);
329	if (!data)
330		return -ENOMEM;
331
332	rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
333	if (rc)
334		goto out;
335
336	memcpy(buf, data, max_size);
337
338out:
339	kfree(data);
340
341	return max_size;
342}
343
344static DEVICE_ATTR_RO(armcp_kernel_ver);
345static DEVICE_ATTR_RO(armcp_ver);
346static DEVICE_ATTR_RO(cpld_ver);
347static DEVICE_ATTR_RO(device_type);
348static DEVICE_ATTR_RO(fuse_ver);
349static DEVICE_ATTR_WO(hard_reset);
350static DEVICE_ATTR_RO(hard_reset_cnt);
351static DEVICE_ATTR_RO(infineon_ver);
352static DEVICE_ATTR_RW(max_power);
353static DEVICE_ATTR_RO(pci_addr);
354static DEVICE_ATTR_RO(preboot_btl_ver);
355static DEVICE_ATTR_WO(soft_reset);
356static DEVICE_ATTR_RO(soft_reset_cnt);
357static DEVICE_ATTR_RO(status);
358static DEVICE_ATTR_RO(thermal_ver);
359static DEVICE_ATTR_RO(uboot_ver);
360
361static struct bin_attribute bin_attr_eeprom = {
362	.attr = {.name = "eeprom", .mode = (0444)},
363	.size = PAGE_SIZE,
364	.read = eeprom_read_handler
365};
366
367static struct attribute *hl_dev_attrs[] = {
368	&dev_attr_armcp_kernel_ver.attr,
369	&dev_attr_armcp_ver.attr,
370	&dev_attr_cpld_ver.attr,
371	&dev_attr_device_type.attr,
372	&dev_attr_fuse_ver.attr,
373	&dev_attr_hard_reset.attr,
374	&dev_attr_hard_reset_cnt.attr,
375	&dev_attr_infineon_ver.attr,
376	&dev_attr_max_power.attr,
377	&dev_attr_pci_addr.attr,
378	&dev_attr_preboot_btl_ver.attr,
379	&dev_attr_soft_reset.attr,
380	&dev_attr_soft_reset_cnt.attr,
381	&dev_attr_status.attr,
382	&dev_attr_thermal_ver.attr,
383	&dev_attr_uboot_ver.attr,
384	NULL,
385};
386
387static struct bin_attribute *hl_dev_bin_attrs[] = {
388	&bin_attr_eeprom,
389	NULL
390};
391
392static struct attribute_group hl_dev_attr_group = {
393	.attrs = hl_dev_attrs,
394	.bin_attrs = hl_dev_bin_attrs,
395};
396
397static struct attribute_group hl_dev_clks_attr_group;
398
399static const struct attribute_group *hl_dev_attr_groups[] = {
400	&hl_dev_attr_group,
401	&hl_dev_clks_attr_group,
402	NULL,
403};
404
405int hl_sysfs_init(struct hl_device *hdev)
406{
407	int rc;
408
409	hdev->pm_mng_profile = PM_AUTO;
410	hdev->max_power = hdev->asic_prop.max_power_default;
411
412	hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
413
414	rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
415	if (rc) {
416		dev_err(hdev->dev,
417			"Failed to add groups to device, error %d\n", rc);
418		return rc;
419	}
420
421	return 0;
422}
423
424void hl_sysfs_fini(struct hl_device *hdev)
425{
426	device_remove_groups(hdev->dev, hl_dev_attr_groups);
427}