]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/integrator/v2_0/include/plf_io.h
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / integrator / v2_0 / include / plf_io.h
1 #ifndef CYGONCE_PLF_IO_H
2 #define CYGONCE_PLF_IO_H
3
4 //=============================================================================
5 //
6 //      plf_io.h
7 //
8 //      Platform specific IO support
9 //
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.
15 //
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.
19 //
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
23 // for more details.
24 //
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.
28 //
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.
35 //
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.
38 //
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####
45 //
46 // Author(s):    Philippe Robin
47 // Contributors: David A Rusling
48 // Date:         November 7, 2000
49 // Purpose:      Integrator PCI IO support macros
50 // Description: 
51 // Usage:        #include <cyg/hal/plf_io.h>
52 //
53 //####DESCRIPTIONEND####
54 //
55 //=============================================================================
56
57 #include <pkgconf/hal_arm_integrator.h>
58
59 #include <cyg/hal/hal_integrator.h>
60
61 #include <cyg/hal/hal_platform_ints.h>  // Interrupt vectors
62
63 __externC void cyg_plf_pci_init(void);
64
65 // Initialization of the PCI bus.
66 #define HAL_PCI_INIT() cyg_plf_pci_init()
67
68
69 // V3 access routines
70 #define _V3Write16(o,v) (*(volatile cyg_uint16 *)(PCI_V3_BASE + (cyg_uint32)(o)) \
71                                          = (cyg_uint16)(v))
72 #define _V3Read16(o)    (*(volatile cyg_uint16 *)(PCI_V3_BASE + (cyg_uint32)(o)))
73
74 #define _V3Write32(o,v) (*(volatile cyg_uint32 *)(PCI_V3_BASE + (cyg_uint32)(o)) \
75                                         = (cyg_uint32)(v))
76 #define _V3Read32(o)    (*(volatile cyg_uint32 *)(PCI_V3_BASE + (cyg_uint32)(o)))
77
78 // _V3OpenConfigWindow - open V3 configuration window
79 #define _V3OpenConfigWindow()                                                   \
80     {                                                                           \
81     /* Set up base0 to see all 512Mbytes of memory space (not        */         \
82     /* prefetchable), this frees up base1 for re-use by configuration*/         \
83     /* memory */                                                                \
84                                                                                 \
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(). */                         \
89                                                                                 \
90     _V3Write32 (V3_LB_BASE1, ((CPU_PCI_CNFG_ADRS & 0xFFF00000) |                \
91                              0x40 | V3_LB_BASE_M_ENABLE));                      \
92     }
93
94 // _V3CloseConfigWindow - close V3 configuration window
95 #define _V3CloseConfigWindow()                                                  \
96     {                                                                           \
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);   \
102                                                                                 \
103     /* And shrink base0 back to a 256M window (NOTE: MAP0 already correct) */   \
104                                                                                 \
105     _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) |              \
106                              0x80 | V3_LB_BASE_M_ENABLE));                      \
107     }
108
109 // Compute address necessary to access PCI config space for the given
110 // bus and device.
111 #define HAL_PCI_CONFIG_ADDRESS( __bus, __devfn, __offset ) \
112     ({                                                                                  \
113     cyg_uint32 __address, __devicebit;                                                  \
114     cyg_uint16 __mapaddress;                                                            \
115     cyg_uint32 __dev = CYG_PCI_DEV_GET_DEV(__devfn);    /* FIXME to check!! (slot?) */  \
116                                                                                         \
117     if (__bus == 0) {                                                                   \
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));                                              \
125                                                                                         \
126         if ((__devicebit & 0xFF000000) != 0) {                                          \
127             /* high order bits are handled by the MAP register */                       \
128             __mapaddress |= (__devicebit >> 16);                                        \
129         } else {                                                                        \
130             /* low order bits handled directly in the address */                        \
131             __address |= __devicebit;                                                   \
132         }                                                                               \
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*/      \
142     }                                                                                   \
143     _V3Write16(V3_LB_MAP1, __mapaddress);                                               \
144                                                                                         \
145     __address;                                                                          \
146     })
147
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 )               \
151     {                                                                           \
152     _V3OpenConfigWindow();                                                      \
153     __val = *(volatile cyg_uint8 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset);    \
154     _V3CloseConfigWindow();                                                     \
155     }
156
157 #define HAL_PCI_CFG_READ_UINT16( __bus, __devfn, __offset, __val )              \
158     {                                                                           \
159     _V3OpenConfigWindow();                                                      \
160     __val = *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset);   \
161     _V3CloseConfigWindow();                                                     \
162     }
163
164 #define HAL_PCI_CFG_READ_UINT32( __bus, __devfn, __offset, __val )                      \
165     {                                                                                   \
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();                                                             \
170     }
171
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 )              \
175     {                                                                           \
176     _V3OpenConfigWindow();                                                      \
177     *(volatile cyg_uint8 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val;    \
178     _V3CloseConfigWindow();                                                     \
179     }
180
181 #define HAL_PCI_CFG_WRITE_UINT16( __bus, __devfn, __offset, __val )             \
182     {                                                                           \
183     _V3OpenConfigWindow();                                                      \
184     *(volatile cyg_uint16 *)HAL_PCI_CONFIG_ADDRESS(__bus, __devfn, __offset) = __val;   \
185     _V3CloseConfigWindow();                                                     \
186     }
187
188 #define HAL_PCI_CFG_WRITE_UINT32( __bus, __devfn, __offset, __val )                                       \
189     {                                                                                                     \
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();                                                                               \
194     }
195
196 //-----------------------------------------------------------------------------
197 // Resources
198
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
202
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)
206
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
213
214 #define HAL_PCI_TRANSLATE_INTERRUPT( __bus, __devfn, __vec, __valid)          \
215     CYG_MACRO_START                                                           \
216     cyg_uint8 __req;                                                          \
217     cyg_uint32 __dev;                                                         \
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 */            \
233     };                                                                        \
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?)*/ \
236                                                                               \
237     /* if PIN = 0, default to A */                                            \
238     if (__req == 0)                                                           \
239         __req = 1;                                                            \
240                                                                               \
241     __vec = irq_tab[__dev - 9][__req - 1];                                    \
242     __valid = true;                                                           \
243     CYG_MACRO_END
244
245 //-----------------------------------------------------------------------------
246
247 #define CYGARC_PHYSICAL_ADDRESS(x) (x)
248
249 //-----------------------------------------------------------------------------
250 // end of plf_io.h
251 #endif // CYGONCE_PLF_IO_H