1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright 2016-2019 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;
16 hl_set_frequency(hdev, MME_PLL, hdev->high_pll);
17 hl_set_frequency(hdev, TPC_PLL, hdev->high_pll);
18 hl_set_frequency(hdev, IC_PLL, hdev->high_pll);
21 hl_set_frequency(hdev, MME_PLL, GOYA_PLL_FREQ_LOW);
22 hl_set_frequency(hdev, TPC_PLL, GOYA_PLL_FREQ_LOW);
23 hl_set_frequency(hdev, IC_PLL, GOYA_PLL_FREQ_LOW);
26 hl_set_frequency(hdev, MME_PLL, goya->mme_clk);
27 hl_set_frequency(hdev, TPC_PLL, goya->tpc_clk);
28 hl_set_frequency(hdev, IC_PLL, goya->ic_clk);
31 dev_err(hdev->dev, "unknown frequency setting\n");
35 int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
39 if (hl_device_disabled_or_in_reset(hdev))
42 value = hl_get_frequency(hdev, MME_PLL, false);
45 dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n",
50 *max_clk = (value / 1000 / 1000);
52 value = hl_get_frequency(hdev, MME_PLL, true);
56 "Failed to retrieve device current clock %ld\n",
61 *cur_clk = (value / 1000 / 1000);
66 static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
69 struct hl_device *hdev = dev_get_drvdata(dev);
72 if (hl_device_disabled_or_in_reset(hdev))
75 value = hl_get_frequency(hdev, MME_PLL, false);
80 return sprintf(buf, "%lu\n", value);
83 static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
84 const char *buf, size_t count)
86 struct hl_device *hdev = dev_get_drvdata(dev);
87 struct goya_device *goya = hdev->asic_specific;
91 if (hl_device_disabled_or_in_reset(hdev)) {
96 if (hdev->pm_mng_profile == PM_AUTO) {
101 rc = kstrtoul(buf, 0, &value);
108 hl_set_frequency(hdev, MME_PLL, value);
109 goya->mme_clk = value;
115 static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
118 struct hl_device *hdev = dev_get_drvdata(dev);
121 if (hl_device_disabled_or_in_reset(hdev))
124 value = hl_get_frequency(hdev, TPC_PLL, false);
129 return sprintf(buf, "%lu\n", value);
132 static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
133 const char *buf, size_t count)
135 struct hl_device *hdev = dev_get_drvdata(dev);
136 struct goya_device *goya = hdev->asic_specific;
140 if (hl_device_disabled_or_in_reset(hdev)) {
145 if (hdev->pm_mng_profile == PM_AUTO) {
150 rc = kstrtoul(buf, 0, &value);
157 hl_set_frequency(hdev, TPC_PLL, value);
158 goya->tpc_clk = value;
164 static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
167 struct hl_device *hdev = dev_get_drvdata(dev);
170 if (hl_device_disabled_or_in_reset(hdev))
173 value = hl_get_frequency(hdev, IC_PLL, false);
178 return sprintf(buf, "%lu\n", value);
181 static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
182 const char *buf, size_t count)
184 struct hl_device *hdev = dev_get_drvdata(dev);
185 struct goya_device *goya = hdev->asic_specific;
189 if (hl_device_disabled_or_in_reset(hdev)) {
194 if (hdev->pm_mng_profile == PM_AUTO) {
199 rc = kstrtoul(buf, 0, &value);
206 hl_set_frequency(hdev, IC_PLL, value);
207 goya->ic_clk = value;
213 static ssize_t mme_clk_curr_show(struct device *dev,
214 struct device_attribute *attr, char *buf)
216 struct hl_device *hdev = dev_get_drvdata(dev);
219 if (hl_device_disabled_or_in_reset(hdev))
222 value = hl_get_frequency(hdev, MME_PLL, true);
227 return sprintf(buf, "%lu\n", value);
230 static ssize_t tpc_clk_curr_show(struct device *dev,
231 struct device_attribute *attr, char *buf)
233 struct hl_device *hdev = dev_get_drvdata(dev);
236 if (hl_device_disabled_or_in_reset(hdev))
239 value = hl_get_frequency(hdev, TPC_PLL, true);
244 return sprintf(buf, "%lu\n", value);
247 static ssize_t ic_clk_curr_show(struct device *dev,
248 struct device_attribute *attr, char *buf)
250 struct hl_device *hdev = dev_get_drvdata(dev);
253 if (hl_device_disabled_or_in_reset(hdev))
256 value = hl_get_frequency(hdev, IC_PLL, true);
261 return sprintf(buf, "%lu\n", value);
264 static ssize_t pm_mng_profile_show(struct device *dev,
265 struct device_attribute *attr, char *buf)
267 struct hl_device *hdev = dev_get_drvdata(dev);
269 if (hl_device_disabled_or_in_reset(hdev))
272 return sprintf(buf, "%s\n",
273 (hdev->pm_mng_profile == PM_AUTO) ? "auto" :
274 (hdev->pm_mng_profile == PM_MANUAL) ? "manual" :
278 static ssize_t pm_mng_profile_store(struct device *dev,
279 struct device_attribute *attr, const char *buf, size_t count)
281 struct hl_device *hdev = dev_get_drvdata(dev);
283 if (hl_device_disabled_or_in_reset(hdev)) {
288 mutex_lock(&hdev->fpriv_list_lock);
290 if (hdev->compute_ctx) {
292 "Can't change PM profile while compute context is opened on the device\n");
297 if (strncmp("auto", buf, strlen("auto")) == 0) {
298 /* Make sure we are in LOW PLL when changing modes */
299 if (hdev->pm_mng_profile == PM_MANUAL) {
300 hdev->curr_pll_profile = PLL_HIGH;
301 hdev->pm_mng_profile = PM_AUTO;
302 hl_device_set_frequency(hdev, PLL_LOW);
304 } else if (strncmp("manual", buf, strlen("manual")) == 0) {
305 if (hdev->pm_mng_profile == PM_AUTO) {
306 /* Must release the lock because the work thread also
307 * takes this lock. But before we release it, set
308 * the mode to manual so nothing will change if a user
309 * suddenly opens the device
311 hdev->pm_mng_profile = PM_MANUAL;
313 mutex_unlock(&hdev->fpriv_list_lock);
315 /* Flush the current work so we can return to the user
316 * knowing that he is the only one changing frequencies
318 flush_delayed_work(&hdev->work_freq);
323 dev_err(hdev->dev, "value should be auto or manual\n");
328 mutex_unlock(&hdev->fpriv_list_lock);
333 static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
336 struct hl_device *hdev = dev_get_drvdata(dev);
338 if (hl_device_disabled_or_in_reset(hdev))
341 return sprintf(buf, "%u\n", hdev->high_pll);
344 static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
345 const char *buf, size_t count)
347 struct hl_device *hdev = dev_get_drvdata(dev);
351 if (hl_device_disabled_or_in_reset(hdev)) {
356 rc = kstrtoul(buf, 0, &value);
363 hdev->high_pll = value;
369 static DEVICE_ATTR_RW(high_pll);
370 static DEVICE_ATTR_RW(ic_clk);
371 static DEVICE_ATTR_RO(ic_clk_curr);
372 static DEVICE_ATTR_RW(mme_clk);
373 static DEVICE_ATTR_RO(mme_clk_curr);
374 static DEVICE_ATTR_RW(pm_mng_profile);
375 static DEVICE_ATTR_RW(tpc_clk);
376 static DEVICE_ATTR_RO(tpc_clk_curr);
378 static struct attribute *goya_dev_attrs[] = {
379 &dev_attr_high_pll.attr,
380 &dev_attr_ic_clk.attr,
381 &dev_attr_ic_clk_curr.attr,
382 &dev_attr_mme_clk.attr,
383 &dev_attr_mme_clk_curr.attr,
384 &dev_attr_pm_mng_profile.attr,
385 &dev_attr_tpc_clk.attr,
386 &dev_attr_tpc_clk_curr.attr,
390 void goya_add_device_attr(struct hl_device *hdev,
391 struct attribute_group *dev_attr_grp)
393 dev_attr_grp->attrs = goya_dev_attrs;