1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2014 ARM Limited
8 #include <linux/init.h>
10 #include <linux/of_device.h>
11 #include <linux/vexpress.h>
14 struct vexpress_config_bridge
{
15 struct vexpress_config_bridge_ops
*ops
;
20 static DEFINE_MUTEX(vexpress_config_mutex
);
21 static struct class *vexpress_config_class
;
22 static u32 vexpress_config_site_master
= VEXPRESS_SITE_MASTER
;
25 void vexpress_config_set_master(u32 site
)
27 vexpress_config_site_master
= site
;
30 u32
vexpress_config_get_master(void)
32 return vexpress_config_site_master
;
35 void vexpress_config_lock(void *arg
)
37 mutex_lock(&vexpress_config_mutex
);
40 void vexpress_config_unlock(void *arg
)
42 mutex_unlock(&vexpress_config_mutex
);
46 static void vexpress_config_find_prop(struct device_node
*node
,
47 const char *name
, u32
*val
)
54 if (of_property_read_u32(node
, name
, val
) == 0) {
58 node
= of_get_next_parent(node
);
62 int vexpress_config_get_topo(struct device_node
*node
, u32
*site
,
63 u32
*position
, u32
*dcc
)
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
))
70 vexpress_config_find_prop(node
, "arm,vexpress,position", position
);
71 vexpress_config_find_prop(node
, "arm,vexpress,dcc", dcc
);
77 static void vexpress_config_devres_release(struct device
*dev
, void *res
)
79 struct vexpress_config_bridge
*bridge
= dev_get_drvdata(dev
->parent
);
80 struct regmap
*regmap
= res
;
82 bridge
->ops
->regmap_exit(regmap
, bridge
->context
);
85 struct regmap
*devm_regmap_init_vexpress_config(struct device
*dev
)
87 struct vexpress_config_bridge
*bridge
;
88 struct regmap
*regmap
;
91 if (WARN_ON(dev
->parent
->class != vexpress_config_class
))
92 return ERR_PTR(-ENODEV
);
94 bridge
= dev_get_drvdata(dev
->parent
);
96 return ERR_PTR(-EINVAL
);
98 res
= devres_alloc(vexpress_config_devres_release
, sizeof(*res
),
101 return ERR_PTR(-ENOMEM
);
103 regmap
= (bridge
->ops
->regmap_init
)(dev
, bridge
->context
);
104 if (IS_ERR(regmap
)) {
110 devres_add(dev
, res
);
114 EXPORT_SYMBOL_GPL(devm_regmap_init_vexpress_config
);
116 struct device
*vexpress_config_bridge_register(struct device
*parent
,
117 struct vexpress_config_bridge_ops
*ops
, void *context
)
120 struct vexpress_config_bridge
*bridge
;
122 if (!vexpress_config_class
) {
123 vexpress_config_class
= class_create(THIS_MODULE
,
125 if (IS_ERR(vexpress_config_class
))
126 return (void *)vexpress_config_class
;
129 dev
= device_create(vexpress_config_class
, parent
, 0,
130 NULL
, "%s.bridge", dev_name(parent
));
135 bridge
= devm_kmalloc(dev
, sizeof(*bridge
), GFP_KERNEL
);
138 device_unregister(dev
);
139 return ERR_PTR(-ENOMEM
);
142 bridge
->context
= context
;
144 dev_set_drvdata(dev
, bridge
);
146 dev_dbg(parent
, "Registered bridge '%s', parent node %p\n",
147 dev_name(dev
), parent
->of_node
);
153 static int vexpress_config_node_match(struct device
*dev
, const void *data
)
155 const struct device_node
*node
= data
;
157 dev_dbg(dev
, "Parent node %p, looking for %p\n",
158 dev
->parent
->of_node
, node
);
160 return dev
->parent
->of_node
== node
;
163 static int vexpress_config_populate(struct device_node
*node
)
165 struct device_node
*bridge
;
166 struct device
*parent
;
169 bridge
= of_parse_phandle(node
, "arm,vexpress,config-bridge", 0);
173 parent
= class_find_device(vexpress_config_class
, NULL
, bridge
,
174 vexpress_config_node_match
);
176 if (WARN_ON(!parent
))
179 ret
= of_platform_populate(node
, NULL
, NULL
, parent
);
186 static int __init
vexpress_config_init(void)
189 struct device_node
*node
;
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
);
202 postcore_initcall(vexpress_config_init
);