]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/hwmon: Read energy status from PMT
authorKarthik Poosa <karthik.poosa@intel.com>
Thu, 29 May 2025 16:34:57 +0000 (22:04 +0530)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Fri, 30 May 2025 15:30:01 +0000 (11:30 -0400)
Read card and package energy status using pmt apis instead
of xe_mmio for supported platforms.
Enable Battlemage to read energy from PMT.

v2:
 - Remove unused has_pmt_energy field. (Badal)
 - Use GENMASK to extract energy data. (Badal)

v3:
 - Move PMT energy register offset and GENMASK to xe_pmt.h
 - Address review comments. (Jani)

v4:
 - Remove unnecessary debug print. (Badal)

v5:
 - Resolve an unused variable warning.
 - Add a return value check.

Signed-off-by: Karthik Poosa <karthik.poosa@intel.com>
Reviewed-by: Badal Nilawar <badal.nilawar@intel.com>
Link: https://lore.kernel.org/r/20250529163458.2354509-6-karthik.poosa@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/regs/xe_pcode_regs.h
drivers/gpu/drm/xe/regs/xe_pmt.h
drivers/gpu/drm/xe/xe_hwmon.c
drivers/gpu/drm/xe/xe_vsec.c
drivers/gpu/drm/xe/xe_vsec.h

index c556a04670eef74ebbc864e4c478ea62cce3fb08..fb097607b86cab8469baa08cea9351411bf8f21f 100644 (file)
 #define PVC_GT0_PLATFORM_ENERGY_STATUS          XE_REG(0x28106c)
 #define PVC_GT0_PACKAGE_POWER_SKU               XE_REG(0x281080)
 
-#define BMG_PACKAGE_ENERGY_STATUS              XE_REG(0x138120)
 #define BMG_FAN_1_SPEED                                XE_REG(0x138140)
 #define BMG_FAN_2_SPEED                                XE_REG(0x138170)
 #define BMG_FAN_3_SPEED                                XE_REG(0x1381a0)
 #define BMG_VRAM_TEMPERATURE                   XE_REG(0x1382c0)
 #define BMG_PACKAGE_TEMPERATURE                        XE_REG(0x138434)
-#define BMG_PLATFORM_ENERGY_STATUS             XE_REG(0x138458)
 
 #endif /* _XE_PCODE_REGS_H_ */
index f45abcd96ba8a49c94930d52bd3bd3dbaed1f0f7..b0efd9b48d1e0ccbcf1d296b35744df23d4182ae 100644 (file)
 #define BMG_PMT_BASE_OFFSET            0xDB000
 #define BMG_DISCOVERY_OFFSET           (SOC_BASE + BMG_PMT_BASE_OFFSET)
 
+#define PUNIT_TELEMETRY_GUID           XE_REG(BMG_DISCOVERY_OFFSET + 0x4)
+#define BMG_ENERGY_STATUS_PMT_OFFSET   (0x30)
+#define        ENERGY_PKG                      REG_GENMASK64(31, 0)
+#define        ENERGY_CARD                     REG_GENMASK64(63, 32)
+
 #define BMG_TELEMETRY_BASE_OFFSET      0xE0000
 #define BMG_TELEMETRY_OFFSET           (SOC_BASE + BMG_TELEMETRY_BASE_OFFSET)
 
index f07592aba2266cbf4aed5589ae8f953e1121d3b2..c57c613471c323b517e1a907405974fb2de5d2c2 100644 (file)
@@ -20,6 +20,8 @@
 #include "xe_pcode_api.h"
 #include "xe_sriov.h"
 #include "xe_pm.h"
