Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR MIT
0002 /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
0003 
0004 #include <linux/interrupt.h>
0005 #include <linux/iopoll.h>
0006 #include <linux/device.h>
0007 #include <linux/slab.h>
0008 
0009 #include <drm/lima_drm.h>
0010 
0011 #include "lima_device.h"
0012 #include "lima_gp.h"
0013 #include "lima_regs.h"
0014 #include "lima_gem.h"
0015 #include "lima_vm.h"
0016 
0017 #define gp_write(reg, data) writel(data, ip->iomem + reg)
0018 #define gp_read(reg) readl(ip->iomem + reg)
0019 
0020 static irqreturn_t lima_gp_irq_handler(int irq, void *data)
0021 {
0022     struct lima_ip *ip = data;
0023     struct lima_device *dev = ip->dev;
0024     struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
0025     struct lima_sched_task *task = pipe->current_task;
0026     u32 state = gp_read(LIMA_GP_INT_STAT);
0027     u32 status = gp_read(LIMA_GP_STATUS);
0028     bool done = false;
0029 
0030     /* for shared irq case */
0031     if (!state)
0032         return IRQ_NONE;
0033 
0034     if (state & LIMA_GP_IRQ_MASK_ERROR) {
0035         if ((state & LIMA_GP_IRQ_MASK_ERROR) ==
0036             LIMA_GP_IRQ_PLBU_OUT_OF_MEM) {
0037             dev_dbg(dev->dev, "gp out of heap irq status=%x\n",
0038                 status);
0039         } else {
0040             dev_err(dev->dev, "gp error irq state=%x status=%x\n",
0041                 state, status);
0042             if (task)
0043                 task->recoverable = false;
0044         }
0045 
0046         /* mask all interrupts before hard reset */
0047         gp_write(LIMA_GP_INT_MASK, 0);
0048 
0049         pipe->error = true;
0050         done = true;
0051     } else {
0052         bool valid = state & (LIMA_GP_IRQ_VS_END_CMD_LST |
0053                       LIMA_GP_IRQ_PLBU_END_CMD_LST);
0054         bool active = status & (LIMA_GP_STATUS_VS_ACTIVE |
0055                     LIMA_GP_STATUS_PLBU_ACTIVE);
0056         done = valid && !active;
0057         pipe->error = false;
0058     }
0059 
0060     gp_write(LIMA_GP_INT_CLEAR, state);
0061 
0062     if (done)
0063         lima_sched_pipe_task_done(pipe);
0064 
0065     return IRQ_HANDLED;
0066 }
0067 
0068 static void lima_gp_soft_reset_async(struct lima_ip *ip)
0069 {
0070     if (ip->data.async_reset)
0071         return;
0072 
0073     gp_write(LIMA_GP_INT_MASK, 0);
0074     gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_RESET_COMPLETED);
0075     gp_write(LIMA_GP_CMD, LIMA_GP_CMD_SOFT_RESET);
0076     ip->data.async_reset = true;
0077 }
0078 
0079 static int lima_gp_soft_reset_async_wait(struct lima_ip *ip)
0080 {
0081     struct lima_device *dev = ip->dev;
0082     int err;
0083     u32 v;
0084 
0085     if (!ip->data.async_reset)
0086         return 0;
0087 
0088     err = readl_poll_timeout(ip->iomem + LIMA_GP_INT_RAWSTAT, v,
0089                  v & LIMA_GP_IRQ_RESET_COMPLETED,
0090                  0, 100);
0091     if (err) {
0092         dev_err(dev->dev, "gp soft reset time out\n");
0093         return err;
0094     }
0095 
0096     gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
0097     gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
0098 
0099     ip->data.async_reset = false;
0100     return 0;
0101 }
0102 
0103 static int lima_gp_task_validate(struct lima_sched_pipe *pipe,
0104                  struct lima_sched_task *task)
0105 {
0106     struct drm_lima_gp_frame *frame = task->frame;
0107     u32 *f = frame->frame;
0108     (void)pipe;
0109 
0110     if (f[LIMA_GP_VSCL_START_ADDR >> 2] >
0111         f[LIMA_GP_VSCL_END_ADDR >> 2] ||
0112         f[LIMA_GP_PLBUCL_START_ADDR >> 2] >
0113         f[LIMA_GP_PLBUCL_END_ADDR >> 2] ||
0114         f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] >
0115         f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2])
0116         return -EINVAL;
0117 
0118     if (f[LIMA_GP_VSCL_START_ADDR >> 2] ==
0119         f[LIMA_GP_VSCL_END_ADDR >> 2] &&
0120         f[LIMA_GP_PLBUCL_START_ADDR >> 2] ==
0121         f[LIMA_GP_PLBUCL_END_ADDR >> 2])
0122         return -EINVAL;
0123 
0124     return 0;
0125 }
0126 
0127 static void lima_gp_task_run(struct lima_sched_pipe *pipe,
0128                  struct lima_sched_task *task)
0129 {
0130     struct lima_ip *ip = pipe->processor[0];
0131     struct drm_lima_gp_frame *frame = task->frame;
0132     u32 *f = frame->frame;
0133     u32 cmd = 0;
0134     int i;
0135 
0136     /* update real heap buffer size for GP */
0137     for (i = 0; i < task->num_bos; i++) {
0138         struct lima_bo *bo = task->bos[i];
0139 
0140         if (bo->heap_size &&
0141             lima_vm_get_va(task->vm, bo) ==
0142             f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2]) {
0143             f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
0144                 f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] +
0145                 bo->heap_size;
0146             task->recoverable = true;
0147             task->heap = bo;
0148             break;
0149         }
0150     }
0151 
0152     if (f[LIMA_GP_VSCL_START_ADDR >> 2] !=
0153         f[LIMA_GP_VSCL_END_ADDR >> 2])
0154         cmd |= LIMA_GP_CMD_START_VS;
0155     if (f[LIMA_GP_PLBUCL_START_ADDR >> 2] !=
0156         f[LIMA_GP_PLBUCL_END_ADDR >> 2])
0157         cmd |= LIMA_GP_CMD_START_PLBU;
0158 
0159     /* before any hw ops, wait last success task async soft reset */
0160     lima_gp_soft_reset_async_wait(ip);
0161 
0162     for (i = 0; i < LIMA_GP_FRAME_REG_NUM; i++)
0163         writel(f[i], ip->iomem + LIMA_GP_VSCL_START_ADDR + i * 4);
0164 
0165     gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
0166     gp_write(LIMA_GP_CMD, cmd);
0167 }
0168 
0169 static int lima_gp_hard_reset_poll(struct lima_ip *ip)
0170 {
0171     gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
0172     return gp_read(LIMA_GP_PERF_CNT_0_LIMIT) == 0xC01A0000;
0173 }
0174 
0175 static int lima_gp_hard_reset(struct lima_ip *ip)
0176 {
0177     struct lima_device *dev = ip->dev;
0178     int ret;
0179 
0180     gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
0181     gp_write(LIMA_GP_INT_MASK, 0);
0182     gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
0183     ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
0184     if (ret) {
0185         dev_err(dev->dev, "gp hard reset timeout\n");
0186         return ret;
0187     }
0188 
0189     gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0);
0190     gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
0191     gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
0192     return 0;
0193 }
0194 
0195 static void lima_gp_task_fini(struct lima_sched_pipe *pipe)
0196 {
0197     lima_gp_soft_reset_async(pipe->processor[0]);
0198 }
0199 
0200 static void lima_gp_task_error(struct lima_sched_pipe *pipe)
0201 {
0202     struct lima_ip *ip = pipe->processor[0];
0203 
0204     dev_err(ip->dev->dev, "gp task error int_state=%x status=%x\n",
0205         gp_read(LIMA_GP_INT_STAT), gp_read(LIMA_GP_STATUS));
0206 
0207     lima_gp_hard_reset(ip);
0208 }
0209 
0210 static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe)
0211 {
0212     lima_sched_pipe_task_done(pipe);
0213 }
0214 
0215 static int lima_gp_task_recover(struct lima_sched_pipe *pipe)
0216 {
0217     struct lima_ip *ip = pipe->processor[0];
0218     struct lima_sched_task *task = pipe->current_task;
0219     struct drm_lima_gp_frame *frame = task->frame;
0220     u32 *f = frame->frame;
0221     size_t fail_size =
0222         f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] -
0223         f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2];
0224 
0225     if (fail_size == task->heap->heap_size) {
0226         int ret;
0227 
0228         ret = lima_heap_alloc(task->heap, task->vm);
0229         if (ret < 0)
0230             return ret;
0231     }
0232 
0233     gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
0234     /* Resume from where we stopped, i.e. new start is old end */
0235     gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR,
0236          f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
0237     f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
0238         f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size;
0239     gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
0240          f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
0241     gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
0242     return 0;
0243 }
0244 
0245 static void lima_gp_print_version(struct lima_ip *ip)
0246 {
0247     u32 version, major, minor;
0248     char *name;
0249 
0250     version = gp_read(LIMA_GP_VERSION);
0251     major = (version >> 8) & 0xFF;
0252     minor = version & 0xFF;
0253     switch (version >> 16) {
0254     case 0xA07:
0255         name = "mali200";
0256         break;
0257     case 0xC07:
0258         name = "mali300";
0259         break;
0260     case 0xB07:
0261         name = "mali400";
0262         break;
0263     case 0xD07:
0264         name = "mali450";
0265         break;
0266     default:
0267         name = "unknown";
0268         break;
0269     }
0270     dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n",
0271          lima_ip_name(ip), name, major, minor);
0272 }
0273 
0274 static struct kmem_cache *lima_gp_task_slab;
0275 static int lima_gp_task_slab_refcnt;
0276 
0277 static int lima_gp_hw_init(struct lima_ip *ip)
0278 {
0279     ip->data.async_reset = false;
0280     lima_gp_soft_reset_async(ip);
0281     return lima_gp_soft_reset_async_wait(ip);
0282 }
0283 
0284 int lima_gp_resume(struct lima_ip *ip)
0285 {
0286     return lima_gp_hw_init(ip);
0287 }
0288 
0289 void lima_gp_suspend(struct lima_ip *ip)
0290 {
0291 
0292 }
0293 
0294 int lima_gp_init(struct lima_ip *ip)
0295 {
0296     struct lima_device *dev = ip->dev;
0297     int err;
0298 
0299     lima_gp_print_version(ip);
0300 
0301     err = lima_gp_hw_init(ip);
0302     if (err)
0303         return err;
0304 
0305     err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler,
0306                    IRQF_SHARED, lima_ip_name(ip), ip);
0307     if (err) {
0308         dev_err(dev->dev, "gp %s fail to request irq\n",
0309             lima_ip_name(ip));
0310         return err;
0311     }
0312 
0313     dev->gp_version = gp_read(LIMA_GP_VERSION);
0314 
0315     return 0;
0316 }
0317 
0318 void lima_gp_fini(struct lima_ip *ip)
0319 {
0320 
0321 }
0322 
0323 int lima_gp_pipe_init(struct lima_device *dev)
0324 {
0325     int frame_size = sizeof(struct drm_lima_gp_frame);
0326     struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
0327 
0328     if (!lima_gp_task_slab) {
0329         lima_gp_task_slab = kmem_cache_create_usercopy(
0330             "lima_gp_task", sizeof(struct lima_sched_task) + frame_size,
0331             0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task),
0332             frame_size, NULL);
0333         if (!lima_gp_task_slab)
0334             return -ENOMEM;
0335     }
0336     lima_gp_task_slab_refcnt++;
0337 
0338     pipe->frame_size = frame_size;
0339     pipe->task_slab = lima_gp_task_slab;
0340 
0341     pipe->task_validate = lima_gp_task_validate;
0342     pipe->task_run = lima_gp_task_run;
0343     pipe->task_fini = lima_gp_task_fini;
0344     pipe->task_error = lima_gp_task_error;
0345     pipe->task_mmu_error = lima_gp_task_mmu_error;
0346     pipe->task_recover = lima_gp_task_recover;
0347 
0348     return 0;
0349 }
0350 
0351 void lima_gp_pipe_fini(struct lima_device *dev)
0352 {
0353     if (!--lima_gp_task_slab_refcnt) {
0354         kmem_cache_destroy(lima_gp_task_slab);
0355         lima_gp_task_slab = NULL;
0356     }
0357 }