RTEMS CPU Kit with SuperCore  4.11.3
access.h
Go to the documentation of this file.
1 /* Routines to access PCI memory/configuration space and other PCI related
2  * functions the PCI Library provides.
3  *
4  * COPYRIGHT (c) 2010 Cobham Gaisler AB.
5  *
6  * The license and distribution terms for this file may be
7  * found in the file LICENSE in this distribution or at
8  * http://www.rtems.org/license/LICENSE.
9  */
10 
11 
12 #ifndef __PCI_ACCESS_H__
13 #define __PCI_ACCESS_H__
14 
15 #include <stdint.h>
16 #include <libcpu/byteorder.h>
17 #include <rtems/score/basedefs.h>
18 #include <pci.h>
19 
20 /* Let BSP configure load/store from PCI */
21 #include <bsp.h>
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /* Identification of a PCI configuration space device (16-bit) */
28 typedef uint16_t pci_dev_t;
29 /* Create a PCI Configuration Space ID */
30 #define PCI_DEV(bus, slot, func) (((bus)<<8) | ((slot)<<3) | (func))
31 /* Get Bus of a PCI Configuration Space ID */
32 #define PCI_DEV_BUS(dev) (((dev) >> 8) & 0xff)
33 /* Get Slot/Device of a PCI Configuration Space ID */
34 #define PCI_DEV_SLOT(dev) (((dev) >> 3) & 0x1f)
35 /* Get Function of a PCI Configuration Space ID */
36 #define PCI_DEV_FUNC(dev) ((dev) & 0x7)
37 /* Get Device and Function of a PCI Configuration Space ID */
38 #define PCI_DEV_DEVFUNC(dev) ((dev) & 0xff)
39 /* Expand Device into argument lists */
40 #define PCI_DEV_EXPAND(dev) PCI_DEV_BUS((dev)), PCI_DEV_SLOT((dev)), PCI_DEV_FUNC((dev))
41 
42 /* Configuration Space Read/Write Operations */
43 struct pci_cfg_ops {
44  /* Configuration Space Access and Setup Routines */
45  int (*read8)(pci_dev_t dev, int ofs, uint8_t *data);
46  int (*read16)(pci_dev_t dev, int ofs, uint16_t *data);
47  int (*read32)(pci_dev_t dev, int ofs, uint32_t *data);
48  int (*write8)(pci_dev_t dev, int ofs, uint8_t data);
49  int (*write16)(pci_dev_t dev, int ofs, uint16_t data);
50  int (*write32)(pci_dev_t dev, int ofs, uint32_t data);
51 };
52 
53 /* Read a register over PCI I/O Space, and swap it if necessary (due to
54  * PCI endianness)
55  */
56 struct pci_io_ops {
57  uint8_t (*read8)(uint8_t *adr);
58  uint16_t(*read16)(uint16_t *adr);
59  uint32_t (*read32)(uint32_t *adr);
60  void (*write8)(uint8_t *adr, uint8_t data);
61  void (*write16)(uint16_t *adr, uint16_t data);
62  void (*write32)(uint32_t *adr, uint32_t data);
63 };
64 
65 /* Read a register over PCI Memory Space (non-prefetchable memory), and
66  * swap it if necessary (due to PCI endianness)
67  */
68 struct pci_memreg_ops {
69  uint8_t (*ld8)(uint8_t *adr);
70  void (*st8)(uint8_t *adr, uint8_t data);
71 
72  uint16_t(*ld_le16)(uint16_t *adr);
73  void (*st_le16)(uint16_t *adr, uint16_t data);
74  uint16_t(*ld_be16)(uint16_t *adr);
75  void (*st_be16)(uint16_t *adr, uint16_t data);
76 
77  uint32_t (*ld_le32)(uint32_t *adr);
78  void (*st_le32)(uint32_t *adr, uint32_t data);
79  uint32_t (*ld_be32)(uint32_t *adr);
80  void (*st_be32)(uint32_t *adr, uint32_t data);
81 };
82 
83 typedef uint8_t (*pci_ld8_t)(uint8_t *adr);
84 typedef void (*pci_st8_t)(uint8_t *adr, uint8_t data);
85 typedef uint16_t(pci_ld16_t)(uint16_t *adr);
86 typedef void (*pci_st16_t)(uint16_t *adr, uint16_t data);
87 typedef uint32_t (*pci_ld32_t)(uint32_t *adr);
88 typedef void (*pci_st32_t)(uint32_t *adr, uint32_t data);
89 
90 struct pci_access_drv {
91  /* Configuration */
92  struct pci_cfg_ops cfg;
93 
94  /* I/O Access operations */
95  struct pci_io_ops io;
96 
97  /* Registers over Memory Access operations. Note that these funcs
98  * are only for code that need to be compatible with both Big-Endian
99  * and Little-Endian PCI bus or for some other reason need function
100  * pointers to access functions. Normally drivers use the inline
101  * functions for Registers-over-Memory access to avoid extra function
102  * call.
103  */
104  struct pci_memreg_ops *memreg;
105 
106  /* Translate from PCI address to CPU address (dir=0). Translate
107  * CPU address to PCI address (dir!=0). The address will can be
108  * used to perform I/O access or memory access by CPU or PCI DMA
109  * peripheral.
110  *
111  * address In/Out. CPU address or PCI address.
112  * type Access type. 1=I/O, 2=MEMIO, 3=MEM
113  * dir Translate direction. 0=PCI-to-CPU, 0!=CPU-to-PCI,
114  *
115  * Return Value
116  * 0 = Success
117  * -1 = Requested Address not mapped into other address space
118  * i.e. not accessible
119  */
120  int (*translate)(uint32_t *address, int type, int dir);
121 };
122 
123 /* Access Routines valid after a PCI-Access-Driver has registered */
124 extern struct pci_access_drv pci_access_ops;
125 
126 /* Register PCI Access Driver */
127 extern int pci_access_drv_register(struct pci_access_drv *drv);
128 
129 /* Set/unset bits in command and status register of a PCI device */
130 extern void pci_modify_cmdsts(pci_dev_t dev, uint32_t mask, uint32_t val);
131 
132 /* Enable Memory in command register */
133 RTEMS_INLINE_ROUTINE void pci_mem_enable(pci_dev_t dev)
134 {
135  pci_modify_cmdsts(dev, PCIM_CMD_MEMEN, PCIM_CMD_MEMEN);
136 }
137 
138 RTEMS_INLINE_ROUTINE void pci_mem_disable(pci_dev_t dev)
139 {
140  pci_modify_cmdsts(dev, PCIM_CMD_MEMEN, 0);
141 }
142 
143 RTEMS_INLINE_ROUTINE void pci_io_enable(pci_dev_t dev)
144 {
145  pci_modify_cmdsts(dev, PCIM_CMD_PORTEN, PCIM_CMD_PORTEN);
146 }
147 
148 RTEMS_INLINE_ROUTINE void pci_io_disable(pci_dev_t dev)
149 {
150  pci_modify_cmdsts(dev, PCIM_CMD_PORTEN, 0);
151 }
152 
153 RTEMS_INLINE_ROUTINE void pci_master_enable(pci_dev_t dev)
154 {
155  pci_modify_cmdsts(dev, PCIM_CMD_BUSMASTEREN, PCIM_CMD_BUSMASTEREN);
156 }
157 
158 RTEMS_INLINE_ROUTINE void pci_master_disable(pci_dev_t dev)
159 {
160  pci_modify_cmdsts(dev, PCIM_CMD_BUSMASTEREN, 0);
161 }
162 
163 /* Configuration Space Access Read Routines */
164 extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data);
165 extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data);
166 extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data);
167 
168 /* Configuration Space Access Write Routines */
169 extern int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data);
170 extern int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data);
171 extern int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data);
172 
173 /* Read a register over PCI I/O Space */
174 extern uint8_t pci_io_r8(uint32_t adr);
175 extern uint16_t pci_io_r16(uint32_t adr);
176 extern uint32_t pci_io_r32(uint32_t adr);
177 
178 /* Write a register over PCI I/O Space */
179 extern void pci_io_w8(uint32_t adr, uint8_t data);
180 extern void pci_io_w16(uint32_t adr, uint16_t data);
181 extern void pci_io_w32(uint32_t adr, uint32_t data);
182 
183 /* Translate PCI address into CPU accessible address */
184 RTEMS_INLINE_ROUTINE int pci_pci2cpu(uint32_t *address, int type)
185 {
186  return pci_access_ops.translate(address, type, 0);
187 }
188 
189 /* Translate CPU accessible address into PCI address (for DMA) */
190 RTEMS_INLINE_ROUTINE int pci_cpu2pci(uint32_t *address, int type)
191 {
192  return pci_access_ops.translate(address, type, 1);
193 }
194 
195 /*** Read/Write a register over PCI Memory Space ***/
196 
197 RTEMS_INLINE_ROUTINE uint8_t pci_ld8(volatile uint8_t *addr)
198 {
199  return *addr;
200 }
201 
202 RTEMS_INLINE_ROUTINE void pci_st8(volatile uint8_t *addr, uint8_t val)
203 {
204  *addr = val;
205 }
206 
207 #ifdef BSP_PCI_BIG_ENDIAN
208 
209 /* BSP has decided Big Endian PCI Bus (non-standard) */
210 
211 RTEMS_INLINE_ROUTINE uint16_t pci_ld_le16(volatile uint16_t *addr)
212 {
213  return ld_be16(addr);
214 }
215 
216 RTEMS_INLINE_ROUTINE void pci_st_le16(volatile uint16_t *addr, uint16_t val)
217 {
218  st_be16(addr, val);
219 }
220 
221 RTEMS_INLINE_ROUTINE uint32_t pci_ld_le32(volatile uint32_t *addr)
222 {
223  return ld_be32(addr);
224 }
225 
226 RTEMS_INLINE_ROUTINE void pci_st_le32(volatile uint32_t *addr, uint32_t val)
227 {
228  st_be32(addr, val);
229 }
230 
231 RTEMS_INLINE_ROUTINE uint16_t pci_ld_be16(volatile uint16_t *addr)
232 {
233  return ld_le16(addr);
234 }
235 
236 RTEMS_INLINE_ROUTINE void pci_st_be16(volatile uint16_t *addr, uint16_t val)
237 {
238  st_le16(addr, val);
239 }
240 
241 RTEMS_INLINE_ROUTINE uint32_t pci_ld_be32(volatile uint32_t *addr)
242 {
243  return ld_le32(addr);
244 }
245 
246 RTEMS_INLINE_ROUTINE void pci_st_be32(volatile uint32_t *addr, uint32_t val)
247 {
248  st_le32(addr, val);
249 }
250 
251 #else
252 
253 /* Little Endian PCI Bus */
254 
255 RTEMS_INLINE_ROUTINE uint16_t pci_ld_le16(volatile uint16_t *addr)
256 {
257  return ld_le16(addr);
258 }
259 
260 RTEMS_INLINE_ROUTINE void pci_st_le16(volatile uint16_t *addr, uint16_t val)
261 {
262  st_le16(addr, val);
263 }
264 
265 RTEMS_INLINE_ROUTINE uint32_t pci_ld_le32(volatile uint32_t *addr)
266 {
267  return ld_le32(addr);
268 }
269 
270 RTEMS_INLINE_ROUTINE void pci_st_le32(volatile uint32_t *addr, uint32_t val)
271 {
272  st_le32(addr, val);
273 }
274 
275 RTEMS_INLINE_ROUTINE uint16_t pci_ld_be16(volatile uint16_t *addr)
276 {
277  return ld_be16(addr);
278 }
279 
280 RTEMS_INLINE_ROUTINE void pci_st_be16(volatile uint16_t *addr, uint16_t val)
281 {
282  st_be16(addr, val);
283 }
284 
285 RTEMS_INLINE_ROUTINE uint32_t pci_ld_be32(volatile uint32_t *addr)
286 {
287  return ld_be32(addr);
288 }
289 
290 RTEMS_INLINE_ROUTINE void pci_st_be32(volatile uint32_t *addr, uint32_t val)
291 {
292  st_be32(addr, val);
293 }
294 
295 #endif
296 
297 /* Registers-over-Memory Space access routines. The routines are not inlined
298  * so it is possible during run-time to select which function implemention
299  * to use. The use of these functions are not recommended since it will have a
300  * performance penalty.
301  *
302  * 8-bit accesses are the same for Little and Big endian PCI buses.
303  */
304 uint8_t pci_mem_ld8(uint8_t *adr);
305 void pci_mem_st8(uint8_t *adr, uint8_t data);
306 /* Registers-over-Memory Space - Generic Big endian PCI bus definitions */
307 uint16_t pci_mem_be_ld_le16(uint16_t *adr);
308 uint16_t pci_mem_be_ld_be16(uint16_t *adr);
309 uint32_t pci_mem_be_ld_le32(uint32_t *adr);
310 uint32_t pci_mem_be_ld_be32(uint32_t *adr);
311 void pci_mem_be_st_le16(uint16_t *adr, uint16_t data);
312 void pci_mem_be_st_be16(uint16_t *adr, uint16_t data);
313 void pci_mem_be_st_le32(uint32_t *adr, uint32_t data);
314 void pci_mem_be_st_be32(uint32_t *adr, uint32_t data);
315 /* Registers-over-Memory Space - Generic Little endian PCI bus definitions */
316 uint16_t pci_mem_le_ld_le16(uint16_t *adr);
317 uint16_t pci_mem_le_ld_be16(uint16_t *adr);
318 uint32_t pci_mem_le_ld_le32(uint32_t *adr);
319 uint32_t pci_mem_le_ld_be32(uint32_t *adr);
320 void pci_mem_le_st_le16(uint16_t *adr, uint16_t data);
321 void pci_mem_le_st_be16(uint16_t *adr, uint16_t data);
322 void pci_mem_le_st_le32(uint32_t *adr, uint32_t data);
323 void pci_mem_le_st_be32(uint32_t *adr, uint32_t data);
324 
325 /* Get Read/Write function for accessing a register over PCI Memory Space
326  * (non-inline functions).
327  *
328  * Arguments
329  * wr 0(Read), 1(Write)
330  * size 1(Byte), 2(Word), 4(Double Word)
331  * func Where function pointer will be stored
332  * endian PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
333  * type 1(I/O), 3(REG over MEM), 4(CFG)
334  *
335  * Return
336  * 0 Found function
337  * others No such function defined by host driver or BSP
338  */
339 extern int pci_access_func(int wr, int size, void **func, int endian, int type);
340 
341 /* Predefined functions for Host drivers or BSPs that define the
342  * register-over-memory space functions operations.
343  */
344 extern struct pci_memreg_ops pci_mem_le_ops; /* For Little-Endian PCI bus */
345 extern struct pci_memreg_ops pci_mem_be_ops; /* For Big-Endian PCI bus */
346 
347 #ifdef __cplusplus
348 }
349 #endif
350 
351 #endif /* !__PCI_ACCESS_H__ */
Definition: access.h:91
#define RTEMS_INLINE_ROUTINE
The following (in conjunction with compiler arguments) are used to choose between the use of static i...
Definition: basedefs.h:135
Definition: access.h:69
Definition: access.h:44
Definition: access.h:57
Basic Definitions.