GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
obj-y += hw_decompress.o
@@ -0,0 +1,5 @@
/*
* Copyright (c) LOTUS. All rights reserved.
*/
#include "hw_decompress_v1.c"
@@ -0,0 +1,330 @@
/*
* Copyright (c) LOTUS. All rights reserved.
*/
#include "hw_decompress_v1.h"
#include <linux/lotus/hw_decompress.h>
#include <asm/io.h>
#ifndef error
#define error(fmt, args...) do { \
printf("ERROR: " pr_fmt(fmt) "\nat %s:%d/%s()\n", \
##args, __FILE__, __LINE__, __func__); \
} while (0)
#include <common.h>
#endif
#include <compiler.h>
#if (defined CONFIG_TARGET_XMFALCON)
#include "hw_decompress_xmfalcon.c"
#elif (defined CONFIG_TARGET_XMORCA)
#include "hw_decompress_xmorca.c"
#endif
unsigned int hw_dec_type;
unsigned int hw_dec_sop;
unsigned int hw_dec_eop;
unsigned int hw_dec_cur_blk;
unsigned int hw_blk_total_num;
void hw_dec_sop_eop_first_set(int block_num)
{
if (block_num == 1) {
hw_dec_sop = 1;
hw_dec_eop = 1;
} else {
hw_dec_sop = 1;
hw_dec_eop = 0;
}
hw_dec_cur_blk = 0;
hw_blk_total_num = block_num;
}
static inline void hw_dec_work_en_set(int work_en_flg)
{
/* Enable the emar */
writel(work_en_flg, HW_DEC_REG_BASE_ADDR + EAMR_WORK_EN_REG_OFST);
}
static inline void hw_dec_rtn_baddr_set(unsigned int addr)
{
writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_BADDR);
}
static inline void hw_dec_dprs_data_baddr_set(unsigned int addr)
{
writel(addr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_BADDR);
}
static inline void hw_dec_data_rtn_len_set(unsigned int len)
{
writel(len, HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_LEN);
}
static inline void hw_dec_dprs_data_len_set(unsigned int len)
{
writel(len, HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_LEN);
}
static inline void hw_dec_crc_check_en(unsigned int crc_en)
{
writel(crc_en, HW_DEC_REG_BASE_ADDR + CRC_CHECK_EN);
}
static inline void hw_dec_data_crc32_set(unsigned int crc32)
{
writel(crc32, HW_DEC_REG_BASE_ADDR + DPRS_DATA_CRC32);
}
static inline unsigned int hw_dec_buf_status_get(void)
{
return readl(HW_DEC_REG_BASE_ADDR + BUF_INFO);
}
static inline unsigned int hw_dec_dprs_rtn_status_get(void)
{
return readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_INFO);
}
static inline void hw_dec_buf_status_clr(void)
{
writel(0x1, HW_DEC_REG_BASE_ADDR + BUF_INFO_CLR);
}
static inline void hw_dec_dprs_rtn_status_clr(void)
{
writel(0x1, HW_DEC_REG_BASE_ADDR + RLT_INFO_CLR);
}
static void hw_dec_intr_en_set(int blk_intr_en, int task_intr_en)
{
u_intr_en intr_en;
intr_en.bits.task_intrpt_en = task_intr_en;
intr_en.bits.block_intrpt_en = blk_intr_en;
writel(intr_en.u32, HW_DEC_REG_BASE_ADDR + INT_EN_REG_ADDR);
}
static inline unsigned int hw_dec_intr_status_get(void)
{
return readl(HW_DEC_REG_BASE_ADDR + INT_STATUS_REG_ADDR);
}
static void hw_dec_block_intr_status_clr(void)
{
u_intr_clr intr_clr;
intr_clr.u32 = readl(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
intr_clr.bits.block_intrpt_clr = 0x1;
writel(intr_clr.u32, HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
}
static void hw_dec_task_intr_status_clr(void)
{
u_intr_clr intr_clr;
intr_clr.u32 = readl(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
intr_clr.bits.task_intrpt_clr = 0x1;
writel(intr_clr.u32, HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR);
}
int hw_dec_intr_proc(int irq, const void *para)
{
u_buf_status buf_status;
u_intr_status intr_status;
u_dprs_rtn_status dprs_status;
int ret = 0;
intr_status.u32 = hw_dec_intr_status_get();
if (intr_status.bits.block_intrpt) {
buf_status.u32 = hw_dec_buf_status_get();
if (buf_status.bits.aval_flg)
hw_dec_buf_status_clr();
hw_dec_block_intr_status_clr();
}
if (intr_status.bits.task_intrpt) {
dprs_status.u32 = hw_dec_dprs_rtn_status_get();
if (dprs_status.bits.aval_flg) {
if (dprs_status.bits.err_info)
ret = -2; /* -2:failed */
hw_dec_dprs_rtn_status_clr();
}
hw_dec_task_intr_status_clr();
goto out;
}
ret = -1;
out:
return ret;
}
void 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)
{
unsigned int val;
if (hw_dec_sop) {
if (!dec_type) {
/* set the parameters of output buffer */
hw_dec_rtn_baddr_set(dst_baddr);
hw_dec_data_rtn_len_set(dst_len);
} else {
/* set the parameter of output buffer */
hw_dec_dprs_data_baddr_set(dst_baddr);
hw_dec_dprs_data_len_set(page_nr(dst_len) * 4); /* 4:Align */
}
}
/* set the parameter of input buffer */
writel(src_baddr, HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_BADDR);
val = src_len |
(hw_dec_eop << 28) | (hw_dec_sop << 29) | (!dec_type << 31); /* 28,29,31 Move Left bit */
writel(val, HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_LEN);
hw_dec_crc_check_en(crc_en);
}
static inline void delay(unsigned int num)
{
volatile unsigned int i;
for (i = 0; i < (100 * num); i++) /* 100: Cycle */
__asm__ __volatile__("nop");
}
int hw_dec_wait_finish(void)
{
int ret;
int times = 0;
do {
ret = hw_dec_intr_proc(HW_DEC_INTR, NULL);
times++;
if (times > 2000000) { /* 2000000 ms */
error("hardware decompress overtime!\n");
break;
}
delay(1);
} while (-1 == ret);
return ret;
}
int hw_dec_decompress(const unsigned char *dst, int* const dstlen,
const unsigned char *src, int srclen,
const void *unused)
{
int ret;
hw_dec_sop_eop_first_set(1);
if (dstlen == NULL)
return -1;
hw_dec_start((unsigned int)(uintptr_t)src, (unsigned int)(uintptr_t)dst,
srclen, *dstlen, 1, 0, hw_dec_type);
ret = hw_dec_wait_finish();
*dstlen = readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_LEN);
if (ret)
return -1;
return 0;
}
static int set_sop_and_eop(hw_decompress_op_type op_type)
{
if (op_type == HW_DECOMPRESS_OP_START) {
hw_dec_sop = 1;
hw_dec_eop = 0;
} else if (op_type == HW_DECOMPRESS_OP_CONTINUE) {
hw_dec_sop = 0;
hw_dec_eop = 0;
} else if (op_type == HW_DECOMPRESS_OP_END) {
hw_dec_sop = 0;
hw_dec_eop = 1;
} else if (op_type == HW_DECOMPRESS_OP_ONCE) {
hw_dec_sop = 1;
hw_dec_eop = 1;
} else {
return -1;
}
return 0;
}
/*
* Support decompressing gzip file by sections
*/
int hw_dec_decompress_ex(hw_decompress_op_type op_type, const unsigned char *dst,
unsigned int *dstlen, const unsigned char *src, unsigned int srclen)
{
if ((dst == NULL) || (src == NULL) || (dstlen == NULL)) {
return -1;
}
if ((*dstlen == 0) || (srclen == 0)) {
return -1;
}
int ret = set_sop_and_eop(op_type);
if (ret != 0) {
return -1;
}
hw_dec_type = 0;
const unsigned int crc_en = 1;
hw_dec_start((unsigned int)(uintptr_t)src, (unsigned int)(uintptr_t)dst,
srclen, *dstlen, crc_en, 0, hw_dec_type);
if ((op_type == HW_DECOMPRESS_OP_END) || (op_type == HW_DECOMPRESS_OP_ONCE)) {
ret = hw_dec_wait_finish();
*dstlen = readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_LEN);
if (ret != 0) {
return ret;
}
}
return 0;
}
void hw_dec_init(void)
{
/* enable decompress clock */
enable_decompress_clock();
/* Init the emar interface */
writel(0, HW_DEC_REG_BASE_ADDR + EAMR_RID_REG_OFST);
writel(0x3, HW_DEC_REG_BASE_ADDR + EAMR_ROSD_REG_OFST);
writel(0, HW_DEC_REG_BASE_ADDR + EAMR_WID_REG_OFST);
writel(0x3, HW_DEC_REG_BASE_ADDR + EAMR_WOSD_REG_OFST);
/* Enable interrupt */
hw_dec_intr_en_set(0x1, 0x1);
/* Enable emar */
hw_dec_work_en_set(0x1);
}
void hw_dec_uinit(void)
{
hw_dec_work_en_set(0x0);
hw_dec_intr_en_set(0x0, 0x0);
/* disable decompress clock */
disable_decompress_clock();
}
@@ -0,0 +1,129 @@
/*
* Copyright (c) LOTUS. All rights reserved.
*/
#ifndef HW_DECOMPRESS_V1_H
#define HW_DECOMPRESS_V1_H
#include <asm/arch/platform.h>
#define PAGE_SIZE 4096
#define page_nr(x) (((x) + PAGE_SIZE - 1) / PAGE_SIZE)
/* The base address for emar */
#define HW_DEC_REG_BASE_ADDR (GZIP_REG_BASE)
/* The global init registers for emar interface */
#define EAMR_RID_REG_OFST 0x0110UL
#define EAMR_ROSD_REG_OFST 0x0114UL
#define EAMR_WID_REG_OFST 0x0128UL
#define EAMR_WOSD_REG_OFST 0x012CUL
/* The enable register */
#define EAMR_WORK_EN_REG_OFST 0x0118UL
#define DPRS_DATA_SRC_BADDR 0x2058UL
#define DPRS_DATA_SRC_LEN 0x205CUL
/* Decompress parameter reigsters for page address */
#define DPRS_DATA_RTN_BADDR 0x2038UL
#define DPRS_DATA_RTN_LEN 0x203CUL
/* Decompress parameter registers for page data */
#define DPRS_DATA_INFO_BADDR 0x2030UL
#define DPRS_DATA_INFO_LEN 0x2034UL
#define DPRS_DATA_CRC32 0x2040UL
#define CRC_CHECK_EN 0x4018UL
/* The status registers */
#define BUF_INFO 0x2098UL
#define DPRS_RTN_INFO 0x209CUL
#define DPRS_RTN_LEN 0x2090UL
#define BUF_INFO_CLR 0x20A8UL
#define RLT_INFO_CLR 0x20ACUL
/* The intr registers */
#define INT_EN_REG_ADDR 0x0130UL
#define INT_STATUS_REG_ADDR 0x013CUL
#define INT_CLEAR_REG_ADDR 0x0148UL
#define TASK_MODE_REG 0x214CUL
/* Define the union u_dprs_data_buf_info */
typedef union {
/* Define the struct bits */
struct {
unsigned int buf_len : 24; /* [23..0] */
unsigned int buf_id : 2; /* [25..24] */
unsigned int reserved_1 : 2; /* [27..26] */
unsigned int eop : 1; /* [28] */
unsigned int sop : 1; /* [29] */
unsigned int reserved_0 : 1; /* [30] */
unsigned int mode : 1; /* [31] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_dprs_data_buf_info;
typedef union {
struct {
unsigned int buf_id : 2; /* [1:0] */
unsigned int rsv : 29; /* [30:2] */
unsigned int aval_flg : 1; /* [31] */
} bits;
unsigned int u32;
} u_buf_status;
typedef union {
struct {
unsigned int err_info : 8; /* [7:0] */
unsigned int rsv : 23; /* [30:8] */
unsigned int aval_flg : 1; /* [31] */
} bits;
unsigned int u32;
} u_dprs_rtn_status;
/* Define the union U_INT_EN */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 10;
unsigned int block_intrpt_en : 1; /* [10] */
unsigned int task_intrpt_en : 1; /* [11] */
unsigned int reserved_1 : 20; /* [31..12] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_intr_en;
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 10;
unsigned int block_intrpt : 1; /* [10] */
unsigned int task_intrpt : 1; /* [11] */
unsigned int reserved_1 : 20; /* [31..12] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_intr_status;
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 10;
unsigned int block_intrpt_clr : 1; /* [10] */
unsigned int task_intrpt_clr : 1; /* [11] */
unsigned int reserved_1 : 20; /* [31..12] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_intr_clr;
#endif /* end HW_DECOMPRESS_V1_H */
@@ -0,0 +1,29 @@
/*
* Copyright (c) LOTUS. All rights reserved.
*/
#include <asm/io.h>
#include <config.h>
#define PERI_CRG100 (CRG_REG_BASE + 0x190)
#define GZIP_REG_CRG PERI_CRG100
#define GZIP_CLKEN (0x1<<0)
static void disable_decompress_clock(void)
{
unsigned int regval;
regval = readl(GZIP_REG_CRG);
regval &= ~GZIP_CLKEN;
writel(regval, GZIP_REG_CRG);
}
static void enable_decompress_clock(void)
{
unsigned int regval;
regval = readl(GZIP_REG_CRG);
regval |= GZIP_CLKEN;
writel(regval, GZIP_REG_CRG);
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) LOTUS. All rights reserved.
*/
#include <asm/io.h>
#include <config.h>
#define PERI_CRG100 0x190
#define GZIP_OFFSET PERI_CRG100
#define GZIP_CLKEN (0x1<<0)
#ifndef GZIP_REG_BASE
#define GZIP_REG_BASE 0x11310000
#endif
#define HW_DEC_REG_BASE_ADDR (GZIP_REG_BASE)
static void disable_decompress_clock(void)
{
unsigned int regval;
regval = readl(CRG_REG_BASE + GZIP_OFFSET);
regval &= ~GZIP_CLKEN;
writel(regval, CRG_REG_BASE + GZIP_OFFSET);
}
static void enable_decompress_clock(void)
{
unsigned int regval;
regval = readl(CRG_REG_BASE + GZIP_OFFSET);
regval |= GZIP_CLKEN;
writel(regval, CRG_REG_BASE + GZIP_OFFSET);
}