xref: /freebsd/sys/dev/cxgbe/cudbg/cudbg_flash_utils.c (revision f856f099cb17ccf9c1213bd269f0ee0ecd36cd4b)
1*f856f099SNavdeep Parhar /*-
2*f856f099SNavdeep Parhar  * Copyright (c) 2017 Chelsio Communications, Inc.
3*f856f099SNavdeep Parhar  * All rights reserved.
4*f856f099SNavdeep Parhar  *
5*f856f099SNavdeep Parhar  * Redistribution and use in source and binary forms, with or without
6*f856f099SNavdeep Parhar  * modification, are permitted provided that the following conditions
7*f856f099SNavdeep Parhar  * are met:
8*f856f099SNavdeep Parhar  * 1. Redistributions of source code must retain the above copyright
9*f856f099SNavdeep Parhar  *    notice, this list of conditions and the following disclaimer.
10*f856f099SNavdeep Parhar  * 2. Redistributions in binary form must reproduce the above copyright
11*f856f099SNavdeep Parhar  *    notice, this list of conditions and the following disclaimer in the
12*f856f099SNavdeep Parhar  *    documentation and/or other materials provided with the distribution.
13*f856f099SNavdeep Parhar  *
14*f856f099SNavdeep Parhar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*f856f099SNavdeep Parhar  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*f856f099SNavdeep Parhar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*f856f099SNavdeep Parhar  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*f856f099SNavdeep Parhar  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*f856f099SNavdeep Parhar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*f856f099SNavdeep Parhar  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*f856f099SNavdeep Parhar  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*f856f099SNavdeep Parhar  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*f856f099SNavdeep Parhar  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*f856f099SNavdeep Parhar  * SUCH DAMAGE.
25*f856f099SNavdeep Parhar  */
26*f856f099SNavdeep Parhar 
27*f856f099SNavdeep Parhar #include <sys/cdefs.h>
28*f856f099SNavdeep Parhar __FBSDID("$FreeBSD$");
29*f856f099SNavdeep Parhar 
30*f856f099SNavdeep Parhar #include <sys/types.h>
31*f856f099SNavdeep Parhar #include <sys/param.h>
32*f856f099SNavdeep Parhar 
33*f856f099SNavdeep Parhar #include "common/common.h"
34*f856f099SNavdeep Parhar #include "common/t4_regs.h"
35*f856f099SNavdeep Parhar #include "cudbg.h"
36*f856f099SNavdeep Parhar #include "cudbg_lib_common.h"
37*f856f099SNavdeep Parhar 
38*f856f099SNavdeep Parhar enum {
39*f856f099SNavdeep Parhar 	SF_ATTEMPTS = 10,		/* max retries for SF operations */
40*f856f099SNavdeep Parhar 
41*f856f099SNavdeep Parhar 	/* flash command opcodes */
42*f856f099SNavdeep Parhar 	SF_PROG_PAGE	= 2,	/* program page */
43*f856f099SNavdeep Parhar 	SF_WR_DISABLE	= 4,	/* disable writes */
44*f856f099SNavdeep Parhar 	SF_RD_STATUS	= 5,	/* read status register */
45*f856f099SNavdeep Parhar 	SF_WR_ENABLE	= 6,	/* enable writes */
46*f856f099SNavdeep Parhar 	SF_RD_DATA_FAST = 0xb,	/* read flash */
47*f856f099SNavdeep Parhar 	SF_RD_ID	= 0x9f, /* read ID */
48*f856f099SNavdeep Parhar 	SF_ERASE_SECTOR = 0xd8, /* erase sector */
49*f856f099SNavdeep Parhar };
50*f856f099SNavdeep Parhar 
51*f856f099SNavdeep Parhar int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size);
52*f856f099SNavdeep Parhar int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size,
53*f856f099SNavdeep Parhar 		u32 start_address);
54*f856f099SNavdeep Parhar 
55*f856f099SNavdeep Parhar void
56*f856f099SNavdeep Parhar update_skip_size(struct cudbg_flash_sec_info *sec_info, u32 size)
57*f856f099SNavdeep Parhar {
58*f856f099SNavdeep Parhar 	sec_info->skip_size += size;
59*f856f099SNavdeep Parhar }
60*f856f099SNavdeep Parhar 
61*f856f099SNavdeep Parhar static
62*f856f099SNavdeep Parhar void set_sector_availability(struct cudbg_flash_sec_info *sec_info,
63*f856f099SNavdeep Parhar     int sector_nu, int avail)
64*f856f099SNavdeep Parhar {
65*f856f099SNavdeep Parhar 	sector_nu -= CUDBG_START_SEC;
66*f856f099SNavdeep Parhar 	if (avail)
67*f856f099SNavdeep Parhar 		set_dbg_bitmap(sec_info->sec_bitmap, sector_nu);
68*f856f099SNavdeep Parhar 	else
69*f856f099SNavdeep Parhar 		reset_dbg_bitmap(sec_info->sec_bitmap, sector_nu);
70*f856f099SNavdeep Parhar }
71*f856f099SNavdeep Parhar 
72*f856f099SNavdeep Parhar /* This function will return empty sector available for filling */
73*f856f099SNavdeep Parhar static int
74*f856f099SNavdeep Parhar find_empty_sec(struct cudbg_flash_sec_info *sec_info)
75*f856f099SNavdeep Parhar {
76*f856f099SNavdeep Parhar 	int i, index, bit;
77*f856f099SNavdeep Parhar 
78*f856f099SNavdeep Parhar 	for (i = CUDBG_START_SEC; i < CUDBG_SF_MAX_SECTOR; i++) {
79*f856f099SNavdeep Parhar 		index = (i - CUDBG_START_SEC) / 8;
80*f856f099SNavdeep Parhar 		bit = (i - CUDBG_START_SEC) % 8;
81*f856f099SNavdeep Parhar 		if (!(sec_info->sec_bitmap[index] & (1 << bit)))
82*f856f099SNavdeep Parhar 			return i;
83*f856f099SNavdeep Parhar 	}
84*f856f099SNavdeep Parhar 
85*f856f099SNavdeep Parhar 	return CUDBG_STATUS_FLASH_FULL;
86*f856f099SNavdeep Parhar }
87*f856f099SNavdeep Parhar 
88*f856f099SNavdeep Parhar /* This function will get header initially. If header is already there
89*f856f099SNavdeep Parhar  * then it will update that header */
90*f856f099SNavdeep Parhar static void update_headers(void *handle, struct cudbg_buffer *dbg_buff,
91*f856f099SNavdeep Parhar 		    u64 timestamp, u32 cur_entity_hdr_offset,
92*f856f099SNavdeep Parhar 		    u32 start_offset, u32 ext_size)
93*f856f099SNavdeep Parhar {
94*f856f099SNavdeep Parhar 	struct cudbg_private *priv = handle;
95*f856f099SNavdeep Parhar 	struct cudbg_flash_sec_info *sec_info = &priv->sec_info;
96*f856f099SNavdeep Parhar 	void *sec_hdr;
97*f856f099SNavdeep Parhar 	struct cudbg_hdr *cudbg_hdr;
98*f856f099SNavdeep Parhar 	struct cudbg_flash_hdr *flash_hdr;
99*f856f099SNavdeep Parhar 	struct cudbg_entity_hdr *entity_hdr;
100*f856f099SNavdeep Parhar 	u32 hdr_offset;
101*f856f099SNavdeep Parhar 	u32 data_hdr_size;
102*f856f099SNavdeep Parhar 	u32 total_hdr_size;
103*f856f099SNavdeep Parhar 	u32 sec_hdr_start_addr;
104*f856f099SNavdeep Parhar 
105*f856f099SNavdeep Parhar 	data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
106*f856f099SNavdeep Parhar 				sizeof(struct cudbg_hdr);
107*f856f099SNavdeep Parhar 	total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr);
108*f856f099SNavdeep Parhar 	sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size;
109*f856f099SNavdeep Parhar 	sec_hdr  = sec_info->sec_data + sec_hdr_start_addr;
110*f856f099SNavdeep Parhar 
111*f856f099SNavdeep Parhar 	flash_hdr = (struct cudbg_flash_hdr *)(sec_hdr);
112*f856f099SNavdeep Parhar 	cudbg_hdr = (struct cudbg_hdr *)dbg_buff->data;
113*f856f099SNavdeep Parhar 
114*f856f099SNavdeep Parhar 	/* initially initialize flash hdr and copy all data headers and
115*f856f099SNavdeep Parhar 	 * in next calling (else part) copy only current entity header
116*f856f099SNavdeep Parhar 	 */
117*f856f099SNavdeep Parhar 	if ((start_offset - sec_info->skip_size) == data_hdr_size) {
118*f856f099SNavdeep Parhar 		flash_hdr->signature = CUDBG_FL_SIGNATURE;
119*f856f099SNavdeep Parhar 		flash_hdr->major_ver = CUDBG_FL_MAJOR_VERSION;
120*f856f099SNavdeep Parhar 		flash_hdr->minor_ver = CUDBG_FL_MINOR_VERSION;
121*f856f099SNavdeep Parhar 		flash_hdr->build_ver = CUDBG_FL_BUILD_VERSION;
122*f856f099SNavdeep Parhar 		flash_hdr->hdr_len = sizeof(struct cudbg_flash_hdr);
123*f856f099SNavdeep Parhar 		hdr_offset =  sizeof(struct cudbg_flash_hdr);
124*f856f099SNavdeep Parhar 
125*f856f099SNavdeep Parhar 		memcpy((void *)((char *)sec_hdr + hdr_offset),
126*f856f099SNavdeep Parhar 		       (void *)((char *)dbg_buff->data), data_hdr_size);
127*f856f099SNavdeep Parhar 	} else
128*f856f099SNavdeep Parhar 		memcpy((void *)((char *)sec_hdr +
129*f856f099SNavdeep Parhar 			sizeof(struct cudbg_flash_hdr) +
130*f856f099SNavdeep Parhar 			cur_entity_hdr_offset),
131*f856f099SNavdeep Parhar 			(void *)((char *)dbg_buff->data +
132*f856f099SNavdeep Parhar 			cur_entity_hdr_offset),
133*f856f099SNavdeep Parhar 			sizeof(struct cudbg_entity_hdr));
134*f856f099SNavdeep Parhar 
135*f856f099SNavdeep Parhar 	hdr_offset = data_hdr_size + sizeof(struct cudbg_flash_hdr);
136*f856f099SNavdeep Parhar 	flash_hdr->data_len = cudbg_hdr->data_len - sec_info->skip_size;
137*f856f099SNavdeep Parhar 	flash_hdr->timestamp = timestamp;
138*f856f099SNavdeep Parhar 
139*f856f099SNavdeep Parhar 	entity_hdr = (struct cudbg_entity_hdr *)((char *)sec_hdr +
140*f856f099SNavdeep Parhar 		      sizeof(struct cudbg_flash_hdr) +
141*f856f099SNavdeep Parhar 		      cur_entity_hdr_offset);
142*f856f099SNavdeep Parhar 	/* big entity like mc need to be skipped */
143*f856f099SNavdeep Parhar 	entity_hdr->start_offset -= sec_info->skip_size;
144*f856f099SNavdeep Parhar 
145*f856f099SNavdeep Parhar 	cudbg_hdr = (struct cudbg_hdr *)((char *)sec_hdr +
146*f856f099SNavdeep Parhar 			sizeof(struct cudbg_flash_hdr));
147*f856f099SNavdeep Parhar 	cudbg_hdr->data_len = flash_hdr->data_len;
148*f856f099SNavdeep Parhar 	flash_hdr->data_len += ext_size;
149*f856f099SNavdeep Parhar }
150*f856f099SNavdeep Parhar 
151*f856f099SNavdeep Parhar /* Write CUDBG data into serial flash */
152*f856f099SNavdeep Parhar int cudbg_write_flash(void *handle, u64 timestamp, void *data,
153*f856f099SNavdeep Parhar 		      u32 start_offset, u32 cur_entity_hdr_offset,
154*f856f099SNavdeep Parhar 		      u32 cur_entity_size,
155*f856f099SNavdeep Parhar 		      u32 ext_size)
156*f856f099SNavdeep Parhar {
157*f856f099SNavdeep Parhar 	struct cudbg_private *priv = handle;
158*f856f099SNavdeep Parhar 	struct cudbg_init *cudbg_init = &priv->dbg_init;
159*f856f099SNavdeep Parhar 	struct cudbg_flash_sec_info *sec_info = &priv->sec_info;
160*f856f099SNavdeep Parhar 	struct adapter *adap = cudbg_init->adap;
161*f856f099SNavdeep Parhar 	struct cudbg_flash_hdr *flash_hdr = NULL;
162*f856f099SNavdeep Parhar 	struct cudbg_buffer *dbg_buff = (struct cudbg_buffer *)data;
163*f856f099SNavdeep Parhar 	u32 data_hdr_size;
164*f856f099SNavdeep Parhar 	u32 total_hdr_size;
165*f856f099SNavdeep Parhar 	u32 tmp_size;
166*f856f099SNavdeep Parhar 	u32 sec_data_offset;
167*f856f099SNavdeep Parhar 	u32 sec_hdr_start_addr;
168*f856f099SNavdeep Parhar 	u32 sec_data_size;
169*f856f099SNavdeep Parhar 	u32 space_left;
170*f856f099SNavdeep Parhar 	int rc = 0;
171*f856f099SNavdeep Parhar 	int sec;
172*f856f099SNavdeep Parhar 
173*f856f099SNavdeep Parhar 	data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
174*f856f099SNavdeep Parhar 			sizeof(struct cudbg_hdr);
175*f856f099SNavdeep Parhar 	total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr);
176*f856f099SNavdeep Parhar 	sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size;
177*f856f099SNavdeep Parhar 	sec_data_size = sec_hdr_start_addr;
178*f856f099SNavdeep Parhar 
179*f856f099SNavdeep Parhar 	cudbg_init->print("\tWriting %u bytes to flash\n", cur_entity_size);
180*f856f099SNavdeep Parhar 
181*f856f099SNavdeep Parhar 	/* this function will get header if sec_info->sec_data does not
182*f856f099SNavdeep Parhar 	 * have any header and
183*f856f099SNavdeep Parhar 	 * will update the header if it has header
184*f856f099SNavdeep Parhar 	 */
185*f856f099SNavdeep Parhar 	update_headers(handle, dbg_buff, timestamp,
186*f856f099SNavdeep Parhar 		       cur_entity_hdr_offset,
187*f856f099SNavdeep Parhar 		       start_offset, ext_size);
188*f856f099SNavdeep Parhar 
189*f856f099SNavdeep Parhar 	if (ext_size) {
190*f856f099SNavdeep Parhar 		cur_entity_size += sizeof(struct cudbg_entity_hdr);
191*f856f099SNavdeep Parhar 		start_offset = dbg_buff->offset - cur_entity_size;
192*f856f099SNavdeep Parhar 	}
193*f856f099SNavdeep Parhar 
194*f856f099SNavdeep Parhar 	flash_hdr = (struct cudbg_flash_hdr *)(sec_info->sec_data +
195*f856f099SNavdeep Parhar 			sec_hdr_start_addr);
196*f856f099SNavdeep Parhar 
197*f856f099SNavdeep Parhar 	if (flash_hdr->data_len > CUDBG_FLASH_SIZE) {
198*f856f099SNavdeep Parhar 		rc = CUDBG_STATUS_FLASH_FULL;
199*f856f099SNavdeep Parhar 		goto out;
200*f856f099SNavdeep Parhar 	}
201*f856f099SNavdeep Parhar 
202*f856f099SNavdeep Parhar 	space_left = CUDBG_FLASH_SIZE - flash_hdr->data_len;
203*f856f099SNavdeep Parhar 
204*f856f099SNavdeep Parhar 	if (cur_entity_size > space_left) {
205*f856f099SNavdeep Parhar 		rc = CUDBG_STATUS_FLASH_FULL;
206*f856f099SNavdeep Parhar 		goto out;
207*f856f099SNavdeep Parhar 	}
208*f856f099SNavdeep Parhar 
209*f856f099SNavdeep Parhar 	while (cur_entity_size > 0) {
210*f856f099SNavdeep Parhar 		sec = find_empty_sec(sec_info);
211*f856f099SNavdeep Parhar 		if (sec_info->par_sec) {
212*f856f099SNavdeep Parhar 			sec_data_offset = sec_info->par_sec_offset;
213*f856f099SNavdeep Parhar 			set_sector_availability(sec_info, sec_info->par_sec, 0);
214*f856f099SNavdeep Parhar 			sec_info->par_sec = 0;
215*f856f099SNavdeep Parhar 			sec_info->par_sec_offset = 0;
216*f856f099SNavdeep Parhar 
217*f856f099SNavdeep Parhar 		} else {
218*f856f099SNavdeep Parhar 			sec_info->cur_seq_no++;
219*f856f099SNavdeep Parhar 			flash_hdr->sec_seq_no = sec_info->cur_seq_no;
220*f856f099SNavdeep Parhar 			sec_data_offset = 0;
221*f856f099SNavdeep Parhar 		}
222*f856f099SNavdeep Parhar 
223*f856f099SNavdeep Parhar 		if (cur_entity_size + sec_data_offset > sec_data_size) {
224*f856f099SNavdeep Parhar 			tmp_size = sec_data_size - sec_data_offset;
225*f856f099SNavdeep Parhar 		} else {
226*f856f099SNavdeep Parhar 			tmp_size = cur_entity_size;
227*f856f099SNavdeep Parhar 			sec_info->par_sec = sec;
228*f856f099SNavdeep Parhar 			sec_info->par_sec_offset = cur_entity_size +
229*f856f099SNavdeep Parhar 						  sec_data_offset;
230*f856f099SNavdeep Parhar 		}
231*f856f099SNavdeep Parhar 
232*f856f099SNavdeep Parhar 		memcpy((void *)((char *)sec_info->sec_data + sec_data_offset),
233*f856f099SNavdeep Parhar 		       (void *)((char *)dbg_buff->data + start_offset),
234*f856f099SNavdeep Parhar 		       tmp_size);
235*f856f099SNavdeep Parhar 
236*f856f099SNavdeep Parhar 		rc = write_flash(adap, sec, sec_info->sec_data,
237*f856f099SNavdeep Parhar 				CUDBG_SF_SECTOR_SIZE);
238*f856f099SNavdeep Parhar 		if (rc)
239*f856f099SNavdeep Parhar 			goto out;
240*f856f099SNavdeep Parhar 
241*f856f099SNavdeep Parhar 		cur_entity_size -= tmp_size;
242*f856f099SNavdeep Parhar 		set_sector_availability(sec_info, sec, 1);
243*f856f099SNavdeep Parhar 		start_offset += tmp_size;
244*f856f099SNavdeep Parhar 	}
245*f856f099SNavdeep Parhar out:
246*f856f099SNavdeep Parhar 	return rc;
247*f856f099SNavdeep Parhar }
248*f856f099SNavdeep Parhar 
249*f856f099SNavdeep Parhar int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size)
250*f856f099SNavdeep Parhar {
251*f856f099SNavdeep Parhar 	unsigned int addr;
252*f856f099SNavdeep Parhar 	unsigned int i, n;
253*f856f099SNavdeep Parhar 	unsigned int sf_sec_size;
254*f856f099SNavdeep Parhar 	int rc = 0;
255*f856f099SNavdeep Parhar 
256*f856f099SNavdeep Parhar 	u8 *ptr = (u8 *)data;
257*f856f099SNavdeep Parhar 
258*f856f099SNavdeep Parhar 	sf_sec_size = adap->params.sf_size/adap->params.sf_nsec;
259*f856f099SNavdeep Parhar 
260*f856f099SNavdeep Parhar 	addr =  start_sec * CUDBG_SF_SECTOR_SIZE;
261*f856f099SNavdeep Parhar 	i = DIV_ROUND_UP(size,/* # of sectors spanned */
262*f856f099SNavdeep Parhar 			sf_sec_size);
263*f856f099SNavdeep Parhar 
264*f856f099SNavdeep Parhar 	rc = t4_flash_erase_sectors(adap, start_sec,
265*f856f099SNavdeep Parhar 		   start_sec + i - 1);
266*f856f099SNavdeep Parhar 	/*
267*f856f099SNavdeep Parhar 	 * If size == 0 then we're simply erasing the FLASH sectors associated
268*f856f099SNavdeep Parhar 	 * with the on-adapter OptionROM Configuration File.
269*f856f099SNavdeep Parhar 	 */
270*f856f099SNavdeep Parhar 
271*f856f099SNavdeep Parhar 	if (rc || size == 0)
272*f856f099SNavdeep Parhar 		goto out;
273*f856f099SNavdeep Parhar 
274*f856f099SNavdeep Parhar 	/* this will write to the flash up to SF_PAGE_SIZE at a time */
275*f856f099SNavdeep Parhar 	for (i = 0; i < size; i += SF_PAGE_SIZE) {
276*f856f099SNavdeep Parhar 		if ((size - i) <  SF_PAGE_SIZE)
277*f856f099SNavdeep Parhar 			n = size - i;
278*f856f099SNavdeep Parhar 		else
279*f856f099SNavdeep Parhar 			n = SF_PAGE_SIZE;
280*f856f099SNavdeep Parhar 		rc = t4_write_flash(adap, addr, n, ptr, 0);
281*f856f099SNavdeep Parhar 		if (rc)
282*f856f099SNavdeep Parhar 			goto out;
283*f856f099SNavdeep Parhar 
284*f856f099SNavdeep Parhar 		addr += n;
285*f856f099SNavdeep Parhar 		ptr += n;
286*f856f099SNavdeep Parhar 	}
287*f856f099SNavdeep Parhar 
288*f856f099SNavdeep Parhar 	return 0;
289*f856f099SNavdeep Parhar out:
290*f856f099SNavdeep Parhar 	return rc;
291*f856f099SNavdeep Parhar }
292*f856f099SNavdeep Parhar 
293*f856f099SNavdeep Parhar int cudbg_read_flash_details(void *handle, struct cudbg_flash_hdr *data)
294*f856f099SNavdeep Parhar {
295*f856f099SNavdeep Parhar 	int rc;
296*f856f099SNavdeep Parhar 	rc = cudbg_read_flash(handle, (void *)data,
297*f856f099SNavdeep Parhar 			      sizeof(struct cudbg_flash_hdr), 0);
298*f856f099SNavdeep Parhar 
299*f856f099SNavdeep Parhar 	return rc;
300*f856f099SNavdeep Parhar }
301*f856f099SNavdeep Parhar 
302*f856f099SNavdeep Parhar int cudbg_read_flash_data(void *handle, void *buf, u32 buf_size)
303*f856f099SNavdeep Parhar {
304*f856f099SNavdeep Parhar 	int rc;
305*f856f099SNavdeep Parhar 	u32 total_hdr_size, data_header_size;
306*f856f099SNavdeep Parhar 	void *payload = NULL;
307*f856f099SNavdeep Parhar 	u32 payload_size = 0;
308*f856f099SNavdeep Parhar 
309*f856f099SNavdeep Parhar 	data_header_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
310*f856f099SNavdeep Parhar 		sizeof(struct cudbg_hdr);
311*f856f099SNavdeep Parhar 	total_hdr_size = data_header_size + sizeof(struct cudbg_flash_hdr);
312*f856f099SNavdeep Parhar 
313*f856f099SNavdeep Parhar 	/* Copy flash header to buffer */
314*f856f099SNavdeep Parhar 	rc = cudbg_read_flash(handle, buf, total_hdr_size, 0);
315*f856f099SNavdeep Parhar 	if (rc != 0)
316*f856f099SNavdeep Parhar 		goto out;
317*f856f099SNavdeep Parhar 	payload = (char *)buf + total_hdr_size;
318*f856f099SNavdeep Parhar 	payload_size  = buf_size - total_hdr_size;
319*f856f099SNavdeep Parhar 
320*f856f099SNavdeep Parhar 	/* Reading flash data to buf */
321*f856f099SNavdeep Parhar 	rc = cudbg_read_flash(handle, payload, payload_size, 1);
322*f856f099SNavdeep Parhar 	if (rc != 0)
323*f856f099SNavdeep Parhar 		goto out;
324*f856f099SNavdeep Parhar 
325*f856f099SNavdeep Parhar out:
326*f856f099SNavdeep Parhar 	return rc;
327*f856f099SNavdeep Parhar }
328*f856f099SNavdeep Parhar 
329*f856f099SNavdeep Parhar int cudbg_read_flash(void *handle, void *data, u32 size, int data_flag)
330*f856f099SNavdeep Parhar {
331*f856f099SNavdeep Parhar 	struct cudbg_private *priv = handle;
332*f856f099SNavdeep Parhar 	struct cudbg_init *cudbg_init = &priv->dbg_init;
333*f856f099SNavdeep Parhar 	struct cudbg_flash_sec_info *sec_info = &priv->sec_info;
334*f856f099SNavdeep Parhar 	struct adapter *adap = cudbg_init->adap;
335*f856f099SNavdeep Parhar 	struct cudbg_flash_hdr flash_hdr;
336*f856f099SNavdeep Parhar 	u32 total_hdr_size;
337*f856f099SNavdeep Parhar 	u32 data_hdr_size;
338*f856f099SNavdeep Parhar 	u32 sec_hdr_start_addr;
339*f856f099SNavdeep Parhar 	u32 tmp_size;
340*f856f099SNavdeep Parhar 	u32 data_offset = 0;
341*f856f099SNavdeep Parhar 	u32 i, j;
342*f856f099SNavdeep Parhar 	int rc;
343*f856f099SNavdeep Parhar 
344*f856f099SNavdeep Parhar 	rc = t4_get_flash_params(adap);
345*f856f099SNavdeep Parhar 	if (rc) {
346*f856f099SNavdeep Parhar 		cudbg_init->print("\nGet flash params failed."
347*f856f099SNavdeep Parhar 			"Try Again...readflash\n\n");
348*f856f099SNavdeep Parhar 		return rc;
349*f856f099SNavdeep Parhar 	}
350*f856f099SNavdeep Parhar 
351*f856f099SNavdeep Parhar 	data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) +
352*f856f099SNavdeep Parhar 			sizeof(struct cudbg_hdr);
353*f856f099SNavdeep Parhar 	total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr);
354*f856f099SNavdeep Parhar 	sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size;
355*f856f099SNavdeep Parhar 
356*f856f099SNavdeep Parhar 	if (!data_flag) {
357*f856f099SNavdeep Parhar 		/* fill header */
358*f856f099SNavdeep Parhar 		if (!sec_info->max_timestamp) {
359*f856f099SNavdeep Parhar 			/* finding max time stamp because it may
360*f856f099SNavdeep Parhar 			 * have older filled sector also
361*f856f099SNavdeep Parhar 			 */
362*f856f099SNavdeep Parhar 			memset(&flash_hdr, 0, sizeof(struct cudbg_flash_hdr));
363*f856f099SNavdeep Parhar 			rc = read_flash(adap, CUDBG_START_SEC, &flash_hdr,
364*f856f099SNavdeep Parhar 				sizeof(struct cudbg_flash_hdr),
365*f856f099SNavdeep Parhar 				sec_hdr_start_addr);
366*f856f099SNavdeep Parhar 
367*f856f099SNavdeep Parhar 			if (flash_hdr.signature == CUDBG_FL_SIGNATURE) {
368*f856f099SNavdeep Parhar 				sec_info->max_timestamp = flash_hdr.timestamp;
369*f856f099SNavdeep Parhar 			} else {
370*f856f099SNavdeep Parhar 				rc = read_flash(adap, CUDBG_START_SEC + 1,
371*f856f099SNavdeep Parhar 					&flash_hdr,
372*f856f099SNavdeep Parhar 					sizeof(struct cudbg_flash_hdr),
373*f856f099SNavdeep Parhar 					sec_hdr_start_addr);
374*f856f099SNavdeep Parhar 
375*f856f099SNavdeep Parhar 				if (flash_hdr.signature == CUDBG_FL_SIGNATURE)
376*f856f099SNavdeep Parhar 					sec_info->max_timestamp =
377*f856f099SNavdeep Parhar 							flash_hdr.timestamp;
378*f856f099SNavdeep Parhar 				else {
379*f856f099SNavdeep Parhar 					cudbg_init->print("\n\tNo cudbg dump "\
380*f856f099SNavdeep Parhar 							  "found in flash\n\n");
381*f856f099SNavdeep Parhar 					return CUDBG_STATUS_NO_SIGNATURE;
382*f856f099SNavdeep Parhar 				}
383*f856f099SNavdeep Parhar 
384*f856f099SNavdeep Parhar 			}
385*f856f099SNavdeep Parhar 
386*f856f099SNavdeep Parhar 			/* finding max sequence number because max sequenced
387*f856f099SNavdeep Parhar 			 * sector has updated header
388*f856f099SNavdeep Parhar 			 */
389*f856f099SNavdeep Parhar 			for (i = CUDBG_START_SEC; i <
390*f856f099SNavdeep Parhar 					CUDBG_SF_MAX_SECTOR; i++) {
391*f856f099SNavdeep Parhar 				memset(&flash_hdr, 0,
392*f856f099SNavdeep Parhar 				       sizeof(struct cudbg_flash_hdr));
393*f856f099SNavdeep Parhar 				rc = read_flash(adap, i, &flash_hdr,
394*f856f099SNavdeep Parhar 						sizeof(struct cudbg_flash_hdr),
395*f856f099SNavdeep Parhar 						sec_hdr_start_addr);
396*f856f099SNavdeep Parhar 
397*f856f099SNavdeep Parhar 				if (flash_hdr.signature == CUDBG_FL_SIGNATURE &&
398*f856f099SNavdeep Parhar 				    sec_info->max_timestamp ==
399*f856f099SNavdeep Parhar 				    flash_hdr.timestamp &&
400*f856f099SNavdeep Parhar 				    sec_info->max_seq_no <=
401*f856f099SNavdeep Parhar 				    flash_hdr.sec_seq_no) {
402*f856f099SNavdeep Parhar 					if (sec_info->max_seq_no ==
403*f856f099SNavdeep Parhar 					    flash_hdr.sec_seq_no) {
404*f856f099SNavdeep Parhar 						if (sec_info->hdr_data_len <
405*f856f099SNavdeep Parhar 						    flash_hdr.data_len)
406*f856f099SNavdeep Parhar 							sec_info->max_seq_sec = i;
407*f856f099SNavdeep Parhar 					} else {
408*f856f099SNavdeep Parhar 						sec_info->max_seq_sec = i;
409*f856f099SNavdeep Parhar 						sec_info->hdr_data_len =
410*f856f099SNavdeep Parhar 							flash_hdr.data_len;
411*f856f099SNavdeep Parhar 					}
412*f856f099SNavdeep Parhar 					sec_info->max_seq_no = flash_hdr.sec_seq_no;
413*f856f099SNavdeep Parhar 				}
414*f856f099SNavdeep Parhar 			}
415*f856f099SNavdeep Parhar 		}
416*f856f099SNavdeep Parhar 		rc = read_flash(adap, sec_info->max_seq_sec,
417*f856f099SNavdeep Parhar 				(struct cudbg_flash_hdr *)data,
418*f856f099SNavdeep Parhar 				size, sec_hdr_start_addr);
419*f856f099SNavdeep Parhar 
420*f856f099SNavdeep Parhar 		if (rc)
421*f856f099SNavdeep Parhar 			cudbg_init->print("Read flash header failed, rc %d\n",
422*f856f099SNavdeep Parhar 					rc);
423*f856f099SNavdeep Parhar 
424*f856f099SNavdeep Parhar 		return rc;
425*f856f099SNavdeep Parhar 	}
426*f856f099SNavdeep Parhar 
427*f856f099SNavdeep Parhar 	/* finding sector sequence sorted */
428*f856f099SNavdeep Parhar 	for (i = 1; i <= sec_info->max_seq_no; i++) {
429*f856f099SNavdeep Parhar 		for (j = CUDBG_START_SEC; j < CUDBG_SF_MAX_SECTOR; j++) {
430*f856f099SNavdeep Parhar 			memset(&flash_hdr, 0, sizeof(struct cudbg_flash_hdr));
431*f856f099SNavdeep Parhar 			rc = read_flash(adap, j, &flash_hdr,
432*f856f099SNavdeep Parhar 				sizeof(struct cudbg_flash_hdr),
433*f856f099SNavdeep Parhar 				sec_hdr_start_addr);
434*f856f099SNavdeep Parhar 
435*f856f099SNavdeep Parhar 			if (flash_hdr.signature ==
436*f856f099SNavdeep Parhar 					CUDBG_FL_SIGNATURE &&
437*f856f099SNavdeep Parhar 					sec_info->max_timestamp ==
438*f856f099SNavdeep Parhar 					flash_hdr.timestamp &&
439*f856f099SNavdeep Parhar 					flash_hdr.sec_seq_no == i) {
440*f856f099SNavdeep Parhar 				if (size + total_hdr_size >
441*f856f099SNavdeep Parhar 						CUDBG_SF_SECTOR_SIZE)
442*f856f099SNavdeep Parhar 					tmp_size = CUDBG_SF_SECTOR_SIZE -
443*f856f099SNavdeep Parhar 						total_hdr_size;
444*f856f099SNavdeep Parhar 				else
445*f856f099SNavdeep Parhar 					tmp_size =  size;
446*f856f099SNavdeep Parhar 
447*f856f099SNavdeep Parhar 				if ((i != sec_info->max_seq_no) ||
448*f856f099SNavdeep Parhar 				    (i == sec_info->max_seq_no &&
449*f856f099SNavdeep Parhar 				    j == sec_info->max_seq_sec)){
450*f856f099SNavdeep Parhar 					/* filling data buffer with sector data
451*f856f099SNavdeep Parhar 					 * except sector header
452*f856f099SNavdeep Parhar 					 */
453*f856f099SNavdeep Parhar 					rc = read_flash(adap, j,
454*f856f099SNavdeep Parhar 							(void *)((char *)data +
455*f856f099SNavdeep Parhar 							data_offset),
456*f856f099SNavdeep Parhar 							tmp_size, 0);
457*f856f099SNavdeep Parhar 					data_offset += (tmp_size);
458*f856f099SNavdeep Parhar 					size -= (tmp_size);
459*f856f099SNavdeep Parhar 					break;
460*f856f099SNavdeep Parhar 				}
461*f856f099SNavdeep Parhar 			}
462*f856f099SNavdeep Parhar 		}
463*f856f099SNavdeep Parhar 	}
464*f856f099SNavdeep Parhar 
465*f856f099SNavdeep Parhar 	return rc;
466*f856f099SNavdeep Parhar }
467*f856f099SNavdeep Parhar 
468*f856f099SNavdeep Parhar int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size,
469*f856f099SNavdeep Parhar 		u32 start_address)
470*f856f099SNavdeep Parhar {
471*f856f099SNavdeep Parhar 	unsigned int addr, i, n;
472*f856f099SNavdeep Parhar 	int rc;
473*f856f099SNavdeep Parhar 	u32 *ptr = (u32 *)data;
474*f856f099SNavdeep Parhar 	addr = start_sec * CUDBG_SF_SECTOR_SIZE + start_address;
475*f856f099SNavdeep Parhar 	size = size / 4;
476*f856f099SNavdeep Parhar 	for (i = 0; i < size; i += SF_PAGE_SIZE) {
477*f856f099SNavdeep Parhar 		if ((size - i) <  SF_PAGE_SIZE)
478*f856f099SNavdeep Parhar 			n = size - i;
479*f856f099SNavdeep Parhar 		else
480*f856f099SNavdeep Parhar 			n = SF_PAGE_SIZE;
481*f856f099SNavdeep Parhar 		rc = t4_read_flash(adap, addr, n, ptr, 0);
482*f856f099SNavdeep Parhar 		if (rc)
483*f856f099SNavdeep Parhar 			goto out;
484*f856f099SNavdeep Parhar 
485*f856f099SNavdeep Parhar 		addr = addr + (n*4);
486*f856f099SNavdeep Parhar 		ptr += n;
487*f856f099SNavdeep Parhar 	}
488*f856f099SNavdeep Parhar 
489*f856f099SNavdeep Parhar 	return 0;
490*f856f099SNavdeep Parhar out:
491*f856f099SNavdeep Parhar 	return rc;
492*f856f099SNavdeep Parhar }
493