From: Albert H. <he...@us...> - 2008-03-26 20:15:42
|
Update of /cvsroot/gc-linux/linux/arch/powerpc/platforms/embedded6xx In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv22420/arch/powerpc/platforms/embedded6xx Modified Files: gcn-rsw.c starlet-ipc.c starlet-stm.c Removed Files: ugecon.c ugecon.h 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. --- ugecon.h DELETED --- --- ugecon.c DELETED --- Index: gcn-rsw.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/powerpc/platforms/embedded6xx/gcn-rsw.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- gcn-rsw.c 4 Mar 2008 06:20:55 -0000 1.1 +++ gcn-rsw.c 26 Mar 2008 20:14:58 -0000 1.2 @@ -1,7 +1,7 @@ /* * arch/powerpc/platforms/embedded6xx/gcn-rsw.c * - * Nintendo GameCube reset switch driver + * Nintendo GameCube/Wii reset switch (RSW) driver. * Copyright (C) 2004-2008 The GameCube Linux Team * Copyright (C) 2004 Stefan Esser * Copyright (C) 2004,2005,2008 Albert Herranz @@ -16,7 +16,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/of_platform.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/spinlock.h> #include <linux/delay.h> #include <linux/reboot.h> @@ -25,7 +27,20 @@ #include <linux/kexec.h> #endif -#define RSW_IRQ 1 + +/* for flipper hardware registers */ +#include "flipper-pic.h" + +#define DRV_MODULE_NAME "gcn-rsw" +#define DRV_DESCRIPTION "Nintendo GameCube/Wii Reset SWitch (RSW) driver" +#define DRV_AUTHOR "Stefan Esser <se...@no...>, " \ + "Albert Herranz" + +static char rsw_driver_version[] = "1.0-isobel"; + +#define drv_printk(level, format, arg...) \ + printk(level DRV_MODULE_NAME ": " format , ## arg) + #define RSW_NORMAL_TIMEOUT 3 /* seconds */ #define RSW_EMERGENCY_PUSHES 10 @@ -34,103 +49,105 @@ IDLE = 0, /* nothing to do */ NORMAL_RESET, /* reboot requested */ EMERGENCY_RESET, /* try emergency reboot */ -} gcn_rsw_state_t; +} rsw_state_t; -struct gcn_rsw_private { - gcn_rsw_state_t state; +struct rsw_drvdata { + rsw_state_t state; struct timer_list timer; unsigned long jiffies; int pushes; int timeout; spinlock_t lock; + + void __iomem *io_base; + unsigned int irq; + + struct device *dev; }; -#define DRV_MODULE_NAME "gcn-rsw" -#define DRV_DESCRIPTION "Nintendo GameCube reset switch driver" -#define DRV_AUTHOR "Stefan Esser <se...@no...>" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_AUTHOR); -MODULE_LICENSE("GPL"); - -#define PFX DRV_MODULE_NAME ": " -#define rsw_printk(level, format, arg...) \ - printk(level PFX format , ## arg) - +/* + * Tells if the reset button is pressed. + */ +static int rsw_is_button_pressed(void __iomem * io_base) +{ + u32 icr = in_be32(io_base + FLIPPER_ICR); + + drv_printk(KERN_INFO, "%x\n", icr); + return !(icr & FLIPPER_ICR_RSS); +} /* from kernel/sys.c */ extern void ctrl_alt_del(void); -static struct gcn_rsw_private gcn_rsw_private = { - .state = IDLE, - .timeout = RSW_NORMAL_TIMEOUT, -}; - - -/** - * +/* + * Invokes a normal system restart. */ -static void gcn_rsw_normal_reset(unsigned long dummy) +static void rsw_normal_restart(unsigned long dummy) { ctrl_alt_del(); } -/** - * +/* + * Performs a low level system restart. */ -static void gcn_rsw_emergency_reset(void) +static void rsw_emergency_restart(void) { #ifdef CONFIG_KEXEC struct kimage *image; image = xchg(&kexec_image, 0); - if (image) { + if (image) machine_kexec(image); - } #endif machine_restart(NULL); } -/** - * +/* + * Handles the interrupt associated to the reset button. */ -static irqreturn_t gcn_rsw_handler(int this_irq, void *data) +static irqreturn_t rsw_handler(int irq, void *data) { - struct gcn_rsw_private *priv = (struct gcn_rsw_private *)data; + struct rsw_drvdata *drvdata = (struct rsw_drvdata *)data; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); + if (!rsw_is_button_pressed(drvdata->io_base)) { + /* nothing to do */ + return IRQ_HANDLED; + } + + spin_lock_irqsave(&drvdata->lock, flags); /* someone pushed the reset button */ - switch (priv->state) { + switch (drvdata->state) { case IDLE: - priv->state = NORMAL_RESET; + drvdata->state = NORMAL_RESET; printk(KERN_EMERG "Rebooting in %d seconds...\n", - priv->timeout); + drvdata->timeout); printk(KERN_WARNING "Push the Reset button again to cancel reboot!\n"); /* schedule a reboot in a few seconds */ - init_timer(&priv->timer); - priv->timer.expires = jiffies + priv->timeout * HZ; - priv->timer.function = - (void (*)(unsigned long))gcn_rsw_normal_reset; - add_timer(&priv->timer); - priv->jiffies = jiffies; + init_timer(&drvdata->timer); + drvdata->timer.expires = jiffies + drvdata->timeout * HZ; + drvdata->timer.function = + (void (*)(unsigned long))rsw_normal_restart; + add_timer(&drvdata->timer); + drvdata->jiffies = jiffies; break; case NORMAL_RESET: - if (time_before(jiffies, priv->jiffies + priv->timeout * HZ)) { + if (time_before(jiffies, + drvdata->jiffies + drvdata->timeout * HZ)) { /* the reset button was hit again before deadline */ - del_timer(&priv->timer); - priv->state = IDLE; + del_timer(&drvdata->timer); + drvdata->state = IDLE; printk(KERN_EMERG "Reboot cancelled!\n"); } else { /* * Time expired. System should be now restarting. * Go to emergency mode in case something goes bad. */ - priv->state = EMERGENCY_RESET; - priv->pushes = 0; + drvdata->state = EMERGENCY_RESET; + drvdata->pushes = 0; printk(KERN_WARNING "SWITCHED TO EMERGENCY RESET MODE!\n" "Push %d times the Reset button to force" @@ -141,51 +158,167 @@ break; case EMERGENCY_RESET: /* force a hard reset if the user insists ... */ - if (++priv->pushes >= RSW_EMERGENCY_PUSHES) { - spin_unlock_irqrestore(&priv->lock, flags); - gcn_rsw_emergency_reset(); + if (++drvdata->pushes >= RSW_EMERGENCY_PUSHES) { + spin_unlock_irqrestore(&drvdata->lock, flags); + rsw_emergency_restart(); return IRQ_HANDLED; } else { - printk(KERN_INFO - "%d/%d\n", - priv->pushes, + printk(KERN_INFO "%d/%d\n", drvdata->pushes, RSW_EMERGENCY_PUSHES); } break; } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&drvdata->lock, flags); return IRQ_HANDLED; } -/** - * +/* + * Initializes the driver. */ -static int gcn_rsw_init(void) +static int rsw_init(struct rsw_drvdata *drvdata, struct resource *mem, int irq) { - int err; + int retval; - spin_lock_init(&gcn_rsw_private.lock); + drvdata->io_base = ioremap(mem->start, mem->end - mem->start + 1); + drvdata->irq = irq; - err = request_irq(RSW_IRQ, gcn_rsw_handler, 0, - DRV_MODULE_NAME, - (void *)&gcn_rsw_private); - if (err) { - rsw_printk(KERN_ERR, "request of irq%d failed\n", RSW_IRQ); + spin_lock_init(&drvdata->lock); + drvdata->state = IDLE; + drvdata->timeout = RSW_NORMAL_TIMEOUT; + + retval = request_irq(drvdata->irq, rsw_handler, 0, + DRV_MODULE_NAME, drvdata); + if (retval) { + drv_printk(KERN_ERR, "request of IRQ %d failed\n", + drvdata->irq); } + return retval; +} - return err; +/* + * Deinitializes the driver. + */ +static void rsw_exit(struct rsw_drvdata *drvdata) +{ + free_irq(drvdata->irq, drvdata); + if (drvdata->io_base) { + iounmap(drvdata->io_base); + drvdata->io_base = NULL; + } } -/** +/* + * Common probe function for a reset button device. + */ +static int rsw_do_probe(struct device *dev, struct resource *mem, int irq) +{ + struct rsw_drvdata *drvdata; + int retval; + + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) { + drv_printk(KERN_ERR, "failed to allocate rsw_drvdata\n"); + return -ENOMEM; + } + dev_set_drvdata(dev, drvdata); + drvdata->dev = dev; + + retval = rsw_init(drvdata, mem, irq); + if (retval) { + dev_set_drvdata(dev, NULL); + kfree(drvdata); + } + return retval; +} + +/* + * Common remove function for a reset button device. + */ +static int rsw_do_remove(struct device *dev) +{ + struct rsw_drvdata *drvdata = dev_get_drvdata(dev); + + if (drvdata) { + rsw_exit(drvdata); + dev_set_drvdata(dev, NULL); + kfree(drvdata); + return 0; + } + return -ENODEV; +} + +/* + * OF platform driver hooks. * */ -static void gcn_rsw_exit(void) + +/* + * Driver model probe function. + */ +static int __init rsw_of_probe(struct of_device *odev, + const struct of_device_id *match) { - free_irq(RSW_IRQ, &gcn_rsw_private); + struct resource mem; + int retval; + + retval = of_address_to_resource(odev->node, 0, &mem); + if (retval) { + drv_printk(KERN_ERR, "no io memory range found\n"); + return -ENODEV; + } + + return rsw_do_probe(&odev->dev, + &mem, irq_of_parse_and_map(odev->node, 0)); } -module_init(gcn_rsw_init); -module_exit(gcn_rsw_exit); +/* + * Driver model remove function. + */ +static int __exit rsw_of_remove(struct of_device *odev) +{ + return rsw_do_remove(&odev->dev); +} + +static struct of_device_id rsw_of_match[] = { + {.compatible = "nintendo,rsw"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, rsw_of_match); + +static struct of_platform_driver rsw_of_driver = { + .owner = THIS_MODULE, + .name = DRV_MODULE_NAME, + .match_table = rsw_of_match, + .probe = rsw_of_probe, + .remove = rsw_of_remove, +}; + +/* + * Module initialization function. + */ +static int rsw_init_module(void) +{ + drv_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, + rsw_driver_version); + + return of_register_platform_driver(&rsw_of_driver); +} + +/* + * Module deinitialization function. + */ +static void rsw_exit_module(void) +{ + of_unregister_platform_driver(&rsw_of_driver); +} + +module_init(rsw_init_module); +module_exit(rsw_exit_module); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_AUTHOR); +MODULE_LICENSE("GPL"); Index: starlet-ipc.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/powerpc/platforms/embedded6xx/starlet-ipc.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- starlet-ipc.c 18 Mar 2008 18:57:17 -0000 1.1 +++ starlet-ipc.c 26 Mar 2008 20:14:58 -0000 1.2 @@ -15,8 +15,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> -#include <linux/device.h> -#include <linux/platform_device.h> +#include <linux/of_platform.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/dmapool.h> @@ -27,12 +26,6 @@ #include <asm/starlet.h> -#ifdef CONFIG_PPC_MERGE -#include <platforms/embedded6xx/gamecube.h> -#else -#include <platforms/gamecube.h> -#endif - #define DRV_MODULE_NAME "starlet-ipc" #define DRV_DESCRIPTION "Nintendo Wii starlet IPC driver" @@ -40,25 +33,9 @@ static char starlet_ipc_driver_version[] = "0.1-isobel"; +#define drv_printk(level, format, arg...) \ + printk(level DRV_MODULE_NAME ": " format , ## arg) -#define PFX DRV_MODULE_NAME ": " -#define ipc_printk(level, format, arg...) \ - printk(level PFX format , ## arg) - -#ifdef SD_DEBUG -# define DBG(fmt, args...) \ - printk(KERN_ERR "%s: " fmt, __FUNCTION__ , ## args) -#else -# define DBG(fmt, args...) -#endif - - -#define STARLET_IPC_BASE 0x0d000000 -#define STARLET_IPC_SIZE 0x40 - -#define STARLET_IPC_IRQ 14 - -#define STARLET_IPC_DMA_ALIGN 0x1f /* 32 bytes */ /* * Hardware registers @@ -90,7 +67,7 @@ struct starlet_ipc_request { - /* begin starlet hardware request format */ + /* begin starlet firmware request format */ u32 cmd; s32 result; union { @@ -111,7 +88,7 @@ } ioctl; u32 argv[5]; }; - /* end starlet hardware request format */ + /* end starlet firmware request format */ struct starlet_ipc_device *ipc_dev; struct list_head node; @@ -191,7 +168,7 @@ */ static void starlet_ipc_debug_print_request(struct starlet_ipc_request *req) { - DBG("cmd=%x, result=%d, fd=%x, dma_addr=%p\n", + pr_debug("cmd=%x, result=%d, fd=%x, dma_addr=%p\n", req->cmd, req->result, req->fd, (void *)req->dma_addr); } @@ -232,7 +209,7 @@ void __iomem *io_base = ipc_dev->io_base; unsigned long flags; - DBG("start_request\n"); + pr_debug("start_request\n"); starlet_ipc_debug_print_request(req); spin_lock_irqsave(&ipc_dev->list_lock, flags); @@ -257,7 +234,7 @@ ipc_dev->nr_outstanding--; spin_unlock_irqrestore(&ipc_dev->list_lock, flags); - DBG("complete_request\n"); + pr_debug("complete_request\n"); starlet_ipc_debug_print_request(req); if (req->done) @@ -317,7 +294,7 @@ struct list_head *pending = &ipc_dev->pending_list; unsigned long flags; - DBG("tx buf empty interrupt!\n"); + pr_debug("tx buf empty interrupt!\n"); spin_lock_irqsave(&ipc_dev->list_lock, flags); if (!list_empty(pending)) { @@ -344,14 +321,14 @@ struct starlet_ipc_request *req; unsigned long req_bus_addr; - DBG("rx buf full interrupt!\n"); + pr_debug("rx buf full interrupt!\n"); req_bus_addr = starlet_ipc_recvfrom(io_base); req = starlet_ipc_find_request_by_bus_addr(ipc_dev, req_bus_addr); if (req) { starlet_ipc_complete_request(req); } else { - ipc_printk(KERN_WARNING, "unknown request, bus=%p\n", + drv_printk(KERN_WARNING, "unknown request, bus=%p\n", (void *)req_bus_addr); } return IRQ_HANDLED; @@ -445,7 +422,7 @@ struct starlet_ipc_device *starlet_ipc_get_device(void) { if (!starlet_ipc_device_instance) - ipc_printk(KERN_ERR, "uninitialized device instance!\n"); + drv_printk(KERN_ERR, "uninitialized device instance!\n"); return starlet_ipc_device_instance; } EXPORT_SYMBOL_GPL(starlet_ipc_get_device); @@ -484,14 +461,14 @@ strcpy(buf_aligned_pathname, pathname); vaddr = buf_aligned_pathname; } - dma_addr = dma_map_single(&ipc_dev->pdev.dev, + dma_addr = dma_map_single(ipc_dev->dev, vaddr, len, DMA_TO_DEVICE); req->cmd = STARLET_IOS_OPEN; req->open.pathname = dma_addr; /* bus address */ req->open.mode = flags; retval = starlet_ipc_call_and_wait(req); if (use_private_buf) { - dma_unmap_single(&ipc_dev->pdev.dev, dma_addr, + dma_unmap_single(ipc_dev->dev, dma_addr, len, DMA_TO_DEVICE); mutex_unlock(&buf_aligned_pathname_lock); } @@ -527,9 +504,9 @@ /* * */ -int starlet_ios_ioctl(int fd, int request, - dma_addr_t ibuf, size_t ilen, - dma_addr_t obuf, size_t olen) +int starlet_ios_ioctl_dma(int fd, int request, + dma_addr_t ibuf, size_t ilen, + dma_addr_t obuf, size_t olen) { struct starlet_ipc_device *ipc_dev = starlet_ipc_get_device(); struct starlet_ipc_request *req; @@ -552,76 +529,84 @@ } return retval; } -EXPORT_SYMBOL_GPL(starlet_ios_ioctl); - -/* - * Platform driver interface. - * - */ /* * */ -static int starlet_ipc_init_irq(struct starlet_ipc_device *ipc_dev) +int starlet_ios_ioctl(int fd, int request, + void *ibuf, size_t ilen, + void *obuf, size_t olen) { + struct starlet_ipc_device *ipc_dev = starlet_ipc_get_device(); + dma_addr_t ibuf_ba, obuf_ba; int retval; - int irq = platform_get_irq(&ipc_dev->pdev, 0); - retval = request_irq(irq, starlet_ipc_handler, 0, DRV_MODULE_NAME, - ipc_dev); - if (retval) { - ipc_printk(KERN_ERR, "request of irq%d failed\n", irq); - } else { - /* ack and enable MBOX? and REPLY interrupts */ - out_be32(ipc_dev->io_base + STARLET_IPC_CSR, - STARLET_IPC_CSR_TBEIMASK | STARLET_IPC_CSR_RBFIMASK | - STARLET_IPC_CSR_TBEI | STARLET_IPC_CSR_RBFI); - } + BUG_ON(!IS_ALIGNED((unsigned long)ibuf, STARLET_IPC_DMA_ALIGN+1)); + BUG_ON(!IS_ALIGNED((unsigned long)obuf, STARLET_IPC_DMA_ALIGN+1)); + + ibuf_ba = dma_map_single(ipc_dev->dev, ibuf, ilen, + DMA_TO_DEVICE); + obuf_ba = dma_map_single(ipc_dev->dev, obuf, olen, + DMA_FROM_DEVICE); + retval = starlet_ios_ioctl_dma(fd, request, ibuf_ba, ilen, + obuf_ba, olen); + dma_unmap_single(ipc_dev->dev, ibuf_ba, ilen, DMA_TO_DEVICE); + dma_unmap_single(ipc_dev->dev, obuf_ba, olen, DMA_FROM_DEVICE); + return retval; } +EXPORT_SYMBOL_GPL(starlet_ios_ioctl); /* * + * */ -static void starlet_ipc_exit_irq(struct starlet_ipc_device *ipc_dev) + +/* + * + */ +static void starlet_ios_fixups(void) { - int irq = platform_get_irq(&ipc_dev->pdev, 0); + int fd; + static u32 buf[32/sizeof(u32)] + __attribute__ ((aligned(STARLET_IPC_DMA_ALIGN + 1))); - starlet_ipc_quiesce(ipc_dev); - free_irq(irq, ipc_dev); + /* try to close any open file descriptors, just in case */ + for(fd = 0; fd < 15; fd++) + starlet_ios_close(fd); + + /* stop dvd motor */ + fd = starlet_ios_open("/dev/di", 0); + if (fd >= 0) { + buf[0] = 0xe3000000; /* stop motor command */ + buf[1] = 0; + buf[2] = 0; + starlet_ios_ioctl(fd, buf[0], + buf, sizeof(buf), + buf, sizeof(buf)); + starlet_ios_close(fd); + } } + /* * */ -static int starlet_ipc_probe(struct platform_device *pdev) +static int starlet_ipc_init(struct starlet_ipc_device *ipc_dev, + struct resource *mem, int irq) { - struct starlet_ipc_device *ipc_dev = to_ipc_dev(pdev); - struct resource *mem; size_t size; int retval; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - ipc_printk(KERN_ERR, "failed to determine io address range\n"); - return -ENODEV; - } - - memset(ipc_dev, 0, sizeof(*ipc_dev) - sizeof(ipc_dev->pdev)); - ipc_dev->io_base = ioremap(mem->start, mem->end - mem->start + 1); - if (!ipc_dev->io_base) { - ipc_printk(KERN_ERR, "ioremap from %p to %p failed\n", - (void *)mem->start, (void *)mem->end); - return -EINVAL; - } + ipc_dev->irq = irq; - size = max((size_t) 128, sizeof(struct starlet_ipc_request)); + size = max((size_t)64, sizeof(struct starlet_ipc_request)); ipc_dev->dma_pool = dma_pool_create(DRV_MODULE_NAME, - &ipc_dev->pdev.dev, + ipc_dev->dev, size, STARLET_IPC_DMA_ALIGN + 1, 0); if (!ipc_dev->dma_pool) { - ipc_printk(KERN_ERR, "dma_pool_create failed\n"); + drv_printk(KERN_ERR, "dma_pool_create failed\n"); iounmap(ipc_dev->io_base); return -ENOMEM; } @@ -631,58 +616,155 @@ starlet_ipc_device_instance = ipc_dev; - retval = starlet_ipc_init_irq(ipc_dev); + retval = request_irq(ipc_dev->irq, starlet_ipc_handler, 0, + DRV_MODULE_NAME, ipc_dev); if (retval) { + drv_printk(KERN_ERR, "request of IRQ %d failed\n", irq); starlet_ipc_device_instance = NULL; dma_pool_destroy(ipc_dev->dma_pool); iounmap(ipc_dev->io_base); return retval; } - return 0; + /* ack and enable MBOX? and REPLY interrupts */ + out_be32(ipc_dev->io_base + STARLET_IPC_CSR, + STARLET_IPC_CSR_TBEIMASK | STARLET_IPC_CSR_RBFIMASK | + STARLET_IPC_CSR_TBEI | STARLET_IPC_CSR_RBFI); + + starlet_ios_fixups(); + + return retval; } /* * */ -static int starlet_ipc_remove(struct platform_device *pdev) +static void starlet_ipc_exit(struct starlet_ipc_device *ipc_dev) { - struct starlet_ipc_device *ipc_dev = to_ipc_dev(pdev); + starlet_ipc_device_instance = NULL; + starlet_ipc_quiesce(ipc_dev); + free_irq(ipc_dev->irq, ipc_dev); + dma_pool_destroy(ipc_dev->dma_pool); iounmap(ipc_dev->io_base); - starlet_ipc_exit_irq(ipc_dev); + ipc_dev->io_base = NULL; +} - return 0; + +/* + * Device interface. + * + */ + +/* + * Common probe function for the given device. + */ +static int starlet_ipc_do_probe(struct device *dev, struct resource *mem, + int irq) +{ + struct starlet_ipc_device *ipc_dev; + int retval; + + ipc_dev = kzalloc(sizeof(*ipc_dev), GFP_KERNEL); + if (!ipc_dev) { + drv_printk(KERN_ERR, "failed to allocate ipc_dev\n"); + return -ENOMEM; + } + dev_set_drvdata(dev, ipc_dev); + ipc_dev->dev = dev; + + retval = starlet_ipc_init(ipc_dev, mem, irq); + if (retval) { + dev_set_drvdata(dev, NULL); + kfree(ipc_dev); + } + return retval; } -static struct platform_driver starlet_ipc_driver = { - .probe = starlet_ipc_probe, - .remove = starlet_ipc_remove, - .driver = { - .name = DRV_MODULE_NAME, - }, -}; +/* + * + */ +static int starlet_ipc_do_remove(struct device *dev) +{ + struct starlet_ipc_device *ipc_dev = dev_get_drvdata(dev); -static struct resource starlet_ipc_resources[] = { - [0] = { - .start = STARLET_IPC_BASE, - .end = STARLET_IPC_BASE + STARLET_IPC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = STARLET_IPC_IRQ, - .end = STARLET_IPC_IRQ, - .flags = IORESOURCE_IRQ, - }, + if (ipc_dev) { + starlet_ipc_exit(ipc_dev); + dev_set_drvdata(dev, NULL); + kfree(ipc_dev); + return 0; + } + return -ENODEV; +} + +/* + * + */ +static int starlet_ipc_do_shutdown(struct device *dev) +{ + struct starlet_ipc_device *ipc_dev = dev_get_drvdata(dev); + + if (ipc_dev) { + starlet_ipc_quiesce(ipc_dev); + return 0; + } + return -ENODEV; +} + +/* + * OF Platform device interface. + * + */ + +/* + * + */ +static int starlet_ipc_of_probe(struct of_device *odev, + const struct of_device_id *dev_id) +{ + struct resource res; + int retval; + + retval = of_address_to_resource(odev->node, 0, &res); + if (retval) { + drv_printk(KERN_ERR, "no io memory range found\n"); + return -ENODEV; + } + + return starlet_ipc_do_probe(&odev->dev, &res, + irq_of_parse_and_map(odev->node, 0)); +} + +/* + * + */ +static int starlet_ipc_of_remove(struct of_device *odev) +{ + return starlet_ipc_do_remove(&odev->dev); +} + +/* + * + */ +static int starlet_ipc_of_shutdown(struct of_device *odev) +{ + return starlet_ipc_do_shutdown(&odev->dev); +} + +static struct of_device_id starlet_ipc_of_match[] = { + { .compatible = "nintendo,starlet-ipc" }, + { }, }; -static struct starlet_ipc_device starlet_ipc_device = { - .pdev = { - .name = DRV_MODULE_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(starlet_ipc_resources), - .resource = starlet_ipc_resources, - }, +MODULE_DEVICE_TABLE(of, starlet_ipc_of_match); + +static struct of_platform_driver starlet_ipc_of_driver = { + .owner = THIS_MODULE, + .name = DRV_MODULE_NAME, + .match_table = starlet_ipc_of_match, + .probe = starlet_ipc_of_probe, + .remove = starlet_ipc_of_remove, + .shutdown = starlet_ipc_of_shutdown, }; /* @@ -693,30 +775,23 @@ /* * */ -static int __init starlet_ipc_init(void) +static int __init starlet_ipc_init_module(void) { - int retval; - - ipc_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, + drv_printk(KERN_INFO, "%s - version %s\n", DRV_DESCRIPTION, starlet_ipc_driver_version); - retval = platform_driver_register(&starlet_ipc_driver); - if (!retval) { - retval = platform_device_register(&starlet_ipc_device.pdev); - if (retval) - platform_driver_unregister(&starlet_ipc_driver); - } - return retval; + return of_register_platform_driver(&starlet_ipc_of_driver); } /* * */ -static void __exit starlet_ipc_exit(void) +static void __exit starlet_ipc_exit_module(void) { - platform_device_unregister(&starlet_ipc_device.pdev); - platform_driver_unregister(&starlet_ipc_driver); + of_unregister_platform_driver(&starlet_ipc_of_driver); } -module_init(starlet_ipc_init); -module_exit(starlet_ipc_exit); +module_init(starlet_ipc_init_module); +module_exit(starlet_ipc_exit_module); + + Index: starlet-stm.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/powerpc/platforms/embedded6xx/starlet-stm.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- starlet-stm.c 18 Mar 2008 18:57:17 -0000 1.1 +++ starlet-stm.c 26 Mar 2008 20:14:58 -0000 1.2 @@ -38,23 +38,14 @@ */ static void starlet_stm_common_restart(int request, u32 value) { - struct starlet_ipc_device *ipc_dev = starlet_ipc_get_device(); - dma_addr_t dma_addr; - u32 *vaddr = starlet_stm_buf; + u32 *buf = starlet_stm_buf; size_t len = sizeof(starlet_stm_buf); int fd; - if (!ipc_dev) - return; - fd = starlet_ios_open(dev_stm_immediate, 0); if (fd >= 0) { - *vaddr = value; - dma_addr = dma_map_single(&ipc_dev->pdev.dev, - vaddr, len, DMA_BIDIRECTIONAL); - starlet_ios_ioctl(fd, request, dma_addr, len, dma_addr, len); - dma_unmap_single(&ipc_dev->pdev.dev, - dma_addr, len, DMA_BIDIRECTIONAL); + *buf = value; + starlet_ios_ioctl(fd, request, buf, len, buf, len); starlet_ios_close(fd); } } |