nidas  v1.2-1520
isa_bus.h
Go to the documentation of this file.
1 /* -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8; -*- */
2 /* vim: set shiftwidth=8 softtabstop=8 expandtab: */
3 /*
4  ********************************************************************
5  ** NIDAS: NCAR In-situ Data Acquistion Software
6  **
7  ** 2007, Copyright University Corporation for Atmospheric Research
8  **
9  ** This program is free software; you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation; either version 2 of the License, or
12  ** (at your option) any later version.
13  **
14  ** This program is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** The LICENSE.txt file accompanying this software contains
20  ** a copy of the GNU General Public License. If it is not found,
21  ** write to the Free Software Foundation, Inc.,
22  ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  **
24  ********************************************************************
25 */
26 /*
27 
28  Macros needed for ISA drivers to get the right ioport addresses
29  and IRQs on various processors.
30 */
31 
32 #ifndef NIDAS_LINUX_ISA_BUS_H
33 #define NIDAS_LINUX_ISA_BUS_H
34 
35 #ifdef __KERNEL__
36 
37 #ifdef CONFIG_ARCH_VIPER /* Arcom Viper */
38 
39 #include <linux/version.h>
40 
41 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
42 #include <mach/irqs.h>
43 #include <mach/viper.h>
44 #else
45 #include <asm/arch/viper.h>
46 #endif
47 
48 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,16,0)
49 #define SYSTEM_ISA_IOPORT_BASE 0
50 #elif defined(VIPER_PC104IO_BASE)
51 #define SYSTEM_ISA_IOPORT_BASE ((unsigned long)VIPER_PC104IO_BASE)
52 #endif
53 
54 #define SYSTEM_ISA_IOMEM_BASE 0x3c000000
55 
56 #define ISA_16BIT_ADDR_OFFSET 0
57 /*
58  * Special versions of 16 bit I/O operations, that can an address
59  * offset as necessary on a given CPU. See VULCAN section below.
60  * Offset is not needed on VIPER.
61  */
62 #define inw_16o(a) inw(a)
63 #define insw_16o(a,p,n) insw(a,p,n)
64 #define outw_16o(v,a) outw(v,a)
65 
66 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
67 /* In earlier kernels the viper maps ISA irqs
68  * 3,4,5,6,7,10,11,12,9,14,15 to system interrupts
69  * VIPER_IRQ(0)+0,+1, etc.
70  * Note that 9 is out of order, and 1,2,8 and 13 aren't available.
71  * ISA interrupts 9,14 and 15 are only supported on version 2 Vipers.
72  *
73  * VIPER_IRQ(0) is 104 for kernel 2.6.16, so the above irqs are
74  * mapped to interrupts 104-114.
75  * VIPER_IRQ(0) is 108 for kernel 2.6.21, so the above irqs are
76  * mapped to interrupts 108-118.
77  *
78  * VIPER_IRQ(0)+n are not actual hardware interrupt lines.
79  *
80  * All the ISA interrupts are multiplexed by CPLD code into actual
81  * GPIO interrupt GPIO1=VIPER_CPLD_IRQ. The handler for that interrupt
82  * then calls the interrupt handlers for the PC104 interrupts based on the
83  * bits set in the PC104 interrupt status register.
84  * See <linux_2.6_source>/arch/arm/mach-pxa/viper.c.
85  * Return -1 if interrupt is not available.
86  */
87 #define GET_SYSTEM_ISA_IRQ(x) \
88 ({ \
89  const int irq_map[] = { -1, -1, -1, \
90  VIPER_IRQ(0)+0, \
91  VIPER_IRQ(0)+1, \
92  VIPER_IRQ(0)+2, \
93  VIPER_IRQ(0)+3, \
94  VIPER_IRQ(0)+4, \
95  -1, \
96  VIPER_IRQ(0)+8, \
97  VIPER_IRQ(0)+5, \
98  VIPER_IRQ(0)+6, \
99  VIPER_IRQ(0)+7, \
100  -1, \
101  VIPER_IRQ(0)+9, \
102  VIPER_IRQ(0)+10, \
103  }; \
104  int n = -1; \
105  if ((x) >= 0 && (x) < sizeof(irq_map)/sizeof(irq_map[0])) \
106  n = irq_map[(x)]; \
107  n; \
108 })
109 
110 #else
111 
112 /* Starting in kernel 2.6.35 the viper maps ISA irq 3,4,5,...
113  * to system irqs 3,4,5,... How about that! Simple.
114  * PXA_ISA_IRQ(0) is 0.
115  * See linux-source_2.6.35.../arch/arm/mach-pxa/viper.c.
116  * Return -1 if interrupt is not available.
117  */
118 #define GET_SYSTEM_ISA_IRQ(x) \
119 ({ \
120  const int irq_map[] = { -1, -1, -1, \
121  PXA_ISA_IRQ(0)+3, /* PC104 IRQ 3 */ \
122  PXA_ISA_IRQ(0)+4, /* PC104 IRQ 4 */ \
123  PXA_ISA_IRQ(0)+5, /* PC104 IRQ 5 */ \
124  PXA_ISA_IRQ(0)+6, /* PC104 IRQ 6 */ \
125  PXA_ISA_IRQ(0)+7, /* PC104 IRQ 7 */ \
126  -1, \
127  PXA_ISA_IRQ(0)+9, /* PC104 IRQ 9 */ \
128  PXA_ISA_IRQ(0)+10, /* PC104 IRQ 10 */ \
129  PXA_ISA_IRQ(0)+11, /* PC104 IRQ 11 */ \
130  PXA_ISA_IRQ(0)+12, /* PC104 IRQ 12 */ \
131  -1, \
132  PXA_ISA_IRQ(0)+14, /* PC104 IRQ 14 */ \
133  PXA_ISA_IRQ(0)+15, /* PC104 IRQ 15 */ \
134  }; \
135  int n = -1; \
136  if ((x) >= 0 && (x) < sizeof(irq_map)/sizeof(irq_map[0])) \
137  n = irq_map[(x)]; \
138  n; \
139 })
140 
141 #endif
142 
143 #elif defined(CONFIG_MACH_ARCOM_MERCURY) || defined(CONFIG_MACH_ARCOM_VULCAN) /* Arcom Mercury (or Vulcan) */
144 
145 #include <asm/irq.h>
146 #define SYSTEM_ISA_IOPORT_BASE 0x0
147 #define SYSTEM_ISA_IOMEM_BASE 0x049000000 /* 8 bit memory space. 16 bit is at 0x4a000000 */
148 
149 /*
150  * On VULCANs I/O window 1 of the PCI1520 bridge chip is configured for 16 bit
151  * accesses, and starts at address 0x1000. 0x1000 is subtracted from addresses
152  * that are placed on the ISA bus, so that if an outw/inw is done to address 0x1XXX
153  * the address on the PC104 bus will be 0x0XXX.
154  */
155 #define ISA_16BIT_ADDR_OFFSET 0x1000
156 
157 /*
158  * Add 0x1000 to addresses on VULCANs for 16 bit operations, so they
159  * happen in I/O window 1 on the PCI1520, which is configured
160  * for 16 bit accesses.
161  */
162 #define inw_16o(a) inw((a) + ISA_16BIT_ADDR_OFFSET )
163 #define insw_16o(a,p,n) insw((a) + ISA_16BIT_ADDR_OFFSET ,p,n)
164 #define outw_16o(v,a) outw(v,(a) + ISA_16BIT_ADDR_OFFSET )
165 
166 /*
167  * On the Mercury/Vulcan, most of the ISA interrupts are routed to GPIO
168  * pins on the processor. Handle those mappings here.
169  * Return -1 if interrupt is not available.
170  */
171 #define GET_SYSTEM_ISA_IRQ(x) \
172 ({ \
173  const int irq_map[] = { -1, -1, -1, IRQ_IXP4XX_GPIO5, IRQ_IXP4XX_GPIO6,\
174  IRQ_IXP4XX_GPIO7, IRQ_IXP4XX_GPIO8, \
175  IRQ_IXP4XX_GPIO9, -1, -1, IRQ_IXP4XX_GPIO10,\
176  IRQ_IXP4XX_GPIO11, IRQ_IXP4XX_GPIO12}; \
177  int n = -1; \
178  if ((x) >= 0 && (x) < sizeof(irq_map)/sizeof(irq_map[0])) \
179  n = irq_map[(x)]; \
180  n; \
181 })
182 
183 #elif defined(CONFIG_MACH_ARCOM_TITAN) /* Arcom Titan */
184 
185 #include <linux/version.h>
186 
187 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
188 #include <mach/irqs.h>
189 #include <mach/titan.h>
190 #else
191 #include <asm/arch/titan.h>
192 #endif
193 
194 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,16,0)
195 #define SYSTEM_ISA_IOPORT_BASE 0
196 #elif defined(TITAN_PC104IO_BASE)
197 #define SYSTEM_ISA_IOPORT_BASE ((unsigned long)TITAN_PC104IO_BASE)
198 #elif defined(TITAN_PC104IO_VIRT)
199 #define SYSTEM_ISA_IOPORT_BASE ((unsigned long)TITAN_PC104IO_VIRT)
200 #endif
201 
202 #define SYSTEM_ISA_IOMEM_BASE 0x3c000000
203 
204 #define ISA_16BIT_ADDR_OFFSET 0
205 /*
206  * Special versions of 16 bit I/O operations, that add an address
207  * offset as necessary on a given CPU. See VULCAN section.
208  * Offset is not needed on a Titan
209  */
210 #define inw_16o(a) inw(a)
211 #define insw_16o(a,p,n) insw(a,p,n)
212 #define outw_16o(v,a) outw(v,a)
213 
214 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
215 /* The titan maps ISA irqs 3,4,5,... to system irqs 3,4,5,...
216  * PXA_ISA_IRQ(0) is 0.
217  */
218 #define GET_SYSTEM_ISA_IRQ(x) \
219 ({ \
220  const int irq_map[] = { -1, -1, -1, \
221  PXA_ISA_IRQ(0)+3, /* PC104 IRQ 3 */ \
222  PXA_ISA_IRQ(0)+4, /* PC104 IRQ 4 */ \
223  PXA_ISA_IRQ(0)+5, /* PC104 IRQ 5 */ \
224  PXA_ISA_IRQ(0)+6, /* PC104 IRQ 6 */ \
225  PXA_ISA_IRQ(0)+7, /* PC104 IRQ 7 */ \
226  -1, \
227  PXA_ISA_IRQ(0)+9, /* PC104 IRQ 9 */ \
228  PXA_ISA_IRQ(0)+10, /* PC104 IRQ 10 */ \
229  PXA_ISA_IRQ(0)+11, /* PC104 IRQ 11 */ \
230  PXA_ISA_IRQ(0)+12, /* PC104 IRQ 12 */ \
231  -1, \
232  PXA_ISA_IRQ(0)+14, /* PC104 IRQ 14 */ \
233  PXA_ISA_IRQ(0)+15, /* PC104 IRQ 15 */ \
234  }; \
235  int n = -1; \
236  if ((x) >= 0 && (x) < sizeof(irq_map)/sizeof(irq_map[0])) \
237  n = irq_map[(x)]; \
238  n; \
239 })
240 #else
241 /* Different irq mapping in older kernels. TITAN_IRQ is 160.
242  * 3,4,5,6,7,10,11,12 are mapped to 160-167
243  */
244 #define GET_SYSTEM_ISA_IRQ(x) \
245 ({ \
246  const int irq_map[] = { -1, -1, -1, \
247  TITAN_IRQ(0)+0, /* PC104 IRQ 3 */ \
248  TITAN_IRQ(0)+1, /* PC104 IRQ 4 */ \
249  TITAN_IRQ(0)+2, /* PC104 IRQ 5 */ \
250  TITAN_IRQ(0)+3, /* PC104 IRQ 6 */ \
251  TITAN_IRQ(0)+4, /* PC104 IRQ 7 */ \
252  -1, \
253  -1, /* PC104 IRQ 9 */ \
254  TITAN_IRQ(0)+5, /* PC104 IRQ 10 */ \
255  TITAN_IRQ(0)+6, /* PC104 IRQ 11 */ \
256  TITAN_IRQ(0)+7, /* PC104 IRQ 12 */ \
257  -1, \
258  -1, /* PC104 IRQ 14 */ \
259  -1, /* PC104 IRQ 15 */ \
260  }; \
261  int n = -1; \
262  if ((x) >= 0 && (x) < sizeof(irq_map)/sizeof(irq_map[0])) \
263  n = irq_map[(x)]; \
264  n; \
265 })
266 
267 #endif
268 
269 #else /* nothing machine/architecture specific */
270 
271 #define SYSTEM_ISA_IOPORT_BASE 0x0
272 #define SYSTEM_ISA_IOMEM_BASE 0x0
273 #define GET_SYSTEM_ISA_IRQ(x) (x)
274 
275 #define ISA_16BIT_ADDR_OFFSET 0
276 #define inw_16o(a) inw(a)
277 #define insw_16o(a,p,n) insw(a,p,n)
278 #define outw_16o(v,a) outw(v,a)
279 
280 #endif
281 
282 #endif
283 
284 #endif