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