2026-08-25 10:02:36 +08:00
|
|
|
From e3e4b3d1ce76de7a6811da701fbf9b6688093361 Mon Sep 17 00:00:00 2001
|
2026-08-13 11:28:40 +08:00
|
|
|
From: "chengshuo.wang" <chengshuo.wang@amlogic.com>
|
|
|
|
|
Date: Tue, 3 Feb 2026 13:22:48 +0800
|
2026-08-25 10:02:36 +08:00
|
|
|
Subject: [PATCH 6/6] wifi: Linux requires systemd-rfkill to enable wifibt
|
2026-08-13 11:28:40 +08:00
|
|
|
[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>
|
|
|
|
|
---
|
2026-08-25 10:02:36 +08:00
|
|
|
drivers/wireless/bluetooth/bt_device.c | 2 +-
|
2026-08-13 11:28:40 +08:00
|
|
|
drivers/wireless/wifi/Kconfig | 10 ++--
|
2026-08-25 10:02:36 +08:00
|
|
|
drivers/wireless/wifi/wifi_dt.c | 69 ++++++++++++++++++++++++--
|
|
|
|
|
3 files changed, 74 insertions(+), 7 deletions(-)
|
2026-08-13 11:28:40 +08:00
|
|
|
|
|
|
|
|
diff --git a/drivers/wireless/bluetooth/bt_device.c b/drivers/wireless/bluetooth/bt_device.c
|
2026-08-25 10:02:36 +08:00
|
|
|
index ed495cd6e6..32cb5a7bdd 100644
|
2026-08-13 11:28:40 +08:00
|
|
|
--- a/drivers/wireless/bluetooth/bt_device.c
|
|
|
|
|
+++ b/drivers/wireless/bluetooth/bt_device.c
|
2026-08-25 10:02:36 +08:00
|
|
|
@@ -302,7 +302,7 @@ static int bt_set_block(void *data, bool blocked)
|
2026-08-13 11:28:40 +08:00
|
|
|
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
|
2026-08-25 10:02:36 +08:00
|
|
|
index 8db5794802..1b83810938 100644
|
2026-08-13 11:28:40 +08:00
|
|
|
--- 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)
|
2026-08-25 10:02:36 +08:00
|
|
|
@@ -488,6 +490,36 @@ static long wifi_power_ioctl(struct file *filp,
|
2026-08-13 11:28:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
2026-08-25 10:02:36 +08:00
|
|
|
+ WIFI_INFO("wifi rfkill already blocked\n");
|
2026-08-13 11:28:40 +08:00
|
|
|
+ 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)
|
2026-08-25 10:02:36 +08:00
|
|
|
@@ -982,15 +1014,36 @@ static int wifi_dev_probe(struct platform_device *pdev)
|
2026-08-13 11:28:40 +08:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
2026-08-25 10:02:36 +08:00
|
|
|
+#if IS_ENABLED(CONFIG_AMLOGIC_RFKILL_INIT_SW_UNBLOCK)
|
2026-08-13 11:28:40 +08:00
|
|
|
+ WIFI_INFO("wlan_rfkill_init as default unblock");
|
2026-08-25 10:02:36 +08:00
|
|
|
+ rfkill_init_sw_state(wlan_rfk, false); /* default power on */
|
|
|
|
|
+#else
|
2026-08-13 11:28:40 +08:00
|
|
|
+ WIFI_INFO("wlan_rfkill_init as default block");
|
2026-08-25 10:02:36 +08:00
|
|
|
+ rfkill_init_sw_state(wlan_rfk, true); /* default power off */
|
|
|
|
|
+#endif
|
2026-08-13 11:28:40 +08:00
|
|
|
+ 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);
|
2026-08-25 10:02:36 +08:00
|
|
|
@@ -1006,6 +1059,11 @@ static int wifi_dev_probe(struct platform_device *pdev)
|
2026-08-13 11:28:40 +08:00
|
|
|
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:
|
2026-08-25 10:02:36 +08:00
|
|
|
@@ -1019,6 +1077,11 @@ out:
|
2026-08-13 11:28:40 +08:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--
|
2026-08-25 10:02:36 +08:00
|
|
|
2.43.2
|
2026-08-13 11:28:40 +08:00
|
|
|
|