Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp817272pxf; Thu, 1 Apr 2021 14:32:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzVlFFxufw2mBWddnqD7h8T5Xi7eF6ZQzcWttBCiv111NHqsA30oixTYMhUj+CqwJN25s8N X-Received: by 2002:a17:907:37a:: with SMTP id rs26mr11137350ejb.336.1617312776024; Thu, 01 Apr 2021 14:32:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617312776; cv=none; d=google.com; s=arc-20160816; b=tQuY98e7d4NKVxVQHeiuF1pwP+QBJcCD1VTCrBAAwi8aMhugfKdf1NgW1Q1LYAVJae ETbQXl7DcJJErgiLXOu50kIUKPiMGTDTcYNU+QsyRs8IFpcZwcOq9I+foZQGV2+22Szo /Fa0qaG10N2XtrOl3JZzhrp8jIBgvbnrmWno3h1ZjIvEWGLLTCEWNM2AOhpBJ26ZdoaZ 7y29TcR8RtT+emezgM0rh/amE/1eSMiczCltckwd0bjmqRAlBGRkUJbvS4CEDSr+78z3 b/LvzcxpIFnh3HF35A6KpU3DeMwJCWZ0zOP3zYt6qKyQcp0y8YWUCEwpzULkHtoq9q54 vLQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:ironport-sdr:ironport-sdr; bh=xRexPbZkwZ91RF67wxzsPY4qoL+gKt4C7CBazfzFYZY=; b=a9WzhKNrJIQuYMzUSDAXHMzuGhWuOu9j0F9nMEhqOOJSzDErmWCXWSitYh6Z9KDu50 vP9jAUF2iQReRSAZkZNspT//4XROcB1jSuz8+22KbA0/jMJsZnDjFynVipSCU1XnzL6U SvsPjXvj2JYN0FG+OT1h55cgd1o8R8XjJG0jOOa02pqD7+UoHcpbqng1WlnbZOdH8lx9 loNDFjbBYyRk47bMfkqDZT26TMlPey+SxmbCJypuFWJn03nTZkic7ZX5tthu5Dx+kVmU go2mJDQj6Ycke/RvjAcW7gJU9hzHSm2VusAsW7xYxBXc+iXAKXjmIKoxvK428MiGUCZr 8aNA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a17si5041571eju.485.2021.04.01.14.32.30; Thu, 01 Apr 2021 14:32:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234150AbhDAVcD (ORCPT + 99 others); Thu, 1 Apr 2021 17:32:03 -0400 Received: from mga14.intel.com ([192.55.52.115]:11444 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233588AbhDAVcC (ORCPT ); Thu, 1 Apr 2021 17:32:02 -0400 IronPort-SDR: SdhVsglZmLjT5y++5Qu03IW2Qq48BJQ9y21B0m8PWGxMsN+6dx9AiRwxkT9YU/J1ZMHszjMbFX ymsGlqkyMKrg== X-IronPort-AV: E=McAfee;i="6000,8403,9941"; a="191815248" X-IronPort-AV: E=Sophos;i="5.81,296,1610438400"; d="scan'208";a="191815248" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2021 14:32:02 -0700 IronPort-SDR: Vhgqonq0kjSVTlM4fimvnwkKKPbFiPqGvXyiuv7jIH2tsZ6zo/NxeF3BZ69b/5CnDCbT48RECi N0TSu5iS0PzA== X-IronPort-AV: E=Sophos;i="5.81,296,1610438400"; d="scan'208";a="419374627" Received: from twinkler-lnx.jer.intel.com ([10.12.91.138]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Apr 2021 14:31:59 -0700 From: Tomas Winkler To: Rajneesh Bhardwaj , David E Box , Hans de Goede , Mark Gross Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, Tamar Mashiah , Andy Shevchenko , Tomas Winkler Subject: [PATCH] platform/x86: intel_pmc_core: export platform global_reset via sysfs. Date: Fri, 2 Apr 2021 00:31:44 +0300 Message-Id: <20210401213144.1009224-1-tomas.winkler@intel.com> X-Mailer: git-send-email 2.26.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tamar Mashiah During PCH manufacturing a global reset has to be induced in order for configuration changes take affect upon following platform reset. This setting was commonly done by accessing PMC registers via /dev/mem but due to security concern /dev/mem access is much restricted, hence the reason for exposing this setting via dedicated sysfs interface. To prevent post manufacturing abuse the register is protected by hardware locking. The register in MMIO space is defined for Cannon Lake and newer PCHs. Cc: David E Box Reviewed-by: Andy Shevchenko Signed-off-by: Tamar Mashiah Signed-off-by: Tomas Winkler --- .../ABI/testing/sysfs-platform-intel-pmc | 11 +++ MAINTAINERS | 1 + drivers/platform/x86/intel_pmc_core.c | 95 +++++++++++++++++++ drivers/platform/x86/intel_pmc_core.h | 6 ++ 4 files changed, 113 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc b/Documentation/ABI/testing/sysfs-platform-intel-pmc new file mode 100644 index 000000000000..7ce00e77fbcd --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc @@ -0,0 +1,11 @@ +What: /sys/devices/platform//global_reset +Date: Apr 2021 +KernelVersion: 5.13 +Contact: "Tomas Winkler" +Description: + Display global reset setting bits for PMC. + * bit 31 - global reset is locked + * bit 20 - global reset is set + Writing bit 20 value to the global_reset will induce + a platform global reset upon consequent platform reset. + in case the register is not locked. diff --git a/MAINTAINERS b/MAINTAINERS index 04f68e0cda64..618676eba8c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9166,6 +9166,7 @@ M: Rajneesh Bhardwaj M: David E Box L: platform-driver-x86@vger.kernel.org S: Maintained +F: Documentation/ABI/testing/sysfs-platform-intel-pmc F: drivers/platform/x86/intel_pmc_core* INTEL PMIC GPIO DRIVERS diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index ee2f757515b0..9f252d5f7ac5 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = { .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, + .etr3_offset = ETR3_OFFSET, }; static const struct pmc_reg_map icl_reg_map = { @@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = { .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, + .etr3_offset = ETR3_OFFSET, }; static const struct pmc_bit_map tgl_clocksource_status_map[] = { @@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = { .lpm_sts = tgl_lpm_maps, .lpm_status_offset = TGL_LPM_STATUS_OFFSET, .lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET, + .etr3_offset = ETR3_OFFSET, }; static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) @@ -603,6 +606,97 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value) return (u64)value * pmcdev->map->slp_s0_res_counter_step; } +static int set_global_reset(struct pmc_dev *pmcdev) +{ + const struct pmc_reg_map *map = pmcdev->map; + u32 reg; + int err; + + mutex_lock(&pmcdev->lock); + + if (!map->etr3_offset) { + err = -EOPNOTSUPP; + goto out_unlock; + } + + /* check if CF9 is locked */ + reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + if (reg & ETR3_CF9LOCK) { + err = -EACCES; + goto out_unlock; + } + + /* write CF9 global reset bit */ + reg |= ETR3_CF9GR; + pmc_core_reg_write(pmcdev, map->etr3_offset, reg); + + reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + if ((reg & ETR3_CF9GR) == 0) { + err = -EIO; + goto out_unlock; + } + + err = 0; + +out_unlock: + mutex_unlock(&pmcdev->lock); + return err; +} + +static ssize_t global_reset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pmc_dev *pmcdev = dev_get_drvdata(dev); + const struct pmc_reg_map *map = pmcdev->map; + u32 reg; + + if (!map->etr3_offset) + return -EOPNOTSUPP; + + reg = pmc_core_reg_read(pmcdev, map->etr3_offset); + reg &= ETR3_CF9GR | ETR3_CF9LOCK; + + return sysfs_emit(buf, "0x%08x", reg); +} + +static ssize_t global_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct pmc_dev *pmcdev = dev_get_drvdata(dev); + int err; + u32 reg; + + err = kstrtouint(buf, 16, ®); + if (err) + return err; + + /* allow only cf9 writes */ + if (reg != ETR3_CF9GR) + return -EINVAL; + + err = set_global_reset(pmcdev); + if (err) + return err; + + return len; +} +static DEVICE_ATTR_RW(global_reset); + +static struct attribute *pmc_attrs[] = { + &dev_attr_global_reset.attr, + NULL +}; + +static const struct attribute_group pmc_attr_group = { + .attrs = pmc_attrs, +}; + +static const struct attribute_group *pmc_dev_groups[] = { + &pmc_attr_group, + NULL +}; + static int pmc_core_dev_state_get(void *data, u64 *val) { struct pmc_dev *pmcdev = data; @@ -1364,6 +1458,7 @@ static struct platform_driver pmc_core_driver = { .name = "intel_pmc_core", .acpi_match_table = ACPI_PTR(pmc_core_acpi_ids), .pm = &pmc_core_pm_ops, + .dev_groups = pmc_dev_groups, }, .probe = pmc_core_probe, .remove = pmc_core_remove, diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index f33cd2c34835..98ebdfe57138 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -200,6 +200,11 @@ enum ppfear_regs { #define TGL_LPM_STATUS_OFFSET 0x1C3C #define TGL_LPM_LIVE_STATUS_OFFSET 0x1C5C +/* Extended Test Mode Register 3 (CNL and later) */ +#define ETR3_OFFSET 0x1048 +#define ETR3_CF9GR BIT(20) +#define ETR3_CF9LOCK BIT(31) + const char *tgl_lpm_modes[] = { "S0i2.0", "S0i2.1", @@ -263,6 +268,7 @@ struct pmc_reg_map { const u32 lpm_residency_offset; const u32 lpm_status_offset; const u32 lpm_live_status_offset; + const u32 etr3_offset; }; /** -- 2.26.3