goya_hwmgr.c (8675B)
1// SPDX-License-Identifier: GPL-2.0 2 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 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 284 */ 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 user 290 * knowing that he is the only one changing frequencies 291 */ 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}; 363 364static ssize_t infineon_ver_show(struct device *dev, struct device_attribute *attr, char *buf) 365{ 366 struct hl_device *hdev = dev_get_drvdata(dev); 367 struct cpucp_info *cpucp_info; 368 369 cpucp_info = &hdev->asic_prop.cpucp_info; 370 371 return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version)); 372} 373 374static DEVICE_ATTR_RO(infineon_ver); 375 376static struct attribute *goya_vrm_dev_attrs[] = { 377 &dev_attr_infineon_ver.attr, 378}; 379 380void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp, 381 struct attribute_group *dev_vrm_attr_grp) 382{ 383 dev_clk_attr_grp->attrs = goya_clk_dev_attrs; 384 dev_vrm_attr_grp->attrs = goya_vrm_dev_attrs; 385}