123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /*
- * arch/sh/kernel/cpu/bus.c
- *
- * Virtual bus for SuperH.
- *
- * Copyright (C) 2004 Paul Mundt
- *
- * Shamelessly cloned from arch/arm/mach-omap/bus.c, which was written
- * by:
- *
- * Copyright (C) 2003 - 2004 Nokia Corporation
- * Written by Tony Lindgren <tony@atomide.com>
- * Portions of code based on sa1111.c.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
- #include <linux/kernel.h>
- #include <linux/device.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <asm/bus-sh.h>
- static int sh_bus_match(struct device *dev, struct device_driver *drv)
- {
- struct sh_driver *shdrv = to_sh_driver(drv);
- struct sh_dev *shdev = to_sh_dev(dev);
- return shdev->dev_id == shdrv->dev_id;
- }
- static int sh_bus_suspend(struct device *dev, pm_message_t state)
- {
- struct sh_dev *shdev = to_sh_dev(dev);
- struct sh_driver *shdrv = to_sh_driver(dev->driver);
- if (shdrv && shdrv->suspend)
- return shdrv->suspend(shdev, state);
- return 0;
- }
- static int sh_bus_resume(struct device *dev)
- {
- struct sh_dev *shdev = to_sh_dev(dev);
- struct sh_driver *shdrv = to_sh_driver(dev->driver);
- if (shdrv && shdrv->resume)
- return shdrv->resume(shdev);
- return 0;
- }
- static struct device sh_bus_devices[SH_NR_BUSES] = {
- {
- .bus_id = SH_BUS_NAME_VIRT,
- },
- };
- struct bus_type sh_bus_types[SH_NR_BUSES] = {
- {
- .name = SH_BUS_NAME_VIRT,
- .match = sh_bus_match,
- .suspend = sh_bus_suspend,
- .resume = sh_bus_resume,
- },
- };
- static int sh_device_probe(struct device *dev)
- {
- struct sh_dev *shdev = to_sh_dev(dev);
- struct sh_driver *shdrv = to_sh_driver(dev->driver);
- if (shdrv && shdrv->probe)
- return shdrv->probe(shdev);
- return -ENODEV;
- }
- static int sh_device_remove(struct device *dev)
- {
- struct sh_dev *shdev = to_sh_dev(dev);
- struct sh_driver *shdrv = to_sh_driver(dev->driver);
- if (shdrv && shdrv->remove)
- return shdrv->remove(shdev);
- return 0;
- }
- int sh_device_register(struct sh_dev *dev)
- {
- if (!dev)
- return -EINVAL;
- if (dev->bus_id < 0 || dev->bus_id >= SH_NR_BUSES) {
- printk(KERN_ERR "%s: bus_id invalid: %s bus: %d\n",
- __FUNCTION__, dev->name, dev->bus_id);
- return -EINVAL;
- }
- dev->dev.parent = &sh_bus_devices[dev->bus_id];
- dev->dev.bus = &sh_bus_types[dev->bus_id];
- /* This is needed for USB OHCI to work */
- if (dev->dma_mask)
- dev->dev.dma_mask = dev->dma_mask;
- snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
- dev->name, dev->dev_id);
- printk(KERN_INFO "Registering SH device '%s'. Parent at %s\n",
- dev->dev.bus_id, dev->dev.parent->bus_id);
- return device_register(&dev->dev);
- }
- void sh_device_unregister(struct sh_dev *dev)
- {
- device_unregister(&dev->dev);
- }
- int sh_driver_register(struct sh_driver *drv)
- {
- if (!drv)
- return -EINVAL;
- if (drv->bus_id < 0 || drv->bus_id >= SH_NR_BUSES) {
- printk(KERN_ERR "%s: bus_id invalid: bus: %d device %d\n",
- __FUNCTION__, drv->bus_id, drv->dev_id);
- return -EINVAL;
- }
- drv->drv.probe = sh_device_probe;
- drv->drv.remove = sh_device_remove;
- drv->drv.bus = &sh_bus_types[drv->bus_id];
- return driver_register(&drv->drv);
- }
- void sh_driver_unregister(struct sh_driver *drv)
- {
- driver_unregister(&drv->drv);
- }
- static int __init sh_bus_init(void)
- {
- int i, ret = 0;
- for (i = 0; i < SH_NR_BUSES; i++) {
- ret = device_register(&sh_bus_devices[i]);
- if (ret != 0) {
- printk(KERN_ERR "Unable to register bus device %s\n",
- sh_bus_devices[i].bus_id);
- continue;
- }
- ret = bus_register(&sh_bus_types[i]);
- if (ret != 0) {
- printk(KERN_ERR "Unable to register bus %s\n",
- sh_bus_types[i].name);
- device_unregister(&sh_bus_devices[i]);
- }
- }
- printk(KERN_INFO "SH Virtual Bus initialized\n");
- return ret;
- }
- static void __exit sh_bus_exit(void)
- {
- int i;
- for (i = 0; i < SH_NR_BUSES; i++) {
- bus_unregister(&sh_bus_types[i]);
- device_unregister(&sh_bus_devices[i]);
- }
- }
- module_init(sh_bus_init);
- module_exit(sh_bus_exit);
- MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
- MODULE_DESCRIPTION("SH Virtual Bus");
- MODULE_LICENSE("GPL");
- EXPORT_SYMBOL(sh_bus_types);
- EXPORT_SYMBOL(sh_device_register);
- EXPORT_SYMBOL(sh_device_unregister);
- EXPORT_SYMBOL(sh_driver_register);
- EXPORT_SYMBOL(sh_driver_unregister);
|