mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
This series is based on * 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef Add support for * qsdk kernel/v4.4 * qsdk ethernet subsystem * v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0) * ath11k-firmware * hostapd/iw/... Feature support * full boot, system detection * sysupgrade to nand * HE support via latest hostapd * driver support for usb, crypto, hwmon, cpufreq, ... Missing * NSS/HW flow offloading - FW blob is not redistributable Using the qsdk v4.4 is an intermediate solution while the vanilla is being tested. Vanilla kernel is almost on feature par. Work has already started to upstream the ethernet and switch drivers. Once complete the target will be fully upstream. Signed-off-by: John Crispin <john@phrozen.org>
179 lines
5.4 KiB
Diff
179 lines
5.4 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/ahb.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
|
|
@@ -631,6 +631,23 @@ void ath11k_ahb_power_down(struct ath11k
|
|
rproc_shutdown(ab->tgt_rproc);
|
|
}
|
|
|
|
+int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab)
|
|
+{
|
|
+ if (enable_cold_boot_cal == 0 || ab->qmi.cal_done)
|
|
+ return 0;
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n");
|
|
+ while (ab->qmi.cal_done == 0)
|
|
+ msleep(ATH11K_FW_READY_DELAY);
|
|
+
|
|
+ /* reset the firmware */
|
|
+ ath11k_ahb_power_down(ab);
|
|
+ ath11k_ahb_power_up(ab);
|
|
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "exit wait for cold boot done\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
|
|
{
|
|
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
|
|
@@ -945,6 +962,8 @@ static int ath11k_ahb_probe(struct platf
|
|
goto err_ce_free;
|
|
}
|
|
|
|
+ ath11k_ahb_fwreset_from_cold_boot(ab);
|
|
+
|
|
return 0;
|
|
|
|
err_ce_free:
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -99,6 +99,9 @@ enum ath11k_firmware_mode {
|
|
|
|
/* factory tests etc */
|
|
ATH11K_FIRMWARE_MODE_FTM,
|
|
+
|
|
+ /* Cold boot calibration */
|
|
+ ATH11K_FIRMWARE_MODE_COLD_BOOT = 7,
|
|
};
|
|
|
|
#define ATH11K_IRQ_NUM_MAX 52
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
@@ -9,6 +9,11 @@
|
|
#include <linux/of.h>
|
|
#include <linux/firmware.h>
|
|
|
|
+/* set the default max assoc sta to max supported by driver */
|
|
+unsigned int enable_cold_boot_cal = 1;
|
|
+module_param(enable_cold_boot_cal, uint, 0644);
|
|
+MODULE_PARM_DESC(enable_cold_boot_cal, "cold boot calibration enable:1 disable:0");
|
|
+
|
|
static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
|
|
{
|
|
.data_type = QMI_OPT_FLAG,
|
|
@@ -1677,6 +1682,7 @@ out:
|
|
static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
|
{
|
|
int i, idx;
|
|
+ u32 caldb_location[2] = {0, 0};
|
|
|
|
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
switch (ab->qmi.target_mem[i].type) {
|
|
@@ -1692,9 +1698,20 @@ static int ath11k_qmi_alloc_target_mem_c
|
|
ath11k_warn(ab, "qmi mem size is low to load caldata\n");
|
|
return -EINVAL;
|
|
}
|
|
- /* TODO ath11k does not support cold boot calibration */
|
|
- ab->qmi.target_mem[idx].paddr = 0;
|
|
- ab->qmi.target_mem[idx].vaddr = 0;
|
|
+
|
|
+ if (of_property_read_u32_array(ab->dev->of_node, "qcom,caldb-addr",
|
|
+ &caldb_location[0],
|
|
+ ARRAY_SIZE(caldb_location))) {
|
|
+ ath11k_warn(ab, "qmi no bdf_addr in device_tree\n");
|
|
+ }
|
|
+
|
|
+ if (enable_cold_boot_cal) {
|
|
+ ab->qmi.target_mem[idx].paddr = caldb_location[ab->qmi.target_mem_mode];
|
|
+ ab->qmi.target_mem[idx].vaddr = caldb_location[ab->qmi.target_mem_mode];
|
|
+ } else {
|
|
+ ab->qmi.target_mem[idx].paddr = 0;
|
|
+ ab->qmi.target_mem[idx].vaddr = 0;
|
|
+ }
|
|
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
|
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
|
idx++;
|
|
@@ -2117,6 +2134,32 @@ int ath11k_qmi_firmware_start(struct ath
|
|
return 0;
|
|
}
|
|
|
|
+int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
|
|
+{
|
|
+ int ret;
|
|
+ int coldboot_wait_limit = 0;
|
|
+
|
|
+ ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_COLD_BOOT);
|
|
+ if (ret < 0) {
|
|
+ ath11k_warn(ab, "qmi failed to send wlan fw mode:%d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ath11k_info(ab, "Coldboot calibration wait started\n");
|
|
+ while (ab->qmi.cal_done == 0) {
|
|
+ if (++coldboot_wait_limit >= ATH11K_COLD_BOOT_MAX_WAIT_LIMIT) {
|
|
+ ath11k_warn(ab, "Coldboot Calibration timeout %d secs",
|
|
+ coldboot_wait_limit / 10);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ mdelay(ATH11K_FW_READY_DELAY);
|
|
+ }
|
|
+
|
|
+ ath11k_info(ab, "Coldboot calibration wait ended\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi,
|
|
enum ath11k_qmi_event_type type,
|
|
@@ -2253,11 +2296,16 @@ static void ath11k_qmi_msg_fw_ready_cb(s
|
|
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL);
|
|
}
|
|
|
|
-static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi,
|
|
+static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
|
|
struct sockaddr_qrtr *sq,
|
|
struct qmi_txn *txn,
|
|
const void *decoded)
|
|
{
|
|
+ struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
|
|
+ struct ath11k_base *ab = qmi->ab;
|
|
+
|
|
+ ab->qmi.cal_done = 1;
|
|
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
|
|
}
|
|
|
|
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
|
|
@@ -2368,11 +2416,14 @@ static void ath11k_qmi_driver_event_work
|
|
queue_work(ab->workqueue, &ab->restart_work);
|
|
break;
|
|
}
|
|
-
|
|
- ath11k_core_qmi_firmware_ready(ab);
|
|
- ab->qmi.cal_done = 1;
|
|
- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
|
-
|
|
+ if (enable_cold_boot_cal && ab->qmi.cal_done == 0) {
|
|
+ ath11k_qmi_process_coldboot_calibration(ab);
|
|
+ } else {
|
|
+ clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
|
+ clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
|
+ ath11k_core_qmi_firmware_ready(ab);
|
|
+ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
|
+ }
|
|
break;
|
|
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
|
|
break;
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
|
|
@@ -34,6 +34,11 @@
|
|
#define ATH11K_FIRMWARE_MODE_OFF 4
|
|
#define ATH11K_QMI_TARGET_MEM_MODE_DEFAULT 0
|
|
|
|
+#define ATH11K_FW_READY_DELAY 100 /* 100 msec */
|
|
+#define ATH11K_COLD_BOOT_MAX_WAIT_LIMIT 400
|
|
+
|
|
+extern unsigned int enable_cold_boot_cal;
|
|
+
|
|
struct ath11k_base;
|
|
|
|
enum ath11k_qmi_file_type {
|