diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /lib/lzo | |
Diffstat (limited to 'lib/lzo')
| -rw-r--r-- | lib/lzo/Makefile | 11 | ||||
| -rw-r--r-- | lib/lzo/lzo1x_compress.c | 279 | ||||
| -rw-r--r-- | lib/lzo/lzo1x_decompress_safe.c | 268 | ||||
| -rwxr-xr-x | lib/lzo/lzo1x_hw_compress.c | 238 | ||||
| -rwxr-xr-x | lib/lzo/lzo1x_hw_decompress.c | 106 | ||||
| -rw-r--r-- | lib/lzo/lzodefs.h | 59 | ||||
| -rwxr-xr-x | lib/lzo/sprd_zipdec_drv.c | 238 | ||||
| -rwxr-xr-x | lib/lzo/sprd_zipdec_drv.h | 147 | ||||
| -rwxr-xr-x | lib/lzo/sprd_zipenc_drv.c | 246 | ||||
| -rwxr-xr-x | lib/lzo/sprd_zipenc_drv.h | 136 |
10 files changed, 1728 insertions, 0 deletions
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile new file mode 100644 index 00000000..309baa21 --- /dev/null +++ b/lib/lzo/Makefile @@ -0,0 +1,11 @@ + +ifeq ($(CONFIG_LZO_HW_ALGO),y) +obj-y += lzo1x_hw_compress.o sprd_zipenc_drv.o +obj-y += lzo1x_hw_decompress.o sprd_zipdec_drv.o +endif + +lzo_compress-objs := lzo1x_compress.o +lzo_decompress-objs := lzo1x_decompress_safe.o + +obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o +obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c new file mode 100644 index 00000000..236eb211 --- /dev/null +++ b/lib/lzo/lzo1x_compress.c @@ -0,0 +1,279 @@ +/* + * LZO1X Compressor from LZO + * + * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for Linux kernel use by: + * Nitin Gupta <nitingupta910@gmail.com> + * Richard Purdie <rpurdie@openedhand.com> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unaligned.h> +#include <linux/lzo.h> +#include "lzodefs.h" + +static noinline size_t +lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len, + size_t ti, void *wrkmem) +{ + const unsigned char *ip; + unsigned char *op; + const unsigned char * const in_end = in + in_len; + const unsigned char * const ip_end = in + in_len - 20; + const unsigned char *ii; + lzo_dict_t * const dict = (lzo_dict_t *) wrkmem; + + op = out; + ip = in; + ii = ip; + ip += ti < 4 ? 4 - ti : 0; + + for (;;) { + const unsigned char *m_pos; + size_t t, m_len, m_off; + u32 dv; +literal: + ip += 1 + ((ip - ii) >> 5); +next: + if (unlikely(ip >= ip_end)) + break; + dv = get_unaligned_le32(ip); + t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK; + m_pos = in + dict[t]; + dict[t] = (lzo_dict_t) (ip - in); + if (unlikely(dv != get_unaligned_le32(m_pos))) + goto literal; + + ii -= ti; + ti = 0; + t = ip - ii; + if (t != 0) { + if (t <= 3) { + op[-2] |= t; + COPY4(op, ii); + op += t; + } else if (t <= 16) { + *op++ = (t - 3); + COPY8(op, ii); + COPY8(op + 8, ii + 8); + op += t; + } else { + if (t <= 18) { + *op++ = (t - 3); + } else { + size_t tt = t - 18; + *op++ = 0; + while (unlikely(tt > 255)) { + tt -= 255; + *op++ = 0; + } + *op++ = tt; + } + do { + COPY8(op, ii); + COPY8(op + 8, ii + 8); + op += 16; + ii += 16; + t -= 16; + } while (t >= 16); + if (t > 0) do { + *op++ = *ii++; + } while (--t > 0); + } + } + + m_len = 4; + { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64) + u64 v; + v = get_unaligned((const u64 *) (ip + m_len)) ^ + get_unaligned((const u64 *) (m_pos + m_len)); + if (unlikely(v == 0)) { + do { + m_len += 8; + v = get_unaligned((const u64 *) (ip + m_len)) ^ + get_unaligned((const u64 *) (m_pos + m_len)); + if (unlikely(ip + m_len >= ip_end)) + goto m_len_done; + } while (v == 0); + } +# if defined(__LITTLE_ENDIAN) + m_len += (unsigned) __builtin_ctzll(v) / 8; +# elif defined(__BIG_ENDIAN) + m_len += (unsigned) __builtin_clzll(v) / 8; +# else +# error "missing endian definition" +# endif +#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32) + u32 v; + v = get_unaligned((const u32 *) (ip + m_len)) ^ + get_unaligned((const u32 *) (m_pos + m_len)); + if (unlikely(v == 0)) { + do { + m_len += 4; + v = get_unaligned((const u32 *) (ip + m_len)) ^ + get_unaligned((const u32 *) (m_pos + m_len)); + if (v != 0) + break; + m_len += 4; + v = get_unaligned((const u32 *) (ip + m_len)) ^ + get_unaligned((const u32 *) (m_pos + m_len)); + if (unlikely(ip + m_len >= ip_end)) + goto m_len_done; + } while (v == 0); + } +# if defined(__LITTLE_ENDIAN) + m_len += (unsigned) __builtin_ctz(v) / 8; +# elif defined(__BIG_ENDIAN) + m_len += (unsigned) __builtin_clz(v) / 8; +# else +# error "missing endian definition" +# endif +#else + if (unlikely(ip[m_len] == m_pos[m_len])) { + do { + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (unlikely(ip + m_len >= ip_end)) + goto m_len_done; + } while (ip[m_len] == m_pos[m_len]); + } +#endif + } +m_len_done: + + m_off = ip - m_pos; + ip += m_len; + ii = ip; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) { + m_off -= 1; + *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = (m_off >> 3); + } else if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; + if (m_len <= M3_MAX_LEN) + *op++ = (M3_MARKER | (m_len - 2)); + else { + m_len -= M3_MAX_LEN; + *op++ = M3_MARKER | 0; + while (unlikely(m_len > 255)) { + m_len -= 255; + *op++ = 0; + } + *op++ = (m_len); + } + *op++ = (m_off << 2); + *op++ = (m_off >> 6); + } else { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) + *op++ = (M4_MARKER | ((m_off >> 11) & 8) + | (m_len - 2)); + else { + m_len -= M4_MAX_LEN; + *op++ = (M4_MARKER | ((m_off >> 11) & 8)); + while (unlikely(m_len > 255)) { + m_len -= 255; + *op++ = 0; + } + *op++ = (m_len); + } + *op++ = (m_off << 2); + *op++ = (m_off >> 6); + } + goto next; + } + *out_len = op - out; + return in_end - (ii - ti); +} + +int lzo1x_1_compress(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len, + void *wrkmem) +{ + const unsigned char *ip = in; + unsigned char *op = out; + size_t l = in_len; + size_t t = 0; + + while (l > 20) { + size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1); + uintptr_t ll_end = (uintptr_t) ip + ll; + if ((ll_end + ((t + ll) >> 5)) <= ll_end) + break; + BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS); + memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t)); + t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem); + ip += ll; + op += *out_len; + l -= ll; + } + t += l; + + if (t > 0) { + const unsigned char *ii = in + in_len - t; + + if (op == out && t <= 238) { + *op++ = (17 + t); + } else if (t <= 3) { + op[-2] |= t; + } else if (t <= 18) { + *op++ = (t - 3); + } else { + size_t tt = t - 18; + *op++ = 0; + while (tt > 255) { + tt -= 255; + *op++ = 0; + } + *op++ = tt; + } + if (t >= 16) do { + COPY8(op, ii); + COPY8(op + 8, ii + 8); + op += 16; + ii += 16; + t -= 16; + } while (t >= 16); + if (t > 0) do { + *op++ = *ii++; + } while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} +EXPORT_SYMBOL_GPL(lzo1x_1_compress); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZO1X-1 Compressor"); diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c new file mode 100644 index 00000000..a1c387f6 --- /dev/null +++ b/lib/lzo/lzo1x_decompress_safe.c @@ -0,0 +1,268 @@ +/* + * LZO1X Decompressor from LZO + * + * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for Linux kernel use by: + * Nitin Gupta <nitingupta910@gmail.com> + * Richard Purdie <rpurdie@openedhand.com> + */ + +#ifndef STATIC +#include <linux/module.h> +#include <linux/kernel.h> +#endif +#include <asm/unaligned.h> +#include <linux/lzo.h> +#include "lzodefs.h" + +#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x)) +#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) +#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun +#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun +#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun + +/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base + * count without overflowing an integer. The multiply will overflow when + * multiplying 255 by more than MAXINT/255. The sum will overflow earlier + * depending on the base count. Since the base count is taken from a u8 + * and a few bits, it is safe to assume that it will always be lower than + * or equal to 2*255, thus we can always prevent any overflow by accepting + * two less 255 steps. See Documentation/lzo.txt for more information. + */ +#define MAX_255_COUNT ((((size_t)~0) / 255) - 2) + +int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len) +{ + unsigned char *op; + const unsigned char *ip; + size_t t, next; + size_t state = 0; + const unsigned char *m_pos; + const unsigned char * const ip_end = in + in_len; + unsigned char * const op_end = out + *out_len; + + op = out; + ip = in; + + if (unlikely(in_len < 3)) + goto input_overrun; + if (*ip > 17) { + t = *ip++ - 17; + if (t < 4) { + next = t; + goto match_next; + } + goto copy_literal_run; + } + + for (;;) { + t = *ip++; + if (t < 16) { + if (likely(state == 0)) { + if (unlikely(t == 0)) { + size_t offset; + const unsigned char *ip_last = ip; + + while (unlikely(*ip == 0)) { + ip++; + NEED_IP(1); + } + offset = ip - ip_last; + if (unlikely(offset > MAX_255_COUNT)) + return LZO_E_ERROR; + + offset = (offset << 8) - offset; + t += offset + 15 + *ip++; + } + t += 3; +copy_literal_run: +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) { + const unsigned char *ie = ip + t; + unsigned char *oe = op + t; + do { + COPY8(op, ip); + op += 8; + ip += 8; + COPY8(op, ip); + op += 8; + ip += 8; + } while (ip < ie); + ip = ie; + op = oe; + } else +#endif + { + NEED_OP(t); + NEED_IP(t + 3); + do { + *op++ = *ip++; + } while (--t > 0); + } + state = 4; + continue; + } else if (state != 4) { + next = t & 3; + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + TEST_LB(m_pos); + NEED_OP(2); + op[0] = m_pos[0]; + op[1] = m_pos[1]; + op += 2; + goto match_next; + } else { + next = t & 3; + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + t = 3; + } + } else if (t >= 64) { + next = t & 3; + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1 + (3 - 1); + } else if (t >= 32) { + t = (t & 31) + (3 - 1); + if (unlikely(t == 2)) { + size_t offset; + const unsigned char *ip_last = ip; + + while (unlikely(*ip == 0)) { + ip++; + NEED_IP(1); + } + offset = ip - ip_last; + if (unlikely(offset > MAX_255_COUNT)) + return LZO_E_ERROR; + + offset = (offset << 8) - offset; + t += offset + 31 + *ip++; + NEED_IP(2); + } + m_pos = op - 1; + next = get_unaligned_le16(ip); + ip += 2; + m_pos -= next >> 2; + next &= 3; + } else { + m_pos = op; + m_pos -= (t & 8) << 11; + t = (t & 7) + (3 - 1); + if (unlikely(t == 2)) { + size_t offset; + const unsigned char *ip_last = ip; + + while (unlikely(*ip == 0)) { + ip++; + NEED_IP(1); + } + offset = ip - ip_last; + if (unlikely(offset > MAX_255_COUNT)) + return LZO_E_ERROR; + + offset = (offset << 8) - offset; + t += offset + 7 + *ip++; + NEED_IP(2); + } + next = get_unaligned_le16(ip); + ip += 2; + m_pos -= next >> 2; + next &= 3; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; + } + TEST_LB(m_pos); +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + if (op - m_pos >= 8) { + unsigned char *oe = op + t; + if (likely(HAVE_OP(t + 15))) { + do { + COPY8(op, m_pos); + op += 8; + m_pos += 8; + COPY8(op, m_pos); + op += 8; + m_pos += 8; + } while (op < oe); + op = oe; + if (HAVE_IP(6)) { + state = next; + COPY4(op, ip); + op += next; + ip += next; + continue; + } + } else { + NEED_OP(t); + do { + *op++ = *m_pos++; + } while (op < oe); + } + } else +#endif + { + unsigned char *oe = op + t; + NEED_OP(t); + op[0] = m_pos[0]; + op[1] = m_pos[1]; + op += 2; + m_pos += 2; + do { + *op++ = *m_pos++; + } while (op < oe); + } +match_next: + state = next; + t = next; +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + if (likely(HAVE_IP(6) && HAVE_OP(4))) { + COPY4(op, ip); + op += t; + ip += t; + } else +#endif + { + NEED_IP(t + 3); + NEED_OP(t); + while (t > 0) { + *op++ = *ip++; + t--; + } + } + } + +eof_found: + *out_len = op - out; + return (t != 3 ? LZO_E_ERROR : + ip == ip_end ? LZO_E_OK : + ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN); + +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; + +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; + +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +} +#ifndef STATIC +EXPORT_SYMBOL_GPL(lzo1x_decompress_safe); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZO1X Decompressor"); + +#endif diff --git a/lib/lzo/lzo1x_hw_compress.c b/lib/lzo/lzo1x_hw_compress.c new file mode 100755 index 00000000..346ba437 --- /dev/null +++ b/lib/lzo/lzo1x_hw_compress.c @@ -0,0 +1,238 @@ +/****************************************************************************** + ** File Name: * + ** Author: * + ** DATE: * + ** Copyright: Spreatrum, Incoporated. All Rights Reserved. * + ** Description: * + ****************************************************************************** + + ****************************************************************************** + ** Edit History * + ** ------------------------------------------------------------------------- * + ** DATE NAME DESCRIPTION * + ** * + ******************************************************************************/ + +/**---------------------------------------------------------------------------* + ** Dependencies * + **--------------------------------------------------------------------------- */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/lzo.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/poll.h> +#include <linux/sched.h> +#ifndef CONFIG_64BIT +#include <mach/arch_misc.h> +#endif + +#include <linux/highmem.h> +#include <linux/vmalloc.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/io.h> + +#include "sprd_zipenc_drv.h" +//#include "lzodefs_hw.h" +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/atomic.h> +//macro + +DEFINE_SPINLOCK(zipenc_lock); + +u32 lzo1x_virt_to_phys(u32 virt_addr) +{ + u32 phy_addr; + struct page *page; + if((unsigned long)virt_addr<PAGE_OFFSET){ + printk("%s: virtual addr is error\n",__func__); + return (-1UL); + } + if(virt_addr_valid(virt_addr)){ + phy_addr=virt_to_phys(virt_addr); + } + else if(is_vmalloc_or_module_addr(virt_addr)){ + page =vmalloc_to_page(virt_addr); + phy_addr =(page)? page_to_phys(page): (-1UL); + } + else{ + page = kmap_atomic_to_page(virt_addr); + phy_addr =(page)? page_to_phys(page): (-1UL); + } + return phy_addr; +} + +static int _lzo1x_1_hw_compress(u32 src_addr , u32 src_num , u32 dst_addr , u32 *dst_len) +{ + + u32 len,ol_sts; + u32 phy_src_addr,phy_dst_addr; + + *dst_len=0; + + phy_src_addr = lzo1x_virt_to_phys(src_addr); + phy_dst_addr = lzo1x_virt_to_phys(dst_addr); + + if((phy_src_addr==(-1UL))||(phy_dst_addr==(-1UL))) + { + printk("lzo1x phy addr errors \n"); + return LZO_OTHER_ERROR; + } + + spin_lock(&zipenc_lock); + ZipEnc_SetSrcCfg(phy_src_addr , ZIP_WORK_LENGTH); + ZipEnc_SetDestCfg(phy_dst_addr , ZIP_WORK_LENGTH); + + //dmac_flush_range(src_addr,src_addr+ZIP_WORK_LENGTH); + //dmac_flush_range(dst_addr,dst_addr+ZIP_WORK_LENGTH); + + ZipEnc_Run(); + spin_unlock(&zipenc_lock); + + if(Zip_Enc_Wait_Pool(ZIPENC_DONE_INT)) + { + printk("zip enc error\n"); + return LZO_HW_ERROR; + } + + ol_sts=ZipEnc_Get_Ol_Sts(); + if(ol_sts) + { + return LZO_HW_OUT_LEN_ERROR; + } + else + { + len=ZipEnc_Get_Comp_Len(); + if(len >= ZIP_WORK_LENGTH ) + { + return LZO_HW_OUT_LEN_ERROR; + } + } + *dst_len = len; + return 0; +} + +int lzo1x_1_compress_hw(const unsigned char *src , size_t src_len , unsigned char *dst , size_t *dst_len , void *wrkmen) +{ + volatile u32 enc_len; + volatile int ret; + + u32 src_addr =(u32)src; + u32 dst_addr =(u32)dst; + + if (!dst || !dst_len || !src || (src_len!=PAGE_SIZE)) + { + printk("zip compress input parameter error \n"); + return LZO_HW_IN_PARA_ERROR; + } + //printk("lzo hw compress \r\n"); + if(ret=_lzo1x_1_hw_compress((u32)src_addr ,src_len , dst_addr ,&enc_len)) + { + //printk("lzo compress error ret:%d\n",ret); + if(ret== LZO_HW_OUT_LEN_ERROR) + return ret; + + ZipEnc_Restart(); + + *dst_len=enc_len; + if(ret==LZO_HW_ERROR) + return LZO_HW_ERROR; + else + return LZO_OTHER_ERROR; + } + + *dst_len=enc_len; + return LZO_HW_OK; +} + +#ifndef CONFIG_64BIT +int lzo1x_1_compress_hw(const unsigned char *src , size_t src_len , unsigned char *dst , size_t *dst_len , void *wrkmen) +{ + return ZipEnc_compress(src,src_len,dst,dst_len,wrkmen); +} + +unsigned int get_zip_type(void) +{ + static unsigned int lzo_algo_type = 0; + static int read_chip_cnt = 0; + int chip_id; + if(!read_chip_cnt) + { + read_chip_cnt = 1; + chip_id = sci_get_chip_id(); + if((chip_id==0x7715a000)||(chip_id==0x7715a001)||(chip_id==0x8815a000)) + { + lzo_algo_type = 1; + } + printk("lzo zip type %d is %s zip\r\n",lzo_algo_type, lzo_algo_type ? "sw" : "hw"); + } + return lzo_algo_type; +} + +static int __init ZipEnc_Init(void) +{ + int ret; + + printk("%s\r\n", __func__); + + ZipEnc_Enable(); + //ZipEnc_Reset(); + + CHIP_REG_OR(ZIPENC_CTRL , ZIPENC_EN); + + ZipEnc_In_Swt(zipenc_param.in_switch_mode); + ZipEnc_Out_Swt(zipenc_param.out_switch_mode); + + ZipEnc_LengthLimitMode(); + + ZipEnc_InQueue_Clr(); + ZipEnc_OutQueue_Clr(); + + if(zipenc_param.wait_mode == ZIPENC_WAIT_INT) + { + ZipEnc_RegCallback(ZIPENC_DONE_INT,ZipEnc_Callback_Done); + ZipEnc_RegCallback(ZIPENC_TIMEOUT_INT,ZipEnc_Callback_Timeout); + ZipEnc_IntEn(ZIPENC_DONE_INT); + ZipEnc_IntEn(ZIPENC_TIMEOUT_INT); + ret = request_irq( zipenc_param.int_num, ZipEnc_IsrHandler,0,"zip enc",NULL); + if(ret) + { + printk("zip enc request irq error\n"); + return -1; + } + } + + Zip_Enc_Wait = ((zipenc_param.wait_mode==ZIPENC_WAIT_INT)? (Zip_Enc_Wait_Int) : (Zip_Enc_Wait_Pool)); + ZipEnc_compress = get_zip_type() ? lzo1x_1_compress : _lzo1x_1_compress_hw; + return 0; +} + +static void ZipEnc_DeInit(void) +{ + ZipEnc_Disable(); + if(zipenc_param.work_mode==ZIPENC_QUEUE) + { + ZipEnc_InQueue_Clr(); + ZipEnc_OutQueue_Clr(); + } + + if(zipenc_param.wait_mode==ZIPENC_WAIT_INT) + { + ZipEnc_IntDisable(ZIPENC_DONE_INT); + ZipEnc_UNRegCallback(ZIPENC_DONE_INT); + + ZipEnc_UNRegCallback(ZIPENC_TIMEOUT_INT); + free_irq(zipenc_param.int_num,NULL); + } +} + +module_init(ZipEnc_Init); +module_exit(ZipEnc_DeInit); + +EXPORT_SYMBOL_GPL(lzo1x_1_compress_hw); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZO1X-1 HW Compressor"); +#endif diff --git a/lib/lzo/lzo1x_hw_decompress.c b/lib/lzo/lzo1x_hw_decompress.c new file mode 100755 index 00000000..b0060991 --- /dev/null +++ b/lib/lzo/lzo1x_hw_decompress.c @@ -0,0 +1,106 @@ +/****************************************************************************** + ** File Name: * + ** Author: * + ** DATE: * + ** Copyright: Spreatrum, Incoporated. All Rights Reserved. * + ** Description: * + ****************************************************************************** + + ****************************************************************************** + ** Edit History * + ** ------------------------------------------------------------------------- -* + ** DATE NAME DESCRIPTION * + ** * + ******************************************************************************/ + +/**---------------------------------------------------------------------------* + ** Dependencies * + **--------------------------------------------------------------------------- */ + +#ifndef STATIC +#include <linux/module.h> +#include <linux/kernel.h> +#endif + +#include <linux/interrupt.h> +#include <linux/lzo.h> +#include <linux/poll.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/io.h> + +#include "sprd_zipdec_drv.h" +//#include "lzodefs_hw.h" + +//#include <linux/spinlock_types.h> +#include <linux/sched.h> +#include <linux/atomic.h> +//#include <mach/sci.h> + + +u32 lzo1x_virt_to_phys(u32 virt_addr); + + +DEFINE_SPINLOCK(zipdec_lock); +static int _lzo1x_decompress_single(u32 src_addr , u32 src_num , u32 dst_addr , u32 *dst_len ) +{ + + u32 phy_src_addr,phy_dst_addr; + + *dst_len=0; + + phy_src_addr = lzo1x_virt_to_phys(src_addr); + phy_dst_addr = lzo1x_virt_to_phys(dst_addr); + + if((phy_src_addr==(-1UL))||(phy_dst_addr==(-1UL))){ + printk("lzo1x phy addr errors \n"); + return -1; + } + + spin_lock(&zipdec_lock); + ZipDec_SetSrcCfg(0 , phy_src_addr, src_num); + ZipDec_SetDestCfg(0, phy_dst_addr, ZIP_WORK_LENGTH); + +// dmac_flush_range((void *)(src_addr),(void *)(src_addr+src_num)); +// dmac_flush_range((void *)dst_addr,(void *)(dst_addr+ZIP_WORK_LENGTH)); + + ZipDec_Run(); + spin_unlock(&zipdec_lock); + + if(Zip_Dec_Wait_Pool(ZIPDEC_DONE_INT)) + { + return -1; + } + + *dst_len=ZIP_WORK_LENGTH; + return 0; +} + + + +int lzo1x_decompress_safe_hw(const unsigned char *src , size_t src_len , unsigned char *dst , size_t *dst_len) +{ + u32 dec_len; + + //uint32_t src_addr =(uint32_t)src; + //uint32_t dst_addr =(uint32_t)dst; + + if (!dst || !dst_len || !src || !src_len ||(src_len > PAGE_SIZE)) return LZO_HW_IN_PARA_ERROR; + //printk("lzo hw decompress\r\n"); + + //if(_lzo1x_decompress_single((u32)src_addr ,src_len , dst_addr ,&dec_len)) + if(_lzo1x_decompress_single((u32)src ,(u32)src_len ,(u32)dst ,&dec_len)) + { + *dst_len = dec_len; + ZipDec_Restart(); + return LZO_HW_ERROR; + } + *dst_len = ZIP_WORK_LENGTH; + return LZO_HW_OK; +} + + +EXPORT_SYMBOL_GPL(lzo1x_decompress_safe_hw); + diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h new file mode 100644 index 00000000..6710b83c --- /dev/null +++ b/lib/lzo/lzodefs.h @@ -0,0 +1,59 @@ +/* + * lzodefs.h -- architecture, OS and compiler specific defines + * + * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for Linux kernel use by: + * Nitin Gupta <nitingupta910@gmail.com> + * Richard Purdie <rpurdie@openedhand.com> + */ + + +#define COPY4(dst, src) \ + put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst)) +#if defined(__x86_64__) +#define COPY8(dst, src) \ + put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst)) +#else +#define COPY8(dst, src) \ + COPY4(dst, src); COPY4((dst) + 4, (src) + 4) +#endif + +#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +#error "conflicting endian definitions" +#elif defined(__x86_64__) +#define LZO_USE_CTZ64 1 +#define LZO_USE_CTZ32 1 +#elif defined(__i386__) || defined(__powerpc__) +#define LZO_USE_CTZ32 1 +#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5) +#define LZO_USE_CTZ32 1 +#endif + +#define M1_MAX_OFFSET 0x0400 +#define M2_MAX_OFFSET 0x0800 +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#define M2_MAX_LEN 8 +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#define lzo_dict_t unsigned short +#define D_BITS 13 +#define D_SIZE (1u << D_BITS) +#define D_MASK (D_SIZE - 1) +#define D_HIGH ((D_MASK >> 1) + 1) diff --git a/lib/lzo/sprd_zipdec_drv.c b/lib/lzo/sprd_zipdec_drv.c new file mode 100755 index 00000000..73768610 --- /dev/null +++ b/lib/lzo/sprd_zipdec_drv.c @@ -0,0 +1,238 @@ +/****************************************************************************** + ** File Name: xxx_test.c + ** Author: xxx + ** Date: 22/08/2001 + ** Copyright: 2001 Spreadtrum, Incorporated. All Rights Reserved. + ** Description: Module test entry template file. + ** + ** + ***************************************************************************** + ***************************************************************************** + ** Edit History + **--------------------------------------------------------------------------* + ** DATE NAME DESCRIPTION + ** 22/08/2001 xxx Create. + *****************************************************************************/ + + +/**---------------------------------------------------------------------------* + ** Dependencies * + **---------------------------------------------------------------------------*/ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/types.h> +#include <linux/io.h> +#include <linux/lzo.h> + +#include <soc/sprd/sci_glb_regs.h> +#include <soc/sprd/sci.h> +#include "sprd_zipdec_drv.h" + +unsigned long REGS_ZIPDEC_BASE = 0; + +void sprd_zipmatrix_reset(void) +{ + u32 i; + sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_RST),BIT_ZIP_MTX_SOFT_RST|BIT_ZIPDEC_SOFT_RST); + for(i=0;i<0x200;i++); + sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_RST),BIT_ZIP_MTX_SOFT_RST|BIT_ZIPDEC_SOFT_RST); +} + +void sprd_zipdec_reset(void) +{ + u32 i; + sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_RST),BIT_ZIPDEC_SOFT_RST); + for(i=0;i<0x200;i++); + sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_RST),BIT_ZIPDEC_SOFT_RST); +} + +void sprd_zipdec_enable(u32 enable) +{ + if(enable) + { + sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_EB),BIT_ZIPDEC_EB); + sci_glb_set(REG_GLB_SET(REG_AON_APB_APB_EB1),BIT_ZIP_EMC_EB); + } + else + { + sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_EB),BIT_ZIPDEC_EB); + //sci_glb_set(REG_GLB_CLR(REG_AON_APB_APB_EB1),BIT_ZIP_EMC_EB); + } +} + +void ZipDec_Run(void) +{ + u32 reg_val; + reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); + reg_val |= ZIPDEC_RUN; + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); +} + +void ZipDec_In_Out_SwtMode(u32 Inmode,u32 Outmode) +{ + u32 reg_val; + reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); + reg_val &= ~(ZIPDEC_IN_SWT_MASK|ZIPDEC_OUT_SWT_MASK); + reg_val |= (Inmode<<ZIPDEC_IN_SWT_SHIFT | Outmode<<ZIPDEC_OUT_SWT_SHIFT); + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); +} + +void ZipDec_QueueEnable(u32 enable) +{ + u32 reg_val; + reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); + reg_val = enable ? (reg_val|ZIPDEC_QUEUE_EN): (reg_val&~ZIPDEC_QUEUE_EN); + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); +} + +void ZipDec_QueueLength(u32 length) +{ + u32 reg_val; + reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); + reg_val &= ~ZIPDEC_QUEUE_LEN_MASK; + reg_val |= length <<ZIPDEC_QUEUE_LEN_SHIFT; + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); +} + +void ZipDec_Set_Timeout(u32 timeout) +{ + __raw_writel(timeout,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_TIME_OUT)); +} + +void ZipDec_SetSrcCfg(u32 num,unsigned long src_start_addr, u32 src_len) +{ + __raw_writel(src_start_addr,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_IN_ADDR+4*num)); + __raw_writel(src_len,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_IN_LEN+4*num)); +} + +void ZipDec_SetDestCfg(u32 num,unsigned long dest_start_addr,u32 dst_len) +{ + __raw_writel(dest_start_addr,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_OUT_ADDR+4*num)); + __raw_writel(dst_len,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_OUT_LEN+4*num)); +} + +void ZipDec_Restart(void) +{ + sprd_zipdec_enable(0); + udelay(100); + sprd_zipdec_enable(1); + sprd_zipdec_reset(); + __raw_writel(ZIPDEC_EN,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); +} + +int Zip_Dec_Wait_Pool(ZIPDEC_INT_TYPE num) +{ + + u32 int_sts; + while (1) + { + int_sts = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_RAW)); + + if(int_sts&(0x1<<ZIPDEC_TIMEOUT_INT)) + { + __raw_writel(0xFF,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_CLR)); + //printk("zip dec timeout: 0x%x \n", int_sts); + //printk("ZIPDEC_STS0:0x%x\n",CHIP_REG_GET(ZIPDEC_STS0)); + //printk("ZIPDEC_STS1:0x%x\n",CHIP_REG_GET(ZIPDEC_STS1)); + //printk("ZIPDEC_STS2:0x%x\n",CHIP_REG_GET(ZIPDEC_STS2)); + //printk("ZIPDEC_STS3:0x%x\n",CHIP_REG_GET(ZIPDEC_STS3)); + //printk("ZIPDEC_STS4:0x%x\n",CHIP_REG_GET(ZIPDEC_STS4)); + return -1; + } + if(int_sts&0x1e) + { + __raw_writel(0xFF,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_CLR)); + //printk("zip dec err: 0x%x \n", int_sts); + //printk("ZIPDEC_STS0:0x%x\n",CHIP_REG_GET(ZIPDEC_STS0)); + //printk("ZIPDEC_STS1:0x%x\n",CHIP_REG_GET(ZIPDEC_STS1)); + //printk("ZIPDEC_STS2:0x%x\n",CHIP_REG_GET(ZIPDEC_STS2)); + //printk("ZIPDEC_STS3:0x%x\n",CHIP_REG_GET(ZIPDEC_STS3)); + //printk("ZIPDEC_STS4:0x%x\n",CHIP_REG_GET(ZIPDEC_STS4)); + return -1; + } + if(int_sts&(0x1<<num)) + { + __raw_writel(0xFF,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_CLR)); + break; + } + } + return 0; +} + +static int __init sprd_zipdec_probe(struct platform_device *pdev) +{ + struct resource *regs; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "zipdec get io resource failed!\n"); + return -ENODEV; + } + + REGS_ZIPDEC_BASE = (unsigned long)ioremap_nocache(regs->start,resource_size(regs)); + if (!REGS_ZIPDEC_BASE){ + dev_err(&pdev->dev, "zipdec get base address failed!\n"); + return -ENODEV; + } + + //dev_info(&pdev->dev, "probe zipdec get regbase 0x%lx\n",REGS_ZIPDEC_BASE); +#if 0 + irq_num = platform_get_irq(pdev, 0); + if (irq_num < 0) { + dev_err(&pdev->dev, "zipdec get irq resource failed!\n"); + return irq_num; + } + dev_info(&pdev->dev, "probe zipdec get irq num %d\n",irq_num); +#endif + sprd_zipdec_enable(1); // global enable dec + + sprd_zipdec_reset(); + + __raw_writel(ZIPDEC_EN,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL)); + + return 0; +} + +static void sprd_zipdec_remove(void) +{ + sprd_zipdec_enable(0); +} + +static const struct of_device_id sprd_zipdec_of_match[] = { + { .compatible = "sprd,sprd-zipdec", }, + { /* sentinel */ } +}; + +static struct platform_driver sprd_zipdec_driver = { + .driver = { + .name = "sprd zipdec", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sprd_zipdec_of_match), + }, + .probe = sprd_zipdec_probe, + .remove = __exit_p(sprd_zipdec_remove), +}; + +static int __init sprd_zipdec_init(void) +{ + return platform_driver_register(&sprd_zipdec_driver); +} +subsys_initcall(sprd_zipdec_init); + +static void __exit sprd_zipdec_exit(void) +{ + platform_driver_unregister(&sprd_zipdec_driver); +} +module_exit(sprd_zipdec_exit); + +MODULE_DESCRIPTION("SpreadTrum ZIPDEC Controller driver"); +MODULE_AUTHOR("SPRD"); +MODULE_LICENSE("GPL"); diff --git a/lib/lzo/sprd_zipdec_drv.h b/lib/lzo/sprd_zipdec_drv.h new file mode 100755 index 00000000..d6e0dff7 --- /dev/null +++ b/lib/lzo/sprd_zipdec_drv.h @@ -0,0 +1,147 @@ +/****************************************************************************** + ** File Name: + ** Author: + ** Date: + ** Copyright: + ** Description: + ** + ** + ***************************************************************************** + ***************************************************************************** + ** Edit History + **--------------------------------------------------------------------------* + ** DATE NAME DESCRIPTION + ** 22/08/2001 xxx Create. + *****************************************************************************/ + + +/**---------------------------------------------------------------------------* + ** Dependencies * + **---------------------------------------------------------------------------*/ +#ifndef __SPRD_ZIP_DEC_H__ +#define __SPRD_ZIP_DEC_H__ + +#include <linux/bitops.h> + +#define ZIPDEC_CTRL (0x0000) +#define ZIPDEC_INT_EN (0x0004) +#define ZIPDEC_INT_CLR (0x0008) +#define ZIPDEC_INT_STS (0x000C) + +#define ZIPDEC_INT_RAW (0x0010) +#define ZIPDEC_STS0 (0x0014) +#define ZIPDEC_STS1 (0x0018) +#define ZIPDEC_STS2 (0x001C) + +#define ZIPDEC_STS3 (0x0020) +#define ZIPDEC_STS4 (0x0024) + +#define ZIPDEC_IN_ADDR (0x0040) +#define ZIPDEC_IN_ADDR1 (0x0044) +#define ZIPDEC_IN_ADDR2 (0x0048) +#define ZIPDEC_IN_ADDR3 (0x004C) + +#define ZIPDEC_IN_ADDR4 (0x0050) +#define ZIPDEC_IN_ADDR5 (0x0054) +#define ZIPDEC_IN_ADDR6 (0x0058) +#define ZIPDEC_IN_ADDR7 (0x005C) + +#define ZIPDEC_IN_LEN (0x0060) +#define ZIPDEC_IN_LEN1 (0x0064) +#define ZIPDEC_IN_LEN2 (0x0068) +#define ZIPDEC_IN_LEN3 (0x006C) + +#define ZIPDEC_IN_LEN4 (0x0070) +#define ZIPDEC_IN_LEN5 (0x0074) +#define ZIPDEC_IN_LEN6 (0x0078) +#define ZIPDEC_IN_LEN7 (0x007C) + +#define ZIPDEC_OUT_ADDR (0x0080) +#define ZIPDEC_OUT_ADDR1 (0x0084) +#define ZIPDEC_OUT_ADDR2 (0x0088) +#define ZIPDEC_OUT_ADDR3 (0x008C) + +#define ZIPDEC_OUT_ADDR4 (0x0090) +#define ZIPDEC_OUT_ADDR5 (0x0094) +#define ZIPDEC_OUT_ADDR6 (0x0098) +#define ZIPDEC_OUT_ADDR7 (0x009C) + +#define ZIPDEC_OUT_LEN (0x00A0) +#define ZIPDEC_OUT_LEN1 (0x00A4) +#define ZIPDEC_OUT_LEN2 (0x00A8) +#define ZIPDEC_OUT_LEN3 (0x00AC) + +#define ZIPDEC_OUT_LEN4 (0x00B0) +#define ZIPDEC_OUT_LEN5 (0x00B4) +#define ZIPDEC_OUT_LEN6 (0x00B8) +#define ZIPDEC_OUT_LEN7 (0x00BC) +#define ZIPDEC_TIME_OUT (0x00C0) + +#define ZIPDEC_EN BIT(0) +#define ZIPDEC_QUEUE_EN BIT(3) +#define ZIPDEC_RUN BIT(4) + +#define ZIPDEC_IN_SWT_SHIFT (8) +#define ZIPDEC_IN_SWT_MASK (0x03<<ZIPDEC_IN_SWT_SHIFT) + +#define ZIPDEC_OUT_SWT_SHIFT (10) +#define ZIPDEC_OUT_SWT_MASK (0x03<<ZIPDEC_OUT_SWT_SHIFT) + +#define ZIPDEC_QUEUE_LEN_SHIFT (16) +#define ZIPDEC_QUEUE_LEN_MASK (0x07<<ZIPDEC_QUEUE_LEN_SHIFT) + +#define ZIPDEC_DONE_EN BIT(0) +#define ZIPDEC_QUEUE_DONE_EN BIT(1) +#define ZIPDEC_ERR_EN BIT(2) +#define ZIPDEC_LEN_ERR_EN BIT(5) +#define ZIPDEC_SAVE_LEN_ERR_EN BIT(4) +#define ZIPDEC_FETCH_LEN_ERR_EN BIT(3) +#define ZIPDEC_TIMEOUT_EN BIT(6) + +#define ZIPDEC_DONE_CLR BIT(0) +#define ZIPDEC_QUEUE_DONE_CLR BIT(1) +#define ZIPDEC_ERR_CLR BIT(2) +#define ZIPDEC_LEN_ERR_CLR BIT(5) +#define ZIPDEC_SAVE_LEN_ERR_CLR BIT(4) +#define ZIPDEC_FETCH_LEN_ERR_CLR BIT(3) +#define ZIPDEC_TIMEOUT_CLR BIT(6) + +#define ZIPDEC_SWITCH_MODE0 0 +#define ZIPDEC_SWITCH_MODE1 1 +#define ZIPDEC_SWITCH_MODE2 2 +#define ZIPDEC_SWITCH_MODE3 3 + +#define ZIPDEC_WAIT_POOL 0 +#define ZIPDEC_WAIT_INT 1 + +#define ZIPDEC_NORMAL 0 +#define ZIPDEC_QUEUE 1 + +#define ZIP_WORK_LENGTH (0x1000) + +typedef enum ZIPDEC_INT_TYPE +{ + ZIPDEC_DONE_INT = 0, + ZIPDEC_QUEUE_DONE_INT, + ZIPDEC_ERR_INT, + ZIPDEC_LEN_ERR_INT, + ZIPDEC_SAVE_LEN_ERR_INT, + ZIPDEC_FETCH_LEN_ERR_INT, + ZIPDEC_TIMEOUT_INT, + ZIPDEC_ALL_INT +}ZIPDEC_INT_TYPE; + +void sprd_zipmatrix_reset(void); +void sprd_zipdec_enable(u32 enable); +void sprd_zipdec_reset(void); +void ZipDec_Run(void); +void ZipDec_Queue_Enable(u32 enable); +void ZipDec_SetSrcCfg(u32 num,unsigned long src_start_addr, u32 src_len); +void ZipDec_SetDestCfg(u32 num,unsigned long dest_start_addr,u32 dst_len); +void ZipDec_In_Out_SwtMode(u32 inmode,u32 outmode); +void ZipDec_QueueEn(u32 enable); +void ZipDec_QueueLength(u32 length); +void ZipDec_Set_Timeout(u32 time); +int Zip_Dec_Wait_Pool(ZIPDEC_INT_TYPE num); +void ZipDec_Restart(void); +#endif diff --git a/lib/lzo/sprd_zipenc_drv.c b/lib/lzo/sprd_zipenc_drv.c new file mode 100755 index 00000000..d52e43e0 --- /dev/null +++ b/lib/lzo/sprd_zipenc_drv.c @@ -0,0 +1,246 @@ +/****************************************************************************** + ** File Name: xxx_test.c + ** Author: xxx + ** Date: 22/08/2001 + ** Copyright: 2001 Spreadtrum, Incorporated. All Rights Reserved. + ** Description: Module test entry template file. + ** + ** + ***************************************************************************** + ***************************************************************************** + ** Edit History + **--------------------------------------------------------------------------* + ** DATE NAME DESCRIPTION + ** 22/08/2001 xxx Create. + *****************************************************************************/ + + +/**---------------------------------------------------------------------------* + ** Dependencies * + **---------------------------------------------------------------------------*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/types.h> +#include <linux/io.h> +#include <linux/lzo.h> +#include <soc/sprd/sci_glb_regs.h> +#include <soc/sprd/sci.h> + +#include "sprd_zipenc_drv.h" + +unsigned long REGS_ZIPENC_BASE=0; + +void sprd_zipenc_reset(void) +{ + u32 i; + sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_RST),BIT_ZIPENC_SOFT_RST); + for(i=0;i<0x200;i++); + sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_RST),BIT_ZIPENC_SOFT_RST); +} + +void sprd_zipenc_enable(int enable) +{ + if(enable) + { + sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_EB),BIT_ZIPENC_EB); + sci_glb_set(REG_GLB_SET(REG_AON_APB_APB_EB1),BIT_ZIP_EMC_EB); + } + else + { + sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_EB),BIT_ZIPENC_EB); + } +} + +void ZipEnc_LengthLimitMode(u32 enable) +{ + u32 reg_val; + reg_val=__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); + reg_val= enable ? (reg_val|ZIPENC_MODE) : (reg_val&~ZIPENC_MODE); + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); +} + +void ZipEnc_Run(void) +{ + u32 reg_val; + reg_val = __raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); + reg_val |= ZIPENC_RUN; + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); +} + +void ZipEnc_SetSrcCfg(unsigned long src_start_addr, u32 src_len) +{ + __raw_writel(src_start_addr,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_IN_ADDR)); + __raw_writel(src_len,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_IN_LEN)); +} + +void ZipEnc_SetDestCfg(unsigned long dest_start_addr,u32 dst_len) +{ + __raw_writel(dest_start_addr,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_OUT_ADDR)); + __raw_writel(dst_len,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_OUT_LEN)); +} + + +void ZipEnc_In_Out_SwtMode(u32 inmode ,u32 outmode) +{ + u32 reg_val; + reg_val = __raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); + reg_val &= ~(ZIPENC_IN_SWT_MASK | ZIPENC_OUT_SWT_MASK); + reg_val |= (inmode<<ZIPENC_IN_SWT_SHIFT | outmode<<ZIPENC_OUT_SWT_SHIFT); + __raw_writel(reg_val,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); +} + +void ZipEnc_InQueue_Clr(void) +{ + __raw_writel(ZIPENC_IN_QUEUE,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_IN_QUEUE_CLR)); +} + +void ZipEnc_OutQueue_Clr(void) +{ + __raw_writel(ZIPENC_OUT_QUEUE,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_OUT_QUEUE_CLR)); +} + +u32 ZipEnc_Get_Comp_Len(void) +{ + return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_COMP_LEN))&ZIPENC_COMP_LEN_MASK); +} + +u32 ZipEnc_Get_Ol_Sts(void) +{ + return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_COMP_STS))>>ZIPENC_OL_STS_SHIFT); +} + +u32 ZipEnc_Get_Err_Sts(void) +{ + return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_COMP_STS))&ZIPENC_ERR_STS_MASK); +} + +void ZipEnc_Set_Timeout(u32 timeout) +{ + __raw_writel(timeout<<ZIPENC_TIME_OUT_NUM_SHIFT,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_TIME_OUT)); +} + +u32 ZipEnc_Get_Timeout_Flag(void) +{ + return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_TIME_OUT))>>ZIPENC_TIME_OUT_FLAG_SHIFT); +} + +void ZipEnc_Restart(void) +{ + sprd_zipenc_enable(0); + udelay(100); + + sprd_zipenc_enable(1); // global enable dec + sprd_zipenc_reset(); + + __raw_writel(ZIPENC_EN,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); + ZipEnc_In_Out_SwtMode(ZIPENC_SWITCH_MODE1,ZIPENC_SWITCH_MODE1); + + ZipEnc_InQueue_Clr(); + ZipEnc_OutQueue_Clr(); +} + +int Zip_Enc_Wait_Pool(ZIPENC_INT_TYPE num) +{ + u32 int_sts; + while (1) + { + int_sts = __raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_INT_RAW)); + + if(int_sts&(0x1<<num)) + { + __raw_writel(ZIPENC_DONE_CLR|ZIPENC_SEG_DONE_CLR|ZIPENC_TIMEOUT_CLR,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_INT_CLR)); + break; + } + if(int_sts&(0x1<<ZIPENC_TIMEOUT_INT)) + { + __raw_writel(ZIPENC_DONE_CLR|ZIPENC_SEG_DONE_CLR|ZIPENC_TIMEOUT_CLR,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_INT_CLR)); + printk("zip enc timeout:0x%x\n",int_sts); + return -1; + } + } + return 0; +} +static int __init sprd_zipenc_probe(struct platform_device *pdev) +{ + struct resource *regs; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "zipenc get io resource failed!\n"); + return -ENODEV; + } + + REGS_ZIPENC_BASE = (unsigned long)ioremap_nocache(regs->start,resource_size(regs)); + if (!REGS_ZIPENC_BASE){ + dev_err(&pdev->dev, "zipenc get base address failed!\n"); + return -ENODEV; + } + + //dev_info(&pdev->dev, "probe zipenc get regbase 0x%lx\n",REGS_ZIPENC_BASE); + +#if 0 + irq_num = platform_get_irq(pdev, 0); + if (irq_num < 0) { + dev_err(&pdev->dev, "zipenc get irq resource failed!\n"); + return irq_num; + } + dev_info(&pdev->dev, "probe zipenc get irq num %d\n",irq_num); +#endif + sprd_zipenc_enable(1); // global enable dec + + sprd_zipenc_reset(); + + __raw_writel(ZIPENC_EN,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL)); + + ZipEnc_In_Out_SwtMode(ZIPENC_SWITCH_MODE1,ZIPENC_SWITCH_MODE1); + + ZipEnc_InQueue_Clr(); + + ZipEnc_OutQueue_Clr(); + + return 0; +} + +static void sprd_zipenc_remove(void) +{ + sprd_zipenc_enable(0); +} +static const struct of_device_id sprd_zipenc_of_match[] = { + { .compatible = "sprd,sprd-zipenc", }, + { /* sentinel */ } +}; + +static struct platform_driver sprd_zipenc_driver = { + .driver = { + .name = "sprd zipenc", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sprd_zipenc_of_match), + }, + .probe = sprd_zipenc_probe, + .remove = __exit_p(sprd_zipenc_remove), +}; + +static int __init sprd_zipenc_init(void) +{ + return platform_driver_register(&sprd_zipenc_driver); +} +subsys_initcall(sprd_zipenc_init); + +static void __exit sprd_zipenc_exit(void) +{ + platform_driver_unregister(&sprd_zipenc_driver); +} +module_exit(sprd_zipenc_exit); + +MODULE_DESCRIPTION("SpreadTrum ZIPENC Controller driver"); +MODULE_AUTHOR("SPRD"); +MODULE_LICENSE("GPL"); diff --git a/lib/lzo/sprd_zipenc_drv.h b/lib/lzo/sprd_zipenc_drv.h new file mode 100755 index 00000000..ae5bf168 --- /dev/null +++ b/lib/lzo/sprd_zipenc_drv.h @@ -0,0 +1,136 @@ +/****************************************************************************** + ** File Name: + ** Author: + ** Date: + ** Copyright: + ** Description: + ** + ** + ***************************************************************************** + ***************************************************************************** + ** Edit History + **--------------------------------------------------------------------------* + ** DATE NAME DESCRIPTION + ** 22/08/2001 xxx Create. + *****************************************************************************/ + + +/**---------------------------------------------------------------------------* + ** Dependencies * + **---------------------------------------------------------------------------*/ +#ifndef __SPRD_ZIP_ENC_H__ +#define __SPRD_ZIP_ENC_H__ + +#include <linux/bitops.h> + +#define ZIPENC_CTRL (0x0000) +#define ZIPENC_IN_ADDR (0x0004) +#define ZIPENC_IN_LEN (0x0008) +#define ZIPENC_OUT_ADDR (0x000c) + +#define ZIPENC_OUT_LEN (0x0010) +#define ZIPENC_CUR_IN_ADDR (0x0014) +#define ZIPENC_CUR_IN_LEN (0x0018) +#define ZIPENC_CUR_OUT_ADDR (0x001c) + +#define ZIPENC_CUR_OUT_LEN (0x0020) +#define ZIPENC_IN_QUEUE (0x0024) +#define ZIPENC_OUT_QUEUE (0x0028) +#define ZIPENC_COMP_LEN (0x002c) + +#define ZIPENC_COMP_STS (0x0030) +#define ZIPENC_STS0 (0x0034) +#define ZIPENC_STS1 (0x0038) +#define ZIPENC_STS2 (0x003C) + +#define ZIPENC_INT_EN (0x0040) +#define ZIPENC_INT_CLR (0x0044) +#define ZIPENC_INT_STS (0x0048) +#define ZIPENC_INT_RAW (0x004c) + +#define ZIPENC_IN_ADDRX (0x0050) +#define ZIPENC_IN_LENX (0x0054) +#define ZIPENC_OUT_ADDRX (0x0058) +#define ZIPENC_OUT_LENX (0x005c) +#define ZIPENC_TIME_OUT (0x0060) + + +#define ZIPENC_EN BIT(0) +#define ZIPENC_MODE BIT(1) +#define ZIPENC_RUN BIT(4) + +#define ZIPENC_IN_SWT_SHIFT (8) +#define ZIPENC_IN_SWT_MASK (0x03<<ZIPENC_IN_SWT_SHIFT) + +#define ZIPENC_OUT_SWT_SHIFT (10) +#define ZIPENC_OUT_SWT_MASK (0x03<<ZIPENC_OUT_SWT_SHIFT) + +#define ZIPENC_COMP_LEN_SHIFT (0) +#define ZIPENC_COMP_LEN_MASK (0x1ffff<<ZIPENC_COMP_LEN_SHIFT) + +#define ZIPENC_ERR_STS_SHIFT (0) +#define ZIPENC_ERR_STS_MASK (0xff<<ZIPENC_ERR_STS_SHIFT) + +#define ZIPENC_OL_STS_SHIFT (8) +#define ZIPENC_OL_STS_MASK (0xff<<ZIPENC_OL_STS_SHIFT) + + +#define ZIPENC_TIME_OUT_NUM_SHIFT (0) +#define ZIPENC_TIME_OUT_NUM_MASK (0x00ffffff<<ZIPENC_TIME_OUT_NUM_SHIFT) + +#define ZIPENC_TIME_OUT_FLAG_SHIFT (24) +#define ZIPENC_TIME_OUT_FLAG_MASK (0x00ffffff<<ZIPENC_TIME_OUT_FLAG_SHIFT) + + +#define ZIPENC_IN_QUEUE_CLR BIT(15) +#define ZIPENC_OUT_QUEUE_CLR BIT(15) + +#define ZIPENC_TIMEOUT_EN BIT(2) +#define ZIPENC_SEG_DONE_EN BIT(1) +#define ZIPENC_DONE_EN BIT(0) + +#define ZIPENC_TIMEOUT_CLR BIT(2) +#define ZIPENC_SEG_DONE_CLR BIT(1) +#define ZIPENC_DONE_CLR BIT(0) + +#define ZIPENC_NORMAL_LEN 0 +#define ZIPENC_LIMIT_LEN 1 + +#define ZIPENC_SWITCH_MODE0 0 +#define ZIPENC_SWITCH_MODE1 1 +#define ZIPENC_SWITCH_MODE2 2 +#define ZIPENC_SWITCH_MODE3 3 + +#define ZIPENC_WAIT_POOL 0 +#define ZIPENC_WAIT_INT 1 + +#define ZIPENC_NORMAL 0 +#define ZIPENC_QUEUE 1 + +#define ZIP_WORK_LENGTH (0x1000) + +typedef enum ZIPENC_INT_TYPE +{ + ZIPENC_DONE_INT = 0, + ZIPENC_SEG_DONE_INT, + ZIPENC_TIMEOUT_INT, + ZIPENC_ALL_INT +}ZIPENC_INT_TYPE; + +//void sprd_zipenc_enable(u32 enable); +void sped_zipenc_reset(void); +void ZipEnc_Restart(void); +int Zip_Enc_Wait_Pool(ZIPENC_INT_TYPE num); +void ZipEnc_Run(void); +void ZipEnc_LengthLimitMode(u32 enable); +void ZipEnc_SetSrcCfg(unsigned long src_start_addr, u32 src_len); +void ZipEnc_SetDestCfg(unsigned long dest_start_addr,u32 dst_len); +void ZipEnc_In_Out_SwtMode(u32 inmode,u32 outmode); +void ZipEnc_InQueue_Clr(void); +void ZipEnc_OutQueue_Clr(void); +void ZipEnc_Set_Timeout(u32 time); +u32 ZipEnc_Get_Comp_Len(void); +u32 ZipEnc_Get_Ol_Sts(void); +u32 ZipEnc_Get_Err_Sts(void); +u32 ZipEnc_Get_Timeout_Flag(void); +#endif |
