1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2020 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 const static struct iwl_rfi_lut_entry iwl_rfi_table[IWL_RFI_LUT_SIZE] = { 15 /* LPDDR4 */ 16 17 /* frequency 3733MHz */ 18 {cpu_to_le16(223), {114, 116, 118, 120, 122,}, 19 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 20 21 /* frequency 4267MHz */ 22 {cpu_to_le16(256), {79, 83, 85, 87, 89, 91, 93,}, 23 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 24 PHY_BAND_6, PHY_BAND_6,}}, 25 26 /* DDR5ePOR */ 27 28 /* frequency 4000MHz */ 29 {cpu_to_le16(240), {3, 5, 7, 9, 11, 13, 15,}, 30 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 31 PHY_BAND_6, PHY_BAND_6,}}, 32 33 /* frequency 4400MHz */ 34 {cpu_to_le16(264), {111, 119, 123, 125, 129, 131, 133, 135, 143,}, 35 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 36 PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6,}}, 37 38 /* LPDDR5iPOR */ 39 40 /* frequency 5200MHz */ 41 {cpu_to_le16(312), {36, 38, 40, 42, 50,}, 42 {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 43 44 /* frequency 6000MHz */ 45 {cpu_to_le16(360), {3, 5, 7, 9, 11, 13, 15,}, 46 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 47 PHY_BAND_6, PHY_BAND_6,}}, 48 49 /* frequency 6400MHz */ 50 {cpu_to_le16(384), {79, 83, 85, 87, 89, 91, 93,}, 51 {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 52 PHY_BAND_6, PHY_BAND_6,}}, 53 }; 54 55 int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table) 56 { 57 int ret; 58 struct iwl_rfi_config_cmd cmd; 59 struct iwl_host_cmd hcmd = { 60 .id = WIDE_ID(SYSTEM_GROUP, RFI_CONFIG_CMD), 61 .dataflags[0] = IWL_HCMD_DFL_DUP, 62 .data[0] = &cmd, 63 .len[0] = sizeof(cmd), 64 }; 65 66 if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) 67 return -EOPNOTSUPP; 68 69 /* in case no table is passed, use the default one */ 70 if (!rfi_table) { 71 memcpy(cmd.table, iwl_rfi_table, sizeof(cmd.table)); 72 } else { 73 memcpy(cmd.table, rfi_table, sizeof(cmd.table)); 74 /* notify FW the table is not the default one */ 75 cmd.oem = 1; 76 } 77 78 mutex_lock(&mvm->mutex); 79 ret = iwl_mvm_send_cmd(mvm, &hcmd); 80 mutex_unlock(&mvm->mutex); 81 82 if (ret) 83 IWL_ERR(mvm, "Failed to send RFI config cmd %d\n", ret); 84 85 return ret; 86 } 87 88 struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm) 89 { 90 struct iwl_rfi_freq_table_resp_cmd *resp; 91 int resp_size = sizeof(*resp); 92 int ret; 93 struct iwl_host_cmd cmd = { 94 .id = WIDE_ID(SYSTEM_GROUP, RFI_GET_FREQ_TABLE_CMD), 95 .flags = CMD_WANT_SKB, 96 }; 97 98 if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) 99 return ERR_PTR(-EOPNOTSUPP); 100 101 mutex_lock(&mvm->mutex); 102 ret = iwl_mvm_send_cmd(mvm, &cmd); 103 mutex_unlock(&mvm->mutex); 104 if (ret) 105 return ERR_PTR(ret); 106 107 if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) != resp_size)) 108 return ERR_PTR(-EIO); 109 110 resp = kzalloc(resp_size, GFP_KERNEL); 111 if (!resp) 112 return ERR_PTR(-ENOMEM); 113 114 memcpy(resp, cmd.resp_pkt->data, resp_size); 115 116 iwl_free_resp(&cmd); 117 return resp; 118 } 119