+#include "xe_vsec.h"
+#include "regs/xe_pmt.h"
 
 enum xe_hwmon_reg {
        REG_TEMP,
@@ -252,12 +254,7 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg
                        return GT_PERF_STATUS;
                break;
        case REG_PKG_ENERGY_STATUS:
-               if (xe->info.platform == XE_BATTLEMAGE) {
-                       if (channel == CHANNEL_PKG)
-                               return BMG_PACKAGE_ENERGY_STATUS;
-                       else
-                               return BMG_PLATFORM_ENERGY_STATUS;
-               } else if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) {
+               if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) {
                        return PVC_GT0_PLATFORM_ENERGY_STATUS;
                } else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) {
                        return PCU_CR_PACKAGE_ENERGY_STATUS;
@@ -450,9 +447,32 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy)
        struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe);
        struct xe_hwmon_energy_info *ei = &hwmon->ei[channel];
        u64 reg_val;
+       int ret = 0;
+
+       /* Energy is supported only for card and pkg */
+       if (channel > CHANNEL_PKG) {
+               *energy = 0;
+               return;
+       }
 
-       reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS,
-                                                       channel));
+       if (hwmon->xe->info.platform == XE_BATTLEMAGE) {
+               ret = xe_pmt_telem_read(to_pci_dev(hwmon->xe->drm.dev),
+                                       xe_mmio_read32(mmio, PUNIT_TELEMETRY_GUID),
+                                       &reg_val, BMG_ENERGY_STATUS_PMT_OFFSET, sizeof(reg_val));
+               if (ret != sizeof(reg_val)) {
+                       drm_warn(&hwmon->xe->drm, "energy read from pmt failed, ret %d\n", ret);
+                       *energy = 0;
+                       return;
+               }
+
+               if (channel == CHANNEL_PKG)
+                       reg_val = REG_FIELD_GET64(ENERGY_PKG, reg_val);
+               else
+                       reg_val = REG_FIELD_GET64(ENERGY_CARD, reg_val);
+       } else {
+               reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS,
+                                                               channel));
+       }
 
        if (reg_val >= ei->reg_val_prev)
                ei->accum_energy += reg_val - ei->reg_val_prev;
@@ -934,11 +954,18 @@ xe_hwmon_in_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val)
 static umode_t
 xe_hwmon_energy_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel)
 {
+       long energy = 0;
+
        switch (attr) {
        case hwmon_energy_input:
        case hwmon_energy_label:
-               return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS,
-                                      channel)) ? 0444 : 0;
+               if (hwmon->xe->info.platform == XE_BATTLEMAGE) {
+                       xe_hwmon_energy_get(hwmon, channel, &energy);
+                       return energy ? 0444 : 0;
+               } else {
+                       return xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS,
+                                              channel)) ? 0444 : 0;
+               }
        default:
                return 0;
        }
@@ -1283,4 +1310,4 @@ int xe_hwmon_register(struct xe_device *xe)
 
        return 0;
 }
-
+MODULE_IMPORT_NS("INTEL_PMT_TELEMETRY");
index b378848d3b7bc77736c3df522623f9e2268a1ebb..3e573b0b7ebd84317c207a2eb19ae151b46aaa64 100644 (file)
@@ -149,8 +149,8 @@ static int xe_guid_decode(u32 guid, int *index, u32 *offset)
        return 0;
 }
 
-static int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset,
-                            u32 count)
+int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset,
+                     u32 count)
 {
        struct xe_device *xe = pdev_to_xe_device(pdev);
        void __iomem *telem_addr = xe->mmio.regs + BMG_TELEMETRY_OFFSET;
index 5777c53faec2ad832f50d05b4307f30820a97027..dabfb4e02d7072616f10793a2734a6f538d0e690 100644 (file)
@@ -4,8 +4,12 @@
 #ifndef _XE_VSEC_H_
 #define _XE_VSEC_H_
 
+#include <linux/types.h>
+
+struct pci_dev;
 struct xe_device;
 
 void xe_vsec_init(struct xe_device *xe);
+int xe_pmt_telem_read(struct pci_dev *pdev, u32 guid, u64 *data, loff_t user_offset, u32 count);
 
 #endif