123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- From e2333703373e8b81294da5d1c73c30154f75b082 Mon Sep 17 00:00:00 2001
- From: Christian Lamparter <[email protected]>
- Date: Fri, 15 Oct 2021 18:56:33 +0200
- Subject: [PATCH] ath10k: fetch (pre-)calibration data via nvmem subsystem
- On most embedded ath10k devices (like range extenders,
- routers, accesspoints, ...) the calibration data is
- stored in a easily accessible MTD partitions named
- "ART", "caldata", "calibration", etc...
- Since commit 4b361cfa8624 ("mtd: core: add OTP nvmem provider support"):
- MTD partitions and portions of them can be specified
- as potential nvmem-cells which are accessible through
- the nvmem subsystem.
- This feature - together with an nvmem cell definition either
- in the platform data or via device-tree allows drivers to get
- the (pre-)calibration data which is required for initializing
- the WIFI.
- Tested with Netgear EX6150v2 (IPQ4018)
- Cc: Robert Marko <[email protected]>
- Cc: Thibaut Varene <[email protected]>
- Signed-off-by: Christian Lamparter <[email protected]>
- ---
- --- a/ath10k-5.15/core.c
- +++ b/ath10k-5.15/core.c
- @@ -13,6 +13,7 @@
- #include <linux/dmi.h>
- #include <linux/ctype.h>
- #include <linux/pm_qos.h>
- +#include <linux/nvmem-consumer.h>
- #include <asm/byteorder.h>
- #include <linux/ctype.h>
-
- @@ -1005,7 +1006,8 @@ static int ath10k_core_get_board_id_from
- }
-
- if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
- - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
- + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
- + ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
- bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
- else
- bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
- @@ -2115,7 +2117,8 @@ static int ath10k_download_and_run_otp(s
-
- /* As of now pre-cal is valid for 10_4 variants */
- if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
- - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
- + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
- + ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
- bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
-
- ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
- @@ -2249,6 +2252,39 @@ struct ath10k_bss_rom_ie {
- __le32 rom_len;
- } __packed;
-
- +static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)
- +{
- + struct nvmem_cell *cell;
- + void *buf;
- + size_t len;
- + int ret;
- +
- + cell = devm_nvmem_cell_get(ar->dev, cell_name);
- + if (IS_ERR(cell)) {
- + ret = PTR_ERR(cell);
- + return ret;
- + }
- +
- + buf = nvmem_cell_read(cell, &len);
- + if (IS_ERR(buf))
- + return PTR_ERR(buf);
- +
- + if (ar->hw_params.cal_data_len != len) {
- + kfree(buf);
- + ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n",
- + cell_name, len, ar->hw_params.cal_data_len);
- + return -EMSGSIZE;
- + }
- +
- + ret = ath10k_download_board_data(ar, buf, len);
- + kfree(buf);
- + if (ret)
- + ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",
- + cell_name, ret);
- +
- + return ret;
- +}
- +
- int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
- struct ath10k_fw_file *fw_file)
- {
- @@ -2625,6 +2661,18 @@ static int ath10k_core_pre_cal_download(
- {
- int ret;
-
- + ret = ath10k_download_cal_nvmem(ar, "pre-calibration");
- + if (ret == 0) {
- + ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM;
- + goto success;
- + } else if (ret == -EPROBE_DEFER) {
- + return ret;
- + }
- +
- + ath10k_dbg(ar, ATH10K_DBG_BOOT,
- + "boot did not find a pre-calibration nvmem-cell, try file next: %d\n",
- + ret);
- +
- ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
- if (ret == 0) {
- ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
- @@ -2691,6 +2739,18 @@ static int ath10k_download_cal_data(stru
- "pre cal download procedure failed, try cal file: %d\n",
- ret);
-
- + ret = ath10k_download_cal_nvmem(ar, "calibration");
- + if (ret == 0) {
- + ar->cal_mode = ATH10K_CAL_MODE_NVMEM;
- + goto done;
- + } else if (ret == -EPROBE_DEFER) {
- + return ret;
- + }
- +
- + ath10k_dbg(ar, ATH10K_DBG_BOOT,
- + "boot did not find a calibration nvmem-cell, try file next: %d\n",
- + ret);
- +
- ret = ath10k_download_cal_file(ar, ar->cal_file);
- if (ret == 0) {
- ar->cal_mode = ATH10K_CAL_MODE_FILE;
- --- a/ath10k-5.15/core.h
- +++ b/ath10k-5.15/core.h
- @@ -1109,8 +1109,10 @@ enum ath10k_cal_mode {
- ATH10K_CAL_MODE_FILE,
- ATH10K_CAL_MODE_OTP,
- ATH10K_CAL_MODE_DT,
- + ATH10K_CAL_MODE_NVMEM,
- ATH10K_PRE_CAL_MODE_FILE,
- ATH10K_PRE_CAL_MODE_DT,
- + ATH10K_PRE_CAL_MODE_NVMEM,
- ATH10K_CAL_MODE_EEPROM,
- };
-
- @@ -1130,10 +1132,14 @@ static inline const char *ath10k_cal_mod
- return "otp";
- case ATH10K_CAL_MODE_DT:
- return "dt";
- + case ATH10K_CAL_MODE_NVMEM:
- + return "nvmem";
- case ATH10K_PRE_CAL_MODE_FILE:
- return "pre-cal-file";
- case ATH10K_PRE_CAL_MODE_DT:
- return "pre-cal-dt";
- + case ATH10K_PRE_CAL_MODE_NVMEM:
- + return "pre-cal-nvmem";
- case ATH10K_CAL_MODE_EEPROM:
- return "eeprom";
- }
|