0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/module.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/dma-mapping.h>
0023 #include <linux/miscdevice.h>
0024 #include <linux/interrupt.h>
0025 #include <linux/spinlock.h>
0026 #include <linux/uaccess.h>
0027 #include <linux/ioctl.h>
0028 #include <linux/delay.h>
0029 #include <linux/sched.h>
0030 #include <linux/slab.h>
0031 #include <linux/clk.h>
0032 #include <linux/fs.h>
0033 #include <linux/io.h>
0034 #include <linux/of.h>
0035
0036 #include "pxa3xx-gcu.h"
0037
0038 #define DRV_NAME "pxa3xx-gcu"
0039
0040 #define REG_GCCR 0x00
0041 #define GCCR_SYNC_CLR (1 << 9)
0042 #define GCCR_BP_RST (1 << 8)
0043 #define GCCR_ABORT (1 << 6)
0044 #define GCCR_STOP (1 << 4)
0045
0046 #define REG_GCISCR 0x04
0047 #define REG_GCIECR 0x08
0048 #define REG_GCRBBR 0x20
0049 #define REG_GCRBLR 0x24
0050 #define REG_GCRBHR 0x28
0051 #define REG_GCRBTR 0x2C
0052 #define REG_GCRBEXHR 0x30
0053
0054 #define IE_EOB (1 << 0)
0055 #define IE_EEOB (1 << 5)
0056 #define IE_ALL 0xff
0057
0058 #define SHARED_SIZE PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
0059
0060
0061
0062
0063 #ifdef PXA3XX_GCU_DEBUG
0064 #define QDUMP(msg) \
0065 do { \
0066 QPRINT(priv, KERN_DEBUG, msg); \
0067 } while (0)
0068 #else
0069 #define QDUMP(msg) do {} while (0)
0070 #endif
0071
0072 #define QERROR(msg) \
0073 do { \
0074 QPRINT(priv, KERN_ERR, msg); \
0075 } while (0)
0076
0077 struct pxa3xx_gcu_batch {
0078 struct pxa3xx_gcu_batch *next;
0079 u32 *ptr;
0080 dma_addr_t phys;
0081 unsigned long length;
0082 };
0083
0084 struct pxa3xx_gcu_priv {
0085 struct device *dev;
0086 void __iomem *mmio_base;
0087 struct clk *clk;
0088 struct pxa3xx_gcu_shared *shared;
0089 dma_addr_t shared_phys;
0090 struct resource *resource_mem;
0091 struct miscdevice misc_dev;
0092 wait_queue_head_t wait_idle;
0093 wait_queue_head_t wait_free;
0094 spinlock_t spinlock;
0095 struct timespec64 base_time;
0096
0097 struct pxa3xx_gcu_batch *free;
0098 struct pxa3xx_gcu_batch *ready;
0099 struct pxa3xx_gcu_batch *ready_last;
0100 struct pxa3xx_gcu_batch *running;
0101 };
0102
0103 static inline unsigned long
0104 gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
0105 {
0106 return __raw_readl(priv->mmio_base + off);
0107 }
0108
0109 static inline void
0110 gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
0111 {
0112 __raw_writel(val, priv->mmio_base + off);
0113 }
0114
0115 #define QPRINT(priv, level, msg) \
0116 do { \
0117 struct timespec64 ts; \
0118 struct pxa3xx_gcu_shared *shared = priv->shared; \
0119 u32 base = gc_readl(priv, REG_GCRBBR); \
0120 \
0121 ktime_get_ts64(&ts); \
0122 ts = timespec64_sub(ts, priv->base_time); \
0123 \
0124 printk(level "%lld.%03ld.%03ld - %-17s: %-21s (%s, " \
0125 "STATUS " \
0126 "0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, " \
0127 "T %5ld)\n", \
0128 (s64)(ts.tv_sec), \
0129 ts.tv_nsec / NSEC_PER_MSEC, \
0130 (ts.tv_nsec % NSEC_PER_MSEC) / USEC_PER_MSEC, \
0131 __func__, msg, \
0132 shared->hw_running ? "running" : " idle", \
0133 gc_readl(priv, REG_GCISCR), \
0134 gc_readl(priv, REG_GCRBBR), \
0135 gc_readl(priv, REG_GCRBLR), \
0136 (gc_readl(priv, REG_GCRBEXHR) - base) / 4, \
0137 (gc_readl(priv, REG_GCRBHR) - base) / 4, \
0138 (gc_readl(priv, REG_GCRBTR) - base) / 4); \
0139 } while (0)
0140
0141 static void
0142 pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
0143 {
0144 QDUMP("RESET");
0145
0146
0147 gc_writel(priv, REG_GCIECR, 0);
0148
0149
0150 gc_writel(priv, REG_GCCR, GCCR_ABORT);
0151 gc_writel(priv, REG_GCCR, 0);
0152
0153 memset(priv->shared, 0, SHARED_SIZE);
0154 priv->shared->buffer_phys = priv->shared_phys;
0155 priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
0156
0157 ktime_get_ts64(&priv->base_time);
0158
0159
0160 gc_writel(priv, REG_GCRBLR, 0);
0161 gc_writel(priv, REG_GCRBBR, priv->shared_phys);
0162 gc_writel(priv, REG_GCRBTR, priv->shared_phys);
0163
0164
0165 gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
0166 }
0167
0168 static void
0169 dump_whole_state(struct pxa3xx_gcu_priv *priv)
0170 {
0171 struct pxa3xx_gcu_shared *sh = priv->shared;
0172 u32 base = gc_readl(priv, REG_GCRBBR);
0173
0174 QDUMP("DUMP");
0175
0176 printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
0177 "%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
0178 sh->hw_running ? "running" : "idle ",
0179 gc_readl(priv, REG_GCISCR),
0180 gc_readl(priv, REG_GCRBBR),
0181 gc_readl(priv, REG_GCRBLR),
0182 (gc_readl(priv, REG_GCRBEXHR) - base) / 4,
0183 (gc_readl(priv, REG_GCRBHR) - base) / 4,
0184 (gc_readl(priv, REG_GCRBTR) - base) / 4);
0185 }
0186
0187 static void
0188 flush_running(struct pxa3xx_gcu_priv *priv)
0189 {
0190 struct pxa3xx_gcu_batch *running = priv->running;
0191 struct pxa3xx_gcu_batch *next;
0192
0193 while (running) {
0194 next = running->next;
0195 running->next = priv->free;
0196 priv->free = running;
0197 running = next;
0198 }
0199
0200 priv->running = NULL;
0201 }
0202
0203 static void
0204 run_ready(struct pxa3xx_gcu_priv *priv)
0205 {
0206 unsigned int num = 0;
0207 struct pxa3xx_gcu_shared *shared = priv->shared;
0208 struct pxa3xx_gcu_batch *ready = priv->ready;
0209
0210 QDUMP("Start");
0211
0212 BUG_ON(!ready);
0213
0214 shared->buffer[num++] = 0x05000000;
0215
0216 while (ready) {
0217 shared->buffer[num++] = 0x00000001;
0218 shared->buffer[num++] = ready->phys;
0219 ready = ready->next;
0220 }
0221
0222 shared->buffer[num++] = 0x05000000;
0223 priv->running = priv->ready;
0224 priv->ready = priv->ready_last = NULL;
0225 gc_writel(priv, REG_GCRBLR, 0);
0226 shared->hw_running = 1;
0227
0228
0229 gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
0230
0231
0232 gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
0233
0234
0235 gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
0236 }
0237
0238 static irqreturn_t
0239 pxa3xx_gcu_handle_irq(int irq, void *ctx)
0240 {
0241 struct pxa3xx_gcu_priv *priv = ctx;
0242 struct pxa3xx_gcu_shared *shared = priv->shared;
0243 u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
0244
0245 QDUMP("-Interrupt");
0246
0247 if (!status)
0248 return IRQ_NONE;
0249
0250 spin_lock(&priv->spinlock);
0251 shared->num_interrupts++;
0252
0253 if (status & IE_EEOB) {
0254 QDUMP(" [EEOB]");
0255
0256 flush_running(priv);
0257 wake_up_all(&priv->wait_free);
0258
0259 if (priv->ready) {
0260 run_ready(priv);
0261 } else {
0262
0263
0264
0265 shared->num_idle++;
0266 shared->hw_running = 0;
0267
0268 QDUMP(" '-> Idle.");
0269
0270
0271 gc_writel(priv, REG_GCRBLR, 0);
0272
0273 wake_up_all(&priv->wait_idle);
0274 }
0275
0276 shared->num_done++;
0277 } else {
0278 QERROR(" [???]");
0279 dump_whole_state(priv);
0280 }
0281
0282
0283 gc_writel(priv, REG_GCISCR, status);
0284 spin_unlock(&priv->spinlock);
0285
0286 return IRQ_HANDLED;
0287 }
0288
0289 static int
0290 pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
0291 {
0292 int ret = 0;
0293
0294 QDUMP("Waiting for idle...");
0295
0296
0297
0298 priv->shared->num_wait_idle++;
0299
0300 while (priv->shared->hw_running) {
0301 int num = priv->shared->num_interrupts;
0302 u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
0303
0304 ret = wait_event_interruptible_timeout(priv->wait_idle,
0305 !priv->shared->hw_running, HZ*4);
0306
0307 if (ret != 0)
0308 break;
0309
0310 if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
0311 priv->shared->num_interrupts == num) {
0312 QERROR("TIMEOUT");
0313 ret = -ETIMEDOUT;
0314 break;
0315 }
0316 }
0317
0318 QDUMP("done");
0319
0320 return ret;
0321 }
0322
0323 static int
0324 pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
0325 {
0326 int ret = 0;
0327
0328 QDUMP("Waiting for free...");
0329
0330
0331
0332 priv->shared->num_wait_free++;
0333
0334 while (!priv->free) {
0335 u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
0336
0337 ret = wait_event_interruptible_timeout(priv->wait_free,
0338 priv->free, HZ*4);
0339
0340 if (ret < 0)
0341 break;
0342
0343 if (ret > 0)
0344 continue;
0345
0346 if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
0347 QERROR("TIMEOUT");
0348 ret = -ETIMEDOUT;
0349 break;
0350 }
0351 }
0352
0353 QDUMP("done");
0354
0355 return ret;
0356 }
0357
0358
0359
0360 static inline struct pxa3xx_gcu_priv *to_pxa3xx_gcu_priv(struct file *file)
0361 {
0362 struct miscdevice *dev = file->private_data;
0363 return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
0364 }
0365
0366
0367
0368
0369
0370 static int pxa3xx_gcu_open(struct inode *inode, struct file *file)
0371 {
0372 return 0;
0373 }
0374
0375 static ssize_t
0376 pxa3xx_gcu_write(struct file *file, const char *buff,
0377 size_t count, loff_t *offp)
0378 {
0379 int ret;
0380 unsigned long flags;
0381 struct pxa3xx_gcu_batch *buffer;
0382 struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
0383
0384 size_t words = count / 4;
0385
0386
0387
0388 priv->shared->num_writes++;
0389 priv->shared->num_words += words;
0390
0391
0392 if (words >= PXA3XX_GCU_BATCH_WORDS)
0393 return -E2BIG;
0394
0395
0396 if (!priv->free) {
0397 ret = pxa3xx_gcu_wait_free(priv);
0398 if (ret < 0)
0399 return ret;
0400 }
0401
0402
0403
0404
0405 spin_lock_irqsave(&priv->spinlock, flags);
0406 buffer = priv->free;
0407 priv->free = buffer->next;
0408 spin_unlock_irqrestore(&priv->spinlock, flags);
0409
0410
0411
0412 ret = copy_from_user(buffer->ptr, buff, words * 4);
0413 if (ret) {
0414 spin_lock_irqsave(&priv->spinlock, flags);
0415 buffer->next = priv->free;
0416 priv->free = buffer;
0417 spin_unlock_irqrestore(&priv->spinlock, flags);
0418 return -EFAULT;
0419 }
0420
0421 buffer->length = words;
0422
0423
0424 buffer->ptr[words] = 0x01000000;
0425
0426
0427
0428
0429 spin_lock_irqsave(&priv->spinlock, flags);
0430
0431 buffer->next = NULL;
0432
0433 if (priv->ready) {
0434 BUG_ON(priv->ready_last == NULL);
0435
0436 priv->ready_last->next = buffer;
0437 } else
0438 priv->ready = buffer;
0439
0440 priv->ready_last = buffer;
0441
0442 if (!priv->shared->hw_running)
0443 run_ready(priv);
0444
0445 spin_unlock_irqrestore(&priv->spinlock, flags);
0446
0447 return words * 4;
0448 }
0449
0450
0451 static long
0452 pxa3xx_gcu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0453 {
0454 unsigned long flags;
0455 struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
0456
0457 switch (cmd) {
0458 case PXA3XX_GCU_IOCTL_RESET:
0459 spin_lock_irqsave(&priv->spinlock, flags);
0460 pxa3xx_gcu_reset(priv);
0461 spin_unlock_irqrestore(&priv->spinlock, flags);
0462 return 0;
0463
0464 case PXA3XX_GCU_IOCTL_WAIT_IDLE:
0465 return pxa3xx_gcu_wait_idle(priv);
0466 }
0467
0468 return -ENOSYS;
0469 }
0470
0471 static int
0472 pxa3xx_gcu_mmap(struct file *file, struct vm_area_struct *vma)
0473 {
0474 unsigned int size = vma->vm_end - vma->vm_start;
0475 struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
0476
0477 switch (vma->vm_pgoff) {
0478 case 0:
0479
0480 if (size != SHARED_SIZE)
0481 return -EINVAL;
0482
0483 return dma_mmap_coherent(priv->dev, vma,
0484 priv->shared, priv->shared_phys, size);
0485
0486 case SHARED_SIZE >> PAGE_SHIFT:
0487
0488
0489 if (size != resource_size(priv->resource_mem))
0490 return -EINVAL;
0491
0492 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
0493
0494 return io_remap_pfn_range(vma, vma->vm_start,
0495 priv->resource_mem->start >> PAGE_SHIFT,
0496 size, vma->vm_page_prot);
0497 }
0498
0499 return -EINVAL;
0500 }
0501
0502
0503 #ifdef PXA3XX_GCU_DEBUG_TIMER
0504 static struct timer_list pxa3xx_gcu_debug_timer;
0505 static struct pxa3xx_gcu_priv *debug_timer_priv;
0506
0507 static void pxa3xx_gcu_debug_timedout(struct timer_list *unused)
0508 {
0509 struct pxa3xx_gcu_priv *priv = debug_timer_priv;
0510
0511 QERROR("Timer DUMP");
0512
0513 mod_timer(&pxa3xx_gcu_debug_timer, jiffies + 5 * HZ);
0514 }
0515
0516 static void pxa3xx_gcu_init_debug_timer(struct pxa3xx_gcu_priv *priv)
0517 {
0518
0519 debug_timer_priv = priv;
0520 timer_setup(&pxa3xx_gcu_debug_timer, pxa3xx_gcu_debug_timedout, 0);
0521 pxa3xx_gcu_debug_timedout(NULL);
0522 }
0523 #else
0524 static inline void pxa3xx_gcu_init_debug_timer(struct pxa3xx_gcu_priv *priv) {}
0525 #endif
0526
0527 static int
0528 pxa3xx_gcu_add_buffer(struct device *dev,
0529 struct pxa3xx_gcu_priv *priv)
0530 {
0531 struct pxa3xx_gcu_batch *buffer;
0532
0533 buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
0534 if (!buffer)
0535 return -ENOMEM;
0536
0537 buffer->ptr = dma_alloc_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
0538 &buffer->phys, GFP_KERNEL);
0539 if (!buffer->ptr) {
0540 kfree(buffer);
0541 return -ENOMEM;
0542 }
0543
0544 buffer->next = priv->free;
0545 priv->free = buffer;
0546
0547 return 0;
0548 }
0549
0550 static void
0551 pxa3xx_gcu_free_buffers(struct device *dev,
0552 struct pxa3xx_gcu_priv *priv)
0553 {
0554 struct pxa3xx_gcu_batch *next, *buffer = priv->free;
0555
0556 while (buffer) {
0557 next = buffer->next;
0558
0559 dma_free_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
0560 buffer->ptr, buffer->phys);
0561
0562 kfree(buffer);
0563 buffer = next;
0564 }
0565
0566 priv->free = NULL;
0567 }
0568
0569 static const struct file_operations pxa3xx_gcu_miscdev_fops = {
0570 .owner = THIS_MODULE,
0571 .open = pxa3xx_gcu_open,
0572 .write = pxa3xx_gcu_write,
0573 .unlocked_ioctl = pxa3xx_gcu_ioctl,
0574 .mmap = pxa3xx_gcu_mmap,
0575 };
0576
0577 static int pxa3xx_gcu_probe(struct platform_device *pdev)
0578 {
0579 int i, ret, irq;
0580 struct resource *r;
0581 struct pxa3xx_gcu_priv *priv;
0582 struct device *dev = &pdev->dev;
0583
0584 priv = devm_kzalloc(dev, sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
0585 if (!priv)
0586 return -ENOMEM;
0587
0588 init_waitqueue_head(&priv->wait_idle);
0589 init_waitqueue_head(&priv->wait_free);
0590 spin_lock_init(&priv->spinlock);
0591
0592
0593
0594
0595
0596
0597 priv->misc_dev.minor = PXA3XX_GCU_MINOR,
0598 priv->misc_dev.name = DRV_NAME,
0599 priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops;
0600
0601
0602 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0603 priv->mmio_base = devm_ioremap_resource(dev, r);
0604 if (IS_ERR(priv->mmio_base))
0605 return PTR_ERR(priv->mmio_base);
0606
0607
0608 priv->clk = devm_clk_get(dev, NULL);
0609 if (IS_ERR(priv->clk))
0610 return dev_err_probe(dev, PTR_ERR(priv->clk), "failed to get clock\n");
0611
0612
0613 irq = platform_get_irq(pdev, 0);
0614 if (irq < 0)
0615 return irq;
0616
0617 ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq,
0618 0, DRV_NAME, priv);
0619 if (ret < 0) {
0620 dev_err(dev, "request_irq failed\n");
0621 return ret;
0622 }
0623
0624
0625 priv->shared = dma_alloc_coherent(dev, SHARED_SIZE,
0626 &priv->shared_phys, GFP_KERNEL);
0627 if (!priv->shared) {
0628 dev_err(dev, "failed to allocate DMA memory\n");
0629 return -ENOMEM;
0630 }
0631
0632
0633 ret = misc_register(&priv->misc_dev);
0634 if (ret < 0) {
0635 dev_err(dev, "misc_register() for minor %d failed\n",
0636 PXA3XX_GCU_MINOR);
0637 goto err_free_dma;
0638 }
0639
0640 ret = clk_prepare_enable(priv->clk);
0641 if (ret < 0) {
0642 dev_err(dev, "failed to enable clock\n");
0643 goto err_misc_deregister;
0644 }
0645
0646 for (i = 0; i < 8; i++) {
0647 ret = pxa3xx_gcu_add_buffer(dev, priv);
0648 if (ret) {
0649 pxa3xx_gcu_free_buffers(dev, priv);
0650 dev_err(dev, "failed to allocate DMA memory\n");
0651 goto err_disable_clk;
0652 }
0653 }
0654
0655 platform_set_drvdata(pdev, priv);
0656 priv->resource_mem = r;
0657 priv->dev = dev;
0658 pxa3xx_gcu_reset(priv);
0659 pxa3xx_gcu_init_debug_timer(priv);
0660
0661 dev_info(dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
0662 (void *) r->start, (void *) priv->shared_phys,
0663 SHARED_SIZE, irq);
0664 return 0;
0665
0666 err_disable_clk:
0667 clk_disable_unprepare(priv->clk);
0668
0669 err_misc_deregister:
0670 misc_deregister(&priv->misc_dev);
0671
0672 err_free_dma:
0673 dma_free_coherent(dev, SHARED_SIZE,
0674 priv->shared, priv->shared_phys);
0675
0676 return ret;
0677 }
0678
0679 static int pxa3xx_gcu_remove(struct platform_device *pdev)
0680 {
0681 struct pxa3xx_gcu_priv *priv = platform_get_drvdata(pdev);
0682 struct device *dev = &pdev->dev;
0683
0684 pxa3xx_gcu_wait_idle(priv);
0685 misc_deregister(&priv->misc_dev);
0686 dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys);
0687 clk_disable_unprepare(priv->clk);
0688 pxa3xx_gcu_free_buffers(dev, priv);
0689
0690 return 0;
0691 }
0692
0693 #ifdef CONFIG_OF
0694 static const struct of_device_id pxa3xx_gcu_of_match[] = {
0695 { .compatible = "marvell,pxa300-gcu", },
0696 { }
0697 };
0698 MODULE_DEVICE_TABLE(of, pxa3xx_gcu_of_match);
0699 #endif
0700
0701 static struct platform_driver pxa3xx_gcu_driver = {
0702 .probe = pxa3xx_gcu_probe,
0703 .remove = pxa3xx_gcu_remove,
0704 .driver = {
0705 .name = DRV_NAME,
0706 .of_match_table = of_match_ptr(pxa3xx_gcu_of_match),
0707 },
0708 };
0709
0710 module_platform_driver(pxa3xx_gcu_driver);
0711
0712 MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
0713 MODULE_LICENSE("GPL");
0714 MODULE_ALIAS_MISCDEV(PXA3XX_GCU_MINOR);
0715 MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
0716 "Denis Oliver Kropp <dok@directfb.org>, "
0717 "Daniel Mack <daniel@caiaq.de>");