Lines Matching +full:free +full:- +full:running
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * pxa3xx-gcu.c - Linux kernel module for PXA3xx graphics controllers
22 #include <linux/dma-mapping.h>
36 #include "pxa3xx-gcu.h"
38 #define DRV_NAME "pxa3xx-gcu"
97 struct pxa3xx_gcu_batch *free; member
100 struct pxa3xx_gcu_batch *running; member
106 return __raw_readl(priv->mmio_base + off); in gc_readl()
112 __raw_writel(val, priv->mmio_base + off); in gc_writel()
118 struct pxa3xx_gcu_shared *shared = priv->shared; \
122 ts = timespec64_sub(ts, priv->base_time); \
124 printk(level "%lld.%03ld.%03ld - %-17s: %-21s (%s, " \
132 shared->hw_running ? "running" : " idle", \
136 (gc_readl(priv, REG_GCRBEXHR) - base) / 4, \
137 (gc_readl(priv, REG_GCRBHR) - base) / 4, \
138 (gc_readl(priv, REG_GCRBTR) - base) / 4); \
153 memset(priv->shared, 0, SHARED_SIZE); in pxa3xx_gcu_reset()
154 priv->shared->buffer_phys = priv->shared_phys; in pxa3xx_gcu_reset()
155 priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC; in pxa3xx_gcu_reset()
157 ktime_get_ts64(&priv->base_time); in pxa3xx_gcu_reset()
161 gc_writel(priv, REG_GCRBBR, priv->shared_phys); in pxa3xx_gcu_reset()
162 gc_writel(priv, REG_GCRBTR, priv->shared_phys); in pxa3xx_gcu_reset()
171 struct pxa3xx_gcu_shared *sh = priv->shared; in dump_whole_state()
176 printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n" in dump_whole_state()
178 sh->hw_running ? "running" : "idle ", in dump_whole_state()
182 (gc_readl(priv, REG_GCRBEXHR) - base) / 4, in dump_whole_state()
183 (gc_readl(priv, REG_GCRBHR) - base) / 4, in dump_whole_state()
184 (gc_readl(priv, REG_GCRBTR) - base) / 4); in dump_whole_state()
190 struct pxa3xx_gcu_batch *running = priv->running; in flush_running() local
193 while (running) { in flush_running()
194 next = running->next; in flush_running()
195 running->next = priv->free; in flush_running()
196 priv->free = running; in flush_running()
197 running = next; in flush_running()
200 priv->running = NULL; in flush_running()
207 struct pxa3xx_gcu_shared *shared = priv->shared; in run_ready()
208 struct pxa3xx_gcu_batch *ready = priv->ready; in run_ready()
214 shared->buffer[num++] = 0x05000000; in run_ready()
217 shared->buffer[num++] = 0x00000001; in run_ready()
218 shared->buffer[num++] = ready->phys; in run_ready()
219 ready = ready->next; in run_ready()
222 shared->buffer[num++] = 0x05000000; in run_ready()
223 priv->running = priv->ready; in run_ready()
224 priv->ready = priv->ready_last = NULL; in run_ready()
226 shared->hw_running = 1; in run_ready()
229 gc_writel(priv, REG_GCRBBR, shared->buffer_phys); in run_ready()
232 gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4); in run_ready()
242 struct pxa3xx_gcu_shared *shared = priv->shared; in pxa3xx_gcu_handle_irq()
245 QDUMP("-Interrupt"); in pxa3xx_gcu_handle_irq()
250 spin_lock(&priv->spinlock); in pxa3xx_gcu_handle_irq()
251 shared->num_interrupts++; in pxa3xx_gcu_handle_irq()
257 wake_up_all(&priv->wait_free); in pxa3xx_gcu_handle_irq()
259 if (priv->ready) { in pxa3xx_gcu_handle_irq()
264 * kick-off */ in pxa3xx_gcu_handle_irq()
265 shared->num_idle++; in pxa3xx_gcu_handle_irq()
266 shared->hw_running = 0; in pxa3xx_gcu_handle_irq()
268 QDUMP(" '-> Idle."); in pxa3xx_gcu_handle_irq()
273 wake_up_all(&priv->wait_idle); in pxa3xx_gcu_handle_irq()
276 shared->num_done++; in pxa3xx_gcu_handle_irq()
284 spin_unlock(&priv->spinlock); in pxa3xx_gcu_handle_irq()
298 priv->shared->num_wait_idle++; in pxa3xx_gcu_wait_idle()
300 while (priv->shared->hw_running) { in pxa3xx_gcu_wait_idle()
301 int num = priv->shared->num_interrupts; in pxa3xx_gcu_wait_idle()
304 ret = wait_event_interruptible_timeout(priv->wait_idle, in pxa3xx_gcu_wait_idle()
305 !priv->shared->hw_running, HZ*4); in pxa3xx_gcu_wait_idle()
311 priv->shared->num_interrupts == num) { in pxa3xx_gcu_wait_idle()
313 ret = -ETIMEDOUT; in pxa3xx_gcu_wait_idle()
328 QDUMP("Waiting for free..."); in pxa3xx_gcu_wait_free()
332 priv->shared->num_wait_free++; in pxa3xx_gcu_wait_free()
334 while (!priv->free) { in pxa3xx_gcu_wait_free()
337 ret = wait_event_interruptible_timeout(priv->wait_free, in pxa3xx_gcu_wait_free()
338 priv->free, HZ*4); in pxa3xx_gcu_wait_free()
348 ret = -ETIMEDOUT; in pxa3xx_gcu_wait_free()
362 struct miscdevice *dev = file->private_data; in to_pxa3xx_gcu_priv()
367 * provide an empty .open callback, so the core sets file->private_data
388 priv->shared->num_writes++; in pxa3xx_gcu_write()
389 priv->shared->num_words += words; in pxa3xx_gcu_write()
393 return -E2BIG; in pxa3xx_gcu_write()
395 /* Wait for a free buffer */ in pxa3xx_gcu_write()
396 if (!priv->free) { in pxa3xx_gcu_write()
403 * Get buffer from free list in pxa3xx_gcu_write()
405 spin_lock_irqsave(&priv->spinlock, flags); in pxa3xx_gcu_write()
406 buffer = priv->free; in pxa3xx_gcu_write()
407 priv->free = buffer->next; in pxa3xx_gcu_write()
408 spin_unlock_irqrestore(&priv->spinlock, flags); in pxa3xx_gcu_write()
412 ret = copy_from_user(buffer->ptr, buff, words * 4); in pxa3xx_gcu_write()
414 spin_lock_irqsave(&priv->spinlock, flags); in pxa3xx_gcu_write()
415 buffer->next = priv->free; in pxa3xx_gcu_write()
416 priv->free = buffer; in pxa3xx_gcu_write()
417 spin_unlock_irqrestore(&priv->spinlock, flags); in pxa3xx_gcu_write()
418 return -EFAULT; in pxa3xx_gcu_write()
421 buffer->length = words; in pxa3xx_gcu_write()
424 buffer->ptr[words] = 0x01000000; in pxa3xx_gcu_write()
429 spin_lock_irqsave(&priv->spinlock, flags); in pxa3xx_gcu_write()
431 buffer->next = NULL; in pxa3xx_gcu_write()
433 if (priv->ready) { in pxa3xx_gcu_write()
434 BUG_ON(priv->ready_last == NULL); in pxa3xx_gcu_write()
436 priv->ready_last->next = buffer; in pxa3xx_gcu_write()
438 priv->ready = buffer; in pxa3xx_gcu_write()
440 priv->ready_last = buffer; in pxa3xx_gcu_write()
442 if (!priv->shared->hw_running) in pxa3xx_gcu_write()
445 spin_unlock_irqrestore(&priv->spinlock, flags); in pxa3xx_gcu_write()
459 spin_lock_irqsave(&priv->spinlock, flags); in pxa3xx_gcu_ioctl()
461 spin_unlock_irqrestore(&priv->spinlock, flags); in pxa3xx_gcu_ioctl()
468 return -ENOSYS; in pxa3xx_gcu_ioctl()
474 unsigned int size = vma->vm_end - vma->vm_start; in pxa3xx_gcu_mmap()
477 switch (vma->vm_pgoff) { in pxa3xx_gcu_mmap()
481 return -EINVAL; in pxa3xx_gcu_mmap()
483 return dma_mmap_coherent(priv->dev, vma, in pxa3xx_gcu_mmap()
484 priv->shared, priv->shared_phys, size); in pxa3xx_gcu_mmap()
489 if (size != resource_size(priv->resource_mem)) in pxa3xx_gcu_mmap()
490 return -EINVAL; in pxa3xx_gcu_mmap()
492 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); in pxa3xx_gcu_mmap()
494 return io_remap_pfn_range(vma, vma->vm_start, in pxa3xx_gcu_mmap()
495 priv->resource_mem->start >> PAGE_SHIFT, in pxa3xx_gcu_mmap()
496 size, vma->vm_page_prot); in pxa3xx_gcu_mmap()
499 return -EINVAL; in pxa3xx_gcu_mmap()
535 return -ENOMEM; in pxa3xx_gcu_add_buffer()
537 buffer->ptr = dma_alloc_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4, in pxa3xx_gcu_add_buffer()
538 &buffer->phys, GFP_KERNEL); in pxa3xx_gcu_add_buffer()
539 if (!buffer->ptr) { in pxa3xx_gcu_add_buffer()
541 return -ENOMEM; in pxa3xx_gcu_add_buffer()
544 buffer->next = priv->free; in pxa3xx_gcu_add_buffer()
545 priv->free = buffer; in pxa3xx_gcu_add_buffer()
554 struct pxa3xx_gcu_batch *next, *buffer = priv->free; in pxa3xx_gcu_free_buffers()
557 next = buffer->next; in pxa3xx_gcu_free_buffers()
560 buffer->ptr, buffer->phys); in pxa3xx_gcu_free_buffers()
566 priv->free = NULL; in pxa3xx_gcu_free_buffers()
582 struct device *dev = &pdev->dev; in pxa3xx_gcu_probe()
586 return -ENOMEM; in pxa3xx_gcu_probe()
588 init_waitqueue_head(&priv->wait_idle); in pxa3xx_gcu_probe()
589 init_waitqueue_head(&priv->wait_free); in pxa3xx_gcu_probe()
590 spin_lock_init(&priv->spinlock); in pxa3xx_gcu_probe()
597 priv->misc_dev.minor = PXA3XX_GCU_MINOR; in pxa3xx_gcu_probe()
598 priv->misc_dev.name = DRV_NAME; in pxa3xx_gcu_probe()
599 priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops; in pxa3xx_gcu_probe()
602 priv->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); in pxa3xx_gcu_probe()
603 if (IS_ERR(priv->mmio_base)) in pxa3xx_gcu_probe()
604 return PTR_ERR(priv->mmio_base); in pxa3xx_gcu_probe()
607 priv->clk = devm_clk_get(dev, NULL); in pxa3xx_gcu_probe()
608 if (IS_ERR(priv->clk)) in pxa3xx_gcu_probe()
609 return dev_err_probe(dev, PTR_ERR(priv->clk), "failed to get clock\n"); in pxa3xx_gcu_probe()
624 priv->shared = dma_alloc_coherent(dev, SHARED_SIZE, in pxa3xx_gcu_probe()
625 &priv->shared_phys, GFP_KERNEL); in pxa3xx_gcu_probe()
626 if (!priv->shared) { in pxa3xx_gcu_probe()
628 return -ENOMEM; in pxa3xx_gcu_probe()
632 ret = misc_register(&priv->misc_dev); in pxa3xx_gcu_probe()
639 ret = clk_prepare_enable(priv->clk); in pxa3xx_gcu_probe()
655 priv->resource_mem = r; in pxa3xx_gcu_probe()
656 priv->dev = dev; in pxa3xx_gcu_probe()
661 (void *) r->start, (void *) priv->shared_phys, in pxa3xx_gcu_probe()
666 clk_disable_unprepare(priv->clk); in pxa3xx_gcu_probe()
669 misc_deregister(&priv->misc_dev); in pxa3xx_gcu_probe()
673 priv->shared, priv->shared_phys); in pxa3xx_gcu_probe()
681 struct device *dev = &pdev->dev; in pxa3xx_gcu_remove()
684 misc_deregister(&priv->misc_dev); in pxa3xx_gcu_remove()
685 dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys); in pxa3xx_gcu_remove()
686 clk_disable_unprepare(priv->clk); in pxa3xx_gcu_remove()
692 { .compatible = "marvell,pxa300-gcu", },