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/init.h>
20 #include <linux/list.h>
22 #include <linux/of_device.h>
23 #include <linux/slab.h>
24 #include <linux/string.h>
25 #include <linux/vexpress.h>
28 #define VEXPRESS_CONFIG_MAX_BRIDGES 2
30 struct vexpress_config_bridge
{
31 struct device_node
*node
;
32 struct vexpress_config_bridge_info
*info
;
33 struct list_head transactions
;
34 spinlock_t transactions_lock
;
35 } vexpress_config_bridges
[VEXPRESS_CONFIG_MAX_BRIDGES
];
37 static DECLARE_BITMAP(vexpress_config_bridges_map
,
38 ARRAY_SIZE(vexpress_config_bridges
));
39 static DEFINE_MUTEX(vexpress_config_bridges_mutex
);
41 struct vexpress_config_bridge
*vexpress_config_bridge_register(
42 struct device_node
*node
,
43 struct vexpress_config_bridge_info
*info
)
45 struct vexpress_config_bridge
*bridge
;
48 pr_debug("Registering bridge '%s'\n", info
->name
);
50 mutex_lock(&vexpress_config_bridges_mutex
);
51 i
= find_first_zero_bit(vexpress_config_bridges_map
,
52 ARRAY_SIZE(vexpress_config_bridges
));
53 if (i
>= ARRAY_SIZE(vexpress_config_bridges
)) {
54 pr_err("Can't register more bridges!\n");
55 mutex_unlock(&vexpress_config_bridges_mutex
);
58 __set_bit(i
, vexpress_config_bridges_map
);
59 bridge
= &vexpress_config_bridges
[i
];
63 INIT_LIST_HEAD(&bridge
->transactions
);
64 spin_lock_init(&bridge
->transactions_lock
);
66 mutex_unlock(&vexpress_config_bridges_mutex
);
70 EXPORT_SYMBOL(vexpress_config_bridge_register
);
72 void vexpress_config_bridge_unregister(struct vexpress_config_bridge
*bridge
)
74 struct vexpress_config_bridge __bridge
= *bridge
;
77 mutex_lock(&vexpress_config_bridges_mutex
);
78 for (i
= 0; i
< ARRAY_SIZE(vexpress_config_bridges
); i
++)
79 if (&vexpress_config_bridges
[i
] == bridge
)
80 __clear_bit(i
, vexpress_config_bridges_map
);
81 mutex_unlock(&vexpress_config_bridges_mutex
);
83 WARN_ON(!list_empty(&__bridge
.transactions
));
84 while (!list_empty(&__bridge
.transactions
))
87 EXPORT_SYMBOL(vexpress_config_bridge_unregister
);
90 struct vexpress_config_func
{
91 struct vexpress_config_bridge
*bridge
;
95 struct vexpress_config_func
*__vexpress_config_func_get(struct device
*dev
,
96 struct device_node
*node
)
98 struct device_node
*bridge_node
;
99 struct vexpress_config_func
*func
;
102 if (WARN_ON(dev
&& node
&& dev
->of_node
!= node
))
107 func
= kzalloc(sizeof(*func
), GFP_KERNEL
);
111 bridge_node
= of_node_get(node
);
112 while (bridge_node
) {
113 const __be32
*prop
= of_get_property(bridge_node
,
114 "arm,vexpress,config-bridge", NULL
);
117 bridge_node
= of_find_node_by_phandle(
122 bridge_node
= of_get_next_parent(bridge_node
);
125 mutex_lock(&vexpress_config_bridges_mutex
);
126 for (i
= 0; i
< ARRAY_SIZE(vexpress_config_bridges
); i
++) {
127 struct vexpress_config_bridge
*bridge
=
128 &vexpress_config_bridges
[i
];
130 if (test_bit(i
, vexpress_config_bridges_map
) &&
131 bridge
->node
== bridge_node
) {
132 func
->bridge
= bridge
;
133 func
->func
= bridge
->info
->func_get(dev
, node
);
137 mutex_unlock(&vexpress_config_bridges_mutex
);
147 EXPORT_SYMBOL(__vexpress_config_func_get
);
149 void vexpress_config_func_put(struct vexpress_config_func
*func
)
151 func
->bridge
->info
->func_put(func
->func
);
152 of_node_put(func
->bridge
->node
);
155 EXPORT_SYMBOL(vexpress_config_func_put
);
157 struct vexpress_config_trans
{
158 struct vexpress_config_func
*func
;
163 struct completion completion
;
164 struct list_head list
;
167 static void vexpress_config_dump_trans(const char *what
,
168 struct vexpress_config_trans
*trans
)
170 pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
171 what
, trans
->write
? "write" : "read", trans
,
172 trans
->func
->func
, trans
->offset
,
173 trans
->data
? *trans
->data
: 0, trans
->status
);
176 static int vexpress_config_schedule(struct vexpress_config_trans
*trans
)
179 struct vexpress_config_bridge
*bridge
= trans
->func
->bridge
;
182 init_completion(&trans
->completion
);
183 trans
->status
= -EFAULT
;
185 spin_lock_irqsave(&bridge
->transactions_lock
, flags
);
187 if (list_empty(&bridge
->transactions
)) {
188 vexpress_config_dump_trans("Executing", trans
);
189 status
= bridge
->info
->func_exec(trans
->func
->func
,
190 trans
->offset
, trans
->write
, trans
->data
);
192 vexpress_config_dump_trans("Queuing", trans
);
193 status
= VEXPRESS_CONFIG_STATUS_WAIT
;
197 case VEXPRESS_CONFIG_STATUS_DONE
:
198 vexpress_config_dump_trans("Finished", trans
);
199 trans
->status
= status
;
201 case VEXPRESS_CONFIG_STATUS_WAIT
:
202 list_add_tail(&trans
->list
, &bridge
->transactions
);
206 spin_unlock_irqrestore(&bridge
->transactions_lock
, flags
);
211 void vexpress_config_complete(struct vexpress_config_bridge
*bridge
,
214 struct vexpress_config_trans
*trans
;
216 const char *message
= "Completed";
218 spin_lock_irqsave(&bridge
->transactions_lock
, flags
);
220 trans
= list_first_entry(&bridge
->transactions
,
221 struct vexpress_config_trans
, list
);
222 trans
->status
= status
;
225 vexpress_config_dump_trans(message
, trans
);
226 list_del(&trans
->list
);
227 complete(&trans
->completion
);
229 if (list_empty(&bridge
->transactions
))
232 trans
= list_first_entry(&bridge
->transactions
,
233 struct vexpress_config_trans
, list
);
234 vexpress_config_dump_trans("Executing pending", trans
);
235 trans
->status
= bridge
->info
->func_exec(trans
->func
->func
,
236 trans
->offset
, trans
->write
, trans
->data
);
237 message
= "Finished pending";
238 } while (trans
->status
== VEXPRESS_CONFIG_STATUS_DONE
);
240 spin_unlock_irqrestore(&bridge
->transactions_lock
, flags
);
242 EXPORT_SYMBOL(vexpress_config_complete
);
244 int vexpress_config_wait(struct vexpress_config_trans
*trans
)
246 wait_for_completion(&trans
->completion
);
248 return trans
->status
;
250 EXPORT_SYMBOL(vexpress_config_wait
);
252 int vexpress_config_read(struct vexpress_config_func
*func
, int offset
,
255 struct vexpress_config_trans trans
= {
262 int status
= vexpress_config_schedule(&trans
);
264 if (status
== VEXPRESS_CONFIG_STATUS_WAIT
)
265 status
= vexpress_config_wait(&trans
);
269 EXPORT_SYMBOL(vexpress_config_read
);
271 int vexpress_config_write(struct vexpress_config_func
*func
, int offset
,
274 struct vexpress_config_trans trans
= {
281 int status
= vexpress_config_schedule(&trans
);
283 if (status
== VEXPRESS_CONFIG_STATUS_WAIT
)
284 status
= vexpress_config_wait(&trans
);
288 EXPORT_SYMBOL(vexpress_config_write
);