1 /* 2 * Simple Power-Managed Bus Driver 3 * 4 * Copyright (C) 2014-2015 Glider bvba 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 11 #include <linux/module.h> 12 #include <linux/of_platform.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_runtime.h> 15 16 static int simple_pm_bus_probe(struct platform_device *pdev) 17 { 18 const struct device *dev = &pdev->dev; 19 const struct of_dev_auxdata *lookup = dev_get_platdata(dev); 20 struct device_node *np = dev->of_node; 21 const struct of_device_id *match; 22 23 /* 24 * Allow user to use driver_override to bind this driver to a 25 * transparent bus device which has a different compatible string 26 * that's not listed in simple_pm_bus_of_match. We don't want to do any 27 * of the simple-pm-bus tasks for these devices, so return early. 28 */ 29 if (pdev->driver_override) 30 return 0; 31 32 match = of_match_device(dev->driver->of_match_table, dev); 33 /* 34 * These are transparent bus devices (not simple-pm-bus matches) that 35 * have their child nodes populated automatically. So, don't need to 36 * do anything more. We only match with the device if this driver is 37 * the most specific match because we don't want to incorrectly bind to 38 * a device that has a more specific driver. 39 */ 40 if (match && match->data) { 41 if (of_property_match_string(np, "compatible", match->compatible) == 0) 42 return 0; 43 else 44 return -ENODEV; 45 } 46 47 dev_dbg(&pdev->dev, "%s\n", __func__); 48 49 pm_runtime_enable(&pdev->dev); 50 51 if (np) 52 of_platform_populate(np, NULL, lookup, &pdev->dev); 53 54 return 0; 55 } 56 57 static int simple_pm_bus_remove(struct platform_device *pdev) 58 { 59 const void *data = of_device_get_match_data(&pdev->dev); 60 61 if (pdev->driver_override || data) 62 return 0; 63 64 dev_dbg(&pdev->dev, "%s\n", __func__); 65 66 pm_runtime_disable(&pdev->dev); 67 return 0; 68 } 69 70 #define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */ 71 72 static const struct of_device_id simple_pm_bus_of_match[] = { 73 { .compatible = "simple-pm-bus", }, 74 { .compatible = "simple-bus", .data = ONLY_BUS }, 75 { .compatible = "simple-mfd", .data = ONLY_BUS }, 76 { .compatible = "isa", .data = ONLY_BUS }, 77 { .compatible = "arm,amba-bus", .data = ONLY_BUS }, 78 { /* sentinel */ } 79 }; 80 MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match); 81 82 static struct platform_driver simple_pm_bus_driver = { 83 .probe = simple_pm_bus_probe, 84 .remove = simple_pm_bus_remove, 85 .driver = { 86 .name = "simple-pm-bus", 87 .of_match_table = simple_pm_bus_of_match, 88 }, 89 }; 90 91 module_platform_driver(simple_pm_bus_driver); 92 93 MODULE_DESCRIPTION("Simple Power-Managed Bus Driver"); 94 MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>"); 95 MODULE_LICENSE("GPL v2"); 96