Skip to content
Permalink
Browse files
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 4b361cf ("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 <robimarko@gmail.com>
Cc: Thibaut Varène <hacks@slashdirt.org>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  • Loading branch information
chunkeey authored and intel-lab-lkp committed Oct 15, 2021
1 parent 0a49116 commit 9a08dd8f5ae4d035f503db3a64ed4c6869b038e3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
@@ -12,6 +12,7 @@
#include <linux/dmi.h>
#include <linux/ctype.h>
#include <linux/pm_qos.h>
#include <linux/nvmem-consumer.h>
#include <asm/byteorder.h>

#include "core.h"
@@ -935,7 +936,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
}

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;
@@ -1726,7 +1728,8 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)

/* 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);
@@ -1853,6 +1856,39 @@ static int ath10k_download_cal_eeprom(struct ath10k *ar)
return ret;
}

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': %ld != %d\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)
{
@@ -2087,6 +2123,18 @@ static int ath10k_core_pre_cal_download(struct ath10k *ar)
{
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;
@@ -2153,6 +2201,18 @@ static int ath10k_download_cal_data(struct ath10k *ar)
"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;
@@ -877,8 +877,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,
};

@@ -898,10 +900,14 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
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";
}

0 comments on commit 9a08dd8

Please sign in to comment.