• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hw_decompress_v1.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 
30 #include <common.h>
31 #endif
32 #include <compiler.h>
33 
34 #include "hw_decompress_v1.h"
35 
36 #if (defined CONFIG_TARGET_HI3556V200)
37 #include "hw_decompress_hi3556v200.c"
38 #endif
39 
40 #if (defined CONFIG_TARGET_HI3559V200)
41 #include "hw_decompress_hi3559v200.c"
42 #endif
43 
44 #if (defined CONFIG_TARGET_HI3562V100)
45 #include "hw_decompress_hi3559v200.c"
46 #endif
47 #if (defined CONFIG_TARGET_HI3566V100)
48 #include "hw_decompress_hi3559v200.c"
49 #endif
50 #if ((defined CONFIG_TARGET_HI3516DV300) || (defined CONFIG_TARGET_HI3516AV300))
51 #include "hw_decompress_hi3516dv300.c"
52 #endif
53 
54 #if (defined CONFIG_TARGET_HI3516CV500)
55 #include "hw_decompress_hi3516cv500.c"
56 #endif
57 
58 #if (defined CONFIG_TARGET_HI3516EV200)
59 #include "hw_decompress_hi3516ev200.c"
60 #endif
61 
62 #if (defined CONFIG_TARGET_HI3516EV300)
63 #include "hw_decompress_hi3516ev300.c"
64 #endif
65 
66 #if (defined CONFIG_TARGET_HI3518EV300)
67 #include "hw_decompress_hi3518ev300.c"
68 #endif
69 
70 #if (defined CONFIG_TARGET_HI3516DV200)
71 #include "hw_decompress_hi3516dv200.c"
72 #endif
73 
74 unsigned int hw_dec_type;
75 unsigned int hw_dec_sop;
76 unsigned int hw_dec_eop;
77 unsigned int hw_dec_cur_blk;
78 unsigned int hw_blk_total_num;
79 
hw_dec_sop_eop_first_set(int block_num)80 void hw_dec_sop_eop_first_set(int block_num)
81 {
82 	if (block_num == 1) {
83 		hw_dec_sop = 1;
84 		hw_dec_eop = 1;
85 	} else {
86 		hw_dec_sop = 1;
87 		hw_dec_eop = 0;
88 	}
89 
90 	hw_dec_cur_blk = 0;
91 	hw_blk_total_num = block_num;
92 }
93 
hw_dec_work_en_set(int work_en_flg)94 static inline void hw_dec_work_en_set(int work_en_flg)
95 {
96 	/* Enable the emar */
97 	writel(work_en_flg, HW_DEC_REG_BASE_ADDR + EAMR_WORK_EN_REG_OFST);
98 }
99 
hw_dec_rtn_baddr_set(unsigned int addr)100 static inline void hw_dec_rtn_baddr_set(unsigned int addr)
101 {
102 	writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_BADDR);
103 }
104 
hw_dec_dprs_data_baddr_set(unsigned int addr)105 static inline void hw_dec_dprs_data_baddr_set(unsigned int addr)
106 {
107 	writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_BADDR);
108 }
109 
hw_dec_data_rtn_len_set(unsigned int len)110 static inline void hw_dec_data_rtn_len_set(unsigned int len)
111 {
112 	writel(len, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_LEN);
113 }
114 
hw_dec_dprs_data_len_set(unsigned int len)115 static inline void hw_dec_dprs_data_len_set(unsigned int len)
116 {
117 	writel(len, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_LEN);
118 }
119 
hw_dec_crc_check_en(unsigned int crc_en)120 static inline void hw_dec_crc_check_en(unsigned int crc_en)
121 {
122 	writel(crc_en, HW_DEC_REG_BASE_ADDR + CRC_CHECK_EN);
123 }
124 
hw_dec_data_crc32_set(unsigned int crc32)125 static inline void hw_dec_data_crc32_set(unsigned int crc32)
126 {
127 	writel(crc32, HW_DEC_REG_BASE_ADDR + DPRS_DATA_CRC32);
128 }
129 
hw_dec_buf_status_get(void)130 static inline unsigned int hw_dec_buf_status_get(void)
131 {
132 	return readl(HW_DEC_REG_BASE_ADDR + BUF_INFO);
133 }
134 
hw_dec_dprs_rtn_status_get(void)135 static inline unsigned int hw_dec_dprs_rtn_status_get(void)
136 {
137 	return readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_INFO);
138 }
139 
hw_dec_buf_status_clr(void)140 static inline void hw_dec_buf_status_clr(void)
141 {
142 	writel(0x1, HW_DEC_REG_BASE_ADDR + BUF_INFO_CLR);
143 }
144 
hw_dec_dprs_rtn_status_clr(void)145 static inline void hw_dec_dprs_rtn_status_clr(void)
146 {
147 	writel(0x1, HW_DEC_REG_BASE_ADDR + RLT_INFO_CLR);
148 }
149 
hw_dec_intr_en_set(int blk_intr_en,int task_intr_en)150 static void hw_dec_intr_en_set(int blk_intr_en, int task_intr_en)
151 {
152 	u_intr_en intr_en;
153 	intr_en.bits.task_intrpt_en = task_intr_en;
154 	intr_en.bits.block_intrpt_en = blk_intr_en;
155 	writel(intr_en.u32, HW_DEC_REG_BASE_ADDR + INT_EN_REG_ADDR);
156 }
157 
hw_dec_intr_status_get(void)158 static inline unsigned int hw_dec_intr_status_get(void)
159 {
160 	return readl(HW_DEC_REG_BASE_ADDR + INT_STATUS_REG_ADDR);
161 }
162 
hw_dec_block_intr_status_clr(void)163 static void hw_dec_block_intr_status_clr(void)
164 {
165 	u_intr_clr intr_clr;
166 
167 	intr_clr.u32 = readl(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
168 	intr_clr.bits.block_intrpt_clr = 0x1;
169 	writel(intr_clr.u32, HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
170 }
171 
hw_dec_task_intr_status_clr(void)172 static void hw_dec_task_intr_status_clr(void)
173 {
174 	u_intr_clr intr_clr;
175 
176 	intr_clr.u32 = readl(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
177 	intr_clr.bits.task_intrpt_clr = 0x1;
178 	writel(intr_clr.u32, HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
179 }
180 
hw_dec_intr_proc(int irq,void * para)181 int hw_dec_intr_proc(int irq, void *para)
182 {
183 	u_buf_status buf_status;
184 	u_intr_status intr_status;
185 	u_dprs_rtn_status dprs_status;
186 	int ret = 0;
187 
188 	intr_status.u32 = hw_dec_intr_status_get();
189 	if (intr_status.bits.block_intrpt) {
190 		buf_status.u32 = hw_dec_buf_status_get();
191 		if (buf_status.bits.aval_flg)
192 			hw_dec_buf_status_clr();
193 
194 		hw_dec_block_intr_status_clr();
195 	}
196 
197 	if (intr_status.bits.task_intrpt) {
198 		dprs_status.u32 = hw_dec_dprs_rtn_status_get();
199 		if (dprs_status.bits.aval_flg) {
200 			if (dprs_status.bits.err_info)
201 				ret = -2; /* -2:failed */
202 
203 			hw_dec_dprs_rtn_status_clr();
204 		}
205 
206 		hw_dec_task_intr_status_clr();
207 		goto out;
208 	}
209 
210 	ret = -1;
211 out:
212 	return ret;
213 }
214 
hw_dec_start(unsigned int src_baddr,unsigned int dst_baddr,unsigned int src_len,unsigned int dst_len,unsigned int crc_en,unsigned int crc32,unsigned int dec_type)215 void hw_dec_start(unsigned int src_baddr,
216 			unsigned int dst_baddr,
217 			unsigned int src_len,
218 			unsigned int dst_len,
219 			unsigned int crc_en,
220 			unsigned int crc32,
221 			unsigned int dec_type)
222 {
223 	unsigned int val;
224 
225 	if (hw_dec_sop) {
226 		if (!dec_type) {
227 			/* set the parameters of output buffer */
228 			hw_dec_rtn_baddr_set(dst_baddr);
229 			hw_dec_data_rtn_len_set(dst_len);
230 		} else {
231 			/* set the parameter of output buffer */
232 			hw_dec_dprs_data_baddr_set(dst_baddr);
233 			hw_dec_dprs_data_len_set(page_nr(dst_len) * 4); /* 4:Align */
234 		}
235 	}
236 
237 	/* set the parameter of input buffer */
238 	writel(src_baddr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_BADDR);
239 
240 	val = src_len |
241 		(hw_dec_sop << 28) | (hw_dec_eop << 29) | (!dec_type << 31); /* 28,29,31 Move Left bit */
242 	writel(val, HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_LEN);
243 
244 	hw_dec_crc_check_en(crc_en);
245 }
246 
delay(unsigned int num)247 static inline void delay(unsigned int num)
248 {
249 	volatile unsigned int i;
250 
251 	for (i = 0; i < (100 * num); i++) /* 100: Cycle */
252 		__asm__ __volatile__("nop");
253 }
254 
hw_dec_wait_finish(void)255 int hw_dec_wait_finish(void)
256 {
257 	int ret;
258 	int times = 0;
259 
260 	do {
261 		ret = hw_dec_intr_proc(HW_DEC_INTR, NULL);
262 		times++;
263 		if (times > 2000000) { /* 2000000 ms */
264 			error("hardware decompress overtime!\n");
265 			break;
266 		}
267 		delay(1);
268 	} while (-1 == ret);
269 
270 	return ret;
271 }
272 
hw_dec_decompress(unsigned char * dst,int * dstlen,unsigned char * src,int srclen,void * unused)273 int hw_dec_decompress(unsigned char *dst, int *dstlen,
274 			unsigned char *src, int srclen,
275 			void *unused)
276 {
277 	int ret;
278 
279 	hw_dec_sop_eop_first_set(1);
280 	hw_dec_start((unsigned int)(uintptr_t)src, (unsigned int)(uintptr_t)dst,
281 				 srclen, *dstlen, 1, 0, hw_dec_type);
282 
283 	ret = hw_dec_wait_finish();
284 
285 	*dstlen = readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_LEN);
286 
287 	if (ret)
288 		return -1;
289 
290 	return 0;
291 }
292 
hw_dec_init(void)293 void hw_dec_init(void)
294 {
295 	/* enable decompress clock */
296 	enable_decompress_clock();
297 	/* Init the emar interface */
298 	writel(0, HW_DEC_REG_BASE_ADDR + EAMR_RID_REG_OFST);
299 	writel(0x3, HW_DEC_REG_BASE_ADDR + EAMR_ROSD_REG_OFST);
300 	writel(0, HW_DEC_REG_BASE_ADDR + EAMR_WID_REG_OFST);
301 	writel(0x3, HW_DEC_REG_BASE_ADDR + EAMR_WOSD_REG_OFST);
302 
303 	/* Enable interrupt */
304 	hw_dec_intr_en_set(0x1, 0x1);
305 
306 	/* Enable emar */
307 	hw_dec_work_en_set(0x1);
308 }
309 
hw_dec_uinit(void)310 void hw_dec_uinit(void)
311 {
312 	hw_dec_work_en_set(0x0);
313 	hw_dec_intr_en_set(0x0, 0x0);
314 
315 	/* disable decompress clock */
316 	disable_decompress_clock();
317 }
318 
319