source: rtems/cpukit/libpci/pci/access.h @ 71e8a5c

4.11
Last change on this file since 71e8a5c was 71e8a5c, checked in by Daniel Hellstrom <daniel@…>, on Feb 27, 2015 at 3:45:59 PM

LIBPCI: moved copyright into a single line

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