brintos

brintos / linux-shallow public Read only

0
0
Text · 8.5 KiB · b595721 Raw
388 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/*4 * Copyright 2016-2022 HabanaLabs, Ltd.5 * All Rights Reserved.6 */7 8#include "goyaP.h"9 10void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)11{12	struct goya_device *goya = hdev->asic_specific;13 14	if (!hdev->pdev)15		return;16 17	switch (freq) {18	case PLL_HIGH:19		hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, hdev->high_pll);20		hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, hdev->high_pll);21		hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, hdev->high_pll);22		break;23	case PLL_LOW:24		hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, GOYA_PLL_FREQ_LOW);25		hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, GOYA_PLL_FREQ_LOW);26		hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, GOYA_PLL_FREQ_LOW);27		break;28	case PLL_LAST:29		hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, goya->mme_clk);30		hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, goya->tpc_clk);31		hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, goya->ic_clk);32		break;33	default:34		dev_err(hdev->dev, "unknown frequency setting\n");35	}36}37 38static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,39				char *buf)40{41	struct hl_device *hdev = dev_get_drvdata(dev);42	long value;43 44	if (!hl_device_operational(hdev, NULL))45		return -ENODEV;46 47	value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, false);48 49	if (value < 0)50		return value;51 52	return sprintf(buf, "%lu\n", value);53}54 55static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,56				const char *buf, size_t count)57{58	struct hl_device *hdev = dev_get_drvdata(dev);59	struct goya_device *goya = hdev->asic_specific;60	int rc;61	long value;62 63	if (!hl_device_operational(hdev, NULL)) {64		count = -ENODEV;65		goto fail;66	}67 68	if (goya->pm_mng_profile == PM_AUTO) {69		count = -EPERM;70		goto fail;71	}72 73	rc = kstrtoul(buf, 0, &value);74 75	if (rc) {76		count = -EINVAL;77		goto fail;78	}79 80	hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, value);81	goya->mme_clk = value;82 83fail:84	return count;85}86 87static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,88				char *buf)89{90	struct hl_device *hdev = dev_get_drvdata(dev);91	long value;92 93	if (!hl_device_operational(hdev, NULL))94		return -ENODEV;95 96	value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, false);97 98	if (value < 0)99		return value;100 101	return sprintf(buf, "%lu\n", value);102}103 104static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,105				const char *buf, size_t count)106{107	struct hl_device *hdev = dev_get_drvdata(dev);108	struct goya_device *goya = hdev->asic_specific;109	int rc;110	long value;111 112	if (!hl_device_operational(hdev, NULL)) {113		count = -ENODEV;114		goto fail;115	}116 117	if (goya->pm_mng_profile == PM_AUTO) {118		count = -EPERM;119		goto fail;120	}121 122	rc = kstrtoul(buf, 0, &value);123 124	if (rc) {125		count = -EINVAL;126		goto fail;127	}128 129	hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, value);130	goya->tpc_clk = value;131 132fail:133	return count;134}135 136static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,137				char *buf)138{139	struct hl_device *hdev = dev_get_drvdata(dev);140	long value;141 142	if (!hl_device_operational(hdev, NULL))143		return -ENODEV;144 145	value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, false);146 147	if (value < 0)148		return value;149 150	return sprintf(buf, "%lu\n", value);151}152 153static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,154				const char *buf, size_t count)155{156	struct hl_device *hdev = dev_get_drvdata(dev);157	struct goya_device *goya = hdev->asic_specific;158	int rc;159	long value;160 161	if (!hl_device_operational(hdev, NULL)) {162		count = -ENODEV;163		goto fail;164	}165 166	if (goya->pm_mng_profile == PM_AUTO) {167		count = -EPERM;168		goto fail;169	}170 171	rc = kstrtoul(buf, 0, &value);172 173	if (rc) {174		count = -EINVAL;175		goto fail;176	}177 178	hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, value);179	goya->ic_clk = value;180 181fail:182	return count;183}184 185static ssize_t mme_clk_curr_show(struct device *dev,186				struct device_attribute *attr, char *buf)187{188	struct hl_device *hdev = dev_get_drvdata(dev);189	long value;190 191	if (!hl_device_operational(hdev, NULL))192		return -ENODEV;193 194	value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, true);195 196	if (value < 0)197		return value;198 199	return sprintf(buf, "%lu\n", value);200}201 202static ssize_t tpc_clk_curr_show(struct device *dev,203				struct device_attribute *attr, char *buf)204{205	struct hl_device *hdev = dev_get_drvdata(dev);206	long value;207 208	if (!hl_device_operational(hdev, NULL))209		return -ENODEV;210 211	value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, true);212 213	if (value < 0)214		return value;215 216	return sprintf(buf, "%lu\n", value);217}218 219static ssize_t ic_clk_curr_show(struct device *dev,220				struct device_attribute *attr, char *buf)221{222	struct hl_device *hdev = dev_get_drvdata(dev);223	long value;224 225	if (!hl_device_operational(hdev, NULL))226		return -ENODEV;227 228	value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, true);229 230	if (value < 0)231		return value;232 233	return sprintf(buf, "%lu\n", value);234}235 236static ssize_t pm_mng_profile_show(struct device *dev,237				struct device_attribute *attr, char *buf)238{239	struct hl_device *hdev = dev_get_drvdata(dev);240	struct goya_device *goya = hdev->asic_specific;241 242	if (!hl_device_operational(hdev, NULL))243		return -ENODEV;244 245	return sprintf(buf, "%s\n",246			(goya->pm_mng_profile == PM_AUTO) ? "auto" :247			(goya->pm_mng_profile == PM_MANUAL) ? "manual" :248			"unknown");249}250 251static ssize_t pm_mng_profile_store(struct device *dev,252		struct device_attribute *attr, const char *buf, size_t count)253{254	struct hl_device *hdev = dev_get_drvdata(dev);255	struct goya_device *goya = hdev->asic_specific;256 257	if (!hl_device_operational(hdev, NULL)) {258		count = -ENODEV;259		goto out;260	}261 262	mutex_lock(&hdev->fpriv_list_lock);263 264	if (hdev->is_compute_ctx_active) {265		dev_err(hdev->dev,266			"Can't change PM profile while compute context is opened on the device\n");267		count = -EPERM;268		goto unlock_mutex;269	}270 271	if (strncmp("auto", buf, strlen("auto")) == 0) {272		/* Make sure we are in LOW PLL when changing modes */273		if (goya->pm_mng_profile == PM_MANUAL) {274			goya->curr_pll_profile = PLL_HIGH;275			goya->pm_mng_profile = PM_AUTO;276			goya_set_frequency(hdev, PLL_LOW);277		}278	} else if (strncmp("manual", buf, strlen("manual")) == 0) {279		if (goya->pm_mng_profile == PM_AUTO) {280			/* Must release the lock because the work thread also281			 * takes this lock. But before we release it, set282			 * the mode to manual so nothing will change if a user283			 * suddenly opens the device284			 */285			goya->pm_mng_profile = PM_MANUAL;286 287			mutex_unlock(&hdev->fpriv_list_lock);288 289			/* Flush the current work so we can return to the user290			 * knowing that he is the only one changing frequencies291			 */292			if (goya->goya_work)293				flush_delayed_work(&goya->goya_work->work_freq);294 295			return count;296		}297	} else {298		dev_err(hdev->dev, "value should be auto or manual\n");299		count = -EINVAL;300	}301 302unlock_mutex:303	mutex_unlock(&hdev->fpriv_list_lock);304out:305	return count;306}307 308static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,309				char *buf)310{311	struct hl_device *hdev = dev_get_drvdata(dev);312 313	if (!hl_device_operational(hdev, NULL))314		return -ENODEV;315 316	return sprintf(buf, "%u\n", hdev->high_pll);317}318 319static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,320				const char *buf, size_t count)321{322	struct hl_device *hdev = dev_get_drvdata(dev);323	long value;324	int rc;325 326	if (!hl_device_operational(hdev, NULL)) {327		count = -ENODEV;328		goto out;329	}330 331	rc = kstrtoul(buf, 0, &value);332 333	if (rc) {334		count = -EINVAL;335		goto out;336	}337 338	hdev->high_pll = value;339 340out:341	return count;342}343 344static DEVICE_ATTR_RW(high_pll);345static DEVICE_ATTR_RW(ic_clk);346static DEVICE_ATTR_RO(ic_clk_curr);347static DEVICE_ATTR_RW(mme_clk);348static DEVICE_ATTR_RO(mme_clk_curr);349static DEVICE_ATTR_RW(pm_mng_profile);350static DEVICE_ATTR_RW(tpc_clk);351static DEVICE_ATTR_RO(tpc_clk_curr);352 353static struct attribute *goya_clk_dev_attrs[] = {354	&dev_attr_high_pll.attr,355	&dev_attr_ic_clk.attr,356	&dev_attr_ic_clk_curr.attr,357	&dev_attr_mme_clk.attr,358	&dev_attr_mme_clk_curr.attr,359	&dev_attr_pm_mng_profile.attr,360	&dev_attr_tpc_clk.attr,361	&dev_attr_tpc_clk_curr.attr,362	NULL,363};364 365static ssize_t infineon_ver_show(struct device *dev, struct device_attribute *attr, char *buf)366{367	struct hl_device *hdev = dev_get_drvdata(dev);368	struct cpucp_info *cpucp_info;369 370	cpucp_info = &hdev->asic_prop.cpucp_info;371 372	return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));373}374 375static DEVICE_ATTR_RO(infineon_ver);376 377static struct attribute *goya_vrm_dev_attrs[] = {378	&dev_attr_infineon_ver.attr,379	NULL,380};381 382void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp,383				struct attribute_group *dev_vrm_attr_grp)384{385	dev_clk_attr_grp->attrs = goya_clk_dev_attrs;386	dev_vrm_attr_grp->attrs = goya_vrm_dev_attrs;387}388