Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * processor thermal device RFIM control
0004  * Copyright (c) 2020, Intel Corporation.
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/pci.h>
0010 #include "processor_thermal_device.h"
0011 
0012 MODULE_IMPORT_NS(INT340X_THERMAL);
0013 
0014 struct mmio_reg {
0015     int read_only;
0016     u32 offset;
0017     int bits;
0018     u16 mask;
0019     u16 shift;
0020 };
0021 
0022 /* These will represent sysfs attribute names */
0023 static const char * const fivr_strings[] = {
0024     "vco_ref_code_lo",
0025     "vco_ref_code_hi",
0026     "spread_spectrum_pct",
0027     "spread_spectrum_clk_enable",
0028     "rfi_vco_ref_code",
0029     "fivr_fffc_rev",
0030     NULL
0031 };
0032 
0033 static const struct mmio_reg tgl_fivr_mmio_regs[] = {
0034     { 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */
0035     { 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */
0036     { 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */
0037     { 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */
0038     { 1, 0x5A10, 12, 0xFFF, 0}, /* rfi_vco_ref_code */
0039     { 1, 0x5A14, 2, 0x3, 1}, /* fivr_fffc_rev */
0040 };
0041 
0042 /* These will represent sysfs attribute names */
0043 static const char * const dvfs_strings[] = {
0044     "rfi_restriction_run_busy",
0045     "rfi_restriction_err_code",
0046     "rfi_restriction_data_rate",
0047     "rfi_restriction_data_rate_base",
0048     "ddr_data_rate_point_0",
0049     "ddr_data_rate_point_1",
0050     "ddr_data_rate_point_2",
0051     "ddr_data_rate_point_3",
0052     "rfi_disable",
0053     NULL
0054 };
0055 
0056 static const struct mmio_reg adl_dvfs_mmio_regs[] = {
0057     { 0, 0x5A38, 1, 0x1, 31}, /* rfi_restriction_run_busy */
0058     { 0, 0x5A38, 7, 0x7F, 24}, /* rfi_restriction_err_code */
0059     { 0, 0x5A38, 8, 0xFF, 16}, /* rfi_restriction_data_rate */
0060     { 0, 0x5A38, 16, 0xFFFF, 0}, /* rfi_restriction_data_rate_base */
0061     { 0, 0x5A30, 10, 0x3FF, 0}, /* ddr_data_rate_point_0 */
0062     { 0, 0x5A30, 10, 0x3FF, 10}, /* ddr_data_rate_point_1 */
0063     { 0, 0x5A30, 10, 0x3FF, 20}, /* ddr_data_rate_point_2 */
0064     { 0, 0x5A30, 10, 0x3FF, 30}, /* ddr_data_rate_point_3 */
0065     { 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */
0066 };
0067 
0068 #define RFIM_SHOW(suffix, table)\
0069 static ssize_t suffix##_show(struct device *dev,\
0070                   struct device_attribute *attr,\
0071                   char *buf)\
0072 {\
0073     struct proc_thermal_device *proc_priv;\
0074     struct pci_dev *pdev = to_pci_dev(dev);\
0075     const struct mmio_reg *mmio_regs;\
0076     const char **match_strs;\
0077     u32 reg_val;\
0078     int ret;\
0079 \
0080     proc_priv = pci_get_drvdata(pdev);\
0081     if (table) {\
0082         match_strs = (const char **)dvfs_strings;\
0083         mmio_regs = adl_dvfs_mmio_regs;\
0084     } else { \
0085         match_strs = (const char **)fivr_strings;\
0086         mmio_regs = tgl_fivr_mmio_regs;\
0087     } \
0088     \
0089     ret = match_string(match_strs, -1, attr->attr.name);\
0090     if (ret < 0)\
0091         return ret;\
0092     reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
0093     ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
0094     return sprintf(buf, "%u\n", ret);\
0095 }
0096 
0097 #define RFIM_STORE(suffix, table)\
0098 static ssize_t suffix##_store(struct device *dev,\
0099                    struct device_attribute *attr,\
0100                    const char *buf, size_t count)\
0101 {\
0102     struct proc_thermal_device *proc_priv;\
0103     struct pci_dev *pdev = to_pci_dev(dev);\
0104     unsigned int input;\
0105     const char **match_strs;\
0106     const struct mmio_reg *mmio_regs;\
0107     int ret, err;\
0108     u32 reg_val;\
0109     u32 mask;\
0110 \
0111     proc_priv = pci_get_drvdata(pdev);\
0112     if (table) {\
0113         match_strs = (const char **)dvfs_strings;\
0114         mmio_regs = adl_dvfs_mmio_regs;\
0115     } else { \
0116         match_strs = (const char **)fivr_strings;\
0117         mmio_regs = tgl_fivr_mmio_regs;\
0118     } \
0119     \
0120     ret = match_string(match_strs, -1, attr->attr.name);\
0121     if (ret < 0)\
0122         return ret;\
0123     if (mmio_regs[ret].read_only)\
0124         return -EPERM;\
0125     err = kstrtouint(buf, 10, &input);\
0126     if (err)\
0127         return err;\
0128     mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
0129     reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
0130     reg_val &= ~mask;\
0131     reg_val |= (input << mmio_regs[ret].shift);\
0132     writel(reg_val, (void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
0133     return count;\
0134 }
0135 
0136 RFIM_SHOW(vco_ref_code_lo, 0)
0137 RFIM_SHOW(vco_ref_code_hi, 0)
0138 RFIM_SHOW(spread_spectrum_pct, 0)
0139 RFIM_SHOW(spread_spectrum_clk_enable, 0)
0140 RFIM_SHOW(rfi_vco_ref_code, 0)
0141 RFIM_SHOW(fivr_fffc_rev, 0)
0142 
0143 RFIM_STORE(vco_ref_code_lo, 0)
0144 RFIM_STORE(vco_ref_code_hi, 0)
0145 RFIM_STORE(spread_spectrum_pct, 0)
0146 RFIM_STORE(spread_spectrum_clk_enable, 0)
0147 RFIM_STORE(rfi_vco_ref_code, 0)
0148 RFIM_STORE(fivr_fffc_rev, 0)
0149 
0150 static DEVICE_ATTR_RW(vco_ref_code_lo);
0151 static DEVICE_ATTR_RW(vco_ref_code_hi);
0152 static DEVICE_ATTR_RW(spread_spectrum_pct);
0153 static DEVICE_ATTR_RW(spread_spectrum_clk_enable);
0154 static DEVICE_ATTR_RW(rfi_vco_ref_code);
0155 static DEVICE_ATTR_RW(fivr_fffc_rev);
0156 
0157 static struct attribute *fivr_attrs[] = {
0158     &dev_attr_vco_ref_code_lo.attr,
0159     &dev_attr_vco_ref_code_hi.attr,
0160     &dev_attr_spread_spectrum_pct.attr,
0161     &dev_attr_spread_spectrum_clk_enable.attr,
0162     &dev_attr_rfi_vco_ref_code.attr,
0163     &dev_attr_fivr_fffc_rev.attr,
0164     NULL
0165 };
0166 
0167 static const struct attribute_group fivr_attribute_group = {
0168     .attrs = fivr_attrs,
0169     .name = "fivr"
0170 };
0171 
0172 RFIM_SHOW(rfi_restriction_run_busy, 1)
0173 RFIM_SHOW(rfi_restriction_err_code, 1)
0174 RFIM_SHOW(rfi_restriction_data_rate, 1)
0175 RFIM_SHOW(ddr_data_rate_point_0, 1)
0176 RFIM_SHOW(ddr_data_rate_point_1, 1)
0177 RFIM_SHOW(ddr_data_rate_point_2, 1)
0178 RFIM_SHOW(ddr_data_rate_point_3, 1)
0179 RFIM_SHOW(rfi_disable, 1)
0180 
0181 RFIM_STORE(rfi_restriction_run_busy, 1)
0182 RFIM_STORE(rfi_restriction_err_code, 1)
0183 RFIM_STORE(rfi_restriction_data_rate, 1)
0184 RFIM_STORE(rfi_disable, 1)
0185 
0186 static DEVICE_ATTR_RW(rfi_restriction_run_busy);
0187 static DEVICE_ATTR_RW(rfi_restriction_err_code);
0188 static DEVICE_ATTR_RW(rfi_restriction_data_rate);
0189 static DEVICE_ATTR_RO(ddr_data_rate_point_0);
0190 static DEVICE_ATTR_RO(ddr_data_rate_point_1);
0191 static DEVICE_ATTR_RO(ddr_data_rate_point_2);
0192 static DEVICE_ATTR_RO(ddr_data_rate_point_3);
0193 static DEVICE_ATTR_RW(rfi_disable);
0194 
0195 static ssize_t rfi_restriction_store(struct device *dev,
0196                      struct device_attribute *attr,
0197                      const char *buf, size_t count)
0198 {
0199     u16 id = 0x0008;
0200     u32 input;
0201     int ret;
0202 
0203     ret = kstrtou32(buf, 10, &input);
0204     if (ret)
0205         return ret;
0206 
0207     ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input);
0208     if (ret)
0209         return ret;
0210 
0211     return count;
0212 }
0213 
0214 static ssize_t rfi_restriction_show(struct device *dev,
0215                     struct device_attribute *attr,
0216                     char *buf)
0217 {
0218     u16 id = 0x0007;
0219     u64 resp;
0220     int ret;
0221 
0222     ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
0223     if (ret)
0224         return ret;
0225 
0226     return sprintf(buf, "%llu\n", resp);
0227 }
0228 
0229 static ssize_t ddr_data_rate_show(struct device *dev,
0230                   struct device_attribute *attr,
0231                   char *buf)
0232 {
0233     u16 id = 0x0107;
0234     u64 resp;
0235     int ret;
0236 
0237     ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
0238     if (ret)
0239         return ret;
0240 
0241     return sprintf(buf, "%llu\n", resp);
0242 }
0243 
0244 static DEVICE_ATTR_RW(rfi_restriction);
0245 static DEVICE_ATTR_RO(ddr_data_rate);
0246 
0247 static struct attribute *dvfs_attrs[] = {
0248     &dev_attr_rfi_restriction_run_busy.attr,
0249     &dev_attr_rfi_restriction_err_code.attr,
0250     &dev_attr_rfi_restriction_data_rate.attr,
0251     &dev_attr_ddr_data_rate_point_0.attr,
0252     &dev_attr_ddr_data_rate_point_1.attr,
0253     &dev_attr_ddr_data_rate_point_2.attr,
0254     &dev_attr_ddr_data_rate_point_3.attr,
0255     &dev_attr_rfi_disable.attr,
0256     &dev_attr_ddr_data_rate.attr,
0257     &dev_attr_rfi_restriction.attr,
0258     NULL
0259 };
0260 
0261 static const struct attribute_group dvfs_attribute_group = {
0262     .attrs = dvfs_attrs,
0263     .name = "dvfs"
0264 };
0265 
0266 int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
0267 {
0268     int ret;
0269 
0270     if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
0271         ret = sysfs_create_group(&pdev->dev.kobj, &fivr_attribute_group);
0272         if (ret)
0273             return ret;
0274     }
0275 
0276     if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) {
0277         ret = sysfs_create_group(&pdev->dev.kobj, &dvfs_attribute_group);
0278         if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
0279             sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
0280             return ret;
0281         }
0282     }
0283 
0284     return 0;
0285 }
0286 EXPORT_SYMBOL_GPL(proc_thermal_rfim_add);
0287 
0288 void proc_thermal_rfim_remove(struct pci_dev *pdev)
0289 {
0290     struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
0291 
0292     if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR)
0293         sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
0294 
0295     if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS)
0296         sysfs_remove_group(&pdev->dev.kobj, &dvfs_attribute_group);
0297 }
0298 EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove);
0299 
0300 MODULE_LICENSE("GPL v2");