1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * processor thermal device RFIM control 4 * Copyright (c) 2020, Intel Corporation. 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/pci.h> 10 #include "processor_thermal_device.h" 11 12 MODULE_IMPORT_NS(INT340X_THERMAL); 13 14 struct mmio_reg { 15 int read_only; 16 u32 offset; 17 int bits; 18 u16 mask; 19 u16 shift; 20 }; 21 22 /* These will represent sysfs attribute names */ 23 static const char * const fivr_strings[] = { 24 "vco_ref_code_lo", 25 "vco_ref_code_hi", 26 "spread_spectrum_pct", 27 "spread_spectrum_clk_enable", 28 "rfi_vco_ref_code", 29 "fivr_fffc_rev", 30 NULL 31 }; 32 33 static const struct mmio_reg tgl_fivr_mmio_regs[] = { 34 { 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */ 35 { 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */ 36 { 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */ 37 { 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */ 38 { 1, 0x5A10, 12, 0xFFF, 0}, /* rfi_vco_ref_code */ 39 { 1, 0x5A14, 2, 0x3, 1}, /* fivr_fffc_rev */ 40 }; 41 42 static const char * const dlvr_strings[] = { 43 "dlvr_spread_spectrum_pct", 44 "dlvr_control_mode", 45 "dlvr_control_lock", 46 "dlvr_rfim_enable", 47 "dlvr_freq_select", 48 "dlvr_hardware_rev", 49 "dlvr_freq_mhz", 50 "dlvr_pll_busy", 51 NULL 52 }; 53 54 static const struct mmio_reg dlvr_mmio_regs[] = { 55 { 0, 0x15A08, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */ 56 { 0, 0x15A08, 1, 0x1, 5}, /* dlvr_control_mode */ 57 { 0, 0x15A08, 1, 0x1, 6}, /* dlvr_control_lock */ 58 { 0, 0x15A08, 1, 0x1, 7}, /* dlvr_rfim_enable */ 59 { 0, 0x15A08, 12, 0xFFF, 8}, /* dlvr_freq_select */ 60 { 1, 0x15A10, 2, 0x3, 30}, /* dlvr_hardware_rev */ 61 { 1, 0x15A10, 16, 0xFFFF, 0}, /* dlvr_freq_mhz */ 62 { 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */ 63 }; 64 65 /* These will represent sysfs attribute names */ 66 static const char * const dvfs_strings[] = { 67 "rfi_restriction_run_busy", 68 "rfi_restriction_err_code", 69 "rfi_restriction_data_rate", 70 "rfi_restriction_data_rate_base", 71 "ddr_data_rate_point_0", 72 "ddr_data_rate_point_1", 73 "ddr_data_rate_point_2", 74 "ddr_data_rate_point_3", 75 "rfi_disable", 76 NULL 77 }; 78 79 static const struct mmio_reg adl_dvfs_mmio_regs[] = { 80 { 0, 0x5A38, 1, 0x1, 31}, /* rfi_restriction_run_busy */ 81 { 0, 0x5A38, 7, 0x7F, 24}, /* rfi_restriction_err_code */ 82 { 0, 0x5A38, 8, 0xFF, 16}, /* rfi_restriction_data_rate */ 83 { 0, 0x5A38, 16, 0xFFFF, 0}, /* rfi_restriction_data_rate_base */ 84 { 0, 0x5A30, 10, 0x3FF, 0}, /* ddr_data_rate_point_0 */ 85 { 0, 0x5A30, 10, 0x3FF, 10}, /* ddr_data_rate_point_1 */ 86 { 0, 0x5A30, 10, 0x3FF, 20}, /* ddr_data_rate_point_2 */ 87 { 0, 0x5A30, 10, 0x3FF, 30}, /* ddr_data_rate_point_3 */ 88 { 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */ 89 }; 90 91 #define RFIM_SHOW(suffix, table)\ 92 static ssize_t suffix##_show(struct device *dev,\ 93 struct device_attribute *attr,\ 94 char *buf)\ 95 {\ 96 struct proc_thermal_device *proc_priv;\ 97 struct pci_dev *pdev = to_pci_dev(dev);\ 98 const struct mmio_reg *mmio_regs;\ 99 const char **match_strs;\ 100 u32 reg_val;\ 101 int ret;\ 102 \ 103 proc_priv = pci_get_drvdata(pdev);\ 104 if (table == 1) {\ 105 match_strs = (const char **)dvfs_strings;\ 106 mmio_regs = adl_dvfs_mmio_regs;\ 107 } else if (table == 2) { \ 108 match_strs = (const char **)dlvr_strings;\ 109 mmio_regs = dlvr_mmio_regs;\ 110 } else {\ 111 match_strs = (const char **)fivr_strings;\ 112 mmio_regs = tgl_fivr_mmio_regs;\ 113 } \ 114 ret = match_string(match_strs, -1, attr->attr.name);\ 115 if (ret < 0)\ 116 return ret;\ 117 reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ 118 ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\ 119 return sprintf(buf, "%u\n", ret);\ 120 } 121 122 #define RFIM_STORE(suffix, table)\ 123 static ssize_t suffix##_store(struct device *dev,\ 124 struct device_attribute *attr,\ 125 const char *buf, size_t count)\ 126 {\ 127 struct proc_thermal_device *proc_priv;\ 128 struct pci_dev *pdev = to_pci_dev(dev);\ 129 unsigned int input;\ 130 const char **match_strs;\ 131 const struct mmio_reg *mmio_regs;\ 132 int ret, err;\ 133 u32 reg_val;\ 134 u32 mask;\ 135 \ 136 proc_priv = pci_get_drvdata(pdev);\ 137 if (table == 1) {\ 138 match_strs = (const char **)dvfs_strings;\ 139 mmio_regs = adl_dvfs_mmio_regs;\ 140 } else if (table == 2) { \ 141 match_strs = (const char **)dlvr_strings;\ 142 mmio_regs = dlvr_mmio_regs;\ 143 } else {\ 144 match_strs = (const char **)fivr_strings;\ 145 mmio_regs = tgl_fivr_mmio_regs;\ 146 } \ 147 \ 148 ret = match_string(match_strs, -1, attr->attr.name);\ 149 if (ret < 0)\ 150 return ret;\ 151 if (mmio_regs[ret].read_only)\ 152 return -EPERM;\ 153 err = kstrtouint(buf, 10, &input);\ 154 if (err)\ 155 return err;\ 156 mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\ 157 reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ 158 reg_val &= ~mask;\ 159 reg_val |= (input << mmio_regs[ret].shift);\ 160 writel(reg_val, (void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ 161 return count;\ 162 } 163 164 RFIM_SHOW(vco_ref_code_lo, 0) 165 RFIM_SHOW(vco_ref_code_hi, 0) 166 RFIM_SHOW(spread_spectrum_pct, 0) 167 RFIM_SHOW(spread_spectrum_clk_enable, 0) 168 RFIM_SHOW(rfi_vco_ref_code, 0) 169 RFIM_SHOW(fivr_fffc_rev, 0) 170 171 RFIM_STORE(vco_ref_code_lo, 0) 172 RFIM_STORE(vco_ref_code_hi, 0) 173 RFIM_STORE(spread_spectrum_pct, 0) 174 RFIM_STORE(spread_spectrum_clk_enable, 0) 175 RFIM_STORE(rfi_vco_ref_code, 0) 176 RFIM_STORE(fivr_fffc_rev, 0) 177 178 RFIM_SHOW(dlvr_spread_spectrum_pct, 2) 179 RFIM_SHOW(dlvr_control_mode, 2) 180 RFIM_SHOW(dlvr_control_lock, 2) 181 RFIM_SHOW(dlvr_hardware_rev, 2) 182 RFIM_SHOW(dlvr_freq_mhz, 2) 183 RFIM_SHOW(dlvr_pll_busy, 2) 184 RFIM_SHOW(dlvr_freq_select, 2) 185 RFIM_SHOW(dlvr_rfim_enable, 2) 186 187 RFIM_STORE(dlvr_spread_spectrum_pct, 2) 188 RFIM_STORE(dlvr_rfim_enable, 2) 189 RFIM_STORE(dlvr_freq_select, 2) 190 RFIM_STORE(dlvr_control_mode, 2) 191 RFIM_STORE(dlvr_control_lock, 2) 192 193 static DEVICE_ATTR_RW(dlvr_spread_spectrum_pct); 194 static DEVICE_ATTR_RW(dlvr_control_mode); 195 static DEVICE_ATTR_RW(dlvr_control_lock); 196 static DEVICE_ATTR_RW(dlvr_freq_select); 197 static DEVICE_ATTR_RO(dlvr_hardware_rev); 198 static DEVICE_ATTR_RO(dlvr_freq_mhz); 199 static DEVICE_ATTR_RO(dlvr_pll_busy); 200 static DEVICE_ATTR_RW(dlvr_rfim_enable); 201 202 static struct attribute *dlvr_attrs[] = { 203 &dev_attr_dlvr_spread_spectrum_pct.attr, 204 &dev_attr_dlvr_control_mode.attr, 205 &dev_attr_dlvr_control_lock.attr, 206 &dev_attr_dlvr_freq_select.attr, 207 &dev_attr_dlvr_hardware_rev.attr, 208 &dev_attr_dlvr_freq_mhz.attr, 209 &dev_attr_dlvr_pll_busy.attr, 210 &dev_attr_dlvr_rfim_enable.attr, 211 NULL 212 }; 213 214 static const struct attribute_group dlvr_attribute_group = { 215 .attrs = dlvr_attrs, 216 .name = "dlvr" 217 }; 218 219 static DEVICE_ATTR_RW(vco_ref_code_lo); 220 static DEVICE_ATTR_RW(vco_ref_code_hi); 221 static DEVICE_ATTR_RW(spread_spectrum_pct); 222 static DEVICE_ATTR_RW(spread_spectrum_clk_enable); 223 static DEVICE_ATTR_RW(rfi_vco_ref_code); 224 static DEVICE_ATTR_RW(fivr_fffc_rev); 225 226 static struct attribute *fivr_attrs[] = { 227 &dev_attr_vco_ref_code_lo.attr, 228 &dev_attr_vco_ref_code_hi.attr, 229 &dev_attr_spread_spectrum_pct.attr, 230 &dev_attr_spread_spectrum_clk_enable.attr, 231 &dev_attr_rfi_vco_ref_code.attr, 232 &dev_attr_fivr_fffc_rev.attr, 233 NULL 234 }; 235 236 static const struct attribute_group fivr_attribute_group = { 237 .attrs = fivr_attrs, 238 .name = "fivr" 239 }; 240 241 RFIM_SHOW(rfi_restriction_run_busy, 1) 242 RFIM_SHOW(rfi_restriction_err_code, 1) 243 RFIM_SHOW(rfi_restriction_data_rate, 1) 244 RFIM_SHOW(rfi_restriction_data_rate_base, 1) 245 RFIM_SHOW(ddr_data_rate_point_0, 1) 246 RFIM_SHOW(ddr_data_rate_point_1, 1) 247 RFIM_SHOW(ddr_data_rate_point_2, 1) 248 RFIM_SHOW(ddr_data_rate_point_3, 1) 249 RFIM_SHOW(rfi_disable, 1) 250 251 RFIM_STORE(rfi_restriction_run_busy, 1) 252 RFIM_STORE(rfi_restriction_err_code, 1) 253 RFIM_STORE(rfi_restriction_data_rate, 1) 254 RFIM_STORE(rfi_restriction_data_rate_base, 1) 255 RFIM_STORE(rfi_disable, 1) 256 257 static DEVICE_ATTR_RW(rfi_restriction_run_busy); 258 static DEVICE_ATTR_RW(rfi_restriction_err_code); 259 static DEVICE_ATTR_RW(rfi_restriction_data_rate); 260 static DEVICE_ATTR_RW(rfi_restriction_data_rate_base); 261 static DEVICE_ATTR_RO(ddr_data_rate_point_0); 262 static DEVICE_ATTR_RO(ddr_data_rate_point_1); 263 static DEVICE_ATTR_RO(ddr_data_rate_point_2); 264 static DEVICE_ATTR_RO(ddr_data_rate_point_3); 265 static DEVICE_ATTR_RW(rfi_disable); 266 267 static ssize_t rfi_restriction_store(struct device *dev, 268 struct device_attribute *attr, 269 const char *buf, size_t count) 270 { 271 u16 id = 0x0008; 272 u32 input; 273 int ret; 274 275 ret = kstrtou32(buf, 10, &input); 276 if (ret) 277 return ret; 278 279 ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input); 280 if (ret) 281 return ret; 282 283 return count; 284 } 285 286 static ssize_t rfi_restriction_show(struct device *dev, 287 struct device_attribute *attr, 288 char *buf) 289 { 290 u16 id = 0x0007; 291 u64 resp; 292 int ret; 293 294 ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp); 295 if (ret) 296 return ret; 297 298 return sprintf(buf, "%llu\n", resp); 299 } 300 301 static ssize_t ddr_data_rate_show(struct device *dev, 302 struct device_attribute *attr, 303 char *buf) 304 { 305 u16 id = 0x0107; 306 u64 resp; 307 int ret; 308 309 ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp); 310 if (ret) 311 return ret; 312 313 return sprintf(buf, "%llu\n", resp); 314 } 315 316 static DEVICE_ATTR_RW(rfi_restriction); 317 static DEVICE_ATTR_RO(ddr_data_rate); 318 319 static struct attribute *dvfs_attrs[] = { 320 &dev_attr_rfi_restriction_run_busy.attr, 321 &dev_attr_rfi_restriction_err_code.attr, 322 &dev_attr_rfi_restriction_data_rate.attr, 323 &dev_attr_rfi_restriction_data_rate_base.attr, 324 &dev_attr_ddr_data_rate_point_0.attr, 325 &dev_attr_ddr_data_rate_point_1.attr, 326 &dev_attr_ddr_data_rate_point_2.attr, 327 &dev_attr_ddr_data_rate_point_3.attr, 328 &dev_attr_rfi_disable.attr, 329 &dev_attr_ddr_data_rate.attr, 330 &dev_attr_rfi_restriction.attr, 331 NULL 332 }; 333 334 static const struct attribute_group dvfs_attribute_group = { 335 .attrs = dvfs_attrs, 336 .name = "dvfs" 337 }; 338 339 int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 340 { 341 int ret; 342 343 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) { 344 ret = sysfs_create_group(&pdev->dev.kobj, &fivr_attribute_group); 345 if (ret) 346 return ret; 347 } 348 349 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) { 350 ret = sysfs_create_group(&pdev->dev.kobj, &dlvr_attribute_group); 351 if (ret) 352 return ret; 353 } 354 355 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) { 356 ret = sysfs_create_group(&pdev->dev.kobj, &dvfs_attribute_group); 357 if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) { 358 sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group); 359 return ret; 360 } 361 if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) { 362 sysfs_remove_group(&pdev->dev.kobj, &dlvr_attribute_group); 363 return ret; 364 } 365 } 366 367 return 0; 368 } 369 EXPORT_SYMBOL_GPL(proc_thermal_rfim_add); 370 371 void proc_thermal_rfim_remove(struct pci_dev *pdev) 372 { 373 struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 374 375 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) 376 sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group); 377 378 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) 379 sysfs_remove_group(&pdev->dev.kobj, &dlvr_attribute_group); 380 381 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) 382 sysfs_remove_group(&pdev->dev.kobj, &dvfs_attribute_group); 383 } 384 EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove); 385 386 MODULE_LICENSE("GPL v2"); 387 MODULE_DESCRIPTION("Processor Thermal RFIM Interface"); 388