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 timespec64         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 timespec64 ts;                                   \
 130                struct pxa3xx_gcu_shared *shared = priv->shared;        \
 131                u32 base = gc_readl(priv, REG_GCRBBR);                  \
 132                                                                        \
 133                ktime_get_ts64(&ts);                                    \
 134                ts = timespec64_sub(ts, priv->base_time);               \
 135                                                                        \
 136                printk(level "%lld.%03ld.%03ld - %-17s: %-21s (%s, "    \
 137                        "STATUS "                                       \
 138                        "0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, "    \
 139                        "T %5ld)\n",                                    \
 140                        (s64)(ts.tv_sec),                               \
 141                        ts.tv_nsec / NSEC_PER_MSEC,                     \
 142                        (ts.tv_nsec % NSEC_PER_MSEC) / USEC_PER_MSEC,   \
 143                        __func__, msg,                                  \
 144                        shared->hw_running ? "running" : "   idle",     \
 145                        gc_readl(priv, REG_GCISCR),                     \
 146                        gc_readl(priv, REG_GCRBBR),                     \
 147                        gc_readl(priv, REG_GCRBLR),                     \
 148                        (gc_readl(priv, REG_GCRBEXHR) - base) / 4,      \
 149                        (gc_readl(priv, REG_GCRBHR) - base) / 4,        \
 150                        (gc_readl(priv, REG_GCRBTR) - base) / 4);       \
 151        } while (0)
 152
 153static void
 154pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
 155{
 156        QDUMP("RESET");
 157
 158        /* disable interrupts */
 159        gc_writel(priv, REG_GCIECR, 0);
 160
 161        /* reset hardware */
 162        gc_writel(priv, REG_GCCR, GCCR_ABORT);
 163        gc_writel(priv, REG_GCCR, 0);
 164
 165        memset(priv->shared, 0, SHARED_SIZE);
 166        priv->shared->buffer_phys = priv->shared_phys;
 167        priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
 168
 169        ktime_get_ts64(&priv->base_time);
 170
 171        /* set up the ring buffer pointers */
 172        gc_writel(priv, REG_GCRBLR, 0);
 173        gc_writel(priv, REG_GCRBBR, priv->shared_phys);
 174        gc_writel(priv, REG_GCRBTR, priv->shared_phys);
 175
 176        /* enable all IRQs except EOB */
 177        gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
 178}
 179
 180static void
 181dump_whole_state(struct pxa3xx_gcu_priv *priv)
 182{
 183        struct pxa3xx_gcu_shared *sh = priv->shared;
 184        u32 base = gc_readl(priv, REG_GCRBBR);
 185
 186        QDUMP("DUMP");
 187
 188        printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
 189                "%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
 190                sh->hw_running ? "running" : "idle   ",
 191                gc_readl(priv, REG_GCISCR),
 192                gc_readl(priv, REG_GCRBBR),
 193                gc_readl(priv, REG_GCRBLR),
 194                (gc_readl(priv, REG_GCRBEXHR) - base) / 4,
 195                (gc_readl(priv, REG_GCRBHR) - base) / 4,
 196                (gc_readl(priv, REG_GCRBTR) - base) / 4);
 197}
 198
 199static void
 200flush_running(struct pxa3xx_gcu_priv *priv)
 201{
 202        struct pxa3xx_gcu_batch *running = priv->running;
 203        struct pxa3xx_gcu_batch *next;
 204
 205        while (running) {
 206                next = running->next;
 207                running->next = priv->free;
 208                priv->free = running;
 209                running = next;
 210        }
 211
 212        priv->running = NULL;
 213}
 214
 215static void
 216run_ready(struct pxa3xx_gcu_priv *priv)
 217{
 218        unsigned int num = 0;
 219        struct pxa3xx_gcu_shared *shared = priv->shared;
 220        struct pxa3xx_gcu_batch *ready = priv->ready;
 221
 222        QDUMP("Start");
 223
 224        BUG_ON(!ready);
 225
 226        shared->buffer[num++] = 0x05000000;
 227
 228        while (ready) {
 229                shared->buffer[num++] = 0x00000001;
 230                shared->buffer[num++] = ready->phys;
 231                ready = ready->next;
 232        }
 233
 234        shared->buffer[num++] = 0x05000000;
 235        priv->running = priv->ready;
 236        priv->ready = priv->ready_last = NULL;
 237        gc_writel(priv, REG_GCRBLR, 0);
 238        shared->hw_running = 1;
 239
 240        /* ring base address */
 241        gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
 242
 243        /* ring tail address */
 244        gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
 245
 246        /* ring length */
 247        gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
 248}
 249
 250static irqreturn_t
 251pxa3xx_gcu_handle_irq(int irq, void *ctx)
 252{
 253        struct pxa3xx_gcu_priv *priv = ctx;
 254        struct pxa3xx_gcu_shared *shared = priv->shared;
 255        u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
 256
 257        QDUMP("-Interrupt");
 258
 259        if (!status)
 260                return IRQ_NONE;
 261
 262        spin_lock(&priv->spinlock);
 263        shared->num_interrupts++;
 264
 265        if (status & IE_EEOB) {
 266                QDUMP(" [EEOB]");
 267
 268                flush_running(priv);
 269                wake_up_all(&priv->wait_free);
 270
 271                if (priv->ready) {
 272                        run_ready(priv);
 273                } else {
 274                        /* There is no more data prepared by the userspace.
 275                         * Set hw_running = 0 and wait for the next userspace
 276                         * kick-off */
 277                        shared->num_idle++;
 278                        shared->hw_running = 0;
 279
 280                        QDUMP(" '-> Idle.");
 281
 282                        /* set ring buffer length to zero */
 283                        gc_writel(priv, REG_GCRBLR, 0);
 284
 285                        wake_up_all(&priv->wait_idle);
 286                }
 287
 288                shared->num_done++;
 289        } else {
 290                QERROR(" [???]");
 291                dump_whole_state(priv);
 292        }
 293
 294        /* Clear the interrupt */
 295        gc_writel(priv, REG_GCISCR, status);
 296        spin_unlock(&priv->spinlock);
 297
 298        return IRQ_HANDLED;
 299}
 300
 301static int
 302pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
 303{
 304        int ret = 0;
 305
 306        QDUMP("Waiting for idle...");
 307
 308        /* Does not need to be atomic. There's a lock in user space,
 309         * but anyhow, this is just for statistics. */
 310        priv->shared->num_wait_idle++;
 311
 312        while (priv->shared->hw_running) {
 313                int num = priv->shared->num_interrupts;
 314                u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
 315
 316                ret = wait_event_interruptible_timeout(priv->wait_idle,
 317                                        !priv->shared->hw_running, HZ*4);
 318
 319                if (ret != 0)
 320                        break;
 321
 322                if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
 323                    priv->shared->num_interrupts == num) {
 324                        QERROR("TIMEOUT");
 325                        ret = -ETIMEDOUT;
 326                        break;
 327                }
 328        }
 329
 330        QDUMP("done");
 331
 332        return ret;
 333}
 334
 335static int
 336pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
 337{
 338        int ret = 0;
 339
 340        QDUMP("Waiting for free...");
 341
 342        /* Does not need to be atomic. There's a lock in user space,
 343         * but anyhow, this is just for statistics. */
 344        priv->shared->num_wait_free++;
 345
 346        while (!priv->free) {
 347                u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
 348
 349                ret = wait_event_interruptible_timeout(priv->wait_free,
 350                                                       priv->free, HZ*4);
 351
 352                if (ret < 0)
 353                        break;
 354
 355                if (ret > 0)
 356                        continue;
 357
 358                if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
 359                        QERROR("TIMEOUT");
 360                        ret = -ETIMEDOUT;
 361                        break;
 362                }
 363        }
 364
 365        QDUMP("done");
 366
 367        return ret;
 368}
 369
 370/* Misc device layer */
 371
 372static inline struct pxa3xx_gcu_priv *to_pxa3xx_gcu_priv(struct file *file)
 373{
 374        struct miscdevice *dev = file->private_data;
 375        return container_of(dev, struct pxa3xx_gcu_priv, misc_dev);
 376}
 377
 378/*
 379 * provide an empty .open callback, so the core sets file->private_data
 380 * for us.
 381 */
 382static int pxa3xx_gcu_open(struct inode *inode, struct file *file)
 383{
 384        return 0;
 385}
 386
 387static ssize_t
 388pxa3xx_gcu_write(struct file *file, const char *buff,
 389                 size_t count, loff_t *offp)
 390{
 391        int ret;
 392        unsigned long flags;
 393        struct pxa3xx_gcu_batch *buffer;
 394        struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
 395
 396        int words = count / 4;
 397
 398        /* Does not need to be atomic. There's a lock in user space,
 399         * but anyhow, this is just for statistics. */
 400        priv->shared->num_writes++;
 401        priv->shared->num_words += words;
 402
 403        /* Last word reserved for batch buffer end command */
 404        if (words >= PXA3XX_GCU_BATCH_WORDS)
 405                return -E2BIG;
 406
 407        /* Wait for a free buffer */
 408        if (!priv->free) {
 409                ret = pxa3xx_gcu_wait_free(priv);
 410                if (ret < 0)
 411                        return ret;
 412        }
 413
 414        /*
 415         * Get buffer from free list
 416         */
 417        spin_lock_irqsave(&priv->spinlock, flags);
 418        buffer = priv->free;
 419        priv->free = buffer->next;
 420        spin_unlock_irqrestore(&priv->spinlock, flags);
 421
 422
 423        /* Copy data from user into buffer */
 424        ret = copy_from_user(buffer->ptr, buff, words * 4);
 425        if (ret) {
 426                spin_lock_irqsave(&priv->spinlock, flags);
 427                buffer->next = priv->free;
 428                priv->free = buffer;
 429                spin_unlock_irqrestore(&priv->spinlock, flags);
 430                return -EFAULT;
 431        }
 432
 433        buffer->length = words;
 434
 435        /* Append batch buffer end command */
 436        buffer->ptr[words] = 0x01000000;
 437
 438        /*
 439         * Add buffer to ready list
 440         */
 441        spin_lock_irqsave(&priv->spinlock, flags);
 442
 443        buffer->next = NULL;
 444
 445        if (priv->ready) {
 446                BUG_ON(priv->ready_last == NULL);
 447
 448                priv->ready_last->next = buffer;
 449        } else
 450                priv->ready = buffer;
 451
 452        priv->ready_last = buffer;
 453
 454        if (!priv->shared->hw_running)
 455                run_ready(priv);
 456
 457        spin_unlock_irqrestore(&priv->spinlock, flags);
 458
 459        return words * 4;
 460}
 461
 462
 463static long
 464pxa3xx_gcu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 465{
 466        unsigned long flags;
 467        struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
 468
 469        switch (cmd) {
 470        case PXA3XX_GCU_IOCTL_RESET:
 471                spin_lock_irqsave(&priv->spinlock, flags);
 472                pxa3xx_gcu_reset(priv);
 473                spin_unlock_irqrestore(&priv->spinlock, flags);
 474                return 0;
 475
 476        case PXA3XX_GCU_IOCTL_WAIT_IDLE:
 477                return pxa3xx_gcu_wait_idle(priv);
 478        }
 479
 480        return -ENOSYS;
 481}
 482
 483static int
 484pxa3xx_gcu_mmap(struct file *file, struct vm_area_struct *vma)
 485{
 486        unsigned int size = vma->vm_end - vma->vm_start;
 487        struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
 488
 489        switch (vma->vm_pgoff) {
 490        case 0:
 491                /* hand out the shared data area */
 492                if (size != SHARED_SIZE)
 493                        return -EINVAL;
 494
 495                return dma_mmap_coherent(NULL, vma,
 496                        priv->shared, priv->shared_phys, size);
 497
 498        case SHARED_SIZE >> PAGE_SHIFT:
 499                /* hand out the MMIO base for direct register access
 500                 * from userspace */
 501                if (size != resource_size(priv->resource_mem))
 502                        return -EINVAL;
 503
 504                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 505
 506                return io_remap_pfn_range(vma, vma->vm_start,
 507                                priv->resource_mem->start >> PAGE_SHIFT,
 508                                size, vma->vm_page_prot);
 509        }
 510
 511        return -EINVAL;
 512}
 513
 514
 515#ifdef PXA3XX_GCU_DEBUG_TIMER
 516static struct timer_list pxa3xx_gcu_debug_timer;
 517static struct pxa3xx_gcu_priv *debug_timer_priv;
 518
 519static void pxa3xx_gcu_debug_timedout(struct timer_list *unused)
 520{
 521        struct pxa3xx_gcu_priv *priv = debug_timer_priv;
 522
 523        QERROR("Timer DUMP");
 524
 525        mod_timer(&pxa3xx_gcu_debug_timer, jiffies + 5 * HZ);
 526}
 527
 528static void pxa3xx_gcu_init_debug_timer(struct pxa3xx_gcu_priv *priv)
 529{
 530        /* init the timer structure */
 531        debug_timer_priv = priv;
 532        timer_setup(&pxa3xx_gcu_debug_timer, pxa3xx_gcu_debug_timedout, 0);
 533        pxa3xx_gcu_debug_timedout(NULL);
 534}
 535#else
 536static inline void pxa3xx_gcu_init_debug_timer(struct pxa3xx_gcu_priv *priv) {}
 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: %d\n", irq);
 630                return irq;
 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(priv);
 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