All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
To: <hdegoede@redhat.com>, <markgross@kernel.org>
Cc: <platform-driver-x86@vger.kernel.org>, <Patil.Reddy@amd.com>,
	"Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
Subject: [PATCH v1 04/15] platform/x86/amd/pmf: Add support SPS PMF feature
Date: Tue, 12 Jul 2022 20:28:36 +0530	[thread overview]
Message-ID: <20220712145847.3438544-5-Shyam-sundar.S-k@amd.com> (raw)
In-Reply-To: <20220712145847.3438544-1-Shyam-sundar.S-k@amd.com>

SPS (a.k.a. Static Power Slider) gives a feel of Windows performance
power slider for the Linux users, where the user selects a certain
mode (like "balanced", "low-power" or "performance") and the thermals
associated with each selected mode gets applied from the silicon
side via the mailboxes defined through PMFW.

PMF driver hooks to platform_profile by reading the PMF ACPI fn9 to
see if the support is being advertised by ACPI interface.

If supported, the PMF driver reacts to platform_profile selection choices
made by the user and adjust the system thermal behavior.

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/platform/x86/amd/pmf/Makefile |   2 +-
 drivers/platform/x86/amd/pmf/acpi.c   |  29 +++++
 drivers/platform/x86/amd/pmf/core.c   |  26 ++++
 drivers/platform/x86/amd/pmf/pmf.h    |  65 ++++++++++
 drivers/platform/x86/amd/pmf/sps.c    | 166 ++++++++++++++++++++++++++
 5 files changed, 287 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/amd/pmf/sps.c

diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
index 2617eba773ce..557521a80427 100644
--- a/drivers/platform/x86/amd/pmf/Makefile
+++ b/drivers/platform/x86/amd/pmf/Makefile
@@ -5,4 +5,4 @@
 #
 
 obj-$(CONFIG_AMD_PMF) += amd-pmf.o
-amd-pmf-objs := core.o acpi.o
+amd-pmf-objs := core.o acpi.o sps.o
diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
index addcaae5675c..fd5ab7a116f0 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -54,6 +54,7 @@ static union acpi_object *apmf_if_call(struct apmf_if *apmf_if, int func, struct
 static void apmf_if_parse_functions(struct apmf_if_functions *func, u32 mask)
 {
 	func->system_params = mask & APMF_FUNC_GET_SYS_PARAMS;
+	func->static_slider_granular = mask & APMF_FUNC_STATIC_SLIDER_GRANULAR;
 }
 
 static int apmf_if_verify_interface(struct amd_pmf_dev *pdev, struct apmf_if *ampf_if)
@@ -130,6 +131,34 @@ static int apmf_get_system_params(struct apmf_if *ampf_if)
 	return err;
 }
 
