From: Albert H. <he...@us...> - 2008-03-26 20:15:54
|
Update of /cvsroot/gc-linux/linux/drivers/block In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv22420/drivers/block Modified Files: gcn-aram.c gcn-sd.c rvl-mem2.c Log Message: Remove old ugecon driver (we use now usbgecko_udbg). Rewrite the following drivers as of_platform drivers using the device tree: - gcn-rsw - starlet-ipc - gcn-aram - rvl-mem2 - gcn-di - exi-driver, exi-hw - gcn-si - gcnfb (gcn-vifb) - gcn-ai Marked as broken gcn-mi and gcngx. Updated defconfigs. Index: rvl-mem2.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/rvl-mem2.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- rvl-mem2.c 18 Mar 2008 18:57:18 -0000 1.2 +++ rvl-mem2.c 26 Mar 2008 20:15:08 -0000 1.3 @@ -5,7 +5,7 @@ * Copyright (C) 2008 The GameCube Linux Team * Copyright (C) 2008 Albert Herranz * - * Based on gcn-aram.c. + * Based on gcn-mem2.c. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -16,7 +16,7 @@ #include <linux/module.h> #include <linux/major.h> -#include <linux/platform_device.h> +#include <linux/of_platform.h> #include <linux/blkdev.h> #include <linux/fcntl.h> /* O_ACCMODE */ #include <linux/hdreg.h> /* HDIO_GETGEO */ @@ -27,25 +27,11 @@ #define DRV_DESCRIPTION "Nintendo Wii MEM2 block driver" #define DRV_AUTHOR "Albert Herranz" -static char mem2_driver_version[] = "0.1"; +static char mem2_driver_version[] = "0.1-isobel"; -#define mem2_printk(level, format, arg...) \ +#define drv_printk(level, format, arg...) \ printk(level DRV_MODULE_NAME ": " format , ## arg) -#ifdef MEM2_DEBUG -# define DBG(fmt, args...) \ - printk(KERN_ERR "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DBG(fmt, args...) -#endif - -/* - * Hardware. - */ - -#define MEM2_START 0x10000000 -#define MEM2_SIZE (52*1024*1024) /* 52MB */ -#define MEM2_END (MEM2_START + MEM2_SIZE - 1) /* * Driver settings @@ -56,10 +42,11 @@ #define MEM2_SECTOR_SIZE PAGE_SIZE -struct mem2_device { +struct mem2_drvdata { spinlock_t lock; void __iomem *io_base; + size_t size; struct block_device_operations fops; struct gendisk *disk; @@ -67,13 +54,9 @@ int ref_count; - struct platform_device pdev; /* must be last member */ + struct device *dev; }; - -/* get the mem2 device given the platform device of a mem2 device */ -#define to_mem2_device(n) container_of(n,struct mem2_device,pdev) - /* * */ @@ -83,7 +66,7 @@ */ static void mem2_do_request(struct request_queue *q) { - struct mem2_device *adev = q->queuedata; + struct mem2_drvdata *drvdata = q->queuedata; struct request *req; unsigned long mem2_addr; size_t len; @@ -97,8 +80,8 @@ len = req->current_nr_sectors << 9; /* give up if the request goes out of bounds */ - if (mem2_addr + len > MEM2_SIZE) { - mem2_printk(KERN_ERR, "bad access: block=%lu," + if (mem2_addr + len > drvdata->size) { + drv_printk(KERN_ERR, "bad access: block=%lu," " size=%u\n", (unsigned long)req->sector, len); uptodate = 0; @@ -106,10 +89,10 @@ switch(rq_data_dir(req)) { case READ: memcpy(req->buffer, - adev->io_base + mem2_addr, len); + drvdata->io_base + mem2_addr, len); break; case WRITE: - memcpy(adev->io_base + mem2_addr, + memcpy(drvdata->io_base + mem2_addr, req->buffer, len); break; } @@ -128,11 +111,11 @@ */ static int mem2_open(struct inode *inode, struct file *filp) { - struct mem2_device *adev = inode->i_bdev->bd_disk->private_data; + struct mem2_drvdata *drvdata = inode->i_bdev->bd_disk->private_data; unsigned long flags; int retval = 0; - spin_lock_irqsave(&adev->lock, flags); + spin_lock_irqsave(&drvdata->lock, flags); /* only allow a minor of 0 to be opened */ if (iminor(inode)) { @@ -141,19 +124,19 @@ } /* honor exclusive open mode */ - if (adev->ref_count == -1 || - (adev->ref_count && (filp->f_flags & O_EXCL))) { + if (drvdata->ref_count == -1 || + (drvdata->ref_count && (filp->f_flags & O_EXCL))) { retval = -EBUSY; goto out; } if ((filp->f_flags & O_EXCL)) - adev->ref_count = -1; + drvdata->ref_count = -1; else - adev->ref_count++; + drvdata->ref_count++; out: - spin_unlock_irqrestore(&adev->lock, flags); + spin_unlock_irqrestore(&drvdata->lock, flags); return retval; } @@ -162,15 +145,15 @@ */ static int mem2_release(struct inode *inode, struct file *filp) { - struct mem2_device *adev = inode->i_bdev->bd_disk->private_data; + struct mem2_drvdata *drvdata = inode->i_bdev->bd_disk->private_data; unsigned long flags; - spin_lock_irqsave(&adev->lock, flags); - if (adev->ref_count > 0) - adev->ref_count--; + spin_lock_irqsave(&drvdata->lock, flags); + if (drvdata->ref_count > 0) + drvdata->ref_count--; else - adev->ref_count = 0; - spin_unlock_irqrestore(&adev->lock, flags); + drvdata->ref_count = 0; + spin_unlock_irqrestore(&drvdata->lock, flags); return 0; } @@ -178,9 +161,10 @@ /* * Minimal ioctl for the MEM2 device. */ -static int mem2_ioctl(struct inode *inode, struct file *file, +static int mem2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { + struct mem2_drvdata *drvdata = inode->i_bdev->bd_disk->private_data; struct hd_geometry geo; switch (cmd) { @@ -199,7 +183,7 @@ geo.heads = 16; geo.sectors = 32; geo.start = 0; - geo.cylinders = MEM2_SIZE / (geo.heads * geo.sectors); + geo.cylinders = drvdata->size / (geo.heads * geo.sectors); if (copy_to_user((void __user*)arg,&geo,sizeof(geo))) return -EFAULT; return 0; @@ -220,29 +204,29 @@ /* * */ -static int mem2_init_blk_dev(struct mem2_device *adev) +static int mem2_init_blk_dev(struct mem2_drvdata *drvdata) { struct gendisk *disk; struct request_queue *queue; int retval; - adev->ref_count = 0; + drvdata->ref_count = 0; retval = register_blkdev(MEM2_MAJOR, MEM2_NAME); if (retval) goto err_register_blkdev; retval = -ENOMEM; - spin_lock_init(&adev->lock); - queue = blk_init_queue(mem2_do_request, &adev->lock); + spin_lock_init(&drvdata->lock); + queue = blk_init_queue(mem2_do_request, &drvdata->lock); if (!queue) goto err_blk_init_queue; blk_queue_hardsect_size(queue, MEM2_SECTOR_SIZE); blk_queue_max_phys_segments(queue, 1); blk_queue_max_hw_segments(queue, 1); - queue->queuedata = adev; - adev->queue = queue; + queue->queuedata = drvdata; + drvdata->queue = queue; disk = alloc_disk(1); if (!disk) @@ -252,18 +236,18 @@ disk->first_minor = 0; disk->fops = &mem2_fops; strcpy(disk->disk_name, MEM2_NAME); - disk->queue = adev->queue; - set_capacity(disk, MEM2_SIZE >> 9); - disk->private_data = adev; - adev->disk = disk; + disk->queue = drvdata->queue; + set_capacity(disk, drvdata->size >> 9); + disk->private_data = drvdata; + drvdata->disk = disk; - add_disk(adev->disk); + add_disk(drvdata->disk); retval = 0; goto out; err_alloc_disk: - blk_cleanup_queue(adev->queue); + blk_cleanup_queue(drvdata->queue); err_blk_init_queue: unregister_blkdev(MEM2_MAJOR, MEM2_NAME); err_register_blkdev: @@ -274,142 +258,152 @@ /* * */ -static void mem2_exit_blk_dev(struct mem2_device *adev) +static void mem2_exit_blk_dev(struct mem2_drvdata *drvdata) { - if (adev->disk) { - del_gendisk(adev->disk); - put_disk(adev->disk); + if (drvdata->disk) { + del_gendisk(drvdata->disk); + put_disk(drvdata->disk); } - if (adev->queue) - blk_cleanup_queue(adev->queue); + if (drvdata->queue) + blk_cleanup_queue(drvdata->queue); unregister_blkdev(MEM2_MAJOR, MEM2_NAME); } /* * */ -static int mem2_init(struct mem2_device *adev, struct resource *mem) +static int mem2_init(struct mem2_drvdata *drvdata, struct resource *mem) { - memset(adev, 0, sizeof(*adev) - sizeof(adev->pdev)); + int retval; + size_t size; - adev->io_base = ioremap(MEM2_START, MEM2_SIZE); - if (!adev->io_base) { - mem2_printk(KERN_ERR, "unable to ioremap MEM2\n"); + size = mem->end - mem->start + 1; + drvdata->size = size; + drvdata->io_base = ioremap(mem->start, size); + if (!drvdata->io_base) { + drv_printk(KERN_ERR, "failed to ioremap MEM2\n"); return -EIO; } - return mem2_init_blk_dev(adev); + retval = mem2_init_blk_dev(drvdata); + if (retval) { + iounmap(drvdata->io_base); + } + return retval; } /* * */ -static void mem2_exit(struct mem2_device *adev) +static void mem2_exit(struct mem2_drvdata *drvdata) { - if (adev->io_base) - iounmap(adev->io_base); - mem2_exit_blk_dev(adev); + if (drvdata->io_base) + iounmap(drvdata->io_base); + mem2_exit_blk_dev(drvdata); } /* - * Needed for platform devices. + * */ -static void mem2_dev_release(struct device *dev) +static int mem2_do_probe(struct device *dev, struct resource *mem) { -} - - -static struct resource mem2_resources[] = { - [0] = { - .start = MEM2_START, - .end = MEM2_END, - .flags = IORESOURCE_MEM, - }, -}; + struct mem2_drvdata *drvdata; + int retval; -static struct mem2_device mem2_device = { - .pdev = { - .name = MEM2_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mem2_resources), - .resource = mem2_resources, - .dev = { - .release = mem2_dev_release, - }, - }, -}; + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) { + drv_printk(KERN_ERR, "failed to allocate mem2_drvdata\n"); + return -ENOMEM; + } + dev_set_drvdata(dev, drvdata); + drvdata->dev = dev; + retval = mem2_init(drvdata, mem); + if (retval) { + dev_set_drvdata(dev, NULL); + kfree(drvdata); + } + return retval; +} /* * */ -static int mem2_probe(struct device *device) +static int mem2_do_remove(struct device *dev) { - struct platform_device *pdev = to_platform_device(device); - struct mem2_device *adev = to_mem2_device(pdev); - struct resource *mem; - int retval; + struct mem2_drvdata *drvdata = dev_get_drvdata(dev); - retval = -ENODEV; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem) { - retval = mem2_init(adev, mem); + if (drvdata) { + mem2_exit(drvdata); + dev_set_drvdata(dev, NULL); + return 0; } - return retval; + return -ENODEV; } /* - * + * Driver model probe function. */ -static int mem2_remove(struct device *device) +static int __init mem2_of_probe(struct of_device *odev, + const struct of_device_id *match) { - struct platform_device *pdev = to_platform_device(device); - struct mem2_device *adev = to_mem2_device(pdev); + struct resource res; + int retval; - mem2_exit(adev); + retval = of_address_to_resource(odev->node, 0, &res); + if (retval) { + drv_printk(KERN_ERR, "no memory range found\n"); + return -ENODEV; + } - return 0; + return mem2_do_probe(&odev->dev, &res); } +/* + * Driver model remove function. + */ +static int __exit mem2_of_remove(struct of_device *odev) +{ + return mem2_do_remove(&odev->dev); +} -static struct device_driver mem2_driver = { - .name = MEM2_NAME, - .bus = &platform_bus_type, - .probe = mem2_probe, - .remove = mem2_remove, +static struct of_device_id mem2_of_match[] = { + { .compatible = "nintendo,mem2" }, + { }, +}; + +MODULE_DEVICE_TABLE(of, mem2_of_match); + +static struct of_platform_driver mem2_of_driver = { + .owner = THIS_MODULE, + .name = DRV_MODULE_NAME, + .match_table = mem2_of_match, + .probe = mem2_of_probe, + .remove = mem2_of_remove, }; /* - * + * Module initialization function. */ static int __init mem2_init_module(void) { - int retval = 0; - - mem2_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, - mem2_driver_version); - - retval = driver_register(&mem2_driver); - if (!retval) { - retval = platform_device_register(&mem2_device.pdev); - } + drv_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, + mem2_driver_version); - return retval; + return of_register_platform_driver(&mem2_of_driver); } /* - * + * Module deinitialization funtion. */ static void __exit mem2_exit_module(void) { - platform_device_unregister(&mem2_device.pdev); - driver_unregister(&mem2_driver); + of_unregister_platform_driver(&mem2_of_driver); } module_init(mem2_init_module); module_exit(mem2_exit_module); - MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); Index: gcn-sd.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-sd.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- gcn-sd.c 4 Mar 2008 06:20:55 -0000 1.12 +++ gcn-sd.c 26 Mar 2008 20:15:08 -0000 1.13 @@ -73,7 +73,7 @@ #include <linux/exi.h> #define DRV_MODULE_NAME "gcn-sd" -#define DRV_DESCRIPTION "MMC/SD card block driver for the Nintendo GameCube" +#define DRV_DESCRIPTION "MMC/SD card block driver for the Nintendo GameCube/Wii" #define DRV_AUTHOR "Rob Reylink, " \ "Todd Jeffreys, " \ "Albert Herranz" @@ -501,9 +501,6 @@ /* */ static inline void spi_read(struct sd_host *host, void *data, size_t len) { -#ifdef CONFIG_GAMECUBE_WII - exi_dev_read(host->exi_device, data, len); -#else /* * Houston, we have a problem. * @@ -534,7 +531,6 @@ * */ exi_dev_transfer(host->exi_device, data, len, EXI_OP_READ, EXI_CMD_IDI); -#endif } /* cycles are expressed in 8 clock cycles */ Index: gcn-aram.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-aram.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- gcn-aram.c 19 Nov 2007 17:46:53 -0000 1.15 +++ gcn-aram.c 26 Mar 2008 20:15:08 -0000 1.16 @@ -1,10 +1,10 @@ /* * drivers/block/gcn-aram.c * - * Nintendo GameCube Auxiliary RAM block driver - * Copyright (C) 2004-2007 The GameCube Linux Team + * Nintendo GameCube Auxiliary RAM (ARAM) block driver + * Copyright (C) 2004-2008 The GameCube Linux Team * Copyright (C) 2005 Todd Jeffreys <to...@vo...> - * Copyright (C) 2005,2007 Albert Herranz + * Copyright (C) 2005,2007,2008 Albert Herranz * * Based on previous work by Franz Lehner. * @@ -15,46 +15,33 @@ * */ -#include <linux/module.h> -#include <linux/major.h> -#include <linux/platform_device.h> #include <linux/blkdev.h> +#include <linux/dma-mapping.h> #include <linux/fcntl.h> /* O_ACCMODE */ #include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/interrupt.h> -#include <linux/dma-mapping.h> +#include <linux/major.h> +#include <linux/module.h> +#include <linux/of_platform.h> #include <asm/io.h> #define DRV_MODULE_NAME "gcn-aram" -#define DRV_DESCRIPTION "Nintendo GameCube Auxiliary RAM block driver" +#define DRV_DESCRIPTION "Nintendo GameCube Auxiliary RAM (ARAM) block driver" #define DRV_AUTHOR "Todd Jeffreys <to...@vo...>, " \ "Albert Herranz" -static char aram_driver_version[] = "3.0"; +static char aram_driver_version[] = "4.0"; -#define aram_printk(level, format, arg...) \ +#define drv_printk(level, format, arg...) \ printk(level DRV_MODULE_NAME ": " format , ## arg) -#ifdef ARAM_DEBUG -# define DBG(fmt, args...) \ - printk(KERN_ERR "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DBG(fmt, args...) -#endif /* * Hardware. */ -#define ARAM_IRQ 6 - #define ARAM_DMA_ALIGN 0x1f /* 32 bytes */ -#define DSP_BASE 0xcc005000 -#define DSP_SIZE 0x200 - -#define DSP_IO_BASE ((void __iomem *)DSP_BASE) - #define DSP_CSR 0x00a #define DSP_CSR_RES (1<<0) #define DSP_CSR_PIINT (1<<1) @@ -90,22 +77,22 @@ /* * Driver settings */ -#define ARAM_NAME "gcnaram" -#define ARAM_MAJOR Z2RAM_MAJOR +#define ARAM_NAME DRV_MODULE_NAME +#define ARAM_MAJOR Z2RAM_MAJOR /* we share the major */ #define ARAM_SECTOR_SIZE PAGE_SIZE -#define ARAM_SOUNDMEMORYOFFSET 0 -#define ARAM_BUFFERSIZE (16*1024*1024 - ARAM_SOUNDMEMORYOFFSET) - - +#define ARAM_BUFFERSIZE (16*1024*1024) -struct aram_device { +/* + * Driver data. + */ +struct aram_drvdata { spinlock_t lock; - int irq; - void __iomem *io_base; spinlock_t io_lock; + void __iomem *io_base; + int irq; struct block_device_operations fops; struct gendisk *disk; @@ -117,16 +104,10 @@ int ref_count; - struct platform_device pdev; /* must be last member */ + struct device *dev; }; -/* get the aram device given the platform device of an aram device */ -#define to_aram_device(n) container_of(n,struct aram_device,pdev) - -/* - * Converts a request direction into a DMA data direction. - */ static inline enum dma_data_direction rq_dir_to_dma_dir(struct request *req) { if (rq_data_dir(req) == READ) { @@ -136,9 +117,6 @@ } } -/* - * Converts a request direction into an ARAM data direction. - */ static inline int rq_dir_to_aram_dir(struct request *req) { if (rq_data_dir(req) == READ) { @@ -148,16 +126,12 @@ } } - -/* - * Starts an ARAM DMA transfer. - */ -static void aram_start_dma_transfer(struct aram_device *adev, +static void aram_start_dma_transfer(struct aram_drvdata *drvdata, unsigned long aram_addr) { - void __iomem *io_base = adev->io_base; - dma_addr_t dma_addr = adev->dma_addr; - size_t dma_len = adev->dma_len; + void __iomem *io_base = drvdata->io_base; + dma_addr_t dma_addr = drvdata->dma_addr; + size_t dma_len = drvdata->dma_len; /* DMA transfers require proper alignment */ BUG_ON((dma_addr & ARAM_DMA_ALIGN) != 0 || @@ -167,30 +141,28 @@ out_be32(io_base + AR_DMA_ARADDR, aram_addr); /* writing the low-word kicks off the DMA */ - out_be32(io_base + AR_DMA_CNT, rq_dir_to_aram_dir(adev->req) | dma_len); + out_be32(io_base + AR_DMA_CNT, + rq_dir_to_aram_dir(drvdata->req) | dma_len); } -/* - * Handles ARAM interrupts. - */ static irqreturn_t aram_irq_handler(int irq, void *dev0) { - struct aram_device *adev = dev0; + struct aram_drvdata *drvdata = dev0; struct request *req; - u16 __iomem *csr_reg = adev->io_base + DSP_CSR; + u16 __iomem *csr_reg = drvdata->io_base + DSP_CSR; u16 csr; unsigned long flags; - spin_lock_irqsave(&adev->io_lock, flags); + spin_lock_irqsave(&drvdata->io_lock, flags); csr = in_be16(csr_reg); /* * Do nothing if the interrupt is not targetted for us. - * (We share this interrupt with the sound driver). + * We share this interrupt with the sound driver. */ if (!(csr & DSP_CSR_ARINT)) { - spin_unlock_irqrestore(&adev->io_lock, flags); + spin_unlock_irqrestore(&drvdata->io_lock, flags); return IRQ_NONE; } @@ -199,34 +171,32 @@ out_be16(csr_reg, csr); /* pick up current request being serviced */ - req = adev->req; - adev->req = NULL; + req = drvdata->req; + drvdata->req = NULL; - spin_unlock_irqrestore(&adev->io_lock, flags); + spin_unlock_irqrestore(&drvdata->io_lock, flags); if (req) { if (!end_that_request_first(req, 1, req->current_nr_sectors)) { add_disk_randomness(req->rq_disk); end_that_request_last(req, 1); } - dma_unmap_single(&adev->pdev.dev, adev->dma_addr, adev->dma_len, + dma_unmap_single(drvdata->dev, + drvdata->dma_addr, drvdata->dma_len, rq_dir_to_dma_dir(req)); - spin_lock(&adev->lock); - blk_start_queue(adev->queue); - spin_unlock(&adev->lock); + spin_lock(&drvdata->lock); + blk_start_queue(drvdata->queue); + spin_unlock(&drvdata->lock); } else { - aram_printk(KERN_ERR, "ignoring interrupt, no request\n"); + drv_printk(KERN_ERR, "ignoring interrupt, no request\n"); } return IRQ_HANDLED; } -/* - * Performs block layer requests. - */ static void aram_do_request(struct request_queue *q) { - struct aram_device *adev = q->queuedata; + struct aram_drvdata *drvdata = q->queuedata; struct request *req; unsigned long aram_addr; size_t len; @@ -234,11 +204,11 @@ req = elv_next_request(q); while(req) { - spin_lock_irqsave(&adev->io_lock, flags); + spin_lock_irqsave(&drvdata->io_lock, flags); - /* we can schedule just a single request each time */ - if (adev->req) { - spin_unlock_irqrestore(&adev->io_lock, flags); + /* we schedule a single request each time */ + if (drvdata->req) { + spin_unlock_irqrestore(&drvdata->io_lock, flags); blk_stop_queue(q); break; } @@ -247,15 +217,15 @@ /* ignore requests that we can't handle */ if (!blk_fs_request(req)) { - spin_unlock_irqrestore(&adev->io_lock, flags); + spin_unlock_irqrestore(&drvdata->io_lock, flags); continue; } /* store the request being handled */ - adev->req = req; + drvdata->req = req; blk_stop_queue(q); - spin_unlock_irqrestore(&adev->io_lock, flags); + spin_unlock_irqrestore(&drvdata->io_lock, flags); /* calculate the ARAM address and length */ aram_addr = req->sector << 9; @@ -263,8 +233,8 @@ /* give up if the request goes out of bounds */ if (aram_addr + len > ARAM_BUFFERSIZE) { - aram_printk(KERN_ERR, "bad access: block=%lu," - " size=%u\n", (unsigned long)req->sector, + drv_printk(KERN_ERR, "bad access: block=%lu," + " size=%u\n", (unsigned long)req->sector, len); /* XXX correct? the request is already dequeued */ end_request(req, 0); @@ -274,27 +244,29 @@ BUG_ON(req->nr_phys_segments != 1); /* perform DMA mappings */ - adev->dma_len = len; - adev->dma_addr = dma_map_single(&adev->pdev.dev, req->buffer, - len, rq_dir_to_dma_dir(req)); + drvdata->dma_len = len; + drvdata->dma_addr = dma_map_single(drvdata->dev, + req->buffer, len, + rq_dir_to_dma_dir(req)); /* start the DMA transfer */ - aram_start_dma_transfer(adev, - ARAM_SOUNDMEMORYOFFSET + aram_addr); + aram_start_dma_transfer(drvdata, aram_addr); break; } } /* - * Opens the ARAM device. + * Block device hooks. + * */ + static int aram_open(struct inode *inode, struct file *filp) { - struct aram_device *adev = inode->i_bdev->bd_disk->private_data; + struct aram_drvdata *drvdata = inode->i_bdev->bd_disk->private_data; unsigned long flags; int retval = 0; - spin_lock_irqsave(&adev->lock, flags); + spin_lock_irqsave(&drvdata->lock, flags); /* only allow a minor of 0 to be opened */ if (iminor(inode)) { @@ -303,43 +275,37 @@ } /* honor exclusive open mode */ - if (adev->ref_count == -1 || - (adev->ref_count && (filp->f_flags & O_EXCL))) { + if (drvdata->ref_count == -1 || + (drvdata->ref_count && (filp->f_flags & O_EXCL))) { retval = -EBUSY; goto out; } if ((filp->f_flags & O_EXCL)) - adev->ref_count = -1; + drvdata->ref_count = -1; else - adev->ref_count++; + drvdata->ref_count++; out: - spin_unlock_irqrestore(&adev->lock, flags); + spin_unlock_irqrestore(&drvdata->lock, flags); return retval; } -/* - * Closes the ARAM device. - */ static int aram_release(struct inode *inode, struct file *filp) { - struct aram_device *adev = inode->i_bdev->bd_disk->private_data; + struct aram_drvdata *drvdata = inode->i_bdev->bd_disk->private_data; unsigned long flags; - spin_lock_irqsave(&adev->lock, flags); - if (adev->ref_count > 0) - adev->ref_count--; + spin_lock_irqsave(&drvdata->lock, flags); + if (drvdata->ref_count > 0) + drvdata->ref_count--; else - adev->ref_count = 0; - spin_unlock_irqrestore(&adev->lock, flags); + drvdata->ref_count = 0; + spin_unlock_irqrestore(&drvdata->lock, flags); return 0; } -/* - * Minimal ioctl for the ARAM device. - */ static int aram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -380,24 +346,26 @@ /* + * Setup routines. * */ -static int aram_init_blk_dev(struct aram_device *adev) + +static int aram_init_blk_dev(struct aram_drvdata *drvdata) { struct gendisk *disk; struct request_queue *queue; int retval; - adev->ref_count = 0; + drvdata->ref_count = 0; retval = register_blkdev(ARAM_MAJOR, ARAM_NAME); if (retval) goto err_register_blkdev; retval = -ENOMEM; - spin_lock_init(&adev->lock); - spin_lock_init(&adev->io_lock); - queue = blk_init_queue(aram_do_request, &adev->lock); + spin_lock_init(&drvdata->lock); + spin_lock_init(&drvdata->io_lock); + queue = blk_init_queue(aram_do_request, &drvdata->lock); if (!queue) goto err_blk_init_queue; @@ -405,8 +373,8 @@ blk_queue_dma_alignment(queue, ARAM_DMA_ALIGN); blk_queue_max_phys_segments(queue, 1); blk_queue_max_hw_segments(queue, 1); - queue->queuedata = adev; - adev->queue = queue; + queue->queuedata = drvdata; + drvdata->queue = queue; disk = alloc_disk(1); if (!disk) @@ -416,18 +384,18 @@ disk->first_minor = 0; disk->fops = &aram_fops; strcpy(disk->disk_name, ARAM_NAME); - disk->queue = adev->queue; + disk->queue = drvdata->queue; set_capacity(disk, ARAM_BUFFERSIZE >> 9); - disk->private_data = adev; - adev->disk = disk; + disk->private_data = drvdata; + drvdata->disk = disk; - add_disk(adev->disk); + add_disk(drvdata->disk); retval = 0; goto out; err_alloc_disk: - blk_cleanup_queue(adev->queue); + blk_cleanup_queue(drvdata->queue); err_blk_init_queue: unregister_blkdev(ARAM_MAJOR, ARAM_NAME); err_register_blkdev: @@ -435,238 +403,223 @@ return retval; } -/* - * - */ -static void aram_exit_blk_dev(struct aram_device *adev) +static void aram_exit_blk_dev(struct aram_drvdata *drvdata) { - if (adev->disk) { - del_gendisk(adev->disk); - put_disk(adev->disk); + if (drvdata->disk) { + del_gendisk(drvdata->disk); + put_disk(drvdata->disk); } - if (adev->queue) - blk_cleanup_queue(adev->queue); + if (drvdata->queue) + blk_cleanup_queue(drvdata->queue); unregister_blkdev(ARAM_MAJOR, ARAM_NAME); } -/* - * - */ -static void aram_quiesce(struct aram_device *adev) +static void aram_quiesce(struct aram_drvdata *drvdata) { - u16 __iomem *csr_reg = adev->io_base + DSP_CSR; + u16 __iomem *csr_reg = drvdata->io_base + DSP_CSR; u16 csr; unsigned long flags; /* * Disable ARAM interrupts, but do not accidentally ack non-ARAM ones. */ - spin_lock_irqsave(&adev->io_lock, flags); + spin_lock_irqsave(&drvdata->io_lock, flags); csr = in_be16(csr_reg); csr &= ~(DSP_CSR_AIDINT | DSP_CSR_DSPINT | DSP_CSR_ARINTMASK); out_be16(csr_reg, csr); - spin_unlock_irqrestore(&adev->io_lock, flags); + spin_unlock_irqrestore(&drvdata->io_lock, flags); /* wait until pending transfers are finished */ while(in_be16(csr_reg) & DSP_CSR_DSPDMA) cpu_relax(); } -/* - * - */ -static int aram_init_irq(struct aram_device *adev) +static int aram_init_irq(struct aram_drvdata *drvdata) { - u16 __iomem *csr_reg = adev->io_base + DSP_CSR; + u16 __iomem *csr_reg = drvdata->io_base + DSP_CSR; u16 csr; unsigned long flags; int retval; - /* request interrupt */ - retval = request_irq(adev->irq, aram_irq_handler, + retval = request_irq(drvdata->irq, aram_irq_handler, IRQF_DISABLED | IRQF_SHARED, - DRV_MODULE_NAME, adev); + DRV_MODULE_NAME, drvdata); if (retval) { - aram_printk(KERN_ERR, "request of irq%d failed\n", adev->irq); + drv_printk(KERN_ERR, "request of IRQ %d failed\n", + drvdata->irq); goto out; } /* * Enable ARAM interrupts, and route them to the processor. - * As in the other cases, preserve the AI and DSP interrupts. + * Make sure to preserve the AI and DSP interrupts. */ - spin_lock_irqsave(&adev->io_lock, flags); + spin_lock_irqsave(&drvdata->io_lock, flags); csr = in_be16(csr_reg); csr |= (DSP_CSR_ARINT | DSP_CSR_ARINTMASK | DSP_CSR_PIINT); csr &= ~(DSP_CSR_AIDINT | DSP_CSR_DSPINT); out_be16(csr_reg, csr); - spin_unlock_irqrestore(&adev->io_lock, flags); + spin_unlock_irqrestore(&drvdata->io_lock, flags); out: return retval; } -/* - * - */ -static void aram_exit_irq(struct aram_device *adev) +static void aram_exit_irq(struct aram_drvdata *drvdata) { - aram_quiesce(adev); + aram_quiesce(drvdata); - free_irq(adev->irq, adev); + free_irq(drvdata->irq, drvdata); } -/* - * - */ -static int aram_init(struct aram_device *adev, +static int aram_init(struct aram_drvdata *drvdata, struct resource *mem, int irq) { int retval; - memset(adev, 0, sizeof(*adev) - sizeof(adev->pdev)); - - adev->io_base = (void __iomem *)mem->start; - adev->irq = irq; + drvdata->io_base = ioremap(mem->start, mem->end - mem->start + 1); + drvdata->irq = irq; - retval = aram_init_blk_dev(adev); + retval = aram_init_blk_dev(drvdata); if (!retval) { - retval = aram_init_irq(adev); + retval = aram_init_irq(drvdata); if (retval) { - aram_exit_blk_dev(adev); + aram_exit_blk_dev(drvdata); } } return retval; } -/* - * - */ -static void aram_exit(struct aram_device *adev) +static void aram_exit(struct aram_drvdata *drvdata) { - aram_exit_blk_dev(adev); - aram_exit_irq(adev); + aram_exit_blk_dev(drvdata); + aram_exit_irq(drvdata); + if (drvdata->io_base) { + iounmap(drvdata->io_base); + drvdata->io_base = NULL; + } } /* - * Needed for platform devices. + * Driver model helper routines. + * */ -static void aram_dev_release(struct device *dev) + +static int aram_do_probe(struct device *dev, struct resource *mem, + int irq) { -} + struct aram_drvdata *drvdata; + int retval; + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) { + drv_printk(KERN_ERR, "failed to allocate aram_drvdata\n"); + return -ENOMEM; + } + dev_set_drvdata(dev, drvdata); + drvdata->dev = dev; -static struct resource aram_resources[] = { - [0] = { - .start = DSP_BASE, - .end = DSP_BASE + DSP_SIZE -1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = ARAM_IRQ, - .end = ARAM_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; + retval = aram_init(drvdata, mem, irq); + if (retval) { + dev_set_drvdata(dev, NULL); + kfree(drvdata); + } + return retval; +} -static struct aram_device aram_device = { - .pdev = { - .name = ARAM_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(aram_resources), - .resource = aram_resources, - .dev = { - .release = aram_dev_release, - }, - }, -}; +static int aram_do_remove(struct device *dev) +{ + struct aram_drvdata *drvdata = dev_get_drvdata(dev); + if (drvdata) { + aram_exit(drvdata); + dev_set_drvdata(dev, NULL); + kfree(drvdata); + return 0; + } + return -ENODEV; +} -/* - * - */ -static int aram_probe(struct device *device) +static int aram_do_shutdown(struct device *dev) { - struct platform_device *pdev = to_platform_device(device); - struct aram_device *adev = to_aram_device(pdev); - struct resource *mem; - int irq; - int retval; + struct aram_drvdata *drvdata = dev_get_drvdata(dev); - retval = -ENODEV; - irq = platform_get_irq(pdev, 0); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem) { - retval = aram_init(adev, mem, irq); - } - return retval; + if (drvdata) + aram_quiesce(drvdata); + return 0; } + /* + * OF platform device routines. * */ -static int aram_remove(struct device *device) + +static int __init aram_of_probe(struct of_device *odev, + const struct of_device_id *match) { - struct platform_device *pdev = to_platform_device(device); - struct aram_device *adev = to_aram_device(pdev); + struct resource res; + int retval; - aram_exit(adev); + retval = of_address_to_resource(odev->node, 0, &res); + if (retval) { + drv_printk(KERN_ERR, "no io memory range found\n"); + return -ENODEV; + } - return 0; + return aram_do_probe(&odev->dev, + &res, irq_of_parse_and_map(odev->node, 0)); } -/* - * - */ -static void aram_shutdown(struct device *device) +static int __exit aram_of_remove(struct of_device *odev) { - struct platform_device *pdev = to_platform_device(device); - struct aram_device *adev = to_aram_device(pdev); + return aram_do_remove(&odev->dev); +} - aram_quiesce(adev); +static int aram_of_shutdown(struct of_device *odev) +{ + return aram_do_shutdown(&odev->dev); } -static struct device_driver aram_driver = { - .name = ARAM_NAME, - .bus = &platform_bus_type, - .probe = aram_probe, - .remove = aram_remove, - .shutdown = aram_shutdown, +static struct of_device_id aram_of_match[] = { + { .compatible = "nintendo,aram" }, + { }, }; + +MODULE_DEVICE_TABLE(of, aram_of_match); + +static struct of_platform_driver aram_of_driver = { + .owner = THIS_MODULE, + .name = DRV_MODULE_NAME, + .match_table = aram_of_match, + .probe = aram_of_probe, + .remove = aram_of_remove, + .shutdown = aram_of_shutdown, +}; /* + * Module interfaces. * */ + static int __init aram_init_module(void) { - int retval = 0; - - aram_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, - aram_driver_version); - - retval = driver_register(&aram_driver); - if (!retval) { - retval = platform_device_register(&aram_device.pdev); - } + drv_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, + aram_driver_version); - return retval; + return of_register_platform_driver(&aram_of_driver); } -/* - * - */ static void __exit aram_exit_module(void) { - platform_device_unregister(&aram_device.pdev); - driver_unregister(&aram_driver); + of_unregister_platform_driver(&aram_of_driver); } module_init(aram_init_module); module_exit(aram_exit_module); - MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); |