0001
0002
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
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
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
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
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
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 }