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
;