lima_pp.c (10398B)
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/io.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_pp.h" 13#include "lima_dlbu.h" 14#include "lima_bcast.h" 15#include "lima_vm.h" 16#include "lima_regs.h" 17 18#define pp_write(reg, data) writel(data, ip->iomem + reg) 19#define pp_read(reg) readl(ip->iomem + reg) 20 21static void lima_pp_handle_irq(struct lima_ip *ip, u32 state) 22{ 23 struct lima_device *dev = ip->dev; 24 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; 25 26 if (state & LIMA_PP_IRQ_MASK_ERROR) { 27 u32 status = pp_read(LIMA_PP_STATUS); 28 29 dev_err(dev->dev, "pp error irq state=%x status=%x\n", 30 state, status); 31 32 pipe->error = true; 33 34 /* mask all interrupts before hard reset */ 35 pp_write(LIMA_PP_INT_MASK, 0); 36 } 37 38 pp_write(LIMA_PP_INT_CLEAR, state); 39} 40 41static irqreturn_t lima_pp_irq_handler(int irq, void *data) 42{ 43 struct lima_ip *ip = data; 44 struct lima_device *dev = ip->dev; 45 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; 46 u32 state = pp_read(LIMA_PP_INT_STATUS); 47 48 /* for shared irq case */ 49 if (!state) 50 return IRQ_NONE; 51 52 lima_pp_handle_irq(ip, state); 53 54 if (atomic_dec_and_test(&pipe->task)) 55 lima_sched_pipe_task_done(pipe); 56 57 return IRQ_HANDLED; 58} 59 60static irqreturn_t lima_pp_bcast_irq_handler(int irq, void *data) 61{ 62 int i; 63 irqreturn_t ret = IRQ_NONE; 64 struct lima_ip *pp_bcast = data; 65 struct lima_device *dev = pp_bcast->dev; 66 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; 67 struct drm_lima_m450_pp_frame *frame; 68 69 /* for shared irq case */ 70 if (!pipe->current_task) 71 return IRQ_NONE; 72 73 frame = pipe->current_task->frame; 74 75 for (i = 0; i < frame->num_pp; i++) { 76 struct lima_ip *ip = pipe->processor[i]; 77 u32 status, state; 78 79 if (pipe->done & (1 << i)) 80 continue; 81 82 /* status read first in case int state change in the middle 83 * which may miss the interrupt handling 84 */ 85 status = pp_read(LIMA_PP_STATUS); 86 state = pp_read(LIMA_PP_INT_STATUS); 87 88 if (state) { 89 lima_pp_handle_irq(ip, state); 90 ret = IRQ_HANDLED; 91 } else { 92 if (status & LIMA_PP_STATUS_RENDERING_ACTIVE) 93 continue; 94 } 95 96 pipe->done |= (1 << i); 97 if (atomic_dec_and_test(&pipe->task)) 98 lima_sched_pipe_task_done(pipe); 99 } 100 101 return ret; 102} 103 104static void lima_pp_soft_reset_async(struct lima_ip *ip) 105{ 106 if (ip->data.async_reset) 107 return; 108 109 pp_write(LIMA_PP_INT_MASK, 0); 110 pp_write(LIMA_PP_INT_RAWSTAT, LIMA_PP_IRQ_MASK_ALL); 111 pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_SOFT_RESET); 112 ip->data.async_reset = true; 113} 114 115static int lima_pp_soft_reset_poll(struct lima_ip *ip) 116{ 117 return !(pp_read(LIMA_PP_STATUS) & LIMA_PP_STATUS_RENDERING_ACTIVE) && 118 pp_read(LIMA_PP_INT_RAWSTAT) == LIMA_PP_IRQ_RESET_COMPLETED; 119} 120 121static int lima_pp_soft_reset_async_wait_one(struct lima_ip *ip) 122{ 123 struct lima_device *dev = ip->dev; 124 int ret; 125 126 ret = lima_poll_timeout(ip, lima_pp_soft_reset_poll, 0, 100); 127 if (ret) { 128 dev_err(dev->dev, "pp %s reset time out\n", lima_ip_name(ip)); 129 return ret; 130 } 131 132 pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL); 133 pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED); 134 return 0; 135} 136 137static int lima_pp_soft_reset_async_wait(struct lima_ip *ip) 138{ 139 int i, err = 0; 140 141 if (!ip->data.async_reset) 142 return 0; 143 144 if (ip->id == lima_ip_pp_bcast) { 145 struct lima_device *dev = ip->dev; 146 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; 147 struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame; 148 149 for (i = 0; i < frame->num_pp; i++) 150 err |= lima_pp_soft_reset_async_wait_one(pipe->processor[i]); 151 } else 152 err = lima_pp_soft_reset_async_wait_one(ip); 153 154 ip->data.async_reset = false; 155 return err; 156} 157 158static void lima_pp_write_frame(struct lima_ip *ip, u32 *frame, u32 *wb) 159{ 160 int i, j, n = 0; 161 162 for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++) 163 writel(frame[i], ip->iomem + LIMA_PP_FRAME + i * 4); 164 165 for (i = 0; i < 3; i++) { 166 for (j = 0; j < LIMA_PP_WB_REG_NUM; j++) 167 writel(wb[n++], ip->iomem + LIMA_PP_WB(i) + j * 4); 168 } 169} 170 171static int lima_pp_hard_reset_poll(struct lima_ip *ip) 172{ 173 pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC01A0000); 174 return pp_read(LIMA_PP_PERF_CNT_0_LIMIT) == 0xC01A0000; 175} 176 177static int lima_pp_hard_reset(struct lima_ip *ip) 178{ 179 struct lima_device *dev = ip->dev; 180 int ret; 181 182 pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC0FFE000); 183 pp_write(LIMA_PP_INT_MASK, 0); 184 pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_FORCE_RESET); 185 ret = lima_poll_timeout(ip, lima_pp_hard_reset_poll, 10, 100); 186 if (ret) { 187 dev_err(dev->dev, "pp hard reset timeout\n"); 188 return ret; 189 } 190 191 pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0); 192 pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL); 193 pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED); 194 return 0; 195} 196 197static void lima_pp_print_version(struct lima_ip *ip) 198{ 199 u32 version, major, minor; 200 char *name; 201 202 version = pp_read(LIMA_PP_VERSION); 203 major = (version >> 8) & 0xFF; 204 minor = version & 0xFF; 205 switch (version >> 16) { 206 case 0xC807: 207 name = "mali200"; 208 break; 209 case 0xCE07: 210 name = "mali300"; 211 break; 212 case 0xCD07: 213 name = "mali400"; 214 break; 215 case 0xCF07: 216 name = "mali450"; 217 break; 218 default: 219 name = "unknown"; 220 break; 221 } 222 dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n", 223 lima_ip_name(ip), name, major, minor); 224} 225 226static int lima_pp_hw_init(struct lima_ip *ip) 227{ 228 ip->data.async_reset = false; 229 lima_pp_soft_reset_async(ip); 230 return lima_pp_soft_reset_async_wait(ip); 231} 232 233int lima_pp_resume(struct lima_ip *ip) 234{ 235 return lima_pp_hw_init(ip); 236} 237 238void lima_pp_suspend(struct lima_ip *ip) 239{ 240 241} 242 243int lima_pp_init(struct lima_ip *ip) 244{ 245 struct lima_device *dev = ip->dev; 246 int err; 247 248 lima_pp_print_version(ip); 249 250 err = lima_pp_hw_init(ip); 251 if (err) 252 return err; 253 254 err = devm_request_irq(dev->dev, ip->irq, lima_pp_irq_handler, 255 IRQF_SHARED, lima_ip_name(ip), ip); 256 if (err) { 257 dev_err(dev->dev, "pp %s fail to request irq\n", 258 lima_ip_name(ip)); 259 return err; 260 } 261 262 dev->pp_version = pp_read(LIMA_PP_VERSION); 263 264 return 0; 265} 266 267void lima_pp_fini(struct lima_ip *ip) 268{ 269 270} 271 272int lima_pp_bcast_resume(struct lima_ip *ip) 273{ 274 /* PP has been reset by individual PP resume */ 275 ip->data.async_reset = false; 276 return 0; 277} 278 279void lima_pp_bcast_suspend(struct lima_ip *ip) 280{ 281 282} 283 284int lima_pp_bcast_init(struct lima_ip *ip) 285{ 286 struct lima_device *dev = ip->dev; 287 int err; 288 289 err = devm_request_irq(dev->dev, ip->irq, lima_pp_bcast_irq_handler, 290 IRQF_SHARED, lima_ip_name(ip), ip); 291 if (err) { 292 dev_err(dev->dev, "pp %s fail to request irq\n", 293 lima_ip_name(ip)); 294 return err; 295 } 296 297 return 0; 298} 299 300void lima_pp_bcast_fini(struct lima_ip *ip) 301{ 302 303} 304 305static int lima_pp_task_validate(struct lima_sched_pipe *pipe, 306 struct lima_sched_task *task) 307{ 308 u32 num_pp; 309 310 if (pipe->bcast_processor) { 311 struct drm_lima_m450_pp_frame *f = task->frame; 312 313 num_pp = f->num_pp; 314 315 if (f->_pad) 316 return -EINVAL; 317 } else { 318 struct drm_lima_m400_pp_frame *f = task->frame; 319 320 num_pp = f->num_pp; 321 } 322 323 if (num_pp == 0 || num_pp > pipe->num_processor) 324 return -EINVAL; 325 326 return 0; 327} 328 329static void lima_pp_task_run(struct lima_sched_pipe *pipe, 330 struct lima_sched_task *task) 331{ 332 if (pipe->bcast_processor) { 333 struct drm_lima_m450_pp_frame *frame = task->frame; 334 struct lima_device *dev = pipe->bcast_processor->dev; 335 struct lima_ip *ip = pipe->bcast_processor; 336 int i; 337 338 pipe->done = 0; 339 atomic_set(&pipe->task, frame->num_pp); 340 341 if (frame->use_dlbu) { 342 lima_dlbu_enable(dev, frame->num_pp); 343 344 frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU; 345 lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs); 346 } else 347 lima_dlbu_disable(dev); 348 349 lima_bcast_enable(dev, frame->num_pp); 350 351 lima_pp_soft_reset_async_wait(ip); 352 353 lima_pp_write_frame(ip, frame->frame, frame->wb); 354 355 for (i = 0; i < frame->num_pp; i++) { 356 struct lima_ip *ip = pipe->processor[i]; 357 358 pp_write(LIMA_PP_STACK, frame->fragment_stack_address[i]); 359 if (!frame->use_dlbu) 360 pp_write(LIMA_PP_FRAME, frame->plbu_array_address[i]); 361 } 362 363 pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_START_RENDERING); 364 } else { 365 struct drm_lima_m400_pp_frame *frame = task->frame; 366 int i; 367 368 atomic_set(&pipe->task, frame->num_pp); 369 370 for (i = 0; i < frame->num_pp; i++) { 371 struct lima_ip *ip = pipe->processor[i]; 372 373 frame->frame[LIMA_PP_FRAME >> 2] = 374 frame->plbu_array_address[i]; 375 frame->frame[LIMA_PP_STACK >> 2] = 376 frame->fragment_stack_address[i]; 377 378 lima_pp_soft_reset_async_wait(ip); 379 380 lima_pp_write_frame(ip, frame->frame, frame->wb); 381 382 pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_START_RENDERING); 383 } 384 } 385} 386 387static void lima_pp_task_fini(struct lima_sched_pipe *pipe) 388{ 389 if (pipe->bcast_processor) 390 lima_pp_soft_reset_async(pipe->bcast_processor); 391 else { 392 int i; 393 394 for (i = 0; i < pipe->num_processor; i++) 395 lima_pp_soft_reset_async(pipe->processor[i]); 396 } 397} 398 399static void lima_pp_task_error(struct lima_sched_pipe *pipe) 400{ 401 int i; 402 403 for (i = 0; i < pipe->num_processor; i++) { 404 struct lima_ip *ip = pipe->processor[i]; 405 406 dev_err(ip->dev->dev, "pp task error %d int_state=%x status=%x\n", 407 i, pp_read(LIMA_PP_INT_STATUS), pp_read(LIMA_PP_STATUS)); 408 409 lima_pp_hard_reset(ip); 410 } 411} 412 413static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe) 414{ 415 if (atomic_dec_and_test(&pipe->task)) 416 lima_sched_pipe_task_done(pipe); 417} 418 419static struct kmem_cache *lima_pp_task_slab; 420static int lima_pp_task_slab_refcnt; 421 422int lima_pp_pipe_init(struct lima_device *dev) 423{ 424 int frame_size; 425 struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; 426 427 if (dev->id == lima_gpu_mali400) 428 frame_size = sizeof(struct drm_lima_m400_pp_frame); 429 else 430 frame_size = sizeof(struct drm_lima_m450_pp_frame); 431 432 if (!lima_pp_task_slab) { 433 lima_pp_task_slab = kmem_cache_create_usercopy( 434 "lima_pp_task", sizeof(struct lima_sched_task) + frame_size, 435 0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task), 436 frame_size, NULL); 437 if (!lima_pp_task_slab) 438 return -ENOMEM; 439 } 440 lima_pp_task_slab_refcnt++; 441 442 pipe->frame_size = frame_size; 443 pipe->task_slab = lima_pp_task_slab; 444 445 pipe->task_validate = lima_pp_task_validate; 446 pipe->task_run = lima_pp_task_run; 447 pipe->task_fini = lima_pp_task_fini; 448 pipe->task_error = lima_pp_task_error; 449 pipe->task_mmu_error = lima_pp_task_mmu_error; 450 451 return 0; 452} 453 454void lima_pp_pipe_fini(struct lima_device *dev) 455{ 456 if (!--lima_pp_task_slab_refcnt) { 457 kmem_cache_destroy(lima_pp_task_slab); 458 lima_pp_task_slab = NULL; 459 } 460}