cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pxa3xx-gcu.c (16769B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  pxa3xx-gcu.c - Linux kernel module for PXA3xx graphics controllers
      4 *
      5 *  This driver needs a DirectFB counterpart in user space, communication
      6 *  is handled via mmap()ed memory areas and an ioctl.
      7 *
      8 *  Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
      9 *  Copyright (c) 2009 Janine Kropp <nin@directfb.org>
     10 *  Copyright (c) 2009 Denis Oliver Kropp <dok@directfb.org>
     11 */
     12
     13/*
     14 * WARNING: This controller is attached to System Bus 2 of the PXA which
     15 * needs its arbiter to be enabled explicitly (CKENB & 1<<9).
     16 * There is currently no way to do this from Linux, so you need to teach
     17 * your bootloader for now.
     18 */
     19
     20#include <linux/module.h>
     21#include <linux/platform_device.h>
     22#include <linux/dma-mapping.h>
     23#include <linux/miscdevice.h>
     24#include <linux/interrupt.h>
     25#include <linux/spinlock.h>
     26#include <linux/uaccess.h>
     27#include <linux/ioctl.h>
     28#include <linux/delay.h>
     29#include <linux/sched.h>
     30#include <linux/slab.h>
     31#include <linux/clk.h>
     32#include <linux/fs.h>
     33#include <linux/io.h>
     34#include <linux/of.h>
     35
     36#include "pxa3xx-gcu.h"
     37
     38#define DRV_NAME	"pxa3xx-gcu"
     39
     40#define REG_GCCR	0x00
     41#define GCCR_SYNC_CLR	(1 << 9)
     42#define GCCR_BP_RST	(1 << 8)
     43#define GCCR_ABORT	(1 << 6)
     44#define GCCR_STOP	(1 << 4)
     45
     46#define REG_GCISCR	0x04
     47#define REG_GCIECR	0x08
     48#define REG_GCRBBR	0x20
     49#define REG_GCRBLR	0x24
     50#define REG_GCRBHR	0x28
     51#define REG_GCRBTR	0x2C
     52#define REG_GCRBEXHR	0x30
     53
     54#define IE_EOB		(1 << 0)
     55#define IE_EEOB		(1 << 5)
     56#define IE_ALL		0xff
     57
     58#define SHARED_SIZE	PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
     59
     60/* #define PXA3XX_GCU_DEBUG */
     61/* #define PXA3XX_GCU_DEBUG_TIMER */
     62
     63#ifdef PXA3XX_GCU_DEBUG
     64#define QDUMP(msg)					\
     65	do {						\
     66		QPRINT(priv, KERN_DEBUG, msg);		\
     67	} while (0)
     68#else
     69#define QDUMP(msg)	do {} while (0)
     70#endif
     71
     72#define QERROR(msg)					\
     73	do {						\
     74		QPRINT(priv, KERN_ERR, msg);		\
     75	} while (0)
     76
     77struct pxa3xx_gcu_batch {
     78	struct pxa3xx_gcu_batch *next;
     79	u32			*ptr;
     80	dma_addr_t		 phys;
     81	unsigned long		 length;
     82};
     83
     84struct pxa3xx_gcu_priv {
     85	struct device		 *dev;
     86	void __iomem		 *mmio_base;
     87	struct clk		 *clk;
     88	struct pxa3xx_gcu_shared *shared;
     89	dma_addr_t		  shared_phys;
     90	struct resource		 *resource_mem;
     91	struct miscdevice	  misc_dev;
     92	wait_queue_head_t	  wait_idle;
     93	wait_queue_head_t	  wait_free;
     94	spinlock_t		  spinlock;
     95	struct timespec64	  base_time;
     96
     97	struct pxa3xx_gcu_batch *free;
     98	struct pxa3xx_gcu_batch *ready;
     99	struct pxa3xx_gcu_batch *ready_last;
    100	struct pxa3xx_gcu_batch *running;
    101};
    102
    103static inline unsigned long
    104gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
    105{
    106	return __raw_readl(priv->mmio_base + off);
    107}
    108
    109static inline void
    110gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
    111{
    112	__raw_writel(val, priv->mmio_base + off);
    113}
    114
    115#define QPRINT(priv, level, msg)					\
    116	do {								\
    117		struct timespec64 ts;					\
    118		struct pxa3xx_gcu_shared *shared = priv->shared;	\
    119		u32 base = gc_readl(priv, REG_GCRBBR);			\
    120									\
    121		ktime_get_ts64(&ts);					\
    122		ts = timespec64_sub(ts, priv->base_time);		\
    123									\
    124		printk(level "%lld.%03ld.%03ld - %-17s: %-21s (%s, "	\
    125			"STATUS "					\
    126			"0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, "	\
    127			"T %5ld)\n",					\
    128			(s64)(ts.tv_sec),				\
    129			ts.tv_nsec / NSEC_PER_MSEC,			\
    130			(ts.tv_nsec % NSEC_PER_MSEC) / USEC_PER_MSEC,	\
    131			__func__, msg,					\
    132			shared->hw_running ? "running" : "   idle",	\
    133			gc_readl(priv, REG_GCISCR),			\
    134			gc_readl(priv, REG_GCRBBR),			\
    135			gc_readl(priv, REG_GCRBLR),			\
    136			(gc_readl(priv, REG_GCRBEXHR) - base) / 4,	\
    137			(gc_readl(priv, REG_GCRBHR) - base) / 4,	\
    138			(gc_readl(priv, REG_GCRBTR) - base) / 4);	\
    139	} while (0)
    140
    141static void
    142pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
    143{
    144	QDUMP("RESET");
    145
    146	/* disable interrupts */
    147	gc_writel(priv, REG_GCIECR, 0);
    148
    149	/* reset hardware */
    150	gc_writel(priv, REG_GCCR, GCCR_ABORT);
    151	gc_writel(priv, REG_GCCR, 0);
    152
    153	memset(priv->shared, 0, SHARED_SIZE);
    154	priv->shared->buffer_phys = priv->shared_phys;
    155	priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
    156
    157	ktime_get_ts64(&priv->base_time);
    158
    159	/* set up the ring buffer pointers */
    160	gc_writel(priv, REG_GCRBLR, 0);
    161	gc_writel(priv, REG_GCRBBR, priv->shared_phys);
    162	gc_writel(priv, REG_GCRBTR, priv->shared_phys);
    163
    164	/* enable all IRQs except EOB */
    165	gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
    166}
    167
    168static void
    169dump_whole_state(struct pxa3xx_gcu_priv *priv)
    170{
    171	struct pxa3xx_gcu_shared *sh = priv->shared;
    172	u32 base = gc_readl(priv, REG_GCRBBR);
    173
    174	QDUMP("DUMP");
    175
    176	printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
    177		"%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
    178		sh->hw_running ? "running" : "idle   ",
    179		gc_readl(priv, REG_GCISCR),
    180		gc_readl(priv, REG_GCRBBR),
    181		gc_readl(priv, REG_GCRBLR),
    182		(gc_readl(priv, REG_GCRBEXHR) - base) / 4,
    183		(gc_readl(priv, REG_GCRBHR) - base) / 4,
    184		(gc_readl(priv, REG_GCRBTR) - base) / 4);
    185}
    186
    187static void
    188flush_running(struct pxa3xx_gcu_priv *priv)
    189{
    190	struct pxa3xx_gcu_batch *running = priv->running;
    191	struct pxa3xx_gcu_batch *next;
    192
    193	while (running) {
    194		next = running->next;
    195		running->next = priv->free;
    196		priv->free = running;
    197		running = next;
    198	}
    199
    200	priv->running = NULL;
    201}
    202
    203static void
    204run_ready(struct pxa3xx_gcu_priv *priv)
    205{
    206	unsigned int num = 0;
    207	struct pxa3xx_gcu_shared *shared = priv->shared;
    208	struct pxa3xx_gcu_batch	*ready = priv->ready;
    209
    210	QDUMP("Start");
    211
    212	BUG_ON(!ready);
    213
    214	shared->buffer[num++] = 0x05000000;
    215
    216	while (ready) {
    217		shared->buffer[num++] = 0x00000001;
    218		shared->buffer[num++] = ready->phys;
    219		ready = ready->next;
    220	}
    221
    222	shared->buffer[num++] = 0x05000000;
    223	priv->running = priv->ready;
    224	priv->ready = priv->ready_last = NULL;
    225	gc_writel(priv, REG_GCRBLR, 0);
    226	shared->hw_running = 1;
    227
    228	/* ring base address */
    229	gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
    230
    231	/* ring tail address */
    232	gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
    233
    234	/* ring length */
    235	gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
    236}
    237
    238static irqreturn_t
    239pxa3xx_gcu_handle_irq(int irq, void *ctx)
    240{
    241	struct pxa3xx_gcu_priv *priv = ctx;
    242	struct pxa3xx_gcu_shared *shared = priv->shared;
    243	u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
    244
    245	QDUMP("-Interrupt");
    246
    247	if (!status)
    248		return IRQ_NONE;
    249
    250	spin_lock(&priv->spinlock);
    251	shared->num_interrupts++;
    252
    253	if (status & IE_EEOB) {
    254		QDUMP(" [EEOB]");
    255
    256		flush_running(priv);
    257		wake_up_all(&priv->wait_free);
    258
    259		if (priv->ready) {
    260			run_ready(priv);
    261		} else {
    262			/* There is no more data prepared by the userspace.
    263			 * Set hw_running = 0 and wait for the next userspace
    264			 * kick-off */
    265			shared->num_idle++;
    266			shared->hw_running = 0;
    267
    268			QDUMP(" '-> Idle.");
    269
    270			/* set ring buffer length to zero */
    271			gc_writel(priv, REG_GCRBLR, 0);
    272
    273			wake_up_all(&priv->wait_idle);
    274		}
    275
    276		shared->num_done++;
    277	} else {
    278		QERROR(" [???]");
    279		dump_whole_state(priv);
    280	}
    281
    282	/* Clear the interrupt */
    283	gc_writel(priv, REG_GCISCR, status);
    284	spin_unlock(&priv->spinlock);
    285
    286	return IRQ_HANDLED;
    287}
    288
    289static int
    290pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
    291{
    292	int ret = 0;
    293
    294	QDUMP("Waiting for idle...");
    295
    296	/* Does not need to be atomic. There's a lock in user space,
    297	 * but anyhow, this is just for statistics. */
    298	priv->shared->num_wait_idle++;
    299
    300	while (priv->shared->hw_running) {
    301		int num = priv->shared->num_interrupts;
    302		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
    303
    304		ret = wait_event_interruptible_timeout(priv->wait_idle,
    305					!priv->shared->hw_running, HZ*4);
    306
    307		if (ret != 0)
    308			break;
    309
    310		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
    311		    priv->shared->num_interrupts == num) {
    312			QERROR("TIMEOUT");
    313			ret = -ETIMEDOUT;
    314			break;
    315		}
    316	}
    317
    318	QDUMP("done");
    319
    320	return ret;
    321}
    322
    323static int
    324pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
    325{
    326	int ret = 0;
    327
    328	QDUMP("Waiting for free...");
    329
    330	/* Does not need to be atomic. There's a lock in user space,
    331	 * but anyhow, this is just for statistics. */
    332	priv->shared->num_wait_free++;
    333
    334	while (!priv->free) {
    335		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
    336
    337		ret = wait_event_interruptible_timeout(priv->wait_free,
    338						       priv->free, HZ*4);
    339
    340		if (ret < 0)
    341			break;
    342
    343		if (ret > 0)
    344			continue;
    345
    346		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
    347			QERROR("TIMEOUT");
    348			ret = -ETIMEDOUT;
    349			break;
    350		}
    351	}
    352
    353	QDUMP("done");
    354
    355	return ret;
    356}
    357
    358/* Misc device layer */
    359
    360static inline struct pxa3xx_gcu_priv *to_pxa3xx_gcu_priv(struct file *file)
    361{
    362	struct miscdevice *dev = file->private_data;
    363	return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
    364}
    365
    366/*
    367 * provide an empty .open callback, so the core sets file->private_data
    368 * for us.
    369 */
    370static int pxa3xx_gcu_open(struct inode *inode, struct file *file)
    371{
    372	return 0;
    373}
    374
    375static ssize_t
    376pxa3xx_gcu_write(struct file *file, const char *buff,
    377		 size_t count, loff_t *offp)
    378{
    379	int ret;
    380	unsigned long flags;
    381	struct pxa3xx_gcu_batch	*buffer;
    382	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
    383
    384	size_t words = count / 4;
    385
    386	/* Does not need to be atomic. There's a lock in user space,
    387	 * but anyhow, this is just for statistics. */
    388	priv->shared->num_writes++;
    389	priv->shared->num_words += words;
    390
    391	/* Last word reserved for batch buffer end command */
    392	if (words >= PXA3XX_GCU_BATCH_WORDS)
    393		return -E2BIG;
    394
    395	/* Wait for a free buffer */
    396	if (!priv->free) {
    397		ret = pxa3xx_gcu_wait_free(priv);
    398		if (ret < 0)
    399			return ret;
    400	}
    401
    402	/*
    403	 * Get buffer from free list
    404	 */
    405	spin_lock_irqsave(&priv->spinlock, flags);
    406	buffer = priv->free;
    407	priv->free = buffer->next;
    408	spin_unlock_irqrestore(&priv->spinlock, flags);
    409
    410
    411	/* Copy data from user into buffer */
    412	ret = copy_from_user(buffer->ptr, buff, words * 4);
    413	if (ret) {
    414		spin_lock_irqsave(&priv->spinlock, flags);
    415		buffer->next = priv->free;
    416		priv->free = buffer;
    417		spin_unlock_irqrestore(&priv->spinlock, flags);
    418		return -EFAULT;
    419	}
    420
    421	buffer->length = words;
    422
    423	/* Append batch buffer end command */
    424	buffer->ptr[words] = 0x01000000;
    425
    426	/*
    427	 * Add buffer to ready list
    428	 */
    429	spin_lock_irqsave(&priv->spinlock, flags);
    430
    431	buffer->next = NULL;
    432
    433	if (priv->ready) {
    434		BUG_ON(priv->ready_last == NULL);
    435
    436		priv->ready_last->next = buffer;
    437	} else
    438		priv->ready = buffer;
    439
    440	priv->ready_last = buffer;
    441
    442	if (!priv->shared->hw_running)
    443		run_ready(priv);
    444
    445	spin_unlock_irqrestore(&priv->spinlock, flags);
    446
    447	return words * 4;
    448}
    449
    450
    451static long
    452pxa3xx_gcu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    453{
    454	unsigned long flags;
    455	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
    456
    457	switch (cmd) {
    458	case PXA3XX_GCU_IOCTL_RESET:
    459		spin_lock_irqsave(&priv->spinlock, flags);
    460		pxa3xx_gcu_reset(priv);
    461		spin_unlock_irqrestore(&priv->spinlock, flags);
    462		return 0;
    463
    464	case PXA3XX_GCU_IOCTL_WAIT_IDLE:
    465		return pxa3xx_gcu_wait_idle(priv);
    466	}
    467
    468	return -ENOSYS;
    469}
    470
    471static int
    472pxa3xx_gcu_mmap(struct file *file, struct vm_area_struct *vma)
    473{
    474	unsigned int size = vma->vm_end - vma->vm_start;
    475	struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
    476
    477	switch (vma->vm_pgoff) {
    478	case 0:
    479		/* hand out the shared data area */
    480		if (size != SHARED_SIZE)
    481			return -EINVAL;
    482
    483		return dma_mmap_coherent(priv->dev, vma,
    484			priv->shared, priv->shared_phys, size);
    485
    486	case SHARED_SIZE >> PAGE_SHIFT:
    487		/* hand out the MMIO base for direct register access
    488		 * from userspace */
    489		if (size != resource_size(priv->resource_mem))
    490			return -EINVAL;
    491
    492		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    493
    494		return io_remap_pfn_range(vma, vma->vm_start,
    495				priv->resource_mem->start >> PAGE_SHIFT,
    496				size, vma->vm_page_prot);
    497	}
    498
    499	return -EINVAL;
    500}
    501
    502
    503#ifdef PXA3XX_GCU_DEBUG_TIMER
    504static struct timer_list pxa3xx_gcu_debug_timer;
    505static struct pxa3xx_gcu_priv *debug_timer_priv;
    506
    507static void pxa3xx_gcu_debug_timedout(struct timer_list *unused)
    508{
    509	struct pxa3xx_gcu_priv *priv = debug_timer_priv;
    510
    511	QERROR("Timer DUMP");
    512
    513	mod_timer(&pxa3xx_gcu_debug_timer, jiffies + 5 * HZ);
    514}
    515
    516static void pxa3xx_gcu_init_debug_timer(struct pxa3xx_gcu_priv *priv)
    517{
    518	/* init the timer structure */
    519	debug_timer_priv = priv;
    520	timer_setup(&pxa3xx_gcu_debug_timer, pxa3xx_gcu_debug_timedout, 0);
    521	pxa3xx_gcu_debug_timedout(NULL);
    522}
    523#else
    524static inline void pxa3xx_gcu_init_debug_timer(struct pxa3xx_gcu_priv *priv) {}
    525#endif
    526
    527static int
    528pxa3xx_gcu_add_buffer(struct device *dev,
    529		      struct pxa3xx_gcu_priv *priv)
    530{
    531	struct pxa3xx_gcu_batch *buffer;
    532
    533	buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
    534	if (!buffer)
    535		return -ENOMEM;
    536
    537	buffer->ptr = dma_alloc_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
    538					 &buffer->phys, GFP_KERNEL);
    539	if (!buffer->ptr) {
    540		kfree(buffer);
    541		return -ENOMEM;
    542	}
    543
    544	buffer->next = priv->free;
    545	priv->free = buffer;
    546
    547	return 0;
    548}
    549
    550static void
    551pxa3xx_gcu_free_buffers(struct device *dev,
    552			struct pxa3xx_gcu_priv *priv)
    553{
    554	struct pxa3xx_gcu_batch *next, *buffer = priv->free;
    555
    556	while (buffer) {
    557		next = buffer->next;
    558
    559		dma_free_coherent(dev, PXA3XX_GCU_BATCH_WORDS * 4,
    560				  buffer->ptr, buffer->phys);
    561
    562		kfree(buffer);
    563		buffer = next;
    564	}
    565
    566	priv->free = NULL;
    567}
    568
    569static const struct file_operations pxa3xx_gcu_miscdev_fops = {
    570	.owner =		THIS_MODULE,
    571	.open =			pxa3xx_gcu_open,
    572	.write =		pxa3xx_gcu_write,
    573	.unlocked_ioctl =	pxa3xx_gcu_ioctl,
    574	.mmap =			pxa3xx_gcu_mmap,
    575};
    576
    577static int pxa3xx_gcu_probe(struct platform_device *pdev)
    578{
    579	int i, ret, irq;
    580	struct resource *r;
    581	struct pxa3xx_gcu_priv *priv;
    582	struct device *dev = &pdev->dev;
    583
    584	priv = devm_kzalloc(dev, sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
    585	if (!priv)
    586		return -ENOMEM;
    587
    588	init_waitqueue_head(&priv->wait_idle);
    589	init_waitqueue_head(&priv->wait_free);
    590	spin_lock_init(&priv->spinlock);
    591
    592	/* we allocate the misc device structure as part of our own allocation,
    593	 * so we can get a pointer to our priv structure later on with
    594	 * container_of(). This isn't really necessary as we have a fixed minor
    595	 * number anyway, but this is to avoid statics. */
    596
    597	priv->misc_dev.minor	= PXA3XX_GCU_MINOR,
    598	priv->misc_dev.name	= DRV_NAME,
    599	priv->misc_dev.fops	= &pxa3xx_gcu_miscdev_fops;
    600
    601	/* handle IO resources */
    602	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    603	priv->mmio_base = devm_ioremap_resource(dev, r);
    604	if (IS_ERR(priv->mmio_base))
    605		return PTR_ERR(priv->mmio_base);
    606
    607	/* enable the clock */
    608	priv->clk = devm_clk_get(dev, NULL);
    609	if (IS_ERR(priv->clk))
    610		return dev_err_probe(dev, PTR_ERR(priv->clk), "failed to get clock\n");
    611
    612	/* request the IRQ */
    613	irq = platform_get_irq(pdev, 0);
    614	if (irq < 0)
    615		return irq;
    616
    617	ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq,
    618			       0, DRV_NAME, priv);
    619	if (ret < 0) {
    620		dev_err(dev, "request_irq failed\n");
    621		return ret;
    622	}
    623
    624	/* allocate dma memory */
    625	priv->shared = dma_alloc_coherent(dev, SHARED_SIZE,
    626					  &priv->shared_phys, GFP_KERNEL);
    627	if (!priv->shared) {
    628		dev_err(dev, "failed to allocate DMA memory\n");
    629		return -ENOMEM;
    630	}
    631
    632	/* register misc device */
    633	ret = misc_register(&priv->misc_dev);
    634	if (ret < 0) {
    635		dev_err(dev, "misc_register() for minor %d failed\n",
    636			PXA3XX_GCU_MINOR);
    637		goto err_free_dma;
    638	}
    639
    640	ret = clk_prepare_enable(priv->clk);
    641	if (ret < 0) {
    642		dev_err(dev, "failed to enable clock\n");
    643		goto err_misc_deregister;
    644	}
    645
    646	for (i = 0; i < 8; i++) {
    647		ret = pxa3xx_gcu_add_buffer(dev, priv);
    648		if (ret) {
    649			pxa3xx_gcu_free_buffers(dev, priv);
    650			dev_err(dev, "failed to allocate DMA memory\n");
    651			goto err_disable_clk;
    652		}
    653	}
    654
    655	platform_set_drvdata(pdev, priv);
    656	priv->resource_mem = r;
    657	priv->dev = dev;
    658	pxa3xx_gcu_reset(priv);
    659	pxa3xx_gcu_init_debug_timer(priv);
    660
    661	dev_info(dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
    662			(void *) r->start, (void *) priv->shared_phys,
    663			SHARED_SIZE, irq);
    664	return 0;
    665
    666err_disable_clk:
    667	clk_disable_unprepare(priv->clk);
    668
    669err_misc_deregister:
    670	misc_deregister(&priv->misc_dev);
    671
    672err_free_dma:
    673	dma_free_coherent(dev, SHARED_SIZE,
    674			  priv->shared, priv->shared_phys);
    675
    676	return ret;
    677}
    678
    679static int pxa3xx_gcu_remove(struct platform_device *pdev)
    680{
    681	struct pxa3xx_gcu_priv *priv = platform_get_drvdata(pdev);
    682	struct device *dev = &pdev->dev;
    683
    684	pxa3xx_gcu_wait_idle(priv);
    685	misc_deregister(&priv->misc_dev);
    686	dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys);
    687	clk_disable_unprepare(priv->clk);
    688	pxa3xx_gcu_free_buffers(dev, priv);
    689
    690	return 0;
    691}
    692
    693#ifdef CONFIG_OF
    694static const struct of_device_id pxa3xx_gcu_of_match[] = {
    695	{ .compatible = "marvell,pxa300-gcu", },
    696	{ }
    697};
    698MODULE_DEVICE_TABLE(of, pxa3xx_gcu_of_match);
    699#endif
    700
    701static struct platform_driver pxa3xx_gcu_driver = {
    702	.probe	  = pxa3xx_gcu_probe,
    703	.remove	 = pxa3xx_gcu_remove,
    704	.driver	 = {
    705		.name   = DRV_NAME,
    706		.of_match_table = of_match_ptr(pxa3xx_gcu_of_match),
    707	},
    708};
    709
    710module_platform_driver(pxa3xx_gcu_driver);
    711
    712MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
    713MODULE_LICENSE("GPL");
    714MODULE_ALIAS_MISCDEV(PXA3XX_GCU_MINOR);
    715MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
    716		"Denis Oliver Kropp <dok@directfb.org>, "
    717		"Daniel Mack <daniel@caiaq.de>");