Unverified Commit 0c5405d3 authored by Karthik Poosa's avatar Karthik Poosa Committed by Rodrigo Vivi
Browse files

drm/xe/hwmon: Read energy status from PMT



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: default avatarKarthik Poosa <karthik.poosa@intel.com>
Reviewed-by: default avatarBadal Nilawar <badal.nilawar@intel.com>
Link: https://lore.kernel.org/r/20250529163458.2354509-6-karthik.poosa@intel.com


Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 719d8a59
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -18,12 +18,10 @@
#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_ */
+5 −0
Original line number Diff line number Diff line
@@ -10,6 +10,11 @@
#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)

+38 −11
Original line number Diff line number Diff line
@@ -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;
	}

	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:
		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");
+2 −2
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ 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,
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);
+4 −0
Original line number Diff line number Diff line
@@ -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