From fb06d38cdbf11a54387ea60d36b4c37993c840a0 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Thu, 14 May 2020 15:53:47 +0800 Subject: [PATCH] soc: rockchip: decompress: update driver 1. add soft reset 2. dump register when decompress failed 3. add start callback Change-Id: Ie7d02892a5531f6510cd18ff938817a5352896dd Signed-off-by: Simon Xue --- drivers/soc/rockchip/rockchip_decompress.c | 88 +++++++++++++++++-- .../linux/soc/rockchip/rockchip_decompress.h | 16 ++++ 2 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 include/linux/soc/rockchip/rockchip_decompress.h diff --git a/drivers/soc/rockchip/rockchip_decompress.c b/drivers/soc/rockchip/rockchip_decompress.c index 57a8b6f71835..9f79f363c301 100644 --- a/drivers/soc/rockchip/rockchip_decompress.c +++ b/drivers/soc/rockchip/rockchip_decompress.c @@ -3,6 +3,7 @@ * Copyright (C) 2020 Rockchip Electronics Co., Ltd */ #include +#include #include #include #include @@ -12,6 +13,8 @@ #include #include #include +#include +#include #define DECOM_CTRL 0x0 #define DECOM_ENR 0x4 @@ -33,6 +36,8 @@ #define DECOM_DICTID 0x44 #define DECOM_CSL 0x48 #define DECOM_CSH 0x4c +#define DECOM_LMTSL 0x50 +#define DECOM_LMTSH 0x54 #define LZ4_HEAD_CSUM_CHECK_EN BIT(1) #define LZ4_BLOCK_CSUM_CHECK_EN BIT(2) @@ -75,12 +80,6 @@ DISEIEN | LENEIEN | LITEIEN | SQMEIEN | SLCIEN | \ HDEIEN | DSIEN) -enum decom_mod { - LZ4_MOD, - GZIP_MOD, - ZLIB_MOD, -}; - struct rk_decom { struct device *dev; int irq; @@ -89,8 +88,11 @@ struct rk_decom { void __iomem *regs; phys_addr_t mem_start; size_t mem_size; + struct reset_control *reset; }; +static struct rk_decom *g_decom; + static DECLARE_WAIT_QUEUE_HEAD(initrd_decom_done); static bool initrd_continue; @@ -99,6 +101,64 @@ void __init wait_initrd_hw_decom_done(void) wait_event(initrd_decom_done, initrd_continue); } +int rk_decom_start(u32 mode, phys_addr_t mem_start, phys_addr_t mem_dst, u32 dst_max_size) +{ + u32 irq_status; + u32 decom_enr; + + if (!g_decom) + return -EINVAL; + + decom_enr = readl(g_decom->regs + DECOM_ENR); + if (decom_enr & 0x1) { + pr_err("decompress busy\n"); + return -EBUSY; + } + + if (g_decom->reset) { + reset_control_assert(g_decom->reset); + udelay(10); + reset_control_deassert(g_decom->reset); + } + + irq_status = readl(g_decom->regs + DECOM_ISR); + /* clear interrupts */ + if (irq_status) + writel(irq_status, g_decom->regs + DECOM_ISR); + + switch (mode) { + case LZ4_MOD: + writel(LZ4_CONT_CSUM_CHECK_EN | + LZ4_HEAD_CSUM_CHECK_EN | + LZ4_BLOCK_CSUM_CHECK_EN | + LZ4_MOD, g_decom->regs + DECOM_CTRL); + break; + case GZIP_MOD: + writel(DECOM_DEFLATE_MODE | DECOM_GZIP_MODE, + g_decom->regs + DECOM_CTRL); + break; + case ZLIB_MOD: + writel(DECOM_DEFLATE_MODE | DECOM_ZLIB_MODE, + g_decom->regs + DECOM_CTRL); + break; + default: + pr_err("undefined mode : %d\n", mode); + return -EINVAL; + } + + writel(mem_start, g_decom->regs + DECOM_RADDR); + writel(mem_dst, g_decom->regs + DECOM_WADDR); + + writel(dst_max_size, g_decom->regs + DECOM_LMTSL); + writel(0x0, g_decom->regs + DECOM_LMTSH); + + writel(DECOM_INT_MASK, g_decom->regs + DECOM_IEN); + writel(DECOM_ENABLE, g_decom->regs + DECOM_ENR); + + return 0; +} +EXPORT_SYMBOL(rk_decom_start); + static irqreturn_t rk_decom_irq_handler(int irq, void *priv) { struct rk_decom *rk_dec = priv; @@ -118,6 +178,10 @@ static irqreturn_t rk_decom_irq_handler(int irq, void *priv) dev_info(rk_dec->dev, "decom failed, irq_status = 0x%x, decom_status = 0x%x, try again !\n", irq_status, decom_status); + + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, + 32, 4, rk_dec->regs, 0x128, false); + writel(DECOM_ENABLE, rk_dec->regs + DECOM_ENR); } } @@ -201,6 +265,16 @@ static int rockchip_decom_probe(struct platform_device *pdev) dev_set_drvdata(dev, rk_dec); + rk_dec->reset = devm_reset_control_get_exclusive(dev, "dresetn"); + if (IS_ERR(rk_dec->reset)) { + ret = PTR_ERR(rk_dec->reset); + if (ret != -ENOENT) + return ret; + + dev_dbg(dev, "no reset control found\n"); + rk_dec->reset = NULL; + } + ret = devm_request_threaded_irq(dev, rk_dec->irq, rk_decom_irq_handler, rk_decom_irq_thread, IRQF_ONESHOT, dev_name(dev), rk_dec); @@ -209,6 +283,8 @@ static int rockchip_decom_probe(struct platform_device *pdev) goto disable_clk; } + g_decom = rk_dec; + return 0; disable_clk: diff --git a/include/linux/soc/rockchip/rockchip_decompress.h b/include/linux/soc/rockchip/rockchip_decompress.h new file mode 100644 index 000000000000..a6b29235d49a --- /dev/null +++ b/include/linux/soc/rockchip/rockchip_decompress.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd */ + +#ifndef _ROCKCHIP_DECOMPRESS +#define _ROCKCHIP_DECOMPRESS + +enum decom_mod { + LZ4_MOD, + GZIP_MOD, + ZLIB_MOD, +}; + +int rk_decom_start(u32 mode, phys_addr_t mem_start, phys_addr_t mem_dst, u32 limit_size); + +#endif