18c2ecf20Sopenharmony_ci/******************************************************************************
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license.  When using or
48c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright(c) 2018 - 2021 Intel Corporation
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
118c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as
128c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
158c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
168c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
178c2ecf20Sopenharmony_ci * General Public License for more details.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * BSD LICENSE
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * Copyright(c) 2018 - 2020 Intel Corporation
228c2ecf20Sopenharmony_ci * All rights reserved.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
258c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
268c2ecf20Sopenharmony_ci * are met:
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci *  * Redistributions of source code must retain the above copyright
298c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
308c2ecf20Sopenharmony_ci *  * Redistributions in binary form must reproduce the above copyright
318c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
328c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
338c2ecf20Sopenharmony_ci *    distribution.
348c2ecf20Sopenharmony_ci *  * Neither the name Intel Corporation nor the names of its
358c2ecf20Sopenharmony_ci *    contributors may be used to endorse or promote products derived
368c2ecf20Sopenharmony_ci *    from this software without specific prior written permission.
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
398c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
408c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
418c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
428c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
438c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
448c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
458c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
468c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
478c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
488c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci *****************************************************************************/
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#include "iwl-trans.h"
538c2ecf20Sopenharmony_ci#include "iwl-fh.h"
548c2ecf20Sopenharmony_ci#include "iwl-context-info-gen3.h"
558c2ecf20Sopenharmony_ci#include "internal.h"
568c2ecf20Sopenharmony_ci#include "iwl-prph.h"
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic void
598c2ecf20Sopenharmony_ciiwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans,
608c2ecf20Sopenharmony_ci			      struct iwl_prph_scratch_hwm_cfg *dbg_cfg,
618c2ecf20Sopenharmony_ci			      u32 *control_flags)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	enum iwl_fw_ini_allocation_id alloc_id = IWL_FW_INI_ALLOCATION_ID_DBGC1;
648c2ecf20Sopenharmony_ci	struct iwl_fw_ini_allocation_tlv *fw_mon_cfg;
658c2ecf20Sopenharmony_ci	u32 dbg_flags = 0;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	if (!iwl_trans_dbg_ini_valid(trans)) {
688c2ecf20Sopenharmony_ci		struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci		iwl_pcie_alloc_fw_monitor(trans, 0);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci		if (fw_mon->size) {
738c2ecf20Sopenharmony_ci			dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci			IWL_DEBUG_FW(trans,
768c2ecf20Sopenharmony_ci				     "WRT: Applying DRAM buffer destination\n");
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci			dbg_cfg->hwm_base_addr = cpu_to_le64(fw_mon->physical);
798c2ecf20Sopenharmony_ci			dbg_cfg->hwm_size = cpu_to_le32(fw_mon->size);
808c2ecf20Sopenharmony_ci		}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci		goto out;
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	fw_mon_cfg = &trans->dbg.fw_mon_cfg[alloc_id];
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	switch (le32_to_cpu(fw_mon_cfg->buf_location)) {
888c2ecf20Sopenharmony_ci	case IWL_FW_INI_LOCATION_SRAM_PATH:
898c2ecf20Sopenharmony_ci		dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL;
908c2ecf20Sopenharmony_ci		IWL_DEBUG_FW(trans,
918c2ecf20Sopenharmony_ci				"WRT: Applying SMEM buffer destination\n");
928c2ecf20Sopenharmony_ci		break;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	case IWL_FW_INI_LOCATION_NPK_PATH:
958c2ecf20Sopenharmony_ci		dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF;
968c2ecf20Sopenharmony_ci		IWL_DEBUG_FW(trans,
978c2ecf20Sopenharmony_ci			     "WRT: Applying NPK buffer destination\n");
988c2ecf20Sopenharmony_ci		break;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	case IWL_FW_INI_LOCATION_DRAM_PATH:
1018c2ecf20Sopenharmony_ci		if (trans->dbg.fw_mon_ini[alloc_id].num_frags) {
1028c2ecf20Sopenharmony_ci			struct iwl_dram_data *frag =
1038c2ecf20Sopenharmony_ci				&trans->dbg.fw_mon_ini[alloc_id].frags[0];
1048c2ecf20Sopenharmony_ci			dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
1058c2ecf20Sopenharmony_ci			dbg_cfg->hwm_base_addr = cpu_to_le64(frag->physical);
1068c2ecf20Sopenharmony_ci			dbg_cfg->hwm_size = cpu_to_le32(frag->size);
1078c2ecf20Sopenharmony_ci			IWL_DEBUG_FW(trans,
1088c2ecf20Sopenharmony_ci				     "WRT: Applying DRAM destination (alloc_id=%u, num_frags=%u)\n",
1098c2ecf20Sopenharmony_ci				     alloc_id,
1108c2ecf20Sopenharmony_ci				     trans->dbg.fw_mon_ini[alloc_id].num_frags);
1118c2ecf20Sopenharmony_ci		}
1128c2ecf20Sopenharmony_ci		break;
1138c2ecf20Sopenharmony_ci	default:
1148c2ecf20Sopenharmony_ci		IWL_ERR(trans, "WRT: Invalid buffer destination\n");
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ciout:
1178c2ecf20Sopenharmony_ci	if (dbg_flags)
1188c2ecf20Sopenharmony_ci		*control_flags |= IWL_PRPH_SCRATCH_EARLY_DEBUG_EN | dbg_flags;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciint iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
1228c2ecf20Sopenharmony_ci				 const struct fw_img *fw)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
1258c2ecf20Sopenharmony_ci	struct iwl_context_info_gen3 *ctxt_info_gen3;
1268c2ecf20Sopenharmony_ci	struct iwl_prph_scratch *prph_scratch;
1278c2ecf20Sopenharmony_ci	struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl;
1288c2ecf20Sopenharmony_ci	struct iwl_prph_info *prph_info;
1298c2ecf20Sopenharmony_ci	u32 control_flags = 0;
1308c2ecf20Sopenharmony_ci	int ret;
1318c2ecf20Sopenharmony_ci	int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
1328c2ecf20Sopenharmony_ci			      trans->cfg->min_txq_size);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	switch (trans_pcie->rx_buf_size) {
1358c2ecf20Sopenharmony_ci	case IWL_AMSDU_DEF:
1368c2ecf20Sopenharmony_ci		return -EINVAL;
1378c2ecf20Sopenharmony_ci	case IWL_AMSDU_2K:
1388c2ecf20Sopenharmony_ci		break;
1398c2ecf20Sopenharmony_ci	case IWL_AMSDU_4K:
1408c2ecf20Sopenharmony_ci		control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
1418c2ecf20Sopenharmony_ci		break;
1428c2ecf20Sopenharmony_ci	case IWL_AMSDU_8K:
1438c2ecf20Sopenharmony_ci		control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
1448c2ecf20Sopenharmony_ci		/* if firmware supports the ext size, tell it */
1458c2ecf20Sopenharmony_ci		control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K;
1468c2ecf20Sopenharmony_ci		break;
1478c2ecf20Sopenharmony_ci	case IWL_AMSDU_12K:
1488c2ecf20Sopenharmony_ci		control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
1498c2ecf20Sopenharmony_ci		/* if firmware supports the ext size, tell it */
1508c2ecf20Sopenharmony_ci		control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K;
1518c2ecf20Sopenharmony_ci		break;
1528c2ecf20Sopenharmony_ci	}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	/* Allocate prph scratch */
1558c2ecf20Sopenharmony_ci	prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
1568c2ecf20Sopenharmony_ci					  &trans_pcie->prph_scratch_dma_addr,
1578c2ecf20Sopenharmony_ci					  GFP_KERNEL);
1588c2ecf20Sopenharmony_ci	if (!prph_scratch)
1598c2ecf20Sopenharmony_ci		return -ENOMEM;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	prph_sc_ctrl = &prph_scratch->ctrl_cfg;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	prph_sc_ctrl->version.version = 0;
1648c2ecf20Sopenharmony_ci	prph_sc_ctrl->version.mac_id =
1658c2ecf20Sopenharmony_ci		cpu_to_le16((u16)iwl_read32(trans, CSR_HW_REV));
1668c2ecf20Sopenharmony_ci	prph_sc_ctrl->version.size = cpu_to_le16(sizeof(*prph_scratch) / 4);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	control_flags |= IWL_PRPH_SCRATCH_MTR_MODE;
1698c2ecf20Sopenharmony_ci	control_flags |= IWL_PRPH_MTR_FORMAT_256B & IWL_PRPH_SCRATCH_MTR_FORMAT;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* initialize RX default queue */
1728c2ecf20Sopenharmony_ci	prph_sc_ctrl->rbd_cfg.free_rbd_addr =
1738c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->rxq->bd_dma);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	iwl_pcie_ctxt_info_dbg_enable(trans, &prph_sc_ctrl->hwm_cfg,
1768c2ecf20Sopenharmony_ci				      &control_flags);
1778c2ecf20Sopenharmony_ci	prph_sc_ctrl->control.control_flags = cpu_to_le32(control_flags);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/* allocate ucode sections in dram and set addresses */
1808c2ecf20Sopenharmony_ci	ret = iwl_pcie_init_fw_sec(trans, fw, &prph_scratch->dram);
1818c2ecf20Sopenharmony_ci	if (ret)
1828c2ecf20Sopenharmony_ci		goto err_free_prph_scratch;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	/* Allocate prph information
1868c2ecf20Sopenharmony_ci	 * currently we don't assign to the prph info anything, but it would get
1878c2ecf20Sopenharmony_ci	 * assigned later */
1888c2ecf20Sopenharmony_ci	prph_info = dma_alloc_coherent(trans->dev, sizeof(*prph_info),
1898c2ecf20Sopenharmony_ci				       &trans_pcie->prph_info_dma_addr,
1908c2ecf20Sopenharmony_ci				       GFP_KERNEL);
1918c2ecf20Sopenharmony_ci	if (!prph_info) {
1928c2ecf20Sopenharmony_ci		ret = -ENOMEM;
1938c2ecf20Sopenharmony_ci		goto err_free_prph_scratch;
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/* Allocate context info */
1978c2ecf20Sopenharmony_ci	ctxt_info_gen3 = dma_alloc_coherent(trans->dev,
1988c2ecf20Sopenharmony_ci					    sizeof(*ctxt_info_gen3),
1998c2ecf20Sopenharmony_ci					    &trans_pcie->ctxt_info_dma_addr,
2008c2ecf20Sopenharmony_ci					    GFP_KERNEL);
2018c2ecf20Sopenharmony_ci	if (!ctxt_info_gen3) {
2028c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2038c2ecf20Sopenharmony_ci		goto err_free_prph_info;
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	ctxt_info_gen3->prph_info_base_addr =
2078c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->prph_info_dma_addr);
2088c2ecf20Sopenharmony_ci	ctxt_info_gen3->prph_scratch_base_addr =
2098c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->prph_scratch_dma_addr);
2108c2ecf20Sopenharmony_ci	ctxt_info_gen3->prph_scratch_size =
2118c2ecf20Sopenharmony_ci		cpu_to_le32(sizeof(*prph_scratch));
2128c2ecf20Sopenharmony_ci	ctxt_info_gen3->cr_head_idx_arr_base_addr =
2138c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->rxq->rb_stts_dma);
2148c2ecf20Sopenharmony_ci	ctxt_info_gen3->tr_tail_idx_arr_base_addr =
2158c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->rxq->tr_tail_dma);
2168c2ecf20Sopenharmony_ci	ctxt_info_gen3->cr_tail_idx_arr_base_addr =
2178c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->rxq->cr_tail_dma);
2188c2ecf20Sopenharmony_ci	ctxt_info_gen3->cr_idx_arr_size =
2198c2ecf20Sopenharmony_ci		cpu_to_le16(IWL_NUM_OF_COMPLETION_RINGS);
2208c2ecf20Sopenharmony_ci	ctxt_info_gen3->tr_idx_arr_size =
2218c2ecf20Sopenharmony_ci		cpu_to_le16(IWL_NUM_OF_TRANSFER_RINGS);
2228c2ecf20Sopenharmony_ci	ctxt_info_gen3->mtr_base_addr =
2238c2ecf20Sopenharmony_ci		cpu_to_le64(trans->txqs.txq[trans->txqs.cmd.q_id]->dma_addr);
2248c2ecf20Sopenharmony_ci	ctxt_info_gen3->mcr_base_addr =
2258c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->rxq->used_bd_dma);
2268c2ecf20Sopenharmony_ci	ctxt_info_gen3->mtr_size =
2278c2ecf20Sopenharmony_ci		cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size));
2288c2ecf20Sopenharmony_ci	ctxt_info_gen3->mcr_size =
2298c2ecf20Sopenharmony_ci		cpu_to_le16(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds));
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	trans_pcie->ctxt_info_gen3 = ctxt_info_gen3;
2328c2ecf20Sopenharmony_ci	trans_pcie->prph_info = prph_info;
2338c2ecf20Sopenharmony_ci	trans_pcie->prph_scratch = prph_scratch;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	/* Allocate IML */
2368c2ecf20Sopenharmony_ci	trans_pcie->iml = dma_alloc_coherent(trans->dev, trans->iml_len,
2378c2ecf20Sopenharmony_ci					     &trans_pcie->iml_dma_addr,
2388c2ecf20Sopenharmony_ci					     GFP_KERNEL);
2398c2ecf20Sopenharmony_ci	if (!trans_pcie->iml) {
2408c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2418c2ecf20Sopenharmony_ci		goto err_free_ctxt_info;
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	memcpy(trans_pcie->iml, trans->iml, trans->iml_len);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	iwl_enable_fw_load_int_ctx_info(trans);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	/* kick FW self load */
2498c2ecf20Sopenharmony_ci	iwl_write64(trans, CSR_CTXT_INFO_ADDR,
2508c2ecf20Sopenharmony_ci		    trans_pcie->ctxt_info_dma_addr);
2518c2ecf20Sopenharmony_ci	iwl_write64(trans, CSR_IML_DATA_ADDR,
2528c2ecf20Sopenharmony_ci		    trans_pcie->iml_dma_addr);
2538c2ecf20Sopenharmony_ci	iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
2568c2ecf20Sopenharmony_ci		    CSR_AUTO_FUNC_BOOT_ENA);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return 0;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cierr_free_ctxt_info:
2618c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
2628c2ecf20Sopenharmony_ci			  trans_pcie->ctxt_info_gen3,
2638c2ecf20Sopenharmony_ci			  trans_pcie->ctxt_info_dma_addr);
2648c2ecf20Sopenharmony_ci	trans_pcie->ctxt_info_gen3 = NULL;
2658c2ecf20Sopenharmony_cierr_free_prph_info:
2668c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev,
2678c2ecf20Sopenharmony_ci			  sizeof(*prph_info),
2688c2ecf20Sopenharmony_ci			prph_info,
2698c2ecf20Sopenharmony_ci			trans_pcie->prph_info_dma_addr);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cierr_free_prph_scratch:
2728c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev,
2738c2ecf20Sopenharmony_ci			  sizeof(*prph_scratch),
2748c2ecf20Sopenharmony_ci			prph_scratch,
2758c2ecf20Sopenharmony_ci			trans_pcie->prph_scratch_dma_addr);
2768c2ecf20Sopenharmony_ci	return ret;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_civoid iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (!trans_pcie->ctxt_info_gen3)
2858c2ecf20Sopenharmony_ci		return;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
2888c2ecf20Sopenharmony_ci			  trans_pcie->ctxt_info_gen3,
2898c2ecf20Sopenharmony_ci			  trans_pcie->ctxt_info_dma_addr);
2908c2ecf20Sopenharmony_ci	trans_pcie->ctxt_info_dma_addr = 0;
2918c2ecf20Sopenharmony_ci	trans_pcie->ctxt_info_gen3 = NULL;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev, trans->iml_len, trans_pcie->iml,
2948c2ecf20Sopenharmony_ci			  trans_pcie->iml_dma_addr);
2958c2ecf20Sopenharmony_ci	trans_pcie->iml_dma_addr = 0;
2968c2ecf20Sopenharmony_ci	trans_pcie->iml = NULL;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	iwl_pcie_ctxt_info_free_fw_img(trans);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch),
3018c2ecf20Sopenharmony_ci			  trans_pcie->prph_scratch,
3028c2ecf20Sopenharmony_ci			  trans_pcie->prph_scratch_dma_addr);
3038c2ecf20Sopenharmony_ci	trans_pcie->prph_scratch_dma_addr = 0;
3048c2ecf20Sopenharmony_ci	trans_pcie->prph_scratch = NULL;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_info),
3078c2ecf20Sopenharmony_ci			  trans_pcie->prph_info,
3088c2ecf20Sopenharmony_ci			  trans_pcie->prph_info_dma_addr);
3098c2ecf20Sopenharmony_ci	trans_pcie->prph_info_dma_addr = 0;
3108c2ecf20Sopenharmony_ci	trans_pcie->prph_info = NULL;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ciint iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
3148c2ecf20Sopenharmony_ci					  const void *data, u32 len)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
3178c2ecf20Sopenharmony_ci	struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
3188c2ecf20Sopenharmony_ci		&trans_pcie->prph_scratch->ctrl_cfg;
3198c2ecf20Sopenharmony_ci	int ret;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
3228c2ecf20Sopenharmony_ci		return 0;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	/* only allocate the DRAM if not allocated yet */
3258c2ecf20Sopenharmony_ci	if (!trans->pnvm_loaded) {
3268c2ecf20Sopenharmony_ci		if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
3278c2ecf20Sopenharmony_ci			return -EBUSY;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
3308c2ecf20Sopenharmony_ci						   &trans_pcie->pnvm_dram);
3318c2ecf20Sopenharmony_ci		if (ret < 0) {
3328c2ecf20Sopenharmony_ci			IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n",
3338c2ecf20Sopenharmony_ci				     ret);
3348c2ecf20Sopenharmony_ci			return ret;
3358c2ecf20Sopenharmony_ci		}
3368c2ecf20Sopenharmony_ci	}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =
3398c2ecf20Sopenharmony_ci		cpu_to_le64(trans_pcie->pnvm_dram.physical);
3408c2ecf20Sopenharmony_ci	prph_sc_ctrl->pnvm_cfg.pnvm_size =
3418c2ecf20Sopenharmony_ci		cpu_to_le32(trans_pcie->pnvm_dram.size);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	return 0;
3448c2ecf20Sopenharmony_ci}
345