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.
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.
11 * Copyright (C) 2012 ARM Limited
14 #define pr_fmt(fmt) "vexpress-config: " fmt
16 #include <linux/bitops.h>
17 #include <linux/completion.h>
18 #include <linux/export.h>
19 #include <linux/list.h>
21 #include <linux/of_device.h>
22 #include <linux/slab.h>
23 #include <linux/string.h>
24 #include <linux/vexpress.h>
27 #define VEXPRESS_CONFIG_MAX_BRIDGES 2
29 static struct vexpress_config_bridge {
30 struct device_node *node;
31 struct vexpress_config_bridge_info *info;
32 struct list_head transactions;
33 spinlock_t transactions_lock;
34 } vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];
36 static DECLARE_BITMAP(vexpress_config_bridges_map,
37 ARRAY_SIZE(vexpress_config_bridges));
38 static DEFINE_MUTEX(vexpress_config_bridges_mutex);
40 struct vexpress_config_bridge *vexpress_config_bridge_register(
41 struct device_node *node,
42 struct vexpress_config_bridge_info *info)
44 struct vexpress_config_bridge *bridge;
47 pr_debug("Registering bridge '%s'\n", info->name);
49 mutex_lock(&vexpress_config_bridges_mutex);
50 i = find_first_zero_bit(vexpress_config_bridges_map,
51 ARRAY_SIZE(vexpress_config_bridges));
52 if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
53 pr_err("Can't register more bridges!\n");
54 mutex_unlock(&vexpress_config_bridges_mutex);
57 __set_bit(i, vexpress_config_bridges_map);
58 bridge = &vexpress_config_bridges[i];
62 INIT_LIST_HEAD(&bridge->transactions);
63 spin_lock_init(&bridge->transactions_lock);
65 mutex_unlock(&vexpress_config_bridges_mutex);
69 EXPORT_SYMBOL(vexpress_config_bridge_register);
71 void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
73 struct vexpress_config_bridge __bridge = *bridge;
76 mutex_lock(&vexpress_config_bridges_mutex);
77 for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
78 if (&vexpress_config_bridges[i] == bridge)
79 __clear_bit(i, vexpress_config_bridges_map);
80 mutex_unlock(&vexpress_config_bridges_mutex);
82 WARN_ON(!list_empty(&__bridge.transactions));
83 while (!list_empty(&__bridge.transactions))
86 EXPORT_SYMBOL(vexpress_config_bridge_unregister);
89 struct vexpress_config_func {
90 struct vexpress_config_bridge *bridge;
94 struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
95 struct device_node *node)
97 struct device_node *bridge_node;
98 struct vexpress_config_func *func;
101 if (WARN_ON(dev && node && dev->of_node != node))
106 func = kzalloc(sizeof(*func), GFP_KERNEL);
110 bridge_node = of_node_get(node);
111 while (bridge_node) {
112 const __be32 *prop = of_get_property(bridge_node,
113 "arm,vexpress,config-bridge", NULL);
116 bridge_node = of_find_node_by_phandle(
121 bridge_node = of_get_next_parent(bridge_node);
124 mutex_lock(&vexpress_config_bridges_mutex);
125 for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
126 struct vexpress_config_bridge *bridge =
127 &vexpress_config_bridges[i];
129 if (test_bit(i, vexpress_config_bridges_map) &&
130 bridge->node == bridge_node) {
131 func->bridge = bridge;
132 func->func = bridge->info->func_get(dev, node);
136 mutex_unlock(&vexpress_config_bridges_mutex);
146 EXPORT_SYMBOL(__vexpress_config_func_get);
148 void vexpress_config_func_put(struct vexpress_config_func *func)
150 func->bridge->info->func_put(func->func);
151 of_node_put(func->bridge->node);
154 EXPORT_SYMBOL(vexpress_config_func_put);
156 struct vexpress_config_trans {
157 struct vexpress_config_func *func;
162 struct completion completion;
163 struct list_head list;
166 static void vexpress_config_dump_trans(const char *what,
167 struct vexpress_config_trans *trans)
169 pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
170 what, trans->write ? "write" : "read", trans,
171 trans->func->func, trans->offset,
172 trans->data ? *trans->data : 0, trans->status);
175 static int vexpress_config_schedule(struct vexpress_config_trans *trans)
178 struct vexpress_config_bridge *bridge = trans->func->bridge;
181 init_completion(&trans->completion);
182 trans->status = -EFAULT;
184 spin_lock_irqsave(&bridge->transactions_lock, flags);
186 if (list_empty(&bridge->transactions)) {
187 vexpress_config_dump_trans("Executing", trans);
188 status = bridge->info->func_exec(trans->func->func,
189 trans->offset, trans->write, trans->data);
191 vexpress_config_dump_trans("Queuing", trans);
192 status = VEXPRESS_CONFIG_STATUS_WAIT;
196 case VEXPRESS_CONFIG_STATUS_DONE:
197 vexpress_config_dump_trans("Finished", trans);
198 trans->status = status;
200 case VEXPRESS_CONFIG_STATUS_WAIT:
201 list_add_tail(&trans->list, &bridge->transactions);
205 spin_unlock_irqrestore(&bridge->transactions_lock, flags);
210 void vexpress_config_complete(struct vexpress_config_bridge *bridge,
213 struct vexpress_config_trans *trans;
215 const char *message = "Completed";
217 spin_lock_irqsave(&bridge->transactions_lock, flags);
219 trans = list_first_entry(&bridge->transactions,
220 struct vexpress_config_trans, list);
221 trans->status = status;
224 vexpress_config_dump_trans(message, trans);
225 list_del(&trans->list);
226 complete(&trans->completion);
228 if (list_empty(&bridge->transactions))
231 trans = list_first_entry(&bridge->transactions,
232 struct vexpress_config_trans, list);
233 vexpress_config_dump_trans("Executing pending", trans);
234 trans->status = bridge->info->func_exec(trans->func->func,
235 trans->offset, trans->write, trans->data);
236 message = "Finished pending";
237 } while (trans->status == VEXPRESS_CONFIG_STATUS_DONE);
239 spin_unlock_irqrestore(&bridge->transactions_lock, flags);
241 EXPORT_SYMBOL(vexpress_config_complete);
243 int vexpress_config_wait(struct vexpress_config_trans *trans)
245 wait_for_completion(&trans->completion);
247 return trans->status;
249 EXPORT_SYMBOL(vexpress_config_wait);
251 int vexpress_config_read(struct vexpress_config_func *func, int offset,
254 struct vexpress_config_trans trans = {
261 int status = vexpress_config_schedule(&trans);
263 if (status == VEXPRESS_CONFIG_STATUS_WAIT)
264 status = vexpress_config_wait(&trans);
268 EXPORT_SYMBOL(vexpress_config_read);
270 int vexpress_config_write(struct vexpress_config_func *func, int offset,
273 struct vexpress_config_trans trans = {
280 int status = vexpress_config_schedule(&trans);
282 if (status == VEXPRESS_CONFIG_STATUS_WAIT)
283 status = vexpress_config_wait(&trans);
287 EXPORT_SYMBOL(vexpress_config_write);