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