diff options
-rw-r--r-- | drivers/hwmon/peci-cputemp.c | 65 | ||||
-rw-r--r-- | drivers/hwmon/peci-dimmtemp.c | 78 | ||||
-rw-r--r-- | drivers/mfd/intel-peci-client.c | 6 | ||||
-rw-r--r-- | include/linux/mfd/intel-peci-client.h | 7 |
4 files changed, 138 insertions, 18 deletions
diff --git a/drivers/hwmon/peci-cputemp.c b/drivers/hwmon/peci-cputemp.c index 7b68cf6b20af..c1b842069168 100644 --- a/drivers/hwmon/peci-cputemp.c +++ b/drivers/hwmon/peci-cputemp.c @@ -331,21 +331,58 @@ static int check_resolved_cores(struct peci_cputemp *priv) int ret; /* Get the RESOLVED_CORES register value */ - msg.addr = priv->mgr->client->addr; - msg.device = 30; - msg.function = 3; - msg.rx_len = 4; - msg.bus = 1; - msg.reg = 0xb4; - - ret = peci_command(priv->mgr->client->adapter, - PECI_CMD_RD_PCI_CFG_LOCAL, &msg); - if (msg.cc != PECI_DEV_CC_SUCCESS) - ret = -EAGAIN; - if (ret) - return ret; + switch (priv->gen_info->model) { + case INTEL_FAM6_ICELAKE_X: + msg.addr = priv->mgr->client->addr; + msg.device = 30; + msg.function = 3; + msg.bus = 14; + msg.reg = 0xd4; + msg.rx_len = 4; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_PCI_CFG_LOCAL, &msg); + if (msg.cc != PECI_DEV_CC_SUCCESS) + ret = -EAGAIN; + if (ret) + return ret; + + priv->core_mask = le32_to_cpup((__le32 *)msg.pci_config); + priv->core_mask <<= 32; + + msg.reg = 0xd0; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_PCI_CFG_LOCAL, &msg); + + if (msg.cc != PECI_DEV_CC_SUCCESS) + ret = -EAGAIN; + if (ret) { + priv->core_mask = 0; + return ret; + } + + priv->core_mask |= le32_to_cpup((__le32 *)msg.pci_config); + break; + default: + msg.addr = priv->mgr->client->addr; + msg.device = 30; + msg.function = 3; + msg.bus = 1; + msg.reg = 0xb4; + msg.rx_len = 4; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_PCI_CFG_LOCAL, &msg); + if (msg.cc != PECI_DEV_CC_SUCCESS) + ret = -EAGAIN; + if (ret) + return ret; + + priv->core_mask = le32_to_cpup((__le32 *)msg.pci_config); + break; + } - priv->core_mask = le32_to_cpup((__le32 *)msg.pci_config); if (!priv->core_mask) return -EAGAIN; diff --git a/drivers/hwmon/peci-dimmtemp.c b/drivers/hwmon/peci-dimmtemp.c index 1367e0cf8e78..f5a778f52beb 100644 --- a/drivers/hwmon/peci-dimmtemp.c +++ b/drivers/hwmon/peci-dimmtemp.c @@ -11,7 +11,8 @@ #include "peci-hwmon.h" #define DIMM_MASK_CHECK_DELAY_JIFFIES msecs_to_jiffies(5000) -#define DIMM_MASK_CHECK_RETRY_MAX 60 /* 60 x 5 secs = 5 minutes */ +#define DIMM_MASK_CHECK_RETRY_MAX -1 /* 60 x 5 secs = 5 minutes */ + /* -1 = no timeout */ #define DIMM_TEMP_MAX_DEFAULT 90000 #define DIMM_TEMP_CRIT_DEFAULT 100000 @@ -34,11 +35,12 @@ struct peci_dimmtemp { char **dimmtemp_label; }; -static const u8 support_model[4] = { +static const u8 support_model[] = { INTEL_FAM6_HASWELL_X, INTEL_FAM6_BROADWELL_X, INTEL_FAM6_SKYLAKE_X, INTEL_FAM6_SKYLAKE_XD, + INTEL_FAM6_ICELAKE_X, }; static inline int read_ddr_dimm_temp_config(struct peci_dimmtemp *priv, @@ -55,7 +57,9 @@ static int get_dimm_temp(struct peci_dimmtemp *priv, int dimm_no) int dimm_order = dimm_no % priv->gen_info->dimm_idx_max; int chan_rank = dimm_no / priv->gen_info->dimm_idx_max; struct peci_rd_pci_cfg_local_msg rp_msg; + struct peci_rd_end_pt_cfg_msg re_msg; u8 cfg_data[4]; + u8 cpu_seg, cpu_bus; int ret; if (!peci_sensor_need_update(&priv->temp[dimm_no])) @@ -68,6 +72,73 @@ static int get_dimm_temp(struct peci_dimmtemp *priv, int dimm_no) priv->temp[dimm_no].value = cfg_data[dimm_order] * 1000; switch (priv->gen_info->model) { + case INTEL_FAM6_ICELAKE_X: + re_msg.addr = priv->mgr->client->addr; + re_msg.rx_len = 4; + re_msg.msg_type = PECI_ENDPTCFG_TYPE_LOCAL_PCI; + re_msg.params.pci_cfg.seg = 0; + re_msg.params.pci_cfg.bus = 13; + re_msg.params.pci_cfg.device = 0; + re_msg.params.pci_cfg.function = 2; + re_msg.params.pci_cfg.reg = 0xd4; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_END_PT_CFG, &re_msg); + if (ret || re_msg.cc != PECI_DEV_CC_SUCCESS || + !(re_msg.data[3] & BIT(7))) { + /* Use default or previous value */ + ret = 0; + break; + } + + re_msg.msg_type = PECI_ENDPTCFG_TYPE_LOCAL_PCI; + re_msg.params.pci_cfg.reg = 0xd0; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_END_PT_CFG, &re_msg); + if (ret || re_msg.cc != PECI_DEV_CC_SUCCESS) { + /* Use default or previous value */ + ret = 0; + break; + } + + cpu_seg = re_msg.data[2]; + cpu_bus = re_msg.data[0]; + + re_msg.addr = priv->mgr->client->addr; + re_msg.msg_type = PECI_ENDPTCFG_TYPE_MMIO; + re_msg.params.mmio.seg = cpu_seg; + re_msg.params.mmio.bus = cpu_bus; + /* + * Device 26, Offset 224e0: IMC 0 channel 0 -> rank 0 + * Device 26, Offset 264e0: IMC 0 channel 1 -> rank 1 + * Device 27, Offset 224e0: IMC 1 channel 0 -> rank 2 + * Device 27, Offset 264e0: IMC 1 channel 1 -> rank 3 + * Device 28, Offset 224e0: IMC 2 channel 0 -> rank 4 + * Device 28, Offset 264e0: IMC 2 channel 1 -> rank 5 + * Device 29, Offset 224e0: IMC 3 channel 0 -> rank 6 + * Device 29, Offset 264e0: IMC 3 channel 1 -> rank 7 + */ + re_msg.params.mmio.device = 0x1a + chan_rank / 2; + re_msg.params.mmio.function = 0; + re_msg.params.mmio.bar = 0; + re_msg.params.mmio.addr_type = PECI_ENDPTCFG_ADDR_TYPE_MMIO_Q; + re_msg.params.mmio.offset = 0x224e0 + dimm_order * 4; + if (chan_rank % 2) + re_msg.params.mmio.offset += 0x4000; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_END_PT_CFG, &re_msg); + if (ret || re_msg.cc != PECI_DEV_CC_SUCCESS || + re_msg.data[1] == 0 || re_msg.data[2] == 0) { + /* Use default or previous value */ + ret = 0; + break; + } + + priv->temp_max[dimm_no] = re_msg.data[1] * 1000; + priv->temp_crit[dimm_no] = re_msg.data[2] * 1000; + break; case INTEL_FAM6_SKYLAKE_X: rp_msg.addr = priv->mgr->client->addr; rp_msg.bus = 2; @@ -288,7 +359,8 @@ static int create_dimm_temp_info(struct peci_dimmtemp *priv) ret = check_populated_dimms(priv); if (ret) { if (ret == -EAGAIN) { - if (priv->retry_count < DIMM_MASK_CHECK_RETRY_MAX) { + if (DIMM_MASK_CHECK_RETRY_MAX == -1 || + priv->retry_count < DIMM_MASK_CHECK_RETRY_MAX) { queue_delayed_work(priv->work_queue, &priv->work_handler, DIMM_MASK_CHECK_DELAY_JIFFIES); diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c index 3fcdd89d0b15..1b96cefb8563 100644 --- a/drivers/mfd/intel-peci-client.c +++ b/drivers/mfd/intel-peci-client.c @@ -50,6 +50,12 @@ static const struct cpu_gen_info cpu_gen_info_table[] = { .core_mask_bits = CORE_MASK_BITS_ON_SKXD, .chan_rank_max = CHAN_RANK_MAX_ON_SKXD, .dimm_idx_max = DIMM_IDX_MAX_ON_SKXD }, + { /* Icelake Xeon */ + .family = INTEL_FAM6, + .model = INTEL_FAM6_ICELAKE_X, + .core_mask_bits = CORE_MASK_BITS_ON_ICX, + .chan_rank_max = CHAN_RANK_MAX_ON_ICX, + .dimm_idx_max = DIMM_IDX_MAX_ON_ICX }, }; static int peci_client_get_cpu_gen_info(struct peci_client_manager *priv) diff --git a/include/linux/mfd/intel-peci-client.h b/include/linux/mfd/intel-peci-client.h index c60591348c37..1303e3f93c33 100644 --- a/include/linux/mfd/intel-peci-client.h +++ b/include/linux/mfd/intel-peci-client.h @@ -18,6 +18,7 @@ #define INTEL_FAM6_BROADWELL_X 0x4F #define INTEL_FAM6_SKYLAKE_X 0x55 #define INTEL_FAM6_SKYLAKE_XD 0x56 +#define INTEL_FAM6_ICELAKE_X 0x6A #endif #define INTEL_FAM6 6 /* P6 (Pentium Pro and later) */ @@ -38,7 +39,11 @@ #define CHAN_RANK_MAX_ON_SKXD 2 /* Max number of channel ranks on Skylake D */ #define DIMM_IDX_MAX_ON_SKXD 2 /* Max DIMM index per channel on Skylake D */ -#define CORE_MASK_BITS_MAX CORE_MASK_BITS_ON_SKX +#define CORE_MASK_BITS_ON_ICX 64 +#define CHAN_RANK_MAX_ON_ICX 8 /* Max number of channel ranks on Icelake */ +#define DIMM_IDX_MAX_ON_ICX 2 /* Max DIMM index per channel on Icelake */ + +#define CORE_MASK_BITS_MAX CORE_MASK_BITS_ON_ICX #define CHAN_RANK_MAX CHAN_RANK_MAX_ON_HSX #define DIMM_IDX_MAX DIMM_IDX_MAX_ON_HSX #define DIMM_NUMS_MAX (CHAN_RANK_MAX * DIMM_IDX_MAX) |