All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods
@ 2025-04-23  7:49 Kurt Borja
  2025-04-23  7:49 ` [PATCH 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja
  2025-04-23  7:49 ` [PATCH 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja
  0 siblings, 2 replies; 6+ messages in thread
From: Kurt Borja @ 2025-04-23  7:49 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>
---
Kurt Borja (2):
      platform/x86: alienware-wmi-wmax: Expose GPIO debug methods
      Documentation: wmi: alienware-wmi: Add GPIO control documentation

 Documentation/wmi/devices/alienware-wmi.rst    |  85 +++++++++++++++++-
 drivers/platform/x86/dell/alienware-wmi-wmax.c | 116 ++++++++++++++++++++++++-
 2 files changed, 196 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 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods
  2025-04-23  7:49 [PATCH 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods Kurt Borja
@ 2025-04-23  7:49 ` Kurt Borja
  2025-04-27  1:07   ` Armin Wolf
  2025-04-23  7:49 ` [PATCH 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja
  1 sibling, 1 reply; 6+ messages in thread
From: Kurt Borja @ 2025-04-23  7:49 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

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>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
 drivers/platform/x86/dell/alienware-wmi-wmax.c | 116 ++++++++++++++++++++++++-
 1 file changed, 115 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
index faeddfe3b79e0aa51e7c8c6b23aa4ac5c7218706..2e83be02d7c5f8ca8176f1ec39d9929790da0844 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
@@ -65,6 +68,10 @@ static bool force_gmode;
 module_param_unsafe(force_gmode, bool, 0);
 MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
 
+static bool gpio_debug;
+module_param_unsafe(gpio_debug, bool, 0);
+MODULE_PARM_DESC(gpio_debug, "Exposes GPIO debug methods to DebugFS");
+
 struct awcc_quirks {
 	bool hwmon;
 	bool pprof;
@@ -217,6 +224,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 +583,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 +1362,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 +1428,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 +1445,19 @@ static void awcc_debugfs_init(struct wmi_device *wdev)
 		debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root,
 					    awcc_debugfs_pprof_data_read);
 
+	if (gpio_debug) {
+		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

* [PATCH 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation
  2025-04-23  7:49 [PATCH 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods Kurt Borja
  2025-04-23  7:49 ` [PATCH 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja
@ 2025-04-23  7:49 ` Kurt Borja
  2025-04-27  1:01   ` Armin Wolf
  1 sibling, 1 reply; 6+ messages in thread
From: Kurt Borja @ 2025-04-23  7:49 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

Add documentation for the GPIO control methods.

Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
 Documentation/wmi/devices/alienware-wmi.rst | 85 +++++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 4 deletions(-)

diff --git a/Documentation/wmi/devices/alienware-wmi.rst b/Documentation/wmi/devices/alienware-wmi.rst
index 79238051b18bc5de9b502325017cd5c5fcf41748..8751199834b8e2a3a4abf2b735e4ac6067d93c6d 100644
--- a/Documentation/wmi/devices/alienware-wmi.rst
+++ b/Documentation/wmi/devices/alienware-wmi.rst
@@ -231,6 +231,77 @@ 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) mode pin.                       |
+|              |                                                              |
+|              | **HIGH**: Enables DFU mode on next MCU boot.                 |
+|              |                                                              |
+|              | **LOW**: Disables DFU mode on next MCU boot. (default)       |
++--------------+--------------------------------------------------------------+
+| 1            | Negative Reset (NRST) pin.                                   |
+|              |                                                              |
+|              | **HIGH**: Turn on MCU. (default)                             |
+|              |                                                              |
+|              | **LOW**: Turn off MCU.                                       |
++--------------+--------------------------------------------------------------+
+
+See :ref:`acknowledgements` for more information on this MCU.
+
+.. warning::
+   The following methods are only exposed to DebugFS if the ``gpio_debug``
+   unsafe module parameter is set, as you could end up bricking the MCU.
+
+WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr)
+------------------------------------------------------------------
+
++--------------------+------------------------------------+--------------------+
+| Operation (Byte 0) | Description                        | Arguments          |
++====================+====================================+====================+
+| 0x00               | Set the Device Firmware Update     | - Byte 1: Pin      |
+|                    | (DFU) pin status.                  |   status           |
++--------------------+------------------------------------+--------------------+
+| 0x01               | Set the Negative Reset (NRST) pin  | - Byte 1: Pin      |
+|                    | status.                            |   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          |
++====================+====================================+====================+
+| 0x00               | Get the Device Firmware Update     | - None             |
+|                    | (DFU) pin status.                  |                    |
++--------------------+------------------------------------+--------------------+
+| 0x01               | Get the Negative Reset (NRST) pin  | - None             |
+|                    | status.                            |                    |
++--------------------+------------------------------------+--------------------+
+
+.. warning::
+   There known firmware bug in some laptops where reading the status of a pin
+   also flips it.
+
 Other information Methods
 =========================
 
@@ -239,10 +310,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 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation
  2025-04-23  7:49 ` [PATCH 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja
@ 2025-04-27  1:01   ` Armin Wolf
  0 siblings, 0 replies; 6+ messages in thread
From: Armin Wolf @ 2025-04-27  1:01 UTC (permalink / raw)
  To: Kurt Borja, Hans de Goede, Ilpo Järvinen
  Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel,
	linux-kernel

Am 23.04.25 um 09:49 schrieb Kurt Borja:

> Add documentation for the GPIO control methods.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
>   Documentation/wmi/devices/alienware-wmi.rst | 85 +++++++++++++++++++++++++++--
>   1 file changed, 81 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/wmi/devices/alienware-wmi.rst b/Documentation/wmi/devices/alienware-wmi.rst
> index 79238051b18bc5de9b502325017cd5c5fcf41748..8751199834b8e2a3a4abf2b735e4ac6067d93c6d 100644
> --- a/Documentation/wmi/devices/alienware-wmi.rst
> +++ b/Documentation/wmi/devices/alienware-wmi.rst
> @@ -231,6 +231,77 @@ 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

Hi,

please remove the comma.

> +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) mode pin.                       |
> +|              |                                                              |
> +|              | **HIGH**: Enables DFU mode on next MCU boot.                 |
> +|              |                                                              |
> +|              | **LOW**: Disables DFU mode on next MCU boot. (default)       |
> ++--------------+--------------------------------------------------------------+
> +| 1            | Negative Reset (NRST) pin.                                   |
> +|              |                                                              |
> +|              | **HIGH**: Turn on MCU. (default)                             |
> +|              |                                                              |
> +|              | **LOW**: Turn off MCU.                                       |
> ++--------------+--------------------------------------------------------------+
> +
> +See :ref:`acknowledgements` for more information on this MCU.
> +
> +.. warning::
> +   The following methods are only exposed to DebugFS if the ``gpio_debug``
> +   unsafe module parameter is set, as you could end up bricking the MCU.
> +
> +WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr)
> +------------------------------------------------------------------
> +
> ++--------------------+------------------------------------+--------------------+
> +| Operation (Byte 0) | Description                        | Arguments          |
> ++====================+====================================+====================+
> +| 0x00               | Set the Device Firmware Update     | - Byte 1: Pin      |
> +|                    | (DFU) pin status.                  |   status           |
> ++--------------------+------------------------------------+--------------------+
> +| 0x01               | Set the Negative Reset (NRST) pin  | - Byte 1: Pin      |
> +|                    | status.                            |   status           |
> ++--------------------+------------------------------------+--------------------+

