diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch | 1375 |
1 files changed, 1189 insertions, 186 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch index db21250bb..d2ecdfd72 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch @@ -1,4 +1,4 @@ -From 63ccbbe64f7e6560233971b886f6166fc59d20ef Mon Sep 17 00:00:00 2001 +From 9c27803dd432c7a9fc57dd3e16f0fd724919575e Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> Date: Mon, 7 Jan 2019 09:56:10 -0800 Subject: [PATCH] Update PECI drivers to sync with linux upstreaming version @@ -10,28 +10,32 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> --- Documentation/hwmon/peci-cputemp | 34 +- drivers/hwmon/Kconfig | 4 +- - drivers/hwmon/peci-cputemp.c | 156 ++++-- + drivers/hwmon/peci-cputemp.c | 162 ++++-- drivers/hwmon/peci-dimmtemp.c | 69 +-- drivers/hwmon/peci-hwmon.h | 9 +- drivers/mfd/Kconfig | 5 +- - drivers/mfd/intel-peci-client.c | 43 +- - drivers/peci/Kconfig | 35 +- - drivers/peci/Makefile | 6 +- - drivers/peci/busses/Kconfig | 19 + - drivers/peci/busses/Makefile | 6 + + drivers/mfd/intel-peci-client.c | 49 +- + drivers/peci/Kconfig | 46 +- + drivers/peci/Makefile | 7 +- + drivers/peci/busses/Kconfig | 32 ++ + drivers/peci/busses/Makefile | 7 + drivers/peci/busses/peci-aspeed.c | 494 +++++++++++++++++++ + drivers/peci/busses/peci-npcm.c | 410 +++++++++++++++ drivers/peci/peci-aspeed.c | 505 ------------------- - drivers/peci/peci-core.c | 889 ++++++++++++++++++---------------- - drivers/peci/peci-dev.c | 340 +++++++++++++ - include/linux/mfd/intel-peci-client.h | 6 +- + drivers/peci/peci-core.c | 905 +++++++++++++++++++--------------- + drivers/peci/peci-dev.c | 346 +++++++++++++ + drivers/peci/peci-npcm.c | 410 --------------- + include/linux/mfd/intel-peci-client.h | 32 +- include/linux/peci.h | 30 +- - include/uapi/linux/peci-ioctl.h | 394 ++++++++------- - 18 files changed, 1805 insertions(+), 1239 deletions(-) + include/uapi/linux/peci-ioctl.h | 416 +++++++++------- + 20 files changed, 2296 insertions(+), 1676 deletions(-) create mode 100644 drivers/peci/busses/Kconfig create mode 100644 drivers/peci/busses/Makefile create mode 100644 drivers/peci/busses/peci-aspeed.c + create mode 100644 drivers/peci/busses/peci-npcm.c delete mode 100644 drivers/peci/peci-aspeed.c create mode 100644 drivers/peci/peci-dev.c + delete mode 100644 drivers/peci/peci-npcm.c diff --git a/Documentation/hwmon/peci-cputemp b/Documentation/hwmon/peci-cputemp index 821a9258f2e6..a3a3e465c888 100644 @@ -89,7 +93,7 @@ index 821a9258f2e6..a3a3e465c888 100644 +temp[6-*]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of the core. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 996e80590b5b..93945eb19261 100644 +index 18cd3b17f660..0bd06a938526 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1321,7 +1321,7 @@ config SENSORS_PECI_CPUTEMP @@ -111,7 +115,7 @@ index 996e80590b5b..93945eb19261 100644 source "drivers/hwmon/pmbus/Kconfig" diff --git a/drivers/hwmon/peci-cputemp.c b/drivers/hwmon/peci-cputemp.c -index 11880c86a854..30ba1638e358 100644 +index 11880c86a854..3cb2db2fdf0a 100644 --- a/drivers/hwmon/peci-cputemp.c +++ b/drivers/hwmon/peci-cputemp.c @@ -1,5 +1,5 @@ @@ -214,7 +218,7 @@ index 11880c86a854..30ba1638e358 100644 /* Note that the tjmax should be available before calling it */ priv->temp.die.value = priv->temp.tjmax.value + -@@ -144,24 +151,67 @@ static int get_die_temp(struct peci_cputemp *priv) +@@ -144,24 +151,70 @@ static int get_die_temp(struct peci_cputemp *priv) return 0; } @@ -237,6 +241,9 @@ index 11880c86a854..30ba1638e358 100644 + if (ret) + return ret; + ++ if (msg.cc != PECI_DEV_CC_SUCCESS) ++ return -EAGAIN; ++ + dts_margin = (msg.pkg_config[1] << 8) | msg.pkg_config[0]; + + /** @@ -289,7 +296,7 @@ index 11880c86a854..30ba1638e358 100644 * Processors return a value of the core DTS reading in 10.6 format * (10 bits signed decimal, 6 bits fractional). * Error codes: -@@ -192,6 +242,7 @@ static int cputemp_read_string(struct device *dev, +@@ -192,6 +245,7 @@ static int cputemp_read_string(struct device *dev, return -EOPNOTSUPP; *str = cputemp_label[channel]; @@ -297,7 +304,7 @@ index 11880c86a854..30ba1638e358 100644 return 0; } -@@ -200,26 +251,33 @@ static int cputemp_read(struct device *dev, +@@ -200,26 +254,33 @@ static int cputemp_read(struct device *dev, u32 attr, int channel, long *val) { struct peci_cputemp *priv = dev_get_drvdata(dev); @@ -337,7 +344,7 @@ index 11880c86a854..30ba1638e358 100644 case channel_tcontrol: *val = priv->temp.tcontrol.value; break; -@@ -231,8 +289,8 @@ static int cputemp_read(struct device *dev, +@@ -231,8 +292,8 @@ static int cputemp_read(struct device *dev, break; default: core_index = channel - DEFAULT_CHANNEL_NUMS; @@ -348,7 +355,7 @@ index 11880c86a854..30ba1638e358 100644 break; *val = priv->temp.core[core_index].value; -@@ -249,11 +307,11 @@ static int cputemp_read(struct device *dev, +@@ -249,11 +310,11 @@ static int cputemp_read(struct device *dev, *val = priv->temp.tjmax.value - priv->temp.tcontrol.value; break; default: @@ -362,7 +369,7 @@ index 11880c86a854..30ba1638e358 100644 } static umode_t cputemp_is_visible(const void *data, -@@ -262,11 +320,11 @@ static umode_t cputemp_is_visible(const void *data, +@@ -262,11 +323,11 @@ static umode_t cputemp_is_visible(const void *data, { const struct peci_cputemp *priv = data; @@ -379,7 +386,7 @@ index 11880c86a854..30ba1638e358 100644 return 0; } -@@ -280,7 +338,7 @@ static const struct hwmon_ops cputemp_ops = { +@@ -280,7 +341,7 @@ static const struct hwmon_ops cputemp_ops = { static int check_resolved_cores(struct peci_cputemp *priv) { struct peci_rd_pci_cfg_local_msg msg; @@ -388,7 +395,7 @@ index 11880c86a854..30ba1638e358 100644 /* Get the RESOLVED_CORES register value */ msg.addr = priv->mgr->client->addr; -@@ -290,30 +348,31 @@ static int check_resolved_cores(struct peci_cputemp *priv) +@@ -290,30 +351,34 @@ static int check_resolved_cores(struct peci_cputemp *priv) msg.reg = REG_RESOLVED_CORES_OFFSET; msg.rx_len = 4; @@ -400,6 +407,9 @@ index 11880c86a854..30ba1638e358 100644 + PECI_CMD_RD_PCI_CFG_LOCAL, &msg); + if (ret) + return ret; ++ ++ if (msg.cc != PECI_DEV_CC_SUCCESS) ++ return -EAGAIN; priv->core_mask = le32_to_cpup((__le32 *)msg.pci_config); if (!priv->core_mask) @@ -429,7 +439,7 @@ index 11880c86a854..30ba1638e358 100644 priv->temp_config[priv->config_idx++] = config_table[channel_core]; -@@ -326,7 +385,7 @@ static int peci_cputemp_probe(struct platform_device *pdev) +@@ -326,7 +391,7 @@ static int peci_cputemp_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct peci_cputemp *priv; struct device *hwmon_dev; @@ -438,7 +448,7 @@ index 11880c86a854..30ba1638e358 100644 if ((mgr->client->adapter->cmd_mask & (BIT(PECI_CMD_GET_TEMP) | BIT(PECI_CMD_RD_PKG_CFG))) != -@@ -346,12 +405,13 @@ static int peci_cputemp_probe(struct platform_device *pdev) +@@ -346,12 +411,13 @@ static int peci_cputemp_probe(struct platform_device *pdev) mgr->client->addr - PECI_BASE_ADDR); priv->temp_config[priv->config_idx++] = config_table[channel_die]; @@ -686,7 +696,7 @@ index 9af5730ad7ba..28087e9cd4da 100644 bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support" depends on SA1100_H3100 || SA1100_H3600 diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c -index d53e4f1078ac..d62442438512 100644 +index d53e4f1078ac..466085fd43b9 100644 --- a/drivers/mfd/intel-peci-client.c +++ b/drivers/mfd/intel-peci-client.c @@ -1,12 +1,12 @@ @@ -717,7 +727,7 @@ index d53e4f1078ac..d62442438512 100644 static struct mfd_cell peci_functions[] = { { .name = "peci-cputemp", }, { .name = "peci-dimmtemp", }, -@@ -31,19 +25,19 @@ static struct mfd_cell peci_functions[] = { +@@ -31,19 +25,25 @@ static struct mfd_cell peci_functions[] = { }; static const struct cpu_gen_info cpu_gen_info_table[] = { @@ -736,11 +746,17 @@ index d53e4f1078ac..d62442438512 100644 .chan_rank_max = CHAN_RANK_MAX_ON_BDX, .dimm_idx_max = DIMM_IDX_MAX_ON_BDX }, - [CPU_GEN_SKX] = { ++ { /* Broadwell Xeon D */ ++ .family = 6, /* Family code */ ++ .model = INTEL_FAM6_BROADWELL_XEON_D, ++ .core_max = CORE_MAX_ON_XD, ++ .chan_rank_max = CHAN_RANK_MAX_ON_XD, ++ .dimm_idx_max = DIMM_IDX_MAX_ON_XD }, + { /* Skylake Xeon */ .family = 6, /* Family code */ .model = INTEL_FAM6_SKYLAKE_X, .core_max = CORE_MAX_ON_SKX, -@@ -53,16 +47,17 @@ static const struct cpu_gen_info cpu_gen_info_table[] = { +@@ -53,16 +53,17 @@ static const struct cpu_gen_info cpu_gen_info_table[] = { static int peci_client_get_cpu_gen_info(struct peci_client_manager *priv) { @@ -763,7 +779,7 @@ index d53e4f1078ac..d62442438512 100644 family = FIELD_PREP(LOWER_BYTE_MASK, FIELD_GET(CPU_ID_FAMILY_MASK, cpu_id)) | -@@ -83,11 +78,11 @@ static int peci_client_get_cpu_gen_info(struct peci_client_manager *priv) +@@ -83,11 +84,11 @@ static int peci_client_get_cpu_gen_info(struct peci_client_manager *priv) } if (!priv->gen_info) { @@ -778,7 +794,7 @@ index d53e4f1078ac..d62442438512 100644 } static int peci_client_probe(struct peci_client *client) -@@ -103,31 +98,29 @@ static int peci_client_probe(struct peci_client *client) +@@ -103,31 +104,29 @@ static int peci_client_probe(struct peci_client *client) dev_set_drvdata(dev, priv); priv->client = client; @@ -815,7 +831,7 @@ index d53e4f1078ac..d62442438512 100644 static const struct peci_device_id peci_client_ids[] = { { .name = "peci-client" }, diff --git a/drivers/peci/Kconfig b/drivers/peci/Kconfig -index 9e9845ebcff4..9752feee2454 100644 +index 7293108fb543..9752feee2454 100644 --- a/drivers/peci/Kconfig +++ b/drivers/peci/Kconfig @@ -2,10 +2,12 @@ @@ -833,7 +849,7 @@ index 9e9845ebcff4..9752feee2454 100644 help The Platform Environment Control Interface (PECI) is a one-wire bus interface that provides a communication channel from Intel processors -@@ -14,26 +16,23 @@ config PECI +@@ -14,37 +16,23 @@ config PECI If you want PECI support, you should say Y here and also to the specific driver for your bus adapter(s) below. @@ -842,42 +858,53 @@ index 9e9845ebcff4..9752feee2454 100644 -# -# PECI hardware bus configuration -# +- +-menu "PECI Hardware Bus support" +- +-config PECI_ASPEED +- tristate "ASPEED PECI support" +- select REGMAP_MMIO +- depends on OF +- depends on ARCH_ASPEED || COMPILE_TEST +- help +- Say Y here if you want support for the Platform Environment Control +- Interface (PECI) bus adapter driver on the ASPEED SoCs. + This support is also available as a module. If so, the module + will be called peci-core. --menu "PECI Hardware Bus support" +- This support is also available as a module. If so, the module +- will be called peci-aspeed. +if PECI --config PECI_ASPEED -- tristate "ASPEED PECI support" +-config PECI_NPCM +- tristate "Nuvoton NPCM PECI support" - select REGMAP_MMIO - depends on OF -- depends on ARCH_ASPEED || COMPILE_TEST +- depends on ARCH_NPCM || COMPILE_TEST +config PECI_CHARDEV + tristate "PECI device interface" help - Say Y here if you want support for the Platform Environment Control -- Interface (PECI) bus adapter driver on the ASPEED SoCs. +- Interface (PECI) bus adapter driver on the Nuvoton NPCM SoCs. + Say Y here to use peci-* device files, usually found in the /dev + directory on your system. They make it possible to have user-space + programs use the PECI bus. -- This support is also available as a module. If so, the module -- will be called peci-aspeed. -+ This support is also available as a module. If so, the module -+ will be called peci-dev. - + This support is also available as a module. If so, the module +- will be called peci-npcm. -endmenu ++ will be called peci-dev. ++ +source "drivers/peci/busses/Kconfig" endif # PECI + +endmenu diff --git a/drivers/peci/Makefile b/drivers/peci/Makefile -index 886285e69765..da8b0a33fa42 100644 +index 3326da54a21a..da8b0a33fa42 100644 --- a/drivers/peci/Makefile +++ b/drivers/peci/Makefile -@@ -1,9 +1,11 @@ +@@ -1,10 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 # -# Makefile for the PECI core and bus drivers. @@ -890,13 +917,14 @@ index 886285e69765..da8b0a33fa42 100644 # Hardware specific bus drivers -obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o +-obj-$(CONFIG_PECI_NPCM) += peci-npcm.o +obj-y += busses/ diff --git a/drivers/peci/busses/Kconfig b/drivers/peci/busses/Kconfig new file mode 100644 -index 000000000000..a20d470b4250 +index 000000000000..bfacafb7a7ba --- /dev/null +++ b/drivers/peci/busses/Kconfig -@@ -0,0 +1,19 @@ +@@ -0,0 +1,32 @@ +# +# PECI hardware bus configuration +# @@ -912,22 +940,36 @@ index 000000000000..a20d470b4250 + Say Y here if you want support for the Platform Environment Control + Interface (PECI) bus adapter driver on the ASPEED SoCs. + -+ This support is also available as a module. If so, the module ++ This support is also available as a module. If so, the module + will be called peci-aspeed. + ++config PECI_NPCM ++ tristate "Nuvoton NPCM PECI support" ++ select REGMAP_MMIO ++ depends on OF ++ depends on ARCH_NPCM || COMPILE_TEST ++ depends on PECI ++ help ++ Say Y here if you want support for the Platform Environment Control ++ Interface (PECI) bus adapter driver on the Nuvoton NPCM SoCs. ++ ++ This support is also available as a module. If so, the module ++ will be called peci-npcm. ++ +endmenu diff --git a/drivers/peci/busses/Makefile b/drivers/peci/busses/Makefile new file mode 100644 -index 000000000000..69e31dfaca19 +index 000000000000..aa8ce3ae5947 --- /dev/null +++ b/drivers/peci/busses/Makefile -@@ -0,0 +1,6 @@ +@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the PECI hardware bus drivers. +# + +obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o ++obj-$(CONFIG_PECI_NPCM) += peci-npcm.o diff --git a/drivers/peci/busses/peci-aspeed.c b/drivers/peci/busses/peci-aspeed.c new file mode 100644 index 000000000000..8a0dd40730cc @@ -1428,6 +1470,422 @@ index 000000000000..8a0dd40730cc +MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>"); +MODULE_DESCRIPTION("ASPEED PECI driver"); +MODULE_LICENSE("GPL v2"); +diff --git a/drivers/peci/busses/peci-npcm.c b/drivers/peci/busses/peci-npcm.c +new file mode 100644 +index 000000000000..f632365b1416 +--- /dev/null ++++ b/drivers/peci/busses/peci-npcm.c +@@ -0,0 +1,410 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2019 Nuvoton Technology corporation. ++ ++#include <linux/bitfield.h> ++#include <linux/clk.h> ++#include <linux/interrupt.h> ++#include <linux/jiffies.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/peci.h> ++#include <linux/platform_device.h> ++#include <linux/regmap.h> ++#include <linux/mfd/syscon.h> ++#include <linux/reset.h> ++ ++/* NPCM7xx GCR module */ ++#define NPCM7XX_INTCR3_OFFSET 0x9C ++#define NPCM7XX_INTCR3_PECIVSEL BIT(19) ++ ++/* NPCM PECI Registers */ ++#define NPCM_PECI_CTL_STS 0x00 ++#define NPCM_PECI_RD_LENGTH 0x04 ++#define NPCM_PECI_ADDR 0x08 ++#define NPCM_PECI_CMD 0x0C ++#define NPCM_PECI_CTL2 0x10 ++#define NPCM_PECI_WR_LENGTH 0x1C ++#define NPCM_PECI_PDDR 0x2C ++#define NPCM_PECI_DAT_INOUT(n) (0x100 + ((n) * 4)) ++ ++#define NPCM_PECI_MAX_REG 0x200 ++ ++/* NPCM_PECI_CTL_STS - 0x00 : Control Register */ ++#define NPCM_PECI_CTRL_DONE_INT_EN BIT(6) ++#define NPCM_PECI_CTRL_ABRT_ERR BIT(4) ++#define NPCM_PECI_CTRL_CRC_ERR BIT(3) ++#define NPCM_PECI_CTRL_DONE BIT(1) ++#define NPCM_PECI_CTRL_START_BUSY BIT(0) ++ ++/* NPCM_PECI_RD_LENGTH - 0x04 : Command Register */ ++#define NPCM_PECI_RD_LEN_MASK GENMASK(6, 0) ++ ++/* NPCM_PECI_CMD - 0x10 : Command Register */ ++#define NPCM_PECI_CTL2_MASK GENMASK(7, 6) ++ ++/* NPCM_PECI_WR_LENGTH - 0x1C : Command Register */ ++#define NPCM_PECI_WR_LEN_MASK GENMASK(6, 0) ++ ++/* NPCM_PECI_PDDR - 0x2C : Command Register */ ++#define NPCM_PECI_PDDR_MASK GENMASK(4, 0) ++ ++#define NPCM_PECI_INT_MASK (NPCM_PECI_CTRL_ABRT_ERR | \ ++ NPCM_PECI_CTRL_CRC_ERR | \ ++ NPCM_PECI_CTRL_DONE) ++ ++#define NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC 50000 ++#define NPCM_PECI_IDLE_CHECK_INTERVAL_USEC 10000 ++#define NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT 1000 ++#define NPCM_PECI_CMD_TIMEOUT_MS_MAX 60000 ++#define NPCM_PECI_HOST_NEG_BIT_RATE_MAX 31 ++#define NPCM_PECI_HOST_NEG_BIT_RATE_MIN 7 ++#define NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT 15 ++#define NPCM_PECI_PULL_DOWN_DEFAULT 0 ++#define NPCM_PECI_PULL_DOWN_MAX 2 ++ ++struct npcm_peci { ++ u32 cmd_timeout_ms; ++ u32 host_bit_rate; ++ struct completion xfer_complete; ++ struct regmap *gcr_regmap; ++ struct peci_adapter *adapter; ++ struct regmap *regmap; ++ u32 status; ++ spinlock_t lock; /* to sync completion status handling */ ++ struct device *dev; ++ struct clk *clk; ++ int irq; ++}; ++ ++static int npcm_peci_xfer_native(struct npcm_peci *priv, ++ struct peci_xfer_msg *msg) ++{ ++ long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms); ++ unsigned long flags; ++ unsigned int msg_rd; ++ u32 cmd_sts; ++ int i, rc; ++ ++ /* Check command sts and bus idle state */ ++ rc = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, ++ !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), ++ NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, ++ NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); ++ if (rc) ++ return rc; /* -ETIMEDOUT */ ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ reinit_completion(&priv->xfer_complete); ++ ++ regmap_write(priv->regmap, NPCM_PECI_ADDR, msg->addr); ++ regmap_write(priv->regmap, NPCM_PECI_RD_LENGTH, ++ NPCM_PECI_WR_LEN_MASK & msg->rx_len); ++ regmap_write(priv->regmap, NPCM_PECI_WR_LENGTH, ++ NPCM_PECI_WR_LEN_MASK & msg->tx_len); ++ ++ if (msg->tx_len) { ++ regmap_write(priv->regmap, NPCM_PECI_CMD, msg->tx_buf[0]); ++ ++ for (i = 0; i < (msg->tx_len - 1); i++) ++ regmap_write(priv->regmap, NPCM_PECI_DAT_INOUT(i), ++ msg->tx_buf[i + 1]); ++ } ++ ++ priv->status = 0; ++ regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, ++ NPCM_PECI_CTRL_START_BUSY, ++ NPCM_PECI_CTRL_START_BUSY); ++ ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ err = wait_for_completion_interruptible_timeout(&priv->xfer_complete, ++ timeout); ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ regmap_write(priv->regmap, NPCM_PECI_CMD, 0); ++ ++ if (err <= 0 || priv->status != NPCM_PECI_CTRL_DONE) { ++ if (err < 0) { /* -ERESTARTSYS */ ++ rc = (int)err; ++ goto err_irqrestore; ++ } else if (err == 0) { ++ dev_dbg(priv->dev, "Timeout waiting for a response!\n"); ++ rc = -ETIMEDOUT; ++ goto err_irqrestore; ++ } ++ ++ dev_dbg(priv->dev, "No valid response!\n"); ++ rc = -EIO; ++ goto err_irqrestore; ++ } ++ ++ for (i = 0; i < msg->rx_len; i++) { ++ regmap_read(priv->regmap, NPCM_PECI_DAT_INOUT(i), &msg_rd); ++ msg->rx_buf[i] = (u8)msg_rd; ++ } ++ ++err_irqrestore: ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return rc; ++} ++ ++static irqreturn_t npcm_peci_irq_handler(int irq, void *arg) ++{ ++ struct npcm_peci *priv = arg; ++ u32 status_ack = 0; ++ u32 status; ++ ++ spin_lock(&priv->lock); ++ regmap_read(priv->regmap, NPCM_PECI_CTL_STS, &status); ++ priv->status |= (status & NPCM_PECI_INT_MASK); ++ ++ if (status & NPCM_PECI_CTRL_CRC_ERR) { ++ dev_dbg(priv->dev, "PECI_INT_W_FCS_BAD\n"); ++ status_ack |= NPCM_PECI_CTRL_CRC_ERR; ++ } ++ ++ if (status & NPCM_PECI_CTRL_ABRT_ERR) { ++ dev_dbg(priv->dev, "NPCM_PECI_CTRL_ABRT_ERR\n"); ++ status_ack |= NPCM_PECI_CTRL_ABRT_ERR; ++ } ++ ++ /* ++ * All commands should be ended up with a NPCM_PECI_CTRL_DONE ++ * bit set even in an error case. ++ */ ++ if (status & NPCM_PECI_CTRL_DONE) { ++ dev_dbg(priv->dev, "NPCM_PECI_CTRL_DONE\n"); ++ status_ack |= NPCM_PECI_CTRL_DONE; ++ complete(&priv->xfer_complete); ++ } ++ ++ regmap_write_bits(priv->regmap, NPCM_PECI_CTL_STS, ++ NPCM_PECI_INT_MASK, status_ack); ++ ++ spin_unlock(&priv->lock); ++ return IRQ_HANDLED; ++} ++ ++static int npcm_peci_init_ctrl(struct npcm_peci *priv) ++{ ++ u32 cmd_sts, host_neg_bit_rate = 0, pull_down = 0; ++ int ret; ++ bool volt; ++ ++ priv->clk = devm_clk_get(priv->dev, NULL); ++ if (IS_ERR(priv->clk)) { ++ dev_err(priv->dev, "Failed to get clk source.\n"); ++ return PTR_ERR(priv->clk); ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ dev_err(priv->dev, "Failed to enable clock.\n"); ++ return ret; ++ } ++ ++ ret = of_property_read_u32(priv->dev->of_node, "cmd-timeout-ms", ++ &priv->cmd_timeout_ms); ++ if (ret || priv->cmd_timeout_ms > NPCM_PECI_CMD_TIMEOUT_MS_MAX || ++ priv->cmd_timeout_ms == 0) { ++ if (ret) ++ dev_warn(priv->dev, ++ "cmd-timeout-ms not found, use default : %u\n", ++ NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT); ++ else ++ dev_warn(priv->dev, ++ "Invalid cmd-timeout-ms : %u. Use default : %u\n", ++ priv->cmd_timeout_ms, ++ NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT); ++ ++ priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT; ++ } ++ ++ if (of_device_is_compatible(priv->dev->of_node, ++ "nuvoton,npcm750-peci")) { ++ priv->gcr_regmap = syscon_regmap_lookup_by_compatible ++ ("nuvoton,npcm750-gcr"); ++ if (!IS_ERR(priv->gcr_regmap)) { ++ volt = of_property_read_bool(priv->dev->of_node, ++ "high-volt-range"); ++ if (volt) ++ regmap_update_bits(priv->gcr_regmap, ++ NPCM7XX_INTCR3_OFFSET, ++ NPCM7XX_INTCR3_PECIVSEL, ++ NPCM7XX_INTCR3_PECIVSEL); ++ else ++ regmap_update_bits(priv->gcr_regmap, ++ NPCM7XX_INTCR3_OFFSET, ++ NPCM7XX_INTCR3_PECIVSEL, 0); ++ } ++ } ++ ++ ret = of_property_read_u32(priv->dev->of_node, "pull-down", ++ &pull_down); ++ if (ret || pull_down > NPCM_PECI_PULL_DOWN_MAX) { ++ if (ret) ++ dev_warn(priv->dev, ++ "pull-down not found, use default : %u\n", ++ NPCM_PECI_PULL_DOWN_DEFAULT); ++ else ++ dev_warn(priv->dev, ++ "Invalid pull-down : %u. Use default : %u\n", ++ pull_down, ++ NPCM_PECI_PULL_DOWN_DEFAULT); ++ pull_down = NPCM_PECI_PULL_DOWN_DEFAULT; ++ } ++ ++ regmap_update_bits(priv->regmap, NPCM_PECI_CTL2, NPCM_PECI_CTL2_MASK, ++ pull_down << 6); ++ ++ ret = of_property_read_u32(priv->dev->of_node, "host-neg-bit-rate", ++ &host_neg_bit_rate); ++ if (ret || host_neg_bit_rate > NPCM_PECI_HOST_NEG_BIT_RATE_MAX || ++ host_neg_bit_rate < NPCM_PECI_HOST_NEG_BIT_RATE_MIN) { ++ if (ret) ++ dev_warn(priv->dev, ++ "host-neg-bit-rate not found, use default : %u\n", ++ NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT); ++ else ++ dev_warn(priv->dev, ++ "Invalid host-neg-bit-rate : %u. Use default : %u\n", ++ host_neg_bit_rate, ++ NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT); ++ host_neg_bit_rate = NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT; ++ } ++ ++ regmap_update_bits(priv->regmap, NPCM_PECI_PDDR, NPCM_PECI_PDDR_MASK, ++ host_neg_bit_rate); ++ ++ priv->host_bit_rate = clk_get_rate(priv->clk) / ++ (4 * (host_neg_bit_rate + 1)); ++ ++ ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, ++ !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), ++ NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, ++ NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); ++ if (ret) ++ return ret; /* -ETIMEDOUT */ ++ ++ /* PECI interrupt enable */ ++ regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, ++ NPCM_PECI_CTRL_DONE_INT_EN, ++ NPCM_PECI_CTRL_DONE_INT_EN); ++ ++ return 0; ++} ++ ++static const struct regmap_config npcm_peci_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = NPCM_PECI_MAX_REG, ++ .fast_io = true, ++}; ++ ++static int npcm_peci_xfer(struct peci_adapter *adapter, ++ struct peci_xfer_msg *msg) ++{ ++ struct npcm_peci *priv = peci_get_adapdata(adapter); ++ ++ return npcm_peci_xfer_native(priv, msg); ++} ++ ++static int npcm_peci_probe(struct platform_device *pdev) ++{ ++ struct peci_adapter *adapter; ++ struct npcm_peci *priv; ++ struct resource *res; ++ void __iomem *base; ++ int ret; ++ ++ adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv)); ++ if (!adapter) ++ return -ENOMEM; ++ ++ priv = peci_get_adapdata(adapter); ++ priv->adapter = adapter; ++ priv->dev = &pdev->dev; ++ dev_set_drvdata(&pdev->dev, priv); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) { ++ ret = PTR_ERR(base); ++ goto err_put_adapter_dev; ++ } ++ ++ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, ++ &npcm_peci_regmap_config); ++ if (IS_ERR(priv->regmap)) { ++ ret = PTR_ERR(priv->regmap); ++ goto err_put_adapter_dev; ++ } ++ ++ priv->irq = platform_get_irq(pdev, 0); ++ if (!priv->irq) { ++ ret = -ENODEV; ++ goto err_put_adapter_dev; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, priv->irq, npcm_peci_irq_handler, ++ 0, "peci-npcm-irq", priv); ++ if (ret) ++ goto err_put_adapter_dev; ++ ++ init_completion(&priv->xfer_complete); ++ spin_lock_init(&priv->lock); ++ ++ priv->adapter->owner = THIS_MODULE; ++ priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev)); ++ strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name)); ++ priv->adapter->xfer = npcm_peci_xfer; ++ ++ ret = npcm_peci_init_ctrl(priv); ++ if (ret) ++ goto err_put_adapter_dev; ++ ++ ret = peci_add_adapter(priv->adapter); ++ if (ret) ++ goto err_put_adapter_dev; ++ ++ dev_info(&pdev->dev, "peci bus %d registered, host negotiation bit rate %dHz", ++ priv->adapter->nr, priv->host_bit_rate); ++ ++ return 0; ++ ++err_put_adapter_dev: ++ put_device(&adapter->dev); ++ return ret; ++} ++ ++static int npcm_peci_remove(struct platform_device *pdev) ++{ ++ struct npcm_peci *priv = dev_get_drvdata(&pdev->dev); ++ ++ clk_disable_unprepare(priv->clk); ++ peci_del_adapter(priv->adapter); ++ of_node_put(priv->adapter->dev.of_node); ++ ++ return 0; ++} ++ ++static const struct of_device_id npcm_peci_of_table[] = { ++ { .compatible = "nuvoton,npcm750-peci", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, npcm_peci_of_table); ++ ++static struct platform_driver npcm_peci_driver = { ++ .probe = npcm_peci_probe, ++ .remove = npcm_peci_remove, ++ .driver = { ++ .name = "peci-npcm", ++ .of_match_table = of_match_ptr(npcm_peci_of_table), ++ }, ++}; ++module_platform_driver(npcm_peci_driver); ++ ++MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); ++MODULE_DESCRIPTION("NPCM Platform Environment Control Interface (PECI) driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/drivers/peci/peci-aspeed.c b/drivers/peci/peci-aspeed.c deleted file mode 100644 index 51cb2563ceb6..000000000000 @@ -1940,7 +2398,7 @@ index 51cb2563ceb6..000000000000 -MODULE_DESCRIPTION("ASPEED PECI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c -index 6f241469ec7e..e2ef013e5002 100644 +index 6f241469ec7e..d1f0df8b139a 100644 --- a/drivers/peci/peci-core.c +++ b/drivers/peci/peci-core.c @@ -1,38 +1,31 @@ @@ -2040,7 +2498,8 @@ index 6f241469ec7e..e2ef013e5002 100644 + * This function must only be called from process context! + */ +struct peci_xfer_msg *peci_get_xfer_msg(u8 tx_len, u8 rx_len) -+{ + { +- return crc8(peci_crc8_table, data, (size_t)len, 0); + struct peci_xfer_msg *msg; + u8 *tx_buf, *rx_buf; + @@ -2097,8 +2556,7 @@ index 6f241469ec7e..e2ef013e5002 100644 + +/* Calculate an Assured Write Frame Check Sequence byte */ +static int peci_aw_fcs(struct peci_xfer_msg *msg, int len, u8 *aw_fcs) - { -- return crc8(peci_crc8_table, data, (size_t)len, 0); ++{ + u8 *tmp_buf; + + /* Allocate a temporary buffer to use a contiguous byte array */ @@ -2127,8 +2585,7 @@ index 6f241469ec7e..e2ef013e5002 100644 + ulong timeout = jiffies; + u8 aw_fcs; + int ret; - -- /** ++ + /* + * In case if adapter uses DMA, check at here whether tx and rx buffers + * are DMA capable or not. @@ -2144,12 +2601,13 @@ index 6f241469ec7e..e2ef013e5002 100644 + return -EAGAIN; + } + } -+ + +- /** + /* * For some commands, the PECI originator may need to retry a command if * the processor PECI client responds with a 0x8x completion code. In * each instance, the processor PECI client may have started the -@@ -125,55 +223,56 @@ static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg, +@@ -125,55 +223,51 @@ static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg, */ if (do_retry) @@ -2162,11 +2620,10 @@ index 6f241469ec7e..e2ef013e5002 100644 + ret = adapter->xfer(adapter, msg); - if (!do_retry || rc) -+ if (!do_retry || ret) - break; - +- break; +- - if (msg->rx_buf[0] == DEV_PECI_CC_SUCCESS) -+ if (msg->rx_buf[0] == PECI_DEV_CC_SUCCESS) ++ if (!do_retry || ret || !msg->rx_buf) break; /* Retry is needed when completion code is 0x8x */ @@ -2174,10 +2631,9 @@ index 6f241469ec7e..e2ef013e5002 100644 - DEV_PECI_CC_NEED_RETRY) { - rc = -EIO; + if ((msg->rx_buf[0] & PECI_DEV_CC_RETRY_CHECK_MASK) != -+ PECI_DEV_CC_NEED_RETRY) { -+ ret = -EIO; ++ PECI_DEV_CC_NEED_RETRY) break; - } +- } /* Set the retry bit to indicate a retry attempt */ - msg->tx_buf[1] |= DEV_PECI_RETRY_BIT; @@ -2192,11 +2648,11 @@ index 6f241469ec7e..e2ef013e5002 100644 + ret = peci_aw_fcs(msg, 2 + msg->tx_len, &aw_fcs); + if (ret) + break; - -- /** ++ + msg->tx_buf[msg->tx_len - 1] = 0x80 ^ aw_fcs; + } -+ + +- /** + /* * Retry for at least 250ms before returning an error. * Retry interval guideline: @@ -2230,7 +2686,7 @@ index 6f241469ec7e..e2ef013e5002 100644 } static int peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg) -@@ -190,34 +289,37 @@ static int peci_xfer_with_retries(struct peci_adapter *adapter, +@@ -190,34 +284,37 @@ static int peci_xfer_with_retries(struct peci_adapter *adapter, static int peci_scan_cmd_mask(struct peci_adapter *adapter) { @@ -2274,13 +2730,14 @@ index 6f241469ec7e..e2ef013e5002 100644 + goto out; } - /** +- /** - * Setting up the supporting commands based on minor revision number. ++ /* + * Setting up the supporting commands based on revision number. * See PECI Spec Table 3-1. */ revision = FIELD_GET(REVISION_NUM_MASK, dib); -@@ -243,10 +345,14 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter) +@@ -243,10 +340,14 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter) adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB); adapter->cmd_mask |= BIT(PECI_CMD_PING); @@ -2297,7 +2754,7 @@ index 6f241469ec7e..e2ef013e5002 100644 { if (!(adapter->cmd_mask & BIT(PECI_CMD_PING)) && peci_scan_cmd_mask(adapter) < 0) { -@@ -262,70 +368,87 @@ static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd) +@@ -262,70 +363,87 @@ static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd) return 0; } @@ -2316,19 +2773,19 @@ index 6f241469ec7e..e2ef013e5002 100644 - struct peci_xfer_msg msg; + struct peci_xfer_msg *msg; + int ret; ++ ++ msg = peci_get_xfer_msg(0, 0); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = umsg->addr; - msg.addr = umsg->addr; - msg.tx_len = 0; - msg.rx_len = 0; -+ msg = peci_get_xfer_msg(0, 0); -+ if (!msg) -+ return -ENOMEM; ++ ret = peci_xfer(adapter, msg); - return peci_xfer(adapter, &msg); -+ msg->addr = umsg->addr; -+ -+ ret = peci_xfer(adapter, msg); -+ + peci_put_xfer_msg(msg); + + return ret; @@ -2419,7 +2876,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Per the PECI spec, the read length must be a byte, word, or dword */ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) { -@@ -334,29 +457,34 @@ static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg) +@@ -334,29 +452,35 @@ static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg) return -EINVAL; } @@ -2445,17 +2902,18 @@ index 6f241469ec7e..e2ef013e5002 100644 + msg->tx_buf[2] = umsg->index; /* RdPkgConfig index */ + msg->tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */ + msg->tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */ -+ -+ ret = peci_xfer_with_retries(adapter, msg, false); -+ if (!ret) -+ memcpy(umsg->pkg_config, &msg->rx_buf[1], umsg->rx_len); - rc = peci_xfer_with_retries(adapter, &msg, false); - if (!rc) - memcpy(umsg->pkg_config, &msg.rx_buf[1], umsg->rx_len); -+ peci_put_xfer_msg(msg); ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->pkg_config, &msg->rx_buf[1], umsg->rx_len); - return rc; ++ umsg->cc = msg->rx_buf[0]; ++ peci_put_xfer_msg(msg); ++ + return ret; } @@ -2471,7 +2929,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Per the PECI spec, the write length must be a dword */ if (umsg->tx_len != 4) { -@@ -365,86 +493,113 @@ static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg) +@@ -365,86 +489,116 @@ static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg) return -EINVAL; } @@ -2504,19 +2962,20 @@ index 6f241469ec7e..e2ef013e5002 100644 + ret = peci_aw_fcs(msg, 8 + umsg->tx_len, &aw_fcs); + if (ret) + goto out; -+ -+ msg->tx_buf[5 + i] = 0x80 ^ aw_fcs; - /* Add an Assure Write Frame Check Sequence byte */ - msg.tx_buf[5 + i] = 0x80 ^ - peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len); -+ ret = peci_xfer_with_retries(adapter, msg, true); ++ msg->tx_buf[5 + i] = 0x80 ^ aw_fcs; - rc = peci_xfer_with_retries(adapter, &msg, true); -+out: -+ peci_put_xfer_msg(msg); ++ ret = peci_xfer_with_retries(adapter, msg, true); - return rc; ++out: ++ umsg->cc = msg->rx_buf[0]; ++ peci_put_xfer_msg(msg); ++ + return ret; } @@ -2559,17 +3018,18 @@ index 6f241469ec7e..e2ef013e5002 100644 + if (!ret) + memcpy(&umsg->value, &msg->rx_buf[1], sizeof(uint64_t)); + ++ umsg->cc = msg->rx_buf[0]; + peci_put_xfer_msg(msg); + + return ret; -+} -+ -+static int peci_cmd_wr_ia_msr(struct peci_adapter *adapter, void *vmsg) -+{ -+ return -ENOSYS; /* Not implemented yet */ } -static int peci_ioctl_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_wr_ia_msr(struct peci_adapter *adapter, void *vmsg) ++{ ++ return -ENOSYS; /* Not implemented yet */ ++} ++ +static int peci_cmd_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg) { struct peci_rd_pci_cfg_msg *umsg = vmsg; @@ -2614,6 +3074,7 @@ index 6f241469ec7e..e2ef013e5002 100644 - rc = peci_xfer_with_retries(adapter, &msg, false); - if (!rc) - memcpy(umsg->pci_config, &msg.rx_buf[1], 4); ++ umsg->cc = msg->rx_buf[0]; + peci_put_xfer_msg(msg); - return rc; @@ -2637,7 +3098,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Per the PECI spec, the read length must be a byte, word, or dword */ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) { -@@ -453,34 +608,41 @@ static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) +@@ -453,34 +607,42 @@ static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) return -EINVAL; } @@ -2676,6 +3137,7 @@ index 6f241469ec7e..e2ef013e5002 100644 - rc = peci_xfer_with_retries(adapter, &msg, false); - if (!rc) - memcpy(umsg->pci_config, &msg.rx_buf[1], umsg->rx_len); ++ umsg->cc = msg->rx_buf[0]; + peci_put_xfer_msg(msg); - return rc; @@ -2695,7 +3157,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Per the PECI spec, the write length must be a byte, word, or dword */ if (umsg->tx_len != 1 && umsg->tx_len != 2 && umsg->tx_len != 4) { -@@ -489,47 +651,56 @@ static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) +@@ -489,47 +651,57 @@ static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) return -EINVAL; } @@ -2743,6 +3205,7 @@ index 6f241469ec7e..e2ef013e5002 100644 - rc = peci_xfer_with_retries(adapter, &msg, true); +out: ++ umsg->cc = msg->rx_buf[0]; + peci_put_xfer_msg(msg); - return rc; @@ -2782,7 +3245,7 @@ index 6f241469ec7e..e2ef013e5002 100644 }; /** -@@ -545,109 +716,28 @@ static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { +@@ -545,109 +717,28 @@ static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { */ int peci_command(struct peci_adapter *adapter, enum peci_cmd cmd, void *vmsg) { @@ -2901,7 +3364,7 @@ index 6f241469ec7e..e2ef013e5002 100644 static int peci_detect(struct peci_adapter *adapter, u8 addr) { struct peci_ping_msg msg; -@@ -666,9 +756,9 @@ peci_of_match_device(const struct of_device_id *matches, +@@ -666,9 +757,9 @@ peci_of_match_device(const struct of_device_id *matches, return NULL; return of_match_device(matches, &client->dev); @@ -2913,7 +3376,7 @@ index 6f241469ec7e..e2ef013e5002 100644 } static const struct peci_device_id * -@@ -737,6 +827,7 @@ static int peci_device_probe(struct device *dev) +@@ -737,6 +828,7 @@ static int peci_device_probe(struct device *dev) err_detach_pm_domain: dev_pm_domain_detach(&client->dev, true); @@ -2921,7 +3384,7 @@ index 6f241469ec7e..e2ef013e5002 100644 return status; } -@@ -775,13 +866,14 @@ static void peci_device_shutdown(struct device *dev) +@@ -775,13 +867,14 @@ static void peci_device_shutdown(struct device *dev) driver->shutdown(client); } @@ -2937,7 +3400,7 @@ index 6f241469ec7e..e2ef013e5002 100644 static int peci_check_addr_validity(u8 addr) { -@@ -814,18 +906,18 @@ static int peci_check_client_busy(struct device *dev, void *client_new_p) +@@ -814,18 +907,23 @@ static int peci_check_client_busy(struct device *dev, void *client_new_p) int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id) { struct peci_rd_pkg_cfg_msg msg; @@ -2953,16 +3416,22 @@ index 6f241469ec7e..e2ef013e5002 100644 - rc = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg); - if (!rc) +- *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config); + ret = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg); -+ if (!ret) - *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config); ++ if (ret) ++ return ret; ++ ++ if (msg.cc != PECI_DEV_CC_SUCCESS) ++ return -EAGAIN; ++ ++ *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config); - return rc; -+ return ret; ++ return 0; } EXPORT_SYMBOL_GPL(peci_get_cpu_id); -@@ -833,7 +925,7 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter, +@@ -833,7 +931,7 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter, struct peci_board_info const *info) { struct peci_client *client; @@ -2971,7 +3440,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Increase reference count for the adapter assigned */ if (!peci_get_adapter(adapter->nr)) -@@ -847,46 +939,49 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter, +@@ -847,46 +945,49 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter, client->addr = info->addr; strlcpy(client->name, info->type, sizeof(client->name)); @@ -3033,7 +3502,7 @@ index 6f241469ec7e..e2ef013e5002 100644 return NULL; } -@@ -895,8 +990,10 @@ static void peci_unregister_device(struct peci_client *client) +@@ -895,8 +996,10 @@ static void peci_unregister_device(struct peci_client *client) if (!client) return; @@ -3045,7 +3514,7 @@ index 6f241469ec7e..e2ef013e5002 100644 device_unregister(&client->dev); } -@@ -916,7 +1013,7 @@ static void peci_adapter_dev_release(struct device *dev) +@@ -916,7 +1019,7 @@ static void peci_adapter_dev_release(struct device *dev) dev_dbg(dev, "%s: %s\n", __func__, adapter->name); mutex_destroy(&adapter->userspace_clients_lock); @@ -3054,7 +3523,7 @@ index 6f241469ec7e..e2ef013e5002 100644 kfree(adapter); } -@@ -928,7 +1025,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev, +@@ -928,7 +1031,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev, struct peci_board_info info = {}; struct peci_client *client; char *blank, end; @@ -3064,7 +3533,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Parse device type */ blank = strchr(buf, ' '); -@@ -943,16 +1041,17 @@ static ssize_t peci_sysfs_new_device(struct device *dev, +@@ -943,16 +1047,17 @@ static ssize_t peci_sysfs_new_device(struct device *dev, memcpy(info.type, buf, blank - buf); /* Parse remaining parameters, reject extra parameters */ @@ -3085,7 +3554,7 @@ index 6f241469ec7e..e2ef013e5002 100644 client = peci_new_device(adapter, &info); if (!client) return -EINVAL; -@@ -961,8 +1060,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev, +@@ -961,8 +1066,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev, mutex_lock(&adapter->userspace_clients_lock); list_add_tail(&client->detected, &adapter->userspace_clients); mutex_unlock(&adapter->userspace_clients_lock); @@ -3096,7 +3565,7 @@ index 6f241469ec7e..e2ef013e5002 100644 return count; } -@@ -975,9 +1074,9 @@ static ssize_t peci_sysfs_delete_device(struct device *dev, +@@ -975,9 +1080,9 @@ static ssize_t peci_sysfs_delete_device(struct device *dev, struct peci_adapter *adapter = to_peci_adapter(dev); struct peci_client *client, *next; struct peci_board_info info = {}; @@ -3108,7 +3577,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Parse device type */ blank = strchr(buf, ' '); -@@ -992,41 +1091,41 @@ static ssize_t peci_sysfs_delete_device(struct device *dev, +@@ -992,41 +1097,41 @@ static ssize_t peci_sysfs_delete_device(struct device *dev, memcpy(info.type, buf, blank - buf); /* Parse remaining parameters, reject extra parameters */ @@ -3162,7 +3631,7 @@ index 6f241469ec7e..e2ef013e5002 100644 } static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, 0200, NULL, peci_sysfs_delete_device); -@@ -1039,10 +1138,11 @@ static struct attribute *peci_adapter_attrs[] = { +@@ -1039,10 +1144,11 @@ static struct attribute *peci_adapter_attrs[] = { }; ATTRIBUTE_GROUPS(peci_adapter); @@ -3175,7 +3644,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /** * peci_verify_adapter - return parameter as peci_adapter, or NULL -@@ -1063,32 +1163,26 @@ static struct peci_client *peci_of_register_device(struct peci_adapter *adapter, +@@ -1063,32 +1169,26 @@ static struct peci_client *peci_of_register_device(struct peci_adapter *adapter, struct device_node *node) { struct peci_board_info info = {}; @@ -3220,7 +3689,7 @@ index 6f241469ec7e..e2ef013e5002 100644 } static void peci_of_register_devices(struct peci_adapter *adapter) -@@ -1119,7 +1213,7 @@ static void peci_of_register_devices(struct peci_adapter *adapter) +@@ -1119,7 +1219,7 @@ static void peci_of_register_devices(struct peci_adapter *adapter) of_node_put(bus); } @@ -3229,7 +3698,7 @@ index 6f241469ec7e..e2ef013e5002 100644 static void peci_of_register_devices(struct peci_adapter *adapter) { } #endif /* CONFIG_OF */ -@@ -1163,9 +1257,7 @@ static struct peci_adapter *peci_of_find_adapter(struct device_node *node) +@@ -1163,9 +1263,7 @@ static struct peci_adapter *peci_of_find_adapter(struct device_node *node) return adapter; } @@ -3240,7 +3709,7 @@ index 6f241469ec7e..e2ef013e5002 100644 { struct of_reconfig_data *rd = arg; struct peci_adapter *adapter; -@@ -1216,7 +1308,7 @@ static int peci_of_notify(struct notifier_block *nb, +@@ -1216,7 +1314,7 @@ static int peci_of_notify(struct notifier_block *nb, static struct notifier_block peci_of_notifier = { .notifier_call = peci_of_notify, }; @@ -3249,7 +3718,7 @@ index 6f241469ec7e..e2ef013e5002 100644 extern struct notifier_block peci_of_notifier; #endif /* CONFIG_OF_DYNAMIC */ -@@ -1240,7 +1332,7 @@ extern struct notifier_block peci_of_notifier; +@@ -1240,7 +1338,7 @@ extern struct notifier_block peci_of_notifier; * * Return: the peci_adapter structure on success, else NULL. */ @@ -3258,7 +3727,7 @@ index 6f241469ec7e..e2ef013e5002 100644 { struct peci_adapter *adapter; -@@ -1263,7 +1355,7 @@ EXPORT_SYMBOL_GPL(peci_alloc_adapter); +@@ -1263,7 +1361,7 @@ EXPORT_SYMBOL_GPL(peci_alloc_adapter); static int peci_register_adapter(struct peci_adapter *adapter) { @@ -3267,7 +3736,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Can't register until after driver model init */ if (WARN_ON(!is_registered)) -@@ -1275,27 +1367,17 @@ static int peci_register_adapter(struct peci_adapter *adapter) +@@ -1275,27 +1373,17 @@ static int peci_register_adapter(struct peci_adapter *adapter) if (WARN(!adapter->xfer, "peci adapter has no xfer function\n")) goto err_free_idr; @@ -3300,7 +3769,7 @@ index 6f241469ec7e..e2ef013e5002 100644 } dev_dbg(&adapter->dev, "adapter [%s] registered\n", adapter->name); -@@ -1309,13 +1391,11 @@ static int peci_register_adapter(struct peci_adapter *adapter) +@@ -1309,13 +1397,11 @@ static int peci_register_adapter(struct peci_adapter *adapter) return 0; @@ -3315,7 +3784,7 @@ index 6f241469ec7e..e2ef013e5002 100644 } static int peci_add_numbered_adapter(struct peci_adapter *adapter) -@@ -1411,7 +1491,7 @@ void peci_del_adapter(struct peci_adapter *adapter) +@@ -1411,7 +1497,7 @@ void peci_del_adapter(struct peci_adapter *adapter) } mutex_unlock(&adapter->userspace_clients_lock); @@ -3324,7 +3793,7 @@ index 6f241469ec7e..e2ef013e5002 100644 * Detach any active clients. This can't fail, thus we do not * check the returned value. */ -@@ -1420,13 +1500,8 @@ void peci_del_adapter(struct peci_adapter *adapter) +@@ -1420,13 +1506,8 @@ void peci_del_adapter(struct peci_adapter *adapter) /* device name is gone after device_unregister */ dev_dbg(&adapter->dev, "adapter [%s] unregistered\n", adapter->name); @@ -3338,7 +3807,7 @@ index 6f241469ec7e..e2ef013e5002 100644 device_unregister(&adapter->dev); /* free bus id */ -@@ -1436,6 +1511,18 @@ void peci_del_adapter(struct peci_adapter *adapter) +@@ -1436,6 +1517,18 @@ void peci_del_adapter(struct peci_adapter *adapter) } EXPORT_SYMBOL_GPL(peci_del_adapter); @@ -3357,7 +3826,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /** * peci_register_driver - register a PECI driver * @owner: owner module of the driver being registered -@@ -1446,7 +1533,7 @@ EXPORT_SYMBOL_GPL(peci_del_adapter); +@@ -1446,7 +1539,7 @@ EXPORT_SYMBOL_GPL(peci_del_adapter); */ int peci_register_driver(struct module *owner, struct peci_driver *driver) { @@ -3366,7 +3835,7 @@ index 6f241469ec7e..e2ef013e5002 100644 /* Can't register until after driver model init */ if (WARN_ON(!is_registered)) -@@ -1456,13 +1543,13 @@ int peci_register_driver(struct module *owner, struct peci_driver *driver) +@@ -1456,13 +1549,13 @@ int peci_register_driver(struct module *owner, struct peci_driver *driver) driver->driver.owner = owner; driver->driver.bus = &peci_bus_type; @@ -3384,7 +3853,7 @@ index 6f241469ec7e..e2ef013e5002 100644 pr_debug("driver [%s] registered\n", driver->driver.name); -@@ -1492,13 +1579,6 @@ static int __init peci_init(void) +@@ -1492,13 +1585,6 @@ static int __init peci_init(void) return ret; } @@ -3398,7 +3867,7 @@ index 6f241469ec7e..e2ef013e5002 100644 crc8_populate_msb(peci_crc8_table, PECI_CRC8_POLYNOMIAL); if (IS_ENABLED(CONFIG_OF_DYNAMIC)) -@@ -1514,11 +1594,10 @@ static void __exit peci_exit(void) +@@ -1514,11 +1600,10 @@ static void __exit peci_exit(void) if (IS_ENABLED(CONFIG_OF_DYNAMIC)) WARN_ON(of_reconfig_notifier_unregister(&peci_of_notifier)); @@ -3413,10 +3882,10 @@ index 6f241469ec7e..e2ef013e5002 100644 MODULE_AUTHOR("Jason M Biils <jason.m.bills@linux.intel.com>"); diff --git a/drivers/peci/peci-dev.c b/drivers/peci/peci-dev.c new file mode 100644 -index 000000000000..5de0683206bc +index 000000000000..ac9cba0fb429 --- /dev/null +++ b/drivers/peci/peci-dev.c -@@ -0,0 +1,340 @@ +@@ -0,0 +1,346 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018-2019 Intel Corporation + @@ -3517,9 +3986,9 @@ index 000000000000..5de0683206bc +static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg) +{ + struct peci_dev *peci_dev = file->private_data; -+ struct peci_xfer_msg __user *uxmsg; ++ void __user *umsg = (void __user *)arg; + struct peci_xfer_msg *xmsg = NULL; -+ void __user *umsg; ++ struct peci_xfer_msg uxmsg; + enum peci_cmd cmd; + u8 *msg = NULL; + uint msg_len; @@ -3535,30 +4004,35 @@ index 000000000000..5de0683206bc + break; + } + -+ uxmsg = (struct peci_xfer_msg __user *)arg; -+ xmsg = peci_get_xfer_msg(uxmsg->tx_len, uxmsg->rx_len); ++ if (copy_from_user(&uxmsg, umsg, msg_len)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ xmsg = peci_get_xfer_msg(uxmsg.tx_len, uxmsg.rx_len); + if (IS_ERR(xmsg)) { + ret = PTR_ERR(xmsg); + break; + } + -+ if (uxmsg->tx_len && -+ copy_from_user(uxmsg->tx_buf, xmsg->tx_buf, -+ uxmsg->tx_len)) { ++ if (uxmsg.tx_len && ++ copy_from_user(xmsg->tx_buf, uxmsg.tx_buf, uxmsg.tx_len)) { + ret = -EFAULT; + break; + } + ++ xmsg->addr = uxmsg.addr; ++ xmsg->tx_len = uxmsg.tx_len; ++ xmsg->rx_len = uxmsg.rx_len; ++ + ret = peci_command(peci_dev->adapter, cmd, xmsg); -+ if (!ret && uxmsg->rx_len && -+ copy_to_user(xmsg->rx_buf, uxmsg->rx_buf, -+ uxmsg->rx_len)) ++ if (!ret && xmsg->rx_len && ++ copy_to_user(uxmsg.rx_buf, xmsg->rx_buf, xmsg->rx_len)) + ret = -EFAULT; + + break; + + default: -+ umsg = (void __user *)arg; + msg = memdup_user(umsg, msg_len); + if (IS_ERR(msg)) { + ret = PTR_ERR(msg); @@ -3566,7 +4040,8 @@ index 000000000000..5de0683206bc + } + + ret = peci_command(peci_dev->adapter, cmd, msg); -+ if (!ret && copy_to_user(umsg, msg, msg_len)) ++ if ((!ret || ret == -ETIMEDOUT) && ++ copy_to_user(umsg, msg, msg_len)) + ret = -EFAULT; + + break; @@ -3757,8 +4232,424 @@ index 000000000000..5de0683206bc +MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>"); +MODULE_DESCRIPTION("PECI /dev entries driver"); +MODULE_LICENSE("GPL v2"); +diff --git a/drivers/peci/peci-npcm.c b/drivers/peci/peci-npcm.c +deleted file mode 100644 +index f632365b1416..000000000000 +--- a/drivers/peci/peci-npcm.c ++++ /dev/null +@@ -1,410 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-// Copyright (c) 2019 Nuvoton Technology corporation. +- +-#include <linux/bitfield.h> +-#include <linux/clk.h> +-#include <linux/interrupt.h> +-#include <linux/jiffies.h> +-#include <linux/module.h> +-#include <linux/of.h> +-#include <linux/peci.h> +-#include <linux/platform_device.h> +-#include <linux/regmap.h> +-#include <linux/mfd/syscon.h> +-#include <linux/reset.h> +- +-/* NPCM7xx GCR module */ +-#define NPCM7XX_INTCR3_OFFSET 0x9C +-#define NPCM7XX_INTCR3_PECIVSEL BIT(19) +- +-/* NPCM PECI Registers */ +-#define NPCM_PECI_CTL_STS 0x00 +-#define NPCM_PECI_RD_LENGTH 0x04 +-#define NPCM_PECI_ADDR 0x08 +-#define NPCM_PECI_CMD 0x0C +-#define NPCM_PECI_CTL2 0x10 +-#define NPCM_PECI_WR_LENGTH 0x1C +-#define NPCM_PECI_PDDR 0x2C +-#define NPCM_PECI_DAT_INOUT(n) (0x100 + ((n) * 4)) +- +-#define NPCM_PECI_MAX_REG 0x200 +- +-/* NPCM_PECI_CTL_STS - 0x00 : Control Register */ +-#define NPCM_PECI_CTRL_DONE_INT_EN BIT(6) +-#define NPCM_PECI_CTRL_ABRT_ERR BIT(4) +-#define NPCM_PECI_CTRL_CRC_ERR BIT(3) +-#define NPCM_PECI_CTRL_DONE BIT(1) +-#define NPCM_PECI_CTRL_START_BUSY BIT(0) +- +-/* NPCM_PECI_RD_LENGTH - 0x04 : Command Register */ +-#define NPCM_PECI_RD_LEN_MASK GENMASK(6, 0) +- +-/* NPCM_PECI_CMD - 0x10 : Command Register */ +-#define NPCM_PECI_CTL2_MASK GENMASK(7, 6) +- +-/* NPCM_PECI_WR_LENGTH - 0x1C : Command Register */ +-#define NPCM_PECI_WR_LEN_MASK GENMASK(6, 0) +- +-/* NPCM_PECI_PDDR - 0x2C : Command Register */ +-#define NPCM_PECI_PDDR_MASK GENMASK(4, 0) +- +-#define NPCM_PECI_INT_MASK (NPCM_PECI_CTRL_ABRT_ERR | \ +- NPCM_PECI_CTRL_CRC_ERR | \ +- NPCM_PECI_CTRL_DONE) +- +-#define NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC 50000 +-#define NPCM_PECI_IDLE_CHECK_INTERVAL_USEC 10000 +-#define NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT 1000 +-#define NPCM_PECI_CMD_TIMEOUT_MS_MAX 60000 +-#define NPCM_PECI_HOST_NEG_BIT_RATE_MAX 31 +-#define NPCM_PECI_HOST_NEG_BIT_RATE_MIN 7 +-#define NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT 15 +-#define NPCM_PECI_PULL_DOWN_DEFAULT 0 +-#define NPCM_PECI_PULL_DOWN_MAX 2 +- +-struct npcm_peci { +- u32 cmd_timeout_ms; +- u32 host_bit_rate; +- struct completion xfer_complete; +- struct regmap *gcr_regmap; +- struct peci_adapter *adapter; +- struct regmap *regmap; +- u32 status; +- spinlock_t lock; /* to sync completion status handling */ +- struct device *dev; +- struct clk *clk; +- int irq; +-}; +- +-static int npcm_peci_xfer_native(struct npcm_peci *priv, +- struct peci_xfer_msg *msg) +-{ +- long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms); +- unsigned long flags; +- unsigned int msg_rd; +- u32 cmd_sts; +- int i, rc; +- +- /* Check command sts and bus idle state */ +- rc = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, +- !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), +- NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, +- NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); +- if (rc) +- return rc; /* -ETIMEDOUT */ +- +- spin_lock_irqsave(&priv->lock, flags); +- reinit_completion(&priv->xfer_complete); +- +- regmap_write(priv->regmap, NPCM_PECI_ADDR, msg->addr); +- regmap_write(priv->regmap, NPCM_PECI_RD_LENGTH, +- NPCM_PECI_WR_LEN_MASK & msg->rx_len); +- regmap_write(priv->regmap, NPCM_PECI_WR_LENGTH, +- NPCM_PECI_WR_LEN_MASK & msg->tx_len); +- +- if (msg->tx_len) { +- regmap_write(priv->regmap, NPCM_PECI_CMD, msg->tx_buf[0]); +- +- for (i = 0; i < (msg->tx_len - 1); i++) +- regmap_write(priv->regmap, NPCM_PECI_DAT_INOUT(i), +- msg->tx_buf[i + 1]); +- } +- +- priv->status = 0; +- regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, +- NPCM_PECI_CTRL_START_BUSY, +- NPCM_PECI_CTRL_START_BUSY); +- +- spin_unlock_irqrestore(&priv->lock, flags); +- +- err = wait_for_completion_interruptible_timeout(&priv->xfer_complete, +- timeout); +- +- spin_lock_irqsave(&priv->lock, flags); +- +- regmap_write(priv->regmap, NPCM_PECI_CMD, 0); +- +- if (err <= 0 || priv->status != NPCM_PECI_CTRL_DONE) { +- if (err < 0) { /* -ERESTARTSYS */ +- rc = (int)err; +- goto err_irqrestore; +- } else if (err == 0) { +- dev_dbg(priv->dev, "Timeout waiting for a response!\n"); +- rc = -ETIMEDOUT; +- goto err_irqrestore; +- } +- +- dev_dbg(priv->dev, "No valid response!\n"); +- rc = -EIO; +- goto err_irqrestore; +- } +- +- for (i = 0; i < msg->rx_len; i++) { +- regmap_read(priv->regmap, NPCM_PECI_DAT_INOUT(i), &msg_rd); +- msg->rx_buf[i] = (u8)msg_rd; +- } +- +-err_irqrestore: +- spin_unlock_irqrestore(&priv->lock, flags); +- return rc; +-} +- +-static irqreturn_t npcm_peci_irq_handler(int irq, void *arg) +-{ +- struct npcm_peci *priv = arg; +- u32 status_ack = 0; +- u32 status; +- +- spin_lock(&priv->lock); +- regmap_read(priv->regmap, NPCM_PECI_CTL_STS, &status); +- priv->status |= (status & NPCM_PECI_INT_MASK); +- +- if (status & NPCM_PECI_CTRL_CRC_ERR) { +- dev_dbg(priv->dev, "PECI_INT_W_FCS_BAD\n"); +- status_ack |= NPCM_PECI_CTRL_CRC_ERR; +- } +- +- if (status & NPCM_PECI_CTRL_ABRT_ERR) { +- dev_dbg(priv->dev, "NPCM_PECI_CTRL_ABRT_ERR\n"); +- status_ack |= NPCM_PECI_CTRL_ABRT_ERR; +- } +- +- /* +- * All commands should be ended up with a NPCM_PECI_CTRL_DONE +- * bit set even in an error case. +- */ +- if (status & NPCM_PECI_CTRL_DONE) { +- dev_dbg(priv->dev, "NPCM_PECI_CTRL_DONE\n"); +- status_ack |= NPCM_PECI_CTRL_DONE; +- complete(&priv->xfer_complete); +- } +- +- regmap_write_bits(priv->regmap, NPCM_PECI_CTL_STS, +- NPCM_PECI_INT_MASK, status_ack); +- +- spin_unlock(&priv->lock); +- return IRQ_HANDLED; +-} +- +-static int npcm_peci_init_ctrl(struct npcm_peci *priv) +-{ +- u32 cmd_sts, host_neg_bit_rate = 0, pull_down = 0; +- int ret; +- bool volt; +- +- priv->clk = devm_clk_get(priv->dev, NULL); +- if (IS_ERR(priv->clk)) { +- dev_err(priv->dev, "Failed to get clk source.\n"); +- return PTR_ERR(priv->clk); +- } +- +- ret = clk_prepare_enable(priv->clk); +- if (ret) { +- dev_err(priv->dev, "Failed to enable clock.\n"); +- return ret; +- } +- +- ret = of_property_read_u32(priv->dev->of_node, "cmd-timeout-ms", +- &priv->cmd_timeout_ms); +- if (ret || priv->cmd_timeout_ms > NPCM_PECI_CMD_TIMEOUT_MS_MAX || +- priv->cmd_timeout_ms == 0) { +- if (ret) +- dev_warn(priv->dev, +- "cmd-timeout-ms not found, use default : %u\n", +- NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT); +- else +- dev_warn(priv->dev, +- "Invalid cmd-timeout-ms : %u. Use default : %u\n", +- priv->cmd_timeout_ms, +- NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT); +- +- priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT; +- } +- +- if (of_device_is_compatible(priv->dev->of_node, +- "nuvoton,npcm750-peci")) { +- priv->gcr_regmap = syscon_regmap_lookup_by_compatible +- ("nuvoton,npcm750-gcr"); +- if (!IS_ERR(priv->gcr_regmap)) { +- volt = of_property_read_bool(priv->dev->of_node, +- "high-volt-range"); +- if (volt) +- regmap_update_bits(priv->gcr_regmap, +- NPCM7XX_INTCR3_OFFSET, +- NPCM7XX_INTCR3_PECIVSEL, +- NPCM7XX_INTCR3_PECIVSEL); +- else +- regmap_update_bits(priv->gcr_regmap, +- NPCM7XX_INTCR3_OFFSET, +- NPCM7XX_INTCR3_PECIVSEL, 0); +- } +- } +- +- ret = of_property_read_u32(priv->dev->of_node, "pull-down", +- &pull_down); +- if (ret || pull_down > NPCM_PECI_PULL_DOWN_MAX) { +- if (ret) +- dev_warn(priv->dev, +- "pull-down not found, use default : %u\n", +- NPCM_PECI_PULL_DOWN_DEFAULT); +- else +- dev_warn(priv->dev, +- "Invalid pull-down : %u. Use default : %u\n", +- pull_down, +- NPCM_PECI_PULL_DOWN_DEFAULT); +- pull_down = NPCM_PECI_PULL_DOWN_DEFAULT; +- } +- +- regmap_update_bits(priv->regmap, NPCM_PECI_CTL2, NPCM_PECI_CTL2_MASK, +- pull_down << 6); +- +- ret = of_property_read_u32(priv->dev->of_node, "host-neg-bit-rate", +- &host_neg_bit_rate); +- if (ret || host_neg_bit_rate > NPCM_PECI_HOST_NEG_BIT_RATE_MAX || +- host_neg_bit_rate < NPCM_PECI_HOST_NEG_BIT_RATE_MIN) { +- if (ret) +- dev_warn(priv->dev, +- "host-neg-bit-rate not found, use default : %u\n", +- NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT); +- else +- dev_warn(priv->dev, +- "Invalid host-neg-bit-rate : %u. Use default : %u\n", +- host_neg_bit_rate, +- NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT); +- host_neg_bit_rate = NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT; +- } +- +- regmap_update_bits(priv->regmap, NPCM_PECI_PDDR, NPCM_PECI_PDDR_MASK, +- host_neg_bit_rate); +- +- priv->host_bit_rate = clk_get_rate(priv->clk) / +- (4 * (host_neg_bit_rate + 1)); +- +- ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, +- !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), +- NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, +- NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); +- if (ret) +- return ret; /* -ETIMEDOUT */ +- +- /* PECI interrupt enable */ +- regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, +- NPCM_PECI_CTRL_DONE_INT_EN, +- NPCM_PECI_CTRL_DONE_INT_EN); +- +- return 0; +-} +- +-static const struct regmap_config npcm_peci_regmap_config = { +- .reg_bits = 8, +- .val_bits = 8, +- .max_register = NPCM_PECI_MAX_REG, +- .fast_io = true, +-}; +- +-static int npcm_peci_xfer(struct peci_adapter *adapter, +- struct peci_xfer_msg *msg) +-{ +- struct npcm_peci *priv = peci_get_adapdata(adapter); +- +- return npcm_peci_xfer_native(priv, msg); +-} +- +-static int npcm_peci_probe(struct platform_device *pdev) +-{ +- struct peci_adapter *adapter; +- struct npcm_peci *priv; +- struct resource *res; +- void __iomem *base; +- int ret; +- +- adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv)); +- if (!adapter) +- return -ENOMEM; +- +- priv = peci_get_adapdata(adapter); +- priv->adapter = adapter; +- priv->dev = &pdev->dev; +- dev_set_drvdata(&pdev->dev, priv); +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(base)) { +- ret = PTR_ERR(base); +- goto err_put_adapter_dev; +- } +- +- priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, +- &npcm_peci_regmap_config); +- if (IS_ERR(priv->regmap)) { +- ret = PTR_ERR(priv->regmap); +- goto err_put_adapter_dev; +- } +- +- priv->irq = platform_get_irq(pdev, 0); +- if (!priv->irq) { +- ret = -ENODEV; +- goto err_put_adapter_dev; +- } +- +- ret = devm_request_irq(&pdev->dev, priv->irq, npcm_peci_irq_handler, +- 0, "peci-npcm-irq", priv); +- if (ret) +- goto err_put_adapter_dev; +- +- init_completion(&priv->xfer_complete); +- spin_lock_init(&priv->lock); +- +- priv->adapter->owner = THIS_MODULE; +- priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev)); +- strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name)); +- priv->adapter->xfer = npcm_peci_xfer; +- +- ret = npcm_peci_init_ctrl(priv); +- if (ret) +- goto err_put_adapter_dev; +- +- ret = peci_add_adapter(priv->adapter); +- if (ret) +- goto err_put_adapter_dev; +- +- dev_info(&pdev->dev, "peci bus %d registered, host negotiation bit rate %dHz", +- priv->adapter->nr, priv->host_bit_rate); +- +- return 0; +- +-err_put_adapter_dev: +- put_device(&adapter->dev); +- return ret; +-} +- +-static int npcm_peci_remove(struct platform_device *pdev) +-{ +- struct npcm_peci *priv = dev_get_drvdata(&pdev->dev); +- +- clk_disable_unprepare(priv->clk); +- peci_del_adapter(priv->adapter); +- of_node_put(priv->adapter->dev.of_node); +- +- return 0; +-} +- +-static const struct of_device_id npcm_peci_of_table[] = { +- { .compatible = "nuvoton,npcm750-peci", }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, npcm_peci_of_table); +- +-static struct platform_driver npcm_peci_driver = { +- .probe = npcm_peci_probe, +- .remove = npcm_peci_remove, +- .driver = { +- .name = "peci-npcm", +- .of_match_table = of_match_ptr(npcm_peci_of_table), +- }, +-}; +-module_platform_driver(npcm_peci_driver); +- +-MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); +-MODULE_DESCRIPTION("NPCM Platform Environment Control Interface (PECI) driver"); +-MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/intel-peci-client.h b/include/linux/mfd/intel-peci-client.h -index 8f6d823a59cd..1f1b07a9aeab 100644 +index 8f6d823a59cd..7b62a02e46ee 100644 --- a/include/linux/mfd/intel-peci-client.h +++ b/include/linux/mfd/intel-peci-client.h @@ -1,5 +1,5 @@ @@ -3768,7 +4659,7 @@ index 8f6d823a59cd..1f1b07a9aeab 100644 #ifndef __LINUX_MFD_INTEL_PECI_CLIENT_H #define __LINUX_MFD_INTEL_PECI_CLIENT_H -@@ -9,7 +9,7 @@ +@@ -9,14 +9,15 @@ #if IS_ENABLED(CONFIG_X86) #include <asm/intel-family.h> #else @@ -3777,7 +4668,29 @@ index 8f6d823a59cd..1f1b07a9aeab 100644 * Architectures other than x86 cannot include the header file so define these * at here. These are needed for detecting type of client x86 CPUs behind a PECI * connection. -@@ -58,7 +58,6 @@ struct cpu_gen_info { + */ +-#define INTEL_FAM6_HASWELL_X 0x3F +-#define INTEL_FAM6_BROADWELL_X 0x4F +-#define INTEL_FAM6_SKYLAKE_X 0x55 ++#define INTEL_FAM6_HASWELL_X 0x3F ++#define INTEL_FAM6_BROADWELL_X 0x4F ++#define INTEL_FAM6_BROADWELL_XEON_D 0x56 ++#define INTEL_FAM6_SKYLAKE_X 0x55 + #endif + + #define CORE_MAX_ON_HSX 18 /* Max number of cores on Haswell */ +@@ -27,6 +28,10 @@ + #define CHAN_RANK_MAX_ON_BDX 4 /* Max number of channel ranks on Broadwell */ + #define DIMM_IDX_MAX_ON_BDX 3 /* Max DIMM index per channel on Broadwell */ + ++#define CORE_MAX_ON_XD 16 /* Max number of cores on Xeon D */ ++#define CHAN_RANK_MAX_ON_XD 2 /* Max number of channel ranks on Xeon D */ ++#define DIMM_IDX_MAX_ON_XD 2 /* Max DIMM index per channel on Xeon D */ ++ + #define CORE_MAX_ON_SKX 28 /* Max number of cores on Skylake */ + #define CHAN_RANK_MAX_ON_SKX 6 /* Max number of channel ranks on Skylake */ + #define DIMM_IDX_MAX_ON_SKX 2 /* Max DIMM index per channel on Skylake */ +@@ -58,7 +63,6 @@ struct cpu_gen_info { /** * struct peci_client_manager - PECI client manager information * @client; pointer to the PECI client @@ -3785,7 +4698,7 @@ index 8f6d823a59cd..1f1b07a9aeab 100644 * @name: PECI client manager name * @gen_info: CPU generation info of the detected CPU * -@@ -67,7 +66,6 @@ struct cpu_gen_info { +@@ -67,7 +71,6 @@ struct cpu_gen_info { */ struct peci_client_manager { struct peci_client *client; @@ -3793,6 +4706,35 @@ index 8f6d823a59cd..1f1b07a9aeab 100644 char name[PECI_NAME_SIZE]; const struct cpu_gen_info *gen_info; }; +@@ -93,18 +96,23 @@ peci_client_read_package_config(struct peci_client_manager *priv, + u8 index, u16 param, u8 *data) + { + struct peci_rd_pkg_cfg_msg msg; +- int rc; ++ int ret; + + msg.addr = priv->client->addr; + msg.index = index; + msg.param = param; + msg.rx_len = 4; + +- rc = peci_command(priv->client->adapter, PECI_CMD_RD_PKG_CFG, &msg); +- if (!rc) +- memcpy(data, msg.pkg_config, 4); ++ ret = peci_command(priv->client->adapter, PECI_CMD_RD_PKG_CFG, &msg); ++ if (ret) ++ return ret; ++ ++ if (msg.cc != PECI_DEV_CC_SUCCESS) ++ return -EAGAIN; ++ ++ memcpy(data, msg.pkg_config, 4); + +- return rc; ++ return 0; + } + + #endif /* __LINUX_MFD_INTEL_PECI_CLIENT_H */ diff --git a/include/linux/peci.h b/include/linux/peci.h index d0e47d45d1d0..6fc424dc2a73 100644 --- a/include/linux/peci.h @@ -3890,7 +4832,7 @@ index d0e47d45d1d0..6fc424dc2a73 100644 int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id); diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h -index a6dae71cbff5..8467b2fbee1f 100644 +index a6dae71cbff5..253fb42e38b7 100644 --- a/include/uapi/linux/peci-ioctl.h +++ b/include/uapi/linux/peci-ioctl.h @@ -1,5 +1,5 @@ @@ -3900,7 +4842,7 @@ index a6dae71cbff5..8467b2fbee1f 100644 #ifndef __PECI_IOCTL_H #define __PECI_IOCTL_H -@@ -7,136 +7,34 @@ +@@ -7,136 +7,35 @@ #include <linux/ioctl.h> #include <linux/types.h> @@ -3981,13 +4923,13 @@ index a6dae71cbff5..8467b2fbee1f 100644 -#define MBX_INDEX_DIMM_AMBIENT 19 -#define MBX_INDEX_DIMM_TEMP 24 +/* The PECI client's default address of 0x30 */ -+#define PECI_BASE_ADDR 0x30 ++#define PECI_BASE_ADDR 0x30 + +/* Max number of CPU clients */ -+#define PECI_OFFSET_MAX 8 ++#define PECI_OFFSET_MAX 8 + +/* PECI read/write data buffer size max */ -+#define PECI_BUFFER_SIZE 255 ++#define PECI_BUFFER_SIZE 255 /* Device Specific Completion Code (CC) Definition */ -#define DEV_PECI_CC_SUCCESS 0x40 @@ -3995,17 +4937,22 @@ index a6dae71cbff5..8467b2fbee1f 100644 -#define DEV_PECI_CC_OUT_OF_RESOURCE 0x81 -#define DEV_PECI_CC_UNAVAIL_RESOURCE 0x82 -#define DEV_PECI_CC_INVALID_REQ 0x90 -+#define PECI_DEV_CC_SUCCESS 0x40 -+#define PECI_DEV_CC_TIMEOUT 0x80 -+#define PECI_DEV_CC_OUT_OF_RESOURCE 0x81 -+#define PECI_DEV_CC_UNAVAIL_RESOURCE 0x82 -+#define PECI_DEV_CC_INVALID_REQ 0x90 ++#define PECI_DEV_CC_SUCCESS 0x40 ++#define PECI_DEV_CC_NEED_RETRY 0x80 ++#define PECI_DEV_CC_OUT_OF_RESOURCE 0x81 ++#define PECI_DEV_CC_UNAVAIL_RESOURCE 0x82 ++#define PECI_DEV_CC_INVALID_REQ 0x90 ++#define PECI_DEV_CC_MCA_ERROR 0x91 ++#define PECI_DEV_CC_CATASTROPHIC_MCA_ERROR 0x93 ++#define PECI_DEV_CC_FATAL_MCA_DETECTED 0x94 ++#define PECI_DEV_CC_PARITY_ERROR_ON_GPSB_OR_PMSB 0x98 ++#define PECI_DEV_CC_PARITY_ERROR_ON_GPSB_OR_PMSB_IERR 0x9B ++#define PECI_DEV_CC_PARITY_ERROR_ON_GPSB_OR_PMSB_MCA 0x9C /* Completion Code mask to check retry needs */ -#define DEV_PECI_CC_RETRY_CHECK_MASK 0xf0 -#define DEV_PECI_CC_NEED_RETRY 0x80 -+#define PECI_DEV_CC_RETRY_CHECK_MASK 0xf0 -+#define PECI_DEV_CC_NEED_RETRY 0x80 ++#define PECI_DEV_CC_RETRY_CHECK_MASK 0xf0 /* Skylake EDS says to retry for 250ms */ -#define DEV_PECI_RETRY_TIME_MS 250 @@ -4037,13 +4984,9 @@ index a6dae71cbff5..8467b2fbee1f 100644 -#define RDPCICFG_WRITE_LEN 6 -#define RDPCICFG_READ_LEN 5 -#define RDPCICFG_PECI_CMD 0x61 -+#define PECI_DEV_RETRY_TIME_MS 250 -+#define PECI_DEV_RETRY_INTERVAL_USEC 10000 -+#define PECI_DEV_RETRY_BIT 0x01 - +- -#define WRPCICFG_PECI_CMD 0x65 -+#define PECI_WRIAMSR_CMD 0xb5 - +- -#define RDPCICFGLOCAL_WRITE_LEN 5 -#define RDPCICFGLOCAL_READ_LEN_BASE 1 -#define RDPCICFGLOCAL_PECI_CMD 0xe1 @@ -4053,11 +4996,13 @@ index a6dae71cbff5..8467b2fbee1f 100644 -#define WRPCICFGLOCAL_PECI_CMD 0xe5 - -#define PECI_BUFFER_SIZE 32 -+#define PECI_WRPCICFG_CMD 0x65 ++#define PECI_DEV_RETRY_TIME_MS 250 ++#define PECI_DEV_RETRY_INTERVAL_USEC 10000 ++#define PECI_DEV_RETRY_BIT 0x01 /** * enum peci_cmd - PECI client commands -@@ -186,11 +84,12 @@ enum peci_cmd { +@@ -186,11 +85,12 @@ enum peci_cmd { * raw PECI transfer */ struct peci_xfer_msg { @@ -4075,7 +5020,7 @@ index a6dae71cbff5..8467b2fbee1f 100644 } __attribute__((__packed__)); /** -@@ -202,7 +101,8 @@ struct peci_xfer_msg { +@@ -202,7 +102,8 @@ struct peci_xfer_msg { * powered-off, etc. */ struct peci_ping_msg { @@ -4085,7 +5030,7 @@ index a6dae71cbff5..8467b2fbee1f 100644 } __attribute__((__packed__)); /** -@@ -216,8 +116,13 @@ struct peci_ping_msg { +@@ -216,8 +117,13 @@ struct peci_ping_msg { * command. */ struct peci_get_dib_msg { @@ -4101,7 +5046,7 @@ index a6dae71cbff5..8467b2fbee1f 100644 } __attribute__((__packed__)); /** -@@ -232,8 +137,14 @@ struct peci_get_dib_msg { +@@ -232,8 +138,13 @@ struct peci_get_dib_msg { * below the maximum processor junction temperature. */ struct peci_get_temp_msg { @@ -4112,13 +5057,20 @@ index a6dae71cbff5..8467b2fbee1f 100644 +#define PECI_GET_TEMP_CMD 0x01 + + __u8 addr; -+ __u8 padding0[3]; ++ __u8 padding; + __s16 temp_raw; -+ __u8 padding1[2]; } __attribute__((__packed__)); /** -@@ -251,11 +162,72 @@ struct peci_get_temp_msg { +@@ -242,6 +153,7 @@ struct peci_get_temp_msg { + * @index: encoding index for the requested service + * @param: specific data being requested + * @rx_len: number of data to be read in bytes ++ * @cc: completion code + * @pkg_config: package config data to be read + * + * The RdPkgConfig() command provides read access to the Package Configuration +@@ -251,11 +163,73 @@ struct peci_get_temp_msg { * DIMM temperatures and so on. */ struct peci_rd_pkg_cfg_msg { @@ -4191,12 +5143,21 @@ index a6dae71cbff5..8467b2fbee1f 100644 +#define PECI_PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */ + + __u8 rx_len; -+ __u8 padding[3]; ++ __u8 cc; ++ __u8 padding[2]; + __u8 pkg_config[4]; } __attribute__((__packed__)); /** -@@ -272,11 +244,19 @@ struct peci_rd_pkg_cfg_msg { +@@ -264,6 +238,7 @@ struct peci_rd_pkg_cfg_msg { + * @index: encoding index for the requested service + * @param: specific data being requested + * @tx_len: number of data to be written in bytes ++ * @cc: completion code + * @value: package config data to be written + * + * The WrPkgConfig() command provides write access to the Package Configuration +@@ -272,11 +247,20 @@ struct peci_rd_pkg_cfg_msg { * may include power limiting, thermal averaging constant programming and so on. */ struct peci_wr_pkg_cfg_msg { @@ -4216,12 +5177,20 @@ index a6dae71cbff5..8467b2fbee1f 100644 + + __u16 param; + __u8 tx_len; -+ __u8 padding[3]; ++ __u8 cc; ++ __u8 padding[2]; + __u32 value; } __attribute__((__packed__)); /** -@@ -290,10 +270,34 @@ struct peci_wr_pkg_cfg_msg { +@@ -284,16 +268,47 @@ struct peci_wr_pkg_cfg_msg { + * @addr: address of the client + * @thread_id: ID of the specific logical processor + * @address: address of MSR to read from ++ * @cc: completion code + * @value: data to be read + * + * The RdIAMSR() PECI command provides read access to Model Specific Registers * (MSRs) defined in the processor's Intel Architecture (IA). */ struct peci_rd_ia_msr_msg { @@ -4236,6 +5205,8 @@ index a6dae71cbff5..8467b2fbee1f 100644 + __u8 addr; + __u8 thread_id; + __u16 address; ++ __u8 cc; ++ __u8 padding[3]; + __u64 value; +} __attribute__((__packed__)); + @@ -4245,22 +5216,34 @@ index a6dae71cbff5..8467b2fbee1f 100644 + * @thread_id: ID of the specific logical processor + * @address: address of MSR to write to + * @tx_len: number of data to be written in bytes ++ * @cc: completion code + * @value: data to be written + * + * The WrIAMSR() PECI command provides write access to Model Specific Registers + * (MSRs) defined in the processor's Intel Architecture (IA). + */ +struct peci_wr_ia_msr_msg { ++#define PECI_WRIAMSR_CMD 0xb5 ++ + __u8 addr; + __u8 thread_id; + __u16 address; + __u8 tx_len; -+ __u8 padding[3]; ++ __u8 cc; ++ __u8 padding[2]; + __u64 value; } __attribute__((__packed__)); /** -@@ -310,12 +314,52 @@ struct peci_rd_ia_msr_msg { +@@ -303,6 +318,7 @@ struct peci_rd_ia_msr_msg { + * @device: PCI device number + * @function: specific function to read from + * @reg: specific register to read from ++ * @cc: completion code + * @pci_config: config data to be read + * + * The RdPCIConfig() command provides sideband read access to the PCI +@@ -310,12 +326,56 @@ struct peci_rd_ia_msr_msg { * processor. */ struct peci_rd_pci_cfg_msg { @@ -4289,7 +5272,8 @@ index a6dae71cbff5..8467b2fbee1f 100644 + __u8 device; + __u8 function; + __u16 reg; -+ __u8 padding[2]; ++ __u8 cc; ++ __u8 padding[1]; + __u8 pci_config[4]; +} __attribute__((__packed__)); + @@ -4301,6 +5285,7 @@ index a6dae71cbff5..8467b2fbee1f 100644 + * @function: specific function to write to + * @reg: specific register to write to + * @tx_len: number of data to be written in bytes ++ * @cc: completion code + * @pci_config: config data to be written + * + * The RdPCIConfig() command provides sideband write access to the PCI @@ -4308,18 +5293,28 @@ index a6dae71cbff5..8467b2fbee1f 100644 + * processor. + */ +struct peci_wr_pci_cfg_msg { ++#define PECI_WRPCICFG_CMD 0x65 ++ + __u8 addr; + __u8 bus; + __u8 device; + __u8 function; + __u16 reg; + __u8 tx_len; -+ __u8 padding; ++ __u8 cc; + __u8 pci_config[4]; } __attribute__((__packed__)); /** -@@ -333,13 +377,18 @@ struct peci_rd_pci_cfg_msg { +@@ -326,6 +386,7 @@ struct peci_rd_pci_cfg_msg { + * @function: specific function to read from + * @reg: specific register to read from + * @rx_len: number of data to be read in bytes ++ * @cc: completion code + * @pci_config: config data to be read + * + * The RdPCIConfigLocal() command provides sideband read access to the PCI +@@ -333,13 +394,18 @@ struct peci_rd_pci_cfg_msg { * processor IIO and uncore registers within the PCI configuration space. */ struct peci_rd_pci_cfg_local_msg { @@ -4340,12 +5335,20 @@ index a6dae71cbff5..8467b2fbee1f 100644 + __u8 function; + __u16 reg; + __u8 rx_len; -+ __u8 padding[3]; ++ __u8 cc; + __u8 pci_config[4]; } __attribute__((__packed__)); /** -@@ -357,13 +406,18 @@ struct peci_rd_pci_cfg_local_msg { +@@ -350,6 +416,7 @@ struct peci_rd_pci_cfg_local_msg { + * @function: specific function to read from + * @reg: specific register to read from + * @tx_len: number of data to be written in bytes ++ * @cc: completion code + * @value: config data to be written + * + * The WrPCIConfigLocal() command provides sideband write access to the PCI +@@ -357,13 +424,18 @@ struct peci_rd_pci_cfg_local_msg { * access this space even before BIOS enumeration of the system buses. */ struct peci_wr_pci_cfg_local_msg { @@ -4366,12 +5369,12 @@ index a6dae71cbff5..8467b2fbee1f 100644 + __u8 function; + __u16 reg; + __u8 tx_len; -+ __u8 padding[3]; ++ __u8 cc; + __u32 value; } __attribute__((__packed__)); #define PECI_IOC_BASE 0xb7 -@@ -389,9 +443,15 @@ struct peci_wr_pci_cfg_local_msg { +@@ -389,9 +461,15 @@ struct peci_wr_pci_cfg_local_msg { #define PECI_IOC_RD_IA_MSR \ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_IA_MSR, struct peci_rd_ia_msr_msg) |