121254908SGregory Greenman // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
221254908SGregory Greenman /*
39e26f098SGregory 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 
iwl_rfi_supported(struct iwl_mvm * mvm)739e26f098SGregory Greenman bool iwl_rfi_supported(struct iwl_mvm *mvm)
749e26f098SGregory Greenman {
759e26f098SGregory Greenman 	/* The feature depends on a platform bugfix, so for now
769e26f098SGregory Greenman 	 * it's always disabled.
779e26f098SGregory Greenman 	 * When the platform support detection is implemented we should
789e26f098SGregory Greenman 	 * check FW TLV and platform support instead.
799e26f098SGregory Greenman 	 */
809e26f098SGregory Greenman 	return false;
819e26f098SGregory Greenman }
829e26f098SGregory Greenman 
iwl_rfi_send_config_cmd(struct iwl_mvm * mvm,struct iwl_rfi_lut_entry * rfi_table)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 
949e26f098SGregory 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 
iwl_rfi_get_freq_table(struct iwl_mvm * mvm)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 
1269e26f098SGregory 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 
135*c0a40f2fSJohannes Berg 	if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) !=
136*c0a40f2fSJohannes Berg 			 resp_size)) {
137*c0a40f2fSJohannes Berg 		iwl_free_resp(&cmd);
13821254908SGregory Greenman 		return ERR_PTR(-EIO);
139*c0a40f2fSJohannes Berg 	}
14021254908SGregory Greenman 
14108186e25SBixuan Cui 	resp = kmemdup(cmd.resp_pkt->data, resp_size, GFP_KERNEL);
142*c0a40f2fSJohannes Berg 	iwl_free_resp(&cmd);
143*c0a40f2fSJohannes Berg 
14421254908SGregory Greenman 	if (!resp)
14521254908SGregory Greenman 		return ERR_PTR(-ENOMEM);
14621254908SGregory Greenman 
14721254908SGregory Greenman 	return resp;
14821254908SGregory Greenman }
14963b62a2dSGregory Greenman 
iwl_rfi_deactivate_notif_handler(struct iwl_mvm * mvm,struct iwl_rx_cmd_buffer * rxb)15063b62a2dSGregory Greenman void iwl_rfi_deactivate_notif_handler(struct iwl_mvm *mvm,
15163b62a2dSGregory Greenman 				      struct iwl_rx_cmd_buffer *rxb)
15263b62a2dSGregory Greenman {
15363b62a2dSGregory Greenman 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
15463b62a2dSGregory Greenman 	struct iwl_rfi_deactivate_notif *notif = (void *)pkt->data;
15563b62a2dSGregory Greenman 
15663b62a2dSGregory Greenman 	IWL_INFO(mvm, "RFIm is deactivated, reason = %d\n", notif->reason);
15763b62a2dSGregory Greenman }
158