Files
BPI-CM9-Linux/aml-patches/aml-comp/kernel/aml-6.12/common_drivers/0006-wifi-Linux-requires-systemd-rfkill-to-enable-wifibt-.patch

187 lines
5.3 KiB
Diff

From e3e4b3d1ce76de7a6811da701fbf9b6688093361 Mon Sep 17 00:00:00 2001
From: "chengshuo.wang" <chengshuo.wang@amlogic.com>
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 <chengshuo.wang@amlogic.com>
---
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 <linux/printk.h>
#include <linux/init.h>
#include <linux/amlogic/gki_module.h>
+#include <linux/rfkill.h>
#ifdef CONFIG_AMLOGIC_PWM_32K
#include <linux/pwm.h>
#include <linux/amlogic/pwm-meson.h>
@@ -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