0001
0002
0003
0004
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
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},
0035 { 0, 0x5A18, 8, 0xFF, 16},
0036 { 0, 0x5A08, 8, 0xFF, 0},
0037 { 0, 0x5A08, 1, 0x1, 8},
0038 { 1, 0x5A10, 12, 0xFFF, 0},
0039 { 1, 0x5A14, 2, 0x3, 1},
0040 };
0041
0042
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},
0058 { 0, 0x5A38, 7, 0x7F, 24},
0059 { 0, 0x5A38, 8, 0xFF, 16},
0060 { 0, 0x5A38, 16, 0xFFFF, 0},
0061 { 0, 0x5A30, 10, 0x3FF, 0},
0062 { 0, 0x5A30, 10, 0x3FF, 10},
0063 { 0, 0x5A30, 10, 0x3FF, 20},
0064 { 0, 0x5A30, 10, 0x3FF, 30},
0065 { 0, 0x5A40, 1, 0x1, 0},
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");