Maybe it would be better if you just explain that the operation byte selects the GPIO pin to toggle.

> +
> +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          |
> ++====================+====================================+====================+
> +| 0x00               | Get the Device Firmware Update     | - None             |
> +|                    | (DFU) pin status.                  |                    |
> ++--------------------+------------------------------------+--------------------+
> +| 0x01               | Get the Negative Reset (NRST) pin  | - None             |
> +|                    | status.                            |                    |
> ++--------------------+------------------------------------+--------------------+

Same as above.

Thanks,
Armin Wolf

> +
> +.. warning::
> +   There known firmware bug in some laptops where reading the status of a pin
> +   also flips it.
> +
>   Other information Methods
>   =========================
>   
> @@ -239,10 +310,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

* Re: [PATCH 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods
  2025-04-23  7:49 ` [PATCH 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja
@ 2025-04-27  1:07   ` Armin Wolf
  2025-04-27  6:21     ` Kurt Borja
  0 siblings, 1 reply; 6+ messages in thread
From: Armin Wolf @ 2025-04-27  1:07 UTC (permalink / raw)
  To: Kurt Borja, Hans de Goede, Ilpo Järvinen
  Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel,
	linux-kernel

Am 23.04.25 um 09:49 schrieb Kurt Borja:

> 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>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
>   drivers/platform/x86/dell/alienware-wmi-wmax.c | 116 ++++++++++++++++++++++++-
>   1 file changed, 115 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
> index faeddfe3b79e0aa51e7c8c6b23aa4ac5c7218706..2e83be02d7c5f8ca8176f1ec39d9929790da0844 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
> @@ -65,6 +68,10 @@ static bool force_gmode;
>   module_param_unsafe(force_gmode, bool, 0);
>   MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
>   
> +static bool gpio_debug;
> +module_param_unsafe(gpio_debug, bool, 0);
> +MODULE_PARM_DESC(gpio_debug, "Exposes GPIO debug methods to DebugFS");

Hi,

personally i thing that you can drop this module parameter. People using DebugFS should
already know that they need to be careful.

Other than that:
Reviewed-by: Armin Wolf <W_Armin@gmx.de>

> +
>   struct awcc_quirks {
>   	bool hwmon;
>   	bool pprof;
> @@ -217,6 +224,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 +583,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 +1362,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 +1428,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 +1445,19 @@ static void awcc_debugfs_init(struct wmi_device *wdev)
>   		debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root,
>   					    awcc_debugfs_pprof_data_read);
>   
> +	if (gpio_debug) {
> +		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);
>   }
>   
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods
  2025-04-27  1:07   ` Armin Wolf
@ 2025-04-27  6:21     ` Kurt Borja
  0 siblings, 0 replies; 6+ messages in thread
From: Kurt Borja @ 2025-04-27  6:21 UTC (permalink / raw)
  To: Armin Wolf, Hans de Goede, Ilpo Järvinen
  Cc: Gabriel Marcano, platform-driver-x86, Dell.Client.Kernel,
	linux-kernel

On Sat Apr 26, 2025 at 10:07 PM -03, Armin Wolf wrote:
> Am 23.04.25 um 09:49 schrieb Kurt Borja:
>
>> 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>
>> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
>> ---
>>   drivers/platform/x86/dell/alienware-wmi-wmax.c | 116 ++++++++++++++++++++++++-
>>   1 file changed, 115 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
>> index faeddfe3b79e0aa51e7c8c6b23aa4ac5c7218706..2e83be02d7c5f8ca8176f1ec39d9929790da0844 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
>> @@ -65,6 +68,10 @@ static bool force_gmode;
>>   module_param_unsafe(force_gmode, bool, 0);
>>   MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
>>   
>> +static bool gpio_debug;
>> +module_param_unsafe(gpio_debug, bool, 0);
>> +MODULE_PARM_DESC(gpio_debug, "Exposes GPIO debug methods to DebugFS");
>
> Hi,

Hi Armin,

>
> personally i thing that you can drop this module parameter. People using DebugFS should
> already know that they need to be careful.

I sure hope so. I know I was not careful when I started tinkering :p

I agree though, I'll drop it and follow your documentation suggestions.

>
> Other than that:
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>

Thanks a lot!

-- 
 ~ Kurt

>
>> +
>>   struct awcc_quirks {
>>   	bool hwmon;
>>   	bool pprof;
>> @@ -217,6 +224,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 +583,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 +1362,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 +1428,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 +1445,19 @@ static void awcc_debugfs_init(struct wmi_device *wdev)
>>   		debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root,
>>   					    awcc_debugfs_pprof_data_read);
>>   
>> +	if (gpio_debug) {
>> +		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);
>>   }
>>   
>>


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-04-27  6:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-23  7:49 [PATCH 0/2] platform/x86: alienware-wmi-wmax: Add support for GPIO methods Kurt Borja
2025-04-23  7:49 ` [PATCH 1/2] platform/x86: alienware-wmi-wmax: Expose GPIO debug methods Kurt Borja
2025-04-27  1:07   ` Armin Wolf
2025-04-27  6:21     ` Kurt Borja
2025-04-23  7:49 ` [PATCH 2/2] Documentation: wmi: alienware-wmi: Add GPIO control documentation Kurt Borja
2025-04-27  1:01   ` Armin Wolf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.