From e3e4b3d1ce76de7a6811da701fbf9b6688093361 Mon Sep 17 00:00:00 2001 From: "chengshuo.wang" Date: Tue, 3 Feb 2026 13:22:48 +0800 Subject: [PATCH 6/6] wifi: Linux requires systemd-rfkill to enable wifibt [1/1] PD#SWPL-236256 Problem: Linux requires systemd-rfkill to enable wifibt Solution: Set the default rfkill to block, and let the upper layer control the power adjustment. Add a rfkill node for WiFi for use by the upper layer of Linux Verify: S6 Change-Id: I9a4d24aaf3e65d804e710a06064a9bbe2b75f522 Signed-off-by: chengshuo.wang --- drivers/wireless/bluetooth/bt_device.c | 2 +- drivers/wireless/wifi/Kconfig | 10 ++-- drivers/wireless/wifi/wifi_dt.c | 69 ++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/drivers/wireless/bluetooth/bt_device.c b/drivers/wireless/bluetooth/bt_device.c index ed495cd6e6..32cb5a7bdd 100644 --- a/drivers/wireless/bluetooth/bt_device.c +++ b/drivers/wireless/bluetooth/bt_device.c @@ -302,7 +302,7 @@ static int bt_set_block(void *data, bool blocked) static bool rfkill_state = true; if (rfkill_state == blocked) { - pr_info("rfkill already %s\n", blocked ? "off" : "on"); + pr_info("bt rfkill already %s\n", blocked ? "off" : "on"); return 0; } diff --git a/drivers/wireless/wifi/Kconfig b/drivers/wireless/wifi/Kconfig index 77ef0a9335..13ee3c2141 100644 --- a/drivers/wireless/wifi/Kconfig +++ b/drivers/wireless/wifi/Kconfig @@ -33,9 +33,13 @@ config WIFI_POWER_INIT_OFF config AMLOGIC_RFKILL_INIT_SW_UNBLOCK bool "init rfkill sw unblock" - default n + depends on RFKILL_INPUT + default y help - Enable init rfkill sw unblock. - By default,rfkill sw is blocked and not inited. + Enable init rfkill sw unblock. When enabled, BT and WLAN rfkill + initial state is "unblocked" so upper layer does not misjudge + as radio off. Only visible when CONFIG_RFKILL_INPUT (kernel + rfkill input support) is enabled; must be used together with + RFKILL_INPUT to avoid wrong pairing. endif diff --git a/drivers/wireless/wifi/wifi_dt.c b/drivers/wireless/wifi/wifi_dt.c index 8db5794802..1b83810938 100644 --- a/drivers/wireless/wifi/wifi_dt.c +++ b/drivers/wireless/wifi/wifi_dt.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_AMLOGIC_PWM_32K #include #include @@ -306,7 +307,8 @@ EXPORT_SYMBOL(set_usb_bt_power); void set_usb_wifi_power(int is_power) { - usb_power_control(is_power, WIFI_BIT); + if (!is_pcie_wifi()) + usb_power_control(is_power, WIFI_BIT); } EXPORT_SYMBOL(set_usb_wifi_power); static int wifi_power_open(struct inode *inode, struct file *file) @@ -488,6 +490,36 @@ static long wifi_power_ioctl(struct file *filp, } static struct class *wifi_dt_class; +static struct rfkill *wlan_rfk; + +static int wlan_set_block(void *data, bool blocked) +{ +#if IS_ENABLED(CONFIG_AMLOGIC_RFKILL_INIT_SW_UNBLOCK) + static bool rfkill_state = true; + + if (rfkill_state == blocked) { + WIFI_INFO("wifi rfkill already blocked\n"); + return 0; + } + + rfkill_state = blocked; +#endif + + if (!blocked) { + set_usb_wifi_power(0); + set_usb_wifi_power(1); + WIFI_INFO("AML_WIFI: going ON\n"); + } else { + set_usb_wifi_power(0); + WIFI_INFO("AML_WIFI: going OFF\n"); + } + return 0; +} + +static const struct rfkill_ops wlan_rfkill_ops = { + .set_block = wlan_set_block, +}; + static ssize_t power_show(const struct class *class, const struct class_attribute *attr, char *_buf) @@ -982,15 +1014,36 @@ static int wifi_dev_probe(struct platform_device *pdev) wifi_setup_dt(); + wlan_rfk = rfkill_alloc("wlan-dev", &pdev->dev, + RFKILL_TYPE_WLAN, + &wlan_rfkill_ops, NULL); + if (!wlan_rfk) { + WIFI_DEBUG("wlan rfkill alloc fail\n"); + ret = -ENOMEM; + goto error_rfk_alloc; + } + +#if IS_ENABLED(CONFIG_AMLOGIC_RFKILL_INIT_SW_UNBLOCK) + WIFI_INFO("wlan_rfkill_init as default unblock"); + rfkill_init_sw_state(wlan_rfk, false); /* default power on */ +#else + WIFI_INFO("wlan_rfkill_init as default block"); + rfkill_init_sw_state(wlan_rfk, true); /* default power off */ +#endif + ret = rfkill_register(wlan_rfk); + if (ret) { + WIFI_INFO("wlan rfkill_register fail\n"); + goto error_rfkill; + } wifi_dt_class = class_create("aml_wifi"); ret = class_create_file(wifi_dt_class, &class_attr_power); /********wifi rand mac***********/ ret = alloc_chrdev_region(&wifi_mac_devno, 0, 1, WIFI_MAC_DEVICE_NAME); if (ret < 0) - goto error3; + goto error_rfk_alloc; wifi_mac_cdev = cdev_alloc(); if (!wifi_mac_cdev) - goto error3; + goto error_rfk_alloc; cdev_init(wifi_mac_cdev, &wifi_mac_fops); wifi_mac_cdev->owner = THIS_MODULE; ret = cdev_add(wifi_mac_cdev, wifi_mac_devno, 1); @@ -1006,6 +1059,11 @@ static int wifi_dev_probe(struct platform_device *pdev) return 0; error4: cdev_del(wifi_mac_cdev); +error_rfk_alloc: + rfkill_unregister(wlan_rfk); +error_rfkill: + rfkill_destroy(wlan_rfk); + wlan_rfk = NULL; error3: cdev_del(wifi_power_cdev); error2: @@ -1019,6 +1077,11 @@ out: static void wifi_dev_remove(struct platform_device *pdev) { //WIFI_INFO("%s is enter\n", __func__); + if (wlan_rfk) { + rfkill_unregister(wlan_rfk); + rfkill_destroy(wlan_rfk); + wlan_rfk = NULL; + } wifi_teardown_dt(); } -- 2.43.2