[IA64] altix: misc pci interrupt related fixes
[linux-2.6.git] / arch / ia64 / sn / pci / pcibr / pcibr_reg.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/interrupt.h>
10 #include <linux/types.h>
11 #include <asm/sn/io.h>
12 #include <asm/sn/pcibr_provider.h>
13 #include <asm/sn/pcibus_provider_defs.h>
14 #include <asm/sn/pcidev.h>
15 #include <asm/sn/pic.h>
16 #include <asm/sn/tiocp.h>
17
18 union br_ptr {
19         struct tiocp tio;
20         struct pic pic;
21 };
22
23 /*
24  * Control Register Access -- Read/Write                            0000_0020
25  */
26 void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
27 {
28         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
29
30         if (pcibus_info) {
31                 switch (pcibus_info->pbi_bridge_type) {
32                 case PCIBR_BRIDGETYPE_TIOCP:
33                         __sn_clrq_relaxed(&ptr->tio.cp_control, bits);
34                         break;
35                 case PCIBR_BRIDGETYPE_PIC:
36                         __sn_clrq_relaxed(&ptr->pic.p_wid_control, bits);
37                         break;
38                 default:
39                         panic
40                             ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p",
41                              (void *)ptr);
42                 }
43         }
44 }
45
46 void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
47 {
48         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
49
50         if (pcibus_info) {
51                 switch (pcibus_info->pbi_bridge_type) {
52                 case PCIBR_BRIDGETYPE_TIOCP:
53                         __sn_setq_relaxed(&ptr->tio.cp_control, bits);
54                         break;
55                 case PCIBR_BRIDGETYPE_PIC:
56                         __sn_setq_relaxed(&ptr->pic.p_wid_control, bits);
57                         break;
58                 default:
59                         panic
60                             ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p",
61                              (void *)ptr);
62                 }
63         }
64 }
65
66 /*
67  * PCI/PCIX Target Flush Register Access -- Read Only               0000_0050
68  */
69 uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
70 {
71         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
72         uint64_t ret = 0;
73
74         if (pcibus_info) {
75                 switch (pcibus_info->pbi_bridge_type) {
76                 case PCIBR_BRIDGETYPE_TIOCP:
77                         ret = __sn_readq_relaxed(&ptr->tio.cp_tflush);
78                         break;
79                 case PCIBR_BRIDGETYPE_PIC:
80                         ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush);
81                         break;
82                 default:
83                         panic
84                             ("pcireg_tflush_get: unknown bridgetype bridge 0x%p",
85                              (void *)ptr);
86                 }
87         }
88
89         /* Read of the Target Flush should always return zero */
90         if (ret != 0)
91                 panic("pcireg_tflush_get:Target Flush failed\n");
92
93         return ret;
94 }
95
96 /*
97  * Interrupt Status Register Access -- Read Only                    0000_0100
98  */
99 uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
100 {
101         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
102         uint64_t ret = 0;
103
104         if (pcibus_info) {
105                 switch (pcibus_info->pbi_bridge_type) {
106                 case PCIBR_BRIDGETYPE_TIOCP:
107                         ret = __sn_readq_relaxed(&ptr->tio.cp_int_status);
108                         break;
109                 case PCIBR_BRIDGETYPE_PIC:
110                         ret = __sn_readq_relaxed(&ptr->pic.p_int_status);
111                         break;
112                 default:
113                         panic
114                             ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p",
115                              (void *)ptr);
116                 }
117         }
118         return ret;
119 }
120
121 /*
122  * Interrupt Enable Register Access -- Read/Write                   0000_0108
123  */
124 void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
125 {
126         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
127
128         if (pcibus_info) {
129                 switch (pcibus_info->pbi_bridge_type) {
130                 case PCIBR_BRIDGETYPE_TIOCP:
131                         __sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits);
132                         break;
133                 case PCIBR_BRIDGETYPE_PIC:
134                         __sn_clrq_relaxed(&ptr->pic.p_int_enable, bits);
135                         break;
136                 default:
137                         panic
138                             ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p",
139                              (void *)ptr);
140                 }
141         }
142 }
143
144 void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
145 {
146         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
147
148         if (pcibus_info) {
149                 switch (pcibus_info->pbi_bridge_type) {
150                 case PCIBR_BRIDGETYPE_TIOCP:
151                         __sn_setq_relaxed(&ptr->tio.cp_int_enable, bits);
152                         break;
153                 case PCIBR_BRIDGETYPE_PIC:
154                         __sn_setq_relaxed(&ptr->pic.p_int_enable, bits);
155                         break;
156                 default:
157                         panic
158                             ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p",
159                              (void *)ptr);
160                 }
161         }
162 }
163
164 /*
165  * Intr Host Address Register (int_addr) -- Read/Write  0000_0130 - 0000_0168
166  */
167 void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
168                                uint64_t addr)
169 {
170         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
171
172         if (pcibus_info) {
173                 switch (pcibus_info->pbi_bridge_type) {
174                 case PCIBR_BRIDGETYPE_TIOCP:
175                         __sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n],
176                             TIOCP_HOST_INTR_ADDR);
177                         __sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n],
178                             (addr & TIOCP_HOST_INTR_ADDR));
179                         break;
180                 case PCIBR_BRIDGETYPE_PIC:
181                         __sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n],
182                             PIC_HOST_INTR_ADDR);
183                         __sn_setq_relaxed(&ptr->pic.p_int_addr[int_n],
184                             (addr & PIC_HOST_INTR_ADDR));
185                         break;
186                 default:
187                         panic
188                             ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p",
189                              (void *)ptr);
190                 }
191         }
192 }
193
194 /*
195  * Force Interrupt Register Access -- Write Only        0000_01C0 - 0000_01F8
196  */
197 void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
198 {
199         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
200
201         if (pcibus_info) {
202                 switch (pcibus_info->pbi_bridge_type) {
203                 case PCIBR_BRIDGETYPE_TIOCP:
204                         writeq(1, &ptr->tio.cp_force_pin[int_n]);
205                         break;
206                 case PCIBR_BRIDGETYPE_PIC:
207                         writeq(1, &ptr->pic.p_force_pin[int_n]);
208                         break;
209                 default:
210                         panic
211                             ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p",
212                              (void *)ptr);
213                 }
214         }
215 }
216
217 /*
218  * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
219  */
220 uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
221 {
222         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
223         uint64_t ret = 0;
224
225         if (pcibus_info) {
226                 switch (pcibus_info->pbi_bridge_type) {
227                 case PCIBR_BRIDGETYPE_TIOCP:
228                         ret =
229                             __sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]);
230                         break;
231                 case PCIBR_BRIDGETYPE_PIC:
232                         ret =
233                             __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
234                         break;
235                 default:
236                       panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", (void *)ptr);
237                 }
238
239         }
240         /* Read of the Write Buffer Flush should always return zero */
241         return ret;
242 }
243
244 void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
245                         uint64_t val)
246 {
247         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
248
249         if (pcibus_info) {
250                 switch (pcibus_info->pbi_bridge_type) {
251                 case PCIBR_BRIDGETYPE_TIOCP:
252                         writeq(val, &ptr->tio.cp_int_ate_ram[ate_index]);
253                         break;
254                 case PCIBR_BRIDGETYPE_PIC:
255                         writeq(val, &ptr->pic.p_int_ate_ram[ate_index]);
256                         break;
257                 default:
258                         panic
259                             ("pcireg_int_ate_set: unknown bridgetype bridge 0x%p",
260                              (void *)ptr);
261                 }
262         }
263 }
264
265 uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
266 {
267         union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base;
268         uint64_t *ret = (uint64_t *) 0;
269
270         if (pcibus_info) {
271                 switch (pcibus_info->pbi_bridge_type) {
272                 case PCIBR_BRIDGETYPE_TIOCP:
273                         ret = &ptr->tio.cp_int_ate_ram[ate_index];
274                         break;
275                 case PCIBR_BRIDGETYPE_PIC:
276                         ret = &ptr->pic.p_int_ate_ram[ate_index];
277                         break;
278                 default:
279                         panic
280                             ("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p",
281                              (void *)ptr);
282                 }
283         }
284         return ret;
285 }