+int apmf_get_static_slider_granular(struct apmf_if *ampf_if,
+				    struct apmf_static_slider_granular_output *data)
+{
+	union acpi_object *info;
+	size_t size;
+	int err = 0;
+
+	info = apmf_if_call(ampf_if, APMF_FUNC_STATIC_SLIDER_GRANULAR, NULL);
+	if (!info)
+		return -EIO;
+
+	size = *(u16 *)info->buffer.pointer;
+
+	if (size < sizeof(*data)) {
+		pr_err("PMF: buffer too small %zu\n", size);
+		err = -EINVAL;
+		goto out;
+	}
+
+	size = min(sizeof(*data), size);
+	memset(data, 0, sizeof(*data));
+	memcpy(data, info->buffer.pointer, size);
+
+out:
+	kfree(info);
+	return err;
+}
+
 static acpi_handle apmf_if_probe_handle(void)
 {
 	acpi_handle handle = NULL;
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index c5002b7bb904..b6006e8ee1a1 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/power_supply.h>
 #include "pmf.h"
 
 /* PMF-SMU communication registers */
@@ -45,6 +46,14 @@
 #define DELAY_MIN_US	2000
 #define DELAY_MAX_US	3000
 
+int amd_pmf_get_power_source(void)
+{
+	if (power_supply_is_system_supplied() > 0)
+		return POWER_SOURCE_AC;
+	else
+		return POWER_SOURCE_DC;
+}
+
 static inline u32 amd_pmf_reg_read(struct amd_pmf_dev *dev, int reg_offset)
 {
 	return ioread32(dev->regbase + reg_offset);
@@ -138,6 +147,21 @@ static const struct pci_device_id pmf_pci_ids[] = {
 	{ }
 };
 
+static void amd_pmf_init_features(struct amd_pmf_dev *dev)
+{
+	/* Enable Static Slider */
+	if (is_apmf_func_supported(APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+		amd_pmf_init_sps(dev);
+		dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
+	}
+}
+
+static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
+{
+	if (is_apmf_func_supported(APMF_FUNC_STATIC_SLIDER_GRANULAR))
+		amd_pmf_deinit_sps(dev);
+}
+
 static const struct acpi_device_id amd_pmf_acpi_ids[] = {
 	{"AMDI0102", 0},
 	{ }
@@ -206,6 +230,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
 
 	apmf_acpi_init(dev);
 	platform_set_drvdata(pdev, dev);
+	amd_pmf_init_features(dev);
 
 	mutex_init(&dev->lock);
 	dev_info(dev->dev, "registered PMF device successfully\n");
@@ -218,6 +243,7 @@ static int amd_pmf_remove(struct platform_device *pdev)
 	struct amd_pmf_dev *dev = platform_get_drvdata(pdev);
 
 	mutex_destroy(&dev->lock);
+	amd_pmf_deinit_features(dev);
 	kfree(dev->buf);
 	return 0;
 }
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 40f038eb6197..a405987ae653 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -7,14 +7,17 @@
  *
  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
  */
+
 #ifndef PMF_H
 #define PMF_H
 
 #include <linux/acpi.h>
+#include <linux/platform_profile.h>
 
 /* APMF Functions */
 #define APMF_FUNC_VERIFY_INTERFACE			0
 #define APMF_FUNC_GET_SYS_PARAMS			1
+#define APMF_FUNC_STATIC_SLIDER_GRANULAR	9
 
 /* Message Definitions */
 #define SET_SPL				0x03 /* SPL: Sustained Power Limit */
@@ -35,9 +38,12 @@
 #define GET_STT_LIMIT_APU	0x20
 #define GET_STT_LIMIT_HS2	0x21
 
+#define ARG_NONE 0
+
 /* AMD PMF BIOS interfaces */
 struct apmf_if_functions {
 	bool system_params;
+	bool static_slider_granular;
 };
 
 struct apmf_if {
@@ -59,6 +65,30 @@ struct apmf_system_params {
 	u8 command_code;
 } __packed;
 
+enum amd_stt_skin_temp {
+	STT_TEMP_APU,
+	STT_TEMP_HS2,
+	STT_TEMP_COUNT,
+};
+
+enum amd_slider_op {
+	SLIDER_OP_GET,
+	SLIDER_OP_SET,
+};
+
+enum power_source {
+	POWER_SOURCE_AC,
+	POWER_SOURCE_DC,
+	POWER_SOURCE_MAX,
+};
+
+enum power_modes {
+	POWER_MODE_PERFORMANCE,
+	POWER_MODE_BALANCED_POWER,
+	POWER_MODE_POWER_SAVER,
+	POWER_MODE_MAX,
+};
+
 struct amd_pmf_dev {
 	void __iomem *regbase;
 	void __iomem *smu_virt_addr;
@@ -69,11 +99,46 @@ struct amd_pmf_dev {
 	u32 low;
 	struct device *dev;
 	struct apmf_if *apmf_if;
+	enum platform_profile_option current_profile;
+	struct platform_profile_handler pprof;
 	struct mutex lock; /* protects the PMF interface */
 };
 
+struct apmf_sps_prop_granular {
+	u32 fppt;
+	u32 sppt;
+	u32 sppt_apu_only;
+	u32 spl;
+	u32 stt_min;
+	u8 stt_skin_temp[STT_TEMP_COUNT];
+	u32 fan_id;
+} __packed;
+
+/* Static Slider */
+struct apmf_static_slider_granular_output {
+	u16 size;
+	struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX * POWER_MODE_MAX];
+};
+
+struct amd_pmf_static_slider_granular {
+	u16 size;
+	struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX][POWER_MODE_MAX];
+};
+
 /* Core Layer */
 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
+int is_apmf_func_supported(unsigned long index);
 int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32 *data);
+int amd_pmf_get_power_source(void);
+
+/* SPS Layer */
+u8 amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
+void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
+			   struct amd_pmf_static_slider_granular *table);
+int amd_pmf_init_sps(struct amd_pmf_dev *dev);
+void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
+int apmf_get_static_slider_granular(struct apmf_if *ampf_if,
+				    struct apmf_static_slider_granular_output *output);
+void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev);
 
 #endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
