xref: /openbmc/linux/drivers/gpu/drm/lima/lima_gp.c (revision 3dc4b6fb)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
3 
4 #include <linux/interrupt.h>
5 #include <linux/iopoll.h>
6 #include <linux/device.h>
7 #include <linux/slab.h>
8 
9 #include <drm/lima_drm.h>
10 
11 #include "lima_device.h"
12 #include "lima_gp.h"
13 #include "lima_regs.h"
14 
15 #define gp_write(reg, data) writel(data, ip->iomem + reg)
16 #define gp_read(reg) readl(ip->iomem + reg)
17 
18 static irqreturn_t lima_gp_irq_handler(int irq, void *data)
19 {
20 	struct lima_ip *ip = data;
21 	struct lima_device *dev = ip->dev;
22 	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
23 	u32 state = gp_read(LIMA_GP_INT_STAT);
24 	u32 status = gp_read(LIMA_GP_STATUS);
25 	bool done = false;
26 
27 	/* for shared irq case */
28 	if (!state)
29 		return IRQ_NONE;
30 
31 	if (state & LIMA_GP_IRQ_MASK_ERROR) {
32 		dev_err(dev->dev, "gp error irq state=%x status=%x\n",
33 			state, status);
34 
35 		/* mask all interrupts before hard reset */
36 		gp_write(LIMA_GP_INT_MASK, 0);
37 
38 		pipe->error = true;
39 		done = true;
40 	} else {
41 		bool valid = state & (LIMA_GP_IRQ_VS_END_CMD_LST |
42 				      LIMA_GP_IRQ_PLBU_END_CMD_LST);
43 		bool active = status & (LIMA_GP_STATUS_VS_ACTIVE |
44 					LIMA_GP_STATUS_PLBU_ACTIVE);
45 		done = valid && !active;
46 	}
47 
48 	gp_write(LIMA_GP_INT_CLEAR, state);
49 
50 	if (done)
51 		lima_sched_pipe_task_done(pipe);
52 
53 	return IRQ_HANDLED;
54 }
55 
56 static void lima_gp_soft_reset_async(struct lima_ip *ip)
57 {
58 	if (ip->data.async_reset)
59 		return;
60 
61 	gp_write(LIMA_GP_INT_MASK, 0);
62 	gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_RESET_COMPLETED);
63 	gp_write(LIMA_GP_CMD, LIMA_GP_CMD_SOFT_RESET);
64 	ip->data.async_reset = true;
65 }
66 
67 static int lima_gp_soft_reset_async_wait(struct lima_ip *ip)
68 {
69 	struct lima_device *dev = ip->dev;
70 	int err;
71 	u32 v;
72 
73 	if (!ip->data.async_reset)
74 		return 0;
75 
76 	err = readl_poll_timeout(ip->iomem + LIMA_GP_INT_RAWSTAT, v,
77 				 v & LIMA_GP_IRQ_RESET_COMPLETED,
78 				 0, 100);
79 	if (err) {
80 		dev_err(dev->dev, "gp soft reset time out\n");
81 		return err;
82 	}
83 
84 	gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
85 	gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
86 
87 	ip->data.async_reset = false;
88 	return 0;
89 }
90 
91 static int lima_gp_task_validate(struct lima_sched_pipe *pipe,
92 				 struct lima_sched_task *task)
93 {
94 	struct drm_lima_gp_frame *frame = task->frame;
95 	u32 *f = frame->frame;
96 	(void)pipe;
97 
98 	if (f[LIMA_GP_VSCL_START_ADDR >> 2] >
99 	    f[LIMA_GP_VSCL_END_ADDR >> 2] ||
100 	    f[LIMA_GP_PLBUCL_START_ADDR >> 2] >
101 	    f[LIMA_GP_PLBUCL_END_ADDR >> 2] ||
102 	    f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] >
103 	    f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2])
104 		return -EINVAL;
105 
106 	if (f[LIMA_GP_VSCL_START_ADDR >> 2] ==
107 	    f[LIMA_GP_VSCL_END_ADDR >> 2] &&
108 	    f[LIMA_GP_PLBUCL_START_ADDR >> 2] ==
109 	    f[LIMA_GP_PLBUCL_END_ADDR >> 2])
110 		return -EINVAL;
111 
112 	return 0;
113 }
114 
115 static void lima_gp_task_run(struct lima_sched_pipe *pipe,
116 			     struct lima_sched_task *task)
117 {
118 	struct lima_ip *ip = pipe->processor[0];
119 	struct drm_lima_gp_frame *frame = task->frame;
120 	u32 *f = frame->frame;
121 	u32 cmd = 0;
122 	int i;
123 
124 	if (f[LIMA_GP_VSCL_START_ADDR >> 2] !=
125 	    f[LIMA_GP_VSCL_END_ADDR >> 2])
126 		cmd |= LIMA_GP_CMD_START_VS;
127 	if (f[LIMA_GP_PLBUCL_START_ADDR >> 2] !=
128 	    f[LIMA_GP_PLBUCL_END_ADDR >> 2])
129 		cmd |= LIMA_GP_CMD_START_PLBU;
130 
131 	/* before any hw ops, wait last success task async soft reset */
132 	lima_gp_soft_reset_async_wait(ip);
133 
134 	for (i = 0; i < LIMA_GP_FRAME_REG_NUM; i++)
135 		writel(f[i], ip->iomem + LIMA_GP_VSCL_START_ADDR + i * 4);
136 
137 	gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
138 	gp_write(LIMA_GP_CMD, cmd);
139 }
140 
141 static int lima_gp_hard_reset_poll(struct lima_ip *ip)
142 {
143 	gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
144 	return gp_read(LIMA_GP_PERF_CNT_0_LIMIT) == 0xC01A0000;
145 }
146 
147 static int lima_gp_hard_reset(struct lima_ip *ip)
148 {
149 	struct lima_device *dev = ip->dev;
150 	int ret;
151 
152 	gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
153 	gp_write(LIMA_GP_INT_MASK, 0);
154 	gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
155 	ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
156 	if (ret) {
157 		dev_err(dev->dev, "gp hard reset timeout\n");
158 		return ret;
159 	}
160 
161 	gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0);
162 	gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
163 	gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
164 	return 0;
165 }
166 
167 static void lima_gp_task_fini(struct lima_sched_pipe *pipe)
168 {
169 	lima_gp_soft_reset_async(pipe->processor[0]);
170 }
171 
172 static void lima_gp_task_error(struct lima_sched_pipe *pipe)
173 {
174 	struct lima_ip *ip = pipe->processor[0];
175 
176 	dev_err(ip->dev->dev, "gp task error int_state=%x status=%x\n",
177 		gp_read(LIMA_GP_INT_STAT), gp_read(LIMA_GP_STATUS));
178 
179 	lima_gp_hard_reset(ip);
180 }
181 
182 static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe)
183 {
184 	lima_sched_pipe_task_done(pipe);
185 }
186 
187 static void lima_gp_print_version(struct lima_ip *ip)
188 {
189 	u32 version, major, minor;
190 	char *name;
191 
192 	version = gp_read(LIMA_GP_VERSION);
193 	major = (version >> 8) & 0xFF;
194 	minor = version & 0xFF;
195 	switch (version >> 16) {
196 	case 0xA07:
197 	    name = "mali200";
198 		break;
199 	case 0xC07:
200 		name = "mali300";
201 		break;
202 	case 0xB07:
203 		name = "mali400";
204 		break;
205 	case 0xD07:
206 		name = "mali450";
207 		break;
208 	default:
209 		name = "unknown";
210 		break;
211 	}
212 	dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n",
213 		 lima_ip_name(ip), name, major, minor);
214 }
215 
216 static struct kmem_cache *lima_gp_task_slab;
217 static int lima_gp_task_slab_refcnt;
218 
219 int lima_gp_init(struct lima_ip *ip)
220 {
221 	struct lima_device *dev = ip->dev;
222 	int err;
223 
224 	lima_gp_print_version(ip);
225 
226 	ip->data.async_reset = false;
227 	lima_gp_soft_reset_async(ip);
228 	err = lima_gp_soft_reset_async_wait(ip);
229 	if (err)
230 		return err;
231 
232 	err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler,
233 			       IRQF_SHARED, lima_ip_name(ip), ip);
234 	if (err) {
235 		dev_err(dev->dev, "gp %s fail to request irq\n",
236 			lima_ip_name(ip));
237 		return err;
238 	}
239 
240 	dev->gp_version = gp_read(LIMA_GP_VERSION);
241 
242 	return 0;
243 }
244 
245 void lima_gp_fini(struct lima_ip *ip)
246 {
247 
248 }
249 
250 int lima_gp_pipe_init(struct lima_device *dev)
251 {
252 	int frame_size = sizeof(struct drm_lima_gp_frame);
253 	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
254 
255 	if (!lima_gp_task_slab) {
256 		lima_gp_task_slab = kmem_cache_create_usercopy(
257 			"lima_gp_task", sizeof(struct lima_sched_task) + frame_size,
258 			0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task),
259 			frame_size, NULL);
260 		if (!lima_gp_task_slab)
261 			return -ENOMEM;
262 	}
263 	lima_gp_task_slab_refcnt++;
264 
265 	pipe->frame_size = frame_size;
266 	pipe->task_slab = lima_gp_task_slab;
267 
268 	pipe->task_validate = lima_gp_task_validate;
269 	pipe->task_run = lima_gp_task_run;
270 	pipe->task_fini = lima_gp_task_fini;
271 	pipe->task_error = lima_gp_task_error;
272 	pipe->task_mmu_error = lima_gp_task_mmu_error;
273 
274 	return 0;
275 }
276 
277 void lima_gp_pipe_fini(struct lima_device *dev)
278 {
279 	if (!--lima_gp_task_slab_refcnt) {
280 		kmem_cache_destroy(lima_gp_task_slab);
281 		lima_gp_task_slab = NULL;
282 	}
283 }
284