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): hmt, jskov
47 // Contributors: hmt, jskov
49 // Purpose: Intel EBSA285 PCI IO support macros
51 // Usage: #include <cyg/hal/plf_io.h>
53 // Note: Based on information in
54 // "21285 Core Logic for SA-110 Microprocessor"
55 //####DESCRIPTIONEND####
57 //=============================================================================
59 #include <pkgconf/hal_arm_ebsa285.h>
61 #include <cyg/hal/hal_ebsa285.h>
63 #include <cyg/hal/hal_io.h> // IO macros
64 #include <cyg/hal/hal_platform_ints.h> // Interrupt vectors
67 #define CYGARC_PHYSICAL_ADDRESS(_x_) (_x_)
69 // The PCI resources required by the EBSA are hardcoded to the lowest
70 // addresses in the PCI address space, thus:
72 #define EBSA_SDRAM_PCI_ADDR 0
73 #define EBSA_SDRAM_PCI_SIZE (CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE)
74 #define EBSA_CSR_MEM_PCI_ADDR (EBSA_SDRAM_PCI_SIZE)
75 #define EBSA_CSR_MEM_PCI_SIZE 0x80
77 #define EBSA_CSR_IO_PCI_ADDR 0
78 #define EBSA_CSR_IO_PCI_SIZE 0x80
80 // Incidentally I now understand why it's necessary to force PCI reset
81 // (2000-08-07) - with RedBoot in ROM, the RAM app was unconditionally
82 // reinitializing the PCI bus when it was already initialized, without
83 // resetting it. We cannot play the same game here as with
84 // hal_platform_setup.h - I tried - because otherwise the net cannot
85 // re-initialize itself; the scan for devices fails.
87 // Initialize the PCI bus.
88 #define HAL_PCI_INIT() \
90 cyg_uint32 __tmp, __tmp2; \
92 /* Assert PCI_reset */ \
93 HAL_READ_UINT32(SA110_CONTROL, __tmp); \
94 __tmp &= ~SA110_CONTROL_RST_I; \
95 HAL_WRITE_UINT32(SA110_CONTROL, __tmp); \
97 /* Disable PCI Outbound interrupts */ \
98 /* (according to 7-14 SA110_OUT_INT_MASK is not accessible */ \
100 HAL_WRITE_UINT32(SA110_OUT_INT_STATUS, \
101 SA110_OUT_INT_STATUS_DOORBELL_INT \
102 |SA110_OUT_INT_STATUS_OUTBOUND_INT); \
104 /* Disable Doorbells */ \
105 HAL_WRITE_UINT32(SA110_DOORBELL_PCI_MASK, 0); \
106 HAL_WRITE_UINT32(SA110_DOORBELL_SA_MASK, 0); \
108 /* Map high PCI address bits to 0 */ \
109 HAL_WRITE_UINT32(SA110_PCI_ADDR_EXT, 0); \
111 /* Interrupt ID to 1 */ \
112 HAL_WRITE_UINT16(SA110_PCI_CFG_INT_LINE, 0x0100); \
114 /* Remove PCI_reset */ \
115 HAL_READ_UINT32(SA110_CONTROL, __tmp); \
116 __tmp |= SA110_CONTROL_RST_I; \
117 HAL_WRITE_UINT32(SA110_CONTROL, __tmp); \
119 /* Open a window to SDRAM from PCI address space */ \
120 HAL_WRITE_UINT32(SA110_SDRAM_BASE_ADDRESS_MASK, \
121 ((CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_SIZE-1) & 0xfffc0000)); \
122 HAL_WRITE_UINT32(SA110_SDRAM_BASE_ADDRESS_OFFSET, \
123 CYGHWR_HAL_ARM_EBSA285_PCI_MEM_MAP_BASE); \
125 /* Only init PCI if central function is set and */ \
126 /* standalone bit is cleared */ \
127 HAL_READ_UINT32(SA110_CONTROL, __tmp); \
128 HAL_READ_UINT32(SA110_XBUS_XCS2, __tmp2); \
129 if ((__tmp & SA110_CONTROL_CFN) == SA110_CONTROL_CFN \
130 && (__tmp2 & SA110_XBUS_XCS2_PCI_DISABLE) == 0) { \
132 /* Don't respond to any commands */ \
133 HAL_WRITE_UINT16(SA110_PCI_CFG_COMMAND, 0); \
135 /* Set up default addresses for board's resources. */ \
136 HAL_WRITE_UINT32(SA110_PCI_CFG_CSR_MEM_BAR, \
137 EBSA_CSR_MEM_PCI_ADDR); \
138 HAL_WRITE_UINT32(SA110_PCI_CFG_CSR_IO_BAR, EBSA_CSR_IO_PCI_ADDR);\
139 HAL_WRITE_UINT32(SA110_PCI_CFG_SDRAM_BAR, EBSA_SDRAM_PCI_ADDR); \
141 /* Respond to I/O space & Memory transactions. */ \
142 HAL_WRITE_UINT32(SA110_PCI_CFG_COMMAND, \
143 CYG_PCI_CFG_COMMAND_INVALIDATE \
144 |CYG_PCI_CFG_COMMAND_IO \
145 |CYG_PCI_CFG_COMMAND_MEMORY \
146 |CYG_PCI_CFG_COMMAND_MASTER); \
148 /* Signal PCI_init_complete */ \
149 HAL_READ_UINT32(SA110_CONTROL, __tmp); \
150 __tmp |= SA110_CONTROL_INIT_COMPLETE; \
151 HAL_WRITE_UINT32(SA110_CONTROL, __tmp); \
156 // Compute address necessary to access PCI config space for the given
158 #define HAL_PCI_CONFIG_ADDRESS( __bus, __devfn, __offset ) \
161 cyg_uint32 __dev = CYG_PCI_DEV_GET_DEV(__devfn); \
164 /* Access self via CSR base */ \
165 __addr = SA110_CONTROL_STATUS_BASE; \
167 /* Page 3-17, table 3-5: bits 15-11 generate PCI address */ \
168 __addr = SA110_PCI_CONFIG0_BASE | 0x00c00000 | (__dev << 11);\
171 __addr = SA110_PCI_CONFIG1_BASE | (__bus << 16) | (__dev << 11); \
173 __addr |= CYG_PCI_DEV_GET_FN(__devfn) << 8; \
174 __addr |= __offset; \
178 // Read a value from the PCI configuration space of the appropriate
179 // size at an address composed from the bus, devfn and offset.
180 #define HAL_PCI_CFG_READ_UINT8( __bus, __devfn, __offset, __val ) \
181 HAL_READ_UINT8(HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset), __val)
183 #define HAL_PCI_CFG_READ_UINT16( __bus, __devfn, __offset, __val ) \
184 HAL_READ_UINT16(HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset), __val)
186 #define HAL_PCI_CFG_READ_UINT32( __bus, __devfn, __offset, __val ) \
187 HAL_READ_UINT32(HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset), __val)
189 // Write a value to the PCI configuration space of the appropriate
190 // size at an address composed from the bus, devfn and offset.
191 #define HAL_PCI_CFG_WRITE_UINT8( __bus, __devfn, __offset, __val ) \
192 HAL_WRITE_UINT8(HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset), __val)
194 #define HAL_PCI_CFG_WRITE_UINT16( __bus, __devfn, __offset, __val ) \
195 HAL_WRITE_UINT16(HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset), __val)
197 #define HAL_PCI_CFG_WRITE_UINT32( __bus, __devfn, __offset, __val ) \
198 HAL_WRITE_UINT32(HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset), __val)
200 //-----------------------------------------------------------------------------
203 // Map PCI device resources starting from these addresses in PCI space.
204 #define HAL_PCI_ALLOC_BASE_MEMORY (EBSA_SDRAM_PCI_SIZE+EBSA_CSR_MEM_PCI_SIZE)
205 #define HAL_PCI_ALLOC_BASE_IO (EBSA_CSR_IO_PCI_SIZE)
207 // This is where the PCI spaces are mapped in the CPU's address space.
208 #define HAL_PCI_PHYSICAL_MEMORY_BASE 0x80000000
209 #define HAL_PCI_PHYSICAL_IO_BASE 0x7c000000
211 // Translate the PCI interrupt requested by the device (INTA#, INTB#,
212 // INTC# or INTD#) to the associated CPU interrupt (i.e., HAL vector).
213 #define HAL_PCI_TRANSLATE_INTERRUPT( __bus, __devfn, __vec, __valid) \
216 HAL_PCI_CFG_READ_UINT8(__bus, __devfn, CYG_PCI_CFG_INT_PIN, __req); \
218 /* Interrupt assignment as 21285 sees them. (From */ \
219 /* EBSA285 Eval Board Reference Manual, 3.4 Interrupt Assignment) */ \
220 CYG_ADDRWORD __translation[4] = { \
221 CYGNUM_HAL_INTERRUPT_IRQ_IN_1, /* INTC# */ \
222 CYGNUM_HAL_INTERRUPT_IRQ_IN_0, /* INTB# */ \
223 CYGNUM_HAL_INTERRUPT_PCI_IRQ, /* INTA# */ \
224 CYGNUM_HAL_INTERRUPT_IRQ_IN_3}; /* INTD# */ \
226 /* The PCI lines from the different slots are wired like this */ \
227 /* on the PCI backplane: */ \
228 /* pin6A pin7B pin7A pin8B */ \
229 /* System Slot INTA# INTB# INTC# INTD# */ \
230 /* I/O Slot 1 INTB# INTC# INTD# INTA# */ \
231 /* I/O Slot 2 INTC# INTD# INTA# INTB# */ \
232 /* I/O Slot 3 INTD# INTA# INTB# INTC# */ \
233 /* I/O Slot 4 INTA# INTB# INTC# INTD# */ \
235 /* (From PCI Development Backplane, 3.2.2 Interrupts) */ \
237 /* Devsel signals are wired to, resulting in device IDs: */ \
238 /* I/O Slot 1 AD19 / dev 8 [(8+1)&3 = 1] */ \
239 /* I/O Slot 2 AD18 / dev 7 [(7+1)&3 = 0] */ \
240 /* I/O Slot 3 AD17 / dev 6 [(6+1)&3 = 3] */ \
241 /* I/O Slot 4 AD16 / dev 5 [(5+1)&3 = 2] */ \
243 /* (From PCI Development Backplane, 3.2.1 General) */ \
245 /* The observant reader will notice that the array does not */ \
246 /* match the table of how interrupts are wired. The array */ \
247 /* does however match observed behavior of the hardware: */ \
249 /* Observed interrupts with an Intel ethernet card */ \
250 /* put in the slots in turn and set to generate interrupts: */ \
251 /* slot 1/intA# (dev 8): caused host INTB# */ \
252 /* slot 2/intA# (dev 7): caused host INTC# */ \
253 /* slot 3/intA# (dev 6): caused host INTD# */ \
254 /* slot 4/intA# (dev 5): caused host INTA# */ \
256 __vec = __translation[((__req+CYG_PCI_DEV_GET_DEV(__devfn))&3)]; \
259 /* Device will not generate interrupt requests. */ \
264 //-----------------------------------------------------------------------------
266 #endif // CYGONCE_PLF_IO_H