new file mode 100644
index 000000000000..25289cf5608c
--- /dev/null
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD Platform Management Framework (PMF) Driver
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ */
+
+#include "pmf.h"
+
+static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
+			       enum platform_profile_option *profile);
+static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
+			       enum platform_profile_option profile);
+static struct amd_pmf_static_slider_granular config_store;
+
+void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
+{
+	struct apmf_static_slider_granular_output output;
+	int i, j, idx = 0;
+
+	memset(&config_store, 0, sizeof(config_store));
+
+	if (dev->apmf_if->func.static_slider_granular) {
+		apmf_get_static_slider_granular(dev->apmf_if, &output);
+
+		for (i = 0; i < POWER_SOURCE_MAX; i++) {
+			for (j = 0; j < POWER_MODE_MAX; j++) {
+				config_store.prop[i][j].spl = output.prop[idx].spl;
+				config_store.prop[i][j].sppt = output.prop[idx].sppt;
+				config_store.prop[i][j].sppt_apu_only =
+							output.prop[idx].sppt_apu_only;
+				config_store.prop[i][j].fppt = output.prop[idx].fppt;
+				config_store.prop[i][j].stt_min = output.prop[idx].stt_min;
+				config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] =
+						output.prop[idx].stt_skin_temp[STT_TEMP_APU];
+				config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] =
+						output.prop[idx].stt_skin_temp[STT_TEMP_HS2];
+				config_store.prop[i][j].fan_id = output.prop[idx].fan_id;
+				idx++;
+			}
+		}
+	}
+}
+
+void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
+			   struct amd_pmf_static_slider_granular *table)
+{
+	int src = amd_pmf_get_power_source();
+
+	if (op == SLIDER_OP_SET) {
+		amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL);
+		amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL);
+		amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL);
+		amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,
+				 config_store.prop[src][idx].sppt_apu_only, NULL);
+		amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
+				 config_store.prop[src][idx].stt_min, NULL);
+		amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
+				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL);
+		amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
+				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL);
+	} else if (op == SLIDER_OP_GET) {
+		amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);
+		amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);
+		amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt);
+		amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE,
+				 &table->prop[src][idx].sppt_apu_only);
+		amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE,
+				 &table->prop[src][idx].stt_min);
+		amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE,
+				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]);
+		amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE,
+				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]);
+	}
+}
+
+static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
+			       enum platform_profile_option *profile)
+{
+	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+
+	*profile = pmf->current_profile;
+	return 0;
+}
+
+u8 amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
+{
+	u8 mode;
+
+	switch (pmf->current_profile) {
+	case PLATFORM_PROFILE_PERFORMANCE:
+		mode = 0;
+		break;
+	case PLATFORM_PROFILE_BALANCED:
+		mode = 1;
+		break;
+	case PLATFORM_PROFILE_LOW_POWER:
+		mode = 2;
+		break;
+	default:
+		dev_err(pmf->dev, "Unknown Platform Profile.\n");
+		break;
+	}
+
+	return mode;
+}
+
+int amd_pmf_profile_set(struct platform_profile_handler *pprof,
+			enum platform_profile_option profile)
+{
+	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+	u8 mode;
+
+	pmf->current_profile = profile;
+	mode = amd_pmf_get_pprof_modes(pmf);
+	amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
+	return 0;
+}
+
+static void amd_pmf_profile_refresh(struct amd_pmf_dev *dev)
+{
+	enum platform_profile_option profile;
+
+	/* Set intially to Balanced Mode */
+	profile = PLATFORM_PROFILE_BALANCED;
+
+	if (profile != dev->current_profile) {
+		dev->current_profile = profile;
+		platform_profile_notify();
+	}
+}
+
+int amd_pmf_init_sps(struct amd_pmf_dev *dev)
+{
+	int err = 0;
+
+	dev->pprof.profile_get = amd_pmf_profile_get;
+	dev->pprof.profile_set = amd_pmf_profile_set;
+
+	/* Setup supported modes */
+	set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
+	set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
+	set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
+
+	/* Create platform_profile structure and register */
+	err = platform_profile_register(&dev->pprof);
+	if (err) {
+		dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
+			err);
+		return -EEXIST;
+	}
+	/* Ensure initial values are correct */
+	amd_pmf_profile_refresh(dev);
+
+	amd_pmf_load_defaults_sps(dev);
+
+	return err;
+}
+
+void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)
+{
+	platform_profile_remove();
+}
-- 
2.25.1


  parent reply	other threads:[~2022-07-12 15:03 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-12 14:58 [PATCH v1 00/15] platform/x86/amd/pmf: Introduce AMD PMF Driver Shyam Sundar S K
2022-07-12 14:58 ` [PATCH v1 01/15] ACPI: platform_profile: Add support for notification chains Shyam Sundar S K
2022-07-12 15:03   ` Limonciello, Mario
2022-07-27 13:24     ` Hans de Goede
2022-07-27 20:38   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 02/15] platform/x86/amd/pmf: Add support for PMF core layer Shyam Sundar S K
2022-07-27 13:57   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 03/15] platform/x86/amd/pmf: Add support for PMF APCI layer Shyam Sundar S K
2022-07-27 13:57   ` Hans de Goede
2022-07-12 14:58 ` Shyam Sundar S K [this message]
2022-07-27 19:29   ` [PATCH v1 04/15] platform/x86/amd/pmf: Add support SPS PMF feature Hans de Goede
2022-07-27 20:26     ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 05/15] platform/x86/amd/pmf: Add debugfs information Shyam Sundar S K
2022-07-27 19:50   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 06/15] platform/x86/amd/pmf: Add heartbeat signal support Shyam Sundar S K
2022-07-27 19:53   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 07/15] platform/x86/amd/pmf: Add fan control support Shyam Sundar S K
2022-07-27 20:11   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 08/15] platform/x86/amd/pmf: Get performance metrics from PMFW Shyam Sundar S K
2022-07-27 20:36   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 09/15] platform/x86/amd/pmf: Add support for CnQF Shyam Sundar S K
2022-07-27 20:51   ` Hans de Goede
2022-07-27 21:00   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 10/15] platform/x86/amd/pmf: Add sysfs to toggle CnQF Shyam Sundar S K
2022-07-27 20:52   ` Hans de Goede
2022-07-27 21:12     ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 11/15] Documentation/ABI/testing/sysfs-amd-pmf: Add ABI doc for AMD PMF Shyam Sundar S K
2022-07-27 20:52   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 12/15] platform/x86/amd/pmf: Add support for Auto mode feature Shyam Sundar S K
2022-07-27 21:22   ` Hans de Goede
2022-07-28 12:57     ` Shyam Sundar S K
2022-07-28 13:15       ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 13/15] platform/x86/amd/pmf: Handle AMT and CQL events for Auto mode Shyam Sundar S K
2022-07-27 21:33   ` Hans de Goede
2022-07-27 21:44   ` Hans de Goede
2022-07-27 21:46   ` Hans de Goede
2022-07-27 23:52     ` Limonciello, Mario
2022-07-28 13:03       ` Hans de Goede
2022-07-28 13:43         ` Limonciello, Mario
2022-07-28 14:09           ` Hans de Goede
2022-07-28 14:38             ` Limonciello, Mario
2022-07-28 17:46               ` Hans de Goede
2022-07-28 18:06                 ` Limonciello, Mario
2022-07-28 18:17                   ` Hans de Goede
2022-07-28 21:01                     ` Limonciello, Mario
2022-07-29 11:03                       ` Hans de Goede
2022-07-29 15:43                         ` Limonciello, Mario
2022-07-29 17:40                           ` Shyam Sundar S K
2022-07-29 17:59                             ` Hans de Goede
2022-08-01 10:29                               ` Shyam Sundar S K
2022-08-01 11:08                                 ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 14/15] platform/x86/amd/pmf: Force load driver on older supported platforms Shyam Sundar S K
2022-07-27 21:40   ` Hans de Goede
2022-07-12 14:58 ` [PATCH v1 15/15] MAINTAINERS: Add AMD PMF driver entry Shyam Sundar S K
2022-07-27 21:41   ` Hans de Goede
2022-07-28 17:44     ` Shyam Sundar S K

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=20220712145847.3438544-5-Shyam-sundar.S-k@amd.com \
    --to=shyam-sundar.s-k@amd.com \
    --cc=Patil.Reddy@amd.com \
    --cc=hdegoede@redhat.com \
    --cc=markgross@kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.