mirror of https://github.com/torvalds/linux.git
hwmon: (corsair-cpro) Add firmware and bootloader information
Add support for reporting firmware and bootloader version using debugfs. Update documentation accordingly. Signed-off-by: Marius Zachmann <mail@mariuszachmann.de> Link: https://lore.kernel.org/r/20240513194734.43040-2-mail@mariuszachmann.de Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
1613e604df
commit
5997eb60f8
|
|
@ -39,3 +39,11 @@ fan[1-6]_target Sets fan speed target rpm.
|
||||||
pwm[1-6] Sets the fan speed. Values from 0-255. Can only be read if pwm
|
pwm[1-6] Sets the fan speed. Values from 0-255. Can only be read if pwm
|
||||||
was set directly.
|
was set directly.
|
||||||
======================= =====================================================================
|
======================= =====================================================================
|
||||||
|
|
||||||
|
Debugfs entries
|
||||||
|
---------------
|
||||||
|
|
||||||
|
======================= ===================
|
||||||
|
firmware_version Firmware version
|
||||||
|
bootloader_version Bootloader version
|
||||||
|
======================= ===================
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,13 @@
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
#include <linux/hid.h>
|
#include <linux/hid.h>
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
@ -28,6 +30,8 @@
|
||||||
#define LABEL_LENGTH 11
|
#define LABEL_LENGTH 11
|
||||||
#define REQ_TIMEOUT 300
|
#define REQ_TIMEOUT 300
|
||||||
|
|
||||||
|
#define CTL_GET_FW_VER 0x02 /* returns the firmware version in bytes 1-3 */
|
||||||
|
#define CTL_GET_BL_VER 0x06 /* returns the bootloader version in bytes 1-2 */
|
||||||
#define CTL_GET_TMP_CNCT 0x10 /*
|
#define CTL_GET_TMP_CNCT 0x10 /*
|
||||||
* returns in bytes 1-4 for each temp sensor:
|
* returns in bytes 1-4 for each temp sensor:
|
||||||
* 0 not connected
|
* 0 not connected
|
||||||
|
|
@ -78,6 +82,7 @@
|
||||||
struct ccp_device {
|
struct ccp_device {
|
||||||
struct hid_device *hdev;
|
struct hid_device *hdev;
|
||||||
struct device *hwmon_dev;
|
struct device *hwmon_dev;
|
||||||
|
struct dentry *debugfs;
|
||||||
/* For reinitializing the completion below */
|
/* For reinitializing the completion below */
|
||||||
spinlock_t wait_input_report_lock;
|
spinlock_t wait_input_report_lock;
|
||||||
struct completion wait_input_report;
|
struct completion wait_input_report;
|
||||||
|
|
@ -88,6 +93,8 @@ struct ccp_device {
|
||||||
DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
|
DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
|
||||||
DECLARE_BITMAP(fan_cnct, NUM_FANS);
|
DECLARE_BITMAP(fan_cnct, NUM_FANS);
|
||||||
char fan_label[6][LABEL_LENGTH];
|
char fan_label[6][LABEL_LENGTH];
|
||||||
|
u8 firmware_ver[3];
|
||||||
|
u8 bootloader_ver[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* converts response error in buffer to errno */
|
/* converts response error in buffer to errno */
|
||||||
|
|
@ -496,6 +503,83 @@ static int get_temp_cnct(struct ccp_device *ccp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read firmware version */
|
||||||
|
static int get_fw_version(struct ccp_device *ccp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = send_usb_cmd(ccp, CTL_GET_FW_VER, 0, 0, 0);
|
||||||
|
if (ret) {
|
||||||
|
hid_notice(ccp->hdev, "Failed to read firmware version.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ccp->firmware_ver[0] = ccp->buffer[1];
|
||||||
|
ccp->firmware_ver[1] = ccp->buffer[2];
|
||||||
|
ccp->firmware_ver[2] = ccp->buffer[3];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read bootloader version */
|
||||||
|
static int get_bl_version(struct ccp_device *ccp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = send_usb_cmd(ccp, CTL_GET_BL_VER, 0, 0, 0);
|
||||||
|
if (ret) {
|
||||||
|
hid_notice(ccp->hdev, "Failed to read bootloader version.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ccp->bootloader_ver[0] = ccp->buffer[1];
|
||||||
|
ccp->bootloader_ver[1] = ccp->buffer[2];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int firmware_show(struct seq_file *seqf, void *unused)
|
||||||
|
{
|
||||||
|
struct ccp_device *ccp = seqf->private;
|
||||||
|
|
||||||
|
seq_printf(seqf, "%d.%d.%d\n",
|
||||||
|
ccp->firmware_ver[0],
|
||||||
|
ccp->firmware_ver[1],
|
||||||
|
ccp->firmware_ver[2]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(firmware);
|
||||||
|
|
||||||
|
static int bootloader_show(struct seq_file *seqf, void *unused)
|
||||||
|
{
|
||||||
|
struct ccp_device *ccp = seqf->private;
|
||||||
|
|
||||||
|
seq_printf(seqf, "%d.%d\n",
|
||||||
|
ccp->bootloader_ver[0],
|
||||||
|
ccp->bootloader_ver[1]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(bootloader);
|
||||||
|
|
||||||
|
static void ccp_debugfs_init(struct ccp_device *ccp)
|
||||||
|
{
|
||||||
|
char name[32];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
scnprintf(name, sizeof(name), "corsaircpro-%s", dev_name(&ccp->hdev->dev));
|
||||||
|
ccp->debugfs = debugfs_create_dir(name, NULL);
|
||||||
|
|
||||||
|
ret = get_fw_version(ccp);
|
||||||
|
if (!ret)
|
||||||
|
debugfs_create_file("firmware_version", 0444,
|
||||||
|
ccp->debugfs, ccp, &firmware_fops);
|
||||||
|
|
||||||
|
ret = get_bl_version(ccp);
|
||||||
|
if (!ret)
|
||||||
|
debugfs_create_file("bootloader_version", 0444,
|
||||||
|
ccp->debugfs, ccp, &bootloader_fops);
|
||||||
|
}
|
||||||
|
|
||||||
static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
struct ccp_device *ccp;
|
struct ccp_device *ccp;
|
||||||
|
|
@ -542,6 +626,9 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
ret = get_fan_cnct(ccp);
|
ret = get_fan_cnct(ccp);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_hw_close;
|
goto out_hw_close;
|
||||||
|
|
||||||
|
ccp_debugfs_init(ccp);
|
||||||
|
|
||||||
ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro",
|
ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro",
|
||||||
ccp, &ccp_chip_info, NULL);
|
ccp, &ccp_chip_info, NULL);
|
||||||
if (IS_ERR(ccp->hwmon_dev)) {
|
if (IS_ERR(ccp->hwmon_dev)) {
|
||||||
|
|
@ -562,6 +649,7 @@ static void ccp_remove(struct hid_device *hdev)
|
||||||
{
|
{
|
||||||
struct ccp_device *ccp = hid_get_drvdata(hdev);
|
struct ccp_device *ccp = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
|
debugfs_remove_recursive(ccp->debugfs);
|
||||||
hwmon_device_unregister(ccp->hwmon_dev);
|
hwmon_device_unregister(ccp->hwmon_dev);
|
||||||
hid_hw_close(hdev);
|
hid_hw_close(hdev);
|
||||||
hid_hw_stop(hdev);
|
hid_hw_stop(hdev);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue