root/drivers/bus/vexpress-config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vexpress_config_set_master
  2. vexpress_config_get_master
  3. vexpress_config_lock
  4. vexpress_config_unlock
  5. vexpress_config_find_prop
  6. vexpress_config_get_topo
  7. vexpress_config_devres_release
  8. devm_regmap_init_vexpress_config
  9. vexpress_config_bridge_register
  10. vexpress_config_node_match
  11. vexpress_config_populate
  12. vexpress_config_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  * Copyright (C) 2014 ARM Limited
   5  */
   6 
   7 #include <linux/err.h>
   8 #include <linux/init.h>
   9 #include <linux/of.h>
  10 #include <linux/of_device.h>
  11 #include <linux/vexpress.h>
  12 
  13 
  14 struct vexpress_config_bridge {
  15         struct vexpress_config_bridge_ops *ops;
  16         void *context;
  17 };
  18 
  19 
  20 static DEFINE_MUTEX(vexpress_config_mutex);
  21 static struct class *vexpress_config_class;
  22 static u32 vexpress_config_site_master = VEXPRESS_SITE_MASTER;
  23 
  24 
  25 void vexpress_config_set_master(u32 site)
  26 {
  27         vexpress_config_site_master = site;
  28 }
  29 
  30 u32 vexpress_config_get_master(void)
  31 {
  32         return vexpress_config_site_master;
  33 }
  34 
  35 void vexpress_config_lock(void *arg)
  36 {
  37         mutex_lock(&vexpress_config_mutex);
  38 }
  39 
  40 void vexpress_config_unlock(void *arg)
  41 {
  42         mutex_unlock(&vexpress_config_mutex);
  43 }
  44 
  45 
  46 static void vexpress_config_find_prop(struct device_node *node,
  47                 const char *name, u32 *val)
  48 {
  49         /* Default value */
  50         *val = 0;
  51 
  52         of_node_get(node);
  53         while (node) {
  54                 if (of_property_read_u32(node, name, val) == 0) {
  55                         of_node_put(node);
  56                         return;
  57                 }
  58                 node = of_get_next_parent(node);
  59         }
  60 }
  61 
  62 int vexpress_config_get_topo(struct device_node *node, u32 *site,
  63                 u32 *position, u32 *dcc)
  64 {
  65         vexpress_config_find_prop(node, "arm,vexpress,site", site);
  66         if (*site == VEXPRESS_SITE_MASTER)
  67                 *site = vexpress_config_site_master;
  68         if (WARN_ON(vexpress_config_site_master == VEXPRESS_SITE_MASTER))
  69                 return -EINVAL;
  70         vexpress_config_find_prop(node, "arm,vexpress,position", position);
  71         vexpress_config_find_prop(node, "arm,vexpress,dcc", dcc);
  72 
  73         return 0;
  74 }
  75 
  76 
  77 static void vexpress_config_devres_release(struct device *dev, void *res)
  78 {
  79         struct vexpress_config_bridge *bridge = dev_get_drvdata(dev->parent);
  80         struct regmap *regmap = res;
  81 
  82         bridge->ops->regmap_exit(regmap, bridge->context);
  83 }
  84 
  85 struct regmap *devm_regmap_init_vexpress_config(struct device *dev)
  86 {
  87         struct vexpress_config_bridge *bridge;
  88         struct regmap *regmap;
  89         struct regmap **res;
  90 
  91         if (WARN_ON(dev->parent->class != vexpress_config_class))
  92                 return ERR_PTR(-ENODEV);
  93 
  94         bridge = dev_get_drvdata(dev->parent);
  95         if (WARN_ON(!bridge))
  96                 return ERR_PTR(-EINVAL);
  97 
  98         res = devres_alloc(vexpress_config_devres_release, sizeof(*res),
  99                         GFP_KERNEL);
 100         if (!res)
 101                 return ERR_PTR(-ENOMEM);
 102 
 103         regmap = (bridge->ops->regmap_init)(dev, bridge->context);
 104         if (IS_ERR(regmap)) {
 105                 devres_free(res);
 106                 return regmap;
 107         }
 108 
 109         *res = regmap;
 110         devres_add(dev, res);
 111 
 112         return regmap;
 113 }
 114 EXPORT_SYMBOL_GPL(devm_regmap_init_vexpress_config);
 115 
 116 struct device *vexpress_config_bridge_register(struct device *parent,
 117                 struct vexpress_config_bridge_ops *ops, void *context)
 118 {
 119         struct device *dev;
 120         struct vexpress_config_bridge *bridge;
 121 
 122         if (!vexpress_config_class) {
 123                 vexpress_config_class = class_create(THIS_MODULE,
 124                                 "vexpress-config");
 125                 if (IS_ERR(vexpress_config_class))
 126                         return (void *)vexpress_config_class;
 127         }
 128 
 129         dev = device_create(vexpress_config_class, parent, 0,
 130                         NULL, "%s.bridge", dev_name(parent));
 131 
 132         if (IS_ERR(dev))
 133                 return dev;
 134 
 135         bridge = devm_kmalloc(dev, sizeof(*bridge), GFP_KERNEL);
 136         if (!bridge) {
 137                 put_device(dev);
 138                 device_unregister(dev);
 139                 return ERR_PTR(-ENOMEM);
 140         }
 141         bridge->ops = ops;
 142         bridge->context = context;
 143 
 144         dev_set_drvdata(dev, bridge);
 145 
 146         dev_dbg(parent, "Registered bridge '%s', parent node %p\n",
 147                         dev_name(dev), parent->of_node);
 148 
 149         return dev;
 150 }
 151 
 152 
 153 static int vexpress_config_node_match(struct device *dev, const void *data)
 154 {
 155         const struct device_node *node = data;
 156 
 157         dev_dbg(dev, "Parent node %p, looking for %p\n",
 158                         dev->parent->of_node, node);
 159 
 160         return dev->parent->of_node == node;
 161 }
 162 
 163 static int vexpress_config_populate(struct device_node *node)
 164 {
 165         struct device_node *bridge;
 166         struct device *parent;
 167         int ret;
 168 
 169         bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
 170         if (!bridge)
 171                 return -EINVAL;
 172 
 173         parent = class_find_device(vexpress_config_class, NULL, bridge,
 174                         vexpress_config_node_match);
 175         of_node_put(bridge);
 176         if (WARN_ON(!parent))
 177                 return -ENODEV;
 178 
 179         ret = of_platform_populate(node, NULL, NULL, parent);
 180 
 181         put_device(parent);
 182 
 183         return ret;
 184 }
 185 
 186 static int __init vexpress_config_init(void)
 187 {
 188         int err = 0;
 189         struct device_node *node;
 190 
 191         /* Need the config devices early, before the "normal" devices... */
 192         for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
 193                 err = vexpress_config_populate(node);
 194                 if (err) {
 195                         of_node_put(node);
 196                         break;
 197                 }
 198         }
 199 
 200         return err;
 201 }
 202 postcore_initcall(vexpress_config_init);
 203 

/* [<][>][^][v][top][bottom][index][help] */