1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright 2016-2022 HabanaLabs, Ltd.
10 void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
12 struct goya_device *goya = hdev->asic_specific;
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);
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);
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);
34 dev_err(hdev->dev, "unknown frequency setting\n");
38 static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
41 struct hl_device *hdev = dev_get_drvdata(dev);
44 if (!hl_device_operational(hdev, NULL))
47 value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, false);
52 return sprintf(buf, "%lu\n", value);
55 static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
56 const char *buf, size_t count)
58 struct hl_device *hdev = dev_get_drvdata(dev);
59 struct goya_device *goya = hdev->asic_specific;
63 if (!hl_device_operational(hdev, NULL)) {
68 if (goya->pm_mng_profile == PM_AUTO) {
73 rc = kstrtoul(buf, 0, &value);
80 hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, value);
81 goya->mme_clk = value;
87 static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
90 struct hl_device *hdev = dev_get_drvdata(dev);
93 if (!hl_device_operational(hdev, NULL))
96 value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, false);
101 return sprintf(buf, "%lu\n", value);
104 static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
105 const char *buf, size_t count)
107 struct hl_device *hdev = dev_get_drvdata(dev);
108 struct goya_device *goya = hdev->asic_specific;
112 if (!hl_device_operational(hdev, NULL)) {
117 if (goya->pm_mng_profile == PM_AUTO) {
122 rc = kstrtoul(buf, 0, &value);
129 hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, value);
130 goya->tpc_clk = value;
136 static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
139 struct hl_device *hdev = dev_get_drvdata(dev);
142 if (!hl_device_operational(hdev, NULL))
145 value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, false);
150 return sprintf(buf, "%lu\n", value);
153 static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
154 const char *buf, size_t count)
156 struct hl_device *hdev = dev_get_drvdata(dev);
157 struct goya_device *goya = hdev->asic_specific;
161 if (!hl_device_operational(hdev, NULL)) {
166 if (goya->pm_mng_profile == PM_AUTO) {
171 rc = kstrtoul(buf, 0, &value);
178 hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, value);
179 goya->ic_clk = value;
185 static ssize_t mme_clk_curr_show(struct device *dev,
186 struct device_attribute *attr, char *buf)
188 struct hl_device *hdev = dev_get_drvdata(dev);
191 if (!hl_device_operational(hdev, NULL))
194 value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, true);
199 return sprintf(buf, "%lu\n", value);
202 static ssize_t tpc_clk_curr_show(struct device *dev,
203 struct device_attribute *attr, char *buf)
205 struct hl_device *hdev = dev_get_drvdata(dev);
208 if (!hl_device_operational(hdev, NULL))
211 value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, true);
216 return sprintf(buf, "%lu\n", value);
219 static ssize_t ic_clk_curr_show(struct device *dev,
220 struct device_attribute *attr, char *buf)
222 struct hl_device *hdev = dev_get_drvdata(dev);
225 if (!hl_device_operational(hdev, NULL))
228 value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, true);
233 return sprintf(buf, "%lu\n", value);
236 static ssize_t pm_mng_profile_show(struct device *dev,
237 struct device_attribute *attr, char *buf)
239 struct hl_device *hdev = dev_get_drvdata(dev);
240 struct goya_device *goya = hdev->asic_specific;
242 if (!hl_device_operational(hdev, NULL))
245 return sprintf(buf, "%s\n",
246 (goya->pm_mng_profile == PM_AUTO) ? "auto" :
247 (goya->pm_mng_profile == PM_MANUAL) ? "manual" :
251 static ssize_t pm_mng_profile_store(struct device *dev,
252 struct device_attribute *attr, const char *buf, size_t count)
254 struct hl_device *hdev = dev_get_drvdata(dev);
255 struct goya_device *goya = hdev->asic_specific;
257 if (!hl_device_operational(hdev, NULL)) {
262 mutex_lock(&hdev->fpriv_list_lock);
264 if (hdev->is_compute_ctx_active) {
266 "Can't change PM profile while compute context is opened on the device\n");
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);
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 also
281 * takes this lock. But before we release it, set
282 * the mode to manual so nothing will change if a user
283 * suddenly opens the device
285 goya->pm_mng_profile = PM_MANUAL;
287 mutex_unlock(&hdev->fpriv_list_lock);
289 /* Flush the current work so we can return to the user
290 * knowing that he is the only one changing frequencies
293 flush_delayed_work(&goya->goya_work->work_freq);
298 dev_err(hdev->dev, "value should be auto or manual\n");
303 mutex_unlock(&hdev->fpriv_list_lock);
308 static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
311 struct hl_device *hdev = dev_get_drvdata(dev);
313 if (!hl_device_operational(hdev, NULL))
316 return sprintf(buf, "%u\n", hdev->high_pll);
319 static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
320 const char *buf, size_t count)
322 struct hl_device *hdev = dev_get_drvdata(dev);
326 if (!hl_device_operational(hdev, NULL)) {
331 rc = kstrtoul(buf, 0, &value);
338 hdev->high_pll = value;
344 static DEVICE_ATTR_RW(high_pll);
345 static DEVICE_ATTR_RW(ic_clk);
346 static DEVICE_ATTR_RO(ic_clk_curr);
347 static DEVICE_ATTR_RW(mme_clk);
348 static DEVICE_ATTR_RO(mme_clk_curr);
349 static DEVICE_ATTR_RW(pm_mng_profile);
350 static DEVICE_ATTR_RW(tpc_clk);
351 static DEVICE_ATTR_RO(tpc_clk_curr);
353 static 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,
365 static ssize_t infineon_ver_show(struct device *dev, struct device_attribute *attr, char *buf)
367 struct hl_device *hdev = dev_get_drvdata(dev);
368 struct cpucp_info *cpucp_info;
370 cpucp_info = &hdev->asic_prop.cpucp_info;
372 return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));
375 static DEVICE_ATTR_RO(infineon_ver);
377 static struct attribute *goya_vrm_dev_attrs[] = {
378 &dev_attr_infineon_ver.attr,
382 void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp,
383 struct attribute_group *dev_vrm_attr_grp)
385 dev_clk_attr_grp->attrs = goya_clk_dev_attrs;
386 dev_vrm_attr_grp->attrs = goya_vrm_dev_attrs;