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