121254908SGregory Greenman // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 221254908SGregory Greenman /* 3*9e26f098SGregory Greenman * Copyright (C) 2020 - 2022 Intel Corporation 421254908SGregory Greenman */ 521254908SGregory Greenman 621254908SGregory Greenman #include "mvm.h" 721254908SGregory Greenman #include "fw/api/commands.h" 821254908SGregory Greenman #include "fw/api/phy-ctxt.h" 921254908SGregory Greenman 1000d667fcSYang Shen /* 1121254908SGregory Greenman * DDR needs frequency in units of 16.666MHz, so provide FW with the 1221254908SGregory Greenman * frequency values in the adjusted format. 1321254908SGregory Greenman */ 14cd7ae549SWei Yongjun static const struct iwl_rfi_lut_entry iwl_rfi_table[IWL_RFI_LUT_SIZE] = { 155c3310c2SGregory Greenman /* frequency 2667MHz */ 165c3310c2SGregory Greenman {cpu_to_le16(160), {50, 58, 60, 62, 64, 52, 54, 56}, 175c3310c2SGregory Greenman {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 185c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 195c3310c2SGregory Greenman 205c3310c2SGregory Greenman /* frequency 2933MHz */ 215c3310c2SGregory Greenman {cpu_to_le16(176), {149, 151, 153, 157, 159, 161, 165, 163, 167, 169, 225c3310c2SGregory Greenman 171, 173, 175}, 235c3310c2SGregory Greenman {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 245c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 255c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 265c3310c2SGregory Greenman 275c3310c2SGregory Greenman /* frequency 3200MHz */ 285c3310c2SGregory Greenman {cpu_to_le16(192), {79, 81, 83, 85, 87, 89, 91, 93}, 295c3310c2SGregory Greenman {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 305c3310c2SGregory Greenman PHY_BAND_6, PHY_BAND_6, PHY_BAND_6,}}, 3121254908SGregory Greenman 3221254908SGregory Greenman /* frequency 3733MHz */ 335c3310c2SGregory Greenman {cpu_to_le16(223), {114, 116, 118, 120, 122, 106, 110, 124, 126}, 345c3310c2SGregory Greenman {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 355c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 365c3310c2SGregory Greenman 375c3310c2SGregory Greenman /* frequency 4000MHz */ 385c3310c2SGregory Greenman {cpu_to_le16(240), {114, 151, 155, 157, 159, 161, 165}, 395c3310c2SGregory Greenman {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 405c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5,}}, 4121254908SGregory Greenman 4221254908SGregory Greenman /* frequency 4267MHz */ 4321254908SGregory Greenman {cpu_to_le16(256), {79, 83, 85, 87, 89, 91, 93,}, 4421254908SGregory Greenman {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 4521254908SGregory Greenman PHY_BAND_6, PHY_BAND_6,}}, 4621254908SGregory Greenman 4721254908SGregory Greenman /* frequency 4400MHz */ 4821254908SGregory Greenman {cpu_to_le16(264), {111, 119, 123, 125, 129, 131, 133, 135, 143,}, 4921254908SGregory Greenman {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 5021254908SGregory Greenman PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6,}}, 5121254908SGregory Greenman 5221254908SGregory Greenman /* frequency 5200MHz */ 535c3310c2SGregory Greenman {cpu_to_le16(312), {36, 38, 40, 42, 44, 46, 50,}, 545c3310c2SGregory Greenman {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 555c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5,}}, 565c3310c2SGregory Greenman 575c3310c2SGregory Greenman /* frequency 5600MHz */ 585c3310c2SGregory Greenman {cpu_to_le16(336), {106, 110, 112, 114, 116, 118, 120, 122}, 595c3310c2SGregory Greenman {PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, 605c3310c2SGregory Greenman PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, 6121254908SGregory Greenman 6221254908SGregory Greenman /* frequency 6000MHz */ 6321254908SGregory Greenman {cpu_to_le16(360), {3, 5, 7, 9, 11, 13, 15,}, 6421254908SGregory Greenman {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 6521254908SGregory Greenman PHY_BAND_6, PHY_BAND_6,}}, 6621254908SGregory Greenman 6721254908SGregory Greenman /* frequency 6400MHz */ 6821254908SGregory Greenman {cpu_to_le16(384), {79, 83, 85, 87, 89, 91, 93,}, 6921254908SGregory Greenman {PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, 7021254908SGregory Greenman PHY_BAND_6, PHY_BAND_6,}}, 7121254908SGregory Greenman }; 7221254908SGregory Greenman 73*9e26f098SGregory Greenman bool iwl_rfi_supported(struct iwl_mvm *mvm) 74*9e26f098SGregory Greenman { 75*9e26f098SGregory Greenman /* The feature depends on a platform bugfix, so for now 76*9e26f098SGregory Greenman * it's always disabled. 77*9e26f098SGregory Greenman * When the platform support detection is implemented we should 78*9e26f098SGregory Greenman * check FW TLV and platform support instead. 79*9e26f098SGregory Greenman */ 80*9e26f098SGregory Greenman return false; 81*9e26f098SGregory Greenman } 82*9e26f098SGregory Greenman 8321254908SGregory Greenman int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table) 8421254908SGregory Greenman { 8521254908SGregory Greenman int ret; 8621254908SGregory Greenman struct iwl_rfi_config_cmd cmd; 8721254908SGregory Greenman struct iwl_host_cmd hcmd = { 8821254908SGregory Greenman .id = WIDE_ID(SYSTEM_GROUP, RFI_CONFIG_CMD), 8921254908SGregory Greenman .dataflags[0] = IWL_HCMD_DFL_DUP, 9021254908SGregory Greenman .data[0] = &cmd, 9121254908SGregory Greenman .len[0] = sizeof(cmd), 9221254908SGregory Greenman }; 9321254908SGregory Greenman 94*9e26f098SGregory Greenman if (!iwl_rfi_supported(mvm)) 9521254908SGregory Greenman return -EOPNOTSUPP; 9621254908SGregory Greenman 9739fb06f7SGregory Greenman lockdep_assert_held(&mvm->mutex); 9839fb06f7SGregory Greenman 9921254908SGregory Greenman /* in case no table is passed, use the default one */ 10021254908SGregory Greenman if (!rfi_table) { 10121254908SGregory Greenman memcpy(cmd.table, iwl_rfi_table, sizeof(cmd.table)); 10221254908SGregory Greenman } else { 10321254908SGregory Greenman memcpy(cmd.table, rfi_table, sizeof(cmd.table)); 10421254908SGregory Greenman /* notify FW the table is not the default one */ 10521254908SGregory Greenman cmd.oem = 1; 10621254908SGregory Greenman } 10721254908SGregory Greenman 10821254908SGregory Greenman ret = iwl_mvm_send_cmd(mvm, &hcmd); 10921254908SGregory Greenman 11021254908SGregory Greenman if (ret) 11121254908SGregory Greenman IWL_ERR(mvm, "Failed to send RFI config cmd %d\n", ret); 11221254908SGregory Greenman 11321254908SGregory Greenman return ret; 11421254908SGregory Greenman } 11521254908SGregory Greenman 11621254908SGregory Greenman struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm) 11721254908SGregory Greenman { 11821254908SGregory Greenman struct iwl_rfi_freq_table_resp_cmd *resp; 11921254908SGregory Greenman int resp_size = sizeof(*resp); 12021254908SGregory Greenman int ret; 12121254908SGregory Greenman struct iwl_host_cmd cmd = { 12221254908SGregory Greenman .id = WIDE_ID(SYSTEM_GROUP, RFI_GET_FREQ_TABLE_CMD), 12321254908SGregory Greenman .flags = CMD_WANT_SKB, 12421254908SGregory Greenman }; 12521254908SGregory Greenman 126*9e26f098SGregory Greenman if (!iwl_rfi_supported(mvm)) 12721254908SGregory Greenman return ERR_PTR(-EOPNOTSUPP); 12821254908SGregory Greenman 12921254908SGregory Greenman mutex_lock(&mvm->mutex); 13021254908SGregory Greenman ret = iwl_mvm_send_cmd(mvm, &cmd); 13121254908SGregory Greenman mutex_unlock(&mvm->mutex); 13221254908SGregory Greenman if (ret) 13321254908SGregory Greenman return ERR_PTR(ret); 13421254908SGregory Greenman 13521254908SGregory Greenman if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) != resp_size)) 13621254908SGregory Greenman return ERR_PTR(-EIO); 13721254908SGregory Greenman 13808186e25SBixuan Cui resp = kmemdup(cmd.resp_pkt->data, resp_size, GFP_KERNEL); 13921254908SGregory Greenman if (!resp) 14021254908SGregory Greenman return ERR_PTR(-ENOMEM); 14121254908SGregory Greenman 14221254908SGregory Greenman iwl_free_resp(&cmd); 14321254908SGregory Greenman return resp; 14421254908SGregory Greenman } 14563b62a2dSGregory Greenman 14663b62a2dSGregory Greenman void iwl_rfi_deactivate_notif_handler(struct iwl_mvm *mvm, 14763b62a2dSGregory Greenman struct iwl_rx_cmd_buffer *rxb) 14863b62a2dSGregory Greenman { 14963b62a2dSGregory Greenman struct iwl_rx_packet *pkt = rxb_addr(rxb); 15063b62a2dSGregory Greenman struct iwl_rfi_deactivate_notif *notif = (void *)pkt->data; 15163b62a2dSGregory Greenman 15263b62a2dSGregory Greenman IWL_INFO(mvm, "RFIm is deactivated, reason = %d\n", notif->reason); 15363b62a2dSGregory Greenman } 154