OSDN Git Service

bus: vexpress-config: simplify config bus probing
authorRob Herring <robh@kernel.org>
Wed, 29 Apr 2020 20:58:22 +0000 (15:58 -0500)
committerRob Herring <robh@kernel.org>
Wed, 13 May 2020 17:42:46 +0000 (12:42 -0500)
The vexpress-config initialization is dependent on the vexpress-syscfg
driver probing. As vexpress-config was not a driver, deferred probe
could not be used and instead initcall ordering was relied upon. This is
fragile and doesn't work for modules.

Let's move the config bus init into the vexpress-syscfg probe. This
eliminates the initcall ordering requirement and the need to create a
struct device and the "vexpress-config" class.

Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Acked-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Rob Herring <robh@kernel.org>
drivers/bus/vexpress-config.c

index 43f5bea..43deb4d 100644 (file)
@@ -56,7 +56,6 @@ struct vexpress_config_bridge {
 
 
 static DEFINE_MUTEX(vexpress_config_mutex);
-static struct class *vexpress_config_class;
 static u32 vexpress_config_site_master = VEXPRESS_SITE_MASTER;
 
 
@@ -121,9 +120,6 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev)
        struct regmap *regmap;
        struct regmap **res;
 
-       if (WARN_ON(dev->parent->class != vexpress_config_class))
-               return ERR_PTR(-ENODEV);
-
        bridge = dev_get_drvdata(dev->parent);
        if (WARN_ON(!bridge))
                return ERR_PTR(-EINVAL);
@@ -146,94 +142,6 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(devm_regmap_init_vexpress_config);
 
-static struct device *vexpress_config_bridge_register(struct device *parent,
-               struct vexpress_config_bridge_ops *ops, void *context)
-{
-       struct device *dev;
-       struct vexpress_config_bridge *bridge;
-
-       if (!vexpress_config_class) {
-               vexpress_config_class = class_create(THIS_MODULE,
-                               "vexpress-config");
-               if (IS_ERR(vexpress_config_class))
-                       return (void *)vexpress_config_class;
-       }
-
-       dev = device_create(vexpress_config_class, parent, 0,
-                       NULL, "%s.bridge", dev_name(parent));
-
-       if (IS_ERR(dev))
-               return dev;
-
-       bridge = devm_kmalloc(dev, sizeof(*bridge), GFP_KERNEL);
-       if (!bridge) {
-               put_device(dev);
-               device_unregister(dev);
-               return ERR_PTR(-ENOMEM);
-       }
-       bridge->ops = ops;
-       bridge->context = context;
-
-       dev_set_drvdata(dev, bridge);
-
-       dev_dbg(parent, "Registered bridge '%s', parent node %p\n",
-                       dev_name(dev), parent->of_node);
-
-       return dev;
-}
-
-
-static int vexpress_config_node_match(struct device *dev, const void *data)
-{
-       const struct device_node *node = data;
-
-       dev_dbg(dev, "Parent node %p, looking for %p\n",
-                       dev->parent->of_node, node);
-
-       return dev->parent->of_node == node;
-}
-
-static int vexpress_config_populate(struct device_node *node)
-{
-       struct device_node *bridge;
-       struct device *parent;
-       int ret;
-
-       bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
-       if (!bridge)
-               return -EINVAL;
-
-       parent = class_find_device(vexpress_config_class, NULL, bridge,
-                       vexpress_config_node_match);
-       of_node_put(bridge);
-       if (WARN_ON(!parent))
-               return -ENODEV;
-
-       ret = of_platform_populate(node, NULL, NULL, parent);
-
-       put_device(parent);
-
-       return ret;
-}
-
-static int __init vexpress_config_init(void)
-{
-       int err = 0;
-       struct device_node *node;
-
-       /* Need the config devices early, before the "normal" devices... */
-       for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
-               err = vexpress_config_populate(node);
-               if (err) {
-                       of_node_put(node);
-                       break;
-               }
-       }
-
-       return err;
-}
-postcore_initcall(vexpress_config_init);
-
 static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func,
                int index, bool write, u32 *data)
 {
@@ -430,7 +338,8 @@ static int vexpress_syscfg_probe(struct platform_device *pdev)
 {
        struct vexpress_syscfg *syscfg;
        struct resource *res;
-       struct device *bridge;
+       struct vexpress_config_bridge *bridge;
+       struct device_node *node;
 
        syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL);
        if (!syscfg)
@@ -443,11 +352,26 @@ static int vexpress_syscfg_probe(struct platform_device *pdev)
        if (IS_ERR(syscfg->base))
                return PTR_ERR(syscfg->base);
 
-       /* Must use dev.parent (MFD), as that's where DT phandle points at... */
-       bridge = vexpress_config_bridge_register(pdev->dev.parent,
-                       &vexpress_syscfg_bridge_ops, syscfg);
+       bridge = devm_kmalloc(&pdev->dev, sizeof(*bridge), GFP_KERNEL);
+       if (!bridge)
+               return -ENOMEM;
+
+       bridge->ops = &vexpress_syscfg_bridge_ops;
+       bridge->context = syscfg;
+
+       dev_set_drvdata(&pdev->dev, bridge);
 
-       return PTR_ERR_OR_ZERO(bridge);
+       for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
+               struct device_node *bridge_np;
+
+               bridge_np = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
+               if (bridge_np != pdev->dev.parent->of_node)
+                       continue;
+
+               of_platform_populate(node, NULL, NULL, &pdev->dev);
+       }
+
+       return 0;
 }
 
 static const struct platform_device_id vexpress_syscfg_id_table[] = {