Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * Copyright 2016-2022 HabanaLabs, Ltd.
0005  * All Rights Reserved.
0006  */
0007 
0008 #include "goyaP.h"
0009 
0010 void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
0011 {
0012     struct goya_device *goya = hdev->asic_specific;
0013 
0014     if (!hdev->pdev)
0015         return;
0016 
0017     switch (freq) {
0018     case PLL_HIGH:
0019         hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, hdev->high_pll);
0020         hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, hdev->high_pll);
0021         hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, hdev->high_pll);
0022         break;
0023     case PLL_LOW:
0024         hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, GOYA_PLL_FREQ_LOW);
0025         hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, GOYA_PLL_FREQ_LOW);
0026         hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, GOYA_PLL_FREQ_LOW);
0027         break;
0028     case PLL_LAST:
0029         hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, goya->mme_clk);
0030         hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, goya->tpc_clk);
0031         hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, goya->ic_clk);
0032         break;
0033     default:
0034         dev_err(hdev->dev, "unknown frequency setting\n");
0035     }
0036 }
0037 
0038 static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
0039                 char *buf)
0040 {
0041     struct hl_device *hdev = dev_get_drvdata(dev);
0042     long value;
0043 
0044     if (!hl_device_operational(hdev, NULL))
0045         return -ENODEV;
0046 
0047     value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, false);
0048 
0049     if (value < 0)
0050         return value;
0051 
0052     return sprintf(buf, "%lu\n", value);
0053 }
0054 
0055 static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
0056                 const char *buf, size_t count)
0057 {
0058     struct hl_device *hdev = dev_get_drvdata(dev);
0059     struct goya_device *goya = hdev->asic_specific;
0060     int rc;
0061     long value;
0062 
0063     if (!hl_device_operational(hdev, NULL)) {
0064         count = -ENODEV;
0065         goto fail;
0066     }
0067 
0068     if (goya->pm_mng_profile == PM_AUTO) {
0069         count = -EPERM;
0070         goto fail;
0071     }
0072 
0073     rc = kstrtoul(buf, 0, &value);
0074 
0075     if (rc) {
0076         count = -EINVAL;
0077         goto fail;
0078     }
0079 
0080     hl_fw_set_frequency(hdev, HL_GOYA_MME_PLL, value);
0081     goya->mme_clk = value;
0082 
0083 fail:
0084     return count;
0085 }
0086 
0087 static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
0088                 char *buf)
0089 {
0090     struct hl_device *hdev = dev_get_drvdata(dev);
0091     long value;
0092 
0093     if (!hl_device_operational(hdev, NULL))
0094         return -ENODEV;
0095 
0096     value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, false);
0097 
0098     if (value < 0)
0099         return value;
0100 
0101     return sprintf(buf, "%lu\n", value);
0102 }
0103 
0104 static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
0105                 const char *buf, size_t count)
0106 {
0107     struct hl_device *hdev = dev_get_drvdata(dev);
0108     struct goya_device *goya = hdev->asic_specific;
0109     int rc;
0110     long value;
0111 
0112     if (!hl_device_operational(hdev, NULL)) {
0113         count = -ENODEV;
0114         goto fail;
0115     }
0116 
0117     if (goya->pm_mng_profile == PM_AUTO) {
0118         count = -EPERM;
0119         goto fail;
0120     }
0121 
0122     rc = kstrtoul(buf, 0, &value);
0123 
0124     if (rc) {
0125         count = -EINVAL;
0126         goto fail;
0127     }
0128 
0129     hl_fw_set_frequency(hdev, HL_GOYA_TPC_PLL, value);
0130     goya->tpc_clk = value;
0131 
0132 fail:
0133     return count;
0134 }
0135 
0136 static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
0137                 char *buf)
0138 {
0139     struct hl_device *hdev = dev_get_drvdata(dev);
0140     long value;
0141 
0142     if (!hl_device_operational(hdev, NULL))
0143         return -ENODEV;
0144 
0145     value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, false);
0146 
0147     if (value < 0)
0148         return value;
0149 
0150     return sprintf(buf, "%lu\n", value);
0151 }
0152 
0153 static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
0154                 const char *buf, size_t count)
0155 {
0156     struct hl_device *hdev = dev_get_drvdata(dev);
0157     struct goya_device *goya = hdev->asic_specific;
0158     int rc;
0159     long value;
0160 
0161     if (!hl_device_operational(hdev, NULL)) {
0162         count = -ENODEV;
0163         goto fail;
0164     }
0165 
0166     if (goya->pm_mng_profile == PM_AUTO) {
0167         count = -EPERM;
0168         goto fail;
0169     }
0170 
0171     rc = kstrtoul(buf, 0, &value);
0172 
0173     if (rc) {
0174         count = -EINVAL;
0175         goto fail;
0176     }
0177 
0178     hl_fw_set_frequency(hdev, HL_GOYA_IC_PLL, value);
0179     goya->ic_clk = value;
0180 
0181 fail:
0182     return count;
0183 }
0184 
0185 static ssize_t mme_clk_curr_show(struct device *dev,
0186                 struct device_attribute *attr, char *buf)
0187 {
0188     struct hl_device *hdev = dev_get_drvdata(dev);
0189     long value;
0190 
0191     if (!hl_device_operational(hdev, NULL))
0192         return -ENODEV;
0193 
0194     value = hl_fw_get_frequency(hdev, HL_GOYA_MME_PLL, true);
0195 
0196     if (value < 0)
0197         return value;
0198 
0199     return sprintf(buf, "%lu\n", value);
0200 }
0201 
0202 static ssize_t tpc_clk_curr_show(struct device *dev,
0203                 struct device_attribute *attr, char *buf)
0204 {
0205     struct hl_device *hdev = dev_get_drvdata(dev);
0206     long value;
0207 
0208     if (!hl_device_operational(hdev, NULL))
0209         return -ENODEV;
0210 
0211     value = hl_fw_get_frequency(hdev, HL_GOYA_TPC_PLL, true);
0212 
0213     if (value < 0)
0214         return value;
0215 
0216     return sprintf(buf, "%lu\n", value);
0217 }
0218 
0219 static ssize_t ic_clk_curr_show(struct device *dev,
0220                 struct device_attribute *attr, char *buf)
0221 {
0222     struct hl_device *hdev = dev_get_drvdata(dev);
0223     long value;
0224 
0225     if (!hl_device_operational(hdev, NULL))
0226         return -ENODEV;
0227 
0228     value = hl_fw_get_frequency(hdev, HL_GOYA_IC_PLL, true);
0229 
0230     if (value < 0)
0231         return value;
0232 
0233     return sprintf(buf, "%lu\n", value);
0234 }
0235 
0236 static ssize_t pm_mng_profile_show(struct device *dev,
0237                 struct device_attribute *attr, char *buf)
0238 {
0239     struct hl_device *hdev = dev_get_drvdata(dev);
0240     struct goya_device *goya = hdev->asic_specific;
0241 
0242     if (!hl_device_operational(hdev, NULL))
0243         return -ENODEV;
0244 
0245     return sprintf(buf, "%s\n",
0246             (goya->pm_mng_profile == PM_AUTO) ? "auto" :
0247             (goya->pm_mng_profile == PM_MANUAL) ? "manual" :
0248             "unknown");
0249 }
0250 
0251 static ssize_t pm_mng_profile_store(struct device *dev,
0252         struct device_attribute *attr, const char *buf, size_t count)
0253 {
0254     struct hl_device *hdev = dev_get_drvdata(dev);
0255     struct goya_device *goya = hdev->asic_specific;
0256 
0257     if (!hl_device_operational(hdev, NULL)) {
0258         count = -ENODEV;
0259         goto out;
0260     }
0261 
0262     mutex_lock(&hdev->fpriv_list_lock);
0263 
0264     if (hdev->is_compute_ctx_active) {
0265         dev_err(hdev->dev,
0266             "Can't change PM profile while compute context is opened on the device\n");
0267         count = -EPERM;
0268         goto unlock_mutex;
0269     }
0270 
0271     if (strncmp("auto", buf, strlen("auto")) == 0) {
0272         /* Make sure we are in LOW PLL when changing modes */
0273         if (goya->pm_mng_profile == PM_MANUAL) {
0274             goya->curr_pll_profile = PLL_HIGH;
0275             goya->pm_mng_profile = PM_AUTO;
0276             goya_set_frequency(hdev, PLL_LOW);
0277         }
0278     } else if (strncmp("manual", buf, strlen("manual")) == 0) {
0279         if (goya->pm_mng_profile == PM_AUTO) {
0280             /* Must release the lock because the work thread also
0281              * takes this lock. But before we release it, set
0282              * the mode to manual so nothing will change if a user
0283              * suddenly opens the device
0284              */
0285             goya->pm_mng_profile = PM_MANUAL;
0286 
0287             mutex_unlock(&hdev->fpriv_list_lock);
0288 
0289             /* Flush the current work so we can return to the user
0290              * knowing that he is the only one changing frequencies
0291              */
0292             if (goya->goya_work)
0293                 flush_delayed_work(&goya->goya_work->work_freq);
0294 
0295             return count;
0296         }
0297     } else {
0298         dev_err(hdev->dev, "value should be auto or manual\n");
0299         count = -EINVAL;
0300     }
0301 
0302 unlock_mutex:
0303     mutex_unlock(&hdev->fpriv_list_lock);
0304 out:
0305     return count;
0306 }
0307 
0308 static ssize_t high_pll_show(struct device *dev, struct device_attribute *attr,
0309                 char *buf)
0310 {
0311     struct hl_device *hdev = dev_get_drvdata(dev);
0312 
0313     if (!hl_device_operational(hdev, NULL))
0314         return -ENODEV;
0315 
0316     return sprintf(buf, "%u\n", hdev->high_pll);
0317 }
0318 
0319 static ssize_t high_pll_store(struct device *dev, struct device_attribute *attr,
0320                 const char *buf, size_t count)
0321 {
0322     struct hl_device *hdev = dev_get_drvdata(dev);
0323     long value;
0324     int rc;
0325 
0326     if (!hl_device_operational(hdev, NULL)) {
0327         count = -ENODEV;
0328         goto out;
0329     }
0330 
0331     rc = kstrtoul(buf, 0, &value);
0332 
0333     if (rc) {
0334         count = -EINVAL;
0335         goto out;
0336     }
0337 
0338     hdev->high_pll = value;
0339 
0340 out:
0341     return count;
0342 }
0343 
0344 static DEVICE_ATTR_RW(high_pll);
0345 static DEVICE_ATTR_RW(ic_clk);
0346 static DEVICE_ATTR_RO(ic_clk_curr);
0347 static DEVICE_ATTR_RW(mme_clk);
0348 static DEVICE_ATTR_RO(mme_clk_curr);
0349 static DEVICE_ATTR_RW(pm_mng_profile);
0350 static DEVICE_ATTR_RW(tpc_clk);
0351 static DEVICE_ATTR_RO(tpc_clk_curr);
0352 
0353 static struct attribute *goya_clk_dev_attrs[] = {
0354     &dev_attr_high_pll.attr,
0355     &dev_attr_ic_clk.attr,
0356     &dev_attr_ic_clk_curr.attr,
0357     &dev_attr_mme_clk.attr,
0358     &dev_attr_mme_clk_curr.attr,
0359     &dev_attr_pm_mng_profile.attr,
0360     &dev_attr_tpc_clk.attr,
0361     &dev_attr_tpc_clk_curr.attr,
0362     NULL,
0363 };
0364 
0365 static ssize_t infineon_ver_show(struct device *dev, struct device_attribute *attr, char *buf)
0366 {
0367     struct hl_device *hdev = dev_get_drvdata(dev);
0368     struct cpucp_info *cpucp_info;
0369 
0370     cpucp_info = &hdev->asic_prop.cpucp_info;
0371 
0372     return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));
0373 }
0374 
0375 static DEVICE_ATTR_RO(infineon_ver);
0376 
0377 static struct attribute *goya_vrm_dev_attrs[] = {
0378     &dev_attr_infineon_ver.attr,
0379     NULL,
0380 };
0381 
0382 void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_clk_attr_grp,
0383                 struct attribute_group *dev_vrm_attr_grp)
0384 {
0385     dev_clk_attr_grp->attrs = goya_clk_dev_attrs;
0386     dev_vrm_attr_grp->attrs = goya_vrm_dev_attrs;
0387 }