Update source to Armbian-dev-202610.A311Y3

This commit is contained in:
2026-11-11 08:50:43 +08:00
parent 3428a94f6b
commit f459ef6a9e
12514 changed files with 2264376 additions and 468481 deletions
@@ -48,6 +48,7 @@ static struct early_suspend bt_early_suspend;
#define POWER_EVENT_EN 2
#define KEY_NETFLIX (133)
//#define CONTROL_POWER_EN_LINUX
#define BT_WAKEUP_DETECT_FUNC 0
struct bt_dev_runtime_data {
struct rfkill *bt_rfk;
@@ -63,6 +64,13 @@ static int btwake_evt;
static int btpower_evt;
static u32 cus_wakeup_key = KEY_NETFLIX;
#if BT_WAKEUP_DETECT_FUNC
static int btirq_flag;
static int flag_n;
static int flag_p;
static int cnt;
#endif
#if defined(CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND) && defined(CONFIG_AMLOGIC_GX_SUSPEND)
#ifndef CONFIG_AMLOGIC_BT_WAKE_NOT_REPORT
static int distinguish_module(void)
@@ -244,20 +252,49 @@ static void bt_device_off(struct bt_dev_data *pdata)
}
}
static void bt_device_init(struct bt_dev_data *pdata)
static int bt_device_init(struct bt_dev_data *pdata)
{
int ret = 0;
btpower_evt = 0;
if (pdata->gpio_reset > 0)
gpio_request(pdata->gpio_reset, BT_RFKILL);
if (pdata->gpio_en > 0)
gpio_request(pdata->gpio_en, BT_RFKILL);
if (pdata->gpio_reset > 0) {
ret = gpio_request(pdata->gpio_reset, BT_RFKILL);
if (ret) {
pr_err("req gpio_reset fail %d\n", ret);
goto err;
}
gpio_direction_output(pdata->gpio_reset, pdata->power_low_level);
}
if (pdata->gpio_en > 0) {
ret = gpio_request(pdata->gpio_en, BT_RFKILL);
if (ret) {
pr_err("req gpio_en fail %d\n", ret);
goto err_free_reset_io;
}
}
#if BT_WAKEUP_DETECT_FUNC
if (pdata->gpio_btwakeup > 0) {
gpio_request(pdata->gpio_btwakeup, BT_RFKILL);
ret = gpio_request(pdata->gpio_btwakeup, BT_RFKILL);
if (ret) {
pr_err("req gpio_btwakeup fail %d\n", ret);
goto err_free_en_io;
}
gpio_direction_input(pdata->gpio_btwakeup);
}
#endif
return 0;
#if BT_WAKEUP_DETECT_FUNC
err_free_en_io:
if (pdata->gpio_en > 0)
gpio_free(pdata->gpio_en);
#endif
err_free_reset_io:
if (pdata->gpio_reset > 0)
gpio_free(pdata->gpio_reset);
err:
return ret;
}
static void bt_device_deinit(struct bt_dev_data *pdata)
@@ -267,8 +304,12 @@ static void bt_device_deinit(struct bt_dev_data *pdata)
if (pdata->gpio_en > 0)
gpio_free(pdata->gpio_en);
#if BT_WAKEUP_DETECT_FUNC
if (pdata->gpio_btwakeup > 0)
gpio_free(pdata->gpio_btwakeup);
#endif
btpower_evt = 0;
}
static void bt_device_on(struct bt_dev_data *pdata, unsigned long down_time, unsigned long up_time)
@@ -294,6 +335,76 @@ static void bt_device_on(struct bt_dev_data *pdata, unsigned long down_time, uns
}
}
#if BT_WAKEUP_DETECT_FUNC
static irqreturn_t bt_interrupt(int irq, void *dev_id)
{
struct bt_dev_data *pdata = (struct bt_dev_data *)dev_id;
if (btirq_flag == 1) {
schedule_work(&pdata->btwakeup_work);
pr_debug("freeze: test BT IRQ\n");
}
return IRQ_HANDLED;
}
static enum hrtimer_restart btwakeup_timer_handler(struct hrtimer *timer)
{
struct bt_dev_data *pdata = container_of(timer,
struct bt_dev_data, timer);
if (!gpio_get_value(pdata->gpio_btwakeup) && cnt < 5)
cnt++;
if (cnt >= 5 && cnt < 15) {
if (gpio_get_value(pdata->gpio_btwakeup))
flag_p++;
else if (!gpio_get_value(pdata->gpio_btwakeup))
flag_n++;
cnt++;
}
pr_debug("%s power: %d,netflix:%d\n", __func__, flag_p, flag_n);
if (flag_p >= 7) {
pr_info("%s power: %d\n", __func__, flag_p);
btwake_evt = 2;
cnt = 0;
flag_p = 0;
btirq_flag = 0;
input_event(pdata->input_dev,
EV_KEY, KEY_POWER, 1);
input_sync(pdata->input_dev);
input_event(pdata->input_dev,
EV_KEY, KEY_POWER, 0);
input_sync(pdata->input_dev);
} else if (flag_n >= 7) {
pr_info("%s netflix: %d\n", __func__, flag_n);
btwake_evt = 2;
cnt = 0;
flag_n = 0;
btirq_flag = 0;
input_event(pdata->input_dev, EV_KEY, 133, 1);
input_sync(pdata->input_dev);
input_event(pdata->input_dev, EV_KEY, 133, 0);
input_sync(pdata->input_dev);
}
if (btwake_evt != 2 && cnt != 0)
hrtimer_start(&pdata->timer,
ktime_set(0, 20 * 1000000), HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
static void get_btwakeup_irq_work(struct work_struct *work)
{
struct bt_dev_data *pdata = container_of(work,
struct bt_dev_data, btwakeup_work);
if (btwake_evt == 2)
return;
pr_debug("%s btwake_evt = %d", __func__, btwake_evt);
hrtimer_start(&pdata->timer,
ktime_set(0, 100 * 1000000), HRTIMER_MODE_REL);
}
#endif
static int bt_set_block(void *data, bool blocked)
{
struct bt_dev_data *pdata = data;
@@ -302,7 +413,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;
}
@@ -340,6 +451,12 @@ static void bt_lateresume(struct early_suspend *h)
static int bt_suspend(struct platform_device *pdev,
pm_message_t state)
{
#if BT_WAKEUP_DETECT_FUNC
struct bt_dev_runtime_data *prdata = platform_get_drvdata(pdev);
disable_irq(prdata->pdata->irqno_wakeup);
#endif
btwake_evt = 0;
pr_debug("bt suspend\n");
@@ -349,6 +466,11 @@ static int bt_suspend(struct platform_device *pdev,
static int bt_resume(struct platform_device *pdev)
{
#if BT_WAKEUP_DETECT_FUNC
struct bt_dev_runtime_data *prdata = platform_get_drvdata(pdev);
enable_irq(prdata->pdata->irqno_wakeup);
#endif
btwake_evt = 0;
pr_debug("bt resume\n");
@@ -362,6 +484,9 @@ static int bt_resume(struct platform_device *pdev)
case RTC_WAKEUP:
case AUTO_WAKEUP:
btwake_evt = 1;
#if BT_WAKEUP_DETECT_FUNC
btirq_flag = 1;
#endif
break;
#ifndef CONFIG_AMLOGIC_BT_WAKE_NOT_REPORT
case BT_WAKEUP:
@@ -417,7 +542,7 @@ static int bt_probe(struct platform_device *pdev)
//struct gpio_desc *desc;
pr_debug("enter %s of_node\n", __func__);
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
ret = -ENOMEM;
goto err_res;
@@ -444,6 +569,18 @@ static int bt_probe(struct platform_device *pdev)
(pdev->dev.of_node,
"bt_en-gpios", 0);
}
#if BT_WAKEUP_DETECT_FUNC
ret = of_property_read_string(pdev->dev.of_node,
"btwakeup-gpios", &str);
if (ret) {
pr_debug("not get btwakeup-gpios\n");
pdata->gpio_btwakeup = 0;
} else {
pdata->gpio_btwakeup = of_get_named_gpio
(pdev->dev.of_node,
"btwakeup-gpios", 0);
}
#endif
prop = of_get_property(pdev->dev.of_node,
"power_low_level", NULL);
@@ -485,10 +622,20 @@ static int bt_probe(struct platform_device *pdev)
#else
pdata = (struct bt_dev_data *)(pdev->dev.platform_data);
#endif
if (!pdata) {
ret = -ENOMEM;
pr_debug("pdata is NULL\n");
goto err_res;
}
bt_addr_class = class_create("bt_addr");
ret = class_create_file(bt_addr_class, &class_attr_value);
bt_device_init(pdata);
ret = bt_device_init(pdata);
if (ret) {
pr_err("Failed bt_device_init %d\n", ret);
goto err_res;
}
/* default to bluetooth off */
/* rfkill_switch_all(RFKILL_TYPE_BLUETOOTH, 1); */
@@ -544,6 +691,32 @@ static int bt_probe(struct platform_device *pdev)
register_early_suspend(&bt_early_suspend);
#endif
#if BT_WAKEUP_DETECT_FUNC
/*1.Set BT_WAKE_HOST to the input state;*/
/*2.Get interrupt number(irqno_wakeup).*/
if (pdata->gpio_btwakeup > 0) {
pdata->irqno_wakeup = gpio_to_irq(pdata->gpio_btwakeup);
/*Register interrupt service function*/
ret = request_irq(pdata->irqno_wakeup, bt_interrupt,
IRQF_TRIGGER_FALLING, "bt-irq", (void *)pdata);
if (ret < 0)
pr_err("request_irq error ret=%d\n", ret);
//disable_irq(pdata->irqno_wakeup);
ret = device_init_wakeup(&pdev->dev, 1);
if (ret)
pr_err("device_init_wakeup failed: %d\n", ret);
/*Wake up the interrupt*/
ret = dev_pm_set_wake_irq(&pdev->dev, pdata->irqno_wakeup);
if (ret)
pr_err("dev_pm_set_wake_irq failed: %d\n", ret);
INIT_WORK(&pdata->btwakeup_work, get_btwakeup_irq_work);
}
#endif
//input
input_dev = input_allocate_device();
if (!input_dev) {
@@ -572,6 +745,10 @@ static int bt_probe(struct platform_device *pdev)
return -EINVAL;
}
pdata->input_dev = input_dev;
#if BT_WAKEUP_DETECT_FUNC
hrtimer_init(&pdata->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pdata->timer.function = btwakeup_timer_handler;
#endif
return 0;
@@ -33,9 +33,20 @@ config WIFI_POWER_INIT_OFF
config AMLOGIC_RFKILL_INIT_SW_UNBLOCK
bool "init rfkill sw unblock"
depends on RFKILL_INPUT
default y
help
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.
config AMLOGIC_WIFI_RFKILL
bool "WiFi platform rfkill (wlan-dev) power control"
depends on RFKILL
default n
help
Enable init rfkill sw unblock.
By default,rfkill sw is blocked and not inited.
Register platform WLAN rfkill (wlan-dev) for power control.
endif
@@ -29,6 +29,9 @@
#include <linux/printk.h>
#include <linux/init.h>
#include <linux/amlogic/gki_module.h>
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
#include <linux/rfkill.h>
#endif
#ifdef CONFIG_AMLOGIC_PWM_32K
#include <linux/pwm.h>
#include <linux/amlogic/pwm-meson.h>
@@ -127,10 +130,12 @@ struct wifi_power_platform_data *pdata;
static dev_t wifi_mac_devno;
static struct cdev *wifi_mac_cdev;
static struct device *wifi_mac_devp;
#ifdef CONFIG_AMLOGIC_PWM_32K
static struct pwm_state pwm_channel0_state;
static struct pwm_state pwm_channel1_state;
static struct pwm_device *gpwm0;
static struct pwm_device *gpwm1;
#endif
static int usb_power;
#define BT_BIT 0
@@ -306,7 +311,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 +494,38 @@ static long wifi_power_ioctl(struct file *filp,
}
static struct class *wifi_dt_class;
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
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,
};
#endif
static ssize_t power_show(const struct class *class,
const struct class_attribute *attr,
char *_buf)
@@ -982,15 +1020,46 @@ static int wifi_dev_probe(struct platform_device *pdev)
wifi_setup_dt();
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
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;
}
#endif
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)
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
goto error_rfk_alloc;
#else
goto error3;
#endif
wifi_mac_cdev = cdev_alloc();
if (!wifi_mac_cdev)
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
goto error_rfk_alloc;
#else
goto error3;
#endif
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 +1075,13 @@ static int wifi_dev_probe(struct platform_device *pdev)
return 0;
error4:
cdev_del(wifi_mac_cdev);
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
error_rfk_alloc:
rfkill_unregister(wlan_rfk);
error_rfkill:
rfkill_destroy(wlan_rfk);
wlan_rfk = NULL;
#endif
error3:
cdev_del(wifi_power_cdev);
error2:
@@ -1019,6 +1095,13 @@ out:
static void wifi_dev_remove(struct platform_device *pdev)
{
//WIFI_INFO("%s is enter\n", __func__);
#if IS_ENABLED(CONFIG_AMLOGIC_WIFI_RFKILL)
if (wlan_rfk) {
rfkill_unregister(wlan_rfk);
rfkill_destroy(wlan_rfk);
wlan_rfk = NULL;
}
#endif
wifi_teardown_dt();
}
@@ -1095,7 +1178,7 @@ static unsigned char chartonum(char c)
static int mac_addr_set(char *line)
{
unsigned char mac[6];
unsigned char mac[6] = {0};
int i = 0;
WIFI_INFO("try to wifi mac from emmc key!\n");
@@ -1103,6 +1186,10 @@ static int mac_addr_set(char *line)
mac[i] = chartonum(line[0]) << 4 | chartonum(line[1]);
line += 3;
}
if (i != 6) {
WIFI_INFO("Invalid emmc MAC address format!\n");
return -EINVAL;
}
memcpy(WIFI_MAC, mac, 6);
snprintf(wifi_mac, sizeof(wifi_mac),
"%02x:%02x:%02x:%02x:%02x:%02x",
@@ -1165,7 +1252,7 @@ static ssize_t wifi_mac_write(struct file *file, const char __user *buf, size_t
int ret;
int i = 0;
char mac[20];
unsigned char wifi_mac[6];
unsigned char wifi_mac[6] = {0};
if (count > 18) {
WIFI_INFO("MAC addresses don't need to be that long.\n");
@@ -1179,6 +1266,10 @@ static ssize_t wifi_mac_write(struct file *file, const char __user *buf, size_t
}
for (i = 0; i < 6 && mac[i * 3] != '\0' && mac[i * 3 + 1] != '\0'; i++)
wifi_mac[i] = chartonum(mac[i * 3]) << 4 | chartonum(mac[i * 3 + 1]);
if (i != 6) {
WIFI_INFO("Invalid MAC addresses format\n");
return -EINVAL;
}
memcpy(WIFI_MAC_RANDOM, wifi_mac, 6);
@@ -1243,6 +1334,7 @@ EXPORT_SYMBOL(wifi_irq_trigger_level);
void extern_wifi_32k_set_enable(int is_on)
{
#ifdef CONFIG_AMLOGIC_PWM_32K
if (!gpwm0)
return;
@@ -1255,5 +1347,6 @@ void extern_wifi_32k_set_enable(int is_on)
}
pwm_apply_might_sleep(gpwm0, &pwm_channel0_state);
pwm_apply_might_sleep(gpwm1, &pwm_channel1_state);
#endif
}
EXPORT_SYMBOL(extern_wifi_32k_set_enable);