• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
pcireg_control_bit_clr(struct pcibus_info * pcibus_info,u64 bits)26 void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
27 {
28 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
42 		}
43 	}
44 }
45 
pcireg_control_bit_set(struct pcibus_info * pcibus_info,u64 bits)46 void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits)
47 {
48 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
62 		}
63 	}
64 }
65 
66 /*
67  * PCI/PCIX Target Flush Register Access -- Read Only		    0000_0050
68  */
pcireg_tflush_get(struct pcibus_info * pcibus_info)69 u64 pcireg_tflush_get(struct pcibus_info *pcibus_info)
70 {
71 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
72 	u64 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 			     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  */
pcireg_intr_status_get(struct pcibus_info * pcibus_info)99 u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info)
100 {
101 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
102 	u64 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 			     ptr);
116 		}
117 	}
118 	return ret;
119 }
120 
121 /*
122  * Interrupt Enable Register Access -- Read/Write                   0000_0108
123  */
pcireg_intr_enable_bit_clr(struct pcibus_info * pcibus_info,u64 bits)124 void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
125 {
126 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
140 		}
141 	}
142 }
143 
pcireg_intr_enable_bit_set(struct pcibus_info * pcibus_info,u64 bits)144 void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits)
145 {
146 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
160 		}
161 	}
162 }
163 
164 /*
165  * Intr Host Address Register (int_addr) -- Read/Write  0000_0130 - 0000_0168
166  */
pcireg_intr_addr_addr_set(struct pcibus_info * pcibus_info,int int_n,u64 addr)167 void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
168 			       u64 addr)
169 {
170 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
190 		}
191 	}
192 }
193 
194 /*
195  * Force Interrupt Register Access -- Write Only	0000_01C0 - 0000_01F8
196  */
pcireg_force_intr_set(struct pcibus_info * pcibus_info,int int_n)197 void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
198 {
199 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
213 		}
214 	}
215 }
216 
217 /*
218  * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
219  */
pcireg_wrb_flush_get(struct pcibus_info * pcibus_info,int device)220 u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
221 {
222 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
223 	u64 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", ptr);
237 		}
238 
239 	}
240 	/* Read of the Write Buffer Flush should always return zero */
241 	return ret;
242 }
243 
pcireg_int_ate_set(struct pcibus_info * pcibus_info,int ate_index,u64 val)244 void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
245 			u64 val)
246 {
247 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)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 			     ptr);
261 		}
262 	}
263 }
264 
pcireg_int_ate_addr(struct pcibus_info * pcibus_info,int ate_index)265 u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
266 {
267 	union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
268 	u64 __iomem *ret = NULL;
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 			     ptr);
282 		}
283 	}
284 	return ret;
285 }
286