18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci/*
48c2ecf20Sopenharmony_ci * Copyright 2016-2019 HabanaLabs, Ltd.
58c2ecf20Sopenharmony_ci * All Rights Reserved.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "habanalabs.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/pci.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cilong hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	struct cpucp_packet pkt;
158c2ecf20Sopenharmony_ci	long result;
168c2ecf20Sopenharmony_ci	int rc;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	memset(&pkt, 0, sizeof(pkt));
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	if (curr)
218c2ecf20Sopenharmony_ci		pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_CURR_GET <<
228c2ecf20Sopenharmony_ci						CPUCP_PKT_CTL_OPCODE_SHIFT);
238c2ecf20Sopenharmony_ci	else
248c2ecf20Sopenharmony_ci		pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET <<
258c2ecf20Sopenharmony_ci						CPUCP_PKT_CTL_OPCODE_SHIFT);
268c2ecf20Sopenharmony_ci	pkt.pll_index = cpu_to_le32(pll_index);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
298c2ecf20Sopenharmony_ci						0, &result);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	if (rc) {
328c2ecf20Sopenharmony_ci		dev_err(hdev->dev,
338c2ecf20Sopenharmony_ci			"Failed to get frequency of PLL %d, error %d\n",
348c2ecf20Sopenharmony_ci			pll_index, rc);
358c2ecf20Sopenharmony_ci		result = rc;
368c2ecf20Sopenharmony_ci	}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	return result;
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_civoid hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct cpucp_packet pkt;
448c2ecf20Sopenharmony_ci	int rc;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	memset(&pkt, 0, sizeof(pkt));
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET <<
498c2ecf20Sopenharmony_ci					CPUCP_PKT_CTL_OPCODE_SHIFT);
508c2ecf20Sopenharmony_ci	pkt.pll_index = cpu_to_le32(pll_index);
518c2ecf20Sopenharmony_ci	pkt.value = cpu_to_le64(freq);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
548c2ecf20Sopenharmony_ci						0, NULL);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	if (rc)
578c2ecf20Sopenharmony_ci		dev_err(hdev->dev,
588c2ecf20Sopenharmony_ci			"Failed to set frequency to PLL %d, error %d\n",
598c2ecf20Sopenharmony_ci			pll_index, rc);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ciu64 hl_get_max_power(struct hl_device *hdev)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct cpucp_packet pkt;
658c2ecf20Sopenharmony_ci	long result;
668c2ecf20Sopenharmony_ci	int rc;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	memset(&pkt, 0, sizeof(pkt));
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_GET <<
718c2ecf20Sopenharmony_ci				CPUCP_PKT_CTL_OPCODE_SHIFT);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
748c2ecf20Sopenharmony_ci						0, &result);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	if (rc) {
778c2ecf20Sopenharmony_ci		dev_err(hdev->dev, "Failed to get max power, error %d\n", rc);
788c2ecf20Sopenharmony_ci		result = rc;
798c2ecf20Sopenharmony_ci	}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	return result;
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_civoid hl_set_max_power(struct hl_device *hdev)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	struct cpucp_packet pkt;
878c2ecf20Sopenharmony_ci	int rc;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	memset(&pkt, 0, sizeof(pkt));
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_SET <<
928c2ecf20Sopenharmony_ci				CPUCP_PKT_CTL_OPCODE_SHIFT);
938c2ecf20Sopenharmony_ci	pkt.value = cpu_to_le64(hdev->max_power);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
968c2ecf20Sopenharmony_ci						0, NULL);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	if (rc)
998c2ecf20Sopenharmony_ci		dev_err(hdev->dev, "Failed to set max power, error %d\n", rc);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic ssize_t uboot_ver_show(struct device *dev, struct device_attribute *attr,
1038c2ecf20Sopenharmony_ci				char *buf)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", hdev->asic_prop.uboot_ver);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic ssize_t armcp_kernel_ver_show(struct device *dev,
1118c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic ssize_t armcp_ver_show(struct device *dev, struct device_attribute *attr,
1198c2ecf20Sopenharmony_ci				char *buf)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic ssize_t cpld_ver_show(struct device *dev, struct device_attribute *attr,
1278c2ecf20Sopenharmony_ci				char *buf)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	return sprintf(buf, "0x%08x\n",
1328c2ecf20Sopenharmony_ci			hdev->asic_prop.cpucp_info.cpld_version);
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic ssize_t cpucp_kernel_ver_show(struct device *dev,
1368c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.kernel_version);
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic ssize_t cpucp_ver_show(struct device *dev, struct device_attribute *attr,
1448c2ecf20Sopenharmony_ci				char *buf)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.cpucp_version);
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic ssize_t infineon_ver_show(struct device *dev,
1528c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	return sprintf(buf, "0x%04x\n",
1578c2ecf20Sopenharmony_ci			hdev->asic_prop.cpucp_info.infineon_version);
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic ssize_t fuse_ver_show(struct device *dev, struct device_attribute *attr,
1618c2ecf20Sopenharmony_ci				char *buf)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", hdev->asic_prop.cpucp_info.fuse_version);
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic ssize_t thermal_ver_show(struct device *dev,
1698c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	return sprintf(buf, "%s", hdev->asic_prop.cpucp_info.thermal_version);
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic ssize_t preboot_btl_ver_show(struct device *dev,
1778c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", hdev->asic_prop.preboot_ver);
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic ssize_t soft_reset_store(struct device *dev,
1858c2ecf20Sopenharmony_ci				struct device_attribute *attr, const char *buf,
1868c2ecf20Sopenharmony_ci				size_t count)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
1898c2ecf20Sopenharmony_ci	long value;
1908c2ecf20Sopenharmony_ci	int rc;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	rc = kstrtoul(buf, 0, &value);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	if (rc) {
1958c2ecf20Sopenharmony_ci		count = -EINVAL;
1968c2ecf20Sopenharmony_ci		goto out;
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (!hdev->supports_soft_reset) {
2008c2ecf20Sopenharmony_ci		dev_err(hdev->dev, "Device does not support soft-reset\n");
2018c2ecf20Sopenharmony_ci		goto out;
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	dev_warn(hdev->dev, "Soft-Reset requested through sysfs\n");
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	hl_device_reset(hdev, false, false);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ciout:
2098c2ecf20Sopenharmony_ci	return count;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic ssize_t hard_reset_store(struct device *dev,
2138c2ecf20Sopenharmony_ci				struct device_attribute *attr,
2148c2ecf20Sopenharmony_ci				const char *buf, size_t count)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
2178c2ecf20Sopenharmony_ci	long value;
2188c2ecf20Sopenharmony_ci	int rc;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	rc = kstrtoul(buf, 0, &value);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	if (rc) {
2238c2ecf20Sopenharmony_ci		count = -EINVAL;
2248c2ecf20Sopenharmony_ci		goto out;
2258c2ecf20Sopenharmony_ci	}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	dev_warn(hdev->dev, "Hard-Reset requested through sysfs\n");
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	hl_device_reset(hdev, true, false);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ciout:
2328c2ecf20Sopenharmony_ci	return count;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic ssize_t device_type_show(struct device *dev,
2368c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
2398c2ecf20Sopenharmony_ci	char *str;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	switch (hdev->asic_type) {
2428c2ecf20Sopenharmony_ci	case ASIC_GOYA:
2438c2ecf20Sopenharmony_ci		str = "GOYA";
2448c2ecf20Sopenharmony_ci		break;
2458c2ecf20Sopenharmony_ci	case ASIC_GAUDI:
2468c2ecf20Sopenharmony_ci		str = "GAUDI";
2478c2ecf20Sopenharmony_ci		break;
2488c2ecf20Sopenharmony_ci	default:
2498c2ecf20Sopenharmony_ci		dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
2508c2ecf20Sopenharmony_ci				hdev->asic_type);
2518c2ecf20Sopenharmony_ci		return -EINVAL;
2528c2ecf20Sopenharmony_ci	}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", str);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic ssize_t pci_addr_show(struct device *dev, struct device_attribute *attr,
2588c2ecf20Sopenharmony_ci				char *buf)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	return sprintf(buf, "%04x:%02x:%02x.%x\n",
2638c2ecf20Sopenharmony_ci			pci_domain_nr(hdev->pdev->bus),
2648c2ecf20Sopenharmony_ci			hdev->pdev->bus->number,
2658c2ecf20Sopenharmony_ci			PCI_SLOT(hdev->pdev->devfn),
2668c2ecf20Sopenharmony_ci			PCI_FUNC(hdev->pdev->devfn));
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic ssize_t status_show(struct device *dev, struct device_attribute *attr,
2708c2ecf20Sopenharmony_ci				char *buf)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
2738c2ecf20Sopenharmony_ci	char *str;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	if (atomic_read(&hdev->in_reset))
2768c2ecf20Sopenharmony_ci		str = "In reset";
2778c2ecf20Sopenharmony_ci	else if (hdev->disabled)
2788c2ecf20Sopenharmony_ci		str = "Malfunction";
2798c2ecf20Sopenharmony_ci	else
2808c2ecf20Sopenharmony_ci		str = "Operational";
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", str);
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic ssize_t soft_reset_cnt_show(struct device *dev,
2868c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", hdev->soft_reset_cnt);
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_cistatic ssize_t hard_reset_cnt_show(struct device *dev,
2948c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", hdev->hard_reset_cnt);
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_cistatic ssize_t max_power_show(struct device *dev, struct device_attribute *attr,
3028c2ecf20Sopenharmony_ci				char *buf)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
3058c2ecf20Sopenharmony_ci	long val;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (hl_device_disabled_or_in_reset(hdev))
3088c2ecf20Sopenharmony_ci		return -ENODEV;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	val = hl_get_max_power(hdev);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	return sprintf(buf, "%lu\n", val);
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic ssize_t max_power_store(struct device *dev,
3168c2ecf20Sopenharmony_ci		struct device_attribute *attr, const char *buf, size_t count)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
3198c2ecf20Sopenharmony_ci	unsigned long value;
3208c2ecf20Sopenharmony_ci	int rc;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (hl_device_disabled_or_in_reset(hdev)) {
3238c2ecf20Sopenharmony_ci		count = -ENODEV;
3248c2ecf20Sopenharmony_ci		goto out;
3258c2ecf20Sopenharmony_ci	}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	rc = kstrtoul(buf, 0, &value);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	if (rc) {
3308c2ecf20Sopenharmony_ci		count = -EINVAL;
3318c2ecf20Sopenharmony_ci		goto out;
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	hdev->max_power = value;
3358c2ecf20Sopenharmony_ci	hl_set_max_power(hdev);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ciout:
3388c2ecf20Sopenharmony_ci	return count;
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic ssize_t eeprom_read_handler(struct file *filp, struct kobject *kobj,
3428c2ecf20Sopenharmony_ci			struct bin_attribute *attr, char *buf, loff_t offset,
3438c2ecf20Sopenharmony_ci			size_t max_size)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	struct device *dev = container_of(kobj, struct device, kobj);
3468c2ecf20Sopenharmony_ci	struct hl_device *hdev = dev_get_drvdata(dev);
3478c2ecf20Sopenharmony_ci	char *data;
3488c2ecf20Sopenharmony_ci	int rc;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if (hl_device_disabled_or_in_reset(hdev))
3518c2ecf20Sopenharmony_ci		return -ENODEV;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	if (!max_size)
3548c2ecf20Sopenharmony_ci		return -EINVAL;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	data = kzalloc(max_size, GFP_KERNEL);
3578c2ecf20Sopenharmony_ci	if (!data)
3588c2ecf20Sopenharmony_ci		return -ENOMEM;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	rc = hdev->asic_funcs->get_eeprom_data(hdev, data, max_size);
3618c2ecf20Sopenharmony_ci	if (rc)
3628c2ecf20Sopenharmony_ci		goto out;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	memcpy(buf, data, max_size);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ciout:
3678c2ecf20Sopenharmony_ci	kfree(data);
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	return max_size;
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(armcp_kernel_ver);
3738c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(armcp_ver);
3748c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(cpld_ver);
3758c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(cpucp_kernel_ver);
3768c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(cpucp_ver);
3778c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(device_type);
3788c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(fuse_ver);
3798c2ecf20Sopenharmony_cistatic DEVICE_ATTR_WO(hard_reset);
3808c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(hard_reset_cnt);
3818c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(infineon_ver);
3828c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(max_power);
3838c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(pci_addr);
3848c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(preboot_btl_ver);
3858c2ecf20Sopenharmony_cistatic DEVICE_ATTR_WO(soft_reset);
3868c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(soft_reset_cnt);
3878c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(status);
3888c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(thermal_ver);
3898c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(uboot_ver);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_cistatic struct bin_attribute bin_attr_eeprom = {
3928c2ecf20Sopenharmony_ci	.attr = {.name = "eeprom", .mode = (0444)},
3938c2ecf20Sopenharmony_ci	.size = PAGE_SIZE,
3948c2ecf20Sopenharmony_ci	.read = eeprom_read_handler
3958c2ecf20Sopenharmony_ci};
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic struct attribute *hl_dev_attrs[] = {
3988c2ecf20Sopenharmony_ci	&dev_attr_armcp_kernel_ver.attr,
3998c2ecf20Sopenharmony_ci	&dev_attr_armcp_ver.attr,
4008c2ecf20Sopenharmony_ci	&dev_attr_cpld_ver.attr,
4018c2ecf20Sopenharmony_ci	&dev_attr_cpucp_kernel_ver.attr,
4028c2ecf20Sopenharmony_ci	&dev_attr_cpucp_ver.attr,
4038c2ecf20Sopenharmony_ci	&dev_attr_device_type.attr,
4048c2ecf20Sopenharmony_ci	&dev_attr_fuse_ver.attr,
4058c2ecf20Sopenharmony_ci	&dev_attr_hard_reset.attr,
4068c2ecf20Sopenharmony_ci	&dev_attr_hard_reset_cnt.attr,
4078c2ecf20Sopenharmony_ci	&dev_attr_infineon_ver.attr,
4088c2ecf20Sopenharmony_ci	&dev_attr_max_power.attr,
4098c2ecf20Sopenharmony_ci	&dev_attr_pci_addr.attr,
4108c2ecf20Sopenharmony_ci	&dev_attr_preboot_btl_ver.attr,
4118c2ecf20Sopenharmony_ci	&dev_attr_soft_reset.attr,
4128c2ecf20Sopenharmony_ci	&dev_attr_soft_reset_cnt.attr,
4138c2ecf20Sopenharmony_ci	&dev_attr_status.attr,
4148c2ecf20Sopenharmony_ci	&dev_attr_thermal_ver.attr,
4158c2ecf20Sopenharmony_ci	&dev_attr_uboot_ver.attr,
4168c2ecf20Sopenharmony_ci	NULL,
4178c2ecf20Sopenharmony_ci};
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic struct bin_attribute *hl_dev_bin_attrs[] = {
4208c2ecf20Sopenharmony_ci	&bin_attr_eeprom,
4218c2ecf20Sopenharmony_ci	NULL
4228c2ecf20Sopenharmony_ci};
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_cistatic struct attribute_group hl_dev_attr_group = {
4258c2ecf20Sopenharmony_ci	.attrs = hl_dev_attrs,
4268c2ecf20Sopenharmony_ci	.bin_attrs = hl_dev_bin_attrs,
4278c2ecf20Sopenharmony_ci};
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic struct attribute_group hl_dev_clks_attr_group;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic const struct attribute_group *hl_dev_attr_groups[] = {
4328c2ecf20Sopenharmony_ci	&hl_dev_attr_group,
4338c2ecf20Sopenharmony_ci	&hl_dev_clks_attr_group,
4348c2ecf20Sopenharmony_ci	NULL,
4358c2ecf20Sopenharmony_ci};
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ciint hl_sysfs_init(struct hl_device *hdev)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	int rc;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	if (hdev->asic_type == ASIC_GOYA)
4428c2ecf20Sopenharmony_ci		hdev->pm_mng_profile = PM_AUTO;
4438c2ecf20Sopenharmony_ci	else
4448c2ecf20Sopenharmony_ci		hdev->pm_mng_profile = PM_MANUAL;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	hdev->max_power = hdev->asic_prop.max_power_default;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	rc = device_add_groups(hdev->dev, hl_dev_attr_groups);
4518c2ecf20Sopenharmony_ci	if (rc) {
4528c2ecf20Sopenharmony_ci		dev_err(hdev->dev,
4538c2ecf20Sopenharmony_ci			"Failed to add groups to device, error %d\n", rc);
4548c2ecf20Sopenharmony_ci		return rc;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	return 0;
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_civoid hl_sysfs_fini(struct hl_device *hdev)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	device_remove_groups(hdev->dev, hl_dev_attr_groups);
4638c2ecf20Sopenharmony_ci}
464