* [PATCH v2 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods @ 2025-04-27 6:24 Kurt Borja via B4 Relay 2025-04-27 6:24 ` [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja via B4 Relay 2025-04-27 6:24 ` [PATCH v2 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja via B4 Relay 0 siblings, 2 replies; 6+ messages in thread From: Kurt Borja via B4 Relay @ 2025-04-27 6:24 UTC (permalink / raw) To: Hans de Goede, Ilpo Järvinen, Armin Wolf Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel, linux-kernel, Kurt Borja Hi all, I found a great blog post [1], which described the reverse engineering process of the GPIO control methods present on this device. In summary, these methods expose some debugging capabilities of the RGB lighting controller present on Dell gaming laptops. See [Patch 2] for more info. Exposing these methods to DebugFS is useful for developers exploring this RGB controllers (myself included). Thanks for your feedback! [1] https://gabriel.marcanobrady.family/blog/2024/12/16/dell-g5-5505-se-acpi-or-figuring-out-how-to-reset-the-rgb-controller/ Signed-off-by: Kurt Borja <kuurtb@gmail.com> --- Changes in v2: - Dropped module parameter - Added ABI documentation to Patch 1 - Small improvements to documentation based on Armin's comments - Improved Pin description table format - Link to v1: https://lore.kernel.org/r/20250423-awcc-gpio-v1-0-160a11bc3f9a@gmail.com --- Kurt Borja (2): platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Documentation: wmi: alienware-wmi: Add GPIO control documentation Documentation/ABI/testing/debugfs-alienware-wmi | 20 +++++ Documentation/wmi/devices/alienware-wmi.rst | 78 ++++++++++++++++- drivers/platform/x86/dell/alienware-wmi-wmax.c | 108 +++++++++++++++++++++++- 3 files changed, 201 insertions(+), 5 deletions(-) --- base-commit: 981527828c301644bc4014faa9c523e8a5e32a32 change-id: 20250413-awcc-gpio-24b1f5c546d2 Best regards, -- ~ Kurt ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods 2025-04-27 6:24 [PATCH v2 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods Kurt Borja via B4 Relay @ 2025-04-27 6:24 ` Kurt Borja via B4 Relay 2025-05-02 1:37 ` Armin Wolf 2025-04-27 6:24 ` [PATCH v2 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja via B4 Relay 1 sibling, 1 reply; 6+ messages in thread From: Kurt Borja via B4 Relay @ 2025-04-27 6:24 UTC (permalink / raw) To: Hans de Goede, Ilpo Järvinen, Armin Wolf Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel, linux-kernel, Kurt Borja From: Kurt Borja <kuurtb@gmail.com> Devices with the AWCC interface come with a USB RGB-lighting STM32 MCU, which has two GPIO pins with debug capabilities: - Device Firmware Update mode (DFU) - Negative Reset (NRST) The WMAX device has methods to toggle or read the state of these GPIO pins. Expose these methods through DebugFS, hidden behind an unsafe module parameter to avoid common users from toying with these without consideration. Suggested-by: Gabriel Marcano <gabemarcano@yahoo.com> Reviewed-by: Armin Wolf <W_Armin@gmx.de> Signed-off-by: Kurt Borja <kuurtb@gmail.com> --- Documentation/ABI/testing/debugfs-alienware-wmi | 20 +++++ drivers/platform/x86/dell/alienware-wmi-wmax.c | 108 +++++++++++++++++++++++- 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/debugfs-alienware-wmi b/Documentation/ABI/testing/debugfs-alienware-wmi index 48cfd4d0b002efd7b68d9c1d3aa91a3a05f49db5..d20b8627ac5f1528396549a81481e26889bc410e 100644 --- a/Documentation/ABI/testing/debugfs-alienware-wmi +++ b/Documentation/ABI/testing/debugfs-alienware-wmi @@ -42,3 +42,23 @@ Description: details. RO + +What: /sys/kernel/debug/alienware-wmi-<wmi_device_name>/gpio_ctl/total_gpios +Date: May 2025 +KernelVersion: 6.16 +Contact: Kurt Borja <kuurtb@gmail.com> +Description: + Total number of GPIO pins reported by the device. + + RO + +What: /sys/kernel/debug/alienware-wmi-<wmi_device_name>/gpio_ctl/<pin_name>_pin +Date: May 2025 +KernelVersion: 6.16 +Contact: Kurt Borja <kuurtb@gmail.com> +Description: + This file controls <pin_name> status. + + See Documentation/wmi/devices/alienware-wmi.rst for details. + + RW diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c index faeddfe3b79e0aa51e7c8c6b23aa4ac5c7218706..8e682427580a629f48530d7c926db4587352c04c 100644 --- a/drivers/platform/x86/dell/alienware-wmi-wmax.c +++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c @@ -38,6 +38,9 @@ #define AWCC_METHOD_GET_FAN_SENSORS 0x13 #define AWCC_METHOD_THERMAL_INFORMATION 0x14 #define AWCC_METHOD_THERMAL_CONTROL 0x15 +#define AWCC_METHOD_FWUP_GPIO_CONTROL 0x20 +#define AWCC_METHOD_READ_TOTAL_GPIOS 0x21 +#define AWCC_METHOD_READ_GPIO_STATUS 0x22 #define AWCC_METHOD_GAME_SHIFT_STATUS 0x25 #define AWCC_FAILURE_CODE 0xFFFFFFFF @@ -217,6 +220,11 @@ enum AWCC_TEMP_SENSOR_TYPES { AWCC_TEMP_SENSOR_GPU = 0x06, }; +enum AWCC_GPIO_PINS { + AWCC_GPIO_PIN_DFU = 0x00, + AWCC_GPIO_PIN_NRST = 0x01, +}; + enum awcc_thermal_profile { AWCC_PROFILE_USTT_BALANCED, AWCC_PROFILE_USTT_BALANCED_PERFORMANCE, @@ -571,6 +579,38 @@ static int awcc_thermal_information(struct wmi_device *wdev, u8 operation, u8 ar return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); } +static int awcc_fwup_gpio_control(struct wmi_device *wdev, u8 pin, u8 status) +{ + struct wmax_u32_args args = { + .operation = pin, + .arg1 = status, + .arg2 = 0, + .arg3 = 0, + }; + u32 out; + + return awcc_wmi_command(wdev, AWCC_METHOD_FWUP_GPIO_CONTROL, &args, &out); +} + +static int awcc_read_total_gpios(struct wmi_device *wdev, u32 *count) +{ + struct wmax_u32_args args = {}; + + return awcc_wmi_command(wdev, AWCC_METHOD_READ_TOTAL_GPIOS, &args, count); +} + +static int awcc_read_gpio_status(struct wmi_device *wdev, u8 pin, u32 *status) +{ + struct wmax_u32_args args = { + .operation = pin, + .arg1 = 0, + .arg2 = 0, + .arg3 = 0, + }; + + return awcc_wmi_command(wdev, AWCC_METHOD_READ_GPIO_STATUS, &args, status); +} + static int awcc_game_shift_status(struct wmi_device *wdev, u8 operation, u32 *out) { @@ -1318,6 +1358,63 @@ static int awcc_debugfs_pprof_data_read(struct seq_file *seq, void *data) return 0; } +static int awcc_debugfs_total_gpios_read(struct seq_file *seq, void *data) +{ + struct device *dev = seq->private; + struct wmi_device *wdev = to_wmi_device(dev); + u32 count; + int ret; + + ret = awcc_read_total_gpios(wdev, &count); + if (ret) + return ret; + + seq_printf(seq, "%u\n", count); + + return 0; +} + +static int awcc_gpio_pin_show(struct seq_file *seq, void *data) +{ + unsigned long pin = debugfs_get_aux_num(seq->file); + struct wmi_device *wdev = seq->private; + u32 status; + int ret; + + ret = awcc_read_gpio_status(wdev, pin, &status); + if (ret) + return ret; + + seq_printf(seq, "%u\n", status); + + return 0; +} + +static ssize_t awcc_gpio_pin_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned long pin = debugfs_get_aux_num(file); + struct seq_file *seq = file->private_data; + struct wmi_device *wdev = seq->private; + bool status; + int ret; + + if (!ppos || *ppos) + return -EINVAL; + + ret = kstrtobool_from_user(buf, count, &status); + if (ret) + return ret; + + ret = awcc_fwup_gpio_control(wdev, pin, status); + if (ret) + return ret; + + return count; +} + +DEFINE_SHOW_STORE_ATTRIBUTE(awcc_gpio_pin); + static void awcc_debugfs_remove(void *data) { struct dentry *root = data; @@ -1327,7 +1424,7 @@ static void awcc_debugfs_remove(void *data) static void awcc_debugfs_init(struct wmi_device *wdev) { - struct dentry *root; + struct dentry *root, *gpio_ctl; char name[64]; scnprintf(name, sizeof(name), "%s-%s", "alienware-wmi", dev_name(&wdev->dev)); @@ -1344,6 +1441,15 @@ static void awcc_debugfs_init(struct wmi_device *wdev) debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root, awcc_debugfs_pprof_data_read); + gpio_ctl = debugfs_create_dir("gpio_ctl", root); + + debugfs_create_devm_seqfile(&wdev->dev, "total_gpios", gpio_ctl, + awcc_debugfs_total_gpios_read); + debugfs_create_file_aux_num("dfu_pin", 0644, gpio_ctl, wdev, + AWCC_GPIO_PIN_DFU, &awcc_gpio_pin_fops); + debugfs_create_file_aux_num("nrst_pin", 0644, gpio_ctl, wdev, + AWCC_GPIO_PIN_NRST, &awcc_gpio_pin_fops); + devm_add_action_or_reset(&wdev->dev, awcc_debugfs_remove, root); } -- 2.49.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods 2025-04-27 6:24 ` [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja via B4 Relay @ 2025-05-02 1:37 ` Armin Wolf 2025-05-02 7:36 ` Kurt Borja 0 siblings, 1 reply; 6+ messages in thread From: Armin Wolf @ 2025-05-02 1:37 UTC (permalink / raw) To: kuurtb, Hans de Goede, Ilpo Järvinen Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel, linux-kernel Am 27.04.25 um 08:24 schrieb Kurt Borja via B4 Relay: > From: Kurt Borja <kuurtb@gmail.com> > > Devices with the AWCC interface come with a USB RGB-lighting STM32 MCU, > which has two GPIO pins with debug capabilities: > > - Device Firmware Update mode (DFU) > - Negative Reset (NRST) > > The WMAX device has methods to toggle or read the state of these GPIO > pins. Expose these methods through DebugFS, hidden behind an unsafe > module parameter to avoid common users from toying with these without > consideration. > > Suggested-by: Gabriel Marcano <gabemarcano@yahoo.com> > Reviewed-by: Armin Wolf <W_Armin@gmx.de> > Signed-off-by: Kurt Borja <kuurtb@gmail.com> > --- > Documentation/ABI/testing/debugfs-alienware-wmi | 20 +++++ > drivers/platform/x86/dell/alienware-wmi-wmax.c | 108 +++++++++++++++++++++++- > 2 files changed, 127 insertions(+), 1 deletion(-) > > diff --git a/Documentation/ABI/testing/debugfs-alienware-wmi b/Documentation/ABI/testing/debugfs-alienware-wmi > index 48cfd4d0b002efd7b68d9c1d3aa91a3a05f49db5..d20b8627ac5f1528396549a81481e26889bc410e 100644 > --- a/Documentation/ABI/testing/debugfs-alienware-wmi > +++ b/Documentation/ABI/testing/debugfs-alienware-wmi > @@ -42,3 +42,23 @@ Description: > details. > > RO > + > +What: /sys/kernel/debug/alienware-wmi-<wmi_device_name>/gpio_ctl/total_gpios > +Date: May 2025 > +KernelVersion: 6.16 > +Contact: Kurt Borja <kuurtb@gmail.com> > +Description: > + Total number of GPIO pins reported by the device. > + > + RO > + > +What: /sys/kernel/debug/alienware-wmi-<wmi_device_name>/gpio_ctl/<pin_name>_pin > +Date: May 2025 > +KernelVersion: 6.16 > +Contact: Kurt Borja <kuurtb@gmail.com> > +Description: > + This file controls <pin_name> status. > + > + See Documentation/wmi/devices/alienware-wmi.rst for details. > + > + RW > diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c > index faeddfe3b79e0aa51e7c8c6b23aa4ac5c7218706..8e682427580a629f48530d7c926db4587352c04c 100644 > --- a/drivers/platform/x86/dell/alienware-wmi-wmax.c > +++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c > @@ -38,6 +38,9 @@ > #define AWCC_METHOD_GET_FAN_SENSORS 0x13 > #define AWCC_METHOD_THERMAL_INFORMATION 0x14 > #define AWCC_METHOD_THERMAL_CONTROL 0x15 > +#define AWCC_METHOD_FWUP_GPIO_CONTROL 0x20 > +#define AWCC_METHOD_READ_TOTAL_GPIOS 0x21 > +#define AWCC_METHOD_READ_GPIO_STATUS 0x22 > #define AWCC_METHOD_GAME_SHIFT_STATUS 0x25 > > #define AWCC_FAILURE_CODE 0xFFFFFFFF > @@ -217,6 +220,11 @@ enum AWCC_TEMP_SENSOR_TYPES { > AWCC_TEMP_SENSOR_GPU = 0x06, > }; > > +enum AWCC_GPIO_PINS { > + AWCC_GPIO_PIN_DFU = 0x00, > + AWCC_GPIO_PIN_NRST = 0x01, > +}; > + > enum awcc_thermal_profile { > AWCC_PROFILE_USTT_BALANCED, > AWCC_PROFILE_USTT_BALANCED_PERFORMANCE, > @@ -571,6 +579,38 @@ static int awcc_thermal_information(struct wmi_device *wdev, u8 operation, u8 ar > return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); > } > > +static int awcc_fwup_gpio_control(struct wmi_device *wdev, u8 pin, u8 status) > +{ > + struct wmax_u32_args args = { > + .operation = pin, > + .arg1 = status, > + .arg2 = 0, > + .arg3 = 0, > + }; > + u32 out; > + > + return awcc_wmi_command(wdev, AWCC_METHOD_FWUP_GPIO_CONTROL, &args, &out); > +} > + > +static int awcc_read_total_gpios(struct wmi_device *wdev, u32 *count) > +{ > + struct wmax_u32_args args = {}; > + > + return awcc_wmi_command(wdev, AWCC_METHOD_READ_TOTAL_GPIOS, &args, count); > +} > + > +static int awcc_read_gpio_status(struct wmi_device *wdev, u8 pin, u32 *status) > +{ > + struct wmax_u32_args args = { > + .operation = pin, > + .arg1 = 0, > + .arg2 = 0, > + .arg3 = 0, > + }; > + > + return awcc_wmi_command(wdev, AWCC_METHOD_READ_GPIO_STATUS, &args, status); > +} > + > static int awcc_game_shift_status(struct wmi_device *wdev, u8 operation, > u32 *out) > { > @@ -1318,6 +1358,63 @@ static int awcc_debugfs_pprof_data_read(struct seq_file *seq, void *data) > return 0; > } > > +static int awcc_debugfs_total_gpios_read(struct seq_file *seq, void *data) > +{ > + struct device *dev = seq->private; > + struct wmi_device *wdev = to_wmi_device(dev); > + u32 count; > + int ret; > + > + ret = awcc_read_total_gpios(wdev, &count); > + if (ret) > + return ret; > + > + seq_printf(seq, "%u\n", count); > + > + return 0; > +} > + > +static int awcc_gpio_pin_show(struct seq_file *seq, void *data) > +{ > + unsigned long pin = debugfs_get_aux_num(seq->file); > + struct wmi_device *wdev = seq->private; > + u32 status; > + int ret; > + > + ret = awcc_read_gpio_status(wdev, pin, &status); > + if (ret) > + return ret; > + > + seq_printf(seq, "%u\n", status); > + > + return 0; > +} > + > +static ssize_t awcc_gpio_pin_write(struct file *file, const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + unsigned long pin = debugfs_get_aux_num(file); > + struct seq_file *seq = file->private_data; > + struct wmi_device *wdev = seq->private; > + bool status; > + int ret; > + > + if (!ppos || *ppos) > + return -EINVAL; > + > + ret = kstrtobool_from_user(buf, count, &status); > + if (ret) > + return ret; > + > + ret = awcc_fwup_gpio_control(wdev, pin, status); > + if (ret) > + return ret; > + > + return count; > +} > + > +DEFINE_SHOW_STORE_ATTRIBUTE(awcc_gpio_pin); > + > static void awcc_debugfs_remove(void *data) > { > struct dentry *root = data; > @@ -1327,7 +1424,7 @@ static void awcc_debugfs_remove(void *data) > > static void awcc_debugfs_init(struct wmi_device *wdev) > { > - struct dentry *root; > + struct dentry *root, *gpio_ctl; > char name[64]; > > scnprintf(name, sizeof(name), "%s-%s", "alienware-wmi", dev_name(&wdev->dev)); > @@ -1344,6 +1441,15 @@ static void awcc_debugfs_init(struct wmi_device *wdev) > debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root, > awcc_debugfs_pprof_data_read); > > + gpio_ctl = debugfs_create_dir("gpio_ctl", root); > + > + debugfs_create_devm_seqfile(&wdev->dev, "total_gpios", gpio_ctl, > + awcc_debugfs_total_gpios_read); > + debugfs_create_file_aux_num("dfu_pin", 0644, gpio_ctl, wdev, > + AWCC_GPIO_PIN_DFU, &awcc_gpio_pin_fops); > + debugfs_create_file_aux_num("nrst_pin", 0644, gpio_ctl, wdev, > + AWCC_GPIO_PIN_NRST, &awcc_gpio_pin_fops); I just noticed: what happens if the total number of GPIOs is greater than/lower than 2? Maybe you could instead name the debugfs files pinX with X being the pin number. Then you just have to create the debugfs files inside a for loop. What do you thing? Thanks, Armin Wolf > + > devm_add_action_or_reset(&wdev->dev, awcc_debugfs_remove, root); > } > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods 2025-05-02 1:37 ` Armin Wolf @ 2025-05-02 7:36 ` Kurt Borja 0 siblings, 0 replies; 6+ messages in thread From: Kurt Borja @ 2025-05-02 7:36 UTC (permalink / raw) To: Armin Wolf, Hans de Goede, Ilpo Järvinen Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel, linux-kernel On Thu May 1, 2025 at 10:37 PM -03, Armin Wolf wrote: > Am 27.04.25 um 08:24 schrieb Kurt Borja via B4 Relay: > >> From: Kurt Borja <kuurtb@gmail.com> >> >> Devices with the AWCC interface come with a USB RGB-lighting STM32 MCU, >> which has two GPIO pins with debug capabilities: >> >> - Device Firmware Update mode (DFU) >> - Negative Reset (NRST) >> >> The WMAX device has methods to toggle or read the state of these GPIO >> pins. Expose these methods through DebugFS, hidden behind an unsafe >> module parameter to avoid common users from toying with these without >> consideration. >> >> Suggested-by: Gabriel Marcano <gabemarcano@yahoo.com> >> Reviewed-by: Armin Wolf <W_Armin@gmx.de> >> Signed-off-by: Kurt Borja <kuurtb@gmail.com> >> --- >> Documentation/ABI/testing/debugfs-alienware-wmi | 20 +++++ >> drivers/platform/x86/dell/alienware-wmi-wmax.c | 108 +++++++++++++++++++++++- >> 2 files changed, 127 insertions(+), 1 deletion(-) >> >> diff --git a/Documentation/ABI/testing/debugfs-alienware-wmi b/Documentation/ABI/testing/debugfs-alienware-wmi >> index 48cfd4d0b002efd7b68d9c1d3aa91a3a05f49db5..d20b8627ac5f1528396549a81481e26889bc410e 100644 >> --- a/Documentation/ABI/testing/debugfs-alienware-wmi >> +++ b/Documentation/ABI/testing/debugfs-alienware-wmi >> @@ -42,3 +42,23 @@ Description: >> details. >> >> RO >> + >> +What: /sys/kernel/debug/alienware-wmi-<wmi_device_name>/gpio_ctl/total_gpios >> +Date: May 2025 >> +KernelVersion: 6.16 >> +Contact: Kurt Borja <kuurtb@gmail.com> >> +Description: >> + Total number of GPIO pins reported by the device. >> + >> + RO >> + >> +What: /sys/kernel/debug/alienware-wmi-<wmi_device_name>/gpio_ctl/<pin_name>_pin >> +Date: May 2025 >> +KernelVersion: 6.16 >> +Contact: Kurt Borja <kuurtb@gmail.com> >> +Description: >> + This file controls <pin_name> status. >> + >> + See Documentation/wmi/devices/alienware-wmi.rst for details. >> + >> + RW >> diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c >> index faeddfe3b79e0aa51e7c8c6b23aa4ac5c7218706..8e682427580a629f48530d7c926db4587352c04c 100644 >> --- a/drivers/platform/x86/dell/alienware-wmi-wmax.c >> +++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c >> @@ -38,6 +38,9 @@ >> #define AWCC_METHOD_GET_FAN_SENSORS 0x13 >> #define AWCC_METHOD_THERMAL_INFORMATION 0x14 >> #define AWCC_METHOD_THERMAL_CONTROL 0x15 >> +#define AWCC_METHOD_FWUP_GPIO_CONTROL 0x20 >> +#define AWCC_METHOD_READ_TOTAL_GPIOS 0x21 >> +#define AWCC_METHOD_READ_GPIO_STATUS 0x22 >> #define AWCC_METHOD_GAME_SHIFT_STATUS 0x25 >> >> #define AWCC_FAILURE_CODE 0xFFFFFFFF >> @@ -217,6 +220,11 @@ enum AWCC_TEMP_SENSOR_TYPES { >> AWCC_TEMP_SENSOR_GPU = 0x06, >> }; >> >> +enum AWCC_GPIO_PINS { >> + AWCC_GPIO_PIN_DFU = 0x00, >> + AWCC_GPIO_PIN_NRST = 0x01, >> +}; >> + >> enum awcc_thermal_profile { >> AWCC_PROFILE_USTT_BALANCED, >> AWCC_PROFILE_USTT_BALANCED_PERFORMANCE, >> @@ -571,6 +579,38 @@ static int awcc_thermal_information(struct wmi_device *wdev, u8 operation, u8 ar >> return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); >> } >> >> +static int awcc_fwup_gpio_control(struct wmi_device *wdev, u8 pin, u8 status) >> +{ >> + struct wmax_u32_args args = { >> + .operation = pin, >> + .arg1 = status, >> + .arg2 = 0, >> + .arg3 = 0, >> + }; >> + u32 out; >> + >> + return awcc_wmi_command(wdev, AWCC_METHOD_FWUP_GPIO_CONTROL, &args, &out); >> +} >> + >> +static int awcc_read_total_gpios(struct wmi_device *wdev, u32 *count) >> +{ >> + struct wmax_u32_args args = {}; >> + >> + return awcc_wmi_command(wdev, AWCC_METHOD_READ_TOTAL_GPIOS, &args, count); >> +} >> + >> +static int awcc_read_gpio_status(struct wmi_device *wdev, u8 pin, u32 *status) >> +{ >> + struct wmax_u32_args args = { >> + .operation = pin, >> + .arg1 = 0, >> + .arg2 = 0, >> + .arg3 = 0, >> + }; >> + >> + return awcc_wmi_command(wdev, AWCC_METHOD_READ_GPIO_STATUS, &args, status); >> +} >> + >> static int awcc_game_shift_status(struct wmi_device *wdev, u8 operation, >> u32 *out) >> { >> @@ -1318,6 +1358,63 @@ static int awcc_debugfs_pprof_data_read(struct seq_file *seq, void *data) >> return 0; >> } >> >> +static int awcc_debugfs_total_gpios_read(struct seq_file *seq, void *data) >> +{ >> + struct device *dev = seq->private; >> + struct wmi_device *wdev = to_wmi_device(dev); >> + u32 count; >> + int ret; >> + >> + ret = awcc_read_total_gpios(wdev, &count); >> + if (ret) >> + return ret; >> + >> + seq_printf(seq, "%u\n", count); >> + >> + return 0; >> +} >> + >> +static int awcc_gpio_pin_show(struct seq_file *seq, void *data) >> +{ >> + unsigned long pin = debugfs_get_aux_num(seq->file); >> + struct wmi_device *wdev = seq->private; >> + u32 status; >> + int ret; >> + >> + ret = awcc_read_gpio_status(wdev, pin, &status); >> + if (ret) >> + return ret; >> + >> + seq_printf(seq, "%u\n", status); >> + >> + return 0; >> +} >> + >> +static ssize_t awcc_gpio_pin_write(struct file *file, const char __user *buf, >> + size_t count, loff_t *ppos) >> +{ >> + unsigned long pin = debugfs_get_aux_num(file); >> + struct seq_file *seq = file->private_data; >> + struct wmi_device *wdev = seq->private; >> + bool status; >> + int ret; >> + >> + if (!ppos || *ppos) >> + return -EINVAL; >> + >> + ret = kstrtobool_from_user(buf, count, &status); >> + if (ret) >> + return ret; >> + >> + ret = awcc_fwup_gpio_control(wdev, pin, status); >> + if (ret) >> + return ret; >> + >> + return count; >> +} >> + >> +DEFINE_SHOW_STORE_ATTRIBUTE(awcc_gpio_pin); >> + >> static void awcc_debugfs_remove(void *data) >> { >> struct dentry *root = data; >> @@ -1327,7 +1424,7 @@ static void awcc_debugfs_remove(void *data) >> >> static void awcc_debugfs_init(struct wmi_device *wdev) >> { >> - struct dentry *root; >> + struct dentry *root, *gpio_ctl; >> char name[64]; >> >> scnprintf(name, sizeof(name), "%s-%s", "alienware-wmi", dev_name(&wdev->dev)); >> @@ -1344,6 +1441,15 @@ static void awcc_debugfs_init(struct wmi_device *wdev) >> debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root, >> awcc_debugfs_pprof_data_read); >> >> + gpio_ctl = debugfs_create_dir("gpio_ctl", root); >> + >> + debugfs_create_devm_seqfile(&wdev->dev, "total_gpios", gpio_ctl, >> + awcc_debugfs_total_gpios_read); >> + debugfs_create_file_aux_num("dfu_pin", 0644, gpio_ctl, wdev, >> + AWCC_GPIO_PIN_DFU, &awcc_gpio_pin_fops); >> + debugfs_create_file_aux_num("nrst_pin", 0644, gpio_ctl, wdev, >> + AWCC_GPIO_PIN_NRST, &awcc_gpio_pin_fops); > > I just noticed: what happens if the total number of GPIOs is greater than/lower than 2? > > Maybe you could instead name the debugfs files pinX with X being the pin number. Then you just > have to create the debugfs files inside a for loop. > > What do you thing? Hi Armin, I was a bit reluctant when I first made the patch because I wanted to keep things simple. I haven't seen any laptop with a GPIO count \neq 2, however some ACPI implementations of this method don't handle invalid values very well, so I'll take this approach just in case. Thanks for your comments! -- ~ Kurt > > Thanks, > Armin Wolf > >> + >> devm_add_action_or_reset(&wdev->dev, awcc_debugfs_remove, root); >> } >> >> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation 2025-04-27 6:24 [PATCH v2 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods Kurt Borja via B4 Relay 2025-04-27 6:24 ` [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja via B4 Relay @ 2025-04-27 6:24 ` Kurt Borja via B4 Relay 2025-05-02 1:32 ` Armin Wolf 1 sibling, 1 reply; 6+ messages in thread From: Kurt Borja via B4 Relay @ 2025-04-27 6:24 UTC (permalink / raw) To: Hans de Goede, Ilpo Järvinen, Armin Wolf Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel, linux-kernel, Kurt Borja From: Kurt Borja <kuurtb@gmail.com> Add documentation for the GPIO control methods. Signed-off-by: Kurt Borja <kuurtb@gmail.com> --- Documentation/wmi/devices/alienware-wmi.rst | 78 +++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/Documentation/wmi/devices/alienware-wmi.rst b/Documentation/wmi/devices/alienware-wmi.rst index 79238051b18bc5de9b502325017cd5c5fcf41748..2a6052efb9ae0e3fe0a5d9d5775073234dfc96fb 100644 --- a/Documentation/wmi/devices/alienware-wmi.rst +++ b/Documentation/wmi/devices/alienware-wmi.rst @@ -231,6 +231,70 @@ WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) AWCC supports memory overclocking, but this method is very intricate and has not been deciphered yet. +GPIO control Methods +==================== + +Alienware and Dell G Series devices with the AWCC interface usually have an +embedded STM32 RGB lighting controller with USB/HID capabilities. It's vendor ID +is ``187c`` while it's product ID may vary from model to model. + +The control of two GPIO pins of this MCU is exposed as WMI methods for debugging +purposes. + ++--------------+--------------------------------------------------------------+ +| Pin | Description | ++==============+===============================+==============================+ +| 0 | Device Firmware Update (DFU) | **HIGH**: Enables DFU mode | +| | mode pin. | on next MCU boot. | +| | +------------------------------+ +| | | **LOW**: Disables DFU mode | +| | | on next MCU boot. | ++--------------+-------------------------------+------------------------------+ +| 1 | Negative Reset (NRST) pin. | **HIGH**: MCU is ON. | +| | | | +| | +------------------------------+ +| | | **LOW**: MCU is OFF. | +| | | | ++--------------+-------------------------------+------------------------------+ + +See :ref:`acknowledgements` for more information on this MCU. + +.. note:: + Some GPIO control methods break the usual argument structure and take a + **Pin number** instead of an operation on the first byte. + +WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) +------------------------------------------------------------------ + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| Pin number | Set the pin status | - Byte 1: Pin | +| | | status | ++--------------------+------------------------------------+--------------------+ + +WMI method ReadTotalofGPIOs([out] uint32 argr) +---------------------------------------------- + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| 0x00 | Get the total number of GPIOs | - None | ++--------------------+------------------------------------+--------------------+ + +WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) +------------------------------------------------------------------ + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| Pin number | Get the pin status | - None | ++--------------------+------------------------------------+--------------------+ + +.. note:: + There known firmware bug in some laptops where reading the status of a pin + also flips it. + Other information Methods ========================= @@ -239,10 +303,16 @@ WMI method ReadChassisColor([out] uint32 argr) Returns the chassis color internal ID. +.. _acknowledgements: + Acknowledgements ================ -Kudos to `AlexIII <https://github.com/AlexIII/tcc-g15>`_ and -`T-Troll <https://github.com/T-Troll/alienfx-tools/>`_ for documenting and -testing some of this device's functionality, making it possible to generalize -this driver. +Kudos to + +* `AlexIII <https://github.com/AlexIII/tcc-g15>`_ +* `T-Troll <https://github.com/T-Troll/alienfx-tools/>`_ +* `Gabriel Marcano <https://gabriel.marcanobrady.family/blog/2024/12/16/dell-g5-5505-se-acpi-or-figuring-out-how-to-reset-the-rgb-controller/>`_ + +for documenting and testing some of this device's functionality, making it +possible to generalize this driver. -- 2.49.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation 2025-04-27 6:24 ` [PATCH v2 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja via B4 Relay @ 2025-05-02 1:32 ` Armin Wolf 0 siblings, 0 replies; 6+ messages in thread From: Armin Wolf @ 2025-05-02 1:32 UTC (permalink / raw) To: kuurtb, Hans de Goede, Ilpo Järvinen Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel, linux-kernel Am 27.04.25 um 08:24 schrieb Kurt Borja via B4 Relay: > From: Kurt Borja <kuurtb@gmail.com> > > Add documentation for the GPIO control methods. > > Signed-off-by: Kurt Borja <kuurtb@gmail.com> > --- > Documentation/wmi/devices/alienware-wmi.rst | 78 +++++++++++++++++++++++++++-- > 1 file changed, 74 insertions(+), 4 deletions(-) > > diff --git a/Documentation/wmi/devices/alienware-wmi.rst b/Documentation/wmi/devices/alienware-wmi.rst > index 79238051b18bc5de9b502325017cd5c5fcf41748..2a6052efb9ae0e3fe0a5d9d5775073234dfc96fb 100644 > --- a/Documentation/wmi/devices/alienware-wmi.rst > +++ b/Documentation/wmi/devices/alienware-wmi.rst > @@ -231,6 +231,70 @@ WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) > AWCC supports memory overclocking, but this method is very intricate and has > not been deciphered yet. > > +GPIO control Methods > +==================== > + > +Alienware and Dell G Series devices with the AWCC interface usually have an > +embedded STM32 RGB lighting controller with USB/HID capabilities. It's vendor ID > +is ``187c`` while it's product ID may vary from model to model. > + > +The control of two GPIO pins of this MCU is exposed as WMI methods for debugging > +purposes. > + > ++--------------+--------------------------------------------------------------+ > +| Pin | Description | > ++==============+===============================+==============================+ > +| 0 | Device Firmware Update (DFU) | **HIGH**: Enables DFU mode | > +| | mode pin. | on next MCU boot. | > +| | +------------------------------+ > +| | | **LOW**: Disables DFU mode | > +| | | on next MCU boot. | > ++--------------+-------------------------------+------------------------------+ > +| 1 | Negative Reset (NRST) pin. | **HIGH**: MCU is ON. | > +| | | | > +| | +------------------------------+ > +| | | **LOW**: MCU is OFF. | > +| | | | > ++--------------+-------------------------------+------------------------------+ > + > +See :ref:`acknowledgements` for more information on this MCU. > + > +.. note:: > + Some GPIO control methods break the usual argument structure and take a > + **Pin number** instead of an operation on the first byte. > + > +WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) > +------------------------------------------------------------------ > + > ++--------------------+------------------------------------+--------------------+ > +| Operation (Byte 0) | Description | Arguments | > ++====================+====================================+====================+ > +| Pin number | Set the pin status | - Byte 1: Pin | > +| | | status | > ++--------------------+------------------------------------+--------------------+ > + > +WMI method ReadTotalofGPIOs([out] uint32 argr) > +---------------------------------------------- > + > ++--------------------+------------------------------------+--------------------+ > +| Operation (Byte 0) | Description | Arguments | > ++====================+====================================+====================+ > +| 0x00 | Get the total number of GPIOs | - None | > ++--------------------+------------------------------------+--------------------+ Maybe you should write that the "Operation" byte is theoretically not necessary for this WMI method, but that we still have to provide a dummy value or else the firmware will encounter an error. Take a look at the documentation for the msi-wmi-platform driver for details (grep for "CreateByteField()"). Other than that: Reviewed-by: Armin Wolf <W_Armin@gmx.de> > + > +WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) > +------------------------------------------------------------------ > + > ++--------------------+------------------------------------+--------------------+ > +| Operation (Byte 0) | Description | Arguments | > ++====================+====================================+====================+ > +| Pin number | Get the pin status | - None | > ++--------------------+------------------------------------+--------------------+ > + > +.. note:: > + There known firmware bug in some laptops where reading the status of a pin > + also flips it. > + > Other information Methods > ========================= > > @@ -239,10 +303,16 @@ WMI method ReadChassisColor([out] uint32 argr) > > Returns the chassis color internal ID. > > +.. _acknowledgements: > + > Acknowledgements > ================ > > -Kudos to `AlexIII <https://github.com/AlexIII/tcc-g15>`_ and > -`T-Troll <https://github.com/T-Troll/alienfx-tools/>`_ for documenting and > -testing some of this device's functionality, making it possible to generalize > -this driver. > +Kudos to > + > +* `AlexIII <https://github.com/AlexIII/tcc-g15>`_ > +* `T-Troll <https://github.com/T-Troll/alienfx-tools/>`_ > +* `Gabriel Marcano <https://gabriel.marcanobrady.family/blog/2024/12/16/dell-g5-5505-se-acpi-or-figuring-out-how-to-reset-the-rgb-controller/>`_ > + > +for documenting and testing some of this device's functionality, making it > +possible to generalize this driver. > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-05-02 7:36 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-27 6:24 [PATCH v2 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods Kurt Borja via B4 Relay 2025-04-27 6:24 ` [PATCH v2 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja via B4 Relay 2025-05-02 1:37 ` Armin Wolf 2025-05-02 7:36 ` Kurt Borja 2025-04-27 6:24 ` [PATCH v2 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja via B4 Relay 2025-05-02 1:32 ` Armin Wolf
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).