All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tao Ding <dingtao0430@163.com>
To: qemu-devel@nongnu.org
Cc: qemu-riscv@nongnu.org, pbonzini@redhat.com, palmer@dabbelt.com,
	alistair.francis@wdc.com, liwei1518@gmail.com,
	daniel.barboza@oss.qualcomm.com, zhiwei_liu@linux.alibaba.com,
	chao.liu@processmission.com, farosas@suse.de, lvivier@redhat.com,
	pierrick.bouvier@oss.qualcomm.com, caojunze424@gmail.com,
	Tao Ding <dingtao0430@163.com>
Subject: [PATCH v2 4/7] hw/misc: add K230 decomp gzip
Date: Mon, 27 Jul 2026 23:56:59 +0800	[thread overview]
Message-ID: <20260727155702.36484-5-dingtao0430@163.com> (raw)
In-Reply-To: <20260727155702.36484-1-dingtao0430@163.com>

Decompression accelerator is mainly used to implement hardware GZIP decompression function.
According to the k230 SDK, this hardware will be used during the uboot phase to decompress 
compressed files. 

Decomp_gzip does not have the ability to access the system bus. 
Therefore, SDMA is required for data transmission. A typical scenario is SDMA moving compressed 
data from DDR to SRAM, and Decomp_gzip reading data from SRAM. After decompression, decomp_gzip 
writes the data back to SRAM, and SDMA moves the data from SRAM to DDR.

According to "K230 Technical Reference Manual v0.3.1" section 15.
https://download.kendryte.com/developer/k230/HDK/K230%E7%A1%AC%E4%BB%B6%E6%96%87%E6%A1%A3/K230_Technical_Reference_Manual_V0.3.1_20241118.pdf

Signed-off-by: Tao Ding <dingtao0430@163.com>
---
In patchv1, the reviewer identified some bugs, which have been fixed.
bugs:
    Decomp gzip only support Dynamic Huffman format
    Bit 0 in 0x0 register is write only
enhance:
    ues new reset interface

 MAINTAINERS                        |   2 +
 docs/system/riscv/k230.rst         |   1 +
 hw/misc/Kconfig                    |   3 +
 hw/misc/k230_decomp_gzip.c         | 508 +++++++++++++++++++++++++++++
 hw/misc/meson.build                |   1 +
 hw/misc/trace-events               |   4 +
 include/hw/misc/k230_decomp_gzip.h |  92 ++++++
 7 files changed, 611 insertions(+)
 create mode 100644 hw/misc/k230_decomp_gzip.c
 create mode 100644 include/hw/misc/k230_decomp_gzip.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c546596e7..c260199142 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1830,9 +1830,11 @@ F: docs/system/riscv/k230.rst
 F: hw/riscv/k230.c
 F: hw/watchdog/k230_wdt.c
 F: hw/dma/k230_gsdma.c
+F: hw/misc/k230_decomp_gzip.c
 F: include/hw/riscv/k230.h
 F: include/hw/watchdog/k230_wdt.h
 F: include/hw/dma/k230_gsdma.h
+F: include/hw/misc/k230_decomp_gzip.h
 F: tests/functional/riscv64/test_k230.py
 F: tests/qtest/k230-wdt-test.c
 F: tests/qtest/k230-gsdma-test.c
diff --git a/docs/system/riscv/k230.rst b/docs/system/riscv/k230.rst
index a426a1d776..ebd002b62f 100644
--- a/docs/system/riscv/k230.rst
+++ b/docs/system/riscv/k230.rst
@@ -21,6 +21,7 @@ The ``k230`` machine supports the following devices:
 * 2 K230 Watchdog Timer
 * 5 UART
 * System Direct Memory Access (SDMA)
+* GZIP Decompress Engine (Decomp_gzip)
 
 Boot options
 ------------
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1543ee6653..28687482f8 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -257,4 +257,7 @@ config XLNX_VERSAL_TRNG
 config XLNX_ZYNQ_DDRC
     bool
 
+config K230_DECOMP_GZIP
+    bool
+
 source macio/Kconfig
