#define DELAY_MIN_US   2000
 #define DELAY_MAX_US   3000
 
+/* override Metrics Table sample size time (in ms) */
+static int metrics_table_loop_ms = 1000;
+module_param(metrics_table_loop_ms, int, 0644);
+MODULE_PARM_DESC(metrics_table_loop_ms, "Metrics Table sample size time (default = 1000ms)");
+
 static int current_power_limits_show(struct seq_file *seq, void *unused)
 {
        struct amd_pmf_dev *dev = seq->private;
                return POWER_SOURCE_DC;
 }
 
+static void amd_pmf_get_metrics(struct work_struct *work)
+{
+       struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, work_buffer.work);
+       ktime_t time_elapsed_ms;
+       int socket_power;
+
+       /* Transfer table contents */
+       memset(dev->buf, 0, sizeof(dev->m_table));
+       amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, 0, 7, NULL);
+       memcpy(&dev->m_table, dev->buf, sizeof(dev->m_table));
+
+       time_elapsed_ms = ktime_to_ms(ktime_get()) - dev->start_time;
+       /* Calculate the avg SoC power consumption */
+       socket_power = dev->m_table.apu_power + dev->m_table.dgpu_power;
+
+       dev->start_time = ktime_to_ms(ktime_get());
+       schedule_delayed_work(&dev->work_buffer, msecs_to_jiffies(metrics_table_loop_ms));
+}
+
 static inline u32 amd_pmf_reg_read(struct amd_pmf_dev *dev, int reg_offset)
 {
        return ioread32(dev->regbase + reg_offset);
        { }
 };
 
+int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
+{
+       u64 phys_addr;
+       u32 hi, low;
+
+       INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
+
+       /* Get Metrics Table Address */
+       dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
+       if (!dev->buf)
+               return -ENOMEM;
+
+       phys_addr = virt_to_phys(dev->buf);
+       hi = phys_addr >> 32;
+       low = phys_addr & GENMASK(31, 0);
+
+       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
+       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
+
+       /*
+        * Start collecting the metrics data after a small delay
+        * or else, we might end up getting stale values from PMFW.
+        */
+       schedule_delayed_work(&dev->work_buffer, msecs_to_jiffies(metrics_table_loop_ms * 3));
+
+       return 0;
+}
+
 static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 {
        /* Enable Static Slider */
 
        u32 fan_ctl_idx;
 } __packed;
 
+struct smu_pmf_metrics {
+       u16 gfxclk_freq; /* in MHz */
+       u16 socclk_freq; /* in MHz */
+       u16 vclk_freq; /* in MHz */
+       u16 dclk_freq; /* in MHz */
+       u16 memclk_freq; /* in MHz */
+       u16 spare;
+       u16 gfx_activity; /* in Centi */
+       u16 uvd_activity; /* in Centi */
+       u16 voltage[2]; /* in mV */
+       u16 currents[2]; /* in mA */
+       u16 power[2];/* in mW */
+       u16 core_freq[8]; /* in MHz */
+       u16 core_power[8]; /* in mW */
+       u16 core_temp[8]; /* in centi-Celsius */
+       u16 l3_freq; /* in MHz */
+       u16 l3_temp; /* in centi-Celsius */
+       u16 gfx_temp; /* in centi-Celsius */
+       u16 soc_temp; /* in centi-Celsius */
+       u16 throttler_status;
+       u16 current_socketpower; /* in mW */
+       u16 stapm_orig_limit; /* in W */
+       u16 stapm_cur_limit; /* in W */
+       u32 apu_power; /* in mW */
+       u32 dgpu_power; /* in mW */
+       u16 vdd_tdc_val; /* in mA */
+       u16 soc_tdc_val; /* in mA */
+       u16 vdd_edc_val; /* in mA */
+       u16 soc_edcv_al; /* in mA */
+       u16 infra_cpu_maxfreq; /* in MHz */
+       u16 infra_gfx_maxfreq; /* in MHz */
+       u16 skin_temp; /* in centi-Celsius */
+       u16 device_state;
+} __packed;
+
 enum amd_stt_skin_temp {
        STT_TEMP_APU,
        STT_TEMP_HS2,
        struct dentry *dbgfs_dir;
        int hb_interval; /* SBIOS heartbeat interval */
        struct delayed_work heart_beat;
+       struct smu_pmf_metrics m_table;
+       struct delayed_work work_buffer;
+       ktime_t start_time;
 };
 
 struct apmf_sps_prop_granular {
 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_init_metrics_table(struct amd_pmf_dev *dev);
 int amd_pmf_get_power_source(void);
 
 /* SPS Layer */