platform/x86/amd/pmf: Enable Custom BIOS Inputs for PMF-TA
authorShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Thu, 5 Dec 2024 10:19:37 +0000 (15:49 +0530)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Tue, 17 Dec 2024 11:13:16 +0000 (13:13 +0200)
Introduce support for passing custom BIOS inputs to the PMF-TA to assess
BIOS input policy conditions. The PMF driver will adjust system settings
based on these BIOS input conditions and their corresponding output
actions.

Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Link: https://lore.kernel.org/r/20241205101937.2547351-1-Shyam-sundar.S-k@amd.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/amd/pmf/acpi.c
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/amd/pmf/spc.c

index 1b9c7acf0ddf5558be26c4162713cf54b4037163..21ccd677ffa4f6c08629074575fdd80c243f1613 100644 (file)
@@ -321,6 +321,18 @@ int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req
                                                                         req, sizeof(*req));
 }
 
+static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data)
+{
+       struct amd_pmf_dev *pmf_dev = data;
+       int ret;
+
+       guard(mutex)(&pmf_dev->cb_mutex);
+
+       ret = apmf_get_sbios_requests_v2(pmf_dev, &pmf_dev->req);
+       if (ret)
+               dev_err(pmf_dev->dev, "Failed to get v2 SBIOS requests: %d\n", ret);
+}
+
 static void apmf_event_handler(acpi_handle handle, u32 event, void *data)
 {
        struct amd_pmf_dev *pmf_dev = data;
@@ -430,6 +442,15 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
                apmf_event_handler(ahandle, 0, pmf_dev);
        }
 
+       if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) {
+               status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY,
+                                                    apmf_event_handler_v2, pmf_dev);
+               if (ACPI_FAILURE(status)) {
+                       dev_err(pmf_dev->dev, "failed to install notify handler for custom BIOS inputs\n");
+                       return -ENODEV;
+               }
+       }
+
        return 0;
 }
 
@@ -480,6 +501,9 @@ void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
        if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) &&
            is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS))
                acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler);
+
+       if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2)
+               acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler_v2);
 }
 
 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
index 64ab532550ac304d5d6e8b72b6fa25baa33b5312..56024eb40266dc6d32f0437b2bf1f3b31df6d113 100644 (file)
@@ -370,6 +370,8 @@ struct amd_pmf_dev {
        struct input_dev *pmf_idev;
        size_t mtable_size;
        struct resource *res;
+       struct apmf_sbios_req_v2 req; /* To get custom bios pending request */
+       struct mutex cb_mutex;
 };
 
 struct apmf_sps_prop_granular_v2 {
@@ -616,6 +618,16 @@ enum ta_slider {
        TA_MAX,
 };
 
+enum apmf_smartpc_custom_bios_inputs {
+       APMF_SMARTPC_CUSTOM_BIOS_INPUT1,
+       APMF_SMARTPC_CUSTOM_BIOS_INPUT2,
+};
+
+enum apmf_preq_smartpc {
+       NOTIFY_CUSTOM_BIOS_INPUT1 = 5,
+       NOTIFY_CUSTOM_BIOS_INPUT2,
+};
+
 /* Command ids for TA communication */
 enum ta_pmf_command {
        TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE,
@@ -657,7 +669,8 @@ struct ta_pmf_condition_info {
        u32 power_slider;
        u32 lid_state;
        bool user_present;
-       u32 rsvd1[2];
+       u32 bios_input1;
+       u32 bios_input2;
        u32 monitor_count;
        u32 rsvd2[2];
        u32 bat_design;
index 06226eb0eab33f3ee9e259563f207457b578cc67..05bed820636519ba983c45040c67f3038f0c9bbb 100644 (file)
@@ -47,12 +47,35 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
        dev_dbg(dev->dev, "LID State: %s\n", in->ev_info.lid_state ? "close" : "open");
        dev_dbg(dev->dev, "User Presence: %s\n", in->ev_info.user_present ? "Present" : "Away");
        dev_dbg(dev->dev, "Ambient Light: %d\n", in->ev_info.ambient_light);
+       dev_dbg(dev->dev, "Custom BIOS input1: %u\n", in->ev_info.bios_input1);
+       dev_dbg(dev->dev, "Custom BIOS input2: %u\n", in->ev_info.bios_input2);
        dev_dbg(dev->dev, "==== TA inputs END ====\n");
 }
 #else
 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {}
 #endif
 
+static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev,
+                                          struct ta_pmf_enact_table *in)
+{
+       if (!pdev->req.pending_req)
+               return;
+
+       switch (pdev->req.pending_req) {
+       case BIT(NOTIFY_CUSTOM_BIOS_INPUT1):
+               in->ev_info.bios_input1 = pdev->req.custom_policy[APMF_SMARTPC_CUSTOM_BIOS_INPUT1];
+               break;
+       case BIT(NOTIFY_CUSTOM_BIOS_INPUT2):
+               in->ev_info.bios_input2 = pdev->req.custom_policy[APMF_SMARTPC_CUSTOM_BIOS_INPUT2];
+               break;
+       default:
+               dev_dbg(pdev->dev, "Invalid preq for BIOS input: 0x%x\n", pdev->req.pending_req);
+       }
+
+       /* Clear pending requests after handling */
+       memset(&pdev->req, 0, sizeof(pdev->req));
+}
+
 static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in)
 {
        u16 max, avg = 0;
@@ -201,4 +224,5 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
        amd_pmf_get_battery_info(dev, in);
        amd_pmf_get_slider_info(dev, in);
        amd_pmf_get_sensor_info(dev, in);
+       amd_pmf_get_custom_bios_inputs(dev, in);
 }