1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2020 - 2022 Intel Corporation 4 */ 5 6 #include "mvm.h" 7 #include "fw/api/commands.h" 8 #include "fw/api/phy-ctxt.h" 9 10 /* 11 * DDR needs frequency in units of 16.666MHz, so provide FW with the 12 * frequency values in the adjusted format. 13 */ 14 static const struct iwl_rfi_lut_entry iwl_rfi_table[IWL_RFI_LUT_SIZE] = { 15 /* frequency 2667MHz */ 16 {cpu_to_le16(160), {50, 58, 60, 62, 64, 52, 54, 56}, 17 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 18 PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 19 20 /* frequency 2933MHz */ 21 {cpu_to_le16(176), {149, 151, 153, 157, 159, 161, 165, 163, 167, 169, 22 171, 173, 175}, 23 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 24 PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 25 PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 26 27 /* frequency 3200MHz */ 28 {cpu_to_le16(192), {79, 81, 83, 85, 87, 89, 91, 93}, 29 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 30 PHY_BAND_6, PHY_BAND_6, PHY_BAND_6,}}, 31 32 /* frequency 3733MHz */ 33 {cpu_to_le16(223), {114, 116, 118, 120, 122, 106, 110, 124, 126}, 34 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 35 PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 36 37 /* frequency 4000MHz */ 38 {cpu_to_le16(240), {114, 151, 155, 157, 159, 161, 165}, 39 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 40 PHY_BAND_5, PHY_BAND_5,}}, 41 42 /* frequency 4267MHz */ 43 {cpu_to_le16(256), {79, 83, 85, 87, 89, 91, 93,}, 44 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 45 PHY_BAND_6, PHY_BAND_6,}}, 46 47 /* frequency 4400MHz */ 48 {cpu_to_le16(264), {111, 119, 123, 125, 129, 131, 133, 135, 143,}, 49 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 50 PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6,}}, 51 52 /* frequency 5200MHz */ 53 {cpu_to_le16(312), {36, 38, 40, 42, 44, 46, 50,}, 54 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 55 PHY_BAND_5, PHY_BAND_5,}}, 56 57 /* frequency 5600MHz */ 58 {cpu_to_le16(336), {106, 110, 112, 114, 116, 118, 120, 122}, 59 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 60 PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 61 62 /* frequency 6000MHz */ 63 {cpu_to_le16(360), {3, 5, 7, 9, 11, 13, 15,}, 64 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 65 PHY_BAND_6, PHY_BAND_6,}}, 66 67 /* frequency 6400MHz */ 68 {cpu_to_le16(384), {79, 83, 85, 87, 89, 91, 93,}, 69 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 70 PHY_BAND_6, PHY_BAND_6,}}, 71 }; 72 73 bool iwl_rfi_supported(struct iwl_mvm *mvm) 74 { 75 /* The feature depends on a platform bugfix, so for now 76 * it's always disabled. 77 * When the platform support detection is implemented we should 78 * check FW TLV and platform support instead. 79 */ 80 return false; 81 } 82 83 int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table) 84 { 85 int ret; 86 struct iwl_rfi_config_cmd cmd; 87 struct iwl_host_cmd hcmd = { 88 .id = WIDE_ID(SYSTEM_GROUP, RFI_CONFIG_CMD), 89 .dataflags[0] = IWL_HCMD_DFL_DUP, 90 .data[0] = &cmd, 91 .len[0] = sizeof(cmd), 92 }; 93 94 if (!iwl_rfi_supported(mvm)) 95 return -EOPNOTSUPP; 96 97 lockdep_assert_held(&mvm->mutex); 98 99 /* in case no table is passed, use the default one */ 100 if (!rfi_table) { 101 memcpy(cmd.table, iwl_rfi_table, sizeof(cmd.table)); 102 } else { 103 memcpy(cmd.table, rfi_table, sizeof(cmd.table)); 104 /* notify FW the table is not the default one */ 105 cmd.oem = 1; 106 } 107 108 ret = iwl_mvm_send_cmd(mvm, &hcmd); 109 110 if (ret) 111 IWL_ERR(mvm, "Failed to send RFI config cmd %d\n", ret); 112 113 return ret; 114 } 115 116 struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm) 117 { 118 struct iwl_rfi_freq_table_resp_cmd *resp; 119 int resp_size = sizeof(*resp); 120 int ret; 121 struct iwl_host_cmd cmd = { 122 .id = WIDE_ID(SYSTEM_GROUP, RFI_GET_FREQ_TABLE_CMD), 123 .flags = CMD_WANT_SKB, 124 }; 125 126 if (!iwl_rfi_supported(mvm)) 127 return ERR_PTR(-EOPNOTSUPP); 128 129 mutex_lock(&mvm->mutex); 130 ret = iwl_mvm_send_cmd(mvm, &cmd); 131 mutex_unlock(&mvm->mutex); 132 if (ret) 133 return ERR_PTR(ret); 134 135 if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) != 136 resp_size)) { 137 iwl_free_resp(&cmd); 138 return ERR_PTR(-EIO); 139 } 140 141 resp = kmemdup(cmd.resp_pkt->data, resp_size, GFP_KERNEL); 142 iwl_free_resp(&cmd); 143 144 if (!resp) 145 return ERR_PTR(-ENOMEM); 146 147 return resp; 148 } 149 150 void iwl_rfi_deactivate_notif_handler(struct iwl_mvm *mvm, 151 struct iwl_rx_cmd_buffer *rxb) 152 { 153 struct iwl_rx_packet *pkt = rxb_addr(rxb); 154 struct iwl_rfi_deactivate_notif *notif = (void *)pkt->data; 155 156 IWL_INFO(mvm, "RFIm is deactivated, reason = %d\n", notif->reason); 157 } 158