forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/net/wireless/ath/ath10k/hw.c
....@@ -1,21 +1,11 @@
1
+// SPDX-License-Identifier: ISC
12 /*
23 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
3
- *
4
- * Permission to use, copy, modify, and/or distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
7
- *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
154 */
165
176 #include <linux/types.h>
187 #include <linux/bitops.h>
8
+#include <linux/bitfield.h>
199 #include "core.h"
2010 #include "hw.h"
2111 #include "hif.h"
....@@ -165,6 +155,9 @@
165155 .num_target_ce_config_wlan = 7,
166156 .ce_desc_meta_data_mask = 0xFFFC,
167157 .ce_desc_meta_data_lsb = 2,
158
+ .rfkill_pin = 16,
159
+ .rfkill_cfg = 0,
160
+ .rfkill_on_level = 1,
168161 };
169162
170163 const struct ath10k_hw_values qca99x0_values = {
....@@ -317,9 +310,11 @@
317310 };
318311
319312 const struct ath10k_hw_ce_regs wcn3990_ce_regs = {
320
- .sr_base_addr = 0x00000000,
313
+ .sr_base_addr_lo = 0x00000000,
314
+ .sr_base_addr_hi = 0x00000004,
321315 .sr_size_addr = 0x00000008,
322
- .dr_base_addr = 0x0000000c,
316
+ .dr_base_addr_lo = 0x0000000c,
317
+ .dr_base_addr_hi = 0x00000010,
323318 .dr_size_addr = 0x00000014,
324319 .misc_ie_addr = 0x00000034,
325320 .sr_wr_index_addr = 0x0000003c,
....@@ -463,9 +458,9 @@
463458 };
464459
465460 const struct ath10k_hw_ce_regs qcax_ce_regs = {
466
- .sr_base_addr = 0x00000000,
461
+ .sr_base_addr_lo = 0x00000000,
467462 .sr_size_addr = 0x00000004,
468
- .dr_base_addr = 0x00000008,
463
+ .dr_base_addr_lo = 0x00000008,
469464 .dr_size_addr = 0x0000000c,
470465 .ce_cmd_addr = 0x00000018,
471466 .misc_ie_addr = 0x00000034,
....@@ -918,8 +913,225 @@
918913 return 0;
919914 }
920915
916
+/* Program CPU_ADDR_MSB to allow different memory
917
+ * region access.
918
+ */
919
+static void ath10k_hw_map_target_mem(struct ath10k *ar, u32 msb)
920
+{
921
+ u32 address = SOC_CORE_BASE_ADDRESS + FW_RAM_CONFIG_ADDRESS;
922
+
923
+ ath10k_hif_write32(ar, address, msb);
924
+}
925
+
926
+/* 1. Write to memory region of target, such as IRAM adn DRAM.
927
+ * 2. Target address( 0 ~ 00100000 & 0x00400000~0x00500000)
928
+ * can be written directly. See ath10k_pci_targ_cpu_to_ce_addr() too.
929
+ * 3. In order to access the region other than the above,
930
+ * we need to set the value of register CPU_ADDR_MSB.
931
+ * 4. Target memory access space is limited to 1M size. If the size is larger
932
+ * than 1M, need to split it and program CPU_ADDR_MSB accordingly.
933
+ */
934
+static int ath10k_hw_diag_segment_msb_download(struct ath10k *ar,
935
+ const void *buffer,
936
+ u32 address,
937
+ u32 length)
938
+{
939
+ u32 addr = address & REGION_ACCESS_SIZE_MASK;
940
+ int ret, remain_size, size;
941
+ const u8 *buf;
942
+
943
+ ath10k_hw_map_target_mem(ar, CPU_ADDR_MSB_REGION_VAL(address));
944
+
945
+ if (addr + length > REGION_ACCESS_SIZE_LIMIT) {
946
+ size = REGION_ACCESS_SIZE_LIMIT - addr;
947
+ remain_size = length - size;
948
+
949
+ ret = ath10k_hif_diag_write(ar, address, buffer, size);
950
+ if (ret) {
951
+ ath10k_warn(ar,
952
+ "failed to download the first %d bytes segment to address:0x%x: %d\n",
953
+ size, address, ret);
954
+ goto done;
955
+ }
956
+
957
+ /* Change msb to the next memory region*/
958
+ ath10k_hw_map_target_mem(ar,
959
+ CPU_ADDR_MSB_REGION_VAL(address) + 1);
960
+ buf = buffer + size;
961
+ ret = ath10k_hif_diag_write(ar,
962
+ address & ~REGION_ACCESS_SIZE_MASK,
963
+ buf, remain_size);
964
+ if (ret) {
965
+ ath10k_warn(ar,
966
+ "failed to download the second %d bytes segment to address:0x%x: %d\n",
967
+ remain_size,
968
+ address & ~REGION_ACCESS_SIZE_MASK,
969
+ ret);
970
+ goto done;
971
+ }
972
+ } else {
973
+ ret = ath10k_hif_diag_write(ar, address, buffer, length);
974
+ if (ret) {
975
+ ath10k_warn(ar,
976
+ "failed to download the only %d bytes segment to address:0x%x: %d\n",
977
+ length, address, ret);
978
+ goto done;
979
+ }
980
+ }
981
+
982
+done:
983
+ /* Change msb to DRAM */
984
+ ath10k_hw_map_target_mem(ar,
985
+ CPU_ADDR_MSB_REGION_VAL(DRAM_BASE_ADDRESS));
986
+ return ret;
987
+}
988
+
989
+static int ath10k_hw_diag_segment_download(struct ath10k *ar,
990
+ const void *buffer,
991
+ u32 address,
992
+ u32 length)
993
+{
994
+ if (address >= DRAM_BASE_ADDRESS + REGION_ACCESS_SIZE_LIMIT)
995
+ /* Needs to change MSB for memory write */
996
+ return ath10k_hw_diag_segment_msb_download(ar, buffer,
997
+ address, length);
998
+ else
999
+ return ath10k_hif_diag_write(ar, address, buffer, length);
1000
+}
1001
+
1002
+int ath10k_hw_diag_fast_download(struct ath10k *ar,
1003
+ u32 address,
1004
+ const void *buffer,
1005
+ u32 length)
1006
+{
1007
+ const u8 *buf = buffer;
1008
+ bool sgmt_end = false;
1009
+ u32 base_addr = 0;
1010
+ u32 base_len = 0;
1011
+ u32 left = 0;
1012
+ struct bmi_segmented_file_header *hdr;
1013
+ struct bmi_segmented_metadata *metadata;
1014
+ int ret = 0;
1015
+
1016
+ if (length < sizeof(*hdr))
1017
+ return -EINVAL;
1018
+
1019
+ /* check firmware header. If it has no correct magic number
1020
+ * or it's compressed, returns error.
1021
+ */
1022
+ hdr = (struct bmi_segmented_file_header *)buf;
1023
+ if (__le32_to_cpu(hdr->magic_num) != BMI_SGMTFILE_MAGIC_NUM) {
1024
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
1025
+ "Not a supported firmware, magic_num:0x%x\n",
1026
+ hdr->magic_num);
1027
+ return -EINVAL;
1028
+ }
1029
+
1030
+ if (hdr->file_flags != 0) {
1031
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
1032
+ "Not a supported firmware, file_flags:0x%x\n",
1033
+ hdr->file_flags);
1034
+ return -EINVAL;
1035
+ }
1036
+
1037
+ metadata = (struct bmi_segmented_metadata *)hdr->data;
1038
+ left = length - sizeof(*hdr);
1039
+
1040
+ while (left > 0) {
1041
+ if (left < sizeof(*metadata)) {
1042
+ ath10k_warn(ar, "firmware segment is truncated: %d\n",
1043
+ left);
1044
+ ret = -EINVAL;
1045
+ break;
1046
+ }
1047
+ base_addr = __le32_to_cpu(metadata->addr);
1048
+ base_len = __le32_to_cpu(metadata->length);
1049
+ buf = metadata->data;
1050
+ left -= sizeof(*metadata);
1051
+
1052
+ switch (base_len) {
1053
+ case BMI_SGMTFILE_BEGINADDR:
1054
+ /* base_addr is the start address to run */
1055
+ ret = ath10k_bmi_set_start(ar, base_addr);
1056
+ base_len = 0;
1057
+ break;
1058
+ case BMI_SGMTFILE_DONE:
1059
+ /* no more segment */
1060
+ base_len = 0;
1061
+ sgmt_end = true;
1062
+ ret = 0;
1063
+ break;
1064
+ case BMI_SGMTFILE_BDDATA:
1065
+ case BMI_SGMTFILE_EXEC:
1066
+ ath10k_warn(ar,
1067
+ "firmware has unsupported segment:%d\n",
1068
+ base_len);
1069
+ ret = -EINVAL;
1070
+ break;
1071
+ default:
1072
+ if (base_len > left) {
1073
+ /* sanity check */
1074
+ ath10k_warn(ar,
1075
+ "firmware has invalid segment length, %d > %d\n",
1076
+ base_len, left);
1077
+ ret = -EINVAL;
1078
+ break;
1079
+ }
1080
+
1081
+ ret = ath10k_hw_diag_segment_download(ar,
1082
+ buf,
1083
+ base_addr,
1084
+ base_len);
1085
+
1086
+ if (ret)
1087
+ ath10k_warn(ar,
1088
+ "failed to download firmware via diag interface:%d\n",
1089
+ ret);
1090
+ break;
1091
+ }
1092
+
1093
+ if (ret || sgmt_end)
1094
+ break;
1095
+
1096
+ metadata = (struct bmi_segmented_metadata *)(buf + base_len);
1097
+ left -= base_len;
1098
+ }
1099
+
1100
+ if (ret == 0)
1101
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
1102
+ "boot firmware fast diag download successfully.\n");
1103
+ return ret;
1104
+}
1105
+
1106
+static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp)
1107
+{
1108
+ return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI);
1109
+}
1110
+
1111
+static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp)
1112
+{
1113
+ return (resp->data_tx_completion.flags2 &
1114
+ HTT_TX_DATA_RSSI_ENABLE_WCN3990);
1115
+}
1116
+
1117
+static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp)
1118
+{
1119
+ struct htt_data_tx_completion_ext extd;
1120
+ int pad_bytes = 0;
1121
+
1122
+ if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES)
1123
+ pad_bytes += sizeof(extd.a_retries) /
1124
+ sizeof(extd.msdus_rssi[0]);
1125
+
1126
+ if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP)
1127
+ pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]);
1128
+
1129
+ return pad_bytes;
1130
+}
1131
+
9211132 const struct ath10k_hw_ops qca988x_ops = {
9221133 .set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
1134
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
9231135 };
9241136
9251137 static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
....@@ -928,13 +1140,29 @@
9281140 RX_MSDU_END_INFO1_L3_HDR_PAD);
9291141 }
9301142
1143
+static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd)
1144
+{
1145
+ return !!(rxd->msdu_end.common.info0 &
1146
+ __cpu_to_le32(RX_MSDU_END_INFO0_MSDU_LIMIT_ERR));
1147
+}
1148
+
9311149 const struct ath10k_hw_ops qca99x0_ops = {
9321150 .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
1151
+ .rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error,
1152
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
9331153 };
9341154
9351155 const struct ath10k_hw_ops qca6174_ops = {
9361156 .set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
9371157 .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
1158
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
9381159 };
9391160
940
-const struct ath10k_hw_ops wcn3990_ops = {};
1161
+const struct ath10k_hw_ops qca6174_sdio_ops = {
1162
+ .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
1163
+};
1164
+
1165
+const struct ath10k_hw_ops wcn3990_ops = {
1166
+ .tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad,
1167
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990,
1168
+};