Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright (c) 2018-2021 Intel Corporation
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  * Error codes:
0150  *   0x8000: General sensor error
0151  *   0x8001: Reserved
0152  *   0x8002: Underflow on reading value
0153  *   0x8003-0x81ff: Reserved
0154  */
0155 static bool dts_valid(u16 val)
0156 {
0157     return val < 0x8000 || val > 0x81ff;
0158 }
0159 
0160 /*
0161  * Processors return a value of DTS reading in S10.6 fixed point format
0162  * (16 bits: 10-bit signed magnitude, 6-bit fraction).
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  * For older processors, thermal margin reading is returned in S8.8 fixed
0171  * point format (16 bits: 8-bit signed magnitude, 8-bit fraction).
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     /* Note that the tcontrol should be available before calling it */
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     /* Note that the tjmax should be available before calling it */
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     /* Get the RESOLVED_CORES register value */
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      * Failure to resolve cores is non-critical, we're still able to
0422      * provide other sensor data.
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                /* Die temperature */
0453                HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX |
0454                HWMON_T_CRIT | HWMON_T_CRIT_HYST,
0455                /* DTS margin */
0456                HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX |
0457                HWMON_T_CRIT | HWMON_T_CRIT_HYST,
0458                /* Tcontrol temperature */
0459                HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_CRIT,
0460                /* Tthrottle temperature */
0461                HWMON_T_LABEL | HWMON_T_INPUT,
0462                /* Tjmax temperature */
0463                HWMON_T_LABEL | HWMON_T_INPUT,
0464                /* Core temperature - for all core channels */
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      * This is just a sanity check. Since we're using commands that are
0498      * guaranteed to be supported on a given platform, we should never see
0499      * revision lower than expected.
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  * RESOLVED_CORES PCI configuration register may have different location on
0518  * different platforms.
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);