• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hw_decompress_v2.c
3  *
4  * Files related to software decompression and hardware decompression
5  *
6  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <asm/io.h>
24 #ifndef error
25 #define error(fmt, args...) do { \
26 	printf("ERROR: " pr_fmt(fmt) "\nat %s:%d/%s()\n", \
27 		##args, __FILE__, __LINE__, __func__);	\
28 } while (0)
29 #endif
30 
31 #include "hw_decompress_v2.h"
32 
33 #if (defined CONFIG_TARGET_HI3559AV100) || (defined CONFIG_HI3559AV100)
34 #include "hw_decompress_hi3559av100.c"
35 #endif
36 
37 
38 #if (defined CONFIG_TARGET_HI3569V100) || (defined CONFIG_HI3569V100)
39 #include "hw_decompress_hi3569v100.c"
40 #endif
41 
42 #if (defined CONFIG_TARGET_HI3556AV100)
43 #include "hw_decompress_hi3556av100.c"
44 #endif
45 
46 #if (defined CONFIG_TARGET_HI3519AV100)
47 #include "hw_decompress_hi3519av100.c"
48 #endif
49 
50 unsigned int hw_dec_type = 0;
51 static unsigned int hw_dec_sop;
52 static unsigned int hw_dec_eop;
53 static unsigned int hw_dec_cur_blk;
54 static unsigned int hw_blk_total_num;
55 
56 
hw_dec_sop_eop_first_set(int block_num)57 void hw_dec_sop_eop_first_set(int block_num)
58 {
59 	if (block_num == 1) {
60 		hw_dec_sop = 1;
61 		hw_dec_eop = 1;
62 	} else {
63 		hw_dec_sop = 1;
64 		hw_dec_eop = 0;
65 	}
66 
67 	hw_dec_cur_blk = 0;
68 	hw_blk_total_num = block_num;
69 }
70 
hw_dec_work_en_set(int work_en_flg)71 static inline void hw_dec_work_en_set(int work_en_flg)
72 {
73 	/* Enable the emar */
74 	writel(work_en_flg, HW_DEC_REG_BASE_ADDR + EAMR_WORK_EN_REG_OFST);
75 }
76 
hw_dec_rtn_baddr_h32_set(unsigned int addr)77 static inline void hw_dec_rtn_baddr_h32_set(unsigned int addr)
78 {
79 	writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_BADDR_H32);
80 }
81 
hw_dec_rtn_baddr_l32_set(unsigned int addr)82 static inline void hw_dec_rtn_baddr_l32_set(unsigned int addr)
83 {
84 	writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_BADDR_L32);
85 }
86 
hw_dec_dprs_data_baddr_h32_set(unsigned int addr)87 static inline void hw_dec_dprs_data_baddr_h32_set(unsigned int addr)
88 {
89 	writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_BADDR_H32);
90 }
91 
hw_dec_dprs_data_baddr_l32_set(unsigned int addr)92 static inline void hw_dec_dprs_data_baddr_l32_set(unsigned int addr)
93 {
94 	writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_BADDR_L32);
95 }
96 
hw_dec_data_rtn_len_set(unsigned int len)97 static inline void hw_dec_data_rtn_len_set(unsigned int len)
98 {
99 	writel(len, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_LEN);
100 }
101 
hw_dec_dprs_data_len_set(unsigned int len)102 static inline void hw_dec_dprs_data_len_set(unsigned int len)
103 {
104 	writel(len, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_LEN);
105 }
106 
hw_dec_crc_check_en(unsigned int crc_en)107 static inline void hw_dec_crc_check_en(unsigned int crc_en)
108 {
109 	writel(crc_en, HW_DEC_REG_BASE_ADDR + CRC_CHECK_EN);
110 }
111 
hw_dec_data_crc32_set(unsigned int crc32)112 static inline void hw_dec_data_crc32_set(unsigned int crc32)
113 {
114 	writel(crc32, HW_DEC_REG_BASE_ADDR + DPRS_DATA_CRC32);
115 }
116 
hw_dec_buf_status_get(void)117 static inline unsigned int hw_dec_buf_status_get(void)
118 {
119 	return readl(HW_DEC_REG_BASE_ADDR + BUF_INFO);
120 }
121 
hw_dec_dprs_rtn_status_get(void)122 static inline unsigned int hw_dec_dprs_rtn_status_get(void)
123 {
124 	return readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_INFO);
125 }
126 
hw_dec_buf_status_clr(void)127 static inline void hw_dec_buf_status_clr(void)
128 {
129 	writel(0x1, HW_DEC_REG_BASE_ADDR + BUF_INFO_CLR);
130 }
131 
hw_dec_dprs_rtn_status_clr(void)132 static inline void hw_dec_dprs_rtn_status_clr(void)
133 {
134 	writel(0x1, HW_DEC_REG_BASE_ADDR + RLT_INFO_CLR);
135 }
136 
hw_dec_intr_en_set(int blk_intr_en,int task_intr_en)137 static void hw_dec_intr_en_set(int blk_intr_en, int task_intr_en)
138 {
139 	u_intr_en intr_en;
140 	intr_en.bits.task_intrpt_en = task_intr_en;
141 	intr_en.bits.block_intrpt_en = blk_intr_en;
142 	writel(intr_en.u32, HW_DEC_REG_BASE_ADDR + INT_EN_REG_ADDR);
143 }
144 
hw_dec_intr_status_get(void)145 static inline unsigned int hw_dec_intr_status_get(void)
146 {
147 	return readl(HW_DEC_REG_BASE_ADDR + INT_STATUS_REG_ADDR);
148 }
149 
hw_dec_block_intr_status_clr(void)150 static void hw_dec_block_intr_status_clr(void)
151 {
152 	u_intr_clr intr_clr;
153 
154 	intr_clr.u32 = readl(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
155 	intr_clr.bits.block_intrpt_clr = 0x1;
156 	writel(intr_clr.u32, HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
157 }
158 
hw_dec_task_intr_status_clr(void)159 static void hw_dec_task_intr_status_clr(void)
160 {
161 	u_intr_clr intr_clr;
162 
163 	intr_clr.u32 = readl(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
164 	intr_clr.bits.task_intrpt_clr = 0x1;
165 	writel(intr_clr.u32, HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
166 }
167 
hw_dec_intr_proc(int irq,void * para)168 int hw_dec_intr_proc(int irq, void *para)
169 {
170 	u_buf_status buf_status;
171 	u_intr_status intr_status;
172 	u_dprs_rtn_status dprs_status;
173 	int ret = 0;
174 
175 	intr_status.u32 = hw_dec_intr_status_get();
176 	if (intr_status.bits.block_intrpt) {
177 		buf_status.u32 = hw_dec_buf_status_get();
178 		if (buf_status.bits.aval_flg)
179 			hw_dec_buf_status_clr();
180 
181 		hw_dec_block_intr_status_clr();
182 	}
183 
184 	if (!intr_status.bits.task_intrpt)
185 		return -1;
186 
187 	dprs_status.u32 = hw_dec_dprs_rtn_status_get();
188 	if (dprs_status.bits.aval_flg) {
189 		if (dprs_status.bits.err_info) {
190 			if (dprs_status.bits.err_info == 0x81)
191 				error("\n[hw_dec_intr_proc] error = 0x81\n");
192 			else if (dprs_status.bits.err_info == 0x85)
193 				error("\n[hw_dec_intr_proc] error = 0x85\n");
194 			else if (dprs_status.bits.err_info == 0x87)
195 				error("\n[hw_dec_intr_proc] error = 0x87\n");
196 			else if (dprs_status.bits.err_info == 0x89)
197 				error("\n[hw_dec_intr_proc] error = 0x89\n");
198 			else if (dprs_status.bits.err_info == 0x8a)
199 				error("\n[hw_dec_intr_proc] error = 0x8a\n");
200 			else if (dprs_status.bits.err_info == 0x8b)
201 				error("\n[hw_dec_intr_proc] error = 0x8b\n");
202 			else
203 				error("\n[hw_dec_intr_proc] other error !!\n");
204 			ret = -2; /* -2:failed */
205 		}
206 
207 		hw_dec_dprs_rtn_status_clr();
208 	}
209 
210 	hw_dec_task_intr_status_clr();
211 	return ret;
212 }
213 
hw_dec_start(unsigned int src_baddr_h32,unsigned int src_baddr_l32,unsigned int dst_baddr_h32,unsigned int dst_baddr_l32,unsigned int src_len,unsigned int dst_len,unsigned int crc_en,unsigned int crc32,unsigned int dec_type)214 void hw_dec_start(unsigned int src_baddr_h32,
215 			unsigned int src_baddr_l32,
216 			unsigned int dst_baddr_h32,
217 			unsigned int dst_baddr_l32,
218 			unsigned int src_len,
219 			unsigned int dst_len,
220 			unsigned int crc_en,
221 			unsigned int crc32,
222 			unsigned int dec_type)
223 {
224 	unsigned int val;
225 
226 	if (hw_dec_sop) {
227 		if (!dec_type) {
228 			/* set the parameters of output buffer */
229 			hw_dec_rtn_baddr_h32_set(dst_baddr_h32);
230 			hw_dec_rtn_baddr_l32_set(dst_baddr_l32);
231 			hw_dec_data_rtn_len_set(dst_len);
232 		} else {
233 			/* set the parameter of output buffer */
234 			hw_dec_dprs_data_baddr_h32_set(dst_baddr_h32);
235 			hw_dec_dprs_data_baddr_l32_set(dst_baddr_l32);
236 			hw_dec_dprs_data_len_set(page_nr(dst_len) * 4); /* 4:Align */
237 		}
238 	}
239 
240 	/* set the parameter of input buffer */
241 	writel(src_baddr_l32, HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_BADDR_L32);
242 
243 	val = src_len |
244 		(hw_dec_sop << 28) | (hw_dec_eop << 29) | (!dec_type << 31); /* 28,29,31 Move Left bit */
245 	writel(val, HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_LEN);
246 
247 	hw_dec_crc_check_en(crc_en);
248 }
249 
delay(unsigned int num)250 static inline void delay(unsigned int num)
251 {
252 	volatile unsigned int i;
253 
254 	for (i = 0; i < (100 * num); i++) /* 100: Cycle */
255 		__asm__ __volatile__("nop");
256 }
257 
hw_dec_wait_finish(void)258 int hw_dec_wait_finish(void)
259 {
260 	int ret;
261 	int times = 0;
262 
263 	do {
264 		ret = hw_dec_intr_proc(HW_DEC_INTR, NULL);
265 		times++;
266 		if (times > 2000000) { /* 2000000 ms */
267 			error("\nhardware decompress overtime!\n");
268 			break;
269 		}
270 		delay(1);
271 	} while (-1 == ret);
272 
273 	return ret;
274 }
275 
hw_dec_decompress(unsigned char * dst_h32,unsigned char * dst_l32,int * dstlen,unsigned char * src_h32,unsigned char * src_l32,int srclen,void * unused)276 int hw_dec_decompress(unsigned char *dst_h32, unsigned char *dst_l32,
277 				int *dstlen, unsigned char *src_h32,
278 				unsigned char *src_l32, int srclen, void *unused)
279 {
280 	int ret;
281 
282 	if (srclen > GZIP_MAX_LEN) {
283 		error("\nThe max lenth GZIP decompress supported is (16MB - 1) !!!!\n");
284 		return -1;
285 	}
286 
287 	hw_dec_sop_eop_first_set(1);
288 
289 	hw_dec_start((unsigned int)(uintptr_t)src_h32, (unsigned int)(uintptr_t)src_l32,
290 				 (unsigned int)(uintptr_t)dst_h32, (unsigned int)(uintptr_t)dst_l32,
291 				 srclen, *dstlen, 0, 0, hw_dec_type);
292 
293 	ret = hw_dec_wait_finish();
294 
295 	*dstlen = readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_LEN);
296 
297 	if (ret)
298 		return -1;
299 
300 	return 0;
301 }
302 
hw_dec_init(void)303 void hw_dec_init(void)
304 {
305 	/* enable decompress clock */
306 	enable_decompress_clock();
307 	/* Init the emar interface */
308 	/* bit[31:28] : Emar Write Outstanding
309 	   bit[27:24] : Emar Read Outstanding
310 	   bit[23: 0] : reserve */
311 	writel(0, HW_DEC_REG_BASE_ADDR + EAMR_OSD_REG_OFST);
312 	writel((0x3 << 24), HW_DEC_REG_BASE_ADDR + EAMR_OSD_REG_OFST); /* 0x3 Move Left 24bit */
313 	writel((0x3 << 28), HW_DEC_REG_BASE_ADDR + EAMR_OSD_REG_OFST); /* 0x3 Move Left 28bit */
314 
315 	/* Enable interrupt */
316 	hw_dec_intr_en_set(0x1, 0x1);
317 
318 	/* Enable emar */
319 	hw_dec_work_en_set(0x1);
320 }
321 
hw_dec_uinit(void)322 void hw_dec_uinit(void)
323 {
324 	hw_dec_work_en_set(0x0);
325 	hw_dec_intr_en_set(0x0, 0x0);
326 
327 	/* disable decompress clock */
328 	disable_decompress_clock();
329 }
330