@@ -208,6 +208,9 @@ i915-y += gt/uc/intel_uc.o \
# graphics system controller (GSC) support
i915-y += gt/intel_gsc.o
+# graphics hardware monitoring (HWMON) support
+i915-$(CONFIG_HWMON) += i915_hwmon.o
+
# modesetting core code
i915-y += \
display/hsw_ips.o \
@@ -80,6 +80,7 @@
#include "i915_drm_client.h"
#include "i915_drv.h"
#include "i915_getparam.h"
+#include "i915_hwmon.h"
#include "i915_ioc32.h"
#include "i915_ioctl.h"
#include "i915_irq.h"
@@ -721,6 +722,9 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
intel_gt_driver_register(to_gt(dev_priv));
+#ifdef CONFIG_HWMON
+ i915_hwmon_register(dev_priv);
+#endif
intel_display_driver_register(dev_priv);
intel_power_domains_enable(dev_priv);
@@ -747,6 +751,9 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
intel_display_driver_unregister(dev_priv);
+#ifdef CONFIG_HWMON
+ i915_hwmon_unregister(dev_priv);
+#endif
intel_gt_driver_unregister(to_gt(dev_priv));
i915_perf_unregister(dev_priv);
@@ -705,6 +705,8 @@ struct drm_i915_private {
struct i915_perf perf;
+ struct i915_hwmon *hwmon;
+
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
struct intel_gt gt0;
new file mode 100644
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/*
+ * Power-related hwmon entries.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/types.h>
+
+#include "i915_hwmon.h"
+#include "i915_drv.h"
+#include "intel_mchbar_regs.h"
+
+
+struct i915_hwmon_reg {
+};
+
+struct i915_hwmon_drvdata {
+ struct i915_hwmon *hwmon;
+ struct intel_uncore *uncore;
+ struct device *hwmon_dev;
+ char name[12];
+};
+
+struct i915_hwmon {
+ struct i915_hwmon_drvdata ddat;
+ struct mutex hwmon_lock; /* counter overflow logic and rmw */
+ struct i915_hwmon_reg rg;
+};
+
+static struct attribute *hwmon_attributes[] = {
+ NULL
+};
+
+static umode_t hwmon_attributes_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ return 0;
+}
+
+static const struct attribute_group hwmon_attrgroup = {
+ .attrs = hwmon_attributes,
+ .is_visible = hwmon_attributes_visible,
+};
+
+static const struct attribute_group *hwmon_groups[] = {
+ &hwmon_attrgroup,
+ NULL
+};
+
+
+static const struct hwmon_channel_info *i915_info[] = {
+ NULL
+};
+
+static umode_t
+i915_is_visible(const void *drvdata, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ default:
+ return 0;
+ }
+}
+
+static int
+i915_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long *val)
+{
+ switch (type) {
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+i915_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long val)
+{
+ switch (type) {
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct hwmon_ops i915_hwmon_ops = {
+ .is_visible = i915_is_visible,
+ .read = i915_read,
+ .write = i915_write,
+};
+
+static const struct hwmon_chip_info i915_chip_info = {
+ .ops = &i915_hwmon_ops,
+ .info = i915_info,
+};
+
+static void
+i915_hwmon_get_preregistration_info(struct drm_i915_private *i915)
+{
+
+}
+
+void i915_hwmon_register(struct drm_i915_private *i915)
+{
+ struct device *dev = i915->drm.dev;
+ struct i915_hwmon *hwmon;
+ struct device *hwmon_dev;
+ struct i915_hwmon_drvdata *ddat;
+
+ hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
+ if (!hwmon)
+ return;
+
+ i915->hwmon = hwmon;
+
+ mutex_init(&hwmon->hwmon_lock);
+
+ ddat = &hwmon->ddat;
+
+ ddat->hwmon = hwmon;
+ ddat->uncore = &i915->uncore;
+ snprintf(ddat->name, sizeof(ddat->name), "i915");
+
+ i915_hwmon_get_preregistration_info(i915);
+
+ /* hwmon_dev points to device hwmon<i> */
+ hwmon_dev = hwmon_device_register_with_info(dev, ddat->name,
+ ddat,
+ &i915_chip_info,
+ hwmon_groups);
+
+ if (IS_ERR(hwmon_dev)) {
+ mutex_destroy(&hwmon->hwmon_lock);
+ i915->hwmon = NULL;
+ kfree(hwmon);
+ return;
+ }
+
+ ddat->hwmon_dev = hwmon_dev;
+}
+
+void i915_hwmon_unregister(struct drm_i915_private *i915)
+{
+ struct i915_hwmon *hwmon;
+ struct i915_hwmon_drvdata *ddat;
+
+ hwmon = fetch_and_zero(&i915->hwmon);
+ if (!hwmon)
+ return;
+
+ ddat = &hwmon->ddat;
+
+ if (ddat->hwmon_dev)
+ hwmon_device_unregister(ddat->hwmon_dev);
+
+ mutex_destroy(&hwmon->hwmon_lock);
+
+ kfree(hwmon);
+}
new file mode 100644
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: MIT */
+
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __I915_HWMON_H__
+#define __I915_HWMON_H__
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include "i915_reg.h"
+
+struct drm_i915_private;
+struct i915_hwmon;
+
+void i915_hwmon_register(struct drm_i915_private *i915);
+void i915_hwmon_unregister(struct drm_i915_private *i915);
+
+#endif /* __I915_HWMON_H__ */