1 #ifndef CYGONCE_PLF_IO_H
2 #define CYGONCE_PLF_IO_H
4 //=============================================================================
8 // Platform specific IO support
10 //=============================================================================
11 //####ECOSGPLCOPYRIGHTBEGIN####
12 // -------------------------------------------
13 // This file is part of eCos, the Embedded Configurable Operating System.
14 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
39 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40 // at http://sources.redhat.com/ecos/ecos-license/
41 // -------------------------------------------
42 //####ECOSGPLCOPYRIGHTEND####
43 //=============================================================================
44 //#####DESCRIPTIONBEGIN####
46 // Author(s): Philippe Robin
47 // Contributors: David A Rusling
48 // Date: November 7, 2000
49 // Purpose: Integrator PCI IO support macros
51 // Usage: #include <cyg/hal/plf_io.h>
53 //####DESCRIPTIONEND####
55 //=============================================================================
57 #include <pkgconf/hal_arm_integrator.h>
59 #include <cyg/hal/hal_integrator.h>
61 #include <cyg/hal/hal_platform_ints.h> // Interrupt vectors
63 __externC void cyg_plf_pci_init(void);
65 // Initialization of the PCI bus.
66 #define HAL_PCI_INIT() cyg_plf_pci_init()
70 #define _V3Write16(o,v) (*(volatile cyg_uint16 *)(PCI_V3_BASE + (cyg_uint32)(o)) \
72 #define _V3Read16(o) (*(volatile cyg_uint16 *)(PCI_V3_BASE + (cyg_uint32)(o)))
74 #define _V3Write32(o,v) (*(volatile cyg_uint32 *)(PCI_V3_BASE + (cyg_uint32)(o)) \
76 #define _V3Read32(o) (*(volatile cyg_uint32 *)(PCI_V3_BASE + (cyg_uint32)(o)))
78 // _V3OpenConfigWindow - open V3 configuration window
79 #define _V3OpenConfigWindow() \
81 /* Set up base0 to see all 512Mbytes of memory space (not */ \
82 /* prefetchable), this frees up base1 for re-use by configuration*/ \
85 _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) | \
86 0x90 | V3_LB_BASE_M_ENABLE)); \
87 /* Set up base1 to point into configuration space, note that MAP1 */ \
88 /* register is set up by pciMakeConfigAddress(). */ \
90 _V3Write32 (V3_LB_BASE1, ((CPU_PCI_CNFG_ADRS & 0xFFF00000) | \
91 0x40 | V3_LB_BASE_M_ENABLE)); \
94 // _V3CloseConfigWindow - close V3 configuration window
95 #define _V3CloseConfigWindow() \
97 /* Reassign base1 for use by prefetchable PCI memory */ \
98 _V3Write32 (V3_LB_BASE1, (((INTEGRATOR_PCI_BASE + SZ_256M) & 0xFFF00000) \
99 | 0x84 | V3_LB_BASE_M_ENABLE)); \
100 _V3Write16 (V3_LB_MAP1, \
101 (((INTEGRATOR_PCI_BASE + SZ_256M) & 0xFFF00000) >> 16) | 0x0006); \
103 /* And shrink base0 back to a 256M window (NOTE: MAP0 already correct) */ \
105 _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) | \
106 0x80 | V3_LB_BASE_M_ENABLE)); \
109 // Compute address necessary to access PCI config space for the given
111 #define HAL_PCI_CONFIG_ADDRESS( __bus, __devfn, __offset ) \
113 cyg_uint32 __address, __devicebit; \
114 cyg_uint16 __mapaddress; \
115 cyg_uint32 __dev = CYG_PCI_DEV_GET_DEV(__devfn); /* FIXME to check!! (slot?) */ \
118 /* local bus segment so need a type 0 config cycle */ \
119 /* build the PCI configuration "address" with one-hot in A31-A11 */ \
120 __address = PCI_CONFIG_BASE; \
121 __address |= ((__devfn & 0x07) << 8); \
122 __address |= __offset & 0xFF; \
123 __mapaddress = 0x000A; /* 101=>config cycle, 0=>A1=A0=0 */ \
124 __devicebit = (1 << (__dev + 11)); \
126 if ((__devicebit & 0xFF000000) != 0) { \
127 /* high order bits are handled by the MAP register */ \
128 __mapaddress |= (__devicebit >> 16); \
130 /* low order bits handled directly in the address */ \
131 __address |= __devicebit; \
133 } else { /* bus !=0 */ \
134 /* not the local bus segment so need a type 1 config cycle */ \
135 /* A31-A24 are don't care (so clear to 0) */ \
136 __mapaddress = 0x000B; /* 101=>config cycle, 1=>A1&A0 from PCI_CFG */ \
137 __address = PCI_CONFIG_BASE; \
138 __address |= ((__bus & 0xFF) << 16); /* bits 23..16 = bus number */ \
139 __address |= ((__dev & 0x1F) << 11); /* bits 15..11 = device number */ \
140 __address |= ((__devfn & 0x07) << 8); /* bits 10..8 = function number*/ \
141 __address |= __offset & 0xFF; /* bits 7..0 = register number*/ \
143 _V3Write16(V3_LB_MAP1, __mapaddress); \
148 // Read a value from the PCI configuration space of the appropriate
149 // size at an address composed from the bus, devfn and offset.
150 #define HAL_PCI_CFG_READ_UINT8( __bus, __devfn, __offset, __val ) \
152 _V3OpenConfigWindow(); \
153 __val = *(volatile cyg_uint8 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset); \
154 _V3CloseConfigWindow(); \
157 #define HAL_PCI_CFG_READ_UINT16( __bus, __devfn, __offset, __val ) \
159 _V3OpenConfigWindow(); \
160 __val = *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset); \
161 _V3CloseConfigWindow(); \
164 #define HAL_PCI_CFG_READ_UINT32( __bus, __devfn, __offset, __val ) \
166 _V3OpenConfigWindow(); \
167 __val = *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset); \
168 __val |= (*(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, (__offset+2)))<<16; \
169 _V3CloseConfigWindow(); \
172 // Write a value to the PCI configuration space of the appropriate
173 // size at an address composed from the bus, devfn and offset.
174 #define HAL_PCI_CFG_WRITE_UINT8( __bus, __devfn, __offset, __val ) \
176 _V3OpenConfigWindow(); \
177 *(volatile cyg_uint8 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val; \
178 _V3CloseConfigWindow(); \
181 #define HAL_PCI_CFG_WRITE_UINT16( __bus, __devfn, __offset, __val ) \
183 _V3OpenConfigWindow(); \
184 *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val; \
185 _V3CloseConfigWindow(); \
188 #define HAL_PCI_CFG_WRITE_UINT32( __bus, __devfn, __offset, __val ) \
190 _V3OpenConfigWindow(); \
191 *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS((__bus), (__devfn), (__offset)) = ((__val) & 0xFFFF); \
192 *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS((__bus), (__devfn), ((__offset)+2)) = (((__val)>>16) & 0xFFFF); \
193 _V3CloseConfigWindow(); \
196 //-----------------------------------------------------------------------------
199 // Map PCI device resources starting from these addresses in PCI space.
200 #define HAL_PCI_ALLOC_BASE_MEMORY 0
201 #define HAL_PCI_ALLOC_BASE_IO 0x4000
203 // This is where the PCI spaces are mapped in the CPU's address space.
204 #define HAL_PCI_PHYSICAL_MEMORY_BASE (PCI_MEM_BASE)
205 #define HAL_PCI_PHYSICAL_IO_BASE (PCI_IO_BASE)
207 // Translate the PCI interrupt requested by the device (INTA#, INTB#,
208 // INTC# or INTD#) to the associated CPU interrupt (i.e., HAL vector).
209 #define INTA CYGNUM_HAL_INTERRUPT_PCIINT0
210 #define INTB CYGNUM_HAL_INTERRUPT_PCIINT1
211 #define INTC CYGNUM_HAL_INTERRUPT_PCIINT2
212 #define INTD CYGNUM_HAL_INTERRUPT_PCIINT3
214 #define HAL_PCI_TRANSLATE_INTERRUPT( __bus, __devfn, __vec, __valid) \
218 /* DANGER! For now this is the SDM interrupt table... */ \
219 static const cyg_uint8 irq_tab[12][4] = { \
220 /* INTA INTB INTC INTD */ \
221 {INTA, INTB, INTC, INTD}, /* idsel 20, slot 9 */ \
222 {INTB, INTC, INTD, INTA}, /* idsel 21, slot 10 */ \
223 {INTC, INTD, INTA, INTB}, /* idsel 22, slot 11 */ \
224 {INTD, INTA, INTB, INTC}, /* idsel 23, slot 12 */ \
225 {INTA, INTB, INTC, INTD}, /* idsel 24, slot 13 */ \
226 {INTB, INTC, INTD, INTA}, /* idsel 25, slot 14 */ \
227 {INTC, INTD, INTA, INTB}, /* idsel 26, slot 15 */ \
228 {INTD, INTA, INTB, INTC}, /* idsel 27, slot 16 */ \
229 {INTA, INTB, INTC, INTD}, /* idsel 28, slot 17 */ \
230 {INTB, INTC, INTD, INTA}, /* idsel 29, slot 18 */ \
231 {INTC, INTD, INTA, INTB}, /* idsel 30, slot 19 */ \
232 {INTD, INTA, INTB, INTC} /* idsel 31, slot 20 */ \
234 HAL_PCI_CFG_READ_UINT8(__bus, __devfn, CYG_PCI_CFG_INT_PIN, __req); \
235 __dev = CYG_PCI_DEV_GET_DEV(__devfn); /* FIXME to check!! (slot?)*/ \
237 /* if PIN = 0, default to A */ \
241 __vec = irq_tab[__dev - 9][__req - 1]; \
245 //-----------------------------------------------------------------------------
247 #define CYGARC_PHYSICAL_ADDRESS(x) (x)
249 //-----------------------------------------------------------------------------
251 #endif // CYGONCE_PLF_IO_H