xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/aw87xxx/aw_bin_parse.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * aw_bin_parse.c
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (c) 2020 AWINIC Technology CO., LTD
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
7*4882a593Smuzhiyun * under the terms of the GNU General Public License as published by the
8*4882a593Smuzhiyun * Free Software Foundation; either version 2 of the License, or (at your
9*4882a593Smuzhiyun * option) any later version.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/i2c.h>
15*4882a593Smuzhiyun #include <linux/of_gpio.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/device.h>
18*4882a593Smuzhiyun #include <linux/firmware.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun #include <linux/version.h>
21*4882a593Smuzhiyun #include <linux/input.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/debugfs.h>
24*4882a593Smuzhiyun #include <linux/miscdevice.h>
25*4882a593Smuzhiyun #include <asm/uaccess.h>
26*4882a593Smuzhiyun #include <linux/regmap.h>
27*4882a593Smuzhiyun #include <linux/timer.h>
28*4882a593Smuzhiyun #include <linux/workqueue.h>
29*4882a593Smuzhiyun #include <linux/hrtimer.h>
30*4882a593Smuzhiyun #include <linux/mutex.h>
31*4882a593Smuzhiyun #include <linux/cdev.h>
32*4882a593Smuzhiyun #include <linux/list.h>
33*4882a593Smuzhiyun #include <linux/string.h>
34*4882a593Smuzhiyun #include "aw_bin_parse.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define AWINIC_CODE_VERSION "V0.0.7-V1.0.4"	/* "code version"-"excel version" */
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define DEBUG_LOG_LEVEL
39*4882a593Smuzhiyun #ifdef DEBUG_LOG_LEVEL
40*4882a593Smuzhiyun #define DBG(fmt, arg...)   do {\
41*4882a593Smuzhiyun printk("AWINIC_BIN %s,line= %d,"fmt, __func__, __LINE__, ##arg);\
42*4882a593Smuzhiyun } while (0)
43*4882a593Smuzhiyun #define DBG_ERR(fmt, arg...)   do {\
44*4882a593Smuzhiyun printk("AWINIC_BIN_ERR %s,line= %d,"fmt, __func__, __LINE__, ##arg);\
45*4882a593Smuzhiyun } while (0)
46*4882a593Smuzhiyun #else
47*4882a593Smuzhiyun #define DBG(fmt, arg...) do {} while (0)
48*4882a593Smuzhiyun #define DBG_ERR(fmt, arg...) do {} while (0)
49*4882a593Smuzhiyun #endif
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define printing_data_code
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun typedef unsigned short int aw_uint16;
54*4882a593Smuzhiyun typedef unsigned long int aw_uint32;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define BigLittleSwap16(A)	((((aw_uint16)(A) & 0xff00) >> 8) | \
57*4882a593Smuzhiyun 				 (((aw_uint16)(A) & 0x00ff) << 8))
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define BigLittleSwap32(A)	((((aw_uint32)(A) & 0xff000000) >> 24) | \
60*4882a593Smuzhiyun 				(((aw_uint32)(A) & 0x00ff0000) >> 8) | \
61*4882a593Smuzhiyun 				(((aw_uint32)(A) & 0x0000ff00) << 8) | \
62*4882a593Smuzhiyun 				(((aw_uint32)(A) & 0x000000ff) << 24))
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /**
65*4882a593Smuzhiyun *
66*4882a593Smuzhiyun * Interface function
67*4882a593Smuzhiyun *
68*4882a593Smuzhiyun * return value:
69*4882a593Smuzhiyun *       value = 0 :success;
70*4882a593Smuzhiyun *       value = -1 :check bin header version
71*4882a593Smuzhiyun *       value = -2 :check bin data type
72*4882a593Smuzhiyun *       value = -3 :check sum or check bin data len error
73*4882a593Smuzhiyun *       value = -4 :check data version
74*4882a593Smuzhiyun *       value = -5 :check register num
75*4882a593Smuzhiyun *       value = -6 :check dsp reg num
76*4882a593Smuzhiyun *       value = -7 :check soc app num
77*4882a593Smuzhiyun *       value = -8 :bin is NULL point
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun **/
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /********************************************************
82*4882a593Smuzhiyun *
83*4882a593Smuzhiyun * check sum data
84*4882a593Smuzhiyun *
85*4882a593Smuzhiyun ********************************************************/
aw_check_sum(struct aw_bin * bin,int bin_num)86*4882a593Smuzhiyun int aw_check_sum(struct aw_bin *bin, int bin_num)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	unsigned int i = 0;
89*4882a593Smuzhiyun 	unsigned int sum_data = 0;
90*4882a593Smuzhiyun 	unsigned int check_sum = 0;
91*4882a593Smuzhiyun 	char *p_check_sum = NULL;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	DBG("enter\n");
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	p_check_sum =
96*4882a593Smuzhiyun 	    &(bin->info.data[(bin->header_info[bin_num].valid_data_addr -
97*4882a593Smuzhiyun 			      bin->header_info[bin_num].header_len)]);
98*4882a593Smuzhiyun 	DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum);
99*4882a593Smuzhiyun 	check_sum = GET_32_DATA(*(p_check_sum + 3),
100*4882a593Smuzhiyun 				*(p_check_sum + 2),
101*4882a593Smuzhiyun 				*(p_check_sum + 1), *(p_check_sum));
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	for (i = 4;
104*4882a593Smuzhiyun 	     i <
105*4882a593Smuzhiyun 	     bin->header_info[bin_num].bin_data_len +
106*4882a593Smuzhiyun 	     bin->header_info[bin_num].header_len; i++) {
107*4882a593Smuzhiyun 		sum_data += *(p_check_sum + i);
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 	DBG("aw_bin_parse bin_num=%d, check_sum = 0x%x, sum_data = 0x%x\n",
110*4882a593Smuzhiyun 		bin_num, check_sum, sum_data);
111*4882a593Smuzhiyun 	if (sum_data != check_sum) {
112*4882a593Smuzhiyun 		p_check_sum = NULL;
113*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse check sum or check bin data len error\n");
114*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse bin_num=%d, check_sum = 0x%x, sum_data = 0x%x\n", bin_num, check_sum, sum_data);
115*4882a593Smuzhiyun 		return -3;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 	p_check_sum = NULL;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	return 0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
aw_check_data_version(struct aw_bin * bin,int bin_num)122*4882a593Smuzhiyun int aw_check_data_version(struct aw_bin *bin, int bin_num)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	int i = 0;
125*4882a593Smuzhiyun 	DBG("enter\n");
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	for (i = DATA_VERSION_V1; i < DATA_VERSION_MAX; i++) {
128*4882a593Smuzhiyun 		if (bin->header_info[bin_num].bin_data_ver == i) {
129*4882a593Smuzhiyun 			return 0;
130*4882a593Smuzhiyun 		}
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 	DBG_ERR("aw_bin_parse Unrecognized this bin data version\n");
133*4882a593Smuzhiyun 	return -4;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
aw_check_register_num_v1(struct aw_bin * bin,int bin_num)136*4882a593Smuzhiyun int aw_check_register_num_v1(struct aw_bin *bin, int bin_num)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun 	unsigned int check_register_num = 0;
139*4882a593Smuzhiyun 	unsigned int parse_register_num = 0;
140*4882a593Smuzhiyun 	char *p_check_sum = NULL;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	DBG("enter\n");
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	p_check_sum =
145*4882a593Smuzhiyun 	    &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]);
146*4882a593Smuzhiyun 	DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum);
147*4882a593Smuzhiyun 	parse_register_num = GET_32_DATA(*(p_check_sum + 3),
148*4882a593Smuzhiyun 					 *(p_check_sum + 2),
149*4882a593Smuzhiyun 					 *(p_check_sum + 1), *(p_check_sum));
150*4882a593Smuzhiyun 	check_register_num = (bin->header_info[bin_num].bin_data_len - 4) /
151*4882a593Smuzhiyun 	    (bin->header_info[bin_num].reg_byte_len +
152*4882a593Smuzhiyun 	     bin->header_info[bin_num].data_byte_len);
153*4882a593Smuzhiyun 	DBG
154*4882a593Smuzhiyun 	    ("aw_bin_parse bin_num=%d, parse_register_num = 0x%x, check_register_num = 0x%x\n",
155*4882a593Smuzhiyun 	     bin_num, parse_register_num, check_register_num);
156*4882a593Smuzhiyun 	if (parse_register_num != check_register_num) {
157*4882a593Smuzhiyun 		p_check_sum = NULL;
158*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse register num is error\n");
159*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse bin_num=%d, parse_register_num = 0x%x, check_register_num = 0x%x\n", bin_num, parse_register_num, check_register_num);
160*4882a593Smuzhiyun 		return -5;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 	bin->header_info[bin_num].reg_num = parse_register_num;
163*4882a593Smuzhiyun 	bin->header_info[bin_num].valid_data_len =
164*4882a593Smuzhiyun 	    bin->header_info[bin_num].bin_data_len - 4;
165*4882a593Smuzhiyun 	p_check_sum = NULL;
166*4882a593Smuzhiyun 	bin->header_info[bin_num].valid_data_addr =
167*4882a593Smuzhiyun 	    bin->header_info[bin_num].valid_data_addr + 4;
168*4882a593Smuzhiyun 	return 0;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
aw_check_dsp_reg_num_v1(struct aw_bin * bin,int bin_num)171*4882a593Smuzhiyun int aw_check_dsp_reg_num_v1(struct aw_bin *bin, int bin_num)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	unsigned int check_dsp_reg_num = 0;
174*4882a593Smuzhiyun 	unsigned int parse_dsp_reg_num = 0;
175*4882a593Smuzhiyun 	char *p_check_sum = NULL;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	DBG("enter\n");
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	p_check_sum =
180*4882a593Smuzhiyun 	    &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]);
181*4882a593Smuzhiyun 	DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum);
182*4882a593Smuzhiyun 	parse_dsp_reg_num = GET_32_DATA(*(p_check_sum + 7),
183*4882a593Smuzhiyun 					*(p_check_sum + 6),
184*4882a593Smuzhiyun 					*(p_check_sum + 5), *(p_check_sum + 4));
185*4882a593Smuzhiyun 	bin->header_info[bin_num].reg_data_byte_len =
186*4882a593Smuzhiyun 	    GET_32_DATA(*(p_check_sum + 11), *(p_check_sum + 10),
187*4882a593Smuzhiyun 			*(p_check_sum + 9), *(p_check_sum + 8));
188*4882a593Smuzhiyun 	check_dsp_reg_num =
189*4882a593Smuzhiyun 	    (bin->header_info[bin_num].bin_data_len -
190*4882a593Smuzhiyun 	     12) / bin->header_info[bin_num].reg_data_byte_len;
191*4882a593Smuzhiyun 	DBG
192*4882a593Smuzhiyun 	    ("aw_bin_parse bin_num=%d, parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x\n",
193*4882a593Smuzhiyun 	     bin_num, parse_dsp_reg_num, check_dsp_reg_num);
194*4882a593Smuzhiyun 	if (parse_dsp_reg_num != check_dsp_reg_num) {
195*4882a593Smuzhiyun 		p_check_sum = NULL;
196*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse dsp reg num is error\n");
197*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse bin_num=%d, parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x\n", bin_num, parse_dsp_reg_num, check_dsp_reg_num);
198*4882a593Smuzhiyun 		return -6;
199*4882a593Smuzhiyun 	}
200*4882a593Smuzhiyun 	bin->header_info[bin_num].download_addr =
201*4882a593Smuzhiyun 	    GET_32_DATA(*(p_check_sum + 3), *(p_check_sum + 2),
202*4882a593Smuzhiyun 			*(p_check_sum + 1), *(p_check_sum));
203*4882a593Smuzhiyun 	bin->header_info[bin_num].reg_num = parse_dsp_reg_num;
204*4882a593Smuzhiyun 	bin->header_info[bin_num].valid_data_len =
205*4882a593Smuzhiyun 	    bin->header_info[bin_num].bin_data_len - 12;
206*4882a593Smuzhiyun 	p_check_sum = NULL;
207*4882a593Smuzhiyun 	bin->header_info[bin_num].valid_data_addr =
208*4882a593Smuzhiyun 	    bin->header_info[bin_num].valid_data_addr + 12;
209*4882a593Smuzhiyun 	return 0;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
aw_check_soc_app_num_v1(struct aw_bin * bin,int bin_num)212*4882a593Smuzhiyun int aw_check_soc_app_num_v1(struct aw_bin *bin, int bin_num)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	unsigned int check_soc_app_num = 0;
215*4882a593Smuzhiyun 	unsigned int parse_soc_app_num = 0;
216*4882a593Smuzhiyun 	char *p_check_sum = NULL;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	DBG("enter\n");
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	p_check_sum =
221*4882a593Smuzhiyun 	    &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]);
222*4882a593Smuzhiyun 	DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum);
223*4882a593Smuzhiyun 	bin->header_info[bin_num].app_version = GET_32_DATA(*(p_check_sum + 3),
224*4882a593Smuzhiyun 							    *(p_check_sum + 2),
225*4882a593Smuzhiyun 							    *(p_check_sum + 1),
226*4882a593Smuzhiyun 							    *(p_check_sum));
227*4882a593Smuzhiyun 	parse_soc_app_num = GET_32_DATA(*(p_check_sum + 11),
228*4882a593Smuzhiyun 					*(p_check_sum + 10),
229*4882a593Smuzhiyun 					*(p_check_sum + 9), *(p_check_sum + 8));
230*4882a593Smuzhiyun 	check_soc_app_num = bin->header_info[bin_num].bin_data_len - 12;
231*4882a593Smuzhiyun 	DBG
232*4882a593Smuzhiyun 	    ("aw_bin_parse bin_num=%d, parse_soc_app_num = 0x%x, check_soc_app_num = 0x%x\n",
233*4882a593Smuzhiyun 	     bin_num, parse_soc_app_num, check_soc_app_num);
234*4882a593Smuzhiyun 	if (parse_soc_app_num != check_soc_app_num) {
235*4882a593Smuzhiyun 		p_check_sum = NULL;
236*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse soc app num is error\n");
237*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse bin_num=%d, parse_soc_app_num = 0x%x, check_soc_app_num = 0x%x\n", bin_num, parse_soc_app_num, check_soc_app_num);
238*4882a593Smuzhiyun 		return -7;
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 	bin->header_info[bin_num].reg_num = parse_soc_app_num;
241*4882a593Smuzhiyun 	bin->header_info[bin_num].download_addr =
242*4882a593Smuzhiyun 	    GET_32_DATA(*(p_check_sum + 7), *(p_check_sum + 6),
243*4882a593Smuzhiyun 			*(p_check_sum + 5), *(p_check_sum + 4));
244*4882a593Smuzhiyun 	bin->header_info[bin_num].valid_data_len =
245*4882a593Smuzhiyun 	    bin->header_info[bin_num].bin_data_len - 12;
246*4882a593Smuzhiyun 	p_check_sum = NULL;
247*4882a593Smuzhiyun 	bin->header_info[bin_num].valid_data_addr =
248*4882a593Smuzhiyun 	    bin->header_info[bin_num].valid_data_addr + 12;
249*4882a593Smuzhiyun 	return 0;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun /************************
253*4882a593Smuzhiyun ***
254*4882a593Smuzhiyun ***bin header 1_0_0
255*4882a593Smuzhiyun ***
256*4882a593Smuzhiyun ************************/
aw_get_single_bin_header_1_0_0(struct aw_bin * bin)257*4882a593Smuzhiyun void aw_get_single_bin_header_1_0_0(struct aw_bin *bin)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	int i;
260*4882a593Smuzhiyun 	DBG("enter %s\n", __func__);
261*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].header_len = 60;
262*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].check_sum =
263*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 3), *(bin->p_addr + 2),
264*4882a593Smuzhiyun 			*(bin->p_addr + 1), *(bin->p_addr));
265*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].header_ver =
266*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 7), *(bin->p_addr + 6),
267*4882a593Smuzhiyun 			*(bin->p_addr + 5), *(bin->p_addr + 4));
268*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].bin_data_type =
269*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 11), *(bin->p_addr + 10),
270*4882a593Smuzhiyun 			*(bin->p_addr + 9), *(bin->p_addr + 8));
271*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].bin_data_ver =
272*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 15), *(bin->p_addr + 14),
273*4882a593Smuzhiyun 			*(bin->p_addr + 13), *(bin->p_addr + 12));
274*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].bin_data_len =
275*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 19), *(bin->p_addr + 18),
276*4882a593Smuzhiyun 			*(bin->p_addr + 17), *(bin->p_addr + 16));
277*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].ui_ver =
278*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 23), *(bin->p_addr + 22),
279*4882a593Smuzhiyun 			*(bin->p_addr + 21), *(bin->p_addr + 20));
280*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].reg_byte_len =
281*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 35), *(bin->p_addr + 34),
282*4882a593Smuzhiyun 			*(bin->p_addr + 33), *(bin->p_addr + 32));
283*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].data_byte_len =
284*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 39), *(bin->p_addr + 38),
285*4882a593Smuzhiyun 			*(bin->p_addr + 37), *(bin->p_addr + 36));
286*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].device_addr =
287*4882a593Smuzhiyun 	    GET_32_DATA(*(bin->p_addr + 43), *(bin->p_addr + 42),
288*4882a593Smuzhiyun 			*(bin->p_addr + 41), *(bin->p_addr + 40));
289*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
290*4882a593Smuzhiyun 		bin->header_info[bin->all_bin_parse_num].chip_type[i] =
291*4882a593Smuzhiyun 		    *(bin->p_addr + 24 + i);
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].reg_num = 0x00000000;
294*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].reg_data_byte_len = 0x00000000;
295*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].download_addr = 0x00000000;
296*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].app_version = 0x00000000;
297*4882a593Smuzhiyun 	bin->header_info[bin->all_bin_parse_num].valid_data_len = 0x00000000;
298*4882a593Smuzhiyun 	bin->all_bin_parse_num += 1;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
aw_parse_each_of_multi_bins_1_0_0(unsigned int bin_num,int bin_serial_num,struct aw_bin * bin)301*4882a593Smuzhiyun int aw_parse_each_of_multi_bins_1_0_0(unsigned int bin_num, int bin_serial_num,
302*4882a593Smuzhiyun 				      struct aw_bin *bin)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	int ret = 0;
305*4882a593Smuzhiyun 	unsigned int bin_start_addr = 0;
306*4882a593Smuzhiyun 	unsigned int valid_data_len = 0;
307*4882a593Smuzhiyun 	DBG("aw_bin_parse enter multi bin branch -- %s\n", __func__);
308*4882a593Smuzhiyun 	if (!bin_serial_num) {
309*4882a593Smuzhiyun 		bin_start_addr = GET_32_DATA(*(bin->p_addr + 67),
310*4882a593Smuzhiyun 					     *(bin->p_addr + 66),
311*4882a593Smuzhiyun 					     *(bin->p_addr + 65),
312*4882a593Smuzhiyun 					     *(bin->p_addr + 64));
313*4882a593Smuzhiyun 		bin->p_addr += (60 + bin_start_addr);
314*4882a593Smuzhiyun 		bin->header_info[bin->all_bin_parse_num].valid_data_addr =
315*4882a593Smuzhiyun 		    bin->header_info[bin->all_bin_parse_num -
316*4882a593Smuzhiyun 				     1].valid_data_addr + 4 + 8 * bin_num + 60;
317*4882a593Smuzhiyun 	} else {
318*4882a593Smuzhiyun 		valid_data_len =
319*4882a593Smuzhiyun 		    bin->header_info[bin->all_bin_parse_num - 1].bin_data_len;
320*4882a593Smuzhiyun 		bin->p_addr += (60 + valid_data_len);
321*4882a593Smuzhiyun 		bin->header_info[bin->all_bin_parse_num].valid_data_addr =
322*4882a593Smuzhiyun 		    bin->header_info[bin->all_bin_parse_num -
323*4882a593Smuzhiyun 				     1].valid_data_addr +
324*4882a593Smuzhiyun 		    bin->header_info[bin->all_bin_parse_num - 1].bin_data_len +
325*4882a593Smuzhiyun 		    60;
326*4882a593Smuzhiyun 	}
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	ret = aw_parse_bin_header_1_0_0(bin);
329*4882a593Smuzhiyun 	return ret;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun /* Get the number of bins in multi bins, and set a for loop, loop processing each bin data */
aw_get_multi_bin_header_1_0_0(struct aw_bin * bin)333*4882a593Smuzhiyun int aw_get_multi_bin_header_1_0_0(struct aw_bin *bin)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun 	int i = 0;
336*4882a593Smuzhiyun 	int ret = 0;
337*4882a593Smuzhiyun 	unsigned int bin_num = 0;
338*4882a593Smuzhiyun 	DBG("aw_bin_parse enter multi bin branch -- %s\n", __func__);
339*4882a593Smuzhiyun 	bin_num = GET_32_DATA(*(bin->p_addr + 63),
340*4882a593Smuzhiyun 			      *(bin->p_addr + 62),
341*4882a593Smuzhiyun 			      *(bin->p_addr + 61), *(bin->p_addr + 60));
342*4882a593Smuzhiyun 	if (bin->multi_bin_parse_num == 1) {
343*4882a593Smuzhiyun 		bin->header_info[bin->all_bin_parse_num].valid_data_addr = 60;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 	aw_get_single_bin_header_1_0_0(bin);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	for (i = 0; i < bin_num; i++) {
348*4882a593Smuzhiyun 		DBG("aw_bin_parse enter multi bin for is %d\n", i);
349*4882a593Smuzhiyun 		ret = aw_parse_each_of_multi_bins_1_0_0(bin_num, i, bin);
350*4882a593Smuzhiyun 		if (ret < 0) {
351*4882a593Smuzhiyun 			return ret;
352*4882a593Smuzhiyun 		}
353*4882a593Smuzhiyun 	}
354*4882a593Smuzhiyun 	return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun /********************************************************
358*4882a593Smuzhiyun *
359*4882a593Smuzhiyun * If the bin framework header version is 1.0.0,
360*4882a593Smuzhiyun   determine the data type of bin, and then perform different processing
361*4882a593Smuzhiyun   according to the data type
362*4882a593Smuzhiyun   If it is a single bin data type, write the data directly into the structure array
363*4882a593Smuzhiyun   If it is a multi-bin data type, first obtain the number of bins,
364*4882a593Smuzhiyun   and then recursively call the bin frame header processing function
365*4882a593Smuzhiyun   according to the bin number to process the frame header information of each bin separately
366*4882a593Smuzhiyun *
367*4882a593Smuzhiyun ********************************************************/
aw_parse_bin_header_1_0_0(struct aw_bin * bin)368*4882a593Smuzhiyun int aw_parse_bin_header_1_0_0(struct aw_bin *bin)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	int ret = 0;
371*4882a593Smuzhiyun 	unsigned int bin_data_type;
372*4882a593Smuzhiyun 	DBG("enter %s\n", __func__);
373*4882a593Smuzhiyun 	bin_data_type = GET_32_DATA(*(bin->p_addr + 11),
374*4882a593Smuzhiyun 				    *(bin->p_addr + 10),
375*4882a593Smuzhiyun 				    *(bin->p_addr + 9), *(bin->p_addr + 8));
376*4882a593Smuzhiyun 	DBG("aw_bin_parse bin_data_type 0x%x\n", bin_data_type);
377*4882a593Smuzhiyun 	switch (bin_data_type) {
378*4882a593Smuzhiyun 	case DATA_TYPE_REGISTER:
379*4882a593Smuzhiyun 	case DATA_TYPE_DSP_REG:
380*4882a593Smuzhiyun 	case DATA_TYPE_SOC_APP:
381*4882a593Smuzhiyun 		/* Divided into two processing methods,
382*4882a593Smuzhiyun 		   one is single bin processing,
383*4882a593Smuzhiyun 		   and the other is single bin processing in multi bin */
384*4882a593Smuzhiyun 		DBG("aw_bin_parse enter single bin branch\n");
385*4882a593Smuzhiyun 		bin->single_bin_parse_num += 1;
386*4882a593Smuzhiyun 		DBG("%s bin->single_bin_parse_num is %d\n", __func__,
387*4882a593Smuzhiyun 			bin->single_bin_parse_num);
388*4882a593Smuzhiyun 		if (!bin->multi_bin_parse_num) {
389*4882a593Smuzhiyun 			bin->header_info[bin->
390*4882a593Smuzhiyun 					 all_bin_parse_num].valid_data_addr =
391*4882a593Smuzhiyun 			    60;
392*4882a593Smuzhiyun 		}
393*4882a593Smuzhiyun 		aw_get_single_bin_header_1_0_0(bin);
394*4882a593Smuzhiyun 		break;
395*4882a593Smuzhiyun 	case DATA_TYPE_MULTI_BINS:
396*4882a593Smuzhiyun 		/* Get the number of times to enter multi bins */
397*4882a593Smuzhiyun 		DBG("aw_bin_parse enter multi bin branch\n");
398*4882a593Smuzhiyun 		bin->multi_bin_parse_num += 1;
399*4882a593Smuzhiyun 		DBG("%s bin->multi_bin_parse_num is %d\n", __func__,
400*4882a593Smuzhiyun 			bin->multi_bin_parse_num);
401*4882a593Smuzhiyun 		ret = aw_get_multi_bin_header_1_0_0(bin);
402*4882a593Smuzhiyun 		if (ret < 0) {
403*4882a593Smuzhiyun 			return ret;
404*4882a593Smuzhiyun 		}
405*4882a593Smuzhiyun 		break;
406*4882a593Smuzhiyun 	default:
407*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse Unrecognized this bin data type\n");
408*4882a593Smuzhiyun 		return -2;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 	return 0;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun /* get the bin's header version */
aw_check_bin_header_version(struct aw_bin * bin)414*4882a593Smuzhiyun static int aw_check_bin_header_version(struct aw_bin *bin)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	int ret = 0;
417*4882a593Smuzhiyun 	unsigned int header_version = 0;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	header_version = GET_32_DATA(*(bin->p_addr + 7),
420*4882a593Smuzhiyun 				     *(bin->p_addr + 6),
421*4882a593Smuzhiyun 				     *(bin->p_addr + 5), *(bin->p_addr + 4));
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	DBG("aw_bin_parse header_version 0x%x\n", header_version);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	/* Write data to the corresponding structure array
426*4882a593Smuzhiyun 	   according to different formats of the bin frame header version */
427*4882a593Smuzhiyun 	switch (header_version) {
428*4882a593Smuzhiyun 	case HEADER_VERSION_1_0_0:
429*4882a593Smuzhiyun 		ret = aw_parse_bin_header_1_0_0(bin);
430*4882a593Smuzhiyun 		return ret;
431*4882a593Smuzhiyun 	default:
432*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse Unrecognized this bin header version \n");
433*4882a593Smuzhiyun 		return -1;
434*4882a593Smuzhiyun 	}
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
aw_parsing_bin_file(struct aw_bin * bin)437*4882a593Smuzhiyun int aw_parsing_bin_file(struct aw_bin *bin)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	int i = 0;
440*4882a593Smuzhiyun 	int ret = 0;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	DBG("aw_bin_parse code version:%s\n", AWINIC_CODE_VERSION);
443*4882a593Smuzhiyun 	if (!bin) {
444*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse bin is NULL\n");
445*4882a593Smuzhiyun 		return -8;
446*4882a593Smuzhiyun 	}
447*4882a593Smuzhiyun 	bin->p_addr = bin->info.data;
448*4882a593Smuzhiyun 	bin->all_bin_parse_num = 0;
449*4882a593Smuzhiyun 	bin->multi_bin_parse_num = 0;
450*4882a593Smuzhiyun 	bin->single_bin_parse_num = 0;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	/* filling bins header info */
453*4882a593Smuzhiyun 	ret = aw_check_bin_header_version(bin);
454*4882a593Smuzhiyun 	if (ret < 0) {
455*4882a593Smuzhiyun 		DBG_ERR("aw_bin_parse check bin header version error\n");
456*4882a593Smuzhiyun 		return ret;
457*4882a593Smuzhiyun 	}
458*4882a593Smuzhiyun 	bin->p_addr = NULL;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/* check bin header info */
461*4882a593Smuzhiyun 	for (i = 0; i < bin->all_bin_parse_num; i++) {
462*4882a593Smuzhiyun 		/* check sum */
463*4882a593Smuzhiyun 		ret = aw_check_sum(bin, i);
464*4882a593Smuzhiyun 		if (ret < 0) {
465*4882a593Smuzhiyun 			DBG_ERR("aw_bin_parse check sum data error\n");
466*4882a593Smuzhiyun 			return ret;
467*4882a593Smuzhiyun 		}
468*4882a593Smuzhiyun 		/* check bin data version */
469*4882a593Smuzhiyun 		ret = aw_check_data_version(bin, i);
470*4882a593Smuzhiyun 		if (ret < 0) {
471*4882a593Smuzhiyun 			DBG_ERR("aw_bin_parse check data version error\n");
472*4882a593Smuzhiyun 			return ret;
473*4882a593Smuzhiyun 		}
474*4882a593Smuzhiyun 		/* check valid data */
475*4882a593Smuzhiyun 		if (bin->header_info[i].bin_data_ver == DATA_VERSION_V1) {
476*4882a593Smuzhiyun 			/* check register num */
477*4882a593Smuzhiyun 			if (bin->header_info[i].bin_data_type ==
478*4882a593Smuzhiyun 			    DATA_TYPE_REGISTER) {
479*4882a593Smuzhiyun 				ret = aw_check_register_num_v1(bin, i);
480*4882a593Smuzhiyun 				if (ret < 0) {
481*4882a593Smuzhiyun 					DBG_ERR
482*4882a593Smuzhiyun 					    ("aw_bin_parse check register num error\n");
483*4882a593Smuzhiyun 					return ret;
484*4882a593Smuzhiyun 				}
485*4882a593Smuzhiyun 				/* check dsp reg num */
486*4882a593Smuzhiyun 			} else if (bin->header_info[i].bin_data_type ==
487*4882a593Smuzhiyun 				   DATA_TYPE_DSP_REG) {
488*4882a593Smuzhiyun 				ret = aw_check_dsp_reg_num_v1(bin, i);
489*4882a593Smuzhiyun 				if (ret < 0) {
490*4882a593Smuzhiyun 					DBG_ERR
491*4882a593Smuzhiyun 					    ("aw_bin_parse check dsp reg num error\n");
492*4882a593Smuzhiyun 					return ret;
493*4882a593Smuzhiyun 				}
494*4882a593Smuzhiyun 				/* check soc app num */
495*4882a593Smuzhiyun 			} else if (bin->header_info[i].bin_data_type ==
496*4882a593Smuzhiyun 				   DATA_TYPE_SOC_APP) {
497*4882a593Smuzhiyun 				ret = aw_check_soc_app_num_v1(bin, i);
498*4882a593Smuzhiyun 				if (ret < 0) {
499*4882a593Smuzhiyun 					DBG_ERR
500*4882a593Smuzhiyun 					    ("aw_bin_parse check soc app num error\n");
501*4882a593Smuzhiyun 					return ret;
502*4882a593Smuzhiyun 				}
503*4882a593Smuzhiyun 			} else {
504*4882a593Smuzhiyun 				bin->header_info[i].valid_data_len =
505*4882a593Smuzhiyun 				    bin->header_info[i].bin_data_len;
506*4882a593Smuzhiyun 			}
507*4882a593Smuzhiyun 		}
508*4882a593Smuzhiyun 	}
509*4882a593Smuzhiyun 	DBG("aw_bin_parse parsing success\n");
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	return 0;
512*4882a593Smuzhiyun }
513