120-ath10k-fetch-calibration-data-via-nvmem-subsystem.patch 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. From e2333703373e8b81294da5d1c73c30154f75b082 Mon Sep 17 00:00:00 2001
  2. From: Christian Lamparter <[email protected]>
  3. Date: Fri, 15 Oct 2021 18:56:33 +0200
  4. Subject: [PATCH] ath10k: fetch (pre-)calibration data via nvmem subsystem
  5. On most embedded ath10k devices (like range extenders,
  6. routers, accesspoints, ...) the calibration data is
  7. stored in a easily accessible MTD partitions named
  8. "ART", "caldata", "calibration", etc...
  9. Since commit 4b361cfa8624 ("mtd: core: add OTP nvmem provider support"):
  10. MTD partitions and portions of them can be specified
  11. as potential nvmem-cells which are accessible through
  12. the nvmem subsystem.
  13. This feature - together with an nvmem cell definition either
  14. in the platform data or via device-tree allows drivers to get
  15. the (pre-)calibration data which is required for initializing
  16. the WIFI.
  17. Tested with Netgear EX6150v2 (IPQ4018)
  18. Cc: Robert Marko <[email protected]>
  19. Cc: Thibaut Varene <[email protected]>
  20. Signed-off-by: Christian Lamparter <[email protected]>
  21. ---
  22. --- a/ath10k-5.15/core.c
  23. +++ b/ath10k-5.15/core.c
  24. @@ -13,6 +13,7 @@
  25. #include <linux/dmi.h>
  26. #include <linux/ctype.h>
  27. #include <linux/pm_qos.h>
  28. +#include <linux/nvmem-consumer.h>
  29. #include <asm/byteorder.h>
  30. #include <linux/ctype.h>
  31. @@ -1005,7 +1006,8 @@ static int ath10k_core_get_board_id_from
  32. }
  33. if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
  34. - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
  35. + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
  36. + ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
  37. bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
  38. else
  39. bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
  40. @@ -2115,7 +2117,8 @@ static int ath10k_download_and_run_otp(s
  41. /* As of now pre-cal is valid for 10_4 variants */
  42. if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
  43. - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
  44. + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
  45. + ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
  46. bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
  47. ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
  48. @@ -2249,6 +2252,39 @@ struct ath10k_bss_rom_ie {
  49. __le32 rom_len;
  50. } __packed;
  51. +static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)
  52. +{
  53. + struct nvmem_cell *cell;
  54. + void *buf;
  55. + size_t len;
  56. + int ret;
  57. +
  58. + cell = devm_nvmem_cell_get(ar->dev, cell_name);
  59. + if (IS_ERR(cell)) {
  60. + ret = PTR_ERR(cell);
  61. + return ret;
  62. + }
  63. +
  64. + buf = nvmem_cell_read(cell, &len);
  65. + if (IS_ERR(buf))
  66. + return PTR_ERR(buf);
  67. +
  68. + if (ar->hw_params.cal_data_len != len) {
  69. + kfree(buf);
  70. + ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n",
  71. + cell_name, len, ar->hw_params.cal_data_len);
  72. + return -EMSGSIZE;
  73. + }
  74. +
  75. + ret = ath10k_download_board_data(ar, buf, len);
  76. + kfree(buf);
  77. + if (ret)
  78. + ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",
  79. + cell_name, ret);
  80. +
  81. + return ret;
  82. +}
  83. +
  84. int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
  85. struct ath10k_fw_file *fw_file)
  86. {
  87. @@ -2625,6 +2661,18 @@ static int ath10k_core_pre_cal_download(
  88. {
  89. int ret;
  90. + ret = ath10k_download_cal_nvmem(ar, "pre-calibration");
  91. + if (ret == 0) {
  92. + ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM;
  93. + goto success;
  94. + } else if (ret == -EPROBE_DEFER) {
  95. + return ret;
  96. + }
  97. +
  98. + ath10k_dbg(ar, ATH10K_DBG_BOOT,
  99. + "boot did not find a pre-calibration nvmem-cell, try file next: %d\n",
  100. + ret);
  101. +
  102. ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
  103. if (ret == 0) {
  104. ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
  105. @@ -2691,6 +2739,18 @@ static int ath10k_download_cal_data(stru
  106. "pre cal download procedure failed, try cal file: %d\n",
  107. ret);
  108. + ret = ath10k_download_cal_nvmem(ar, "calibration");
  109. + if (ret == 0) {
  110. + ar->cal_mode = ATH10K_CAL_MODE_NVMEM;
  111. + goto done;
  112. + } else if (ret == -EPROBE_DEFER) {
  113. + return ret;
  114. + }
  115. +
  116. + ath10k_dbg(ar, ATH10K_DBG_BOOT,
  117. + "boot did not find a calibration nvmem-cell, try file next: %d\n",
  118. + ret);
  119. +
  120. ret = ath10k_download_cal_file(ar, ar->cal_file);
  121. if (ret == 0) {
  122. ar->cal_mode = ATH10K_CAL_MODE_FILE;
  123. --- a/ath10k-5.15/core.h
  124. +++ b/ath10k-5.15/core.h
  125. @@ -1109,8 +1109,10 @@ enum ath10k_cal_mode {
  126. ATH10K_CAL_MODE_FILE,
  127. ATH10K_CAL_MODE_OTP,
  128. ATH10K_CAL_MODE_DT,
  129. + ATH10K_CAL_MODE_NVMEM,
  130. ATH10K_PRE_CAL_MODE_FILE,
  131. ATH10K_PRE_CAL_MODE_DT,
  132. + ATH10K_PRE_CAL_MODE_NVMEM,
  133. ATH10K_CAL_MODE_EEPROM,
  134. };
  135. @@ -1130,10 +1132,14 @@ static inline const char *ath10k_cal_mod
  136. return "otp";
  137. case ATH10K_CAL_MODE_DT:
  138. return "dt";
  139. + case ATH10K_CAL_MODE_NVMEM:
  140. + return "nvmem";
  141. case ATH10K_PRE_CAL_MODE_FILE:
  142. return "pre-cal-file";
  143. case ATH10K_PRE_CAL_MODE_DT:
  144. return "pre-cal-dt";
  145. + case ATH10K_PRE_CAL_MODE_NVMEM:
  146. + return "pre-cal-nvmem";
  147. case ATH10K_CAL_MODE_EEPROM:
  148. return "eeprom";
  149. }