[PATCH v4 5/5] drm/xe/hwmon: Read energy status from PMT

Jani Nikula jani.nikula at linux.intel.com
Wed May 7 11:04:54 UTC 2025


On Tue, 06 May 2025, Karthik Poosa <karthik.poosa at intel.com> wrote:
> 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)
>
> Signed-off-by: Karthik Poosa <karthik.poosa at intel.com>
> ---
>  drivers/gpu/drm/xe/regs/xe_pcode_regs.h |  5 +--
>  drivers/gpu/drm/xe/regs/xe_pmt.h        |  2 ++
>  drivers/gpu/drm/xe/xe_hwmon.c           | 46 +++++++++++++++++++------
>  drivers/gpu/drm/xe/xe_vsec.c            |  4 +--
>  drivers/gpu/drm/xe/xe_vsec.h            |  4 +++
>  5 files changed, 46 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h
> index c556a04670ee..c65d6ed470b5 100644
> --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h
> @@ -18,12 +18,13 @@
>  #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)
> +#define BMG_ENERGY_STATUS_PMT_OFFSET		(0x30)
> +#define	ENERGY_PKG				REG_GENMASK64(31, 0)
> +#define	ENERGY_CARD				REG_GENMASK64(63, 32)
>  
>  #endif /* _XE_PCODE_REGS_H_ */
> diff --git a/drivers/gpu/drm/xe/regs/xe_pmt.h b/drivers/gpu/drm/xe/regs/xe_pmt.h
> index f45abcd96ba8..ad91f6fef6bb 100644
> --- a/drivers/gpu/drm/xe/regs/xe_pmt.h
> +++ b/drivers/gpu/drm/xe/regs/xe_pmt.h
> @@ -10,6 +10,8 @@
>  #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_TELEMETRY_BASE_OFFSET	0xE0000
>  #define BMG_TELEMETRY_OFFSET		(SOC_BASE + BMG_TELEMETRY_BASE_OFFSET)
>  
> diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c
> index c0aa5587e855..a990f2c32449 100644
> --- a/drivers/gpu/drm/xe/xe_hwmon.c
> +++ b/drivers/gpu/drm/xe/xe_hwmon.c
> @@ -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,
> @@ -253,12 +255,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;
> @@ -441,9 +438,29 @@ 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));
> +		drm_dbg(&hwmon->xe->drm, "energy from pmt, ch %d read from mbx 0x%016llx, ret %d\n",
> +			channel, reg_val, ret);
> +
> +		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;
> @@ -919,11 +936,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;
>  	}
> @@ -1268,4 +1292,4 @@ int xe_hwmon_register(struct xe_device *xe)
>  
>  	return 0;
>  }
> -
> +MODULE_IMPORT_NS("INTEL_PMT_TELEMETRY");
> diff --git a/drivers/gpu/drm/xe/xe_vsec.c b/drivers/gpu/drm/xe/xe_vsec.c
> index b378848d3b7b..3e573b0b7ebd 100644
> --- a/drivers/gpu/drm/xe/xe_vsec.c
> +++ b/drivers/gpu/drm/xe/xe_vsec.c
> @@ -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;
> diff --git a/drivers/gpu/drm/xe/xe_vsec.h b/drivers/gpu/drm/xe/xe_vsec.h
> index 5777c53faec2..6d0db46d4700 100644
> --- a/drivers/gpu/drm/xe/xe_vsec.h
> +++ b/drivers/gpu/drm/xe/xe_vsec.h
> @@ -4,8 +4,12 @@
>  #ifndef _XE_VSEC_H_
>  #define _XE_VSEC_H_
>  
> +#include "linux/types.h"

<linux/types.h>

> +#include "linux/pci.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

-- 
Jani Nikula, Intel


More information about the Intel-xe mailing list