static long pxa3xx_gcu_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; struct pxa3xx_gcu_priv *priv = file_dev(file); switch (cmd) { case PXA3XX_GCU_IOCTL_RESET: spin_lock_irqsave(&priv->spinlock, flags); pxa3xx_gcu_reset(priv); spin_unlock_irqrestore(&priv->spinlock, flags); return 0; case PXA3XX_GCU_IOCTL_WAIT_IDLE: return pxa3xx_gcu_wait_idle(priv); } return -ENOSYS; }
static int __devinit pxa3xx_gcu_probe(struct platform_device *dev) { int i, ret, irq; struct resource *r; struct pxa3xx_gcu_priv *priv; priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL); if (!priv) return -ENOMEM; for (i = 0; i < 8; i++) { ret = add_buffer(dev, priv); if (ret) { dev_err(&dev->dev, "failed to allocate DMA memory\n"); goto err_free_priv; } } init_waitqueue_head(&priv->wait_idle); init_waitqueue_head(&priv->wait_free); spin_lock_init(&priv->spinlock); /* we allocate the misc device structure as part of our own allocation, * so we can get a pointer to our priv structure later on with * container_of(). This isn't really necessary as we have a fixed minor * number anyway, but this is to avoid statics. */ priv->misc_fops.owner = THIS_MODULE; priv->misc_fops.write = pxa3xx_gcu_misc_write; priv->misc_fops.unlocked_ioctl = pxa3xx_gcu_misc_ioctl; priv->misc_fops.mmap = pxa3xx_gcu_misc_mmap; priv->misc_dev.minor = MISCDEV_MINOR, priv->misc_dev.name = DRV_NAME, priv->misc_dev.fops = &priv->misc_fops, /* register misc device */ ret = misc_register(&priv->misc_dev); if (ret < 0) { dev_err(&dev->dev, "misc_register() for minor %d failed\n", MISCDEV_MINOR); goto err_free_priv; } /* handle IO resources */ r = platform_get_resource(dev, IORESOURCE_MEM, 0); if (r == NULL) { dev_err(&dev->dev, "no I/O memory resource defined\n"); ret = -ENODEV; goto err_misc_deregister; } if (!request_mem_region(r->start, resource_size(r), dev->name)) { dev_err(&dev->dev, "failed to request I/O memory\n"); ret = -EBUSY; goto err_misc_deregister; } priv->mmio_base = ioremap_nocache(r->start, resource_size(r)); if (!priv->mmio_base) { dev_err(&dev->dev, "failed to map I/O memory\n"); ret = -EBUSY; goto err_free_mem_region; } /* allocate dma memory */ priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE, &priv->shared_phys, GFP_KERNEL); if (!priv->shared) { dev_err(&dev->dev, "failed to allocate DMA memory\n"); ret = -ENOMEM; goto err_free_io; } /* enable the clock */ priv->clk = clk_get(&dev->dev, NULL); if (IS_ERR(priv->clk)) { dev_err(&dev->dev, "failed to get clock\n"); ret = -ENODEV; goto err_free_dma; } ret = clk_enable(priv->clk); if (ret < 0) { dev_err(&dev->dev, "failed to enable clock\n"); goto err_put_clk; } /* request the IRQ */ irq = platform_get_irq(dev, 0); if (irq < 0) { dev_err(&dev->dev, "no IRQ defined\n"); ret = -ENODEV; goto err_put_clk; } ret = request_irq(irq, pxa3xx_gcu_handle_irq, 0, DRV_NAME, priv); if (ret) { dev_err(&dev->dev, "request_irq failed\n"); ret = -EBUSY; goto err_put_clk; } platform_set_drvdata(dev, priv); priv->resource_mem = r; pxa3xx_gcu_reset(priv); pxa3xx_gcu_init_debug_timer(); dev_info(&dev->dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n", (void *) r->start, (void *) priv->shared_phys, SHARED_SIZE, irq); return 0; err_put_clk: clk_disable(priv->clk); clk_put(priv->clk); err_free_dma: dma_free_coherent(&dev->dev, SHARED_SIZE, priv->shared, priv->shared_phys); err_free_io: iounmap(priv->mmio_base); err_free_mem_region: release_mem_region(r->start, resource_size(r)); err_misc_deregister: misc_deregister(&priv->misc_dev); err_free_priv: platform_set_drvdata(dev, NULL); free_buffers(dev, priv); kfree(priv); return ret; }
static int pxa3xx_gcu_probe(struct platform_device *pdev) { int i, ret, irq; struct resource *r; struct pxa3xx_gcu_priv *priv; struct device *dev = &pdev->dev; priv = devm_kzalloc(dev, sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL); if (!priv) return -ENOMEM; init_waitqueue_head(&priv->wait_idle); init_waitqueue_head(&priv->wait_free); spin_lock_init(&priv->spinlock); /* we allocate the misc device structure as part of our own allocation, * so we can get a pointer to our priv structure later on with * container_of(). This isn't really necessary as we have a fixed minor * number anyway, but this is to avoid statics. */ priv->misc_dev.minor = MISCDEV_MINOR, priv->misc_dev.name = DRV_NAME, priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops; /* handle IO resources */ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->mmio_base = devm_request_and_ioremap(dev, r); if (IS_ERR(priv->mmio_base)) { dev_err(dev, "failed to map I/O memory\n"); return PTR_ERR(priv->mmio_base); } /* enable the clock */ priv->clk = devm_clk_get(dev, NULL); if (IS_ERR(priv->clk)) { dev_err(dev, "failed to get clock\n"); return PTR_ERR(priv->clk); } /* request the IRQ */ irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "no IRQ defined\n"); return -ENODEV; } ret = devm_request_irq(dev, irq, pxa3xx_gcu_handle_irq, 0, DRV_NAME, priv); if (ret < 0) { dev_err(dev, "request_irq failed\n"); return ret; } /* allocate dma memory */ priv->shared = dma_alloc_coherent(dev, SHARED_SIZE, &priv->shared_phys, GFP_KERNEL); if (!priv->shared) { dev_err(dev, "failed to allocate DMA memory\n"); return -ENOMEM; } /* register misc device */ ret = misc_register(&priv->misc_dev); if (ret < 0) { dev_err(dev, "misc_register() for minor %d failed\n", MISCDEV_MINOR); goto err_free_dma; } ret = clk_enable(priv->clk); if (ret < 0) { dev_err(dev, "failed to enable clock\n"); goto err_misc_deregister; } for (i = 0; i < 8; i++) { ret = pxa3xx_gcu_add_buffer(dev, priv); if (ret) { dev_err(dev, "failed to allocate DMA memory\n"); goto err_disable_clk; } } platform_set_drvdata(pdev, priv); priv->resource_mem = r; pxa3xx_gcu_reset(priv); pxa3xx_gcu_init_debug_timer(); dev_info(dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n", (void *) r->start, (void *) priv->shared_phys, SHARED_SIZE, irq); return 0; err_free_dma: dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys); err_misc_deregister: misc_deregister(&priv->misc_dev); err_disable_clk: clk_disable(priv->clk); return ret; }