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
);