From: "David E. Box" <david.e.box@linux.intel.com>
To: irenic.rajneesh@gmail.com, david.e.box@linux.intel.com,
hdegoede@redhat.com, mgross@linux.intel.com,
gayatri.kammela@intel.com
Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH V2 7/9] platform/x86: intel_pmc_core: Add option to set/clear LPM mode
Date: Fri, 16 Apr 2021 20:12:50 -0700 [thread overview]
Message-ID: <20210417031252.3020837-8-david.e.box@linux.intel.com> (raw)
In-Reply-To: <20210417031252.3020837-1-david.e.box@linux.intel.com>
By default the Low Power Mode (LPM or sub-state) status registers will
latch condition status on every entry into Package C10. This is
configurable in the PMC to allow latching on any achievable sub-state. Add
a debugfs file to support this.
Also add the option to clear the status registers to 0. Clearing the status
registers before testing removes ambiguity around when the current values
were set.
The new file, latch_lpm_mode, looks like this:
[c10] S0i2.0 S0i3.0 S0i2.1 S0i3.1 S0i3.2 clear
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
V2: - Rebase on Tamar/Tomas global reset patch that already adds
Extended Test Register 3
- In write function, make sure count is 1 less than buffer to reserve
space for '\0'
- Use sysfs_streq to properly compare the input string
drivers/platform/x86/intel_pmc_core.c | 112 ++++++++++++++++++++++++++
drivers/platform/x86/intel_pmc_core.h | 20 +++++
2 files changed, 132 insertions(+)
diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c
index 684f13f0c4a5..97cf3384c4c0 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -586,6 +586,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED,
.lpm_num_maps = TGL_LPM_NUM_MAPS,
.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
+ .lpm_sts_latch_en_offset = TGL_LPM_STS_LATCH_EN_OFFSET,
.lpm_en_offset = TGL_LPM_EN_OFFSET,
.lpm_priority_offset = TGL_LPM_PRI_OFFSET,
.lpm_residency_offset = TGL_LPM_RESIDENCY_OFFSET,
@@ -1321,6 +1322,114 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_substate_req_regs);
+static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused)
+{
+ struct pmc_dev *pmcdev = s->private;
+ bool c10;
+ u32 reg;
+ int idx, mode;
+
+ reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset);
+ if (reg & LPM_STS_LATCH_MODE) {
+ seq_puts(s, "c10");
+ c10 = false;
+ } else {
+ seq_puts(s, "[c10]");
+ c10 = true;
+ }
+
+ pmc_for_each_mode(idx, mode, pmcdev) {
+ if ((BIT(mode) & reg) && !c10)
+ seq_printf(s, " [%s]", pmc_lpm_modes[mode]);
+ else
+ seq_printf(s, " %s", pmc_lpm_modes[mode]);
+ }
+
+ seq_puts(s, " clear\n");
+
+ return 0;
+}
+
+static ssize_t pmc_core_lpm_latch_mode_write(struct file *file,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *s = file->private_data;
+ struct pmc_dev *pmcdev = s->private;
+ bool clear = false, c10 = false;
+ unsigned char buf[8];
+ size_t ret;
+ int idx, m, mode;
+ u32 reg;
+
+ if (count > sizeof(buf) - 1)
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count);
+ if (ret < 0)
+ return ret;
+
+ buf[count] = '\0';
+
+ /*
+ * Allowed strings are:
+ * Any enabled substate, e.g. 'S0i2.0'
+ * 'c10'
+ * 'clear'
+ */
+ mode = sysfs_match_string(pmc_lpm_modes, buf);
+
+ /* Check string matches enabled mode */
+ pmc_for_each_mode(idx, m, pmcdev)
+ if (mode == m)
+ break;
+
+ if (mode != m || mode < 0) {
+ if (sysfs_streq(buf, "clear"))
+ clear = true;
+ else if (sysfs_streq(buf, "c10"))
+ c10 = true;
+ else
+ return -EINVAL;
+ }
+
+ if (clear) {
+ mutex_lock(&pmcdev->lock);
+
+ reg = pmc_core_reg_read(pmcdev, pmcdev->map->etr3_offset);
+ reg |= ETR3_CLEAR_LPM_EVENTS;
+ pmc_core_reg_write(pmcdev, pmcdev->map->etr3_offset, reg);
+
+ mutex_unlock(&pmcdev->lock);
+
+ return count;
+ }
+
+ if (c10) {
+ mutex_lock(&pmcdev->lock);
+
+ reg = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_sts_latch_en_offset);
+ reg &= ~LPM_STS_LATCH_MODE;
+ pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg);
+
+ mutex_unlock(&pmcdev->lock);
+
+ return count;
+ }
+
+ /*
+ * For LPM mode latching we set the latch enable bit and selected mode
+ * and clear everything else.
+ */
+ reg = LPM_STS_LATCH_MODE | BIT(mode);
+ mutex_lock(&pmcdev->lock);
+ pmc_core_reg_write(pmcdev, pmcdev->map->lpm_sts_latch_en_offset, reg);
+ mutex_unlock(&pmcdev->lock);
+
+ return count;
+}
+DEFINE_PMC_CORE_ATTR_WRITE(pmc_core_lpm_latch_mode);
+
static int pmc_core_pkgc_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
@@ -1439,6 +1548,9 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
debugfs_create_file("substate_live_status_registers", 0444,
pmcdev->dbgfs_dir, pmcdev,
&pmc_core_substate_l_sts_regs_fops);
+ debugfs_create_file("lpm_latch_mode", 0644,
+ pmcdev->dbgfs_dir, pmcdev,
+ &pmc_core_lpm_latch_mode_fops);
}
if (pmcdev->lpm_req_regs) {
diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h
index 64fb368f40f6..c45805671c4a 100644
--- a/drivers/platform/x86/intel_pmc_core.h
+++ b/drivers/platform/x86/intel_pmc_core.h
@@ -189,6 +189,7 @@ enum ppfear_regs {
#define LPM_MAX_NUM_MODES 8
#define GET_X2_COUNTER(v) ((v) >> 1)
+#define LPM_STS_LATCH_MODE BIT(31)
#define TGL_NUM_IP_IGN_ALLOWED 22
#define TGL_PMC_SLP_S0_RES_COUNTER_STEP 0x7A
@@ -197,6 +198,7 @@ enum ppfear_regs {
/*
* Tigerlake Power Management Controller register offsets
*/
+#define TGL_LPM_STS_LATCH_EN_OFFSET 0x1C34
#define TGL_LPM_EN_OFFSET 0x1C78
#define TGL_LPM_RESIDENCY_OFFSET 0x1C80
@@ -211,6 +213,9 @@ enum ppfear_regs {
#define ETR3_CF9GR BIT(20)
#define ETR3_CF9LOCK BIT(31)
+/* Extended Test Mode Register LPM bits (TGL and later */
+#define ETR3_CLEAR_LPM_EVENTS BIT(28)
+
const char *pmc_lpm_modes[] = {
"S0i2.0",
"S0i2.1",
@@ -271,6 +276,7 @@ struct pmc_reg_map {
/* Low Power Mode registers */
const int lpm_num_maps;
const int lpm_res_counter_step_x2;
+ const u32 lpm_sts_latch_en_offset;
const u32 lpm_en_offset;
const u32 lpm_priority_offset;
const u32 lpm_residency_offset;
@@ -319,4 +325,18 @@ struct pmc_dev {
i < pmcdev->num_lpm_modes; \
i++, mode = pmcdev->lpm_en_modes[i])
+#define DEFINE_PMC_CORE_ATTR_WRITE(__name) \
+static int __name ## _open(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, __name ## _show, inode->i_private); \
+} \
+ \
+static const struct file_operations __name ## _fops = { \
+ .owner = THIS_MODULE, \
+ .open = __name ## _open, \
+ .read = seq_read, \
+ .write = __name ## _write, \
+ .release = single_release, \
+}
+
#endif /* PMC_CORE_H */
--
2.25.1
next prev parent reply other threads:[~2021-04-17 3:12 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-17 3:12 [PATCH V2 0/9] intel_pmc_core: Add sub-state requirements and mode David E. Box
2021-04-17 3:12 ` [PATCH V2 1/9] platform/x86: intel_pmc_core: Don't use global pmcdev in quirks David E. Box
2021-04-17 3:12 ` [PATCH V2 2/9] platform/x86: intel_pmc_core: Remove global struct pmc_dev David E. Box
2021-04-17 3:12 ` [PATCH V2 3/9] platform/x86: intel_pmc_core: Handle sub-states generically David E. Box
2021-04-17 3:12 ` [PATCH V2 4/9] platform/x86: intel_pmc_core: Show LPM residency in microseconds David E. Box
2021-04-17 3:12 ` [PATCH V2 5/9] platform/x86: intel_pmc_core: Get LPM requirements for Tiger Lake David E. Box
2021-04-17 5:55 ` kernel test robot
2021-04-17 6:25 ` kernel test robot
2021-04-17 8:52 ` Hans de Goede
2021-04-18 1:59 ` David E. Box
2021-04-17 9:00 ` Hans de Goede
2021-04-18 1:43 ` David E. Box
2021-04-17 3:12 ` [PATCH V2 6/9] platform/x86: intel_pmc_core: Add requirements file to debugfs David E. Box
2021-04-17 3:12 ` David E. Box [this message]
2021-04-17 3:12 ` [PATCH V2 8/9] platform/x86: intel_pmc_core: Add LTR registers for Tiger Lake David E. Box
2021-04-17 3:12 ` [PATCH V2 9/9] platform/x86: intel_pmc_core: Add support for Alder Lake PCH-P David E. Box
2021-04-17 9:12 ` [PATCH V2 0/9] intel_pmc_core: Add sub-state requirements and mode Hans de Goede
2021-04-19 8:47 ` Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210417031252.3020837-8-david.e.box@linux.intel.com \
--to=david.e.box@linux.intel.com \
--cc=gayatri.kammela@intel.com \
--cc=hdegoede@redhat.com \
--cc=irenic.rajneesh@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgross@linux.intel.com \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).