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