From 9ffddd41726ca3ca4d3be7577378691233963dfa Mon Sep 17 00:00:00 2001 From: yjd01941629 Date: Sun, 7 Apr 2024 12:46:29 +0800 Subject: [PATCH] For AIC8800 (WIFI/BT chip): The AIC8800 driver must be unloaded before entering STR (Suspend to RAM); otherwise, upon waking from STR, initialization will fail. 1.broken-cd: The default non-removable attribute fails to recognize the AIC8800, thus it is set to rely on a software card detection signal instead of hardware, always treating the card slot as if a card is present. 2.keep-power-in-suspend: The SDIO of TH1520 does not support keeping power when entering STR, and the driver of AIC8800 does not support SDIO with this function. Therefore, this node is added here to meet the driver requirements of AIC8800. 3.support_power_ctrl:The newly added device node is used to control the WL-REG-ON signal (which controls the power of AIC8800) after waking up from STR. Change-Id: Ia33309da9f3e6bdf291f408d26909f11afd24842 --- arch/riscv/boot/dts/thead/th1520-lpi4a.dtsi | 4 +- net/rfkill/rfkill-wlan.c | 51 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/arch/riscv/boot/dts/thead/th1520-lpi4a.dtsi b/arch/riscv/boot/dts/thead/th1520-lpi4a.dtsi index 58acfb248..a82fb05c7 100644 --- a/arch/riscv/boot/dts/thead/th1520-lpi4a.dtsi +++ b/arch/riscv/boot/dts/thead/th1520-lpi4a.dtsi @@ -274,6 +274,7 @@ pinctrl-0 = <&pinctrl_wifi_wake>; wifi_chip_type = "rtl8723ds"; WIFI,poweren_gpio = <&pcal6408ahk_c 4 0>; + support_power_ctrl; status = "okay"; }; @@ -992,12 +993,13 @@ pull_up; no-sd; no-mmc; - non-removable; + broken-cd; io_fixed_1v8; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; wakeup-source; + keep-power-in-suspend; status = "okay"; }; diff --git a/net/rfkill/rfkill-wlan.c b/net/rfkill/rfkill-wlan.c index 3fac7e680..c8fcb180f 100644 --- a/net/rfkill/rfkill-wlan.c +++ b/net/rfkill/rfkill-wlan.c @@ -60,6 +60,7 @@ struct rfkill_wlan_data { static struct rfkill_wlan_data *g_rfkill = NULL; static int power_set_time = 0; +static int support_power_ctrl = 0; //Used to control whether power switch control is supported. static const char wlan_name[] = #if defined (CONFIG_BCM4330) @@ -660,6 +661,15 @@ static int wlan_platdata_parse_dt(struct device *dev, LOG("%s: get property: WIFI,poweren_gpio = %d, flags = %d.\n", __func__, gpio, flags); } else data->power_n.io = -1; gpio = of_get_named_gpio_flags(node, "WIFI,vbat_gpio", 0, &flags); + + if (of_find_property(node, "support_power_ctrl", NULL)) { + support_power_ctrl = true; + LOG("%s: Turn off the power during suspension and turn it on when resuming, support_power_ctrl = %d.\n", __func__, support_power_ctrl); + } else { + support_power_ctrl = false; + LOG("%s: power is only turned on during initialization and is not controlled afterwards, support_power_ctrl = %d.\n", __func__, support_power_ctrl); + } + if (gpio_is_valid(gpio)) { data->vbat_n.io = gpio; data->vbat_n.enable = (flags == GPIO_ACTIVE_HIGH) ? 1:0; @@ -901,12 +911,53 @@ static int rfkill_wlan_remove(struct platform_device *pdev) static int rfkill_wlan_suspend(struct platform_device *pdev, pm_message_t state) { + struct rfkill_wlan_data *mrfkill = g_rfkill; + struct rksdmmc_gpio *poweron, *reset; + poweron = &mrfkill->pdata->power_n; + reset = &mrfkill->pdata->reset_n; + + // turn off the wifi's power + if( support_power_ctrl ){ + if (gpio_is_valid(poweron->io)) { + gpio_set_value(poweron->io, !(poweron->enable)); + msleep(100); + } + + if (gpio_is_valid(reset->io)) { + gpio_set_value(reset->io, !(reset->enable)); + } + + wifi_power_state = 0; + LOG("wifi shut off power.\n"); + } + LOG("Enter %s\n", __func__); return 0; } static int rfkill_wlan_resume(struct platform_device *pdev) { + struct rfkill_wlan_data *mrfkill = g_rfkill; + struct rksdmmc_gpio *poweron, *reset; + poweron = &mrfkill->pdata->power_n; + reset = &mrfkill->pdata->reset_n; + + // turn on the wifi's power + if( support_power_ctrl ){ + if (gpio_is_valid(poweron->io)) { + gpio_set_value(poweron->io, poweron->enable); + msleep(500); + } + + if (gpio_is_valid(reset->io)) { + gpio_set_value(reset->io, reset->enable); + msleep(100); + } + + wifi_power_state = 1; + LOG("wifi turn on power. %d\n", poweron->io); + } + LOG("Enter %s\n", __func__); return 0; }