root/drivers/gpu/drm/lima/lima_pp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lima_pp_handle_irq
  2. lima_pp_irq_handler
  3. lima_pp_bcast_irq_handler
  4. lima_pp_soft_reset_async
  5. lima_pp_soft_reset_poll
  6. lima_pp_soft_reset_async_wait_one
  7. lima_pp_soft_reset_async_wait
  8. lima_pp_write_frame
  9. lima_pp_hard_reset_poll
  10. lima_pp_hard_reset
  11. lima_pp_print_version
  12. lima_pp_init
  13. lima_pp_fini
  14. lima_pp_bcast_init
  15. lima_pp_bcast_fini
  16. lima_pp_task_validate
  17. lima_pp_task_run
  18. lima_pp_task_fini
  19. lima_pp_task_error
  20. lima_pp_task_mmu_error
  21. lima_pp_pipe_init
  22. lima_pp_pipe_fini

   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 
  21 static 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 
  41 static 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 
  60 static 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 
 104 static 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 
 115 static 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 
 121 static 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 
 137 static 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 
 158 static 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 
 171 static 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 
 177 static 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 
 197 static 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 
 226 int lima_pp_init(struct lima_ip *ip)
 227 {
 228         struct lima_device *dev = ip->dev;
 229         int err;
 230 
 231         lima_pp_print_version(ip);
 232 
 233         ip->data.async_reset = false;
 234         lima_pp_soft_reset_async(ip);
 235         err = lima_pp_soft_reset_async_wait(ip);
 236         if (err)
 237                 return err;
 238 
 239         err = devm_request_irq(dev->dev, ip->irq, lima_pp_irq_handler,
 240                                IRQF_SHARED, lima_ip_name(ip), ip);
 241         if (err) {
 242                 dev_err(dev->dev, "pp %s fail to request irq\n",
 243                         lima_ip_name(ip));
 244                 return err;
 245         }
 246 
 247         dev->pp_version = pp_read(LIMA_PP_VERSION);
 248 
 249         return 0;
 250 }
 251 
 252 void lima_pp_fini(struct lima_ip *ip)
 253 {
 254 
 255 }
 256 
 257 int lima_pp_bcast_init(struct lima_ip *ip)
 258 {
 259         struct lima_device *dev = ip->dev;
 260         int err;
 261 
 262         err = devm_request_irq(dev->dev, ip->irq, lima_pp_bcast_irq_handler,
 263                                IRQF_SHARED, lima_ip_name(ip), ip);
 264         if (err) {
 265                 dev_err(dev->dev, "pp %s fail to request irq\n",
 266                         lima_ip_name(ip));
 267                 return err;
 268         }
 269 
 270         return 0;
 271 }
 272 
 273 void lima_pp_bcast_fini(struct lima_ip *ip)
 274 {
 275 
 276 }
 277 
 278 static int lima_pp_task_validate(struct lima_sched_pipe *pipe,
 279                                  struct lima_sched_task *task)
 280 {
 281         u32 num_pp;
 282 
 283         if (pipe->bcast_processor) {
 284                 struct drm_lima_m450_pp_frame *f = task->frame;
 285 
 286                 num_pp = f->num_pp;
 287 
 288                 if (f->_pad)
 289                         return -EINVAL;
 290         } else {
 291                 struct drm_lima_m400_pp_frame *f = task->frame;
 292 
 293                 num_pp = f->num_pp;
 294         }
 295 
 296         if (num_pp == 0 || num_pp > pipe->num_processor)
 297                 return -EINVAL;
 298 
 299         return 0;
 300 }
 301 
 302 static void lima_pp_task_run(struct lima_sched_pipe *pipe,
 303                              struct lima_sched_task *task)
 304 {
 305         if (pipe->bcast_processor) {
 306                 struct drm_lima_m450_pp_frame *frame = task->frame;
 307                 struct lima_device *dev = pipe->bcast_processor->dev;
 308                 struct lima_ip *ip = pipe->bcast_processor;
 309                 int i;
 310 
 311                 pipe->done = 0;
 312                 atomic_set(&pipe->task, frame->num_pp);
 313 
 314                 if (frame->use_dlbu) {
 315                         lima_dlbu_enable(dev, frame->num_pp);
 316 
 317                         frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU;
 318                         lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs);
 319                 } else
 320                         lima_dlbu_disable(dev);
 321 
 322                 lima_bcast_enable(dev, frame->num_pp);
 323 
 324                 lima_pp_soft_reset_async_wait(ip);
 325 
 326                 lima_pp_write_frame(ip, frame->frame, frame->wb);
 327 
 328                 for (i = 0; i < frame->num_pp; i++) {
 329                         struct lima_ip *ip = pipe->processor[i];
 330 
 331                         pp_write(LIMA_PP_STACK, frame->fragment_stack_address[i]);
 332                         if (!frame->use_dlbu)
 333                                 pp_write(LIMA_PP_FRAME, frame->plbu_array_address[i]);
 334                 }
 335 
 336                 pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_START_RENDERING);
 337         } else {
 338                 struct drm_lima_m400_pp_frame *frame = task->frame;
 339                 int i;
 340 
 341                 atomic_set(&pipe->task, frame->num_pp);
 342 
 343                 for (i = 0; i < frame->num_pp; i++) {
 344                         struct lima_ip *ip = pipe->processor[i];
 345 
 346                         frame->frame[LIMA_PP_FRAME >> 2] =
 347                                 frame->plbu_array_address[i];
 348                         frame->frame[LIMA_PP_STACK >> 2] =
 349                                 frame->fragment_stack_address[i];
 350 
 351                         lima_pp_soft_reset_async_wait(ip);
 352 
 353                         lima_pp_write_frame(ip, frame->frame, frame->wb);
 354 
 355                         pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_START_RENDERING);
 356                 }
 357         }
 358 }
 359 
 360 static void lima_pp_task_fini(struct lima_sched_pipe *pipe)
 361 {
 362         if (pipe->bcast_processor)
 363                 lima_pp_soft_reset_async(pipe->bcast_processor);
 364         else {
 365                 int i;
 366 
 367                 for (i = 0; i < pipe->num_processor; i++)
 368                         lima_pp_soft_reset_async(pipe->processor[i]);
 369         }
 370 }
 371 
 372 static void lima_pp_task_error(struct lima_sched_pipe *pipe)
 373 {
 374         int i;
 375 
 376         for (i = 0; i < pipe->num_processor; i++) {
 377                 struct lima_ip *ip = pipe->processor[i];
 378 
 379                 dev_err(ip->dev->dev, "pp task error %d int_state=%x status=%x\n",
 380                         i, pp_read(LIMA_PP_INT_STATUS), pp_read(LIMA_PP_STATUS));
 381 
 382                 lima_pp_hard_reset(ip);
 383         }
 384 }
 385 
 386 static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe)
 387 {
 388         if (atomic_dec_and_test(&pipe->task))
 389                 lima_sched_pipe_task_done(pipe);
 390 }
 391 
 392 static struct kmem_cache *lima_pp_task_slab;
 393 static int lima_pp_task_slab_refcnt;
 394 
 395 int lima_pp_pipe_init(struct lima_device *dev)
 396 {
 397         int frame_size;
 398         struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
 399 
 400         if (dev->id == lima_gpu_mali400)
 401                 frame_size = sizeof(struct drm_lima_m400_pp_frame);
 402         else
 403                 frame_size = sizeof(struct drm_lima_m450_pp_frame);
 404 
 405         if (!lima_pp_task_slab) {
 406                 lima_pp_task_slab = kmem_cache_create_usercopy(
 407                         "lima_pp_task", sizeof(struct lima_sched_task) + frame_size,
 408                         0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task),
 409                         frame_size, NULL);
 410                 if (!lima_pp_task_slab)
 411                         return -ENOMEM;
 412         }
 413         lima_pp_task_slab_refcnt++;
 414 
 415         pipe->frame_size = frame_size;
 416         pipe->task_slab = lima_pp_task_slab;
 417 
 418         pipe->task_validate = lima_pp_task_validate;
 419         pipe->task_run = lima_pp_task_run;
 420         pipe->task_fini = lima_pp_task_fini;
 421         pipe->task_error = lima_pp_task_error;
 422         pipe->task_mmu_error = lima_pp_task_mmu_error;
 423 
 424         return 0;
 425 }
 426 
 427 void lima_pp_pipe_fini(struct lima_device *dev)
 428 {
 429         if (!--lima_pp_task_slab_refcnt) {
 430                 kmem_cache_destroy(lima_pp_task_slab);
 431                 lima_pp_task_slab = NULL;
 432         }
 433 }

/* [<][>][^][v][top][bottom][index][help] */