xref: /rk3399_rockchip-uboot/drivers/misc/rockchip_decompress.c (revision 008ec9b4bc06f98dd7efdc7d2f44eb066be036e6)
1 // SPDX-License-Identifier:     GPL-2.0+
2 /*
3  * Copyright (C) 2019 Rockchip Electronics Co., Ltd
4  */
5 #include <common.h>
6 #include <asm/io.h>
7 #include <dm.h>
8 #include <linux/bitops.h>
9 #include <misc.h>
10 #include <irq-generic.h>
11 
12 DECLARE_GLOBAL_DATA_PTR;
13 
14 #define DECOM_CTRL		0x0
15 #define DECOM_ENR		0x4
16 #define DECOM_RADDR		0x8
17 #define DECOM_WADDR		0xc
18 #define DECOM_UDDSL		0x10
19 #define DECOM_UDDSH		0x14
20 #define DECOM_TXTHR		0x18
21 #define DECOM_RXTHR		0x1c
22 #define DECOM_SLEN		0x20
23 #define DECOM_STAT		0x24
24 #define DECOM_ISR		0x28
25 #define DECOM_IEN		0x2c
26 #define DECOM_AXI_STAT		0x30
27 #define DECOM_TSIZEL		0x34
28 #define DECOM_TSIZEH		0x38
29 #define DECOM_MGNUM		0x3c
30 #define DECOM_FRAME		0x40
31 #define DECOM_DICTID		0x44
32 #define DECOM_CSL		0x48
33 #define DECOM_CSH		0x4c
34 
35 #define LZ4_HEAD_CSUM_CHECK_EN	BIT(1)
36 #define LZ4_BLOCK_CSUM_CHECK_EN	BIT(2)
37 #define LZ4_CONT_CSUM_CHECK_EN	BIT(3)
38 
39 #define DSOLIEN			BIT(19)
40 #define ZDICTEIEN		BIT(18)
41 #define GCMEIEN			BIT(17)
42 #define GIDEIEN			BIT(16)
43 #define CCCEIEN			BIT(15)
44 #define BCCEIEN			BIT(14)
45 #define HCCEIEN			BIT(13)
46 #define CSEIEN			BIT(12)
47 #define DICTEIEN		BIT(11)
48 #define VNEIEN			BIT(10)
49 #define WNEIEN			BIT(9)
50 #define RDCEIEN			BIT(8)
51 #define WRCEIEN			BIT(7)
52 #define DISEIEN			BIT(6)
53 #define LENEIEN			BIT(5)
54 #define LITEIEN			BIT(4)
55 #define SQMEIEN			BIT(3)
56 #define SLCIEN			BIT(2)
57 #define HDEIEN			BIT(1)
58 #define DSIEN			BIT(0)
59 
60 #define DECOM_STOP		BIT(0)
61 #define DECOM_COMPLETE		BIT(0)
62 #define DECOM_GZIP_MODE		BIT(4)
63 #define DECOM_ZLIB_MODE		BIT(5)
64 #define DECOM_DEFLATE_MODE	BIT(0)
65 
66 #define DECOM_ENABLE		0x1
67 #define DECOM_DISABLE		0x0
68 
69 #define DECOM_IRQ		0xffff /* fixme */
70 
71 #define DECOM_INT_MASK \
72 	(DSOLIEN | ZDICTEIEN | GCMEIEN | GIDEIEN | \
73 	CCCEIEN | BCCEIEN | HCCEIEN | CSEIEN | \
74 	DICTEIEN | VNEIEN | WNEIEN | RDCEIEN | WRCEIEN | \
75 	DISEIEN | LENEIEN | LITEIEN | SQMEIEN | SLCIEN | \
76 	HDEIEN | DSIEN)
77 
78 enum decom_mod {
79 	LZ4_MOD,
80 	GZIP_MOD,
81 	ZLIB_MOD,
82 };
83 
84 struct rockchip_decom_param {
85 	unsigned long addr_src;
86 	unsigned long addr_dst;
87 	unsigned long size;
88 	enum decom_mod mode;
89 };
90 
91 struct rockchip_decom_priv {
92 	void __iomem *base;
93 	bool done;
94 };
95 
96 static int rockchip_decom_start(struct udevice *dev, void *buf)
97 {
98 	struct rockchip_decom_priv *priv = dev_get_priv(dev);
99 	struct rockchip_decom_param *param = (struct rockchip_decom_param *)buf;
100 
101 	priv->done = false;
102 
103 	if (param->mode == LZ4_MOD)
104 		writel(LZ4_CONT_CSUM_CHECK_EN |
105 		       LZ4_HEAD_CSUM_CHECK_EN |
106 		       LZ4_BLOCK_CSUM_CHECK_EN |
107 		       LZ4_MOD, priv->base + DECOM_CTRL);
108 
109 	if (param->mode == GZIP_MOD)
110 		writel(DECOM_DEFLATE_MODE | DECOM_GZIP_MODE,
111 		       priv->base + DECOM_CTRL);
112 
113 	if (param->mode == ZLIB_MOD)
114 		writel(DECOM_DEFLATE_MODE | DECOM_ZLIB_MODE,
115 		       priv->base + DECOM_CTRL);
116 
117 	writel(param->addr_src, priv->base + DECOM_RADDR);
118 	writel(param->addr_dst, priv->base + DECOM_WADDR);
119 
120 	writel(DECOM_INT_MASK, priv->base + DECOM_IEN);
121 	writel(DECOM_ENABLE, priv->base + DECOM_ENR);
122 
123 	return 0;
124 }
125 
126 static int rockchip_decom_stop(struct udevice *dev)
127 {
128 	struct rockchip_decom_priv *priv = dev_get_priv(dev);
129 	int irq_status;
130 
131 	irq_status = readl(priv->base + DECOM_ISR);
132 	/* clear interrupts */
133 	if (irq_status)
134 		writel(irq_status, priv->base + DECOM_ISR);
135 
136 	writel(DECOM_DISABLE, priv->base + DECOM_ENR);
137 
138 	return 0;
139 }
140 
141 /* Caller must call this function to check if decompress done */
142 static int rockchip_decom_done_poll(struct udevice *dev)
143 {
144 	struct rockchip_decom_priv *priv = dev_get_priv(dev);
145 	int decom_status;
146 
147 	decom_status = readl(priv->base + DECOM_STAT);
148 	if (decom_status & DECOM_COMPLETE)
149 		return 0;
150 
151 	return -EINVAL;
152 }
153 
154 /* Caller must fill in param @buf which represent struct rockchip_decom_param */
155 static int rockchip_decom_ioctl(struct udevice *dev, unsigned long request,
156 				void *buf)
157 {
158 	int ret = -EINVAL;
159 
160 	switch (request) {
161 	case IOCTL_REQ_START:
162 		ret = rockchip_decom_start(dev, buf);
163 		break;
164 	case IOCTL_REQ_POLL:
165 		ret = rockchip_decom_done_poll(dev);
166 		break;
167 	case IOCTL_REQ_STOP:
168 		ret = rockchip_decom_stop(dev);
169 		break;
170 	}
171 
172 	return ret;
173 }
174 
175 static const struct misc_ops rockchip_decom_ops = {
176 	.ioctl = rockchip_decom_ioctl,
177 };
178 
179 static int rockchip_decom_ofdata_to_platdata(struct udevice *dev)
180 {
181 	struct rockchip_decom_priv *priv = dev_get_priv(dev);
182 
183 	priv->base = dev_read_addr_ptr(dev);
184 	if (!priv->base)
185 		return -ENOENT;
186 
187 	return 0;
188 }
189 
190 #ifndef CONFIG_SPL_BUILD
191 static void rockchip_decom_irqhandler(int irq, void *data)
192 {
193 	struct udevice *dev = data;
194 	struct rockchip_decom_priv *priv = dev_get_priv(dev);
195 	int irq_status;
196 	int decom_status;
197 
198 	irq_status = readl(priv->base + DECOM_ISR);
199 	/* clear interrupts */
200 	writel(irq_status, priv->base + DECOM_ISR);
201 	if (irq_status & DECOM_STOP) {
202 		decom_status = readl(priv->base + DECOM_STAT);
203 		if (decom_status & DECOM_COMPLETE) {
204 			priv->done = true;
205 			/*
206 			 * TODO:
207 			 * Inform someone that decompress completed
208 			 */
209 			printf("decom completed\n");
210 		} else {
211 			printf("decom failed, irq_status = 0x%x, decom_status = 0x%x\n",
212 			       irq_status, decom_status);
213 		}
214 	}
215 }
216 #endif
217 
218 static int rockchip_decom_probe(struct udevice *dev)
219 {
220 #ifndef CONFIG_SPL_BUILD
221 	irq_install_handler(DECOM_IRQ, rockchip_decom_irqhandler, dev);
222 	irq_handler_enable(DECOM_IRQ);
223 #endif
224 	return 0;
225 }
226 
227 static const struct udevice_id rockchip_decom_ids[] = {
228 	{ .compatible = "rockchip,hw-decompress" },
229 	{}
230 };
231 
232 U_BOOT_DRIVER(rockchip_hw_decompress) = {
233 	.name = "rockchip_hw_decompress",
234 	.id = UCLASS_MISC,
235 	.of_match = rockchip_decom_ids,
236 	.probe = rockchip_decom_probe,
237 	.ofdata_to_platdata = rockchip_decom_ofdata_to_platdata,
238 	.priv_auto_alloc_size = sizeof(struct rockchip_decom_priv),
239 	.ops = &rockchip_decom_ops,
240 };
241