xref: /freebsd-src/sys/dev/qlnx/qlnxe/ecore_init_ops.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
111e25f0dSDavid C Somayajulu /*
211e25f0dSDavid C Somayajulu  * Copyright (c) 2017-2018 Cavium, Inc.
311e25f0dSDavid C Somayajulu  * All rights reserved.
411e25f0dSDavid C Somayajulu  *
511e25f0dSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
611e25f0dSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
711e25f0dSDavid C Somayajulu  *  are met:
811e25f0dSDavid C Somayajulu  *
911e25f0dSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
1011e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
1111e25f0dSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
1211e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
1311e25f0dSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
1411e25f0dSDavid C Somayajulu  *
1511e25f0dSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1611e25f0dSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1711e25f0dSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1811e25f0dSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
1911e25f0dSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2011e25f0dSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2111e25f0dSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2211e25f0dSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2311e25f0dSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2411e25f0dSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2511e25f0dSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
2611e25f0dSDavid C Somayajulu  */
2711e25f0dSDavid C Somayajulu 
2811e25f0dSDavid C Somayajulu /*
2911e25f0dSDavid C Somayajulu  * File : ecore_init_ops.c
3011e25f0dSDavid C Somayajulu  */
3111e25f0dSDavid C Somayajulu #include <sys/cdefs.h>
3211e25f0dSDavid C Somayajulu /* include the precompiled configuration values - only once */
3311e25f0dSDavid C Somayajulu #include "bcm_osal.h"
3411e25f0dSDavid C Somayajulu #include "ecore_hsi_common.h"
3511e25f0dSDavid C Somayajulu #include "ecore.h"
3611e25f0dSDavid C Somayajulu #include "ecore_hw.h"
3711e25f0dSDavid C Somayajulu #include "ecore_status.h"
3811e25f0dSDavid C Somayajulu #include "ecore_rt_defs.h"
3911e25f0dSDavid C Somayajulu #include "ecore_init_fw_funcs.h"
4011e25f0dSDavid C Somayajulu 
4111e25f0dSDavid C Somayajulu #ifndef CONFIG_ECORE_BINARY_FW
4211e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ZIPPED_FW
4311e25f0dSDavid C Somayajulu #include "ecore_init_values_zipped.h"
4411e25f0dSDavid C Somayajulu #else
4511e25f0dSDavid C Somayajulu #include "ecore_init_values.h"
4611e25f0dSDavid C Somayajulu #endif
4711e25f0dSDavid C Somayajulu #endif
4811e25f0dSDavid C Somayajulu 
4911e25f0dSDavid C Somayajulu #include "ecore_iro_values.h"
5011e25f0dSDavid C Somayajulu #include "ecore_sriov.h"
5111e25f0dSDavid C Somayajulu #include "ecore_gtt_values.h"
5211e25f0dSDavid C Somayajulu #include "reg_addr.h"
5311e25f0dSDavid C Somayajulu #include "ecore_init_ops.h"
5411e25f0dSDavid C Somayajulu 
5511e25f0dSDavid C Somayajulu #define ECORE_INIT_MAX_POLL_COUNT	100
5611e25f0dSDavid C Somayajulu #define ECORE_INIT_POLL_PERIOD_US	500
5711e25f0dSDavid C Somayajulu 
ecore_init_iro_array(struct ecore_dev * p_dev)5811e25f0dSDavid C Somayajulu void ecore_init_iro_array(struct ecore_dev *p_dev)
5911e25f0dSDavid C Somayajulu {
6011e25f0dSDavid C Somayajulu 	p_dev->iro_arr = iro_arr;
6111e25f0dSDavid C Somayajulu }
6211e25f0dSDavid C Somayajulu 
6311e25f0dSDavid C Somayajulu /* Runtime configuration helpers */
ecore_init_clear_rt_data(struct ecore_hwfn * p_hwfn)6411e25f0dSDavid C Somayajulu void ecore_init_clear_rt_data(struct ecore_hwfn *p_hwfn)
6511e25f0dSDavid C Somayajulu {
6611e25f0dSDavid C Somayajulu 	int i;
6711e25f0dSDavid C Somayajulu 
6811e25f0dSDavid C Somayajulu 	for (i = 0; i < RUNTIME_ARRAY_SIZE; i++)
6911e25f0dSDavid C Somayajulu 		p_hwfn->rt_data.b_valid[i] = false;
7011e25f0dSDavid C Somayajulu }
7111e25f0dSDavid C Somayajulu 
ecore_init_store_rt_reg(struct ecore_hwfn * p_hwfn,u32 rt_offset,u32 val)7211e25f0dSDavid C Somayajulu void ecore_init_store_rt_reg(struct ecore_hwfn *p_hwfn,
7311e25f0dSDavid C Somayajulu 			     u32 rt_offset, u32 val)
7411e25f0dSDavid C Somayajulu {
759efd0ba7SDavid C Somayajulu 	if (rt_offset >= RUNTIME_ARRAY_SIZE) {
769efd0ba7SDavid C Somayajulu 		DP_ERR(p_hwfn,
779efd0ba7SDavid C Somayajulu 		       "Avoid storing %u in rt_data at index %u since RUNTIME_ARRAY_SIZE is %u!\n",
789efd0ba7SDavid C Somayajulu 		       val, rt_offset, RUNTIME_ARRAY_SIZE);
799efd0ba7SDavid C Somayajulu 		return;
809efd0ba7SDavid C Somayajulu 	}
819efd0ba7SDavid C Somayajulu 
8211e25f0dSDavid C Somayajulu 	p_hwfn->rt_data.init_val[rt_offset] = val;
8311e25f0dSDavid C Somayajulu 	p_hwfn->rt_data.b_valid[rt_offset] = true;
8411e25f0dSDavid C Somayajulu }
8511e25f0dSDavid C Somayajulu 
ecore_init_store_rt_agg(struct ecore_hwfn * p_hwfn,u32 rt_offset,u32 * p_val,osal_size_t size)8611e25f0dSDavid C Somayajulu void ecore_init_store_rt_agg(struct ecore_hwfn *p_hwfn,
8711e25f0dSDavid C Somayajulu 			     u32 rt_offset, u32 *p_val,
8811e25f0dSDavid C Somayajulu 			     osal_size_t size)
8911e25f0dSDavid C Somayajulu {
9011e25f0dSDavid C Somayajulu 	osal_size_t i;
9111e25f0dSDavid C Somayajulu 
929efd0ba7SDavid C Somayajulu 	if ((rt_offset + size - 1) >= RUNTIME_ARRAY_SIZE) {
939efd0ba7SDavid C Somayajulu 		DP_ERR(p_hwfn,
949efd0ba7SDavid C Somayajulu 		       "Avoid storing values in rt_data at indices %u-%u since RUNTIME_ARRAY_SIZE is %u!\n",
959efd0ba7SDavid C Somayajulu 		       rt_offset, (u32)(rt_offset + size - 1),
969efd0ba7SDavid C Somayajulu 		       RUNTIME_ARRAY_SIZE);
979efd0ba7SDavid C Somayajulu 		return;
989efd0ba7SDavid C Somayajulu 	}
999efd0ba7SDavid C Somayajulu 
10011e25f0dSDavid C Somayajulu 	for (i = 0; i < size / sizeof(u32); i++) {
10111e25f0dSDavid C Somayajulu 		p_hwfn->rt_data.init_val[rt_offset + i] = p_val[i];
10211e25f0dSDavid C Somayajulu 		p_hwfn->rt_data.b_valid[rt_offset + i] = true;
10311e25f0dSDavid C Somayajulu 	}
10411e25f0dSDavid C Somayajulu }
10511e25f0dSDavid C Somayajulu 
ecore_init_rt(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 addr,u16 rt_offset,u16 size,bool b_must_dmae)10611e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_init_rt(struct ecore_hwfn *p_hwfn,
10711e25f0dSDavid C Somayajulu 					  struct ecore_ptt *p_ptt,
10811e25f0dSDavid C Somayajulu 					  u32 addr,
10911e25f0dSDavid C Somayajulu 					  u16 rt_offset,
11011e25f0dSDavid C Somayajulu 					  u16 size,
11111e25f0dSDavid C Somayajulu 					  bool b_must_dmae)
11211e25f0dSDavid C Somayajulu {
11311e25f0dSDavid C Somayajulu 	u32 *p_init_val = &p_hwfn->rt_data.init_val[rt_offset];
11411e25f0dSDavid C Somayajulu 	bool *p_valid = &p_hwfn->rt_data.b_valid[rt_offset];
11511e25f0dSDavid C Somayajulu 	u16 i, segment;
11611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
11711e25f0dSDavid C Somayajulu 
11811e25f0dSDavid C Somayajulu 	/* Since not all RT entries are initialized, go over the RT and
11911e25f0dSDavid C Somayajulu 	 * for each segment of initialized values use DMA.
12011e25f0dSDavid C Somayajulu 	 */
12111e25f0dSDavid C Somayajulu 	for (i = 0; i < size; i++) {
12211e25f0dSDavid C Somayajulu 		if (!p_valid[i])
12311e25f0dSDavid C Somayajulu 			continue;
12411e25f0dSDavid C Somayajulu 
12511e25f0dSDavid C Somayajulu 		/* In case there isn't any wide-bus configuration here,
12611e25f0dSDavid C Somayajulu 		 * simply write the data instead of using dmae.
12711e25f0dSDavid C Somayajulu 		 */
12811e25f0dSDavid C Somayajulu 		if (!b_must_dmae) {
12911e25f0dSDavid C Somayajulu 			ecore_wr(p_hwfn, p_ptt, addr + (i << 2),
13011e25f0dSDavid C Somayajulu 				 p_init_val[i]);
13111e25f0dSDavid C Somayajulu 			continue;
13211e25f0dSDavid C Somayajulu 		}
13311e25f0dSDavid C Somayajulu 
13411e25f0dSDavid C Somayajulu 		/* Start of a new segment */
13511e25f0dSDavid C Somayajulu 		for (segment = 1; i + segment < size; segment++)
13611e25f0dSDavid C Somayajulu 			if (!p_valid[i + segment])
13711e25f0dSDavid C Somayajulu 				break;
13811e25f0dSDavid C Somayajulu 
13911e25f0dSDavid C Somayajulu 		rc = ecore_dmae_host2grc(p_hwfn, p_ptt,
14011e25f0dSDavid C Somayajulu 					 (osal_uintptr_t)(p_init_val + i),
141217ec208SDavid C Somayajulu 					 addr + (i << 2), segment,
142217ec208SDavid C Somayajulu 					 OSAL_NULL /* default parameters */);
14311e25f0dSDavid C Somayajulu 		if (rc != ECORE_SUCCESS)
14411e25f0dSDavid C Somayajulu 			return rc;
14511e25f0dSDavid C Somayajulu 
14611e25f0dSDavid C Somayajulu 		/* Jump over the entire segment, including invalid entry */
14711e25f0dSDavid C Somayajulu 		i += segment;
14811e25f0dSDavid C Somayajulu 	}
14911e25f0dSDavid C Somayajulu 
15011e25f0dSDavid C Somayajulu 	return rc;
15111e25f0dSDavid C Somayajulu }
15211e25f0dSDavid C Somayajulu 
ecore_init_alloc(struct ecore_hwfn * p_hwfn)15311e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_init_alloc(struct ecore_hwfn *p_hwfn)
15411e25f0dSDavid C Somayajulu {
15511e25f0dSDavid C Somayajulu 	struct ecore_rt_data *rt_data = &p_hwfn->rt_data;
15611e25f0dSDavid C Somayajulu 
15711e25f0dSDavid C Somayajulu 	if (IS_VF(p_hwfn->p_dev))
15811e25f0dSDavid C Somayajulu 		return ECORE_SUCCESS;
15911e25f0dSDavid C Somayajulu 
16011e25f0dSDavid C Somayajulu 	rt_data->b_valid = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
16111e25f0dSDavid C Somayajulu 				       sizeof(bool) * RUNTIME_ARRAY_SIZE);
16211e25f0dSDavid C Somayajulu 	if (!rt_data->b_valid)
16311e25f0dSDavid C Somayajulu 		return ECORE_NOMEM;
16411e25f0dSDavid C Somayajulu 
16511e25f0dSDavid C Somayajulu 	rt_data->init_val = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
16611e25f0dSDavid C Somayajulu 					sizeof(u32) * RUNTIME_ARRAY_SIZE);
16711e25f0dSDavid C Somayajulu 	if (!rt_data->init_val) {
16811e25f0dSDavid C Somayajulu 		OSAL_FREE(p_hwfn->p_dev, rt_data->b_valid);
16911e25f0dSDavid C Somayajulu 		rt_data->b_valid = OSAL_NULL;
17011e25f0dSDavid C Somayajulu 		return ECORE_NOMEM;
17111e25f0dSDavid C Somayajulu 	}
17211e25f0dSDavid C Somayajulu 
17311e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
17411e25f0dSDavid C Somayajulu }
17511e25f0dSDavid C Somayajulu 
ecore_init_free(struct ecore_hwfn * p_hwfn)17611e25f0dSDavid C Somayajulu void ecore_init_free(struct ecore_hwfn *p_hwfn)
17711e25f0dSDavid C Somayajulu {
17811e25f0dSDavid C Somayajulu 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->rt_data.init_val);
17911e25f0dSDavid C Somayajulu 	p_hwfn->rt_data.init_val = OSAL_NULL;
18011e25f0dSDavid C Somayajulu 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->rt_data.b_valid);
18111e25f0dSDavid C Somayajulu 	p_hwfn->rt_data.b_valid = OSAL_NULL;
18211e25f0dSDavid C Somayajulu }
18311e25f0dSDavid C Somayajulu 
ecore_init_array_dmae(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 addr,u32 dmae_data_offset,u32 size,const u32 * p_buf,bool b_must_dmae,bool b_can_dmae)18411e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_init_array_dmae(struct ecore_hwfn *p_hwfn,
18511e25f0dSDavid C Somayajulu 				  struct ecore_ptt *p_ptt,
18611e25f0dSDavid C Somayajulu 				  u32 addr, u32 dmae_data_offset,
18711e25f0dSDavid C Somayajulu 				  u32 size, const u32 *p_buf,
18811e25f0dSDavid C Somayajulu 				  bool b_must_dmae, bool b_can_dmae)
18911e25f0dSDavid C Somayajulu {
19011e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc	= ECORE_SUCCESS;
19111e25f0dSDavid C Somayajulu 
19211e25f0dSDavid C Somayajulu 	/* Perform DMAE only for lengthy enough sections or for wide-bus */
19311e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
19411e25f0dSDavid C Somayajulu 	if ((CHIP_REV_IS_SLOW(p_hwfn->p_dev) && (size < 16)) ||
19511e25f0dSDavid C Somayajulu 	    !b_can_dmae || (!b_must_dmae && (size < 16))) {
19611e25f0dSDavid C Somayajulu #else
19711e25f0dSDavid C Somayajulu 	if (!b_can_dmae || (!b_must_dmae && (size < 16))) {
19811e25f0dSDavid C Somayajulu #endif
19911e25f0dSDavid C Somayajulu 		const u32 *data = p_buf + dmae_data_offset;
20011e25f0dSDavid C Somayajulu 		u32 i;
20111e25f0dSDavid C Somayajulu 
20211e25f0dSDavid C Somayajulu 		for (i = 0; i < size; i++)
20311e25f0dSDavid C Somayajulu 			ecore_wr(p_hwfn, p_ptt, addr + (i << 2), data[i]);
20411e25f0dSDavid C Somayajulu 	} else {
20511e25f0dSDavid C Somayajulu 		rc = ecore_dmae_host2grc(p_hwfn, p_ptt,
20611e25f0dSDavid C Somayajulu 					 (osal_uintptr_t)(p_buf +
20711e25f0dSDavid C Somayajulu 							  dmae_data_offset),
208217ec208SDavid C Somayajulu 					 addr, size,
209217ec208SDavid C Somayajulu 					 OSAL_NULL /* default parameters */);
21011e25f0dSDavid C Somayajulu 	}
21111e25f0dSDavid C Somayajulu 
21211e25f0dSDavid C Somayajulu 	return rc;
21311e25f0dSDavid C Somayajulu }
21411e25f0dSDavid C Somayajulu 
21511e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_init_fill_dmae(struct ecore_hwfn *p_hwfn,
21611e25f0dSDavid C Somayajulu 						 struct ecore_ptt *p_ptt,
2179efd0ba7SDavid C Somayajulu 						 u32 addr, u32 fill_count)
21811e25f0dSDavid C Somayajulu {
21911e25f0dSDavid C Somayajulu 	static u32 zero_buffer[DMAE_MAX_RW_SIZE];
220217ec208SDavid C Somayajulu 	struct ecore_dmae_params params;
22111e25f0dSDavid C Somayajulu 
22211e25f0dSDavid C Somayajulu 	OSAL_MEMSET(zero_buffer, 0, sizeof(u32) * DMAE_MAX_RW_SIZE);
22311e25f0dSDavid C Somayajulu 
224217ec208SDavid C Somayajulu 	OSAL_MEMSET(&params, 0, sizeof(params));
225217ec208SDavid C Somayajulu 	params.flags = ECORE_DMAE_FLAG_RW_REPL_SRC;
22611e25f0dSDavid C Somayajulu 	return ecore_dmae_host2grc(p_hwfn, p_ptt,
22711e25f0dSDavid C Somayajulu 				   (osal_uintptr_t)(&(zero_buffer[0])),
228217ec208SDavid C Somayajulu 				   addr, fill_count, &params);
22911e25f0dSDavid C Somayajulu }
23011e25f0dSDavid C Somayajulu 
23111e25f0dSDavid C Somayajulu static void ecore_init_fill(struct ecore_hwfn *p_hwfn,
23211e25f0dSDavid C Somayajulu 			    struct ecore_ptt *p_ptt,
23311e25f0dSDavid C Somayajulu 			    u32 addr, u32 fill, u32 fill_count)
23411e25f0dSDavid C Somayajulu {
23511e25f0dSDavid C Somayajulu 	u32 i;
23611e25f0dSDavid C Somayajulu 
23711e25f0dSDavid C Somayajulu 	for (i = 0; i < fill_count; i++, addr += sizeof(u32))
23811e25f0dSDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt, addr, fill);
23911e25f0dSDavid C Somayajulu }
24011e25f0dSDavid C Somayajulu 
24111e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_init_cmd_array(struct ecore_hwfn *p_hwfn,
24211e25f0dSDavid C Somayajulu 						 struct ecore_ptt *p_ptt,
243*134b0936SMark O'Donovan 						 const struct init_write_op *cmd,
24411e25f0dSDavid C Somayajulu 						 bool b_must_dmae,
24511e25f0dSDavid C Somayajulu 						 bool b_can_dmae)
24611e25f0dSDavid C Somayajulu {
24711e25f0dSDavid C Somayajulu 	u32 dmae_array_offset = OSAL_LE32_TO_CPU(cmd->args.array_offset);
24811e25f0dSDavid C Somayajulu 	u32 data = OSAL_LE32_TO_CPU(cmd->data);
24911e25f0dSDavid C Somayajulu 	u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2;
25011e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ZIPPED_FW
25111e25f0dSDavid C Somayajulu 	u32 offset, output_len, input_len, max_size;
25211e25f0dSDavid C Somayajulu #endif
25311e25f0dSDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
254*134b0936SMark O'Donovan 	const union init_array_hdr *hdr;
25511e25f0dSDavid C Somayajulu 	const u32 *array_data;
25611e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
25711e25f0dSDavid C Somayajulu 	u32 size;
25811e25f0dSDavid C Somayajulu 
25911e25f0dSDavid C Somayajulu 	array_data = p_dev->fw_data->arr_data;
26011e25f0dSDavid C Somayajulu 
261*134b0936SMark O'Donovan 	hdr = (const union init_array_hdr *) (array_data +
26211e25f0dSDavid C Somayajulu 					dmae_array_offset);
26311e25f0dSDavid C Somayajulu 	data = OSAL_LE32_TO_CPU(hdr->raw.data);
26411e25f0dSDavid C Somayajulu 	switch (GET_FIELD(data, INIT_ARRAY_RAW_HDR_TYPE)) {
26511e25f0dSDavid C Somayajulu 	case INIT_ARR_ZIPPED:
26611e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ZIPPED_FW
26711e25f0dSDavid C Somayajulu 		offset = dmae_array_offset + 1;
26811e25f0dSDavid C Somayajulu 		input_len = GET_FIELD(data,
26911e25f0dSDavid C Somayajulu 				      INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE);
27011e25f0dSDavid C Somayajulu 		max_size = MAX_ZIPPED_SIZE * 4;
27111e25f0dSDavid C Somayajulu 		OSAL_MEMSET(p_hwfn->unzip_buf, 0, max_size);
27211e25f0dSDavid C Somayajulu 
27311e25f0dSDavid C Somayajulu 		output_len = OSAL_UNZIP_DATA(p_hwfn, input_len,
27411e25f0dSDavid C Somayajulu 					     (u8 *)&array_data[offset],
27511e25f0dSDavid C Somayajulu 					     max_size, (u8 *)p_hwfn->unzip_buf);
27611e25f0dSDavid C Somayajulu 		if (output_len) {
27711e25f0dSDavid C Somayajulu 			rc = ecore_init_array_dmae(p_hwfn, p_ptt, addr, 0,
27811e25f0dSDavid C Somayajulu 						   output_len,
27911e25f0dSDavid C Somayajulu 						   p_hwfn->unzip_buf,
28011e25f0dSDavid C Somayajulu 						   b_must_dmae, b_can_dmae);
28111e25f0dSDavid C Somayajulu 		} else {
28211e25f0dSDavid C Somayajulu 			DP_NOTICE(p_hwfn, true,
28311e25f0dSDavid C Somayajulu 				  "Failed to unzip dmae data\n");
28411e25f0dSDavid C Somayajulu 			rc = ECORE_INVAL;
28511e25f0dSDavid C Somayajulu 		}
28611e25f0dSDavid C Somayajulu #else
28711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
28811e25f0dSDavid C Somayajulu 			  "Using zipped firmware without config enabled\n");
28911e25f0dSDavid C Somayajulu 		rc = ECORE_INVAL;
29011e25f0dSDavid C Somayajulu #endif
29111e25f0dSDavid C Somayajulu 		break;
29211e25f0dSDavid C Somayajulu 	case INIT_ARR_PATTERN:
29311e25f0dSDavid C Somayajulu 	{
29411e25f0dSDavid C Somayajulu 		u32 repeats = GET_FIELD(data,
29511e25f0dSDavid C Somayajulu 					INIT_ARRAY_PATTERN_HDR_REPETITIONS);
29611e25f0dSDavid C Somayajulu 		u32 i;
29711e25f0dSDavid C Somayajulu 
29811e25f0dSDavid C Somayajulu 		size = GET_FIELD(data,
29911e25f0dSDavid C Somayajulu 				 INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE);
30011e25f0dSDavid C Somayajulu 
30111e25f0dSDavid C Somayajulu 		for (i = 0; i < repeats; i++, addr += size << 2) {
30211e25f0dSDavid C Somayajulu 			rc = ecore_init_array_dmae(p_hwfn, p_ptt, addr,
30311e25f0dSDavid C Somayajulu 						   dmae_array_offset + 1,
30411e25f0dSDavid C Somayajulu 						   size, array_data,
30511e25f0dSDavid C Somayajulu 						   b_must_dmae, b_can_dmae);
30611e25f0dSDavid C Somayajulu 			if (rc)
30711e25f0dSDavid C Somayajulu 				break;
30811e25f0dSDavid C Somayajulu 		}
30911e25f0dSDavid C Somayajulu 		break;
31011e25f0dSDavid C Somayajulu 	}
31111e25f0dSDavid C Somayajulu 	case INIT_ARR_STANDARD:
31211e25f0dSDavid C Somayajulu 		size = GET_FIELD(data,
31311e25f0dSDavid C Somayajulu 				 INIT_ARRAY_STANDARD_HDR_SIZE);
31411e25f0dSDavid C Somayajulu 		rc = ecore_init_array_dmae(p_hwfn, p_ptt, addr,
31511e25f0dSDavid C Somayajulu 					   dmae_array_offset + 1,
31611e25f0dSDavid C Somayajulu 					   size, array_data,
31711e25f0dSDavid C Somayajulu 					   b_must_dmae, b_can_dmae);
31811e25f0dSDavid C Somayajulu 		break;
31911e25f0dSDavid C Somayajulu 	}
32011e25f0dSDavid C Somayajulu 
32111e25f0dSDavid C Somayajulu 	return rc;
32211e25f0dSDavid C Somayajulu }
32311e25f0dSDavid C Somayajulu 
32411e25f0dSDavid C Somayajulu /* init_ops write command */
32511e25f0dSDavid C Somayajulu static enum _ecore_status_t ecore_init_cmd_wr(struct ecore_hwfn *p_hwfn,
32611e25f0dSDavid C Somayajulu 					      struct ecore_ptt *p_ptt,
327*134b0936SMark O'Donovan 					      const struct init_write_op *p_cmd,
32811e25f0dSDavid C Somayajulu 					      bool b_can_dmae)
32911e25f0dSDavid C Somayajulu {
33011e25f0dSDavid C Somayajulu 	u32 data = OSAL_LE32_TO_CPU(p_cmd->data);
33111e25f0dSDavid C Somayajulu 	bool b_must_dmae = GET_FIELD(data, INIT_WRITE_OP_WIDE_BUS);
33211e25f0dSDavid C Somayajulu 	u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2;
33311e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc	= ECORE_SUCCESS;
33411e25f0dSDavid C Somayajulu 
33511e25f0dSDavid C Somayajulu 	/* Sanitize */
33611e25f0dSDavid C Somayajulu 	if (b_must_dmae && !b_can_dmae) {
33711e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true,
33811e25f0dSDavid C Somayajulu 			  "Need to write to %08x for Wide-bus but DMAE isn't allowed\n",
33911e25f0dSDavid C Somayajulu 			  addr);
34011e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
34111e25f0dSDavid C Somayajulu 	}
34211e25f0dSDavid C Somayajulu 
34311e25f0dSDavid C Somayajulu 	switch (GET_FIELD(data, INIT_WRITE_OP_SOURCE)) {
34411e25f0dSDavid C Somayajulu 	case INIT_SRC_INLINE:
34511e25f0dSDavid C Somayajulu 		data = OSAL_LE32_TO_CPU(p_cmd->args.inline_val);
34611e25f0dSDavid C Somayajulu 		ecore_wr(p_hwfn, p_ptt, addr, data);
34711e25f0dSDavid C Somayajulu 		break;
34811e25f0dSDavid C Somayajulu 	case INIT_SRC_ZEROS:
34911e25f0dSDavid C Somayajulu 		data = OSAL_LE32_TO_CPU(p_cmd->args.zeros_count);
35011e25f0dSDavid C Somayajulu 		if (b_must_dmae || (b_can_dmae && (data >= 64)))
3519efd0ba7SDavid C Somayajulu 			rc = ecore_init_fill_dmae(p_hwfn, p_ptt, addr, data);
35211e25f0dSDavid C Somayajulu 		else
35311e25f0dSDavid C Somayajulu 			ecore_init_fill(p_hwfn, p_ptt, addr, 0, data);
35411e25f0dSDavid C Somayajulu 		break;
35511e25f0dSDavid C Somayajulu 	case INIT_SRC_ARRAY:
35611e25f0dSDavid C Somayajulu 		rc = ecore_init_cmd_array(p_hwfn, p_ptt, p_cmd,
35711e25f0dSDavid C Somayajulu 					  b_must_dmae, b_can_dmae);
35811e25f0dSDavid C Somayajulu 		break;
35911e25f0dSDavid C Somayajulu 	case INIT_SRC_RUNTIME:
360217ec208SDavid C Somayajulu 		rc = ecore_init_rt(p_hwfn, p_ptt, addr,
36111e25f0dSDavid C Somayajulu 				   OSAL_LE16_TO_CPU(p_cmd->args.runtime.offset),
36211e25f0dSDavid C Somayajulu 				   OSAL_LE16_TO_CPU(p_cmd->args.runtime.size),
36311e25f0dSDavid C Somayajulu 				   b_must_dmae);
36411e25f0dSDavid C Somayajulu 		break;
36511e25f0dSDavid C Somayajulu 	}
36611e25f0dSDavid C Somayajulu 
36711e25f0dSDavid C Somayajulu 	return rc;
36811e25f0dSDavid C Somayajulu }
36911e25f0dSDavid C Somayajulu 
37011e25f0dSDavid C Somayajulu static OSAL_INLINE bool comp_eq(u32 val, u32 expected_val)
37111e25f0dSDavid C Somayajulu {
37211e25f0dSDavid C Somayajulu 	return (val == expected_val);
37311e25f0dSDavid C Somayajulu }
37411e25f0dSDavid C Somayajulu 
37511e25f0dSDavid C Somayajulu static OSAL_INLINE bool comp_and(u32 val, u32 expected_val)
37611e25f0dSDavid C Somayajulu {
37711e25f0dSDavid C Somayajulu 	return (val & expected_val) == expected_val;
37811e25f0dSDavid C Somayajulu }
37911e25f0dSDavid C Somayajulu 
38011e25f0dSDavid C Somayajulu static OSAL_INLINE bool comp_or(u32 val, u32 expected_val)
38111e25f0dSDavid C Somayajulu {
38211e25f0dSDavid C Somayajulu 	return (val | expected_val) > 0;
38311e25f0dSDavid C Somayajulu }
38411e25f0dSDavid C Somayajulu 
38511e25f0dSDavid C Somayajulu /* init_ops read/poll commands */
38611e25f0dSDavid C Somayajulu static void ecore_init_cmd_rd(struct ecore_hwfn *p_hwfn,
38711e25f0dSDavid C Somayajulu 			      struct ecore_ptt *p_ptt,
388*134b0936SMark O'Donovan 			      const struct init_read_op *cmd)
38911e25f0dSDavid C Somayajulu {
39011e25f0dSDavid C Somayajulu 	bool (*comp_check)(u32 val, u32 expected_val);
39111e25f0dSDavid C Somayajulu 	u32 delay = ECORE_INIT_POLL_PERIOD_US, val;
39211e25f0dSDavid C Somayajulu 	u32 data, addr, poll;
39311e25f0dSDavid C Somayajulu 	int i;
39411e25f0dSDavid C Somayajulu 
39511e25f0dSDavid C Somayajulu 	data = OSAL_LE32_TO_CPU(cmd->op_data);
39611e25f0dSDavid C Somayajulu 	addr = GET_FIELD(data, INIT_READ_OP_ADDRESS) << 2;
39711e25f0dSDavid C Somayajulu 	poll = GET_FIELD(data, INIT_READ_OP_POLL_TYPE);
39811e25f0dSDavid C Somayajulu 
39911e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
40011e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_EMUL(p_hwfn->p_dev))
40111e25f0dSDavid C Somayajulu 		delay *= 100;
40211e25f0dSDavid C Somayajulu #endif
40311e25f0dSDavid C Somayajulu 
40411e25f0dSDavid C Somayajulu 	val = ecore_rd(p_hwfn, p_ptt, addr);
40511e25f0dSDavid C Somayajulu 
40611e25f0dSDavid C Somayajulu 	if (poll == INIT_POLL_NONE)
40711e25f0dSDavid C Somayajulu 		return;
40811e25f0dSDavid C Somayajulu 
40911e25f0dSDavid C Somayajulu 	switch (poll) {
41011e25f0dSDavid C Somayajulu 	case INIT_POLL_EQ:
41111e25f0dSDavid C Somayajulu 		comp_check = comp_eq;
41211e25f0dSDavid C Somayajulu 		break;
41311e25f0dSDavid C Somayajulu 	case INIT_POLL_OR:
41411e25f0dSDavid C Somayajulu 		comp_check = comp_or;
41511e25f0dSDavid C Somayajulu 		break;
41611e25f0dSDavid C Somayajulu 	case INIT_POLL_AND:
41711e25f0dSDavid C Somayajulu 		comp_check = comp_and;
41811e25f0dSDavid C Somayajulu 		break;
41911e25f0dSDavid C Somayajulu 	default:
42011e25f0dSDavid C Somayajulu 		DP_ERR(p_hwfn, "Invalid poll comparison type %08x\n",
42111e25f0dSDavid C Somayajulu 		       cmd->op_data);
42211e25f0dSDavid C Somayajulu 		return;
42311e25f0dSDavid C Somayajulu 	}
42411e25f0dSDavid C Somayajulu 
42511e25f0dSDavid C Somayajulu 	data = OSAL_LE32_TO_CPU(cmd->expected_val);
42611e25f0dSDavid C Somayajulu 	for (i = 0;
42711e25f0dSDavid C Somayajulu 	     i < ECORE_INIT_MAX_POLL_COUNT && !comp_check(val, data);
42811e25f0dSDavid C Somayajulu 	     i++) {
42911e25f0dSDavid C Somayajulu 		OSAL_UDELAY(delay);
43011e25f0dSDavid C Somayajulu 		val = ecore_rd(p_hwfn, p_ptt, addr);
43111e25f0dSDavid C Somayajulu 	}
43211e25f0dSDavid C Somayajulu 
43311e25f0dSDavid C Somayajulu 	if (i == ECORE_INIT_MAX_POLL_COUNT)
434217ec208SDavid C Somayajulu 		DP_ERR(p_hwfn, "Timeout when polling reg: 0x%08x [ Waiting-for: %08x Got: %08x (comparison %08x)]\n",
43511e25f0dSDavid C Somayajulu 		       addr,
43611e25f0dSDavid C Somayajulu 		       OSAL_LE32_TO_CPU(cmd->expected_val), val,
43711e25f0dSDavid C Somayajulu 		       OSAL_LE32_TO_CPU(cmd->op_data));
43811e25f0dSDavid C Somayajulu }
43911e25f0dSDavid C Somayajulu 
440217ec208SDavid C Somayajulu /* init_ops callbacks entry point */
441217ec208SDavid C Somayajulu static enum _ecore_status_t ecore_init_cmd_cb(struct ecore_hwfn *p_hwfn,
442217ec208SDavid C Somayajulu 					      struct ecore_ptt *p_ptt,
443*134b0936SMark O'Donovan 					      const struct init_callback_op *p_cmd)
444217ec208SDavid C Somayajulu {
445217ec208SDavid C Somayajulu 	enum _ecore_status_t rc;
446217ec208SDavid C Somayajulu 
447217ec208SDavid C Somayajulu 	switch (p_cmd->callback_id) {
448217ec208SDavid C Somayajulu 	case DMAE_READY_CB:
449217ec208SDavid C Somayajulu 		rc = ecore_dmae_sanity(p_hwfn, p_ptt, "engine_phase");
450217ec208SDavid C Somayajulu 		break;
451217ec208SDavid C Somayajulu 	default:
452217ec208SDavid C Somayajulu 		DP_NOTICE(p_hwfn, false, "Unexpected init op callback ID %d\n",
453217ec208SDavid C Somayajulu 			  p_cmd->callback_id);
454217ec208SDavid C Somayajulu 		return ECORE_INVAL;
455217ec208SDavid C Somayajulu 	}
456217ec208SDavid C Somayajulu 
457217ec208SDavid C Somayajulu 	return rc;
458217ec208SDavid C Somayajulu }
459217ec208SDavid C Somayajulu 
46011e25f0dSDavid C Somayajulu static u8 ecore_init_cmd_mode_match(struct ecore_hwfn *p_hwfn,
46111e25f0dSDavid C Somayajulu 				    u16 *p_offset, int modes)
46211e25f0dSDavid C Somayajulu {
46311e25f0dSDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
46411e25f0dSDavid C Somayajulu 	const u8 *modes_tree_buf;
46511e25f0dSDavid C Somayajulu 	u8 arg1, arg2, tree_val;
46611e25f0dSDavid C Somayajulu 
46711e25f0dSDavid C Somayajulu 	modes_tree_buf = p_dev->fw_data->modes_tree_buf;
46811e25f0dSDavid C Somayajulu 	tree_val = modes_tree_buf[(*p_offset)++];
46911e25f0dSDavid C Somayajulu 	switch(tree_val) {
47011e25f0dSDavid C Somayajulu 	case INIT_MODE_OP_NOT:
47111e25f0dSDavid C Somayajulu 		return ecore_init_cmd_mode_match(p_hwfn, p_offset, modes) ^ 1;
47211e25f0dSDavid C Somayajulu 	case INIT_MODE_OP_OR:
47311e25f0dSDavid C Somayajulu 		arg1 = ecore_init_cmd_mode_match(p_hwfn, p_offset, modes);
47411e25f0dSDavid C Somayajulu 		arg2 = ecore_init_cmd_mode_match(p_hwfn, p_offset, modes);
47511e25f0dSDavid C Somayajulu 		return arg1 | arg2;
47611e25f0dSDavid C Somayajulu 	case INIT_MODE_OP_AND:
47711e25f0dSDavid C Somayajulu 		arg1 = ecore_init_cmd_mode_match(p_hwfn, p_offset, modes);
47811e25f0dSDavid C Somayajulu 		arg2 = ecore_init_cmd_mode_match(p_hwfn, p_offset, modes);
47911e25f0dSDavid C Somayajulu 		return arg1 & arg2;
48011e25f0dSDavid C Somayajulu 	default:
48111e25f0dSDavid C Somayajulu 		tree_val -= MAX_INIT_MODE_OPS;
48211e25f0dSDavid C Somayajulu 		return (modes & (1 << tree_val)) ? 1 : 0;
48311e25f0dSDavid C Somayajulu 	}
48411e25f0dSDavid C Somayajulu }
48511e25f0dSDavid C Somayajulu 
48611e25f0dSDavid C Somayajulu static u32 ecore_init_cmd_mode(struct ecore_hwfn *p_hwfn,
487*134b0936SMark O'Donovan 			       const struct init_if_mode_op *p_cmd, int modes)
48811e25f0dSDavid C Somayajulu {
48911e25f0dSDavid C Somayajulu 	u16 offset = OSAL_LE16_TO_CPU(p_cmd->modes_buf_offset);
49011e25f0dSDavid C Somayajulu 
49111e25f0dSDavid C Somayajulu 	if (ecore_init_cmd_mode_match(p_hwfn, &offset, modes))
49211e25f0dSDavid C Somayajulu 		return 0;
49311e25f0dSDavid C Somayajulu 	else
49411e25f0dSDavid C Somayajulu 		return GET_FIELD(OSAL_LE32_TO_CPU(p_cmd->op_data),
49511e25f0dSDavid C Somayajulu 				 INIT_IF_MODE_OP_CMD_OFFSET);
49611e25f0dSDavid C Somayajulu }
49711e25f0dSDavid C Somayajulu 
498*134b0936SMark O'Donovan static u32 ecore_init_cmd_phase(const struct init_if_phase_op *p_cmd,
49911e25f0dSDavid C Somayajulu 				u32 phase, u32 phase_id)
50011e25f0dSDavid C Somayajulu {
50111e25f0dSDavid C Somayajulu 	u32 data = OSAL_LE32_TO_CPU(p_cmd->phase_data);
502217ec208SDavid C Somayajulu 	u32 op_data = OSAL_LE32_TO_CPU(p_cmd->op_data);
50311e25f0dSDavid C Somayajulu 
50411e25f0dSDavid C Somayajulu 	if (!(GET_FIELD(data, INIT_IF_PHASE_OP_PHASE) == phase &&
50511e25f0dSDavid C Somayajulu 	      (GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == ANY_PHASE_ID ||
50611e25f0dSDavid C Somayajulu 	       GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == phase_id)))
507217ec208SDavid C Somayajulu 		return GET_FIELD(op_data, INIT_IF_PHASE_OP_CMD_OFFSET);
50811e25f0dSDavid C Somayajulu 	else
50911e25f0dSDavid C Somayajulu 		return 0;
51011e25f0dSDavid C Somayajulu }
51111e25f0dSDavid C Somayajulu 
51211e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_init_run(struct ecore_hwfn *p_hwfn,
51311e25f0dSDavid C Somayajulu 				    struct ecore_ptt *p_ptt,
51411e25f0dSDavid C Somayajulu 				    int phase,
51511e25f0dSDavid C Somayajulu 				    int phase_id,
51611e25f0dSDavid C Somayajulu 				    int modes)
51711e25f0dSDavid C Somayajulu {
51811e25f0dSDavid C Somayajulu 	struct ecore_dev *p_dev = p_hwfn->p_dev;
51911e25f0dSDavid C Somayajulu 	u32 cmd_num, num_init_ops;
520*134b0936SMark O'Donovan 	const union init_op *init_ops;
52111e25f0dSDavid C Somayajulu 	bool b_dmae = false;
52211e25f0dSDavid C Somayajulu 	enum _ecore_status_t rc = ECORE_SUCCESS;
52311e25f0dSDavid C Somayajulu 
52411e25f0dSDavid C Somayajulu 	num_init_ops = p_dev->fw_data->init_ops_size;
52511e25f0dSDavid C Somayajulu 	init_ops = p_dev->fw_data->init_ops;
52611e25f0dSDavid C Somayajulu 
52711e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ZIPPED_FW
52811e25f0dSDavid C Somayajulu 	p_hwfn->unzip_buf = OSAL_ZALLOC(p_hwfn->p_dev, GFP_ATOMIC,
52911e25f0dSDavid C Somayajulu 					MAX_ZIPPED_SIZE * 4);
53011e25f0dSDavid C Somayajulu 	if (!p_hwfn->unzip_buf) {
53111e25f0dSDavid C Somayajulu 		DP_NOTICE(p_hwfn, true, "Failed to allocate unzip buffer\n");
53211e25f0dSDavid C Somayajulu 		return ECORE_NOMEM;
53311e25f0dSDavid C Somayajulu 	}
53411e25f0dSDavid C Somayajulu #endif
53511e25f0dSDavid C Somayajulu 
53611e25f0dSDavid C Somayajulu 	for (cmd_num = 0; cmd_num < num_init_ops; cmd_num++) {
537*134b0936SMark O'Donovan 		const union init_op *cmd = &init_ops[cmd_num];
53811e25f0dSDavid C Somayajulu 		u32 data = OSAL_LE32_TO_CPU(cmd->raw.op_data);
53911e25f0dSDavid C Somayajulu 
54011e25f0dSDavid C Somayajulu 		switch (GET_FIELD(data, INIT_CALLBACK_OP_OP)) {
54111e25f0dSDavid C Somayajulu 		case INIT_OP_WRITE:
54211e25f0dSDavid C Somayajulu 			rc = ecore_init_cmd_wr(p_hwfn, p_ptt, &cmd->write,
54311e25f0dSDavid C Somayajulu 					       b_dmae);
54411e25f0dSDavid C Somayajulu 			break;
54511e25f0dSDavid C Somayajulu 
54611e25f0dSDavid C Somayajulu 		case INIT_OP_READ:
54711e25f0dSDavid C Somayajulu 			ecore_init_cmd_rd(p_hwfn, p_ptt, &cmd->read);
54811e25f0dSDavid C Somayajulu 			break;
54911e25f0dSDavid C Somayajulu 
55011e25f0dSDavid C Somayajulu 		case INIT_OP_IF_MODE:
55111e25f0dSDavid C Somayajulu 			cmd_num += ecore_init_cmd_mode(p_hwfn, &cmd->if_mode,
55211e25f0dSDavid C Somayajulu 						       modes);
55311e25f0dSDavid C Somayajulu 			break;
55411e25f0dSDavid C Somayajulu 		case INIT_OP_IF_PHASE:
5559efd0ba7SDavid C Somayajulu 			cmd_num += ecore_init_cmd_phase(&cmd->if_phase, phase,
5569efd0ba7SDavid C Somayajulu 							phase_id);
55711e25f0dSDavid C Somayajulu 			b_dmae = GET_FIELD(data,
55811e25f0dSDavid C Somayajulu 					   INIT_IF_PHASE_OP_DMAE_ENABLE);
55911e25f0dSDavid C Somayajulu 			break;
56011e25f0dSDavid C Somayajulu 		case INIT_OP_DELAY:
56111e25f0dSDavid C Somayajulu 			/* ecore_init_run is always invoked from
56211e25f0dSDavid C Somayajulu 			 * sleep-able context
56311e25f0dSDavid C Somayajulu 			 */
56411e25f0dSDavid C Somayajulu 			OSAL_UDELAY(cmd->delay.delay);
56511e25f0dSDavid C Somayajulu 			break;
56611e25f0dSDavid C Somayajulu 
56711e25f0dSDavid C Somayajulu 		case INIT_OP_CALLBACK:
568217ec208SDavid C Somayajulu 			rc = ecore_init_cmd_cb(p_hwfn, p_ptt, &cmd->callback);
56911e25f0dSDavid C Somayajulu 			break;
57011e25f0dSDavid C Somayajulu 		}
57111e25f0dSDavid C Somayajulu 
57211e25f0dSDavid C Somayajulu 		if (rc)
57311e25f0dSDavid C Somayajulu 			break;
57411e25f0dSDavid C Somayajulu 	}
57511e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_ZIPPED_FW
57611e25f0dSDavid C Somayajulu 	OSAL_FREE(p_hwfn->p_dev, p_hwfn->unzip_buf);
57711e25f0dSDavid C Somayajulu 	p_hwfn->unzip_buf = OSAL_NULL;
57811e25f0dSDavid C Somayajulu #endif
57911e25f0dSDavid C Somayajulu 	return rc;
58011e25f0dSDavid C Somayajulu }
58111e25f0dSDavid C Somayajulu 
5829efd0ba7SDavid C Somayajulu void ecore_gtt_init(struct ecore_hwfn *p_hwfn,
5839efd0ba7SDavid C Somayajulu 		    struct ecore_ptt *p_ptt)
58411e25f0dSDavid C Somayajulu {
58511e25f0dSDavid C Somayajulu 	u32 gtt_base;
58611e25f0dSDavid C Somayajulu 	u32 i;
58711e25f0dSDavid C Somayajulu 
58811e25f0dSDavid C Somayajulu #ifndef ASIC_ONLY
58911e25f0dSDavid C Somayajulu 	if (CHIP_REV_IS_SLOW(p_hwfn->p_dev)) {
59011e25f0dSDavid C Somayajulu 		/* This is done by MFW on ASIC; regardless, this should only
59111e25f0dSDavid C Somayajulu 		 * be done once per chip [i.e., common]. Implementation is
59211e25f0dSDavid C Somayajulu 		 * not too bright, but it should work on the simple FPGA/EMUL
59311e25f0dSDavid C Somayajulu 		 * scenarios.
59411e25f0dSDavid C Somayajulu 		 */
59511e25f0dSDavid C Somayajulu 		static bool initialized = false;
59611e25f0dSDavid C Somayajulu 		int poll_cnt = 500;
59711e25f0dSDavid C Somayajulu 		u32 val;
59811e25f0dSDavid C Somayajulu 
59911e25f0dSDavid C Somayajulu 		/* initialize PTT/GTT (poll for completion) */
60011e25f0dSDavid C Somayajulu 		if (!initialized) {
6019efd0ba7SDavid C Somayajulu 			ecore_wr(p_hwfn, p_ptt,
60211e25f0dSDavid C Somayajulu 				 PGLUE_B_REG_START_INIT_PTT_GTT, 1);
60311e25f0dSDavid C Somayajulu 			initialized = true;
60411e25f0dSDavid C Somayajulu 		}
60511e25f0dSDavid C Somayajulu 
60611e25f0dSDavid C Somayajulu 		do {
60711e25f0dSDavid C Somayajulu 			/* ptt might be overrided by HW until this is done */
60811e25f0dSDavid C Somayajulu 			OSAL_UDELAY(10);
60911e25f0dSDavid C Somayajulu 			ecore_ptt_invalidate(p_hwfn);
6109efd0ba7SDavid C Somayajulu 			val = ecore_rd(p_hwfn, p_ptt,
61111e25f0dSDavid C Somayajulu 				       PGLUE_B_REG_INIT_DONE_PTT_GTT);
61211e25f0dSDavid C Somayajulu 		} while ((val != 1) && --poll_cnt);
61311e25f0dSDavid C Somayajulu 
61411e25f0dSDavid C Somayajulu 		if (!poll_cnt)
61511e25f0dSDavid C Somayajulu 			DP_ERR(p_hwfn, "PGLUE_B_REG_INIT_DONE didn't complete\n");
61611e25f0dSDavid C Somayajulu 	}
61711e25f0dSDavid C Somayajulu #endif
61811e25f0dSDavid C Somayajulu 
61911e25f0dSDavid C Somayajulu 	/* Set the global windows */
62011e25f0dSDavid C Somayajulu 	gtt_base = PXP_PF_WINDOW_ADMIN_START + PXP_PF_WINDOW_ADMIN_GLOBAL_START;
62111e25f0dSDavid C Somayajulu 
62211e25f0dSDavid C Somayajulu 	for (i = 0; i < OSAL_ARRAY_SIZE(pxp_global_win); i++)
62311e25f0dSDavid C Somayajulu 		if (pxp_global_win[i])
62411e25f0dSDavid C Somayajulu 			REG_WR(p_hwfn, gtt_base + i * PXP_GLOBAL_ENTRY_SIZE,
62511e25f0dSDavid C Somayajulu 			       pxp_global_win[i]);
62611e25f0dSDavid C Somayajulu }
62711e25f0dSDavid C Somayajulu 
62811e25f0dSDavid C Somayajulu enum _ecore_status_t ecore_init_fw_data(struct ecore_dev *p_dev,
6299efd0ba7SDavid C Somayajulu #ifdef CONFIG_ECORE_BINARY_FW
6309efd0ba7SDavid C Somayajulu 					const u8 *fw_data)
6319efd0ba7SDavid C Somayajulu #else
6329efd0ba7SDavid C Somayajulu 					const u8 OSAL_UNUSED *fw_data)
6339efd0ba7SDavid C Somayajulu #endif
63411e25f0dSDavid C Somayajulu {
63511e25f0dSDavid C Somayajulu 	struct ecore_fw_data *fw = p_dev->fw_data;
63611e25f0dSDavid C Somayajulu 
63711e25f0dSDavid C Somayajulu #ifdef CONFIG_ECORE_BINARY_FW
63811e25f0dSDavid C Somayajulu 	struct bin_buffer_hdr *buf_hdr;
63911e25f0dSDavid C Somayajulu 	u32 offset, len;
64011e25f0dSDavid C Somayajulu 
6419efd0ba7SDavid C Somayajulu 	if (!fw_data) {
64211e25f0dSDavid C Somayajulu 		DP_NOTICE(p_dev, true, "Invalid fw data\n");
64311e25f0dSDavid C Somayajulu 		return ECORE_INVAL;
64411e25f0dSDavid C Somayajulu 	}
64511e25f0dSDavid C Somayajulu 
6469efd0ba7SDavid C Somayajulu 	buf_hdr = (struct bin_buffer_hdr *)fw_data;
64711e25f0dSDavid C Somayajulu 
64811e25f0dSDavid C Somayajulu 	offset = buf_hdr[BIN_BUF_INIT_FW_VER_INFO].offset;
6499efd0ba7SDavid C Somayajulu 	fw->fw_ver_info = (struct fw_ver_info *)(fw_data + offset);
65011e25f0dSDavid C Somayajulu 
65111e25f0dSDavid C Somayajulu 	offset = buf_hdr[BIN_BUF_INIT_CMD].offset;
6529efd0ba7SDavid C Somayajulu 	fw->init_ops = (union init_op *)(fw_data + offset);
65311e25f0dSDavid C Somayajulu 
65411e25f0dSDavid C Somayajulu 	offset = buf_hdr[BIN_BUF_INIT_VAL].offset;
6559efd0ba7SDavid C Somayajulu 	fw->arr_data = (u32 *)(fw_data + offset);
65611e25f0dSDavid C Somayajulu 
65711e25f0dSDavid C Somayajulu 	offset = buf_hdr[BIN_BUF_INIT_MODE_TREE].offset;
6589efd0ba7SDavid C Somayajulu 	fw->modes_tree_buf = (u8 *)(fw_data + offset);
65911e25f0dSDavid C Somayajulu 	len = buf_hdr[BIN_BUF_INIT_CMD].length;
66011e25f0dSDavid C Somayajulu 	fw->init_ops_size = len / sizeof(struct init_raw_op);
66111e25f0dSDavid C Somayajulu #else
662*134b0936SMark O'Donovan 	fw->init_ops = (const union init_op *)init_ops;
663*134b0936SMark O'Donovan 	fw->arr_data = (const u32 *)init_val;
664*134b0936SMark O'Donovan 	fw->modes_tree_buf = (const u8 *)modes_tree_buf;
66511e25f0dSDavid C Somayajulu 	fw->init_ops_size = init_ops_size;
66611e25f0dSDavid C Somayajulu #endif
66711e25f0dSDavid C Somayajulu 
66811e25f0dSDavid C Somayajulu 	return ECORE_SUCCESS;
66911e25f0dSDavid C Somayajulu }
670