Linux Audio

Check our new training course

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