summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/peci-cputemp.c65
-rw-r--r--drivers/hwmon/peci-dimmtemp.c78
-rw-r--r--drivers/mfd/intel-peci-client.c6
-rw-r--r--include/linux/mfd/intel-peci-client.h7
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)