 6d0099d1a1
			
		
	
	6d0099d1a1
	
	
		
			
	
		
	
	
		
			Some checks failed
		
		
	
	Build Kernel / Build all affected Kernels (push) Has been cancelled
				
			Build all core packages / Build all core packages for selected target (push) Has been cancelled
				
			Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
				
			Build Toolchains / Build Toolchains for each target (push) Has been cancelled
				
			Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
				
			Coverity scan build / Coverity x86/64 build (push) Has been cancelled
				
			
		
			
				
	
	
		
			163 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From e2333703373e8b81294da5d1c73c30154f75b082 Mon Sep 17 00:00:00 2001
 | |
| From: Christian Lamparter <chunkeey@gmail.com>
 | |
| 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 <robimarko@gmail.com>
 | |
| Cc: Thibaut Varene <hacks@slashdirt.org>
 | |
| Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
 | |
| ---
 | |
| --- 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";
 | |
|  	}
 |