xref: /linux/drivers/rapidio/rio-access.c (revision bb9707077b4ee5f77bc9939b057ff8a0d410296f)
1 /*
2  * RapidIO configuration space access support
3  *
4  * Copyright 2005 MontaVista Software, Inc.
5  * Matt Porter <mporter@kernel.crashing.org>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  */
12 
13 #include <linux/rio.h>
14 #include <linux/module.h>
15 
16 /*
17  * These interrupt-safe spinlocks protect all accesses to RIO
18  * configuration space and doorbell access.
19  */
20 static DEFINE_SPINLOCK(rio_config_lock);
21 static DEFINE_SPINLOCK(rio_doorbell_lock);
22 
23 /*
24  *  Wrappers for all RIO configuration access functions.  They just check
25  *  alignment, do locking and call the low-level functions pointed to
26  *  by rio_mport->ops.
27  */
28 
29 #define RIO_8_BAD 0
30 #define RIO_16_BAD (offset & 1)
31 #define RIO_32_BAD (offset & 3)
32 
33 /**
34  * RIO_LOP_READ - Generate rio_local_read_config_* functions
35  * @size: Size of configuration space read (8, 16, 32 bits)
36  * @type: C type of value argument
37  * @len: Length of configuration space read (1, 2, 4 bytes)
38  *
39  * Generates rio_local_read_config_* functions used to access
40  * configuration space registers on the local device.
41  */
42 #define RIO_LOP_READ(size,type,len) \
43 int __rio_local_read_config_##size \
44 	(struct rio_mport *mport, u32 offset, type *value)		\
45 {									\
46 	int res;							\
47 	unsigned long flags;						\
48 	u32 data = 0;							\
49 	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
50 	spin_lock_irqsave(&rio_config_lock, flags);			\
51 	res = mport->ops->lcread(mport, mport->id, offset, len, &data);	\
52 	*value = (type)data;						\
53 	spin_unlock_irqrestore(&rio_config_lock, flags);		\
54 	return res;							\
55 }
56 
57 /**
58  * RIO_LOP_WRITE - Generate rio_local_write_config_* functions
59  * @size: Size of configuration space write (8, 16, 32 bits)
60  * @type: C type of value argument
61  * @len: Length of configuration space write (1, 2, 4 bytes)
62  *
63  * Generates rio_local_write_config_* functions used to access
64  * configuration space registers on the local device.
65  */
66 #define RIO_LOP_WRITE(size,type,len) \
67 int __rio_local_write_config_##size \
68 	(struct rio_mport *mport, u32 offset, type value)		\
69 {									\
70 	int res;							\
71 	unsigned long flags;						\
72 	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
73 	spin_lock_irqsave(&rio_config_lock, flags);			\
74 	res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
75 	spin_unlock_irqrestore(&rio_config_lock, flags);		\
76 	return res;							\
77 }
78 
79 RIO_LOP_READ(8, u8, 1)
80 RIO_LOP_READ(16, u16, 2)
81 RIO_LOP_READ(32, u32, 4)
82 RIO_LOP_WRITE(8, u8, 1)
83 RIO_LOP_WRITE(16, u16, 2)
84 RIO_LOP_WRITE(32, u32, 4)
85 
86 EXPORT_SYMBOL_GPL(__rio_local_read_config_8);
87 EXPORT_SYMBOL_GPL(__rio_local_read_config_16);
88 EXPORT_SYMBOL_GPL(__rio_local_read_config_32);
89 EXPORT_SYMBOL_GPL(__rio_local_write_config_8);
90 EXPORT_SYMBOL_GPL(__rio_local_write_config_16);
91 EXPORT_SYMBOL_GPL(__rio_local_write_config_32);
92 
93 /**
94  * RIO_OP_READ - Generate rio_mport_read_config_* functions
95  * @size: Size of configuration space read (8, 16, 32 bits)
96  * @type: C type of value argument
97  * @len: Length of configuration space read (1, 2, 4 bytes)
98  *
99  * Generates rio_mport_read_config_* functions used to access
100  * configuration space registers on the local device.
101  */
102 #define RIO_OP_READ(size,type,len) \
103 int rio_mport_read_config_##size \
104 	(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value)	\
105 {									\
106 	int res;							\
107 	unsigned long flags;						\
108 	u32 data = 0;							\
109 	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
110 	spin_lock_irqsave(&rio_config_lock, flags);			\
111 	res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
112 	*value = (type)data;						\
113 	spin_unlock_irqrestore(&rio_config_lock, flags);		\
114 	return res;							\
115 }
116 
117 /**
118  * RIO_OP_WRITE - Generate rio_mport_write_config_* functions
119  * @size: Size of configuration space write (8, 16, 32 bits)
120  * @type: C type of value argument
121  * @len: Length of configuration space write (1, 2, 4 bytes)
122  *
123  * Generates rio_mport_write_config_* functions used to access
124  * configuration space registers on the local device.
125  */
126 #define RIO_OP_WRITE(size,type,len) \
127 int rio_mport_write_config_##size \
128 	(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value)	\
129 {									\
130 	int res;							\
131 	unsigned long flags;						\
132 	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
133 	spin_lock_irqsave(&rio_config_lock, flags);			\
134 	res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \
135 	spin_unlock_irqrestore(&rio_config_lock, flags);		\
136 	return res;							\
137 }
138 
139 RIO_OP_READ(8, u8, 1)
140 RIO_OP_READ(16, u16, 2)
141 RIO_OP_READ(32, u32, 4)
142 RIO_OP_WRITE(8, u8, 1)
143 RIO_OP_WRITE(16, u16, 2)
144 RIO_OP_WRITE(32, u32, 4)
145 
146 EXPORT_SYMBOL_GPL(rio_mport_read_config_8);
147 EXPORT_SYMBOL_GPL(rio_mport_read_config_16);
148 EXPORT_SYMBOL_GPL(rio_mport_read_config_32);
149 EXPORT_SYMBOL_GPL(rio_mport_write_config_8);
150 EXPORT_SYMBOL_GPL(rio_mport_write_config_16);
151 EXPORT_SYMBOL_GPL(rio_mport_write_config_32);
152 
153 /**
154  * rio_mport_send_doorbell - Send a doorbell message
155  *
156  * @mport: RIO master port
157  * @destid: RIO device destination ID
158  * @data: Doorbell message data
159  *
160  * Send a doorbell message to a RIO device. The doorbell message
161  * has a 16-bit info field provided by the data argument.
162  */
163 int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
164 {
165 	int res;
166 	unsigned long flags;
167 
168 	spin_lock_irqsave(&rio_doorbell_lock, flags);
169 	res = mport->ops->dsend(mport, mport->id, destid, data);
170 	spin_unlock_irqrestore(&rio_doorbell_lock, flags);
171 
172 	return res;
173 }
174 
175 EXPORT_SYMBOL_GPL(rio_mport_send_doorbell);
176