11f4d4ed6SAlexander Lobakin // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2fe56b9e6SYuval Mintz /* QLogic qed NIC Driver
3e8f1cb50SMintz, Yuval * Copyright (c) 2015-2017 QLogic Corporation
4663eacd8SAlexander Lobakin * Copyright (c) 2019-2020 Marvell International Ltd.
5fe56b9e6SYuval Mintz */
6fe56b9e6SYuval Mintz
7fe56b9e6SYuval Mintz #include <linux/types.h>
8fe56b9e6SYuval Mintz #include <linux/io.h>
9fe56b9e6SYuval Mintz #include <linux/delay.h>
10fe56b9e6SYuval Mintz #include <linux/errno.h>
11fe56b9e6SYuval Mintz #include <linux/kernel.h>
12fe56b9e6SYuval Mintz #include <linux/slab.h>
13fe56b9e6SYuval Mintz #include <linux/string.h>
14fe56b9e6SYuval Mintz #include "qed.h"
15fe56b9e6SYuval Mintz #include "qed_hsi.h"
16fe56b9e6SYuval Mintz #include "qed_hw.h"
17fe56b9e6SYuval Mintz #include "qed_init_ops.h"
18*b90cb538SOmkar Kulkarni #include "qed_iro_hsi.h"
19fe56b9e6SYuval Mintz #include "qed_reg_addr.h"
201408cc1fSYuval Mintz #include "qed_sriov.h"
21fe56b9e6SYuval Mintz
22fe56b9e6SYuval Mintz #define QED_INIT_MAX_POLL_COUNT 100
23fe56b9e6SYuval Mintz #define QED_INIT_POLL_PERIOD_US 500
24fe56b9e6SYuval Mintz
25fe56b9e6SYuval Mintz static u32 pxp_global_win[] = {
26fe56b9e6SYuval Mintz 0,
27fe56b9e6SYuval Mintz 0,
28fe56b9e6SYuval Mintz 0x1c02, /* win 2: addr=0x1c02000, size=4096 bytes */
29fe56b9e6SYuval Mintz 0x1c80, /* win 3: addr=0x1c80000, size=4096 bytes */
30fe56b9e6SYuval Mintz 0x1d00, /* win 4: addr=0x1d00000, size=4096 bytes */
31fe56b9e6SYuval Mintz 0x1d01, /* win 5: addr=0x1d01000, size=4096 bytes */
326aebde8dSMichal Kalderon 0x1d02, /* win 6: addr=0x1d02000, size=4096 bytes */
336aebde8dSMichal Kalderon 0x1d80, /* win 7: addr=0x1d80000, size=4096 bytes */
346aebde8dSMichal Kalderon 0x1d81, /* win 8: addr=0x1d81000, size=4096 bytes */
356aebde8dSMichal Kalderon 0x1d82, /* win 9: addr=0x1d82000, size=4096 bytes */
366aebde8dSMichal Kalderon 0x1e00, /* win 10: addr=0x1e00000, size=4096 bytes */
376aebde8dSMichal Kalderon 0x1e01, /* win 11: addr=0x1e01000, size=4096 bytes */
386aebde8dSMichal Kalderon 0x1e80, /* win 12: addr=0x1e80000, size=4096 bytes */
396aebde8dSMichal Kalderon 0x1f00, /* win 13: addr=0x1f00000, size=4096 bytes */
406aebde8dSMichal Kalderon 0x1c08, /* win 14: addr=0x1c08000, size=4096 bytes */
41fe56b9e6SYuval Mintz 0,
42fe56b9e6SYuval Mintz 0,
43fe56b9e6SYuval Mintz 0,
44fe56b9e6SYuval Mintz 0,
45fe56b9e6SYuval Mintz };
46fe56b9e6SYuval Mintz
470dfda108SAlexander Lobakin /* IRO Array */
480dfda108SAlexander Lobakin static const u32 iro_arr[] = {
490dfda108SAlexander Lobakin 0x00000000, 0x00000000, 0x00080000,
50*b90cb538SOmkar Kulkarni 0x00004478, 0x00000008, 0x00080000,
510dfda108SAlexander Lobakin 0x00003288, 0x00000088, 0x00880000,
52*b90cb538SOmkar Kulkarni 0x000058a8, 0x00000020, 0x00200000,
53*b90cb538SOmkar Kulkarni 0x00003188, 0x00000008, 0x00080000,
540dfda108SAlexander Lobakin 0x00000b00, 0x00000008, 0x00040000,
550dfda108SAlexander Lobakin 0x00000a80, 0x00000008, 0x00040000,
560dfda108SAlexander Lobakin 0x00000000, 0x00000008, 0x00020000,
570dfda108SAlexander Lobakin 0x00000080, 0x00000008, 0x00040000,
580dfda108SAlexander Lobakin 0x00000084, 0x00000008, 0x00020000,
59*b90cb538SOmkar Kulkarni 0x00005798, 0x00000004, 0x00040000,
60*b90cb538SOmkar Kulkarni 0x00004e50, 0x00000000, 0x00780000,
610dfda108SAlexander Lobakin 0x00003e40, 0x00000000, 0x00780000,
62*b90cb538SOmkar Kulkarni 0x00004500, 0x00000000, 0x00780000,
630dfda108SAlexander Lobakin 0x00003210, 0x00000000, 0x00780000,
640dfda108SAlexander Lobakin 0x00003b50, 0x00000000, 0x00780000,
650dfda108SAlexander Lobakin 0x00007f58, 0x00000000, 0x00780000,
66*b90cb538SOmkar Kulkarni 0x00005fd8, 0x00000000, 0x00080000,
670dfda108SAlexander Lobakin 0x00007100, 0x00000000, 0x00080000,
68*b90cb538SOmkar Kulkarni 0x0000af20, 0x00000000, 0x00080000,
690dfda108SAlexander Lobakin 0x00004398, 0x00000000, 0x00080000,
700dfda108SAlexander Lobakin 0x0000a5a0, 0x00000000, 0x00080000,
710dfda108SAlexander Lobakin 0x0000bde8, 0x00000000, 0x00080000,
720dfda108SAlexander Lobakin 0x00000020, 0x00000004, 0x00040000,
73*b90cb538SOmkar Kulkarni 0x00005688, 0x00000010, 0x00100000,
740dfda108SAlexander Lobakin 0x0000c210, 0x00000030, 0x00300000,
75*b90cb538SOmkar Kulkarni 0x0000b108, 0x00000038, 0x00380000,
760dfda108SAlexander Lobakin 0x00003d20, 0x00000080, 0x00400000,
770dfda108SAlexander Lobakin 0x0000bf60, 0x00000000, 0x00040000,
780dfda108SAlexander Lobakin 0x00004560, 0x00040080, 0x00040000,
790dfda108SAlexander Lobakin 0x000001f8, 0x00000004, 0x00040000,
800dfda108SAlexander Lobakin 0x00003d60, 0x00000080, 0x00200000,
810dfda108SAlexander Lobakin 0x00008960, 0x00000040, 0x00300000,
820dfda108SAlexander Lobakin 0x0000e840, 0x00000060, 0x00600000,
83*b90cb538SOmkar Kulkarni 0x00004698, 0x00000080, 0x00380000,
84*b90cb538SOmkar Kulkarni 0x000107b8, 0x000000c0, 0x00c00000,
850dfda108SAlexander Lobakin 0x000001f8, 0x00000002, 0x00020000,
86*b90cb538SOmkar Kulkarni 0x0000a260, 0x00000000, 0x01080000,
87*b90cb538SOmkar Kulkarni 0x0000a368, 0x00000008, 0x00080000,
880dfda108SAlexander Lobakin 0x000001c0, 0x00000008, 0x00080000,
890dfda108SAlexander Lobakin 0x000001f8, 0x00000008, 0x00080000,
900dfda108SAlexander Lobakin 0x00000ac0, 0x00000008, 0x00080000,
910dfda108SAlexander Lobakin 0x00002578, 0x00000008, 0x00080000,
920dfda108SAlexander Lobakin 0x000024f8, 0x00000008, 0x00080000,
930dfda108SAlexander Lobakin 0x00000280, 0x00000008, 0x00080000,
940dfda108SAlexander Lobakin 0x00000680, 0x00080018, 0x00080000,
950dfda108SAlexander Lobakin 0x00000b78, 0x00080018, 0x00020000,
96*b90cb538SOmkar Kulkarni 0x0000c600, 0x00000058, 0x003c0000,
97*b90cb538SOmkar Kulkarni 0x00012038, 0x00000020, 0x00100000,
98*b90cb538SOmkar Kulkarni 0x00011b00, 0x00000048, 0x00180000,
99*b90cb538SOmkar Kulkarni 0x00009650, 0x00000050, 0x00200000,
1000dfda108SAlexander Lobakin 0x00008b10, 0x00000040, 0x00280000,
101*b90cb538SOmkar Kulkarni 0x000116c0, 0x00000018, 0x00100000,
102*b90cb538SOmkar Kulkarni 0x0000c808, 0x00000048, 0x00380000,
103*b90cb538SOmkar Kulkarni 0x00011790, 0x00000020, 0x00200000,
104*b90cb538SOmkar Kulkarni 0x000046d0, 0x00000080, 0x00100000,
1050dfda108SAlexander Lobakin 0x00003618, 0x00000010, 0x00100000,
106*b90cb538SOmkar Kulkarni 0x0000a9e8, 0x00000008, 0x00010000,
1070dfda108SAlexander Lobakin 0x000097a0, 0x00000008, 0x00010000,
108*b90cb538SOmkar Kulkarni 0x00011a10, 0x00000008, 0x00010000,
109*b90cb538SOmkar Kulkarni 0x0000e9f8, 0x00000008, 0x00010000,
110*b90cb538SOmkar Kulkarni 0x00012648, 0x00000008, 0x00010000,
111*b90cb538SOmkar Kulkarni 0x000121c8, 0x00000008, 0x00010000,
112*b90cb538SOmkar Kulkarni 0x0000af08, 0x00000030, 0x00100000,
113*b90cb538SOmkar Kulkarni 0x0000d748, 0x00000028, 0x00280000,
114*b90cb538SOmkar Kulkarni 0x00009e68, 0x00000018, 0x00180000,
115*b90cb538SOmkar Kulkarni 0x00009fe8, 0x00000008, 0x00080000,
116*b90cb538SOmkar Kulkarni 0x00013ea8, 0x00000008, 0x00080000,
117*b90cb538SOmkar Kulkarni 0x00012f18, 0x00000018, 0x00180000,
118*b90cb538SOmkar Kulkarni 0x0000dfe8, 0x00500288, 0x00100000,
119*b90cb538SOmkar Kulkarni 0x000131a0, 0x00000138, 0x00280000,
1200dfda108SAlexander Lobakin };
1210dfda108SAlexander Lobakin
qed_init_iro_array(struct qed_dev * cdev)122fe56b9e6SYuval Mintz void qed_init_iro_array(struct qed_dev *cdev)
123fe56b9e6SYuval Mintz {
124*b90cb538SOmkar Kulkarni cdev->iro_arr = iro_arr + E4_IRO_ARR_OFFSET;
125fe56b9e6SYuval Mintz }
126fe56b9e6SYuval Mintz
qed_init_store_rt_reg(struct qed_hwfn * p_hwfn,u32 rt_offset,u32 val)1271a635e48SYuval Mintz void qed_init_store_rt_reg(struct qed_hwfn *p_hwfn, u32 rt_offset, u32 val)
128fe56b9e6SYuval Mintz {
129*b90cb538SOmkar Kulkarni if (rt_offset >= RUNTIME_ARRAY_SIZE) {
130*b90cb538SOmkar Kulkarni DP_ERR(p_hwfn,
131*b90cb538SOmkar Kulkarni "Avoid storing %u in rt_data at index %u!\n",
132*b90cb538SOmkar Kulkarni val, rt_offset);
133*b90cb538SOmkar Kulkarni return;
134*b90cb538SOmkar Kulkarni }
135*b90cb538SOmkar Kulkarni
136fc48b7a6SYuval Mintz p_hwfn->rt_data.init_val[rt_offset] = val;
137fc48b7a6SYuval Mintz p_hwfn->rt_data.b_valid[rt_offset] = true;
138fe56b9e6SYuval Mintz }
139fe56b9e6SYuval Mintz
qed_init_store_rt_agg(struct qed_hwfn * p_hwfn,u32 rt_offset,u32 * p_val,size_t size)140fe56b9e6SYuval Mintz void qed_init_store_rt_agg(struct qed_hwfn *p_hwfn,
1411a635e48SYuval Mintz u32 rt_offset, u32 *p_val, size_t size)
142fe56b9e6SYuval Mintz {
143fe56b9e6SYuval Mintz size_t i;
144fe56b9e6SYuval Mintz
145*b90cb538SOmkar Kulkarni if ((rt_offset + size - 1) >= RUNTIME_ARRAY_SIZE) {
146*b90cb538SOmkar Kulkarni DP_ERR(p_hwfn,
147*b90cb538SOmkar Kulkarni "Avoid storing values in rt_data at indices %u-%u!\n",
148*b90cb538SOmkar Kulkarni rt_offset,
149*b90cb538SOmkar Kulkarni (u32)(rt_offset + size - 1));
150*b90cb538SOmkar Kulkarni return;
151*b90cb538SOmkar Kulkarni }
152*b90cb538SOmkar Kulkarni
153fe56b9e6SYuval Mintz for (i = 0; i < size / sizeof(u32); i++) {
154fc48b7a6SYuval Mintz p_hwfn->rt_data.init_val[rt_offset + i] = p_val[i];
155fc48b7a6SYuval Mintz p_hwfn->rt_data.b_valid[rt_offset + i] = true;
156fe56b9e6SYuval Mintz }
157fe56b9e6SYuval Mintz }
158fe56b9e6SYuval Mintz
qed_init_rt(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,u32 addr,u16 rt_offset,u16 size,bool b_must_dmae)159fc48b7a6SYuval Mintz static int qed_init_rt(struct qed_hwfn *p_hwfn,
160fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
1611a635e48SYuval Mintz u32 addr, u16 rt_offset, u16 size, bool b_must_dmae)
162fe56b9e6SYuval Mintz {
163fc48b7a6SYuval Mintz u32 *p_init_val = &p_hwfn->rt_data.init_val[rt_offset];
164fc48b7a6SYuval Mintz bool *p_valid = &p_hwfn->rt_data.b_valid[rt_offset];
1656bc82d9bSMichal Kalderon u16 i, j, segment;
166fc48b7a6SYuval Mintz int rc = 0;
167fe56b9e6SYuval Mintz
168fc48b7a6SYuval Mintz /* Since not all RT entries are initialized, go over the RT and
169fc48b7a6SYuval Mintz * for each segment of initialized values use DMA.
170fc48b7a6SYuval Mintz */
171fe56b9e6SYuval Mintz for (i = 0; i < size; i++) {
172fc48b7a6SYuval Mintz if (!p_valid[i])
173fe56b9e6SYuval Mintz continue;
174fc48b7a6SYuval Mintz
175fc48b7a6SYuval Mintz /* In case there isn't any wide-bus configuration here,
176fc48b7a6SYuval Mintz * simply write the data instead of using dmae.
177fc48b7a6SYuval Mintz */
178fc48b7a6SYuval Mintz if (!b_must_dmae) {
1791a635e48SYuval Mintz qed_wr(p_hwfn, p_ptt, addr + (i << 2), p_init_val[i]);
1806bc82d9bSMichal Kalderon p_valid[i] = false;
181fc48b7a6SYuval Mintz continue;
182fe56b9e6SYuval Mintz }
183fc48b7a6SYuval Mintz
184fc48b7a6SYuval Mintz /* Start of a new segment */
185fc48b7a6SYuval Mintz for (segment = 1; i + segment < size; segment++)
186fc48b7a6SYuval Mintz if (!p_valid[i + segment])
187fc48b7a6SYuval Mintz break;
188fc48b7a6SYuval Mintz
189fc48b7a6SYuval Mintz rc = qed_dmae_host2grc(p_hwfn, p_ptt,
190fc48b7a6SYuval Mintz (uintptr_t)(p_init_val + i),
19183bf76e3SMichal Kalderon addr + (i << 2), segment, NULL);
1921a635e48SYuval Mintz if (rc)
193fc48b7a6SYuval Mintz return rc;
194fc48b7a6SYuval Mintz
1956bc82d9bSMichal Kalderon /* invalidate after writing */
196*b90cb538SOmkar Kulkarni for (j = i; j < (u32)(i + segment); j++)
1976bc82d9bSMichal Kalderon p_valid[j] = false;
1986bc82d9bSMichal Kalderon
199fc48b7a6SYuval Mintz /* Jump over the entire segment, including invalid entry */
200fc48b7a6SYuval Mintz i += segment;
201fc48b7a6SYuval Mintz }
202fc48b7a6SYuval Mintz
203fc48b7a6SYuval Mintz return rc;
204fe56b9e6SYuval Mintz }
205fe56b9e6SYuval Mintz
qed_init_alloc(struct qed_hwfn * p_hwfn)206fe56b9e6SYuval Mintz int qed_init_alloc(struct qed_hwfn *p_hwfn)
207fe56b9e6SYuval Mintz {
208fc48b7a6SYuval Mintz struct qed_rt_data *rt_data = &p_hwfn->rt_data;
209fe56b9e6SYuval Mintz
2101408cc1fSYuval Mintz if (IS_VF(p_hwfn->cdev))
2111408cc1fSYuval Mintz return 0;
2121408cc1fSYuval Mintz
2136396bb22SKees Cook rt_data->b_valid = kcalloc(RUNTIME_ARRAY_SIZE, sizeof(bool),
214fc48b7a6SYuval Mintz GFP_KERNEL);
215fc48b7a6SYuval Mintz if (!rt_data->b_valid)
216fe56b9e6SYuval Mintz return -ENOMEM;
217fe56b9e6SYuval Mintz
2186396bb22SKees Cook rt_data->init_val = kcalloc(RUNTIME_ARRAY_SIZE, sizeof(u32),
219fc48b7a6SYuval Mintz GFP_KERNEL);
220fc48b7a6SYuval Mintz if (!rt_data->init_val) {
221fc48b7a6SYuval Mintz kfree(rt_data->b_valid);
2223587cb87STomer Tayar rt_data->b_valid = NULL;
223fc48b7a6SYuval Mintz return -ENOMEM;
224fc48b7a6SYuval Mintz }
225fe56b9e6SYuval Mintz
226fe56b9e6SYuval Mintz return 0;
227fe56b9e6SYuval Mintz }
228fe56b9e6SYuval Mintz
qed_init_free(struct qed_hwfn * p_hwfn)229fe56b9e6SYuval Mintz void qed_init_free(struct qed_hwfn *p_hwfn)
230fe56b9e6SYuval Mintz {
231fc48b7a6SYuval Mintz kfree(p_hwfn->rt_data.init_val);
2323587cb87STomer Tayar p_hwfn->rt_data.init_val = NULL;
233fc48b7a6SYuval Mintz kfree(p_hwfn->rt_data.b_valid);
2343587cb87STomer Tayar p_hwfn->rt_data.b_valid = NULL;
235fe56b9e6SYuval Mintz }
236fe56b9e6SYuval Mintz
qed_init_array_dmae(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,u32 addr,u32 dmae_data_offset,u32 size,const u32 * buf,bool b_must_dmae,bool b_can_dmae)237fe56b9e6SYuval Mintz static int qed_init_array_dmae(struct qed_hwfn *p_hwfn,
238fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
239fe56b9e6SYuval Mintz u32 addr,
240fe56b9e6SYuval Mintz u32 dmae_data_offset,
241fe56b9e6SYuval Mintz u32 size,
242fe56b9e6SYuval Mintz const u32 *buf,
243fe56b9e6SYuval Mintz bool b_must_dmae,
244fe56b9e6SYuval Mintz bool b_can_dmae)
245fe56b9e6SYuval Mintz {
246fe56b9e6SYuval Mintz int rc = 0;
247fe56b9e6SYuval Mintz
248fe56b9e6SYuval Mintz /* Perform DMAE only for lengthy enough sections or for wide-bus */
249fe56b9e6SYuval Mintz if (!b_can_dmae || (!b_must_dmae && (size < 16))) {
250fe56b9e6SYuval Mintz const u32 *data = buf + dmae_data_offset;
251fe56b9e6SYuval Mintz u32 i;
252fe56b9e6SYuval Mintz
253fe56b9e6SYuval Mintz for (i = 0; i < size; i++)
254fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, addr + (i << 2), data[i]);
255fe56b9e6SYuval Mintz } else {
256fe56b9e6SYuval Mintz rc = qed_dmae_host2grc(p_hwfn, p_ptt,
257fe56b9e6SYuval Mintz (uintptr_t)(buf + dmae_data_offset),
25883bf76e3SMichal Kalderon addr, size, NULL);
259fe56b9e6SYuval Mintz }
260fe56b9e6SYuval Mintz
261fe56b9e6SYuval Mintz return rc;
262fe56b9e6SYuval Mintz }
263fe56b9e6SYuval Mintz
qed_init_fill_dmae(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,u32 addr,u32 fill_count)264fe56b9e6SYuval Mintz static int qed_init_fill_dmae(struct qed_hwfn *p_hwfn,
265fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
266*b90cb538SOmkar Kulkarni u32 addr, u32 fill_count)
267fe56b9e6SYuval Mintz {
268fe56b9e6SYuval Mintz static u32 zero_buffer[DMAE_MAX_RW_SIZE];
26983bf76e3SMichal Kalderon struct qed_dmae_params params = {};
270fe56b9e6SYuval Mintz
271fe56b9e6SYuval Mintz memset(zero_buffer, 0, sizeof(u32) * DMAE_MAX_RW_SIZE);
272fe56b9e6SYuval Mintz
273fe56b9e6SYuval Mintz /* invoke the DMAE virtual/physical buffer API with
274fe56b9e6SYuval Mintz * 1. DMAE init channel
275fe56b9e6SYuval Mintz * 2. addr,
276fe56b9e6SYuval Mintz * 3. p_hwfb->temp_data,
277fe56b9e6SYuval Mintz * 4. fill_count
278fe56b9e6SYuval Mintz */
279804c5702SMichal Kalderon SET_FIELD(params.flags, QED_DMAE_PARAMS_RW_REPL_SRC, 0x1);
280fe56b9e6SYuval Mintz return qed_dmae_host2grc(p_hwfn, p_ptt,
281fe56b9e6SYuval Mintz (uintptr_t)(&zero_buffer[0]),
28283bf76e3SMichal Kalderon addr, fill_count, ¶ms);
283fe56b9e6SYuval Mintz }
284fe56b9e6SYuval Mintz
qed_init_fill(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,u32 addr,u32 fill,u32 fill_count)285fe56b9e6SYuval Mintz static void qed_init_fill(struct qed_hwfn *p_hwfn,
286fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
2871a635e48SYuval Mintz u32 addr, u32 fill, u32 fill_count)
288fe56b9e6SYuval Mintz {
289fe56b9e6SYuval Mintz u32 i;
290fe56b9e6SYuval Mintz
291fe56b9e6SYuval Mintz for (i = 0; i < fill_count; i++, addr += sizeof(u32))
292fe56b9e6SYuval Mintz qed_wr(p_hwfn, p_ptt, addr, fill);
293fe56b9e6SYuval Mintz }
294fe56b9e6SYuval Mintz
qed_init_cmd_array(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,struct init_write_op * cmd,bool b_must_dmae,bool b_can_dmae)295fe56b9e6SYuval Mintz static int qed_init_cmd_array(struct qed_hwfn *p_hwfn,
296fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
297fe56b9e6SYuval Mintz struct init_write_op *cmd,
2981a635e48SYuval Mintz bool b_must_dmae, bool b_can_dmae)
299fe56b9e6SYuval Mintz {
3001a635e48SYuval Mintz u32 dmae_array_offset = le32_to_cpu(cmd->args.array_offset);
301fe56b9e6SYuval Mintz u32 data = le32_to_cpu(cmd->data);
302fe56b9e6SYuval Mintz u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2;
3031a635e48SYuval Mintz
304fe56b9e6SYuval Mintz u32 offset, output_len, input_len, max_size;
305fe56b9e6SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev;
306fe56b9e6SYuval Mintz union init_array_hdr *hdr;
307fe56b9e6SYuval Mintz const u32 *array_data;
308fe56b9e6SYuval Mintz int rc = 0;
309fe56b9e6SYuval Mintz u32 size;
310fe56b9e6SYuval Mintz
311fe56b9e6SYuval Mintz array_data = cdev->fw_data->arr_data;
312fe56b9e6SYuval Mintz
3131a635e48SYuval Mintz hdr = (union init_array_hdr *)(array_data + dmae_array_offset);
314fe56b9e6SYuval Mintz data = le32_to_cpu(hdr->raw.data);
315fe56b9e6SYuval Mintz switch (GET_FIELD(data, INIT_ARRAY_RAW_HDR_TYPE)) {
316fe56b9e6SYuval Mintz case INIT_ARR_ZIPPED:
317fe56b9e6SYuval Mintz offset = dmae_array_offset + 1;
318fe56b9e6SYuval Mintz input_len = GET_FIELD(data,
319fe56b9e6SYuval Mintz INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE);
320fe56b9e6SYuval Mintz max_size = MAX_ZIPPED_SIZE * 4;
321fe56b9e6SYuval Mintz memset(p_hwfn->unzip_buf, 0, max_size);
322fe56b9e6SYuval Mintz
323fe56b9e6SYuval Mintz output_len = qed_unzip_data(p_hwfn, input_len,
324fe56b9e6SYuval Mintz (u8 *)&array_data[offset],
325fe56b9e6SYuval Mintz max_size, (u8 *)p_hwfn->unzip_buf);
326fe56b9e6SYuval Mintz if (output_len) {
327fe56b9e6SYuval Mintz rc = qed_init_array_dmae(p_hwfn, p_ptt, addr, 0,
328fe56b9e6SYuval Mintz output_len,
329fe56b9e6SYuval Mintz p_hwfn->unzip_buf,
330fe56b9e6SYuval Mintz b_must_dmae, b_can_dmae);
331fe56b9e6SYuval Mintz } else {
332fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn, "Failed to unzip dmae data\n");
333fe56b9e6SYuval Mintz rc = -EINVAL;
334fe56b9e6SYuval Mintz }
335fe56b9e6SYuval Mintz break;
336fe56b9e6SYuval Mintz case INIT_ARR_PATTERN:
337fe56b9e6SYuval Mintz {
338fe56b9e6SYuval Mintz u32 repeats = GET_FIELD(data,
339fe56b9e6SYuval Mintz INIT_ARRAY_PATTERN_HDR_REPETITIONS);
340fe56b9e6SYuval Mintz u32 i;
341fe56b9e6SYuval Mintz
342fe56b9e6SYuval Mintz size = GET_FIELD(data, INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE);
343fe56b9e6SYuval Mintz
344fe56b9e6SYuval Mintz for (i = 0; i < repeats; i++, addr += size << 2) {
345fe56b9e6SYuval Mintz rc = qed_init_array_dmae(p_hwfn, p_ptt, addr,
346fe56b9e6SYuval Mintz dmae_array_offset + 1,
347fe56b9e6SYuval Mintz size, array_data,
348fe56b9e6SYuval Mintz b_must_dmae, b_can_dmae);
349fe56b9e6SYuval Mintz if (rc)
350fe56b9e6SYuval Mintz break;
351fe56b9e6SYuval Mintz }
352fe56b9e6SYuval Mintz break;
353fe56b9e6SYuval Mintz }
354fe56b9e6SYuval Mintz case INIT_ARR_STANDARD:
355fe56b9e6SYuval Mintz size = GET_FIELD(data, INIT_ARRAY_STANDARD_HDR_SIZE);
356fe56b9e6SYuval Mintz rc = qed_init_array_dmae(p_hwfn, p_ptt, addr,
357fe56b9e6SYuval Mintz dmae_array_offset + 1,
358fe56b9e6SYuval Mintz size, array_data,
359fe56b9e6SYuval Mintz b_must_dmae, b_can_dmae);
360fe56b9e6SYuval Mintz break;
361fe56b9e6SYuval Mintz }
362fe56b9e6SYuval Mintz
363fe56b9e6SYuval Mintz return rc;
364fe56b9e6SYuval Mintz }
365fe56b9e6SYuval Mintz
366fe56b9e6SYuval Mintz /* init_ops write command */
qed_init_cmd_wr(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,struct init_write_op * p_cmd,bool b_can_dmae)367fe56b9e6SYuval Mintz static int qed_init_cmd_wr(struct qed_hwfn *p_hwfn,
368fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
3691a635e48SYuval Mintz struct init_write_op *p_cmd, bool b_can_dmae)
370fe56b9e6SYuval Mintz {
3711a635e48SYuval Mintz u32 data = le32_to_cpu(p_cmd->data);
372fe56b9e6SYuval Mintz bool b_must_dmae = GET_FIELD(data, INIT_WRITE_OP_WIDE_BUS);
3731a635e48SYuval Mintz u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2;
3741a635e48SYuval Mintz union init_write_args *arg = &p_cmd->args;
375fe56b9e6SYuval Mintz int rc = 0;
376fe56b9e6SYuval Mintz
377fe56b9e6SYuval Mintz /* Sanitize */
378fe56b9e6SYuval Mintz if (b_must_dmae && !b_can_dmae) {
379fe56b9e6SYuval Mintz DP_NOTICE(p_hwfn,
380fe56b9e6SYuval Mintz "Need to write to %08x for Wide-bus but DMAE isn't allowed\n",
381fe56b9e6SYuval Mintz addr);
382fe56b9e6SYuval Mintz return -EINVAL;
383fe56b9e6SYuval Mintz }
384fe56b9e6SYuval Mintz
385fe56b9e6SYuval Mintz switch (GET_FIELD(data, INIT_WRITE_OP_SOURCE)) {
386fe56b9e6SYuval Mintz case INIT_SRC_INLINE:
38783aeb933SYuval Mintz data = le32_to_cpu(p_cmd->args.inline_val);
38883aeb933SYuval Mintz qed_wr(p_hwfn, p_ptt, addr, data);
389fe56b9e6SYuval Mintz break;
390fe56b9e6SYuval Mintz case INIT_SRC_ZEROS:
39183aeb933SYuval Mintz data = le32_to_cpu(p_cmd->args.zeros_count);
39283aeb933SYuval Mintz if (b_must_dmae || (b_can_dmae && (data >= 64)))
393*b90cb538SOmkar Kulkarni rc = qed_init_fill_dmae(p_hwfn, p_ptt, addr, data);
394fe56b9e6SYuval Mintz else
39583aeb933SYuval Mintz qed_init_fill(p_hwfn, p_ptt, addr, 0, data);
396fe56b9e6SYuval Mintz break;
397fe56b9e6SYuval Mintz case INIT_SRC_ARRAY:
3981a635e48SYuval Mintz rc = qed_init_cmd_array(p_hwfn, p_ptt, p_cmd,
399fe56b9e6SYuval Mintz b_must_dmae, b_can_dmae);
400fe56b9e6SYuval Mintz break;
401fe56b9e6SYuval Mintz case INIT_SRC_RUNTIME:
402fe56b9e6SYuval Mintz qed_init_rt(p_hwfn, p_ptt, addr,
403fe56b9e6SYuval Mintz le16_to_cpu(arg->runtime.offset),
404fc48b7a6SYuval Mintz le16_to_cpu(arg->runtime.size),
405fc48b7a6SYuval Mintz b_must_dmae);
406fe56b9e6SYuval Mintz break;
407fe56b9e6SYuval Mintz }
408fe56b9e6SYuval Mintz
409fe56b9e6SYuval Mintz return rc;
410fe56b9e6SYuval Mintz }
411fe56b9e6SYuval Mintz
comp_eq(u32 val,u32 expected_val)412fe56b9e6SYuval Mintz static inline bool comp_eq(u32 val, u32 expected_val)
413fe56b9e6SYuval Mintz {
414fe56b9e6SYuval Mintz return val == expected_val;
415fe56b9e6SYuval Mintz }
416fe56b9e6SYuval Mintz
comp_and(u32 val,u32 expected_val)417fe56b9e6SYuval Mintz static inline bool comp_and(u32 val, u32 expected_val)
418fe56b9e6SYuval Mintz {
419fe56b9e6SYuval Mintz return (val & expected_val) == expected_val;
420fe56b9e6SYuval Mintz }
421fe56b9e6SYuval Mintz
comp_or(u32 val,u32 expected_val)422fe56b9e6SYuval Mintz static inline bool comp_or(u32 val, u32 expected_val)
423fe56b9e6SYuval Mintz {
424fe56b9e6SYuval Mintz return (val | expected_val) > 0;
425fe56b9e6SYuval Mintz }
426fe56b9e6SYuval Mintz
427fe56b9e6SYuval Mintz /* init_ops read/poll commands */
qed_init_cmd_rd(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,struct init_read_op * cmd)428fe56b9e6SYuval Mintz static void qed_init_cmd_rd(struct qed_hwfn *p_hwfn,
4291a635e48SYuval Mintz struct qed_ptt *p_ptt, struct init_read_op *cmd)
430fe56b9e6SYuval Mintz {
431fc48b7a6SYuval Mintz bool (*comp_check)(u32 val, u32 expected_val);
432fe56b9e6SYuval Mintz u32 delay = QED_INIT_POLL_PERIOD_US, val;
433fc48b7a6SYuval Mintz u32 data, addr, poll;
434fc48b7a6SYuval Mintz int i;
435fc48b7a6SYuval Mintz
436fc48b7a6SYuval Mintz data = le32_to_cpu(cmd->op_data);
437fc48b7a6SYuval Mintz addr = GET_FIELD(data, INIT_READ_OP_ADDRESS) << 2;
438fc48b7a6SYuval Mintz poll = GET_FIELD(data, INIT_READ_OP_POLL_TYPE);
439fc48b7a6SYuval Mintz
440fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, addr);
441fe56b9e6SYuval Mintz
442fc48b7a6SYuval Mintz if (poll == INIT_POLL_NONE)
443fc48b7a6SYuval Mintz return;
444fe56b9e6SYuval Mintz
445fc48b7a6SYuval Mintz switch (poll) {
446fc48b7a6SYuval Mintz case INIT_POLL_EQ:
447fe56b9e6SYuval Mintz comp_check = comp_eq;
448fe56b9e6SYuval Mintz break;
449fc48b7a6SYuval Mintz case INIT_POLL_OR:
450fe56b9e6SYuval Mintz comp_check = comp_or;
451fe56b9e6SYuval Mintz break;
452fc48b7a6SYuval Mintz case INIT_POLL_AND:
453fe56b9e6SYuval Mintz comp_check = comp_and;
454fe56b9e6SYuval Mintz break;
455fe56b9e6SYuval Mintz default:
456fe56b9e6SYuval Mintz DP_ERR(p_hwfn, "Invalid poll comparison type %08x\n",
457fc48b7a6SYuval Mintz cmd->op_data);
458fe56b9e6SYuval Mintz return;
459fe56b9e6SYuval Mintz }
460fe56b9e6SYuval Mintz
461fc48b7a6SYuval Mintz data = le32_to_cpu(cmd->expected_val);
462fe56b9e6SYuval Mintz for (i = 0;
463fc48b7a6SYuval Mintz i < QED_INIT_MAX_POLL_COUNT && !comp_check(val, data);
464fe56b9e6SYuval Mintz i++) {
465fe56b9e6SYuval Mintz udelay(delay);
466fe56b9e6SYuval Mintz val = qed_rd(p_hwfn, p_ptt, addr);
467fe56b9e6SYuval Mintz }
468fe56b9e6SYuval Mintz
469fc48b7a6SYuval Mintz if (i == QED_INIT_MAX_POLL_COUNT) {
470fe56b9e6SYuval Mintz DP_ERR(p_hwfn,
471e75d039aSColin Ian King "Timeout when polling reg: 0x%08x [ Waiting-for: %08x Got: %08x (comparison %08x)]\n",
472fe56b9e6SYuval Mintz addr, le32_to_cpu(cmd->expected_val),
473fc48b7a6SYuval Mintz val, le32_to_cpu(cmd->op_data));
474fe56b9e6SYuval Mintz }
475fe56b9e6SYuval Mintz }
476fe56b9e6SYuval Mintz
477fe56b9e6SYuval Mintz /* init_ops callbacks entry point */
qed_init_cmd_cb(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,struct init_callback_op * p_cmd)478da090917STomer Tayar static int qed_init_cmd_cb(struct qed_hwfn *p_hwfn,
479fe56b9e6SYuval Mintz struct qed_ptt *p_ptt,
480fe56b9e6SYuval Mintz struct init_callback_op *p_cmd)
481fe56b9e6SYuval Mintz {
482da090917STomer Tayar int rc;
483da090917STomer Tayar
484da090917STomer Tayar switch (p_cmd->callback_id) {
485da090917STomer Tayar case DMAE_READY_CB:
486da090917STomer Tayar rc = qed_dmae_sanity(p_hwfn, p_ptt, "engine_phase");
487da090917STomer Tayar break;
488da090917STomer Tayar default:
489da090917STomer Tayar DP_NOTICE(p_hwfn, "Unexpected init op callback ID %d\n",
490da090917STomer Tayar p_cmd->callback_id);
491da090917STomer Tayar return -EINVAL;
492da090917STomer Tayar }
493da090917STomer Tayar
494da090917STomer Tayar return rc;
495fe56b9e6SYuval Mintz }
496fe56b9e6SYuval Mintz
qed_init_cmd_mode_match(struct qed_hwfn * p_hwfn,u16 * p_offset,int modes)497fe56b9e6SYuval Mintz static u8 qed_init_cmd_mode_match(struct qed_hwfn *p_hwfn,
4981a635e48SYuval Mintz u16 *p_offset, int modes)
499fe56b9e6SYuval Mintz {
500fe56b9e6SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev;
501fe56b9e6SYuval Mintz const u8 *modes_tree_buf;
502fe56b9e6SYuval Mintz u8 arg1, arg2, tree_val;
503fe56b9e6SYuval Mintz
504fe56b9e6SYuval Mintz modes_tree_buf = cdev->fw_data->modes_tree_buf;
5051a635e48SYuval Mintz tree_val = modes_tree_buf[(*p_offset)++];
506fe56b9e6SYuval Mintz switch (tree_val) {
507fe56b9e6SYuval Mintz case INIT_MODE_OP_NOT:
5081a635e48SYuval Mintz return qed_init_cmd_mode_match(p_hwfn, p_offset, modes) ^ 1;
509fe56b9e6SYuval Mintz case INIT_MODE_OP_OR:
5101a635e48SYuval Mintz arg1 = qed_init_cmd_mode_match(p_hwfn, p_offset, modes);
5111a635e48SYuval Mintz arg2 = qed_init_cmd_mode_match(p_hwfn, p_offset, modes);
512fe56b9e6SYuval Mintz return arg1 | arg2;
513fe56b9e6SYuval Mintz case INIT_MODE_OP_AND:
5141a635e48SYuval Mintz arg1 = qed_init_cmd_mode_match(p_hwfn, p_offset, modes);
5151a635e48SYuval Mintz arg2 = qed_init_cmd_mode_match(p_hwfn, p_offset, modes);
516fe56b9e6SYuval Mintz return arg1 & arg2;
517fe56b9e6SYuval Mintz default:
518fe56b9e6SYuval Mintz tree_val -= MAX_INIT_MODE_OPS;
5191a635e48SYuval Mintz return (modes & BIT(tree_val)) ? 1 : 0;
520fe56b9e6SYuval Mintz }
521fe56b9e6SYuval Mintz }
522fe56b9e6SYuval Mintz
qed_init_cmd_mode(struct qed_hwfn * p_hwfn,struct init_if_mode_op * p_cmd,int modes)523fe56b9e6SYuval Mintz static u32 qed_init_cmd_mode(struct qed_hwfn *p_hwfn,
5241a635e48SYuval Mintz struct init_if_mode_op *p_cmd, int modes)
525fe56b9e6SYuval Mintz {
526fe56b9e6SYuval Mintz u16 offset = le16_to_cpu(p_cmd->modes_buf_offset);
527fe56b9e6SYuval Mintz
528fe56b9e6SYuval Mintz if (qed_init_cmd_mode_match(p_hwfn, &offset, modes))
529fe56b9e6SYuval Mintz return 0;
530fe56b9e6SYuval Mintz else
531fe56b9e6SYuval Mintz return GET_FIELD(le32_to_cpu(p_cmd->op_data),
532fe56b9e6SYuval Mintz INIT_IF_MODE_OP_CMD_OFFSET);
533fe56b9e6SYuval Mintz }
534fe56b9e6SYuval Mintz
qed_init_cmd_phase(struct init_if_phase_op * p_cmd,u32 phase,u32 phase_id)535*b90cb538SOmkar Kulkarni static u32 qed_init_cmd_phase(struct init_if_phase_op *p_cmd,
5361a635e48SYuval Mintz u32 phase, u32 phase_id)
537fe56b9e6SYuval Mintz {
538fe56b9e6SYuval Mintz u32 data = le32_to_cpu(p_cmd->phase_data);
539fe56b9e6SYuval Mintz u32 op_data = le32_to_cpu(p_cmd->op_data);
540fe56b9e6SYuval Mintz
541fe56b9e6SYuval Mintz if (!(GET_FIELD(data, INIT_IF_PHASE_OP_PHASE) == phase &&
542fe56b9e6SYuval Mintz (GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == ANY_PHASE_ID ||
543fe56b9e6SYuval Mintz GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == phase_id)))
544fe56b9e6SYuval Mintz return GET_FIELD(op_data, INIT_IF_PHASE_OP_CMD_OFFSET);
545fe56b9e6SYuval Mintz else
546fe56b9e6SYuval Mintz return 0;
547fe56b9e6SYuval Mintz }
548fe56b9e6SYuval Mintz
qed_init_run(struct qed_hwfn * p_hwfn,struct qed_ptt * p_ptt,int phase,int phase_id,int modes)549fe56b9e6SYuval Mintz int qed_init_run(struct qed_hwfn *p_hwfn,
5501a635e48SYuval Mintz struct qed_ptt *p_ptt, int phase, int phase_id, int modes)
551fe56b9e6SYuval Mintz {
5520500a70dSMichal Kalderon bool b_dmae = (phase != PHASE_ENGINE);
553fe56b9e6SYuval Mintz struct qed_dev *cdev = p_hwfn->cdev;
554fe56b9e6SYuval Mintz u32 cmd_num, num_init_ops;
555fe56b9e6SYuval Mintz union init_op *init_ops;
556fe56b9e6SYuval Mintz int rc = 0;
557fe56b9e6SYuval Mintz
558fe56b9e6SYuval Mintz num_init_ops = cdev->fw_data->init_ops_size;
559fe56b9e6SYuval Mintz init_ops = cdev->fw_data->init_ops;
560fe56b9e6SYuval Mintz
561fe56b9e6SYuval Mintz p_hwfn->unzip_buf = kzalloc(MAX_ZIPPED_SIZE * 4, GFP_ATOMIC);
5622591c280SJoe Perches if (!p_hwfn->unzip_buf)
563fe56b9e6SYuval Mintz return -ENOMEM;
564fe56b9e6SYuval Mintz
565fe56b9e6SYuval Mintz for (cmd_num = 0; cmd_num < num_init_ops; cmd_num++) {
566fe56b9e6SYuval Mintz union init_op *cmd = &init_ops[cmd_num];
567fe56b9e6SYuval Mintz u32 data = le32_to_cpu(cmd->raw.op_data);
568fe56b9e6SYuval Mintz
569fe56b9e6SYuval Mintz switch (GET_FIELD(data, INIT_CALLBACK_OP_OP)) {
570fe56b9e6SYuval Mintz case INIT_OP_WRITE:
571fe56b9e6SYuval Mintz rc = qed_init_cmd_wr(p_hwfn, p_ptt, &cmd->write,
572fe56b9e6SYuval Mintz b_dmae);
573fe56b9e6SYuval Mintz break;
574fe56b9e6SYuval Mintz case INIT_OP_READ:
575fe56b9e6SYuval Mintz qed_init_cmd_rd(p_hwfn, p_ptt, &cmd->read);
576fe56b9e6SYuval Mintz break;
577fe56b9e6SYuval Mintz case INIT_OP_IF_MODE:
578fe56b9e6SYuval Mintz cmd_num += qed_init_cmd_mode(p_hwfn, &cmd->if_mode,
579fe56b9e6SYuval Mintz modes);
580fe56b9e6SYuval Mintz break;
581fe56b9e6SYuval Mintz case INIT_OP_IF_PHASE:
582*b90cb538SOmkar Kulkarni cmd_num += qed_init_cmd_phase(&cmd->if_phase,
583fe56b9e6SYuval Mintz phase, phase_id);
584fe56b9e6SYuval Mintz break;
585fe56b9e6SYuval Mintz case INIT_OP_DELAY:
586fe56b9e6SYuval Mintz /* qed_init_run is always invoked from
587fe56b9e6SYuval Mintz * sleep-able context
588fe56b9e6SYuval Mintz */
589fe56b9e6SYuval Mintz udelay(le32_to_cpu(cmd->delay.delay));
590fe56b9e6SYuval Mintz break;
591fe56b9e6SYuval Mintz
592fe56b9e6SYuval Mintz case INIT_OP_CALLBACK:
593da090917STomer Tayar rc = qed_init_cmd_cb(p_hwfn, p_ptt, &cmd->callback);
5940500a70dSMichal Kalderon if (phase == PHASE_ENGINE &&
5950500a70dSMichal Kalderon cmd->callback.callback_id == DMAE_READY_CB)
5960500a70dSMichal Kalderon b_dmae = true;
597fe56b9e6SYuval Mintz break;
598fe56b9e6SYuval Mintz }
599fe56b9e6SYuval Mintz
600fe56b9e6SYuval Mintz if (rc)
601fe56b9e6SYuval Mintz break;
602fe56b9e6SYuval Mintz }
603fe56b9e6SYuval Mintz
604fe56b9e6SYuval Mintz kfree(p_hwfn->unzip_buf);
6053587cb87STomer Tayar p_hwfn->unzip_buf = NULL;
606fe56b9e6SYuval Mintz return rc;
607fe56b9e6SYuval Mintz }
608fe56b9e6SYuval Mintz
qed_gtt_init(struct qed_hwfn * p_hwfn)609fe56b9e6SYuval Mintz void qed_gtt_init(struct qed_hwfn *p_hwfn)
610fe56b9e6SYuval Mintz {
611fe56b9e6SYuval Mintz u32 gtt_base;
612fe56b9e6SYuval Mintz u32 i;
613fe56b9e6SYuval Mintz
614fe56b9e6SYuval Mintz /* Set the global windows */
615fe56b9e6SYuval Mintz gtt_base = PXP_PF_WINDOW_ADMIN_START + PXP_PF_WINDOW_ADMIN_GLOBAL_START;
616fe56b9e6SYuval Mintz
617fe56b9e6SYuval Mintz for (i = 0; i < ARRAY_SIZE(pxp_global_win); i++)
618fe56b9e6SYuval Mintz if (pxp_global_win[i])
619fe56b9e6SYuval Mintz REG_WR(p_hwfn, gtt_base + i * PXP_GLOBAL_ENTRY_SIZE,
620fe56b9e6SYuval Mintz pxp_global_win[i]);
621fe56b9e6SYuval Mintz }
622fe56b9e6SYuval Mintz
qed_init_fw_data(struct qed_dev * cdev,const u8 * data)623351a4dedSYuval Mintz int qed_init_fw_data(struct qed_dev *cdev, const u8 *data)
624fe56b9e6SYuval Mintz {
625fe56b9e6SYuval Mintz struct qed_fw_data *fw = cdev->fw_data;
626fe56b9e6SYuval Mintz struct bin_buffer_hdr *buf_hdr;
627fe56b9e6SYuval Mintz u32 offset, len;
628fe56b9e6SYuval Mintz
629fe56b9e6SYuval Mintz if (!data) {
630fe56b9e6SYuval Mintz DP_NOTICE(cdev, "Invalid fw data\n");
631fe56b9e6SYuval Mintz return -EINVAL;
632fe56b9e6SYuval Mintz }
633fe56b9e6SYuval Mintz
634351a4dedSYuval Mintz /* First Dword contains metadata and should be skipped */
635be086e7cSMintz, Yuval buf_hdr = (struct bin_buffer_hdr *)data;
636351a4dedSYuval Mintz
63705fafbfbSYuval Mintz offset = buf_hdr[BIN_BUF_INIT_FW_VER_INFO].offset;
638351a4dedSYuval Mintz fw->fw_ver_info = (struct fw_ver_info *)(data + offset);
639fe56b9e6SYuval Mintz
640fe56b9e6SYuval Mintz offset = buf_hdr[BIN_BUF_INIT_CMD].offset;
641fe56b9e6SYuval Mintz fw->init_ops = (union init_op *)(data + offset);
642fe56b9e6SYuval Mintz
643fe56b9e6SYuval Mintz offset = buf_hdr[BIN_BUF_INIT_VAL].offset;
644fe56b9e6SYuval Mintz fw->arr_data = (u32 *)(data + offset);
645fe56b9e6SYuval Mintz
646fe56b9e6SYuval Mintz offset = buf_hdr[BIN_BUF_INIT_MODE_TREE].offset;
647fe56b9e6SYuval Mintz fw->modes_tree_buf = (u8 *)(data + offset);
648fe56b9e6SYuval Mintz len = buf_hdr[BIN_BUF_INIT_CMD].length;
649fe56b9e6SYuval Mintz fw->init_ops_size = len / sizeof(struct init_raw_op);
650fe56b9e6SYuval Mintz
65130d5f858SMichal Kalderon offset = buf_hdr[BIN_BUF_INIT_OVERLAYS].offset;
65230d5f858SMichal Kalderon fw->fw_overlays = (u32 *)(data + offset);
65330d5f858SMichal Kalderon len = buf_hdr[BIN_BUF_INIT_OVERLAYS].length;
65430d5f858SMichal Kalderon fw->fw_overlays_len = len;
65530d5f858SMichal Kalderon
656fe56b9e6SYuval Mintz return 0;
657fe56b9e6SYuval Mintz }
658