pq3pci.c revision 1.6 1 1.6 dyoung /* $NetBSD: pq3pci.c,v 1.6 2011/05/17 17:34:51 dyoung Exp $ */
2 1.2 matt /*-
3 1.2 matt * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 1.2 matt * All rights reserved.
5 1.2 matt *
6 1.2 matt * This code is derived from software contributed to The NetBSD Foundation
7 1.2 matt * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 1.2 matt * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 1.2 matt *
10 1.2 matt * This material is based upon work supported by the Defense Advanced Research
11 1.2 matt * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 1.2 matt * Contract No. N66001-09-C-2073.
13 1.2 matt * Approved for Public Release, Distribution Unlimited
14 1.2 matt *
15 1.2 matt * Redistribution and use in source and binary forms, with or without
16 1.2 matt * modification, are permitted provided that the following conditions
17 1.2 matt * are met:
18 1.2 matt * 1. Redistributions of source code must retain the above copyright
19 1.2 matt * notice, this list of conditions and the following disclaimer.
20 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright
21 1.2 matt * notice, this list of conditions and the following disclaimer in the
22 1.2 matt * documentation and/or other materials provided with the distribution.
23 1.2 matt *
24 1.2 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 1.2 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 1.2 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 1.2 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 1.2 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 1.2 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 1.2 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 1.2 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 1.2 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 1.2 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 1.2 matt * POSSIBILITY OF SUCH DAMAGE.
35 1.2 matt */
36 1.2 matt
37 1.2 matt #define PCI_PRIVATE
38 1.2 matt #define GLOBAL_PRIVATE
39 1.2 matt #define __INTR_PRIVATE
40 1.2 matt
41 1.2 matt #include "opt_mpc85xx.h"
42 1.2 matt #include "opt_pci.h"
43 1.2 matt #include "locators.h"
44 1.2 matt
45 1.2 matt #include <sys/cdefs.h>
46 1.2 matt
47 1.6 dyoung __KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.6 2011/05/17 17:34:51 dyoung Exp $");
48 1.2 matt
49 1.2 matt #include <sys/param.h>
50 1.2 matt #include <sys/device.h>
51 1.2 matt #include <sys/cpu.h>
52 1.2 matt #include <sys/intr.h>
53 1.2 matt #include <sys/bus.h>
54 1.2 matt #include <sys/extent.h>
55 1.2 matt #include <sys/bitops.h>
56 1.2 matt #include <sys/kmem.h>
57 1.2 matt #include <sys/malloc.h> /* for extent */
58 1.2 matt
59 1.2 matt #include <dev/pci/pcireg.h>
60 1.2 matt #include <dev/pci/pcivar.h>
61 1.2 matt #include <dev/pci/pciconf.h>
62 1.2 matt #include <dev/pci/pcidevs.h>
63 1.2 matt
64 1.2 matt #include <powerpc/booke/cpuvar.h>
65 1.2 matt #include <powerpc/booke/spr.h>
66 1.2 matt #include <powerpc/booke/e500var.h>
67 1.2 matt #include <powerpc/booke/e500reg.h>
68 1.2 matt #include <powerpc/booke/openpicreg.h>
69 1.2 matt
70 1.2 matt #define PORDEVSR_MPC8536_TRUTH_ENCODE(inst, field, value, result) \
71 1.2 matt TRUTH_ENCODE(SVR_MPC8536v1, inst, PORDEVSR_##field, \
72 1.3 matt __SHIFTIN(field##_##MPC8536##_##value, PORDEVSR_##field), result)
73 1.2 matt #define PORDEVSR_MPC8544_TRUTH_ENCODE(inst, field, value, result) \
74 1.2 matt TRUTH_ENCODE(SVR_MPC8544v1, inst, PORDEVSR_##field, \
75 1.3 matt __SHIFTIN(field##_##MPC8544##_##value, PORDEVSR_##field), result)
76 1.2 matt #define PORDEVSR_MPC8548_TRUTH_ENCODE(inst, field, value, result) \
77 1.2 matt TRUTH_ENCODE(SVR_MPC8548v1, inst, PORDEVSR_##field, \
78 1.3 matt __SHIFTIN(field##_##MPC8548##_##value, PORDEVSR_##field), result)
79 1.2 matt #define PORDEVSR_MPC8555_TRUTH_ENCODE(inst, field, value, result) \
80 1.2 matt TRUTH_ENCODE(SVR_MPC8555v1, inst, PORDEVSR_##field, \
81 1.3 matt __SHIFTIN(field##_##MPC8555##_##value, PORDEVSR_##field), result)
82 1.2 matt #define PORDEVSR_MPC8572_TRUTH_ENCODE(inst, field, value, result) \
83 1.2 matt TRUTH_ENCODE(SVR_MPC8572v1, inst, PORDEVSR_##field, \
84 1.3 matt __SHIFTIN(field##_##MPC8572##_##value, PORDEVSR_##field), result)
85 1.3 matt #define PORDEVSR_P20x0_TRUTH_ENCODE(inst, field, value, result) \
86 1.4 matt TRUTH_ENCODE(SVR_P2020v2, inst, PORDEVSR_##field, \
87 1.3 matt __SHIFTIN(field##_##P20x0##_##value, PORDEVSR_##field), result), \
88 1.4 matt TRUTH_ENCODE(SVR_P2010v2, inst, PORDEVSR_##field, \
89 1.3 matt __SHIFTIN(field##_##P20x0##_##value, PORDEVSR_##field), result)
90 1.2 matt
91 1.2 matt #define PORDEVSR_TRUTH_ENCODE(svr, inst, field, value, result) \
92 1.2 matt TRUTH_ENCODE(svr, inst, PORDEVSR_##field, \
93 1.3 matt __SHIFTIN(field##_##value, PORDEVSR_##field), result)
94 1.2 matt
95 1.2 matt const struct e500_truthtab pq3pci_pcie_lanes[] = {
96 1.2 matt #ifdef MPC8548
97 1.3 matt PORDEVSR_MPC8548_TRUTH_ENCODE(0, IOSEL, SRIO2500_PCIE1_X4, 4),
98 1.3 matt PORDEVSR_MPC8548_TRUTH_ENCODE(0, IOSEL, SRIO1250_PCIE1_X4, 4),
99 1.3 matt PORDEVSR_MPC8548_TRUTH_ENCODE(0, IOSEL, PCIE1_X8, 8),
100 1.2 matt #endif
101 1.2 matt
102 1.2 matt #ifdef MPC8544
103 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(1, IOSEL, PCIE1_ON, 4),
104 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(1, IOSEL, PCIE1_SGMII_ON, 4),
105 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(1, IOSEL, PCIE12_ON, 4),
106 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(1, IOSEL, PCIE12_SGMII_ON, 4),
107 1.2 matt PORDEVSR_MPC8544_TRUTH_ENCODE(1, IOSEL, PCIE123_ON, 4),
108 1.2 matt PORDEVSR_MPC8544_TRUTH_ENCODE(1, IOSEL, PCIE123_SGMII_ON, 4),
109 1.2 matt
110 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(2, IOSEL, PCIE12_ON, 4),
111 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(2, IOSEL, PCIE12_SGMII_ON, 4),
112 1.2 matt PORDEVSR_MPC8544_TRUTH_ENCODE(2, IOSEL, PCIE123_ON, 4),
113 1.2 matt PORDEVSR_MPC8544_TRUTH_ENCODE(2, IOSEL, PCIE123_SGMII_ON, 4),
114 1.2 matt
115 1.3 matt PORDEVSR_MPC8544_TRUTH_ENCODE(3, IOSEL, PCIE123_ON, 1),
116 1.2 matt PORDEVSR_MPC8544_TRUTH_ENCODE(3, IOSEL, PCIE123_SGMII_ON, 1),
117 1.2 matt #endif
118 1.2 matt
119 1.2 matt #ifdef MPC8536
120 1.3 matt PORDEVSR_MPC8536_TRUTH_ENCODE(1, IOSEL, PCIE1_X4, 4),
121 1.3 matt PORDEVSR_MPC8536_TRUTH_ENCODE(1, IOSEL, PCIE1_X8, 8),
122 1.2 matt PORDEVSR_MPC8536_TRUTH_ENCODE(1, IOSEL, PCIE12_X4, 4),
123 1.2 matt PORDEVSR_MPC8536_TRUTH_ENCODE(1, IOSEL, PCIE1_X4_PCI23_X2, 4),
124 1.2 matt
125 1.3 matt PORDEVSR_MPC8536_TRUTH_ENCODE(2, IOSEL, PCIE12_X4, 4),
126 1.2 matt PORDEVSR_MPC8536_TRUTH_ENCODE(2, IOSEL, PCIE1_X4_PCI23_X2, 2),
127 1.2 matt
128 1.2 matt PORDEVSR_MPC8536_TRUTH_ENCODE(3, IOSEL, PCIE1_X4_PCI23_X2, 2),
129 1.2 matt #endif
130 1.2 matt
131 1.2 matt #ifdef MPC8572
132 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(1, IOSEL, SRIO2500_PCIE1_X4, 4),
133 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(1, IOSEL, SRIO1250_PCIE1_X4, 4),
134 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(1, IOSEL, PCIE1_X4, 4),
135 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(1, IOSEL, PCIE12_X4, 4),
136 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(1, IOSEL, PCIE1_X4_23_X2, 4),
137 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(1, IOSEL, PCIE1_X8, 8),
138 1.3 matt
139 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(2, IOSEL, PCIE12_X4, 4),
140 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(2, IOSEL, PCIE1_X4_23_X2, 2),
141 1.3 matt
142 1.3 matt PORDEVSR_MPC8572_TRUTH_ENCODE(3, IOSEL, PCIE1_X4_23_X2, 2),
143 1.3 matt #endif
144 1.3 matt
145 1.3 matt #ifdef P2020
146 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE1_X1, 1),
147 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE12_X1_3_X2, 1),
148 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE13_X2, 2),
149 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE1_X4, 4),
150 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE1_X1_SRIO2500_1X, 1),
151 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE12_X1_SGMII23, 1),
152 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(1, IOSEL, PCIE1_X2_SGMII23, 2),
153 1.2 matt
154 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(2, IOSEL, PCIE12_X1_3_X2, 1),
155 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(2, IOSEL, PCIE12_X1_SGMII23, 1),
156 1.2 matt
157 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(3, IOSEL, PCIE12_X1_3_X2, 2),
158 1.3 matt PORDEVSR_P20x0_TRUTH_ENCODE(3, IOSEL, PCIE13_X2, 2),
159 1.2 matt #endif
160 1.2 matt };
161 1.2 matt
162 1.2 matt static const struct e500_truthtab pq3pci_pci_pcix[] = {
163 1.2 matt #ifdef MPC8548
164 1.3 matt PORDEVSR_TRUTH_ENCODE(SVR_MPC8548v1, 1, PCI1, PCIX, 1),
165 1.2 matt #endif
166 1.2 matt };
167 1.2 matt
168 1.2 matt static const struct e500_truthtab pq3pci_pci_pci32[] = {
169 1.2 matt #ifdef MPC8548
170 1.3 matt PORDEVSR_TRUTH_ENCODE(SVR_MPC8548v1, 1, PCI32, FALSE, 64),
171 1.3 matt PORDEVSR_TRUTH_ENCODE(SVR_MPC8548v1, 1, PCI32, TRUE, 32),
172 1.2 matt #endif
173 1.2 matt
174 1.2 matt #ifdef MPC8555
175 1.3 matt PORDEVSR_TRUTH_ENCODE(SVR_MPC8555v1, 0, PCI32, FALSE, 64),
176 1.3 matt PORDEVSR_TRUTH_ENCODE(SVR_MPC8555v1, 0, PCI32, TRUE, 32),
177 1.2 matt #endif
178 1.2 matt };
179 1.2 matt
180 1.2 matt struct pq3pci_bst {
181 1.2 matt struct powerpc_bus_space bs_tag;
182 1.2 matt char bs_name[16];
183 1.2 matt char bs_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)] __aligned(8);
184 1.2 matt };
185 1.2 matt
186 1.2 matt typedef enum { IH_NONE, IH_INTX, IH_MSI, IH_MSIX } pq3pci_intr_class_t;
187 1.2 matt
188 1.2 matt struct pq3pci_genihand {
189 1.2 matt pq3pci_intr_class_t ih_class;
190 1.2 matt int (*ih_func)(void *);
191 1.2 matt void *ih_arg;
192 1.2 matt struct pq3pci_softc *ih_sc;
193 1.2 matt };
194 1.2 matt
195 1.2 matt struct pq3pci_intrhand {
196 1.2 matt struct pq3pci_genihand pih_ih;
197 1.2 matt SIMPLEQ_ENTRY(pq3pci_intrhand) pih_link;
198 1.2 matt int pih_ipl;
199 1.2 matt struct pq3pci_intrsource *pih_source;
200 1.2 matt uint64_t pih_count;
201 1.2 matt };
202 1.2 matt
203 1.2 matt struct pq3pci_callhand {
204 1.2 matt struct pq3pci_genihand pch_ih;
205 1.2 matt struct callout pch_callout;
206 1.2 matt int pch_ipl;
207 1.2 matt };
208 1.2 matt
209 1.2 matt #define PIH_MAKE(irq, ist, nmsi) (((nmsi) << 20) | ((irq) << 8) | (ist))
210 1.2 matt #define PIH_IST(pih) (((pih) >> 0) & 0xff)
211 1.2 matt #define PIH_IRQ(pih) (((pih) >> 8) & 0xfff)
212 1.2 matt #define PIH_NMSI(pih) (((pih) >> 20) & 0xff)
213 1.2 matt
214 1.2 matt struct pq3pci_intrsource {
215 1.2 matt SIMPLEQ_ENTRY(pq3pci_intrsource) pis_link;
216 1.2 matt SIMPLEQ_HEAD(,pq3pci_intrhand) pis_ihands;
217 1.2 matt struct evcnt pis_ev;
218 1.2 matt struct evcnt pis_ev_spurious;
219 1.2 matt kmutex_t *pis_lock;
220 1.2 matt pci_intr_handle_t pis_handle;
221 1.2 matt void *pis_ih;
222 1.2 matt };
223 1.2 matt
224 1.2 matt struct pq3pci_msihand {
225 1.2 matt struct pq3pci_genihand msih_ih;
226 1.2 matt struct pq3pci_msigroup *msih_group;
227 1.2 matt struct evcnt msih_ev;
228 1.2 matt struct evcnt msih_ev_spurious;
229 1.2 matt pcitag_t msih_tag;
230 1.2 matt int msih_msioff;
231 1.2 matt };
232 1.2 matt
233 1.2 matt struct pq3pci_msigroup {
234 1.2 matt kmutex_t *msig_lock;
235 1.2 matt void *msig_ih;
236 1.2 matt uint32_t msig_free_mask;
237 1.2 matt int msig_ipl;
238 1.2 matt u_int msig_group;
239 1.2 matt bus_size_t msig_msir;
240 1.2 matt struct pq3pci_msihand msig_ihands[32];
241 1.2 matt };
242 1.2 matt
243 1.2 matt struct pq3pci_softc {
244 1.2 matt device_t sc_dev;
245 1.2 matt bus_space_tag_t sc_bst;
246 1.2 matt bus_space_handle_t sc_bsh;
247 1.2 matt void *sc_ih;
248 1.2 matt bool sc_pcie;
249 1.2 matt struct genppc_pci_chipset sc_pc;
250 1.2 matt struct pq3pci_bst sc_pci_io_bst;
251 1.2 matt struct pq3pci_bst sc_pci_mem_bst;
252 1.2 matt u_int sc_pba_flags;
253 1.2 matt kmutex_t *sc_conf_lock;
254 1.2 matt kmutex_t *sc_intr_lock;
255 1.2 matt struct evcnt sc_ev_spurious;
256 1.2 matt prop_dictionary_t sc_intrmap;
257 1.2 matt uint32_t sc_intrmask;
258 1.2 matt };
259 1.2 matt
260 1.2 matt static int pq3pci_cpunode_match(device_t, cfdata_t, void *aux);
261 1.2 matt static void pq3pci_cpunode_attach(device_t, device_t, void *aux);
262 1.2 matt static pci_chipset_tag_t pq3pci_pci_chipset_init(struct pq3pci_softc *);
263 1.2 matt
264 1.2 matt static SIMPLEQ_HEAD(,pq3pci_intrsource) pq3pci_intrsources
265 1.2 matt = SIMPLEQ_HEAD_INITIALIZER(pq3pci_intrsources);
266 1.2 matt static struct pq3pci_msigroup *pq3pci_msigroups[8];
267 1.2 matt
268 1.2 matt static struct pq3pci_intrsource *
269 1.2 matt pq3pci_intr_source_lookup(struct pq3pci_softc *, pci_intr_handle_t);
270 1.2 matt
271 1.2 matt static const char msi_intr_names[8][32][8] = {
272 1.2 matt {
273 1.2 matt "msi 0", "msi 1", "msi 2", "msi 3",
274 1.2 matt "msi 4", "msi 5", "msi 6", "msi 7",
275 1.2 matt "msi 8", "msi 9", "msi 10", "msi 11",
276 1.2 matt "msi 12", "msi 13", "msi 14", "msi 15",
277 1.2 matt "msi 16", "msi 17", "msi 18", "msi 19",
278 1.2 matt "msi 20", "msi 21", "msi 22", "msi 23",
279 1.2 matt "msi 24", "msi 25", "msi 26", "msi 27",
280 1.2 matt "msi 28", "msi 29", "msi 30", "msi 31",
281 1.2 matt }, {
282 1.2 matt "msi 32", "msi 33", "msi 34", "msi 35",
283 1.2 matt "msi 36", "msi 37", "msi 38", "msi 39",
284 1.2 matt "msi 40", "msi 41", "msi 42", "msi 43",
285 1.2 matt "msi 44", "msi 45", "msi 46", "msi 47",
286 1.2 matt "msi 48", "msi 49", "msi 50", "msi 51",
287 1.2 matt "msi 52", "msi 53", "msi 54", "msi 55",
288 1.2 matt "msi 56", "msi 57", "msi 58", "msi 59",
289 1.2 matt "msi 60", "msi 61", "msi 62", "msi 63",
290 1.2 matt }, {
291 1.2 matt "msi 64", "msi 65", "msi 66", "msi 67",
292 1.2 matt "msi 68", "msi 69", "msi 70", "msi 71",
293 1.2 matt "msi 72", "msi 73", "msi 74", "msi 75",
294 1.2 matt "msi 76", "msi 77", "msi 78", "msi 79",
295 1.2 matt "msi 80", "msi 81", "msi 82", "msi 83",
296 1.2 matt "msi 84", "msi 85", "msi 86", "msi 87",
297 1.2 matt "msi 88", "msi 89", "msi 90", "msi 91",
298 1.2 matt "msi 92", "msi 93", "msi 94", "msi 95",
299 1.2 matt }, {
300 1.2 matt "msi 96", "msi 97", "msi 98", "msi 99",
301 1.2 matt "msi 100", "msi 101", "msi 102", "msi 103",
302 1.2 matt "msi 104", "msi 105", "msi 106", "msi 107",
303 1.2 matt "msi 108", "msi 109", "msi 110", "msi 111",
304 1.2 matt "msi 112", "msi 113", "msi 114", "msi 115",
305 1.2 matt "msi 116", "msi 117", "msi 118", "msi 119",
306 1.2 matt "msi 120", "msi 121", "msi 122", "msi 123",
307 1.2 matt "msi 124", "msi 125", "msi 126", "msi 127",
308 1.2 matt }, {
309 1.2 matt "msi 128", "msi 129", "msi 130", "msi 131",
310 1.2 matt "msi 132", "msi 133", "msi 134", "msi 135",
311 1.2 matt "msi 136", "msi 137", "msi 138", "msi 139",
312 1.2 matt "msi 140", "msi 141", "msi 142", "msi 143",
313 1.2 matt "msi 144", "msi 145", "msi 146", "msi 147",
314 1.2 matt "msi 148", "msi 149", "msi 150", "msi 151",
315 1.2 matt "msi 152", "msi 153", "msi 154", "msi 155",
316 1.2 matt "msi 156", "msi 157", "msi 158", "msi 159",
317 1.2 matt }, {
318 1.2 matt "msi 160", "msi 161", "msi 162", "msi 163",
319 1.2 matt "msi 164", "msi 165", "msi 166", "msi 167",
320 1.2 matt "msi 168", "msi 169", "msi 170", "msi 171",
321 1.2 matt "msi 172", "msi 173", "msi 174", "msi 175",
322 1.2 matt "msi 176", "msi 177", "msi 178", "msi 179",
323 1.2 matt "msi 180", "msi 181", "msi 182", "msi 183",
324 1.2 matt "msi 184", "msi 185", "msi 186", "msi 187",
325 1.2 matt "msi 188", "msi 189", "msi 190", "msi 191",
326 1.2 matt }, {
327 1.2 matt "msi 192", "msi 193", "msi 194", "msi 195",
328 1.2 matt "msi 196", "msi 197", "msi 198", "msi 199",
329 1.2 matt "msi 200", "msi 201", "msi 202", "msi 203",
330 1.2 matt "msi 204", "msi 205", "msi 206", "msi 207",
331 1.2 matt "msi 208", "msi 209", "msi 210", "msi 211",
332 1.2 matt "msi 212", "msi 213", "msi 214", "msi 215",
333 1.2 matt "msi 216", "msi 217", "msi 218", "msi 219",
334 1.2 matt "msi 220", "msi 221", "msi 222", "msi 223",
335 1.2 matt }, {
336 1.2 matt "msi 224", "msi 225", "msi 226", "msi 227",
337 1.2 matt "msi 228", "msi 229", "msi 230", "msi 231",
338 1.2 matt "msi 232", "msi 233", "msi 234", "msi 235",
339 1.2 matt "msi 236", "msi 237", "msi 238", "msi 239",
340 1.2 matt "msi 240", "msi 241", "msi 242", "msi 243",
341 1.2 matt "msi 244", "msi 245", "msi 246", "msi 247",
342 1.2 matt "msi 248", "msi 249", "msi 250", "msi 251",
343 1.2 matt "msi 252", "msi 253", "msi 254", "msi 255",
344 1.2 matt },
345 1.2 matt };
346 1.2 matt
347 1.2 matt CFATTACH_DECL_NEW(pq3pci_cpunode, sizeof(struct pq3pci_softc),
348 1.2 matt pq3pci_cpunode_match, pq3pci_cpunode_attach, NULL, NULL);
349 1.2 matt
350 1.2 matt CFATTACH_DECL_NEW(pq3pcie_cpunode, sizeof(struct pq3pci_softc),
351 1.2 matt pq3pci_cpunode_match, pq3pci_cpunode_attach, NULL, NULL);
352 1.2 matt
353 1.2 matt int
354 1.2 matt pq3pci_cpunode_match(device_t parent, cfdata_t cf, void *aux)
355 1.2 matt {
356 1.2 matt
357 1.2 matt if (!e500_cpunode_submatch(parent, cf, cf->cf_name + 3, aux))
358 1.2 matt return 0;
359 1.2 matt
360 1.2 matt return 1;
361 1.2 matt }
362 1.2 matt
363 1.2 matt struct pq3pci_owin {
364 1.2 matt uint32_t potar;
365 1.2 matt uint32_t potear;
366 1.2 matt uint32_t powbar;
367 1.2 matt uint32_t powar;
368 1.2 matt };
369 1.2 matt
370 1.2 matt static bool
371 1.2 matt pq3pci_owin_setup(struct pq3pci_softc *sc, u_int winnum,
372 1.2 matt const struct pq3pci_owin *owin)
373 1.2 matt {
374 1.2 matt const bool io_win = (owin->powar & PEXOWAR_RTT) == PEXOWAR_RTT_IO;
375 1.2 matt struct pq3pci_bst *bs = io_win ? &sc->sc_pci_io_bst : &sc->sc_pci_mem_bst;
376 1.2 matt const uint64_t pci_base = ((uint64_t)owin->potar << 12)
377 1.2 matt | ((uint64_t)owin->potear << (32+12));
378 1.2 matt const uint64_t local_base = (uint64_t)owin->powbar << 12;
379 1.2 matt const u_int win_size_log2 = PEXIWAR_IWS_GET(owin->powar) + 1;
380 1.2 matt
381 1.2 matt bs->bs_tag.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN
382 1.2 matt | (io_win ? _BUS_SPACE_IO_TYPE : _BUS_SPACE_MEM_TYPE);
383 1.2 matt bs->bs_tag.pbs_base = pci_base;
384 1.2 matt bs->bs_tag.pbs_offset = local_base - pci_base;
385 1.2 matt bs->bs_tag.pbs_limit = bs->bs_tag.pbs_base + (1ULL << win_size_log2);
386 1.2 matt
387 1.2 matt #if 0
388 1.2 matt const char units[] = " KMGTP";
389 1.2 matt aprint_normal_dev(sc->sc_dev,
390 1.2 matt "outbound window %u: potar=%#x, potear=%#x, powbar=%x, powar=%#x\n",
391 1.2 matt winnum, owin->potar, owin->potear, owin->powbar, owin->powar);
392 1.2 matt aprint_normal_dev(sc->sc_dev,
393 1.3 matt "outbound window %u: maps %u%cB of PCI %s space @ %#"PRIx64" onto local addresses @ %#"PRIx64".\n",
394 1.2 matt winnum, 1 << (win_size_log2 % 10), units[win_size_log2 / 10],
395 1.2 matt (owin->powar & PEXOWAR_RTT) == PEXOWAR_RTT_IO ? "I/O" : "memory",
396 1.2 matt local_base, pci_base);
397 1.2 matt #endif
398 1.2 matt
399 1.2 matt snprintf(bs->bs_name, sizeof(bs->bs_name), "%s-%s@%u",
400 1.2 matt device_xname(sc->sc_dev), io_win ? "io" : "mem", winnum);
401 1.2 matt
402 1.2 matt #if 0
403 1.2 matt printf("%s: %s: base=%#x offset=%#x limit=%#x\n", __func__, bs->bs_name,
404 1.2 matt bs->bs_tag.pbs_base, bs->bs_tag.pbs_offset, bs->bs_tag.pbs_limit);
405 1.2 matt #endif
406 1.2 matt
407 1.2 matt int error = bus_space_init(&bs->bs_tag, bs->bs_name,
408 1.2 matt bs->bs_ex_storage, sizeof(bs->bs_ex_storage));
409 1.2 matt if (error) {
410 1.2 matt aprint_error(": failed to create %s bus space: %d\n",
411 1.2 matt bs->bs_name, error);
412 1.2 matt return false;
413 1.2 matt }
414 1.2 matt aprint_debug_dev(sc->sc_dev, "bus space %s created\n", bs->bs_name);
415 1.2 matt sc->sc_pba_flags |=
416 1.6 dyoung io_win ? PCI_FLAGS_IO_OKAY : PCI_FLAGS_MEM_OKAY;
417 1.2 matt return true;
418 1.2 matt }
419 1.2 matt
420 1.2 matt struct pq3pci_iwin {
421 1.2 matt uint32_t pitar;
422 1.2 matt uint32_t piwbar;
423 1.2 matt uint32_t piwbear;
424 1.2 matt uint32_t piwar;
425 1.2 matt };
426 1.2 matt
427 1.2 matt static bool
428 1.2 matt pq3pci_iwin_setup(struct pq3pci_softc *sc, u_int winnum,
429 1.2 matt const struct pq3pci_iwin *iwin)
430 1.2 matt {
431 1.2 matt const uint64_t pci_base = ((uint64_t)iwin->piwbar << 12)
432 1.2 matt | ((uint64_t)iwin->piwbear << (32+12));
433 1.2 matt const uint64_t local_base = (uint64_t)iwin->pitar << 12;
434 1.2 matt const u_int win_size_log2 = PEXIWAR_IWS_GET(iwin->piwar) + 1;
435 1.2 matt #if DEBUG > 1
436 1.2 matt const char units[] = " KMGTP";
437 1.2 matt aprint_normal_dev(sc->sc_dev,
438 1.2 matt "inbound window %u: pitar=%#x, piwbar=%x, piwbear=%#x, piwar=%#x\n",
439 1.2 matt winnum, iwin->pitar, iwin->piwbar, iwin->piwbear, iwin->piwar);
440 1.2 matt aprint_normal_dev(sc->sc_dev,
441 1.3 matt "inbound window %u: maps %u%cB of PCI address space @ %#"PRIx64" to local memory @ %#"PRIx64".\n",
442 1.2 matt winnum, 1 << (win_size_log2 % 10), units[win_size_log2 / 10],
443 1.2 matt pci_base, local_base);
444 1.2 matt #endif /* DEBUG */
445 1.2 matt /*
446 1.2 matt * Let's make sure this window is usable.
447 1.2 matt */
448 1.2 matt if (pci_base != 0) {
449 1.2 matt aprint_error(": invalid inbound window: "
450 1.2 matt "PCI base (%#"PRIx64" != 0\n", pci_base);
451 1.2 matt return false;
452 1.2 matt }
453 1.2 matt if (local_base != 0) {
454 1.2 matt aprint_error(": invalid inbound window: "
455 1.2 matt "local base (%#"PRIx64" != 0\n", local_base);
456 1.2 matt return false;
457 1.2 matt }
458 1.2 matt if ((iwin->piwar & PEXIWAR_RTT) != PEXIWAR_RTT_MEM_SNOOP) {
459 1.2 matt aprint_error(": invalid inbound window: "
460 1.2 matt "unsupported read transaction type (%#"PRIxMAX")\n",
461 1.2 matt iwin->piwar & PEXIWAR_RTT);
462 1.2 matt return false;
463 1.2 matt }
464 1.2 matt if ((iwin->piwar & PEXIWAR_WTT) != PEXIWAR_WTT_MEM_SNOOP) {
465 1.2 matt aprint_error(": invalid inbound window: "
466 1.2 matt "unsupported write transaction type (%#"PRIxMAX")\n",
467 1.2 matt iwin->piwar & PEXIWAR_WTT);
468 1.2 matt return false;
469 1.2 matt }
470 1.2 matt if ((iwin->piwar & PEXIWAR_TRGT) != PEXIWAR_TRGT_LOCALMEM) {
471 1.2 matt aprint_error(": invalid inbound window: "
472 1.2 matt "unsupported target (%#"PRIxMAX")\n",
473 1.2 matt iwin->piwar & PEXIWAR_TRGT);
474 1.2 matt return false;
475 1.2 matt }
476 1.2 matt if (board_info_get_number("mem-size") > (1ULL << win_size_log2)) {
477 1.2 matt aprint_error(": invalid inbound window: "
478 1.2 matt "doesn't map all of memory (%#"PRIx64" < %#"PRIx64")\n",
479 1.2 matt 1ULL << win_size_log2, board_info_get_number("mem-size"));
480 1.2 matt return false;
481 1.2 matt }
482 1.2 matt return true;
483 1.2 matt }
484 1.2 matt
485 1.2 matt static void
486 1.2 matt pq3pci_pch_callout(void *v)
487 1.2 matt {
488 1.2 matt struct pq3pci_callhand * const pch = v;
489 1.2 matt
490 1.2 matt int s = splraise(pch->pch_ipl);
491 1.2 matt (*pch->pch_ih.ih_func)(pch->pch_ih.ih_arg);
492 1.2 matt splx(s);
493 1.2 matt callout_schedule(&pch->pch_callout, 1);
494 1.2 matt }
495 1.2 matt
496 1.2 matt static int
497 1.2 matt pq3pci_msi_spurious_intr(void *v)
498 1.2 matt {
499 1.2 matt (void) v;
500 1.2 matt
501 1.2 matt return 0;
502 1.2 matt }
503 1.2 matt
504 1.2 matt static int
505 1.2 matt pq3pci_msi_intr(void *v)
506 1.2 matt {
507 1.2 matt struct pq3pci_msigroup * const msig = v;
508 1.2 matt
509 1.2 matt mutex_spin_enter(msig->msig_lock);
510 1.2 matt KASSERT(curcpu()->ci_cpl == msig->msig_ipl);
511 1.2 matt //KASSERT(curcpu()->ci_idepth == 0);
512 1.2 matt for (int rv = 0;;) {
513 1.2 matt uint32_t group = cpu_read_4(msig->msig_msir);
514 1.2 matt if (group == 0) {
515 1.2 matt mutex_spin_exit(msig->msig_lock);
516 1.2 matt return rv;
517 1.2 matt }
518 1.2 matt
519 1.2 matt const bool working_msi_p =
520 1.2 matt msig->msig_group != 0 || (group & 1) == 0;
521 1.2 matt if (working_msi_p) {
522 1.2 matt /*
523 1.2 matt * if MSIs are working, just clear the free MSIs.
524 1.2 matt */
525 1.2 matt group &= ~msig->msig_free_mask;
526 1.2 matt } else {
527 1.2 matt /*
528 1.2 matt * If MSIs are broken, we don't really what MSIs
529 1.2 matt * have happened.
530 1.2 matt */
531 1.2 matt for (struct pq3pci_msihand *msih = msig->msig_ihands + 31;
532 1.2 matt group != 0;
533 1.2 matt msih--) {
534 1.2 matt const u_int n = __builtin_clz(group);
535 1.2 matt msih -= n;
536 1.2 matt group <<= n + 1;
537 1.2 matt msih->msih_ev.ev_count++;
538 1.2 matt }
539 1.2 matt group = ~msig->msig_free_mask;
540 1.2 matt }
541 1.2 matt for (struct pq3pci_msihand *msih = msig->msig_ihands + 31;
542 1.2 matt group != 0;
543 1.2 matt msih--) {
544 1.2 matt KASSERT(msig->msig_ihands <= msih);
545 1.2 matt KASSERT(msih < &msig->msig_ihands[32]);
546 1.2 matt const u_int n = __builtin_clz(group);
547 1.2 matt msih -= n;
548 1.2 matt group <<= n + 1;
549 1.2 matt msih->msih_ev.ev_count += working_msi_p;
550 1.2 matt if ((*msih->msih_ih.ih_func)(msih->msih_ih.ih_arg)) {
551 1.2 matt rv = 1;
552 1.2 matt msih->msih_ev.ev_count += !working_msi_p;
553 1.2 matt } else {
554 1.2 matt msih->msih_ev_spurious.ev_count += working_msi_p;
555 1.2 matt }
556 1.2 matt }
557 1.2 matt }
558 1.2 matt }
559 1.2 matt
560 1.2 matt static int
561 1.2 matt pq3pci_onchip_intr(void *v)
562 1.2 matt {
563 1.2 matt panic(__func__);
564 1.2 matt }
565 1.2 matt
566 1.2 matt static int
567 1.2 matt pq3pci_pis_intr(void *v)
568 1.2 matt {
569 1.2 matt struct pq3pci_intrsource * const pis = v;
570 1.2 matt struct pq3pci_intrhand *pih;
571 1.2 matt int rv = 0;
572 1.2 matt
573 1.2 matt mutex_spin_enter(pis->pis_lock);
574 1.2 matt pis->pis_ev.ev_count++;
575 1.2 matt SIMPLEQ_FOREACH(pih, &pis->pis_ihands, pih_link) {
576 1.2 matt struct pq3pci_softc * const sc = pih->pih_ih.ih_sc;
577 1.2 matt int s = splraise(pih->pih_ipl);
578 1.2 matt pih->pih_count++;
579 1.2 matt rv = (*pih->pih_ih.ih_func)(pih->pih_ih.ih_arg);
580 1.2 matt splx(s);
581 1.2 matt #if 0
582 1.2 matt printf("%s %d:%s %"PRIu64": %p(%p) %"PRIu64": %d\n", __func__,
583 1.2 matt curcpu()->ci_idepth,
584 1.3 matt pis->pis_ev.ev_group, pis->pis_ev.ev_count,
585 1.2 matt pih->pih_ih.ih_func, pih->pih_ih.ih_arg, pih->pih_count, rv);
586 1.2 matt #endif
587 1.2 matt if (rv != 0) {
588 1.2 matt bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCI_INT_ACK);
589 1.2 matt break;
590 1.2 matt }
591 1.2 matt pih->pih_count--;
592 1.2 matt }
593 1.2 matt if (rv == 0)
594 1.2 matt pis->pis_ev_spurious.ev_count++;
595 1.2 matt mutex_spin_exit(pis->pis_lock);
596 1.2 matt return rv;
597 1.2 matt }
598 1.2 matt
599 1.2 matt static void
600 1.2 matt pq3pci_intr_source_setup(struct pq3pci_softc *sc,
601 1.2 matt struct pq3pci_intrsource *pis, pci_intr_handle_t handle)
602 1.2 matt {
603 1.2 matt SIMPLEQ_INIT(&pis->pis_ihands);
604 1.2 matt pis->pis_handle = handle;
605 1.2 matt pis->pis_ih = intr_establish(PIH_IRQ(handle), IPL_VM, PIH_IST(handle),
606 1.2 matt pq3pci_pis_intr, pis);
607 1.2 matt pis->pis_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM);
608 1.2 matt const char * const intrstr
609 1.2 matt = intr_string(PIH_IRQ(handle), PIH_IST(handle));
610 1.2 matt evcnt_attach_dynamic(&pis->pis_ev, EVCNT_TYPE_INTR,
611 1.2 matt NULL, intrstr, "intr");
612 1.2 matt evcnt_attach_dynamic(&pis->pis_ev_spurious, EVCNT_TYPE_INTR,
613 1.2 matt &pis->pis_ev, intrstr, "spurious intr");
614 1.2 matt SIMPLEQ_INSERT_TAIL(&pq3pci_intrsources, pis, pis_link);
615 1.2 matt }
616 1.2 matt
617 1.2 matt static bool
618 1.2 matt pq3pci_intrmap_setup(struct pq3pci_softc *sc,
619 1.2 matt const struct cpunode_locators *cnl)
620 1.2 matt {
621 1.2 matt char prop_name[32];
622 1.2 matt snprintf(prop_name, sizeof(prop_name), "%s%u-interrupt-map",
623 1.2 matt cnl->cnl_name, cnl->cnl_instance);
624 1.2 matt sc->sc_intrmap = board_info_get_object(prop_name);
625 1.2 matt if (sc->sc_intrmap == NULL) {
626 1.2 matt aprint_error(": missing %s board property", prop_name);
627 1.2 matt return false;
628 1.2 matt }
629 1.2 matt
630 1.2 matt KASSERT(prop_object_type(sc->sc_intrmap) == PROP_TYPE_DICTIONARY);
631 1.2 matt prop_number_t pn = prop_dictionary_get(sc->sc_intrmap, "interrupt-mask");
632 1.2 matt KASSERT(pn != NULL);
633 1.2 matt
634 1.2 matt sc->sc_intrmask = prop_number_unsigned_integer_value(pn);
635 1.2 matt
636 1.2 matt sc->sc_ih = intr_establish(cnl->cnl_intrs[0], IPL_VM, IST_ONCHIP,
637 1.2 matt pq3pci_onchip_intr, sc);
638 1.2 matt if (sc->sc_ih == NULL)
639 1.2 matt panic("%s: failed to establish interrupt %d\n",
640 1.2 matt device_xname(sc->sc_dev), cnl->cnl_intrs[0]);
641 1.3 matt
642 1.2 matt return true;
643 1.2 matt }
644 1.2 matt
645 1.2 matt void
646 1.2 matt pq3pci_cpunode_attach(device_t parent, device_t self, void *aux)
647 1.2 matt {
648 1.2 matt struct cpunode_softc * const psc = device_private(parent);
649 1.2 matt struct pq3pci_softc * const sc = device_private(self);
650 1.2 matt struct cpunode_attach_args * const cna = aux;
651 1.2 matt struct cpunode_locators * const cnl = &cna->cna_locs;
652 1.2 matt char buf[32];
653 1.2 matt
654 1.2 matt sc->sc_dev = self;
655 1.2 matt sc->sc_bst = cna->cna_memt;
656 1.2 matt psc->sc_children |= cna->cna_childmask;
657 1.2 matt sc->sc_pcie = strcmp(cnl->cnl_name, "pcie") == 0;
658 1.2 matt
659 1.2 matt const uint32_t pordevsr = cpu_read_4(GLOBAL_BASE + PORDEVSR);
660 1.2 matt if (sc->sc_pcie) {
661 1.2 matt u_int lanes = e500_truth_decode(cnl->cnl_instance, pordevsr,
662 1.2 matt pq3pci_pcie_lanes, __arraycount(pq3pci_pcie_lanes), 0);
663 1.2 matt if (lanes == 0) {
664 1.2 matt aprint_normal(": disabled\n");
665 1.2 matt return;
666 1.2 matt }
667 1.2 matt snprintf(buf, sizeof(buf), "PCI-Express x%u", lanes);
668 1.2 matt } else {
669 1.2 matt bool pcix_p = e500_truth_decode(cnl->cnl_instance, pordevsr,
670 1.2 matt pq3pci_pci_pcix, __arraycount(pq3pci_pci_pcix), 0);
671 1.2 matt u_int width = e500_truth_decode(cnl->cnl_instance, pordevsr,
672 1.2 matt pq3pci_pci_pci32, __arraycount(pq3pci_pci_pci32), 32);
673 1.2 matt snprintf(buf, sizeof(buf), "%u-bit PCI%s",
674 1.2 matt width, (pcix_p ? "X" : ""));
675 1.2 matt }
676 1.2 matt
677 1.2 matt if (!pq3pci_intrmap_setup(sc, cnl))
678 1.2 matt return;
679 1.2 matt
680 1.2 matt evcnt_attach_dynamic(&sc->sc_ev_spurious, EVCNT_TYPE_INTR, NULL,
681 1.2 matt device_xname(self), "spurious intr");
682 1.2 matt
683 1.2 matt int error = bus_space_map(sc->sc_bst, cnl->cnl_addr, cnl->cnl_size, 0,
684 1.2 matt &sc->sc_bsh);
685 1.2 matt if (error) {
686 1.2 matt aprint_error(": failed to map registers: %d\n", error);
687 1.2 matt return;
688 1.2 matt }
689 1.2 matt
690 1.2 matt u_int valid_owins = 0;
691 1.2 matt for (u_int i = 1, off = PEXOTAR1 - PEXOTAR0;
692 1.2 matt i < 4; i++, off += PEXOTAR1 - PEXOTAR0) {
693 1.2 matt struct pq3pci_owin owin;
694 1.2 matt owin.potar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
695 1.2 matt PEXOTAR0 + off);
696 1.2 matt owin.potear = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
697 1.2 matt PEXOTEAR0 + off);
698 1.2 matt owin.powbar = 0;
699 1.2 matt if (i > 0) {
700 1.2 matt /* Doesn't exist for outbound window 0 */
701 1.2 matt owin.powbar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
702 1.2 matt PEXOWBAR1 - (PEXOTAR1 - PEXOTAR0) + off);
703 1.2 matt }
704 1.2 matt owin.powar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
705 1.2 matt PEXOWAR0 + off);
706 1.2 matt #if 0
707 1.2 matt aprint_normal_dev(self,
708 1.2 matt "owin[%u]: potar=%#x potear=%#x powbar=%#x powar=%#x\n",
709 1.2 matt i, owin.potar, owin.potear, owin.powbar, owin.powar);
710 1.2 matt #endif
711 1.2 matt if (owin.powar & PEXOWAR_EN) {
712 1.2 matt valid_owins++;
713 1.2 matt if (!pq3pci_owin_setup(sc, i, &owin))
714 1.2 matt return;
715 1.2 matt }
716 1.2 matt }
717 1.2 matt #ifndef PCI_NETBSD_CONFIGURE
718 1.2 matt if (valid_owins == 0) {
719 1.2 matt aprint_normal(": %s controller%s\n", buf,
720 1.2 matt " (disabled)");
721 1.2 matt return;
722 1.2 matt }
723 1.2 matt #endif
724 1.2 matt
725 1.2 matt u_int valid_iwins = 0;
726 1.2 matt for (u_int i = 0, off = 0; i < 3; i++, off += PEXITAR2 - PEXITAR1) {
727 1.2 matt struct pq3pci_iwin iwin;
728 1.2 matt iwin.pitar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
729 1.2 matt PEXITAR1 + off);
730 1.2 matt iwin.piwbar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
731 1.2 matt PEXIWBAR1 + off);
732 1.2 matt if (i > 0) {
733 1.2 matt /* Doesn't exist */
734 1.2 matt iwin.piwbear = bus_space_read_4(sc->sc_bst,
735 1.2 matt sc->sc_bsh,
736 1.2 matt PEXIWBEAR2 - (PEXITAR2 - PEXITAR1) + off);
737 1.2 matt } else {
738 1.2 matt iwin.piwbear = 0;
739 1.2 matt }
740 1.2 matt iwin.piwar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
741 1.2 matt PEXIWAR1 + off);
742 1.2 matt #if 0
743 1.2 matt aprint_normal_dev(self,
744 1.2 matt "iwin[%u]: pitar=%#x piwbar=%#x piwbear=%#x piwar=%#x\n",
745 1.2 matt i, iwin.pitar, iwin.piwbar, iwin.piwbear, iwin.piwar);
746 1.2 matt #endif
747 1.2 matt if (iwin.piwar & PEXIWAR_EN) {
748 1.2 matt valid_iwins++;
749 1.2 matt if (!pq3pci_iwin_setup(sc, i, &iwin))
750 1.2 matt return;
751 1.2 matt }
752 1.2 matt }
753 1.2 matt
754 1.2 matt sc->sc_conf_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM);
755 1.2 matt
756 1.2 matt pci_chipset_tag_t pc = pq3pci_pci_chipset_init(sc);
757 1.2 matt
758 1.2 matt #ifndef PCI_NETBSD_CONFIGURE
759 1.2 matt if (valid_iwins == 0) {
760 1.2 matt aprint_normal(": %s controller%s\n", buf,
761 1.2 matt " (disabled)");
762 1.2 matt return;
763 1.2 matt }
764 1.2 matt #else
765 1.2 matt if (sc->sc_pcie && pci_conf_read(pc, 0, PEX_LTSSM) < LTSSM_L0) {
766 1.2 matt aprint_normal(": %s controller%s\n", buf,
767 1.2 matt " (offline)");
768 1.2 matt return;
769 1.2 matt }
770 1.2 matt if (!sc->sc_pcie && (pci_conf_read(pc, 0, PCI_PBFR) & PBFR_PAH)) {
771 1.2 matt aprint_normal(": %s controller%s\n", buf,
772 1.2 matt " (agent mode)");
773 1.2 matt return;
774 1.2 matt }
775 1.2 matt if (valid_iwins == 0) {
776 1.2 matt struct pq3pci_iwin iwin = {
777 1.2 matt .pitar = 0,
778 1.2 matt .piwbar = 0,
779 1.2 matt .piwbear = 0,
780 1.2 matt .piwar = PEXIWAR_EN|PEXIWAR_PF|PEXIWAR_TRGT_LOCALMEM
781 1.2 matt |PEXIWAR_RTT_MEM_SNOOP|PEXIWAR_WTT_MEM_SNOOP
782 1.2 matt |__SHIFTIN(30-__builtin_clz(pmemsize),PEXIWAR_IWS),
783 1.2 matt };
784 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXITAR2, iwin.pitar);
785 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXIWBAR2, iwin.piwbar);
786 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXIWBEAR2, iwin.piwbear);
787 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXIWAR2, iwin.piwar);
788 1.2 matt
789 1.2 matt if (!pq3pci_iwin_setup(sc, 2, &iwin)) {
790 1.2 matt aprint_error(": error creating inbound window\n");
791 1.2 matt return;
792 1.2 matt }
793 1.2 matt
794 1.2 matt }
795 1.2 matt
796 1.2 matt if (valid_owins == 0) {
797 1.2 matt u_long membase, iobase;
798 1.2 matt error = extent_alloc(pcimem_ex, PCI_MEMSIZE, PCI_MEMSIZE,
799 1.2 matt PCI_MEMSIZE, EX_WAITOK, &membase);
800 1.2 matt if (error) {
801 1.2 matt aprint_error(
802 1.2 matt ": error allocating address space for %s: %d\n",
803 1.2 matt "PCI memory", error);
804 1.2 matt return;
805 1.2 matt }
806 1.2 matt struct pq3pci_owin owin1 = {
807 1.2 matt .potar = membase >> 12,
808 1.2 matt .potear = 0,
809 1.2 matt .powbar = membase >> 12,
810 1.2 matt .powar = PEXOWAR_EN|PEXOWAR_TC0
811 1.2 matt |PEXOWAR_RTT_MEM|PEXOWAR_WTT_MEM
812 1.2 matt |__SHIFTIN(ilog2(PCI_MEMSIZE)-1,PEXOWAR_OWS),
813 1.2 matt };
814 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTAR1, owin1.potar);
815 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTEAR1, owin1.potear);
816 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWBAR1, owin1.powbar);
817 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWAR1, owin1.powar);
818 1.2 matt if (!pq3pci_owin_setup(sc, 1, &owin1)) {
819 1.2 matt aprint_error(
820 1.2 matt ": error creating bus space for %s\n",
821 1.2 matt "PCI memory");
822 1.2 matt return;
823 1.2 matt }
824 1.2 matt
825 1.2 matt error = extent_alloc(pciio_ex, PCI_IOSIZE, PCI_IOSIZE,
826 1.2 matt PCI_IOSIZE, EX_WAITOK, &iobase);
827 1.2 matt if (error) {
828 1.2 matt aprint_error(
829 1.2 matt ": error allocating address space for %s: %d\n",
830 1.2 matt "PCI I/O space", error);
831 1.2 matt return;
832 1.2 matt }
833 1.2 matt struct pq3pci_owin owin2 = {
834 1.2 matt .potar = 0,
835 1.2 matt .potear = 0,
836 1.2 matt .powbar = iobase >> 12,
837 1.2 matt .powar = PEXOWAR_EN|PEXOWAR_TC0
838 1.2 matt |PEXOWAR_RTT_IO|PEXOWAR_WTT_IO
839 1.2 matt |__SHIFTIN(ilog2(PCI_IOSIZE)-1,PEXOWAR_OWS),
840 1.2 matt };
841 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTAR2, owin2.potar);
842 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTEAR2, owin2.potear);
843 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWBAR2, owin2.powbar);
844 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWAR2, owin2.powar);
845 1.2 matt if (!pq3pci_owin_setup(sc, 2, &owin2)) {
846 1.2 matt aprint_error(
847 1.2 matt ": error creating bus space for %s\n",
848 1.2 matt "PCI I/O space");
849 1.2 matt return;
850 1.2 matt }
851 1.2 matt
852 1.2 matt struct extent *ioext = extent_create("pciio", 0, PCI_IOSIZE,
853 1.2 matt M_DEVBUF, NULL, 0, EX_NOWAIT);
854 1.2 matt struct extent *memext = extent_create("pcimem", membase,
855 1.2 matt membase + PCI_MEMSIZE, M_DEVBUF, NULL, 0, EX_NOWAIT);
856 1.3 matt
857 1.2 matt error = pci_configure_bus(pc, ioext, memext, NULL, 0,
858 1.2 matt curcpu()->ci_ci.dcache_line_size);
859 1.3 matt
860 1.2 matt extent_destroy(ioext);
861 1.2 matt extent_destroy(memext);
862 1.2 matt
863 1.2 matt if (error) {
864 1.2 matt aprint_normal(": configuration failed\n");
865 1.2 matt return;
866 1.2 matt }
867 1.2 matt }
868 1.2 matt #endif
869 1.2 matt
870 1.2 matt aprint_normal(": %s controller%s\n", buf, "");
871 1.2 matt
872 1.2 matt struct pcibus_attach_args pba;
873 1.2 matt memset(&pba, 0, sizeof(pba));
874 1.2 matt
875 1.2 matt pba.pba_flags = sc->sc_pba_flags | PCI_FLAGS_MSI_OKAY
876 1.2 matt | PCI_FLAGS_MSIX_OKAY;
877 1.6 dyoung if (pba.pba_flags & PCI_FLAGS_IO_OKAY)
878 1.2 matt pba.pba_iot = pc->pc_iot;
879 1.6 dyoung if (pba.pba_flags & PCI_FLAGS_MEM_OKAY)
880 1.2 matt pba.pba_memt = pc->pc_memt;
881 1.2 matt pba.pba_dmat = cna->cna_dmat;
882 1.2 matt pba.pba_pc = pc;
883 1.2 matt pba.pba_bus = 0;
884 1.2 matt
885 1.2 matt /*
886 1.2 matt * Program BAR0 so that MSIs can work.
887 1.2 matt */
888 1.2 matt pci_conf_write(pc, 0, PCI_BAR0, sc->sc_bst->pbs_offset);
889 1.2 matt pcireg_t cmdsts = pci_conf_read(pc, 0, PCI_COMMAND_STATUS_REG);
890 1.2 matt cmdsts |= PCI_COMMAND_INTERRUPT_DISABLE;
891 1.2 matt pci_conf_write(pc, 0, PCI_COMMAND_STATUS_REG, cmdsts);
892 1.2 matt
893 1.2 matt #if 0
894 1.2 matt /*
895 1.2 matt *
896 1.2 matt */
897 1.2 matt pq3pci_intr_source_lookup(sc, PIH_MAKE(0, IST_LEVEL, 0));
898 1.2 matt #endif
899 1.2 matt #if 0
900 1.2 matt if (sc->sc_pcie)
901 1.2 matt pci_conf_print(pc, 0, NULL);
902 1.2 matt #endif
903 1.2 matt
904 1.2 matt config_found_ia(self, "pcibus", &pba, pcibusprint);
905 1.2 matt }
906 1.2 matt
907 1.2 matt static void
908 1.2 matt pq3pci_attach_hook(device_t parent, device_t self,
909 1.2 matt struct pcibus_attach_args *pba)
910 1.2 matt {
911 1.2 matt /* do nothing */
912 1.2 matt }
913 1.2 matt
914 1.2 matt static int
915 1.2 matt pq3pci_bus_maxdevs(void *v, int busno)
916 1.2 matt {
917 1.2 matt struct pq3pci_softc * const sc = v;
918 1.2 matt return sc->sc_pcie && busno < 2 ? 1 : 32;
919 1.2 matt }
920 1.2 matt
921 1.2 matt static void
922 1.2 matt pq3pci_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func)
923 1.2 matt {
924 1.2 matt if (bus)
925 1.2 matt *bus = (tag >> 16) & 0xff;
926 1.2 matt if (dev)
927 1.2 matt *dev = (tag >> 11) & 0x1f;
928 1.2 matt if (func)
929 1.2 matt *func = (tag >> 8) & 0x07;
930 1.2 matt }
931 1.2 matt
932 1.2 matt static pcitag_t
933 1.2 matt pq3pci_make_tag(void *v, int bus, int dev, int func)
934 1.2 matt {
935 1.2 matt return (bus << 16) | (dev << 11) | (func << 8);
936 1.2 matt }
937 1.2 matt
938 1.2 matt static inline pcitag_t
939 1.2 matt pq3pci_config_addr_read(pci_chipset_tag_t pc)
940 1.2 matt {
941 1.2 matt pcitag_t v;
942 1.2 matt __asm volatile("lwz\t%0, 0(%1)" : "=r"(v) : "b"(pc->pc_addr));
943 1.2 matt __asm volatile("mbar\n\tmsync");
944 1.2 matt return v;
945 1.2 matt }
946 1.2 matt
947 1.2 matt static inline void
948 1.2 matt pq3pci_config_addr_write(pci_chipset_tag_t pc, pcitag_t v)
949 1.2 matt {
950 1.2 matt __asm volatile("stw\t%0, 0(%1)" :: "r"(v), "b"(pc->pc_addr));
951 1.2 matt __asm volatile("mbar\n\tmsync");
952 1.2 matt }
953 1.2 matt
954 1.2 matt static inline pcireg_t
955 1.2 matt pq3pci_config_data_read(pci_chipset_tag_t pc)
956 1.2 matt {
957 1.2 matt pcireg_t v;
958 1.2 matt __asm volatile("lwbrx\t%0, 0, %1" : "=r"(v) : "b"(pc->pc_data));
959 1.2 matt __asm volatile("mbar\n\tmsync");
960 1.2 matt return v;
961 1.2 matt }
962 1.2 matt
963 1.2 matt static inline void
964 1.2 matt pq3pci_config_data_write(pci_chipset_tag_t pc, pcireg_t v)
965 1.2 matt {
966 1.2 matt __asm volatile("stwbrx\t%0, 0, %1" :: "r"(v), "r"(pc->pc_data));
967 1.2 matt __asm volatile("mbar\n\tmsync");
968 1.2 matt }
969 1.2 matt
970 1.2 matt static pcireg_t
971 1.2 matt pq3pci_conf_read(void *v, pcitag_t tag, int reg)
972 1.2 matt {
973 1.2 matt struct pq3pci_softc * const sc = v;
974 1.2 matt struct genppc_pci_chipset * const pc = &sc->sc_pc;
975 1.2 matt
976 1.2 matt if (reg >= 256) {
977 1.2 matt if (!sc->sc_pcie)
978 1.2 matt return 0xffffffff;
979 1.2 matt reg = (reg & 0xff) | ((reg & 0xf00) << 16);
980 1.2 matt }
981 1.2 matt if (sc->sc_pcie && ((tag >> 16) & 0xff) != 0) {
982 1.2 matt // pcireg_t slot_status = pci_conf_read(pc, 0, 0x64);
983 1.2 matt // printf("%s: tag 0x0 slot status: %#x\n",__func__, slot_status);
984 1.2 matt // if ((slot_status & __BIT(6+16)) == 0)
985 1.2 matt // printf(" addr=%#llx ", tag | reg | PEX_CONFIG_ADDR_EN);
986 1.2 matt // return 0xffffffff;
987 1.2 matt }
988 1.2 matt
989 1.2 matt mutex_spin_enter(sc->sc_conf_lock);
990 1.2 matt
991 1.2 matt pq3pci_config_addr_write(pc, tag | reg | PEX_CONFIG_ADDR_EN);
992 1.2 matt pcireg_t rv = pq3pci_config_data_read(pc);
993 1.2 matt
994 1.2 matt mutex_spin_exit(sc->sc_conf_lock);
995 1.2 matt
996 1.2 matt #if 0
997 1.2 matt uint32_t err = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PEX_ERR_DR);
998 1.2 matt if (err & PEXERRDR_ICCA) {
999 1.2 matt aprint_error_dev(sc->sc_dev, "%s: tag %#x reg %#x icca: %#x\n",
1000 1.2 matt __func__, tag, reg, pq3pci_config_addr_read(pc));
1001 1.2 matt bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEX_ERR_DR,
1002 1.2 matt PEXERRDR_ICCA);
1003 1.2 matt }
1004 1.2 matt #endif
1005 1.2 matt return rv;
1006 1.2 matt }
1007 1.2 matt
1008 1.2 matt static void
1009 1.2 matt pq3pci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
1010 1.2 matt {
1011 1.2 matt struct pq3pci_softc * const sc = v;
1012 1.2 matt struct genppc_pci_chipset * const pc = &sc->sc_pc;
1013 1.2 matt
1014 1.2 matt if (reg >= 256) {
1015 1.2 matt if (!sc->sc_pcie)
1016 1.2 matt return;
1017 1.2 matt reg = (reg & 0xff) | ((reg & 0xf00) << 16);
1018 1.2 matt }
1019 1.2 matt
1020 1.2 matt mutex_spin_enter(sc->sc_conf_lock);
1021 1.2 matt
1022 1.2 matt #if 0
1023 1.2 matt aprint_error_dev(sc->sc_dev, "%s: tag %#x reg %#x data %#x\n",
1024 1.2 matt __func__, tag, reg, data);
1025 1.2 matt #endif
1026 1.2 matt pq3pci_config_addr_write(pc, tag | reg | PEX_CONFIG_ADDR_EN);
1027 1.2 matt pq3pci_config_data_write(pc, data);
1028 1.2 matt
1029 1.2 matt mutex_spin_exit(sc->sc_conf_lock);
1030 1.2 matt }
1031 1.2 matt
1032 1.2 matt static int
1033 1.2 matt pq3pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func,
1034 1.2 matt pcireg_t id)
1035 1.2 matt {
1036 1.2 matt struct pq3pci_softc * const sc = pc->pc_conf_v;
1037 1.2 matt if (sc->sc_pcie && bus != 0) {
1038 1.2 matt pcireg_t slot_status = pci_conf_read(pc, 0, 0x64);
1039 1.2 matt if ((slot_status & __BIT(6+16)) == 0)
1040 1.2 matt return 0;
1041 1.2 matt }
1042 1.2 matt if (!sc->sc_pcie && bus == 0 && dev == 0) {
1043 1.2 matt return PCI_CONF_DEFAULT ^ (PCI_CONF_MAP_IO|PCI_CONF_MAP_MEM|PCI_CONF_MAP_ROM);
1044 1.2 matt }
1045 1.2 matt return PCI_CONF_DEFAULT;
1046 1.2 matt }
1047 1.2 matt
1048 1.2 matt static void
1049 1.2 matt pq3pci_msi_group_setup(struct pq3pci_msigroup *msig, u_int group, int ipl)
1050 1.2 matt {
1051 1.2 matt const char (*intr_names)[8] = msi_intr_names[group];
1052 1.2 matt
1053 1.2 matt KASSERT(ipl == IPL_VM);
1054 1.2 matt
1055 1.2 matt pq3pci_msigroups[group] = msig;
1056 1.2 matt msig->msig_group = group;
1057 1.2 matt msig->msig_free_mask = ~0 << (group == 0);
1058 1.2 matt msig->msig_ipl = ipl;
1059 1.2 matt msig->msig_lock = mutex_obj_alloc(MUTEX_DEFAULT, ipl);
1060 1.2 matt msig->msig_ih = intr_establish(msig->msig_group, ipl, IST_MSIGROUP,
1061 1.2 matt pq3pci_msi_intr, msig);
1062 1.2 matt msig->msig_msir = OPENPIC_BASE + OPENPIC_MSIR(msig->msig_group);
1063 1.2 matt for (u_int i = 0; i < __arraycount(msig->msig_ihands); i++) {
1064 1.2 matt struct pq3pci_msihand * const msih = msig->msig_ihands + i;
1065 1.2 matt msih->msih_ih.ih_class = IH_MSI;
1066 1.2 matt msih->msih_ih.ih_func = pq3pci_msi_spurious_intr;
1067 1.2 matt msih->msih_ih.ih_arg = msih;
1068 1.2 matt msih->msih_group = msig;
1069 1.2 matt evcnt_attach_dynamic(&msih->msih_ev, EVCNT_TYPE_INTR,
1070 1.2 matt NULL, intr_names[i], "intr");
1071 1.2 matt evcnt_attach_dynamic(&msih->msih_ev_spurious, EVCNT_TYPE_INTR,
1072 1.2 matt &msih->msih_ev, intr_names[i], "spurious intr");
1073 1.2 matt }
1074 1.2 matt }
1075 1.2 matt
1076 1.2 matt static pci_intr_handle_t
1077 1.2 matt pq3pci_msi_alloc(int ipl, u_int rmsi)
1078 1.2 matt {
1079 1.2 matt size_t freegroup = 0;
1080 1.2 matt size_t maplen = __arraycount(pq3pci_msigroups);
1081 1.2 matt KASSERT(rmsi <= 5);
1082 1.2 matt uint32_t bitmap[maplen];
1083 1.2 matt
1084 1.2 matt for (u_int i = 0; i < maplen; i++) {
1085 1.2 matt struct pq3pci_msigroup * const msig = pq3pci_msigroups[i];
1086 1.2 matt if (msig == NULL) {
1087 1.2 matt bitmap[i] = 0;
1088 1.2 matt if (freegroup == 0)
1089 1.2 matt freegroup = i + 1;
1090 1.2 matt continue;
1091 1.2 matt }
1092 1.2 matt /*
1093 1.2 matt * If this msigroup has the wrong IPL or there's nothing
1094 1.2 matt * free, try the next one.
1095 1.2 matt */
1096 1.2 matt if (msig->msig_ipl != ipl || msig->msig_free_mask == 0) {
1097 1.2 matt bitmap[i] = 0;
1098 1.2 matt continue;
1099 1.2 matt }
1100 1.2 matt
1101 1.2 matt bitmap[i] = msig->msig_free_mask;
1102 1.2 matt }
1103 1.2 matt for (u_int i = 0; i < maplen; i++) {
1104 1.2 matt uint32_t mapbits = bitmap[i];
1105 1.2 matt u_int n = ffs(mapbits);
1106 1.2 matt if (n--) {
1107 1.2 matt return PIH_MAKE(i * 32 + n, IST_MSI, 0);
1108 1.2 matt }
1109 1.2 matt }
1110 1.2 matt
1111 1.2 matt if (freegroup-- == 0)
1112 1.2 matt return 0;
1113 1.2 matt
1114 1.2 matt struct pq3pci_msigroup * const msig =
1115 1.2 matt kmem_zalloc(sizeof(*msig), KM_SLEEP);
1116 1.2 matt KASSERT(msig != NULL);
1117 1.2 matt pq3pci_msi_group_setup(msig, freegroup, ipl);
1118 1.2 matt u_int n = ffs(msig->msig_free_mask) - 1;
1119 1.2 matt return PIH_MAKE(freegroup * 32 + n, IST_MSI, 0);
1120 1.2 matt }
1121 1.2 matt
1122 1.2 matt static struct pq3pci_msihand *
1123 1.2 matt pq3pci_msi_lookup(pci_intr_handle_t handle)
1124 1.2 matt {
1125 1.2 matt const int irq = PIH_IRQ(handle);
1126 1.2 matt KASSERT(irq < 256);
1127 1.2 matt struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
1128 1.2 matt KASSERT(msig != NULL);
1129 1.2 matt return &msig->msig_ihands[irq & 31];
1130 1.2 matt }
1131 1.2 matt
1132 1.2 matt static struct pq3pci_msihand *
1133 1.2 matt pq3pci_msi_claim(pci_intr_handle_t handle)
1134 1.2 matt {
1135 1.2 matt const int irq = PIH_IRQ(handle);
1136 1.2 matt uint32_t irq_mask = __BIT(irq & 31);
1137 1.2 matt KASSERT(irq < 256);
1138 1.2 matt struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
1139 1.2 matt KASSERT(msig != NULL);
1140 1.2 matt struct pq3pci_msihand * const msih = &msig->msig_ihands[irq & 31];
1141 1.2 matt mutex_spin_enter(msig->msig_lock);
1142 1.2 matt KASSERT(msig->msig_free_mask & irq_mask);
1143 1.2 matt msig->msig_free_mask ^= irq_mask;
1144 1.2 matt mutex_spin_exit(msig->msig_lock);
1145 1.2 matt return msih;
1146 1.2 matt }
1147 1.2 matt
1148 1.2 matt static struct pq3pci_intrsource *
1149 1.2 matt pq3pci_intr_source_lookup(struct pq3pci_softc *sc, pci_intr_handle_t handle)
1150 1.2 matt {
1151 1.2 matt struct pq3pci_intrsource *pis;
1152 1.2 matt SIMPLEQ_FOREACH(pis, &pq3pci_intrsources, pis_link) {
1153 1.2 matt if (pis->pis_handle == handle)
1154 1.2 matt return pis;
1155 1.2 matt }
1156 1.2 matt pis = kmem_zalloc(sizeof(*pis), KM_SLEEP);
1157 1.2 matt pq3pci_intr_source_setup(sc, pis, handle);
1158 1.2 matt return pis;
1159 1.2 matt }
1160 1.2 matt
1161 1.2 matt static pci_intr_handle_t
1162 1.5 dyoung pq3pci_intr_handle_lookup(struct pq3pci_softc *sc,
1163 1.5 dyoung const struct pci_attach_args *pa)
1164 1.2 matt {
1165 1.2 matt prop_dictionary_t entry;
1166 1.2 matt
1167 1.2 matt if (sc->sc_pcie) do {
1168 1.2 matt pcireg_t msictl;
1169 1.2 matt int msioff;
1170 1.2 matt if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI,
1171 1.2 matt &msioff, &msictl))
1172 1.2 matt break;
1173 1.2 matt msictl = pci_conf_read(pa->pa_pc, pa->pa_tag, msioff);
1174 1.2 matt msictl &= ~PCI_MSI_CTL_MSI_ENABLE;
1175 1.2 matt msictl &= ~(PCI_MSI_CTL_MME_MASK << PCI_MSI_CTL_MME_SHIFT);
1176 1.2 matt int rmsi = (msictl >> PCI_MSI_CTL_MMC_SHIFT) & PCI_MSI_CTL_MMC_MASK;
1177 1.2 matt pci_conf_write(pa->pa_pc, pa->pa_tag, msioff, msictl);
1178 1.2 matt pci_intr_handle_t handle = pq3pci_msi_alloc(IPL_VM, rmsi);
1179 1.2 matt struct pq3pci_msihand * const msih = pq3pci_msi_lookup(handle);
1180 1.2 matt msih->msih_tag = pa->pa_tag;
1181 1.2 matt msih->msih_msioff = msioff;
1182 1.2 matt return handle;
1183 1.2 matt } while (false);
1184 1.2 matt
1185 1.2 matt
1186 1.2 matt if (sc->sc_intrmask == 0) {
1187 1.2 matt entry = prop_dictionary_get(sc->sc_intrmap, "000000");
1188 1.2 matt } else {
1189 1.2 matt char prop_name[8];
1190 1.2 matt u_int intrinc = __LOWEST_SET_BIT(sc->sc_intrmask);
1191 1.2 matt pcitag_t tag = (pa->pa_intrpin - PCI_INTERRUPT_PIN_A) * intrinc;
1192 1.2 matt
1193 1.2 matt snprintf(prop_name, sizeof(prop_name), "%06x",
1194 1.2 matt tag & sc->sc_intrmask);
1195 1.2 matt
1196 1.2 matt #if 0
1197 1.2 matt printf("%s: %#x %#x %u (%u) -> %#x & %#x -> %#x <%s>\n",
1198 1.2 matt __func__, pa->pa_tag, pa->pa_intrtag, pa->pa_intrpin, pa->pa_rawintrpin,
1199 1.2 matt tag, sc->sc_intrmask, tag & sc->sc_intrmask, prop_name);
1200 1.2 matt #endif
1201 1.2 matt
1202 1.2 matt entry = prop_dictionary_get(sc->sc_intrmap, prop_name);
1203 1.2 matt }
1204 1.2 matt KASSERT(entry != NULL);
1205 1.2 matt KASSERT(prop_object_type(entry) == PROP_TYPE_DICTIONARY);
1206 1.2 matt
1207 1.2 matt prop_number_t pn_irq = prop_dictionary_get(entry, "interrupt");
1208 1.2 matt KASSERT(pn_irq != NULL);
1209 1.2 matt KASSERT(prop_object_type(pn_irq) == PROP_TYPE_NUMBER);
1210 1.2 matt int irq = prop_number_unsigned_integer_value(pn_irq);
1211 1.2 matt prop_number_t pn_ist = prop_dictionary_get(entry, "type");
1212 1.2 matt KASSERT(pn_ist != NULL);
1213 1.2 matt KASSERT(prop_object_type(pn_ist) == PROP_TYPE_NUMBER);
1214 1.2 matt int ist = prop_number_unsigned_integer_value(pn_ist);
1215 1.2 matt
1216 1.2 matt return PIH_MAKE(irq, ist, 0);
1217 1.2 matt }
1218 1.2 matt
1219 1.2 matt static int
1220 1.5 dyoung pq3pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *handlep)
1221 1.2 matt {
1222 1.2 matt struct pq3pci_softc * const sc = pa->pa_pc->pc_intr_v;
1223 1.2 matt
1224 1.2 matt if (pa->pa_intrpin == PCI_INTERRUPT_PIN_NONE)
1225 1.2 matt return ENOENT;
1226 1.2 matt
1227 1.2 matt *handlep = pq3pci_intr_handle_lookup(sc, pa);
1228 1.2 matt
1229 1.2 matt return 0;
1230 1.2 matt }
1231 1.2 matt
1232 1.2 matt static const char *
1233 1.2 matt pq3pci_intr_string(void *v, pci_intr_handle_t handle)
1234 1.2 matt {
1235 1.2 matt if (PIH_IST(handle) == IST_MSI) {
1236 1.2 matt const char (*intr_names)[8] = msi_intr_names[0];
1237 1.2 matt return intr_names[PIH_IRQ(handle)];
1238 1.2 matt }
1239 1.2 matt
1240 1.2 matt return intr_string(PIH_IRQ(handle), PIH_IST(handle));
1241 1.2 matt }
1242 1.2 matt
1243 1.2 matt static const struct evcnt *
1244 1.2 matt pq3pci_intr_evcnt(void *v, pci_intr_handle_t handle)
1245 1.2 matt {
1246 1.2 matt struct pq3pci_softc * const sc = v;
1247 1.2 matt struct pq3pci_intrsource * const pis =
1248 1.2 matt pq3pci_intr_source_lookup(sc, handle);
1249 1.2 matt
1250 1.2 matt KASSERT(pis != NULL);
1251 1.2 matt
1252 1.2 matt return &pis->pis_ev;
1253 1.2 matt }
1254 1.2 matt
1255 1.2 matt static void *
1256 1.2 matt pq3pci_intr_establish(void *v, pci_intr_handle_t handle, int ipl,
1257 1.2 matt int (*func)(void *), void *arg)
1258 1.2 matt {
1259 1.2 matt struct pq3pci_softc * const sc = v;
1260 1.2 matt
1261 1.2 matt if (0) {
1262 1.2 matt struct pq3pci_callhand * const pch =
1263 1.2 matt kmem_zalloc(sizeof(*pch), KM_SLEEP);
1264 1.2 matt KASSERT(pch);
1265 1.2 matt pch->pch_ih.ih_arg = arg;
1266 1.2 matt pch->pch_ih.ih_func = func;
1267 1.2 matt pch->pch_ih.ih_sc = sc;
1268 1.2 matt pch->pch_ipl = ipl;
1269 1.2 matt
1270 1.2 matt callout_init(&pch->pch_callout, 0);
1271 1.2 matt callout_reset(&pch->pch_callout, 1, pq3pci_pch_callout, pch);
1272 1.2 matt
1273 1.2 matt return pch;
1274 1.2 matt }
1275 1.2 matt
1276 1.2 matt const int ist = PIH_IST(handle);
1277 1.2 matt
1278 1.2 matt if (ist == IST_MSI) {
1279 1.2 matt pci_chipset_tag_t pc = &sc->sc_pc;
1280 1.2 matt struct pq3pci_msihand * const msih = pq3pci_msi_claim(handle);
1281 1.2 matt pcireg_t cmdsts, msictl;
1282 1.2 matt
1283 1.2 matt if (msih == NULL)
1284 1.2 matt return NULL;
1285 1.2 matt
1286 1.2 matt struct pq3pci_msigroup * const msig = msih->msih_group;
1287 1.2 matt const pcitag_t tag = msih->msih_tag;
1288 1.2 matt
1289 1.2 matt mutex_spin_enter(msig->msig_lock);
1290 1.2 matt msih->msih_ih.ih_class = IH_MSI;
1291 1.2 matt msih->msih_ih.ih_arg = arg;
1292 1.2 matt msih->msih_ih.ih_func = func;
1293 1.2 matt msih->msih_ih.ih_sc = sc;
1294 1.2 matt
1295 1.2 matt int off = msih->msih_msioff;
1296 1.2 matt msictl = pci_conf_read(pc, tag, off);
1297 1.2 matt
1298 1.2 matt /*
1299 1.2 matt * The PCSRBAR has already been setup as a 1:1 BAR so we point
1300 1.2 matt * MSIs at the MSII register in the OpenPIC.
1301 1.2 matt */
1302 1.2 matt off += 4;
1303 1.2 matt pci_conf_write(pc, tag, off,
1304 1.2 matt sc->sc_bst->pbs_offset + OPENPIC_BASE + OPENPIC_MSIIR);
1305 1.2 matt
1306 1.2 matt /*
1307 1.2 matt * Upper address is going to be 0.
1308 1.2 matt */
1309 1.2 matt if (msictl & PCI_MSI_CTL_64BIT_ADDR) {
1310 1.2 matt off += 4;
1311 1.2 matt pci_conf_write(pc, tag, off, 0);
1312 1.2 matt }
1313 1.2 matt
1314 1.2 matt /*
1315 1.2 matt * Set the magic value. Since PCI writes this to the least
1316 1.2 matt * significant byte of AD[31:0], let's hope the bridge byte
1317 1.2 matt * swaps to so it's the most significant bytes or nothing is
1318 1.2 matt * going to happen.
1319 1.2 matt */
1320 1.2 matt off += 4;
1321 1.2 matt pci_conf_write(pc, tag, off, PIH_IRQ(handle));
1322 1.2 matt
1323 1.2 matt /*
1324 1.2 matt * Should the driver do this? How would it know to do it?
1325 1.2 matt */
1326 1.2 matt if (msictl & PCI_MSI_CTL_PERVEC_MASK) {
1327 1.2 matt off += 4;
1328 1.2 matt pci_conf_write(pc, tag, off, 0);
1329 1.2 matt }
1330 1.2 matt
1331 1.2 matt /*
1332 1.2 matt * Let's make sure he won't raise any INTx. Technically
1333 1.2 matt * setting MSI enable will prevent that as well but might
1334 1.2 matt * as well be as safe as possible.
1335 1.2 matt */
1336 1.2 matt cmdsts = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
1337 1.2 matt cmdsts |= PCI_COMMAND_INTERRUPT_DISABLE;
1338 1.2 matt pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmdsts);
1339 1.2 matt
1340 1.2 matt #if 1
1341 1.2 matt /*
1342 1.2 matt * Now we can enable the MSI
1343 1.2 matt */
1344 1.2 matt msictl |= PCI_MSI_CTL_MSI_ENABLE;
1345 1.2 matt pci_conf_write(pc, tag, msih->msih_msioff, msictl);
1346 1.2 matt #endif
1347 1.2 matt
1348 1.2 matt mutex_spin_exit(msig->msig_lock);
1349 1.2 matt
1350 1.2 matt #if 0
1351 1.2 matt struct pq3pci_callhand * const pch =
1352 1.2 matt kmem_zalloc(sizeof(*pch), KM_SLEEP);
1353 1.2 matt KASSERT(pch);
1354 1.2 matt
1355 1.2 matt pch->pch_ih.ih_arg = msig;
1356 1.2 matt pch->pch_ih.ih_func = pq3pci_msi_intr;
1357 1.2 matt #if 1
1358 1.2 matt pch->pch_ih.ih_arg = arg;
1359 1.2 matt pch->pch_ih.ih_func = func;
1360 1.2 matt #endif
1361 1.2 matt pch->pch_ih.ih_sc = sc;
1362 1.2 matt pch->pch_ipl = ipl;
1363 1.2 matt
1364 1.2 matt callout_init(&pch->pch_callout, 0);
1365 1.2 matt callout_reset(&pch->pch_callout, 1, pq3pci_pch_callout, pch);
1366 1.2 matt
1367 1.2 matt #if 1
1368 1.2 matt return pch;
1369 1.2 matt #endif
1370 1.2 matt #endif
1371 1.2 matt
1372 1.2 matt return msih;
1373 1.2 matt } else {
1374 1.2 matt struct pq3pci_intrsource * const pis =
1375 1.2 matt pq3pci_intr_source_lookup(sc, handle);
1376 1.2 matt KASSERT(pis != NULL);
1377 1.2 matt
1378 1.2 matt struct pq3pci_intrhand * const pih =
1379 1.2 matt kmem_zalloc(sizeof(*pih), KM_SLEEP);
1380 1.2 matt
1381 1.2 matt if (pih == NULL)
1382 1.2 matt return NULL;
1383 1.2 matt
1384 1.2 matt pih->pih_ih.ih_class = IH_INTX;
1385 1.2 matt pih->pih_ih.ih_func = func;
1386 1.2 matt pih->pih_ih.ih_arg = arg;
1387 1.2 matt pih->pih_ih.ih_sc = sc;
1388 1.2 matt pih->pih_ipl = ipl;
1389 1.2 matt pih->pih_source = pis;
1390 1.2 matt
1391 1.2 matt mutex_spin_enter(pis->pis_lock);
1392 1.2 matt SIMPLEQ_INSERT_TAIL(&pis->pis_ihands, pih, pih_link);
1393 1.2 matt mutex_spin_exit(pis->pis_lock);
1394 1.2 matt
1395 1.2 matt return pih;
1396 1.2 matt }
1397 1.2 matt }
1398 1.2 matt
1399 1.2 matt static void
1400 1.2 matt pq3pci_intr_disestablish(void *v, void *ih)
1401 1.2 matt {
1402 1.2 matt struct pq3pci_genihand * const gih = ih;
1403 1.2 matt
1404 1.2 matt if (gih->ih_class == IH_INTX) {
1405 1.2 matt struct pq3pci_intrhand * const pih = ih;
1406 1.2 matt struct pq3pci_intrsource * const pis = pih->pih_source;
1407 1.2 matt
1408 1.2 matt mutex_spin_enter(pis->pis_lock);
1409 1.2 matt SIMPLEQ_REMOVE(&pis->pis_ihands, pih, pq3pci_intrhand, pih_link);
1410 1.2 matt mutex_spin_exit(pis->pis_lock);
1411 1.2 matt
1412 1.2 matt kmem_free(pih, sizeof(*pih));
1413 1.2 matt return;
1414 1.2 matt }
1415 1.2 matt struct pq3pci_msihand * const msih = ih;
1416 1.2 matt struct pq3pci_msigroup * const msig = msih->msih_group;
1417 1.2 matt struct genppc_pci_chipset * const pc = &msih->msih_ih.ih_sc->sc_pc;
1418 1.2 matt const pcitag_t tag = msih->msih_tag;
1419 1.2 matt
1420 1.2 matt mutex_spin_enter(msig->msig_lock);
1421 1.2 matt
1422 1.2 matt /*
1423 1.2 matt * disable the MSI
1424 1.2 matt */
1425 1.2 matt pcireg_t msictl = pci_conf_read(pc, tag, msih->msih_msioff);
1426 1.2 matt msictl &= ~PCI_MSI_CTL_MSI_ENABLE;
1427 1.2 matt pci_conf_write(pc, tag, msih->msih_msioff, msictl);
1428 1.2 matt
1429 1.2 matt msih->msih_ih.ih_func = pq3pci_msi_spurious_intr;
1430 1.2 matt msih->msih_ih.ih_arg = msig;
1431 1.2 matt msih->msih_ih.ih_sc = NULL;
1432 1.2 matt msih->msih_tag = 0;
1433 1.2 matt msih->msih_msioff = 0;
1434 1.2 matt mutex_spin_exit(msig->msig_lock);
1435 1.2 matt }
1436 1.2 matt
1437 1.2 matt static void
1438 1.2 matt pq3pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin,
1439 1.2 matt int swiz, int *iline)
1440 1.2 matt {
1441 1.2 matt }
1442 1.2 matt
1443 1.2 matt static pci_chipset_tag_t
1444 1.2 matt pq3pci_pci_chipset_init(struct pq3pci_softc *sc)
1445 1.2 matt {
1446 1.2 matt struct genppc_pci_chipset * const pc = &sc->sc_pc;
1447 1.2 matt
1448 1.2 matt pc->pc_conf_v = sc;
1449 1.2 matt pc->pc_attach_hook = pq3pci_attach_hook;
1450 1.2 matt pc->pc_bus_maxdevs = pq3pci_bus_maxdevs;
1451 1.2 matt pc->pc_make_tag = pq3pci_make_tag;
1452 1.2 matt pc->pc_conf_read = pq3pci_conf_read;
1453 1.2 matt pc->pc_conf_write = pq3pci_conf_write;
1454 1.2 matt #ifdef PCI_NETBSD_CONFIGURE
1455 1.2 matt pc->pc_conf_hook = pq3pci_conf_hook;
1456 1.2 matt #endif
1457 1.2 matt
1458 1.2 matt pc->pc_intr_v = sc;
1459 1.2 matt pc->pc_intr_map = pq3pci_intr_map;
1460 1.2 matt pc->pc_intr_string = pq3pci_intr_string;
1461 1.2 matt pc->pc_intr_evcnt = pq3pci_intr_evcnt;
1462 1.2 matt pc->pc_intr_establish = pq3pci_intr_establish;
1463 1.2 matt pc->pc_intr_disestablish = pq3pci_intr_disestablish;
1464 1.2 matt pc->pc_conf_interrupt = pq3pci_conf_interrupt;
1465 1.2 matt pc->pc_decompose_tag = pq3pci_decompose_tag;
1466 1.2 matt pc->pc_conf_hook = pq3pci_conf_hook;
1467 1.2 matt
1468 1.2 matt /*
1469 1.2 matt * This is a horrible kludge but it makes life easier.
1470 1.2 matt */
1471 1.2 matt pc->pc_addr = (void *)(sc->sc_bsh + PEX_CONFIG_ADDR);
1472 1.2 matt pc->pc_data = (void *)(sc->sc_bsh + PEX_CONFIG_DATA);
1473 1.2 matt pc->pc_bus = 0;
1474 1.2 matt pc->pc_memt = &sc->sc_pci_mem_bst.bs_tag;
1475 1.2 matt pc->pc_iot = &sc->sc_pci_io_bst.bs_tag;
1476 1.3 matt
1477 1.2 matt SIMPLEQ_INIT(&pc->pc_pbi);
1478 1.2 matt
1479 1.2 matt return pc;
1480 1.2 matt }
1481