0001
0002
0003
0004 #include <linux/auxiliary_bus.h>
0005 #include <linux/bitfield.h>
0006 #include <linux/bitops.h>
0007 #include <linux/hwmon.h>
0008 #include <linux/jiffies.h>
0009 #include <linux/module.h>
0010 #include <linux/peci.h>
0011 #include <linux/peci-cpu.h>
0012 #include <linux/units.h>
0013
0014 #include "common.h"
0015
0016 #define CORE_NUMS_MAX 64
0017
0018 #define BASE_CHANNEL_NUMS 5
0019 #define CPUTEMP_CHANNEL_NUMS (BASE_CHANNEL_NUMS + CORE_NUMS_MAX)
0020
0021 #define TEMP_TARGET_FAN_TEMP_MASK GENMASK(15, 8)
0022 #define TEMP_TARGET_REF_TEMP_MASK GENMASK(23, 16)
0023 #define TEMP_TARGET_TJ_OFFSET_MASK GENMASK(29, 24)
0024
0025 #define DTS_MARGIN_MASK GENMASK(15, 0)
0026 #define PCS_MODULE_TEMP_MASK GENMASK(15, 0)
0027
0028 struct resolved_cores_reg {
0029 u8 bus;
0030 u8 dev;
0031 u8 func;
0032 u8 offset;
0033 };
0034
0035 struct cpu_info {
0036 struct resolved_cores_reg *reg;
0037 u8 min_peci_revision;
0038 s32 (*thermal_margin_to_millidegree)(u16 val);
0039 };
0040
0041 struct peci_temp_target {
0042 s32 tcontrol;
0043 s32 tthrottle;
0044 s32 tjmax;
0045 struct peci_sensor_state state;
0046 };
0047
0048 enum peci_temp_target_type {
0049 tcontrol_type,
0050 tthrottle_type,
0051 tjmax_type,
0052 crit_hyst_type,
0053 };
0054
0055 struct peci_cputemp {
0056 struct peci_device *peci_dev;
0057 struct device *dev;
0058 const char *name;
0059 const struct cpu_info *gen_info;
0060 struct {
0061 struct peci_temp_target target;
0062 struct peci_sensor_data die;
0063 struct peci_sensor_data dts;
0064 struct peci_sensor_data core[CORE_NUMS_MAX];
0065 } temp;
0066 const char **coretemp_label;
0067 DECLARE_BITMAP(core_mask, CORE_NUMS_MAX);
0068 };
0069
0070 enum cputemp_channels {
0071 channel_die,
0072 channel_dts,
0073 channel_tcontrol,
0074 channel_tthrottle,
0075 channel_tjmax,
0076 channel_core,
0077 };
0078
0079 static const char * const cputemp_label[BASE_CHANNEL_NUMS] = {
0080 "Die",
0081 "DTS",
0082 "Tcontrol",
0083 "Tthrottle",
0084 "Tjmax",
0085 };
0086
0087 static int update_temp_target(struct peci_cputemp *priv)
0088 {
0089 s32 tthrottle_offset, tcontrol_margin;
0090 u32 pcs;
0091 int ret;
0092
0093 if (!peci_sensor_need_update(&priv->temp.target.state))
0094 return 0;
0095
0096 ret = peci_pcs_read(priv->peci_dev, PECI_PCS_TEMP_TARGET, 0, &pcs);
0097 if (ret)
0098 return ret;
0099
0100 priv->temp.target.tjmax =
0101 FIELD_GET(TEMP_TARGET_REF_TEMP_MASK, pcs) * MILLIDEGREE_PER_DEGREE;
0102
0103 tcontrol_margin = FIELD_GET(TEMP_TARGET_FAN_TEMP_MASK, pcs);
0104 tcontrol_margin = sign_extend32(tcontrol_margin, 7) * MILLIDEGREE_PER_DEGREE;
0105 priv->temp.target.tcontrol = priv->temp.target.tjmax - tcontrol_margin;
0106
0107 tthrottle_offset = FIELD_GET(TEMP_TARGET_TJ_OFFSET_MASK, pcs) * MILLIDEGREE_PER_DEGREE;
0108 priv->temp.target.tthrottle = priv->temp.target.tjmax - tthrottle_offset;
0109
0110 peci_sensor_mark_updated(&priv->temp.target.state);
0111
0112 return 0;
0113 }
0114
0115 static int get_temp_target(struct peci_cputemp *priv, enum peci_temp_target_type type, long *val)
0116 {
0117 int ret;
0118
0119 mutex_lock(&priv->temp.target.state.lock);
0120
0121 ret = update_temp_target(priv);
0122 if (ret)
0123 goto unlock;
0124
0125 switch (type) {
0126 case tcontrol_type:
0127 *val = priv->temp.target.tcontrol;
0128 break;
0129 case tthrottle_type:
0130 *val = priv->temp.target.tthrottle;
0131 break;
0132 case tjmax_type:
0133 *val = priv->temp.target.tjmax;
0134 break;
0135 case crit_hyst_type:
0136 *val = priv->temp.target.tjmax - priv->temp.target.tcontrol;
0137 break;
0138 default:
0139 ret = -EOPNOTSUPP;
0140 break;
0141 }
0142 unlock:
0143 mutex_unlock(&priv->temp.target.state.lock);
0144
0145 return ret;
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155 static bool dts_valid(u16 val)
0156 {
0157 return val < 0x8000 || val > 0x81ff;
0158 }
0159
0160
0161
0162
0163
0164 static s32 dts_ten_dot_six_to_millidegree(u16 val)
0165 {
0166 return sign_extend32(val, 15) * MILLIDEGREE_PER_DEGREE / 64;
0167 }
0168
0169
0170
0171
0172
0173 static s32 dts_eight_dot_eight_to_millidegree(u16 val)
0174 {
0175 return sign_extend32(val, 15) * MILLIDEGREE_PER_DEGREE / 256;
0176 }
0177
0178 static int get_die_temp(struct peci_cputemp *priv, long *val)
0179 {
0180 int ret = 0;
0181 long tjmax;
0182 u16 temp;
0183
0184 mutex_lock(&priv->temp.die.state.lock);
0185 if (!peci_sensor_need_update(&priv->temp.die.state))
0186 goto skip_update;
0187
0188 ret = peci_temp_read(priv->peci_dev, &temp);
0189 if (ret)
0190 goto err_unlock;
0191
0192 if (!dts_valid(temp)) {
0193 ret = -EIO;
0194 goto err_unlock;
0195 }
0196
0197 ret = get_temp_target(priv, tjmax_type, &tjmax);
0198 if (ret)
0199 goto err_unlock;
0200
0201 priv->temp.die.value = (s32)tjmax + dts_ten_dot_six_to_millidegree(temp);
0202
0203 peci_sensor_mark_updated(&priv->temp.die.state);
0204
0205 skip_update:
0206 *val = priv->temp.die.value;
0207 err_unlock:
0208 mutex_unlock(&priv->temp.die.state.lock);
0209 return ret;
0210 }
0211
0212 static int get_dts(struct peci_cputemp *priv, long *val)
0213 {
0214 int ret = 0;
0215 u16 thermal_margin;
0216 long tcontrol;
0217 u32 pcs;
0218
0219 mutex_lock(&priv->temp.dts.state.lock);
0220 if (!peci_sensor_need_update(&priv->temp.dts.state))
0221 goto skip_update;
0222
0223 ret = peci_pcs_read(priv->peci_dev, PECI_PCS_THERMAL_MARGIN, 0, &pcs);
0224 if (ret)
0225 goto err_unlock;
0226
0227 thermal_margin = FIELD_GET(DTS_MARGIN_MASK, pcs);
0228 if (!dts_valid(thermal_margin)) {
0229 ret = -EIO;
0230 goto err_unlock;
0231 }
0232
0233 ret = get_temp_target(priv, tcontrol_type, &tcontrol);
0234 if (ret)
0235 goto err_unlock;
0236
0237
0238 priv->temp.dts.value =
0239 (s32)tcontrol - priv->gen_info->thermal_margin_to_millidegree(thermal_margin);
0240
0241 peci_sensor_mark_updated(&priv->temp.dts.state);
0242
0243 skip_update:
0244 *val = priv->temp.dts.value;
0245 err_unlock:
0246 mutex_unlock(&priv->temp.dts.state.lock);
0247 return ret;
0248 }
0249
0250 static int get_core_temp(struct peci_cputemp *priv, int core_index, long *val)
0251 {
0252 int ret = 0;
0253 u16 core_dts_margin;
0254 long tjmax;
0255 u32 pcs;
0256
0257 mutex_lock(&priv->temp.core[core_index].state.lock);
0258 if (!peci_sensor_need_update(&priv->temp.core[core_index].state))
0259 goto skip_update;
0260
0261 ret = peci_pcs_read(priv->peci_dev, PECI_PCS_MODULE_TEMP, core_index, &pcs);
0262 if (ret)
0263 goto err_unlock;
0264
0265 core_dts_margin = FIELD_GET(PCS_MODULE_TEMP_MASK, pcs);
0266 if (!dts_valid(core_dts_margin)) {
0267 ret = -EIO;
0268 goto err_unlock;
0269 }
0270
0271 ret = get_temp_target(priv, tjmax_type, &tjmax);
0272 if (ret)
0273 goto err_unlock;
0274
0275
0276 priv->temp.core[core_index].value =
0277 (s32)tjmax + dts_ten_dot_six_to_millidegree(core_dts_margin);
0278
0279 peci_sensor_mark_updated(&priv->temp.core[core_index].state);
0280
0281 skip_update:
0282 *val = priv->temp.core[core_index].value;
0283 err_unlock:
0284 mutex_unlock(&priv->temp.core[core_index].state.lock);
0285 return ret;
0286 }
0287
0288 static int cputemp_read_string(struct device *dev, enum hwmon_sensor_types type,
0289 u32 attr, int channel, const char **str)
0290 {
0291 struct peci_cputemp *priv = dev_get_drvdata(dev);
0292
0293 if (attr != hwmon_temp_label)
0294 return -EOPNOTSUPP;
0295
0296 *str = channel < channel_core ?
0297 cputemp_label[channel] : priv->coretemp_label[channel - channel_core];
0298
0299 return 0;
0300 }
0301
0302 static int cputemp_read(struct device *dev, enum hwmon_sensor_types type,
0303 u32 attr, int channel, long *val)
0304 {
0305 struct peci_cputemp *priv = dev_get_drvdata(dev);
0306
0307 switch (attr) {
0308 case hwmon_temp_input:
0309 switch (channel) {
0310 case channel_die:
0311 return get_die_temp(priv, val);
0312 case channel_dts:
0313 return get_dts(priv, val);
0314 case channel_tcontrol:
0315 return get_temp_target(priv, tcontrol_type, val);
0316 case channel_tthrottle:
0317 return get_temp_target(priv, tthrottle_type, val);
0318 case channel_tjmax:
0319 return get_temp_target(priv, tjmax_type, val);
0320 default:
0321 return get_core_temp(priv, channel - channel_core, val);
0322 }
0323 break;
0324 case hwmon_temp_max:
0325 return get_temp_target(priv, tcontrol_type, val);
0326 case hwmon_temp_crit:
0327 return get_temp_target(priv, tjmax_type, val);
0328 case hwmon_temp_crit_hyst:
0329 return get_temp_target(priv, crit_hyst_type, val);
0330 default:
0331 return -EOPNOTSUPP;
0332 }
0333
0334 return 0;
0335 }
0336
0337 static umode_t cputemp_is_visible(const void *data, enum hwmon_sensor_types type,
0338 u32 attr, int channel)
0339 {
0340 const struct peci_cputemp *priv = data;
0341
0342 if (channel > CPUTEMP_CHANNEL_NUMS)
0343 return 0;
0344
0345 if (channel < channel_core)
0346 return 0444;
0347
0348 if (test_bit(channel - channel_core, priv->core_mask))
0349 return 0444;
0350
0351 return 0;
0352 }
0353
0354 static int init_core_mask(struct peci_cputemp *priv)
0355 {
0356 struct peci_device *peci_dev = priv->peci_dev;
0357 struct resolved_cores_reg *reg = priv->gen_info->reg;
0358 u64 core_mask;
0359 u32 data;
0360 int ret;
0361
0362
0363 switch (peci_dev->info.model) {
0364 case INTEL_FAM6_ICELAKE_X:
0365 case INTEL_FAM6_ICELAKE_D:
0366 ret = peci_ep_pci_local_read(peci_dev, 0, reg->bus, reg->dev,
0367 reg->func, reg->offset + 4, &data);
0368 if (ret)
0369 return ret;
0370
0371 core_mask = (u64)data << 32;
0372
0373 ret = peci_ep_pci_local_read(peci_dev, 0, reg->bus, reg->dev,
0374 reg->func, reg->offset, &data);
0375 if (ret)
0376 return ret;
0377
0378 core_mask |= data;
0379
0380 break;
0381 default:
0382 ret = peci_pci_local_read(peci_dev, reg->bus, reg->dev,
0383 reg->func, reg->offset, &data);
0384 if (ret)
0385 return ret;
0386
0387 core_mask = data;
0388
0389 break;
0390 }
0391
0392 if (!core_mask)
0393 return -EIO;
0394
0395 bitmap_from_u64(priv->core_mask, core_mask);
0396
0397 return 0;
0398 }
0399
0400 static int create_temp_label(struct peci_cputemp *priv)
0401 {
0402 unsigned long core_max = find_last_bit(priv->core_mask, CORE_NUMS_MAX);
0403 int i;
0404
0405 priv->coretemp_label = devm_kzalloc(priv->dev, core_max * sizeof(char *), GFP_KERNEL);
0406 if (!priv->coretemp_label)
0407 return -ENOMEM;
0408
0409 for_each_set_bit(i, priv->core_mask, CORE_NUMS_MAX) {
0410 priv->coretemp_label[i] = devm_kasprintf(priv->dev, GFP_KERNEL, "Core %d", i);
0411 if (!priv->coretemp_label[i])
0412 return -ENOMEM;
0413 }
0414
0415 return 0;
0416 }
0417
0418 static void check_resolved_cores(struct peci_cputemp *priv)
0419 {
0420
0421
0422
0423
0424
0425 if (init_core_mask(priv))
0426 return;
0427
0428 if (create_temp_label(priv))
0429 bitmap_zero(priv->core_mask, CORE_NUMS_MAX);
0430 }
0431
0432 static void sensor_init(struct peci_cputemp *priv)
0433 {
0434 int i;
0435
0436 mutex_init(&priv->temp.target.state.lock);
0437 mutex_init(&priv->temp.die.state.lock);
0438 mutex_init(&priv->temp.dts.state.lock);
0439
0440 for_each_set_bit(i, priv->core_mask, CORE_NUMS_MAX)
0441 mutex_init(&priv->temp.core[i].state.lock);
0442 }
0443
0444 static const struct hwmon_ops peci_cputemp_ops = {
0445 .is_visible = cputemp_is_visible,
0446 .read_string = cputemp_read_string,
0447 .read = cputemp_read,
0448 };
0449
0450 static const struct hwmon_channel_info *peci_cputemp_info[] = {
0451 HWMON_CHANNEL_INFO(temp,
0452
0453 HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX |
0454 HWMON_T_CRIT | HWMON_T_CRIT_HYST,
0455
0456 HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX |
0457 HWMON_T_CRIT | HWMON_T_CRIT_HYST,
0458
0459 HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_CRIT,
0460
0461 HWMON_T_LABEL | HWMON_T_INPUT,
0462
0463 HWMON_T_LABEL | HWMON_T_INPUT,
0464
0465 [channel_core ... CPUTEMP_CHANNEL_NUMS - 1] =
0466 HWMON_T_LABEL | HWMON_T_INPUT),
0467 NULL
0468 };
0469
0470 static const struct hwmon_chip_info peci_cputemp_chip_info = {
0471 .ops = &peci_cputemp_ops,
0472 .info = peci_cputemp_info,
0473 };
0474
0475 static int peci_cputemp_probe(struct auxiliary_device *adev,
0476 const struct auxiliary_device_id *id)
0477 {
0478 struct device *dev = &adev->dev;
0479 struct peci_device *peci_dev = to_peci_device(dev->parent);
0480 struct peci_cputemp *priv;
0481 struct device *hwmon_dev;
0482
0483 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0484 if (!priv)
0485 return -ENOMEM;
0486
0487 priv->name = devm_kasprintf(dev, GFP_KERNEL, "peci_cputemp.cpu%d",
0488 peci_dev->info.socket_id);
0489 if (!priv->name)
0490 return -ENOMEM;
0491
0492 priv->dev = dev;
0493 priv->peci_dev = peci_dev;
0494 priv->gen_info = (const struct cpu_info *)id->driver_data;
0495
0496
0497
0498
0499
0500
0501 if (peci_dev->info.peci_revision < priv->gen_info->min_peci_revision)
0502 dev_warn(priv->dev,
0503 "Unexpected PECI revision %#x, some features may be unavailable\n",
0504 peci_dev->info.peci_revision);
0505
0506 check_resolved_cores(priv);
0507
0508 sensor_init(priv);
0509
0510 hwmon_dev = devm_hwmon_device_register_with_info(priv->dev, priv->name,
0511 priv, &peci_cputemp_chip_info, NULL);
0512
0513 return PTR_ERR_OR_ZERO(hwmon_dev);
0514 }
0515
0516
0517
0518
0519
0520 static struct resolved_cores_reg resolved_cores_reg_hsx = {
0521 .bus = 1,
0522 .dev = 30,
0523 .func = 3,
0524 .offset = 0xb4,
0525 };
0526
0527 static struct resolved_cores_reg resolved_cores_reg_icx = {
0528 .bus = 14,
0529 .dev = 30,
0530 .func = 3,
0531 .offset = 0xd0,
0532 };
0533
0534 static const struct cpu_info cpu_hsx = {
0535 .reg = &resolved_cores_reg_hsx,
0536 .min_peci_revision = 0x33,
0537 .thermal_margin_to_millidegree = &dts_eight_dot_eight_to_millidegree,
0538 };
0539
0540 static const struct cpu_info cpu_icx = {
0541 .reg = &resolved_cores_reg_icx,
0542 .min_peci_revision = 0x40,
0543 .thermal_margin_to_millidegree = &dts_ten_dot_six_to_millidegree,
0544 };
0545
0546 static const struct auxiliary_device_id peci_cputemp_ids[] = {
0547 {
0548 .name = "peci_cpu.cputemp.hsx",
0549 .driver_data = (kernel_ulong_t)&cpu_hsx,
0550 },
0551 {
0552 .name = "peci_cpu.cputemp.bdx",
0553 .driver_data = (kernel_ulong_t)&cpu_hsx,
0554 },
0555 {
0556 .name = "peci_cpu.cputemp.bdxd",
0557 .driver_data = (kernel_ulong_t)&cpu_hsx,
0558 },
0559 {
0560 .name = "peci_cpu.cputemp.skx",
0561 .driver_data = (kernel_ulong_t)&cpu_hsx,
0562 },
0563 {
0564 .name = "peci_cpu.cputemp.icx",
0565 .driver_data = (kernel_ulong_t)&cpu_icx,
0566 },
0567 {
0568 .name = "peci_cpu.cputemp.icxd",
0569 .driver_data = (kernel_ulong_t)&cpu_icx,
0570 },
0571 { }
0572 };
0573 MODULE_DEVICE_TABLE(auxiliary, peci_cputemp_ids);
0574
0575 static struct auxiliary_driver peci_cputemp_driver = {
0576 .probe = peci_cputemp_probe,
0577 .id_table = peci_cputemp_ids,
0578 };
0579
0580 module_auxiliary_driver(peci_cputemp_driver);
0581
0582 MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
0583 MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
0584 MODULE_DESCRIPTION("PECI cputemp driver");
0585 MODULE_LICENSE("GPL");
0586 MODULE_IMPORT_NS(PECI_CPU);