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