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