misc: decompress: add/update API
- Support get gunzip data size from src data; - Support sync decompress for this round; - Support return the gunzip data size of compressed image. - Add misc_decompress_cleanup() for waiting last decompress done. Signed-off-by: Joseph Chen <chenjh@rock-chips.com> Change-Id: Ie84b2a6174d04592110333d66667da66f98f07f6
This commit is contained in:
parent
01b57c0600
commit
656bdb598a
|
|
@ -4,8 +4,9 @@
|
|||
*/
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <misc.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
#define HEAD_CRC 2
|
||||
#define EXTRA_FIELD 4
|
||||
|
|
@ -14,6 +15,26 @@
|
|||
#define RESERVED 0xe0
|
||||
#define DEFLATED 8
|
||||
|
||||
static u32 misc_decomp_async, misc_decomp_sync;
|
||||
|
||||
static void decomp_set_flags(u32 *flags, u8 comp)
|
||||
{
|
||||
if (comp == IH_COMP_GZIP)
|
||||
*flags |= DECOM_GZIP;
|
||||
else if (comp == IH_COMP_LZ4)
|
||||
*flags |= DECOM_LZ4;
|
||||
}
|
||||
|
||||
void misc_decompress_async(u8 comp)
|
||||
{
|
||||
decomp_set_flags(&misc_decomp_async, comp);
|
||||
}
|
||||
|
||||
void misc_decompress_sync(u8 comp)
|
||||
{
|
||||
decomp_set_flags(&misc_decomp_sync, comp);
|
||||
}
|
||||
|
||||
static int misc_gzip_parse_header(const unsigned char *src, unsigned long len)
|
||||
{
|
||||
int i, flags;
|
||||
|
|
@ -42,19 +63,26 @@ static int misc_gzip_parse_header(const unsigned char *src, unsigned long len)
|
|||
return i;
|
||||
}
|
||||
|
||||
static u32 misc_get_data_size(unsigned long src, unsigned long len, u32 cap)
|
||||
{
|
||||
if (cap == DECOM_GZIP)
|
||||
return *(u32 *)(src + len - 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct udevice *misc_decompress_get_device(u32 capability)
|
||||
{
|
||||
return misc_get_device_by_capability(capability);
|
||||
}
|
||||
|
||||
int misc_decompress_start(struct udevice *dev, unsigned long src,
|
||||
unsigned long dst, unsigned long size)
|
||||
int misc_decompress_start(struct udevice *dev, unsigned long dst,
|
||||
unsigned long src, unsigned long src_len)
|
||||
{
|
||||
struct decom_param param;
|
||||
|
||||
param.addr_dst = dst;
|
||||
param.addr_src = src;
|
||||
param.size = size;
|
||||
if (misc_gzip_parse_header((unsigned char *)src, 0xffff) > 0) {
|
||||
param.mode = DECOM_GZIP;
|
||||
} else {
|
||||
|
|
@ -62,6 +90,10 @@ int misc_decompress_start(struct udevice *dev, unsigned long src,
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
param.size_src = misc_get_data_size(src, src_len, param.mode);
|
||||
if (!param.size_src)
|
||||
return -EINVAL;
|
||||
|
||||
return misc_ioctl(dev, IOCTL_REQ_START, ¶m);
|
||||
}
|
||||
|
||||
|
|
@ -78,18 +110,24 @@ bool misc_decompress_is_complete(struct udevice *dev)
|
|||
return true;
|
||||
}
|
||||
|
||||
int misc_decompress_process(unsigned long src,
|
||||
unsigned long dst,
|
||||
unsigned long limit_size,
|
||||
u32 cap)
|
||||
int misc_decompress_data_size(struct udevice *dev, u64 *size, u32 cap)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int timeout = 10000;
|
||||
struct decom_param param;
|
||||
int ret;
|
||||
|
||||
dev = misc_decompress_get_device(cap);
|
||||
if (!dev)
|
||||
return -EIO;
|
||||
param.mode = cap;
|
||||
param.size_dst = 0; /* clear */
|
||||
|
||||
ret = misc_ioctl(dev, IOCTL_REQ_DATA_SIZE, ¶m);
|
||||
if (!ret)
|
||||
*size = param.size_dst;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int misc_decompress_finish(struct udevice *dev, u32 cap)
|
||||
{
|
||||
int timeout = 10000;
|
||||
|
||||
while (!misc_decompress_is_complete(dev)) {
|
||||
if (timeout < 0)
|
||||
|
|
@ -98,9 +136,82 @@ int misc_decompress_process(unsigned long src,
|
|||
udelay(10);
|
||||
}
|
||||
|
||||
ret = misc_decompress_stop(dev);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
return misc_decompress_start(dev, src, dst, limit_size);
|
||||
return misc_decompress_stop(dev);
|
||||
}
|
||||
|
||||
int misc_decompress_cleanup(void)
|
||||
{
|
||||
const struct misc_ops *ops;
|
||||
struct udevice *dev;
|
||||
struct uclass *uc;
|
||||
int ret;
|
||||
u32 cap;
|
||||
|
||||
ret = uclass_get(UCLASS_MISC, &uc);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
/* use "find_" */
|
||||
for (uclass_find_first_device(UCLASS_MISC, &dev);
|
||||
dev;
|
||||
uclass_find_next_device(&dev)) {
|
||||
ops = device_get_ops(dev);
|
||||
if (!ops || !ops->ioctl)
|
||||
continue;
|
||||
else if (ops->ioctl(dev, IOCTL_REQ_CAPABILITY, &cap))
|
||||
continue;
|
||||
else if (misc_decomp_async & cap)
|
||||
continue;
|
||||
|
||||
if (misc_decomp_sync & cap) {
|
||||
ret = ops->ioctl(dev, IOCTL_REQ_STOP, NULL);
|
||||
if (ret) {
|
||||
printf("Failed to stop decompress: %s, ret=%d\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int misc_decompress_process(unsigned long dst, unsigned long src,
|
||||
unsigned long src_len, u32 cap, bool sync,
|
||||
u64 *size)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
dev = misc_decompress_get_device(cap);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Wait last finish */
|
||||
ret = misc_decompress_finish(dev, cap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = misc_decompress_start(dev, dst, src, src_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Wait this round finish ?
|
||||
*
|
||||
* If sync, return original data length after decompress done.
|
||||
* otherwise return from compressed file information.
|
||||
*/
|
||||
if (sync) {
|
||||
ret = misc_decompress_finish(dev, cap);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (size)
|
||||
ret = misc_decompress_data_size(dev, size, cap);
|
||||
} else {
|
||||
if (size)
|
||||
*size = misc_get_data_size(src, src_len, cap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ static int rockchip_decom_start(struct udevice *dev, void *buf)
|
|||
{
|
||||
struct rockchip_decom_priv *priv = dev_get_priv(dev);
|
||||
struct decom_param *param = (struct decom_param *)buf;
|
||||
unsigned int limit_lo = param->size & 0xffffffff;
|
||||
unsigned int limit_hi = param->size >> 32;
|
||||
unsigned int limit_lo = param->size_src & 0xffffffff;
|
||||
unsigned int limit_hi = param->size_src >> 32;
|
||||
|
||||
priv->done = false;
|
||||
|
||||
|
|
@ -102,13 +102,12 @@ static int rockchip_decom_start(struct udevice *dev, void *buf)
|
|||
writel(LZ4_CONT_CSUM_CHECK_EN |
|
||||
LZ4_HEAD_CSUM_CHECK_EN |
|
||||
LZ4_BLOCK_CSUM_CHECK_EN |
|
||||
DECOM_LZ4_MODE, priv->base + DECOM_CTRL);
|
||||
|
||||
if (param->mode == DECOM_GZIP)
|
||||
DECOM_LZ4_MODE,
|
||||
priv->base + DECOM_CTRL);
|
||||
else if (param->mode == DECOM_GZIP)
|
||||
writel(DECOM_DEFLATE_MODE | DECOM_GZIP_MODE,
|
||||
priv->base + DECOM_CTRL);
|
||||
|
||||
if (param->mode == DECOM_ZLIB)
|
||||
else if (param->mode == DECOM_ZLIB)
|
||||
writel(DECOM_DEFLATE_MODE | DECOM_ZLIB_MODE,
|
||||
priv->base + DECOM_CTRL);
|
||||
|
||||
|
|
@ -118,8 +117,11 @@ static int rockchip_decom_start(struct udevice *dev, void *buf)
|
|||
writel(limit_lo, priv->base + DECOM_LMTSL);
|
||||
writel(limit_hi, priv->base + DECOM_LMTSH);
|
||||
|
||||
#ifdef CONFIG_IRQ
|
||||
writel(DECOM_INT_MASK, priv->base + DECOM_IEN);
|
||||
#endif
|
||||
writel(DECOM_ENABLE, priv->base + DECOM_ENR);
|
||||
|
||||
priv->idle_check_once = true;
|
||||
|
||||
return 0;
|
||||
|
|
@ -128,13 +130,14 @@ static int rockchip_decom_start(struct udevice *dev, void *buf)
|
|||
static int rockchip_decom_stop(struct udevice *dev)
|
||||
{
|
||||
struct rockchip_decom_priv *priv = dev_get_priv(dev);
|
||||
#ifdef CONFIG_IRQ
|
||||
int irq_status;
|
||||
|
||||
irq_status = readl(priv->base + DECOM_ISR);
|
||||
/* clear interrupts */
|
||||
if (irq_status)
|
||||
writel(irq_status, priv->base + DECOM_ISR);
|
||||
|
||||
#endif
|
||||
writel(DECOM_DISABLE, priv->base + DECOM_ENR);
|
||||
|
||||
return 0;
|
||||
|
|
@ -161,6 +164,19 @@ static int rockchip_decom_capability(u32 *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_decom_data_size(struct udevice *dev, u64 *buf)
|
||||
{
|
||||
struct rockchip_decom_priv *priv = dev_get_priv(dev);
|
||||
struct decom_param *param = (struct decom_param *)buf;
|
||||
u32 sizel, sizeh;
|
||||
|
||||
sizel = readl(priv->base + DECOM_TSIZEL);
|
||||
sizeh = readl(priv->base + DECOM_TSIZEH);
|
||||
param->size_dst = sizel | ((u64)sizeh << 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Caller must fill in param @buf which represent struct decom_param */
|
||||
static int rockchip_decom_ioctl(struct udevice *dev, unsigned long request,
|
||||
void *buf)
|
||||
|
|
@ -180,6 +196,12 @@ static int rockchip_decom_ioctl(struct udevice *dev, unsigned long request,
|
|||
case IOCTL_REQ_CAPABILITY:
|
||||
ret = rockchip_decom_capability(buf);
|
||||
break;
|
||||
case IOCTL_REQ_DATA_SIZE:
|
||||
ret = rockchip_decom_data_size(dev, buf);
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported ioctl: %ld\n", (ulong)request);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#define IOCTL_REQ_STOP _IO('m', 0x02)
|
||||
#define IOCTL_REQ_POLL _IO('m', 0x03)
|
||||
#define IOCTL_REQ_CAPABILITY _IO('m', 0x04)
|
||||
#define IOCTL_REQ_DATA_SIZE _IO('m', 0x05)
|
||||
|
||||
enum misc_mode {
|
||||
DECOM_LZ4 = BIT(0),
|
||||
|
|
@ -149,7 +150,8 @@ int misc_otp_write(struct udevice *dev, int offset, const void *buf, int size);
|
|||
struct decom_param {
|
||||
unsigned long addr_src;
|
||||
unsigned long addr_dst;
|
||||
u64 size;
|
||||
u64 size_src;
|
||||
u64 size_dst; /* to be filled for output */
|
||||
enum misc_mode mode;
|
||||
};
|
||||
|
||||
|
|
@ -158,9 +160,11 @@ int misc_decompress_start(struct udevice *dev, unsigned long src,
|
|||
unsigned long dst, unsigned long size);
|
||||
int misc_decompress_stop(struct udevice *dev);
|
||||
bool misc_decompress_is_complete(struct udevice *dev);
|
||||
int misc_decompress_process(unsigned long src,
|
||||
unsigned long dst,
|
||||
unsigned long limit_size,
|
||||
u32 cap);
|
||||
|
||||
void misc_decompress_async(u8 comp);
|
||||
void misc_decompress_sync(u8 comp);
|
||||
int misc_decompress_cleanup(void);
|
||||
int misc_decompress_process(unsigned long dst, unsigned long src,
|
||||
unsigned long src_len, u32 cap, bool sync,
|
||||
u64 *size);
|
||||
#endif /* _MISC_H_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue