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