External Reset 60-SIPT/60-2230C Introduction The 60 Series WiFi radio driver supports a mechanism to initiate a reset of the radio module. Reset is sometimes necessary at driver initialization in cases where the driver has been reloaded or after a warm reset (restart) of the host platform if the radio module had not also undergone a hardware reset. The driver will also initiate a reset if the radio module unexpectedly stops responding. The reset functionality can also be used to achieve maximum power savings in some cases. This document details the hardware and software configuration required on the host platform to implement the reset functionality. Note: The reset implementation is dependent on host platform hardware design for all WiFi interfaces except PCIe. The hardware design must allow the radio module to be reset via GPIO pin under software control for SDIO and USB interfaces. This could either be implemented with GPIO control of a dedicated power rail to the radio module, or by following the datasheet recommendation to control the PMU_EN/WDISABLE_1# signal on the module. Note: The decision to trigger a reset is based on WiFi requirements only. However, Bluetooth operation is sometimes affected when reset occurs. Implementation The hardware and software requirements to implement reset differ based on whether the SDIO, USB or PCIe WiFi interface is used. The Bluetooth impact also varies based on which WiFi interface is used. PCIe This section is relevant to all radio modules that use PCIe for the WiFi interface. The PCIe reset implementation uses the Function Level Reset defined in the PCI specification. This requires no reset specific hardware or software support on the host platform. The reset is limited to WiFi interface only; Bluetooth is not affected. SDIO and USB This section is relevant to all radio modules that use either SDIO or USB for the WiFi interface. The SDIO and USB reset mechanism relies on a host platform provided GPIO to control the power management IC on the radio module. Platforms that use the SIPT module need to control the PMU_EN signal. Platforms that use an M.2 module with an SDIO or USB WiFi interface (2230C, 2230C-SS, 2230C-U, 2230C-UU) need to control the W_DISABLE1# signal, which is directly connected to PMU_EN on the M.2 card. In both cases, a high signal will enable the radio circuitry and a low signal will disable the radio circuitry. Note: The PMU_EN signal controls a PMIC that provides power to both WiFi and Bluetooth portions of the module. The Bluetooth radio will also be reset if the WiFi driver initiates a reset for any reason. Note: The 88W8997 datasheet requires that the PMU_EN signal be de-asserted for a minimum of 100ms to guarantee a complete reset. MMC pwrseq Implementation The GPIO used for reset is configured in the device tree. There are two ways to configure the reset GPIO depending on whether an SDIO or USB based WiFi radio is used. The MMC bus driver that hosts the lrdmwl SDIO WiFi client driver natively supports a reset power sequencing mechanism called mmc pwrseq. This is a good option to use with SDIO based radios. In this model the reset is entirely managed by the MMC bus driver, and the bus driver is fully aware of the WiFi radio state. The following sample device tree snippet demonstrates the MMC pwrseq configuration that can be used with SDIO based radios. The reset GPIO is specified via the property reset-gpios following standard gpio binding. The MMC pwrseq feature is designed to control a “reset” signal, not a power enable signal. MMC pwrseq asserts the configured reset signal prior to enabling bus power, and deasserts the signal after power up is complete. Since the reset GPIO is actually connected to the PMU_EN signal, the reset signal must be configured as an active low signal. This will cause the PMU_EN signal to be deasserted during the period the MMC bus driver intends to hold the radio in reset, and asserted (enabling power) otherwise. See the MMC pwrseq devicetree binding documentation in the kernel for more details on MMC pwrseq. &pinctrl { board { pinctrl_wifi_pmu_en: wifi_pmu_en { atmel,pins = <AT91_PIOE 5 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>; }; ... } } wifi_pwrseq: wifi_pwrseq { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_wifi_pmu_en>; compatible = "mmc-pwrseq-simple"; reset-gpios = <&pioE 5 GPIO_ACTIVE_LOW>; post-power-on-delay-ms = <10>; power-off-delay-us = <100000>; }; &mmc1 { pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_wifi_wake>; mmc-pwrseq = <&wifi_pwrseq>; ... }; lrdmwl Implementation The lrdmwl WiFi driver itself supports a custom reset mechanism that is also configured in the device tree. This option must be used with USB based radios since the USB bus driver doesn’t have native power reset sequencing support like MMC. This option can also be used with SDIO based radios. See the following sample device tree snippets for SDIO and USB interfaces using the custom lrdmwl reset implementation. The GPIO is specified via the property pmu-en-gpios following standard gpio binding. This pin should default to a logical high so that the radio is initially powered up and able to be enumerated on the bus. Note that the compatible property must also be present in the wifi node. &pinctrl { board { pinctrl_wifi_pmu_en: wifi_pmu_en { atmel,pins = <AT91_PIOE 5 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>; }; ... } } &mmc1 { ... /* keep-power-in-suspend; */ slot@0 { ... non-removable; wifi: wifi { compatible = "marvell,sd8997"; ... pmu-en-gpios = <&pioE 5 GPIO_ACTIVE_HIGH>; /* remove-power-on-link-down; */ }; }; }; /* This block used for USB/UART configuration */ &usb2 { ... wifi@2{ compatible = "usb1286,204e"; ... pmu-en-gpios = <&pioE 5 GPIO_ACTIVE_HIGH>; }; }; /* This block used for USB/USB configuration */ &usb2 { ... st60@2{ compatible = "usb1286,204e"; reg = <2>; #address-cells = <2>; #size-cells = <0>; /* Wi-fi functionality is on Configuration 1, Interface 2 */ wifi@2{ compatible = "usbif1286,204e.config1.2"; reg = <2 1>; ... pmu-en-gpios = <&pioE 5 GPIO_ACTIVE_HIGH>; }; }; }; The SDIO based lrdmwl WiFi driver supports additional power management capabilities that leverage the custom reset implementation. The SDIO based driver can be configured to power off/on the radio via the reset line when the platform is suspended/resumed. It can also be configured to power off/on the radio via the reset line at run time when the radio interface is brought up or down. This option can maximize power savings at the expense of longer latency to load firmware when the radio interface is enabled. Note: These additional power management features are supported only on radios using the SDIO WiFi interface. They are not supported on the PCI and USB interfaces. In addition, the Bluetooth radio will be reset along with the WiFi radio. The platform must be configured as follows for the reset mechanism to power off the radio module when the platform is suspended: Device power management (CONFIG_PM) enabled in the kernel configuration MMC slot configured to remove power in suspend (keep-power-in-suspend property NOT specified in the device tree) pmu-en-gpios property configured in the WiFi node as described above The platform must be configured as follows for the reset mechanism to automatically power the radio module off/on based on the radio interface state: MMC slot marked as non-removable pmu-en-gpios property configured in WiFi node as described above remove-power-on-link-down property specified in the WiFi node Bluetooth Impact The Bluetooth radio is reset along with the WiFi radio since both depend on the PMIC that is controlled with the reset GPIO. As a result, existing Bluetooth state is lost. The WiFi driver issues a KOBJ_CHANGE uevent before and after the reset takes place to indicate the Bluetooth firmware is being reloaded. These events can be used to restart the Bluetooth stack or perform any other platform specific action needed due to the reset. Event UEvent Env Value Pre-Reset “FIRMWARE=off” Post-Reset “FIRMWARE=on” See the following example udev rule that could be used to stop and start the Bluetooth stack based on the reset: DRIVERS=="lrdmwl*", ACTION=="change", ENV{FIRMWARE}=="on", DEVPATH=="*mmc*", PROGRAM="/usr/bin/systemctl start btattach.service" DRIVERS=="lrdmwl*", ACTION=="change", ENV{FIRMWARE}=="off", DEVPATH=="*mmc*", PROGRAM="/usr/bin/systemctl stop btattach.service" Note: The example udev rule above simply restarts the Bluetooth stack. Other platform specific action may be needed to re-establish the overall Bluetooth state from an application perspective. Testing The driver exposes a parameter called device_recovery via the debugfs interface at /sys/kernel/debug/ieee80211/phy0/lrdwifi. The driver will initiate a reset any time this parameter is set to 1. This interface can be used to verify that the reset mechanism is working correctly. Note: The phy number could vary based on the number and load order of adapters in the host system. echo 1 > /sys/kernel/debug/ieee80211/phy0/lrdwifi/device_recovery