1*2ee82402SGolan Ben Ami /******************************************************************************
2*2ee82402SGolan Ben Ami  *
3*2ee82402SGolan Ben Ami  * This file is provided under a dual BSD/GPLv2 license.  When using or
4*2ee82402SGolan Ben Ami  * redistributing this file, you may do so under either license.
5*2ee82402SGolan Ben Ami  *
6*2ee82402SGolan Ben Ami  * GPL LICENSE SUMMARY
7*2ee82402SGolan Ben Ami  *
8*2ee82402SGolan Ben Ami  * Copyright(c) 2018 Intel Corporation
9*2ee82402SGolan Ben Ami  *
10*2ee82402SGolan Ben Ami  * This program is free software; you can redistribute it and/or modify
11*2ee82402SGolan Ben Ami  * it under the terms of version 2 of the GNU General Public License as
12*2ee82402SGolan Ben Ami  * published by the Free Software Foundation.
13*2ee82402SGolan Ben Ami  *
14*2ee82402SGolan Ben Ami  * This program is distributed in the hope that it will be useful, but
15*2ee82402SGolan Ben Ami  * WITHOUT ANY WARRANTY; without even the implied warranty of
16*2ee82402SGolan Ben Ami  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17*2ee82402SGolan Ben Ami  * General Public License for more details.
18*2ee82402SGolan Ben Ami  *
19*2ee82402SGolan Ben Ami  * BSD LICENSE
20*2ee82402SGolan Ben Ami  *
21*2ee82402SGolan Ben Ami  * Copyright(c) 2018 Intel Corporation
22*2ee82402SGolan Ben Ami  * All rights reserved.
23*2ee82402SGolan Ben Ami  *
24*2ee82402SGolan Ben Ami  * Redistribution and use in source and binary forms, with or without
25*2ee82402SGolan Ben Ami  * modification, are permitted provided that the following conditions
26*2ee82402SGolan Ben Ami  * are met:
27*2ee82402SGolan Ben Ami  *
28*2ee82402SGolan Ben Ami  *  * Redistributions of source code must retain the above copyright
29*2ee82402SGolan Ben Ami  *    notice, this list of conditions and the following disclaimer.
30*2ee82402SGolan Ben Ami  *  * Redistributions in binary form must reproduce the above copyright
31*2ee82402SGolan Ben Ami  *    notice, this list of conditions and the following disclaimer in
32*2ee82402SGolan Ben Ami  *    the documentation and/or other materials provided with the
33*2ee82402SGolan Ben Ami  *    distribution.
34*2ee82402SGolan Ben Ami  *  * Neither the name Intel Corporation nor the names of its
35*2ee82402SGolan Ben Ami  *    contributors may be used to endorse or promote products derived
36*2ee82402SGolan Ben Ami  *    from this software without specific prior written permission.
37*2ee82402SGolan Ben Ami  *
38*2ee82402SGolan Ben Ami  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39*2ee82402SGolan Ben Ami  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40*2ee82402SGolan Ben Ami  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41*2ee82402SGolan Ben Ami  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42*2ee82402SGolan Ben Ami  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43*2ee82402SGolan Ben Ami  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44*2ee82402SGolan Ben Ami  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45*2ee82402SGolan Ben Ami  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46*2ee82402SGolan Ben Ami  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47*2ee82402SGolan Ben Ami  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48*2ee82402SGolan Ben Ami  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49*2ee82402SGolan Ben Ami  *
50*2ee82402SGolan Ben Ami  *****************************************************************************/
51*2ee82402SGolan Ben Ami 
52*2ee82402SGolan Ben Ami #include "iwl-trans.h"
53*2ee82402SGolan Ben Ami #include "iwl-fh.h"
54*2ee82402SGolan Ben Ami #include "iwl-context-info-gen3.h"
55*2ee82402SGolan Ben Ami #include "internal.h"
56*2ee82402SGolan Ben Ami #include "iwl-prph.h"
57*2ee82402SGolan Ben Ami 
58*2ee82402SGolan Ben Ami int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
59*2ee82402SGolan Ben Ami 				 const struct fw_img *fw)
60*2ee82402SGolan Ben Ami {
61*2ee82402SGolan Ben Ami 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
62*2ee82402SGolan Ben Ami 	struct iwl_context_info_gen3 *ctxt_info_gen3;
63*2ee82402SGolan Ben Ami 	struct iwl_prph_scratch *prph_scratch;
64*2ee82402SGolan Ben Ami 	struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl;
65*2ee82402SGolan Ben Ami 	struct iwl_prph_info *prph_info;
66*2ee82402SGolan Ben Ami 	void *iml_img;
67*2ee82402SGolan Ben Ami 	u32 control_flags = 0;
68*2ee82402SGolan Ben Ami 	int ret;
69*2ee82402SGolan Ben Ami 
70*2ee82402SGolan Ben Ami 	/* Allocate prph scratch */
71*2ee82402SGolan Ben Ami 	prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
72*2ee82402SGolan Ben Ami 					  &trans_pcie->prph_scratch_dma_addr,
73*2ee82402SGolan Ben Ami 					  GFP_KERNEL);
74*2ee82402SGolan Ben Ami 	if (!prph_scratch)
75*2ee82402SGolan Ben Ami 		return -ENOMEM;
76*2ee82402SGolan Ben Ami 
77*2ee82402SGolan Ben Ami 	prph_sc_ctrl = &prph_scratch->ctrl_cfg;
78*2ee82402SGolan Ben Ami 
79*2ee82402SGolan Ben Ami 	prph_sc_ctrl->version.version = 0;
80*2ee82402SGolan Ben Ami 	prph_sc_ctrl->version.mac_id =
81*2ee82402SGolan Ben Ami 		cpu_to_le16((u16)iwl_read32(trans, CSR_HW_REV));
82*2ee82402SGolan Ben Ami 	prph_sc_ctrl->version.size = cpu_to_le16(sizeof(*prph_scratch) / 4);
83*2ee82402SGolan Ben Ami 
84*2ee82402SGolan Ben Ami 	control_flags = IWL_PRPH_SCRATCH_RB_SIZE_4K |
85*2ee82402SGolan Ben Ami 			IWL_PRPH_SCRATCH_MTR_MODE |
86*2ee82402SGolan Ben Ami 			(IWL_PRPH_MTR_FORMAT_256B &
87*2ee82402SGolan Ben Ami 			 IWL_PRPH_SCRATCH_MTR_FORMAT);
88*2ee82402SGolan Ben Ami 	prph_sc_ctrl->control.control_flags = cpu_to_le32(control_flags);
89*2ee82402SGolan Ben Ami 
90*2ee82402SGolan Ben Ami 	/* initialize RX default queue */
91*2ee82402SGolan Ben Ami 	prph_sc_ctrl->rbd_cfg.free_rbd_addr =
92*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->rxq->bd_dma);
93*2ee82402SGolan Ben Ami 
94*2ee82402SGolan Ben Ami 	/* allocate ucode sections in dram and set addresses */
95*2ee82402SGolan Ben Ami 	ret = iwl_pcie_init_fw_sec(trans, fw, &prph_scratch->dram);
96*2ee82402SGolan Ben Ami 	if (ret) {
97*2ee82402SGolan Ben Ami 		dma_free_coherent(trans->dev,
98*2ee82402SGolan Ben Ami 				  sizeof(*prph_scratch),
99*2ee82402SGolan Ben Ami 				  prph_scratch,
100*2ee82402SGolan Ben Ami 				  trans_pcie->prph_scratch_dma_addr);
101*2ee82402SGolan Ben Ami 		return ret;
102*2ee82402SGolan Ben Ami 	}
103*2ee82402SGolan Ben Ami 
104*2ee82402SGolan Ben Ami 	/* Allocate prph information
105*2ee82402SGolan Ben Ami 	 * currently we don't assign to the prph info anything, but it would get
106*2ee82402SGolan Ben Ami 	 * assigned later */
107*2ee82402SGolan Ben Ami 	prph_info = dma_alloc_coherent(trans->dev, sizeof(*prph_info),
108*2ee82402SGolan Ben Ami 				       &trans_pcie->prph_info_dma_addr,
109*2ee82402SGolan Ben Ami 				       GFP_KERNEL);
110*2ee82402SGolan Ben Ami 	if (!prph_info)
111*2ee82402SGolan Ben Ami 		return -ENOMEM;
112*2ee82402SGolan Ben Ami 
113*2ee82402SGolan Ben Ami 	/* Allocate context info */
114*2ee82402SGolan Ben Ami 	ctxt_info_gen3 = dma_alloc_coherent(trans->dev,
115*2ee82402SGolan Ben Ami 					    sizeof(*ctxt_info_gen3),
116*2ee82402SGolan Ben Ami 					    &trans_pcie->ctxt_info_dma_addr,
117*2ee82402SGolan Ben Ami 					    GFP_KERNEL);
118*2ee82402SGolan Ben Ami 	if (!ctxt_info_gen3)
119*2ee82402SGolan Ben Ami 		return -ENOMEM;
120*2ee82402SGolan Ben Ami 
121*2ee82402SGolan Ben Ami 	ctxt_info_gen3->prph_info_base_addr =
122*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->prph_info_dma_addr);
123*2ee82402SGolan Ben Ami 	ctxt_info_gen3->prph_scratch_base_addr =
124*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->prph_scratch_dma_addr);
125*2ee82402SGolan Ben Ami 	ctxt_info_gen3->prph_scratch_size =
126*2ee82402SGolan Ben Ami 		cpu_to_le32(sizeof(*prph_scratch));
127*2ee82402SGolan Ben Ami 	ctxt_info_gen3->cr_head_idx_arr_base_addr =
128*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->rxq->rb_stts_dma);
129*2ee82402SGolan Ben Ami 	ctxt_info_gen3->tr_tail_idx_arr_base_addr =
130*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->rxq->tr_tail_dma);
131*2ee82402SGolan Ben Ami 	ctxt_info_gen3->cr_tail_idx_arr_base_addr =
132*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->rxq->cr_tail_dma);
133*2ee82402SGolan Ben Ami 	ctxt_info_gen3->cr_idx_arr_size =
134*2ee82402SGolan Ben Ami 		cpu_to_le16(IWL_NUM_OF_COMPLETION_RINGS);
135*2ee82402SGolan Ben Ami 	ctxt_info_gen3->tr_idx_arr_size =
136*2ee82402SGolan Ben Ami 		cpu_to_le16(IWL_NUM_OF_TRANSFER_RINGS);
137*2ee82402SGolan Ben Ami 	ctxt_info_gen3->mtr_base_addr =
138*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
139*2ee82402SGolan Ben Ami 	ctxt_info_gen3->mcr_base_addr =
140*2ee82402SGolan Ben Ami 		cpu_to_le64(trans_pcie->rxq->used_bd_dma);
141*2ee82402SGolan Ben Ami 	ctxt_info_gen3->mtr_size =
142*2ee82402SGolan Ben Ami 		cpu_to_le16(TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS));
143*2ee82402SGolan Ben Ami 	ctxt_info_gen3->mcr_size =
144*2ee82402SGolan Ben Ami 		cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE));
145*2ee82402SGolan Ben Ami 
146*2ee82402SGolan Ben Ami 	trans_pcie->ctxt_info_gen3 = ctxt_info_gen3;
147*2ee82402SGolan Ben Ami 	trans_pcie->prph_info = prph_info;
148*2ee82402SGolan Ben Ami 	trans_pcie->prph_scratch = prph_scratch;
149*2ee82402SGolan Ben Ami 
150*2ee82402SGolan Ben Ami 	/* Allocate IML */
151*2ee82402SGolan Ben Ami 	iml_img = dma_alloc_coherent(trans->dev, trans->iml_len,
152*2ee82402SGolan Ben Ami 				     &trans_pcie->iml_dma_addr, GFP_KERNEL);
153*2ee82402SGolan Ben Ami 	if (!iml_img)
154*2ee82402SGolan Ben Ami 		return -ENOMEM;
155*2ee82402SGolan Ben Ami 
156*2ee82402SGolan Ben Ami 	memcpy(iml_img, trans->iml, trans->iml_len);
157*2ee82402SGolan Ben Ami 
158*2ee82402SGolan Ben Ami 	iwl_enable_interrupts(trans);
159*2ee82402SGolan Ben Ami 
160*2ee82402SGolan Ben Ami 	/* Configure debug, if exists */
161*2ee82402SGolan Ben Ami 	if (trans->dbg_dest_tlv)
162*2ee82402SGolan Ben Ami 		iwl_pcie_apply_destination(trans);
163*2ee82402SGolan Ben Ami 
164*2ee82402SGolan Ben Ami 	/* kick FW self load */
165*2ee82402SGolan Ben Ami 	iwl_write64(trans, CSR_CTXT_INFO_ADDR,
166*2ee82402SGolan Ben Ami 		    trans_pcie->ctxt_info_dma_addr);
167*2ee82402SGolan Ben Ami 	iwl_write64(trans, CSR_IML_DATA_ADDR,
168*2ee82402SGolan Ben Ami 		    trans_pcie->iml_dma_addr);
169*2ee82402SGolan Ben Ami 	iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
170*2ee82402SGolan Ben Ami 	iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA);
171*2ee82402SGolan Ben Ami 	iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);
172*2ee82402SGolan Ben Ami 
173*2ee82402SGolan Ben Ami 	return 0;
174*2ee82402SGolan Ben Ami }
175*2ee82402SGolan Ben Ami 
176*2ee82402SGolan Ben Ami void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans)
177*2ee82402SGolan Ben Ami {
178*2ee82402SGolan Ben Ami 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
179*2ee82402SGolan Ben Ami 
180*2ee82402SGolan Ben Ami 	if (!trans_pcie->ctxt_info_gen3)
181*2ee82402SGolan Ben Ami 		return;
182*2ee82402SGolan Ben Ami 
183*2ee82402SGolan Ben Ami 	dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
184*2ee82402SGolan Ben Ami 			  trans_pcie->ctxt_info_gen3,
185*2ee82402SGolan Ben Ami 			  trans_pcie->ctxt_info_dma_addr);
186*2ee82402SGolan Ben Ami 	trans_pcie->ctxt_info_dma_addr = 0;
187*2ee82402SGolan Ben Ami 	trans_pcie->ctxt_info_gen3 = NULL;
188*2ee82402SGolan Ben Ami 
189*2ee82402SGolan Ben Ami 	iwl_pcie_ctxt_info_free_fw_img(trans);
190*2ee82402SGolan Ben Ami 
191*2ee82402SGolan Ben Ami 	dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch),
192*2ee82402SGolan Ben Ami 			  trans_pcie->prph_scratch,
193*2ee82402SGolan Ben Ami 			  trans_pcie->prph_scratch_dma_addr);
194*2ee82402SGolan Ben Ami 	trans_pcie->prph_scratch_dma_addr = 0;
195*2ee82402SGolan Ben Ami 	trans_pcie->prph_scratch = NULL;
196*2ee82402SGolan Ben Ami 
197*2ee82402SGolan Ben Ami 	dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_info),
198*2ee82402SGolan Ben Ami 			  trans_pcie->prph_info,
199*2ee82402SGolan Ben Ami 			  trans_pcie->prph_info_dma_addr);
200*2ee82402SGolan Ben Ami 	trans_pcie->prph_info_dma_addr = 0;
201*2ee82402SGolan Ben Ami 	trans_pcie->prph_info = NULL;
202*2ee82402SGolan Ben Ami }
203