/* * Copyright (c) 2011 Synaptics Incorporated * Copyright (c) 2011 Unixphere * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include static struct rmi_function_list { struct list_head list; struct rmi_function_handler *fh; } rmi_supported_functions; static int rmi_bus_match(struct device *dev, struct device_driver *driver) { struct rmi_driver *rmi_driver; struct rmi_device *rmi_dev; struct rmi_device_platform_data *pdata; pr_info("in function ____%s____ \n", __func__); rmi_driver = to_rmi_driver(driver); rmi_dev = to_rmi_device(dev); pdata = to_rmi_platform_data(rmi_dev); pr_info(" rmi_driver->driver.name = %s\n", rmi_driver->driver.name); pr_info(" device:rmi_device = 0x%x \n", rmi_dev); pr_info(" device:rmi_device:rmi_device_platform_data:driver_name = %s \n", pdata->driver_name); pr_info(" rmi_device:driver = 0x%x \n", rmi_dev->driver); if (!strcmp(pdata->driver_name, rmi_driver->driver.name)) { rmi_dev->driver = rmi_driver; pr_info(" names match, so now rmi_device:driver = 0x%x \n",rmi_dev->driver); return 1; } pr_info(" names DO NOT match, so return nothing \n"); return 0; } #ifdef CONFIG_PM static int rmi_bus_suspend(struct device *dev) { #ifdef GENERIC_SUBSYS_PM_OPS const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; if (pm && pm->suspend) return pm->suspend(dev); #endif return 0; } static int rmi_bus_resume(struct device *dev) { #ifdef GENERIC_SUBSYS_PM_OPS const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; pr_info("in function ____%s____ \n", __func__); if (pm && pm->resume) return pm->resume(dev); #endif return 0; } #endif static int rmi_bus_probe(struct device *dev) { struct rmi_driver *driver; struct rmi_device *rmi_dev = to_rmi_device(dev); pr_info("in function ____%s____ \n", __func__); driver = rmi_dev->driver; if (driver && driver->probe) return driver->probe(rmi_dev); return 0; } static int rmi_bus_remove(struct device *dev) { struct rmi_driver *driver; struct rmi_device *rmi_dev = to_rmi_device(dev); pr_info("in function ____%s____ \n", __func__); driver = rmi_dev->driver; if (driver && driver->remove) return driver->remove(rmi_dev); return 0; } static void rmi_bus_shutdown(struct device *dev) { struct rmi_driver *driver; struct rmi_device *rmi_dev = to_rmi_device(dev); driver = rmi_dev->driver; if (driver && driver->shutdown) driver->shutdown(rmi_dev); } static SIMPLE_DEV_PM_OPS(rmi_bus_pm_ops, rmi_bus_suspend, rmi_bus_resume); struct bus_type rmi_bus_type = { .name = "rmi", .match = rmi_bus_match, .probe = rmi_bus_probe, .remove = rmi_bus_remove, .shutdown = rmi_bus_shutdown, .pm = &rmi_bus_pm_ops }; int rmi_register_phys_device(struct rmi_phys_device *phys) { static int phys_device_num; struct rmi_device_platform_data *pdata = phys->dev->platform_data; struct rmi_device *rmi_dev; pr_info("in function ____%s____ \n", __func__); if (!pdata) { dev_err(phys->dev, "no platform data!\n"); return -EINVAL; } rmi_dev = kzalloc(sizeof(struct rmi_device), GFP_KERNEL); if (!rmi_dev) return -ENOMEM; rmi_dev->phys = phys; rmi_dev->dev.bus = &rmi_bus_type; dev_set_name(&rmi_dev->dev, "sensor%02d", phys_device_num++); phys->rmi_dev = rmi_dev; pr_info(" registering physical device:\n"); pr_info(" dev.init_name = \n", rmi_dev->dev.init_name); pr_info(" dev.bus->name = \n", rmi_dev->dev.bus->name); return device_register(&rmi_dev->dev); } EXPORT_SYMBOL(rmi_register_phys_device); void rmi_unregister_phys_device(struct rmi_phys_device *phys) { struct rmi_device *rmi_dev = phys->rmi_dev; pr_info("in function ____%s____ \n", __func__); device_unregister(&rmi_dev->dev); kfree(rmi_dev); } EXPORT_SYMBOL(rmi_unregister_phys_device); int rmi_register_driver(struct rmi_driver *driver) { pr_info("in function ____%s____ \n", __func__); driver->driver.bus = &rmi_bus_type; return driver_register(&driver->driver); } EXPORT_SYMBOL(rmi_register_driver); static int __rmi_driver_remove(struct device *dev, void *data) { struct rmi_driver *driver = data; struct rmi_device *rmi_dev = to_rmi_device(dev); if (rmi_dev->driver == driver) rmi_dev->driver = NULL; return 0; } void rmi_unregister_driver(struct rmi_driver *driver) { bus_for_each_dev(&rmi_bus_type, NULL, driver, __rmi_driver_remove); driver_unregister(&driver->driver); } EXPORT_SYMBOL(rmi_unregister_driver); static int __rmi_bus_fh_add(struct device *dev, void *data) { struct rmi_driver *driver; struct rmi_device *rmi_dev = to_rmi_device(dev); pr_info("in function ____%s____ \n", __func__); driver = rmi_dev->driver; if (driver && driver->fh_add) driver->fh_add(rmi_dev, data); return 0; } int rmi_register_function_driver(struct rmi_function_handler *fh) { struct rmi_function_list *entry; struct rmi_function_handler *fh_dup; fh_dup = rmi_get_function_handler(fh->func); if (fh_dup) { pr_err("%s: function f%.2x already registered!\n", __func__, fh->func); return -EINVAL; } entry = kzalloc(sizeof(struct rmi_function_list), GFP_KERNEL); if (!entry) return -ENOMEM; entry->fh = fh; list_add_tail(&entry->list, &rmi_supported_functions.list); /* notify devices of the new function handler */ bus_for_each_dev(&rmi_bus_type, NULL, fh, __rmi_bus_fh_add); return 0; } EXPORT_SYMBOL(rmi_register_function_driver); static int __rmi_bus_fh_remove(struct device *dev, void *data) { struct rmi_driver *driver; struct rmi_device *rmi_dev = to_rmi_device(dev); pr_info("in function ____%s____ \n", __func__); driver = rmi_dev->driver; if (driver && driver->fh_remove) driver->fh_remove(rmi_dev, data); return 0; } void rmi_unregister_function_driver(struct rmi_function_handler *fh) { struct rmi_function_list *entry, *n; pr_info("in function ____%s____ \n", __func__); /* notify devices of the removal of the function handler */ bus_for_each_dev(&rmi_bus_type, NULL, fh, __rmi_bus_fh_remove); list_for_each_entry_safe(entry, n, &rmi_supported_functions.list, list) if (entry->fh->func == fh->func) { list_del(&entry->list); kfree(entry); } } EXPORT_SYMBOL(rmi_unregister_function_driver); struct rmi_function_handler *rmi_get_function_handler(int id) { struct rmi_function_list *entry; pr_info("in function ____%s____ \n", __func__); list_for_each_entry(entry, &rmi_supported_functions.list, list) if (entry->fh->func == id) return entry->fh; return NULL; } EXPORT_SYMBOL(rmi_get_function_handler); static int __init rmi_bus_init(void) { int error; pr_info("in function ____%s____ \n", __func__); INIT_LIST_HEAD(&rmi_supported_functions.list); error = bus_register(&rmi_bus_type); if (error < 0) { pr_err("%s: error registering the RMI bus: %d\n", __func__, error); return error; } pr_info("%s: successfully registered RMI bus.\n", __func__); return 0; } static void __exit rmi_bus_exit(void) { struct rmi_function_list *entry, *n; pr_info("in function ____%s____ \n", __func__); list_for_each_entry_safe(entry, n, &rmi_supported_functions.list, list) { list_del(&entry->list); kfree(entry); } bus_unregister(&rmi_bus_type); } module_init(rmi_bus_init); module_exit(rmi_bus_exit); MODULE_AUTHOR("Eric Andersson "); MODULE_DESCRIPTION("RMI bus"); MODULE_LICENSE("GPL");