diff --git a/hw/misc/k230_decomp_gzip.c b/hw/misc/k230_decomp_gzip.c
new file mode 100644
index 0000000000..498ad488e3
--- /dev/null
+++ b/hw/misc/k230_decomp_gzip.c
@@ -0,0 +1,508 @@
+/*
+ * Kendryte K230 GZIP decompression engine
+ *
+ * Copyright (c) 2026 Tao Ding <dingtao0430@163.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Decompression accelerator is mainly used to implement hardware
+ * GZIP decompression function. (K230 TRM section 15)
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/core/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "system/address-spaces.h"
+#include "hw/core/irq.h"
+#include "hw/misc/k230_decomp_gzip.h"
+#include "trace.h"
+
+#define GZIP_METHOD_DEFLATE    8
+#define GZIP_METHOD_VENDOR_9   9
+
+#define DEFLATE_BTYPE_DYNAMIC  2
+
+#define K230_DECOMP_GZIP_OUTPUT_SLOTS 4
+#define K230_DECOMP_GZIP_INPUT_SLOTS 2
+
+static void k230_decomp_gzip_set_output(K230DecompGzipState *s, int line,
+                                        int level)
+{
+    qemu_set_irq(s->signal_out[line], level);
+}
+
+static bool k230_decomp_gzip_read_mem(K230DecompGzipState *s, hwaddr addr,
+                                      void *buf, size_t len)
+{
+    MemTxResult ret = address_space_read(&address_space_memory,
+                                         s->sram_base + addr,
+                                         MEMTXATTRS_UNSPECIFIED, buf, len);
+
+    return ret == MEMTX_OK;
+}
+
+static bool k230_decomp_gzip_write_mem(K230DecompGzipState *s, hwaddr addr,
+                                       const void *buf, size_t len)
+{
+    return address_space_write(&address_space_memory, s->sram_base + addr,
+                               MEMTXATTRS_UNSPECIFIED, buf, len) == MEMTX_OK;
+}
+
+static hwaddr k230_decomp_gzip_output_addr(K230DecompGzipState *s)
+{
+    return K230_DECOMP_GZIP_SRAM_OUT_BASE +
+           s->output.slot * K230_DECOMP_GZIP_BLOCK_SIZE +
+           s->output.current_offset;
+}
+
+static hwaddr k230_decomp_gzip_input_addr(K230DecompGzipState *s)
+{
+    return s->input.slot * K230_DECOMP_GZIP_BLOCK_SIZE +
+           K230_DECOMP_GZIP_SRAM_IN_BASE;
+}
+
+static uint32_t k230_decomp_gzip_current_input_size(K230DecompGzipState *s)
+{
+    if (s->total_requested == 0) {
+        return 0;
+    }
+
+    return ((s->total_requested - 1) % K230_DECOMP_GZIP_BLOCK_SIZE) + 1;
+}
+
+static void k230_decomp_gzip_update_ctrl_en(K230DecompGzipState *s)
+{
+    int level = s->active && !!(s->gzip_src_size & K230_DECOMP_GZIP_CTRL_EN);
+
+    k230_decomp_gzip_set_output(s, K230_DECOMP_GZIP_GPIO_DECOMP_CTRL_EN,
+                                level);
+}
+
+static void k230_decomp_gzip_reset_stream(K230DecompGzipState *s)
+{
+    if (s->zstream_inited) {
+        inflateEnd(&s->zs);
+        s->zstream_inited = false;
+    }
+    memset(&s->zs, 0, sizeof(s->zs));
+}
+
+static void k230_decomp_gzip_finish(K230DecompGzipState *s, bool crc_ok)
+{
+    s->active = false;
+    k230_decomp_gzip_reset_stream(s);
+    k230_decomp_gzip_update_ctrl_en(s);
+    if (crc_ok) {
+        s->decomp_stat |= K230_DECOMP_GZIP_STAT_CRC_OK;
+    } else {
+        s->decomp_stat &= ~K230_DECOMP_GZIP_STAT_CRC_OK;
+    }
+}
+
+static bool k230_decomp_gzip_load_input(K230DecompGzipState *s,
+                                        uint32_t addr, uint32_t size)
+{
+    s->input.current_offset = 0;
+
+    return k230_decomp_gzip_read_mem(s, addr, s->input_buf, size);
+}
+
+static bool k230_decomp_gzip_request_input(K230DecompGzipState *s)
+{
+    uint32_t total_requested = s->total_requested;
+
+    k230_decomp_gzip_set_output(s, K230_DECOMP_GZIP_GPIO_DMA_WRITE_REQ, 1);
+    if (s->total_requested == total_requested) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: dma write request not acknowledged\n",
+                      TYPE_K230_DECOMP_GZIP);
+        return false;
+    }
+    return true;
+}
+
+static bool k230_decomp_gzip_request_output(K230DecompGzipState *s)
+{
+    uint32_t slot = s->output.slot;
+    uint32_t current_offset = s->output.current_offset;
+
+    k230_decomp_gzip_set_output(s, K230_DECOMP_GZIP_GPIO_DMA_READ_REQ, 1);
+    if (s->output.slot == slot &&
+        s->output.current_offset == current_offset) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: dma read request not acknowledged\n",
+                      TYPE_K230_DECOMP_GZIP);
+        return false;
+    }
+    return true;
+}
+
+static bool k230_decomp_gzip_init_stream(K230DecompGzipState *s)
+{
+    uint8_t btype = (s->input_buf[10] >> 1) & 0x3;
+    if (btype != DEFLATE_BTYPE_DYNAMIC) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unsupported DEFLATE BTYPE %u\n",
+                      TYPE_K230_DECOMP_GZIP, btype);
+        return false;
+    }
+
+    /* The compression script for K230 will modify the third byte to 0x9 */
+    if (s->input_buf[2] == GZIP_METHOD_VENDOR_9) {
+        s->input_buf[2] = GZIP_METHOD_DEFLATE;
+    }
+
+    if (inflateInit2(&s->zs, 15 + 16) != Z_OK) {
+        return false;
+    }
+
+    s->zstream_inited = true;
+    return true;
+}
+
+static bool k230_decomp_gzip_run_inflate(K230DecompGzipState *s)
+{
+    uint32_t output_size = s->gzip_out_size;
+    uint32_t current_input_size = k230_decomp_gzip_current_input_size(s);
+    uint32_t avail_in;
+    uint32_t avail_out;
+    uint32_t consumed;
+    uint32_t produced;
+    int ret;
+
+    avail_in = current_input_size - s->input.current_offset;
+    avail_out = K230_DECOMP_GZIP_BLOCK_SIZE - s->output.current_offset;
+
+    s->zs.next_in = s->input_buf + s->input.current_offset;
+    s->zs.avail_in = avail_in;
+    s->zs.next_out = s->output_buf;
+    s->zs.avail_out = avail_out;
+
+    ret = inflate(&s->zs, Z_NO_FLUSH);
+    if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
+        return false;
+    }
+
+    consumed = avail_in - s->zs.avail_in;
+    produced = avail_out - s->zs.avail_out;
+
+    if (produced) {
+        if (s->total_produced + produced > output_size ||
+            !k230_decomp_gzip_write_mem(s, k230_decomp_gzip_output_addr(s),
+                                        s->output_buf, produced)) {
+            return false;
+        }
+        s->output.current_offset += produced;
+        s->total_produced += produced;
+    }
+
+    if (consumed) {
+        s->input.current_offset += consumed;
+    }
+
+    if (ret == Z_STREAM_END) {
+        s->stream_end = true;
+        if (s->total_produced != output_size) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static void k230_decomp_gzip_kick(K230DecompGzipState *s)
+{
+    if (!s->active || s->in_kick) {
+        return;
+    }
+
+    uint32_t input_size = s->gzip_src_size & K230_DECOMP_GZIP_DMA_IN_MASK;
+    s->in_kick = true;
+    while (s->active) {
+        uint32_t current_input_size = k230_decomp_gzip_current_input_size(s);
+        /* Output is full or last block */
+        if (s->output.current_offset == K230_DECOMP_GZIP_BLOCK_SIZE ||
+            (s->stream_end && s->output.current_offset != 0)) {
+            if (!k230_decomp_gzip_request_output(s)) {
+                k230_decomp_gzip_finish(s, false);
+                break;
+            }
+            continue;
+        }
+
+        if (!s->zstream_inited) {
+            if (!k230_decomp_gzip_request_input(s) ||
+                !k230_decomp_gzip_init_stream(s)) {
+                k230_decomp_gzip_finish(s, false);
+                break;
+            }
+            continue;
+        }
+
+        /* Transfer finish */
+        if (s->stream_end) {
+            k230_decomp_gzip_finish(s,
+                                    s->total_produced == s->gzip_out_size);
+            break;
+        }
+
+        /* Input buf has has been fully decompreed, need request more */
+        if (s->input.current_offset == current_input_size) {
+            if (s->total_requested < input_size) {
+                if (!k230_decomp_gzip_request_input(s)) {
+                    k230_decomp_gzip_finish(s, false);
+                    break;
+                }
+                continue;
+            }
+            k230_decomp_gzip_finish(s, false);
+            break;
+        }
+
+        /* Decompress the data, input buf or output buf are consumed in one block */
+        if (!k230_decomp_gzip_run_inflate(s)) {
+            k230_decomp_gzip_finish(s, false);
+            break;
+        }
+    }
+    s->in_kick = false;
+}
+
+static void k230_decomp_gzip_handle_ack(void *opaque, int n, int level)
+{
+    K230DecompGzipState *s = opaque;
+
+    if (!level || !s->active) {
+        return;
+    }
+
+    switch (n) {
+    case K230_DECOMP_GZIP_GPIO_DMA_WRITE_ACK:
+    {
+        uint32_t input_size = s->gzip_src_size & K230_DECOMP_GZIP_DMA_IN_MASK;
+        uint32_t chunk = MIN(K230_DECOMP_GZIP_BLOCK_SIZE,
+                             input_size - s->total_requested);
+
+        if (!k230_decomp_gzip_load_input(s, k230_decomp_gzip_input_addr(s),
+                                         chunk)) {
+            k230_decomp_gzip_finish(s, false);
+            return;
+        }
+        s->total_requested += chunk;
+        s->input.slot = (s->input.slot + 1) % K230_DECOMP_GZIP_INPUT_SLOTS;
+        break;
+    }
+    case K230_DECOMP_GZIP_GPIO_DMA_READ_ACK:
+        if (s->output.current_offset == 0) {
+            k230_decomp_gzip_finish(s, false);
+            return;
+        }
+        s->output.slot = (s->output.slot + 1) % K230_DECOMP_GZIP_OUTPUT_SLOTS;
+        s->output.current_offset = 0;
+        break;
+    default:
+        return;
+    }
+
+    k230_decomp_gzip_kick(s);
+}
+
+static void k230_decomp_gzip_start(K230DecompGzipState *s)
+{
+    uint32_t input_size = s->gzip_src_size & K230_DECOMP_GZIP_DMA_IN_MASK;
+
+    k230_decomp_gzip_reset_stream(s);
+    s->decomp_stat &= ~K230_DECOMP_GZIP_STAT_CRC_OK;
+    s->total_requested = 0;
+    s->total_produced = 0;
+    s->stream_end = false;
+    memset(&s->input, 0, sizeof(s->input));
+    memset(&s->output, 0, sizeof(s->output));
+
+    if (!(s->gzip_src_size & K230_DECOMP_GZIP_CTRL_EN) ||
+        input_size == 0 || s->gzip_out_size == 0) {
+        k230_decomp_gzip_finish(s, false);
+        return;
+    }
+
+    s->active = true;
+    k230_decomp_gzip_update_ctrl_en(s);
+    k230_decomp_gzip_kick(s);
+}
+
+static uint64_t k230_decomp_gzip_read(void *opaque, hwaddr offset,
+                                      unsigned size)
+{
+    K230DecompGzipState *s = opaque;
+    uint64_t value = 0;
+
+    switch (offset) {
+    case K230_DECOMP_GZIP_DECOMP_START:
+        value = s->decomp_start & ~K230_DECOMP_GZIP_START; /* start bit is write only */
+        break;
+    case K230_DECOMP_GZIP_GZIP_SRC_SIZE:
+        value = s->gzip_src_size;
+        break;
+    case K230_DECOMP_GZIP_GZIP_OUT_SIZE:
+        value = s->gzip_out_size;
+        break;
+    case K230_DECOMP_GZIP_DECOMP_STAT:
+        value = s->decomp_stat;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad read offset 0x%" HWADDR_PRIx "\n",
+                      TYPE_K230_DECOMP_GZIP, offset);
+        break;
+    }
+
+    trace_k230_decomp_gzip_read(offset, size, value);
+    return value;
+}
+
+static void k230_decomp_gzip_write(void *opaque, hwaddr offset,
+                                   uint64_t value, unsigned size)
+{
+    K230DecompGzipState *s = opaque;
+
+    trace_k230_decomp_gzip_write(offset, size, value);
+
+    switch (offset) {
+    case K230_DECOMP_GZIP_DECOMP_START:
+        s->decomp_start = value;
+        if (value & K230_DECOMP_GZIP_START) {
+            k230_decomp_gzip_start(s);
+        }
+        break;
+    case K230_DECOMP_GZIP_GZIP_SRC_SIZE:
+        s->gzip_src_size = value;
+        k230_decomp_gzip_update_ctrl_en(s);
+        break;
+    case K230_DECOMP_GZIP_GZIP_OUT_SIZE:
+        s->gzip_out_size = value;
+        break;
+    case K230_DECOMP_GZIP_DECOMP_STAT:
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: bad write offset 0x%" HWADDR_PRIx "\n",
+                      TYPE_K230_DECOMP_GZIP, offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps k230_decomp_gzip_ops = {
+    .read = k230_decomp_gzip_read,
+    .write = k230_decomp_gzip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_k230_decomp_gzip_slot = {
+    .name = "k230.decomp-gzip.slot",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32(slot, K230DecompGzipSlotState),
+        VMSTATE_UINT32(current_offset, K230DecompGzipSlotState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_k230_decomp_gzip = {
+    .name = "k230.decomp-gzip",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32(decomp_start, K230DecompGzipState),
+        VMSTATE_UINT32(gzip_src_size, K230DecompGzipState),
+        VMSTATE_UINT32(gzip_out_size, K230DecompGzipState),
+        VMSTATE_UINT32(decomp_stat, K230DecompGzipState),
+        VMSTATE_STRUCT(input, K230DecompGzipState, 1,
+                       vmstate_k230_decomp_gzip_slot,
+                       K230DecompGzipSlotState),
+        VMSTATE_STRUCT(output, K230DecompGzipState, 1,
+                       vmstate_k230_decomp_gzip_slot,
+                       K230DecompGzipSlotState),
+        VMSTATE_UINT32(total_requested, K230DecompGzipState),
+        VMSTATE_UINT32(total_produced, K230DecompGzipState),
+        VMSTATE_BOOL(active, K230DecompGzipState),
+        VMSTATE_BOOL(in_kick, K230DecompGzipState),
+        VMSTATE_BOOL(zstream_inited, K230DecompGzipState),
+        VMSTATE_BOOL(stream_end, K230DecompGzipState),
+        VMSTATE_UINT8_ARRAY(input_buf, K230DecompGzipState,
+                            K230_DECOMP_GZIP_BLOCK_SIZE),
+        VMSTATE_UINT8_ARRAY(output_buf, K230DecompGzipState,
+                            K230_DECOMP_GZIP_BLOCK_SIZE),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void k230_decomp_gzip_reset_hold(Object *obj, ResetType type)
+{
+    K230DecompGzipState *s = K230_DECOMP_GZIP(obj);
+
+    k230_decomp_gzip_reset_stream(s);
+    memset(&s->zs, 0, sizeof(s->zs));
+    s->decomp_start = 0;
+    s->gzip_src_size = 0;
+    s->gzip_out_size = 0;
+    s->decomp_stat = 0;
+    memset(&s->input, 0, sizeof(s->input));
+    memset(&s->output, 0, sizeof(s->output));
+    s->total_requested = 0;
+    s->total_produced = 0;
+    s->active = false;
+    s->in_kick = false;
+    s->stream_end = false;
+}
+
+static void k230_decomp_gzip_realize(DeviceState *dev, Error **errp)
+{
+    K230DecompGzipState *s = K230_DECOMP_GZIP(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(dev), &k230_decomp_gzip_ops, s,
+                          TYPE_K230_DECOMP_GZIP,
+                          K230_DECOMP_GZIP_MMIO_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+    qdev_init_gpio_in(dev, k230_decomp_gzip_handle_ack,
+                      K230_DECOMP_GZIP_NUM_GPIOS_IN);
+    qdev_init_gpio_out(dev, s->signal_out,
+                       K230_DECOMP_GZIP_NUM_GPIOS_OUT);
+}
+
+static const Property k230_decomp_gzip_properties[] = {
+    DEFINE_PROP_UINT64("sram-base", K230DecompGzipState, sram_base, 0),
+};
+
+static void k230_decomp_gzip_class_init(ObjectClass *oc, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    ResettableClass *rc = RESETTABLE_CLASS(oc);
+
+    dc->realize = k230_decomp_gzip_realize;
+    rc->phases.hold = k230_decomp_gzip_reset_hold;
+    device_class_set_props(dc, k230_decomp_gzip_properties);
+    dc->vmsd = &vmstate_k230_decomp_gzip;
+    dc->desc = "Kendryte K230 GZIP decompression engine";
+}
+
+static const TypeInfo k230_decomp_gzip_info = {
+    .name = TYPE_K230_DECOMP_GZIP,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(K230DecompGzipState),
+    .class_init = k230_decomp_gzip_class_init,
+};
+
+static void k230_decomp_gzip_register_types(void)
+{
+    type_register_static(&k230_decomp_gzip_info);
+}
+
+type_init(k230_decomp_gzip_register_types)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 23265f6035..6f6bf3c85c 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -36,6 +36,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c'))
 system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
 system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
 system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
+system_ss.add(when: 'CONFIG_K230_DECOMP_GZIP', if_true: files('k230_decomp_gzip.c'))
 
 subdir('macio')
 
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c9a868b3ef..16db4ba0cc 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -442,3 +442,7 @@ iommu_testdev_dma_read(uint64_t gva, uint32_t len) "gva=0x%" PRIx64 " len=%u"
 iommu_testdev_dma_verify(uint32_t expected, uint32_t actual) "expected=0x%x actual=0x%x"
 iommu_testdev_dma_result(uint32_t result) "DMA completed result=0x%x"
 iommu_testdev_dma_armed(bool armed) "armed=%d"
+
+# k230_decomp_gzip.c
+k230_decomp_gzip_read(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP read: [0x%"PRIx64"] size %u -> 0x%"PRIx64
+k230_decomp_gzip_write(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP write: [0x%"PRIx64"] size %u <- 0x%"PRIx64
diff --git a/include/hw/misc/k230_decomp_gzip.h b/include/hw/misc/k230_decomp_gzip.h
new file mode 100644
index 0000000000..9911af0095
--- /dev/null
+++ b/include/hw/misc/k230_decomp_gzip.h
@@ -0,0 +1,92 @@
+/*
+ * K230 Decompress Engine
+ *
+ * Copyright (c) 2026 Tao Ding <dingtao0430@163.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_K230_DECOMP_GZIP_H
+#define HW_MISC_K230_DECOMP_GZIP_H
+
+#include <zlib.h>
+#include "hw/core/sysbus.h"
+
+#define TYPE_K230_DECOMP_GZIP "riscv.k230.decomp-gzip"
+OBJECT_DECLARE_SIMPLE_TYPE(K230DecompGzipState, K230_DECOMP_GZIP)
+
+/* K230 DECOMP GZIP ACK input */
+enum {
+    K230_DECOMP_GZIP_GPIO_DMA_WRITE_ACK,
+    K230_DECOMP_GZIP_GPIO_DMA_READ_ACK,
+    K230_DECOMP_GZIP_NUM_GPIOS_IN,
+};
+
+/* K230 DECOMP GZIP REQ output */
+enum {
+    K230_DECOMP_GZIP_GPIO_DECOMP_CTRL_EN,
+    K230_DECOMP_GZIP_GPIO_DMA_WRITE_REQ,
+    K230_DECOMP_GZIP_GPIO_DMA_READ_REQ,
+    K230_DECOMP_GZIP_NUM_GPIOS_OUT,
+};
+
+#define K230_DECOMP_GZIP_MMIO_SIZE       0x4000
+
+/* K230 DECOMP GZIP Registers map */
+/* Start decompression controller */
+#define K230_DECOMP_GZIP_DECOMP_START    0x00
+/* Source data length register */
+#define K230_DECOMP_GZIP_GZIP_SRC_SIZE   0x04
+/* Output data length register */
+#define K230_DECOMP_GZIP_GZIP_OUT_SIZE   0x08
+/* Decompress status register */
+#define K230_DECOMP_GZIP_DECOMP_STAT     0x0c
+
+/* Start decompression controller */
+#define K230_DECOMP_GZIP_START           (1U << 0)
+
+#define K230_DECOMP_GZIP_CTRL_EN         (1U << 31)
+#define K230_DECOMP_GZIP_DMA_IN_MASK     0x7fffffffU
+
+#define K230_DECOMP_GZIP_STAT_CRC_OK     (1U << 10)
+#define K230_DECOMP_GZIP_STAT_STATE_MASK 0xfU
+
+#define K230_DECOMP_GZIP_BLOCK_SIZE      0x00020000
+#define K230_DECOMP_GZIP_SRAM_IN_BASE    0x80000
+#define K230_DECOMP_GZIP_SRAM_OUT_BASE   0
+
+typedef struct K230DecompGzipSlotState {
+    uint32_t slot;  /* Slot index */
+    /*
+     * Data offset in current slot.
+     * First valid data in input buffer. Last valid data in output buffer.
+     */
+    uint32_t current_offset;
+} K230DecompGzipSlotState;
+
+struct K230DecompGzipState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+    hwaddr sram_base;
+    qemu_irq signal_out[K230_DECOMP_GZIP_NUM_GPIOS_OUT];
+    uint32_t decomp_start;
+    uint32_t gzip_src_size;
+    uint32_t gzip_out_size;
+    uint32_t decomp_stat;
+    K230DecompGzipSlotState input;  /* decomp gzip ring input */
+    K230DecompGzipSlotState output; /* decomp gzip ring output */
+    uint32_t total_requested;
+    uint32_t total_produced;
+    bool active;
+    bool in_kick;
+    bool zstream_inited;
+    bool stream_end;
+    /* Read from ring input. */
+    uint8_t input_buf[K230_DECOMP_GZIP_BLOCK_SIZE];
+    /* Write to ring output. */
+    uint8_t output_buf[K230_DECOMP_GZIP_BLOCK_SIZE];
+    z_stream zs;
+};
+
+#endif
-- 
2.43.0



  parent reply	other threads:[~2026-07-27 15:58 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-27 15:56 [PATCH v2 0/7] K230: add gsdma and decomp_gzip Tao Ding
2026-07-27 15:56 ` [PATCH v2 1/7] hw/dma: add K230 gsdma Tao Ding
2026-08-06 11:34   ` Daniel Henrique Barboza
2026-08-07  4:46   ` Chao Liu
2026-07-27 15:56 ` [PATCH v2 2/7] hw/riscv: k230: add gsdma in K230 board Tao Ding
2026-08-06 11:34   ` Daniel Henrique Barboza
2026-07-27 15:56 ` [PATCH v2 3/7] tests/qtest: add test for K230 gsdma Tao Ding
2026-08-06 11:36   ` Daniel Henrique Barboza
2026-07-27 15:56 ` Tao Ding [this message]
2026-08-06 11:47   ` [PATCH v2 4/7] hw/misc: add K230 decomp gzip Daniel Henrique Barboza
2026-07-27 15:57 ` [PATCH v2 5/7] hw/riscv: k230: add decomp gzip in K230 board Tao Ding
2026-08-06 11:48   ` Daniel Henrique Barboza
2026-07-27 15:57 ` [PATCH v2 6/7] tests/qtest: add test for K230 decomp gzip Tao Ding
2026-08-06 12:14   ` Daniel Henrique Barboza
2026-07-27 15:57 ` [PATCH v2 7/7] hw/riscv: k230: add a noc stub region in K230 board Tao Ding
2026-08-06 12:15   ` Daniel Henrique Barboza

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260727155702.36484-5-dingtao0430@163.com \
    --to=dingtao0430@163.com \
    --cc=alistair.francis@wdc.com \
    --cc=caojunze424@gmail.com \
    --cc=chao.liu@processmission.com \
    --cc=daniel.barboza@oss.qualcomm.com \
    --cc=farosas@suse.de \
    --cc=liwei1518@gmail.com \
    --cc=lvivier@redhat.com \
    --cc=palmer@dabbelt.com \
    --cc=pbonzini@redhat.com \
    --cc=pierrick.bouvier@oss.qualcomm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=zhiwei_liu@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.