@@ -103,6 +103,22 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
data, sizeof(*data));
}
+static void apmf_sbios_heartbeat_notify(struct work_struct *work)
+{
+ struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, heart_beat.work);
+ union acpi_object *info;
+
+ dev_dbg(dev->dev, "Sending heartbeat to SBIOS\n");
+ info = apmf_if_call(dev, APMF_FUNC_SBIOS_HEARTBEAT, NULL);
+ if (!info)
+ goto out;
+
+ schedule_delayed_work(&dev->heart_beat, msecs_to_jiffies(dev->hb_interval * 1000));
+
+out:
+ kfree(info);
+}
+
static int apmf_if_verify_interface(struct amd_pmf_dev *pdev)
{
struct apmf_verify_interface output;
@@ -131,15 +147,23 @@ static int apmf_get_system_params(struct amd_pmf_dev *dev)
if (err)
return err;
- dev_dbg(dev->dev, "system params mask:0x%x flags:0x%x cmd_code:0x%x\n",
+ dev_dbg(dev->dev, "system params mask:0x%x flags:0x%x cmd_code:0x%x heartbeat:%d\n",
params.valid_mask,
params.flags,
- params.command_code);
+ params.command_code,
+ params.heartbeat_int);
params.flags = params.flags & params.valid_mask;
+ dev->hb_interval = params.heartbeat_int;
return 0;
}
+void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
+{
+ if (pmf_dev->hb_interval)
+ cancel_delayed_work_sync(&pmf_dev->heart_beat);
+}
+
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
{
int ret;
@@ -156,6 +180,12 @@ int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
goto out;
}
+ if (pmf_dev->hb_interval) {
+ /* send heartbeats only if the interval is not zero */
+ INIT_DELAYED_WORK(&pmf_dev->heart_beat, apmf_sbios_heartbeat_notify);
+ schedule_delayed_work(&pmf_dev->heart_beat, 0);
+ }
+
out:
return ret;
}
@@ -279,6 +279,7 @@ static int amd_pmf_remove(struct platform_device *pdev)
mutex_destroy(&dev->lock);
amd_pmf_deinit_features(dev);
+ apmf_acpi_deinit(dev);
amd_pmf_dbgfs_unregister(dev);
kfree(dev->buf);
return 0;
@@ -17,6 +17,7 @@
/* APMF Functions */
#define APMF_FUNC_VERIFY_INTERFACE 0
#define APMF_FUNC_GET_SYS_PARAMS 1
+#define APMF_FUNC_SBIOS_HEARTBEAT 4
#define APMF_FUNC_STATIC_SLIDER_GRANULAR 9
/* Message Definitions */
@@ -53,6 +54,7 @@ struct apmf_system_params {
u32 valid_mask;
u32 flags;
u8 command_code;
+ u32 heartbeat_int;
} __packed;
enum amd_stt_skin_temp {
@@ -91,6 +93,8 @@ struct amd_pmf_dev {
enum platform_profile_option current_profile;
struct platform_profile_handler pprof;
struct dentry *dbgfs_dir;
+ int hb_interval; /* SBIOS heartbeat interval */
+ struct delayed_work heart_beat;
};
struct apmf_sps_prop_granular {
@@ -116,6 +120,7 @@ struct amd_pmf_static_slider_granular {
/* Core Layer */
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
+void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
int is_apmf_func_supported(struct amd_pmf_dev *pdev, 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);