pq3pci.c revision 1.5
1/*	$NetBSD: pq3pci.c,v 1.5 2011/04/04 20:37:52 dyoung 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.5 2011/04/04 20:37:52 dyoung 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_ENABLED : PCI_FLAGS_MEM_ENABLED;
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	for (int rv = 0;;) {
513		uint32_t group = cpu_read_4(msig->msig_msir);
514		if (group == 0) {
515			mutex_spin_exit(msig->msig_lock);
516			return rv;
517		}
518
519		const bool working_msi_p =
520		    msig->msig_group != 0 || (group & 1) == 0;
521		if (working_msi_p) {
522			/*
523			 * if MSIs are working, just clear the free MSIs.
524			 */
525			group &= ~msig->msig_free_mask;
526		} else {
527			/*
528			 * If MSIs are broken, we don't really what MSIs
529			 * have happened.
530			 */
531			for (struct pq3pci_msihand *msih = msig->msig_ihands + 31;
532			     group != 0;
533			     msih--) {
534				const u_int n = __builtin_clz(group);
535				msih -= n;
536				group <<= n + 1;
537				msih->msih_ev.ev_count++;
538			}
539			group = ~msig->msig_free_mask;
540		}
541		for (struct pq3pci_msihand *msih = msig->msig_ihands + 31;
542		     group != 0;
543		     msih--) {
544			KASSERT(msig->msig_ihands <= msih);
545			KASSERT(msih < &msig->msig_ihands[32]);
546			const u_int n = __builtin_clz(group);
547			msih -= n;
548			group <<= n + 1;
549			msih->msih_ev.ev_count += working_msi_p;
550			if ((*msih->msih_ih.ih_func)(msih->msih_ih.ih_arg)) {
551				rv = 1;
552				msih->msih_ev.ev_count += !working_msi_p;
553			} else {
554				msih->msih_ev_spurious.ev_count += working_msi_p;
555			}
556		}
557	}
558}
559
560static int
561pq3pci_onchip_intr(void *v)
562{
563	panic(__func__);
564}
565
566static int
567pq3pci_pis_intr(void *v)
568{
569	struct pq3pci_intrsource * const pis = v;
570	struct pq3pci_intrhand *pih;
571	int rv = 0;
572
573	mutex_spin_enter(pis->pis_lock);
574	pis->pis_ev.ev_count++;
575	SIMPLEQ_FOREACH(pih, &pis->pis_ihands, pih_link) {
576		struct pq3pci_softc * const sc = pih->pih_ih.ih_sc;
577		int s = splraise(pih->pih_ipl);
578		pih->pih_count++;
579		rv = (*pih->pih_ih.ih_func)(pih->pih_ih.ih_arg);
580		splx(s);
581#if 0
582		printf("%s %d:%s %"PRIu64": %p(%p) %"PRIu64": %d\n", __func__,
583		    curcpu()->ci_idepth,
584		    pis->pis_ev.ev_group, pis->pis_ev.ev_count,
585		    pih->pih_ih.ih_func, pih->pih_ih.ih_arg, pih->pih_count, rv);
586#endif
587		if (rv != 0) {
588			bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCI_INT_ACK);
589			break;
590		}
591		pih->pih_count--;
592	}
593	if (rv == 0)
594		pis->pis_ev_spurious.ev_count++;
595	mutex_spin_exit(pis->pis_lock);
596	return rv;
597}
598
599static void
600pq3pci_intr_source_setup(struct pq3pci_softc *sc,
601	struct pq3pci_intrsource *pis, pci_intr_handle_t handle)
602{
603	SIMPLEQ_INIT(&pis->pis_ihands);
604	pis->pis_handle = handle;
605	pis->pis_ih = intr_establish(PIH_IRQ(handle), IPL_VM, PIH_IST(handle),
606	    pq3pci_pis_intr, pis);
607	pis->pis_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM);
608	const char * const intrstr
609	    = intr_string(PIH_IRQ(handle), PIH_IST(handle));
610	evcnt_attach_dynamic(&pis->pis_ev, EVCNT_TYPE_INTR,
611	    NULL, intrstr, "intr");
612	evcnt_attach_dynamic(&pis->pis_ev_spurious, EVCNT_TYPE_INTR,
613	    &pis->pis_ev, intrstr, "spurious intr");
614	SIMPLEQ_INSERT_TAIL(&pq3pci_intrsources, pis, pis_link);
615}
616
617static bool
618pq3pci_intrmap_setup(struct pq3pci_softc *sc,
619	const struct cpunode_locators *cnl)
620{
621	char prop_name[32];
622	snprintf(prop_name, sizeof(prop_name), "%s%u-interrupt-map",
623	    cnl->cnl_name, cnl->cnl_instance);
624	sc->sc_intrmap = board_info_get_object(prop_name);
625	if (sc->sc_intrmap == NULL) {
626		aprint_error(": missing %s board property", prop_name);
627		return false;
628	}
629
630	KASSERT(prop_object_type(sc->sc_intrmap) == PROP_TYPE_DICTIONARY);
631	prop_number_t pn = prop_dictionary_get(sc->sc_intrmap, "interrupt-mask");
632	KASSERT(pn != NULL);
633
634	sc->sc_intrmask = prop_number_unsigned_integer_value(pn);
635
636	sc->sc_ih = intr_establish(cnl->cnl_intrs[0], IPL_VM, IST_ONCHIP,
637	    pq3pci_onchip_intr, sc);
638	if (sc->sc_ih == NULL)
639		panic("%s: failed to establish interrupt %d\n",
640		    device_xname(sc->sc_dev), cnl->cnl_intrs[0]);
641
642	return true;
643}
644
645void
646pq3pci_cpunode_attach(device_t parent, device_t self, void *aux)
647{
648	struct cpunode_softc * const psc = device_private(parent);
649	struct pq3pci_softc * const sc = device_private(self);
650	struct cpunode_attach_args * const cna = aux;
651	struct cpunode_locators * const cnl = &cna->cna_locs;
652	char buf[32];
653
654	sc->sc_dev = self;
655	sc->sc_bst = cna->cna_memt;
656	psc->sc_children |= cna->cna_childmask;
657	sc->sc_pcie = strcmp(cnl->cnl_name, "pcie") == 0;
658
659	const uint32_t pordevsr = cpu_read_4(GLOBAL_BASE + PORDEVSR);
660	if (sc->sc_pcie) {
661		u_int lanes = e500_truth_decode(cnl->cnl_instance, pordevsr,
662		    pq3pci_pcie_lanes, __arraycount(pq3pci_pcie_lanes), 0);
663		if (lanes == 0) {
664			aprint_normal(": disabled\n");
665			return;
666		}
667		snprintf(buf, sizeof(buf), "PCI-Express x%u", lanes);
668	} else {
669		bool pcix_p = e500_truth_decode(cnl->cnl_instance, pordevsr,
670		    pq3pci_pci_pcix, __arraycount(pq3pci_pci_pcix), 0);
671		u_int width = e500_truth_decode(cnl->cnl_instance, pordevsr,
672		    pq3pci_pci_pci32, __arraycount(pq3pci_pci_pci32), 32);
673		snprintf(buf, sizeof(buf), "%u-bit PCI%s",
674		    width, (pcix_p ? "X" : ""));
675	}
676
677	if (!pq3pci_intrmap_setup(sc, cnl))
678		return;
679
680	evcnt_attach_dynamic(&sc->sc_ev_spurious, EVCNT_TYPE_INTR, NULL,
681	    device_xname(self), "spurious intr");
682
683	int error = bus_space_map(sc->sc_bst, cnl->cnl_addr, cnl->cnl_size, 0,
684	    &sc->sc_bsh);
685	if (error) {
686		aprint_error(": failed to map registers: %d\n", error);
687		return;
688	}
689
690	u_int valid_owins = 0;
691	for (u_int i = 1, off = PEXOTAR1 - PEXOTAR0;
692	     i < 4; i++, off += PEXOTAR1 - PEXOTAR0) {
693		struct pq3pci_owin owin;
694		owin.potar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
695		    PEXOTAR0 + off);
696		owin.potear = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
697		    PEXOTEAR0 + off);
698		owin.powbar = 0;
699		if (i > 0) {
700			/* Doesn't exist for outbound window 0 */
701			owin.powbar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
702			    PEXOWBAR1 - (PEXOTAR1 - PEXOTAR0) + off);
703		}
704		owin.powar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
705		    PEXOWAR0 + off);
706#if 0
707		aprint_normal_dev(self,
708		    "owin[%u]: potar=%#x potear=%#x powbar=%#x powar=%#x\n",
709		    i, owin.potar, owin.potear, owin.powbar, owin.powar);
710#endif
711		if (owin.powar & PEXOWAR_EN) {
712			valid_owins++;
713			if (!pq3pci_owin_setup(sc, i, &owin))
714				return;
715		}
716	}
717#ifndef PCI_NETBSD_CONFIGURE
718	if (valid_owins == 0) {
719		aprint_normal(": %s controller%s\n", buf,
720		    " (disabled)");
721		return;
722	}
723#endif
724
725	u_int valid_iwins = 0;
726	for (u_int i = 0, off = 0; i < 3; i++, off += PEXITAR2 - PEXITAR1) {
727		struct pq3pci_iwin iwin;
728		iwin.pitar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
729		    PEXITAR1 + off);
730		iwin.piwbar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
731		    PEXIWBAR1 + off);
732		if (i > 0) {
733			/* Doesn't exist */
734			iwin.piwbear = bus_space_read_4(sc->sc_bst,
735			    sc->sc_bsh,
736			    PEXIWBEAR2 - (PEXITAR2 - PEXITAR1) + off);
737		} else {
738			iwin.piwbear = 0;
739		}
740		iwin.piwar = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
741		    PEXIWAR1 + off);
742#if 0
743		aprint_normal_dev(self,
744		    "iwin[%u]: pitar=%#x piwbar=%#x piwbear=%#x piwar=%#x\n",
745		    i, iwin.pitar, iwin.piwbar, iwin.piwbear, iwin.piwar);
746#endif
747		if (iwin.piwar & PEXIWAR_EN) {
748			valid_iwins++;
749			if (!pq3pci_iwin_setup(sc, i, &iwin))
750				return;
751		}
752	}
753
754	sc->sc_conf_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM);
755
756	pci_chipset_tag_t pc = pq3pci_pci_chipset_init(sc);
757
758#ifndef PCI_NETBSD_CONFIGURE
759	if (valid_iwins == 0) {
760		aprint_normal(": %s controller%s\n", buf,
761		    " (disabled)");
762		return;
763	}
764#else
765	if (sc->sc_pcie && pci_conf_read(pc, 0, PEX_LTSSM) < LTSSM_L0) {
766		aprint_normal(": %s controller%s\n", buf,
767		    " (offline)");
768		return;
769	}
770	if (!sc->sc_pcie && (pci_conf_read(pc, 0, PCI_PBFR) & PBFR_PAH)) {
771		aprint_normal(": %s controller%s\n", buf,
772		    " (agent mode)");
773		return;
774	}
775	if (valid_iwins == 0) {
776		struct pq3pci_iwin iwin = {
777		    .pitar = 0,
778		    .piwbar = 0,
779		    .piwbear = 0,
780		    .piwar = PEXIWAR_EN|PEXIWAR_PF|PEXIWAR_TRGT_LOCALMEM
781			|PEXIWAR_RTT_MEM_SNOOP|PEXIWAR_WTT_MEM_SNOOP
782			|__SHIFTIN(30-__builtin_clz(pmemsize),PEXIWAR_IWS),
783		};
784		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXITAR2, iwin.pitar);
785		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXIWBAR2, iwin.piwbar);
786		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXIWBEAR2, iwin.piwbear);
787		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXIWAR2, iwin.piwar);
788
789		if (!pq3pci_iwin_setup(sc, 2, &iwin)) {
790			aprint_error(": error creating inbound window\n");
791			return;
792		}
793
794	}
795
796	if (valid_owins == 0) {
797		u_long membase, iobase;
798		error = extent_alloc(pcimem_ex, PCI_MEMSIZE, PCI_MEMSIZE,
799		   PCI_MEMSIZE, EX_WAITOK, &membase);
800		if (error) {
801			aprint_error(
802			    ": error allocating address space for %s: %d\n",
803			    "PCI memory", error);
804			return;
805		}
806		struct pq3pci_owin owin1 = {
807		    .potar = membase >> 12,
808		    .potear = 0,
809		    .powbar = membase >> 12,
810		    .powar = PEXOWAR_EN|PEXOWAR_TC0
811			|PEXOWAR_RTT_MEM|PEXOWAR_WTT_MEM
812			|__SHIFTIN(ilog2(PCI_MEMSIZE)-1,PEXOWAR_OWS),
813		};
814		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTAR1, owin1.potar);
815		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTEAR1, owin1.potear);
816		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWBAR1, owin1.powbar);
817		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWAR1, owin1.powar);
818		if (!pq3pci_owin_setup(sc, 1, &owin1)) {
819			aprint_error(
820			    ": error creating bus space for %s\n",
821			    "PCI memory");
822			return;
823		}
824
825		error = extent_alloc(pciio_ex, PCI_IOSIZE, PCI_IOSIZE,
826		   PCI_IOSIZE, EX_WAITOK, &iobase);
827		if (error) {
828			aprint_error(
829			    ": error allocating address space for %s: %d\n",
830			    "PCI I/O space", error);
831			return;
832		}
833		struct pq3pci_owin owin2 = {
834		    .potar = 0,
835		    .potear = 0,
836		    .powbar = iobase >> 12,
837		    .powar = PEXOWAR_EN|PEXOWAR_TC0
838			|PEXOWAR_RTT_IO|PEXOWAR_WTT_IO
839			|__SHIFTIN(ilog2(PCI_IOSIZE)-1,PEXOWAR_OWS),
840		};
841		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTAR2, owin2.potar);
842		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOTEAR2, owin2.potear);
843		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWBAR2, owin2.powbar);
844		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEXOWAR2, owin2.powar);
845		if (!pq3pci_owin_setup(sc, 2, &owin2)) {
846			aprint_error(
847			    ": error creating bus space for %s\n",
848			    "PCI I/O space");
849			return;
850		}
851
852		struct extent *ioext = extent_create("pciio", 0, PCI_IOSIZE,
853		     M_DEVBUF, NULL, 0, EX_NOWAIT);
854		struct extent *memext = extent_create("pcimem", membase,
855		     membase + PCI_MEMSIZE, M_DEVBUF, NULL, 0, EX_NOWAIT);
856
857		error = pci_configure_bus(pc, ioext, memext, NULL, 0,
858		    curcpu()->ci_ci.dcache_line_size);
859
860		extent_destroy(ioext);
861		extent_destroy(memext);
862
863		if (error) {
864			aprint_normal(": configuration failed\n");
865			return;
866		}
867	}
868#endif
869
870	aprint_normal(": %s controller%s\n", buf, "");
871
872	struct pcibus_attach_args pba;
873	memset(&pba, 0, sizeof(pba));
874
875	pba.pba_flags = sc->sc_pba_flags | PCI_FLAGS_MSI_OKAY
876	    | PCI_FLAGS_MSIX_OKAY;
877	if (pba.pba_flags & PCI_FLAGS_IO_ENABLED)
878		pba.pba_iot = pc->pc_iot;
879	if (pba.pba_flags & PCI_FLAGS_MEM_ENABLED)
880		pba.pba_memt = pc->pc_memt;
881	pba.pba_dmat = cna->cna_dmat;
882	pba.pba_pc = pc;
883	pba.pba_bus = 0;
884
885	/*
886	 * Program BAR0 so that MSIs can work.
887	 */
888	pci_conf_write(pc, 0, PCI_BAR0, sc->sc_bst->pbs_offset);
889	pcireg_t cmdsts = pci_conf_read(pc, 0, PCI_COMMAND_STATUS_REG);
890	cmdsts |= PCI_COMMAND_INTERRUPT_DISABLE;
891	pci_conf_write(pc, 0, PCI_COMMAND_STATUS_REG, cmdsts);
892
893#if 0
894	/*
895	 *
896	 */
897	pq3pci_intr_source_lookup(sc, PIH_MAKE(0, IST_LEVEL, 0));
898#endif
899#if 0
900	if (sc->sc_pcie)
901		pci_conf_print(pc, 0, NULL);
902#endif
903
904	config_found_ia(self, "pcibus", &pba, pcibusprint);
905}
906
907static void
908pq3pci_attach_hook(device_t parent, device_t self,
909	struct pcibus_attach_args *pba)
910{
911	/* do nothing */
912}
913
914static int
915pq3pci_bus_maxdevs(void *v, int busno)
916{
917	struct pq3pci_softc * const sc = v;
918	return sc->sc_pcie && busno < 2 ? 1 : 32;
919}
920
921static void
922pq3pci_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func)
923{
924	if (bus)
925		*bus = (tag >> 16) & 0xff;
926	if (dev)
927		*dev = (tag >> 11) & 0x1f;
928	if (func)
929		*func = (tag >> 8) & 0x07;
930}
931
932static pcitag_t
933pq3pci_make_tag(void *v, int bus, int dev, int func)
934{
935	return (bus << 16) | (dev << 11) | (func << 8);
936}
937
938static inline pcitag_t
939pq3pci_config_addr_read(pci_chipset_tag_t pc)
940{
941	pcitag_t v;
942        __asm volatile("lwz\t%0, 0(%1)" : "=r"(v) : "b"(pc->pc_addr));
943        __asm volatile("mbar\n\tmsync");
944	return v;
945}
946
947static inline void
948pq3pci_config_addr_write(pci_chipset_tag_t pc, pcitag_t v)
949{
950        __asm volatile("stw\t%0, 0(%1)" :: "r"(v), "b"(pc->pc_addr));
951        __asm volatile("mbar\n\tmsync");
952}
953
954static inline pcireg_t
955pq3pci_config_data_read(pci_chipset_tag_t pc)
956{
957	pcireg_t v;
958        __asm volatile("lwbrx\t%0, 0, %1" : "=r"(v) : "b"(pc->pc_data));
959        __asm volatile("mbar\n\tmsync");
960	return v;
961}
962
963static inline void
964pq3pci_config_data_write(pci_chipset_tag_t pc, pcireg_t v)
965{
966        __asm volatile("stwbrx\t%0, 0, %1" :: "r"(v), "r"(pc->pc_data));
967        __asm volatile("mbar\n\tmsync");
968}
969
970static pcireg_t
971pq3pci_conf_read(void *v, pcitag_t tag, int reg)
972{
973	struct pq3pci_softc * const sc = v;
974	struct genppc_pci_chipset * const pc = &sc->sc_pc;
975
976	if (reg >= 256) {
977		if (!sc->sc_pcie)
978			return 0xffffffff;
979		reg = (reg & 0xff) | ((reg & 0xf00) << 16);
980	}
981	if (sc->sc_pcie && ((tag >> 16) & 0xff) != 0) {
982	//	pcireg_t slot_status = pci_conf_read(pc, 0, 0x64);
983	//	printf("%s: tag 0x0 slot status: %#x\n",__func__, slot_status);
984	//	if ((slot_status & __BIT(6+16)) == 0)
985	//		printf(" addr=%#llx ", tag | reg | PEX_CONFIG_ADDR_EN);
986	//		return 0xffffffff;
987	}
988
989	mutex_spin_enter(sc->sc_conf_lock);
990
991	pq3pci_config_addr_write(pc, tag | reg | PEX_CONFIG_ADDR_EN);
992	pcireg_t rv = pq3pci_config_data_read(pc);
993
994	mutex_spin_exit(sc->sc_conf_lock);
995
996#if 0
997	uint32_t err = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PEX_ERR_DR);
998	if (err & PEXERRDR_ICCA) {
999		aprint_error_dev(sc->sc_dev, "%s: tag %#x reg %#x icca: %#x\n",
1000		    __func__, tag, reg, pq3pci_config_addr_read(pc));
1001		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PEX_ERR_DR,
1002		    PEXERRDR_ICCA);
1003	}
1004#endif
1005	return rv;
1006}
1007
1008static void
1009pq3pci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
1010{
1011	struct pq3pci_softc * const sc = v;
1012	struct genppc_pci_chipset * const pc = &sc->sc_pc;
1013
1014	if (reg >= 256) {
1015		if (!sc->sc_pcie)
1016			return;
1017		reg = (reg & 0xff) | ((reg & 0xf00) << 16);
1018	}
1019
1020	mutex_spin_enter(sc->sc_conf_lock);
1021
1022#if 0
1023	aprint_error_dev(sc->sc_dev, "%s: tag %#x reg %#x data %#x\n",
1024	    __func__, tag, reg, data);
1025#endif
1026	pq3pci_config_addr_write(pc, tag | reg | PEX_CONFIG_ADDR_EN);
1027	pq3pci_config_data_write(pc, data);
1028
1029	mutex_spin_exit(sc->sc_conf_lock);
1030}
1031
1032static int
1033pq3pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func,
1034	pcireg_t id)
1035{
1036	struct pq3pci_softc * const sc = pc->pc_conf_v;
1037	if (sc->sc_pcie && bus != 0) {
1038		pcireg_t slot_status = pci_conf_read(pc, 0, 0x64);
1039		if ((slot_status & __BIT(6+16)) == 0)
1040			return 0;
1041	}
1042	if (!sc->sc_pcie && bus == 0 && dev == 0) {
1043		return PCI_CONF_DEFAULT ^ (PCI_CONF_MAP_IO|PCI_CONF_MAP_MEM|PCI_CONF_MAP_ROM);
1044	}
1045	return PCI_CONF_DEFAULT;
1046}
1047
1048static void
1049pq3pci_msi_group_setup(struct pq3pci_msigroup *msig, u_int group, int ipl)
1050{
1051	const char (*intr_names)[8] = msi_intr_names[group];
1052
1053	KASSERT(ipl == IPL_VM);
1054
1055	pq3pci_msigroups[group] = msig;
1056	msig->msig_group = group;
1057	msig->msig_free_mask = ~0 << (group == 0);
1058	msig->msig_ipl = ipl;
1059	msig->msig_lock = mutex_obj_alloc(MUTEX_DEFAULT, ipl);
1060	msig->msig_ih = intr_establish(msig->msig_group, ipl, IST_MSIGROUP,
1061	    pq3pci_msi_intr, msig);
1062	msig->msig_msir = OPENPIC_BASE + OPENPIC_MSIR(msig->msig_group);
1063	for (u_int i = 0; i < __arraycount(msig->msig_ihands); i++) {
1064		struct pq3pci_msihand * const msih = msig->msig_ihands + i;
1065		msih->msih_ih.ih_class = IH_MSI;
1066		msih->msih_ih.ih_func = pq3pci_msi_spurious_intr;
1067		msih->msih_ih.ih_arg = msih;
1068		msih->msih_group = msig;
1069		evcnt_attach_dynamic(&msih->msih_ev, EVCNT_TYPE_INTR,
1070		    NULL, intr_names[i], "intr");
1071		evcnt_attach_dynamic(&msih->msih_ev_spurious, EVCNT_TYPE_INTR,
1072		    &msih->msih_ev, intr_names[i], "spurious intr");
1073	}
1074}
1075
1076static pci_intr_handle_t
1077pq3pci_msi_alloc(int ipl, u_int rmsi)
1078{
1079	size_t freegroup = 0;
1080	size_t maplen = __arraycount(pq3pci_msigroups);
1081	KASSERT(rmsi <= 5);
1082	uint32_t bitmap[maplen];
1083
1084	for (u_int i = 0; i < maplen; i++) {
1085		struct pq3pci_msigroup * const msig = pq3pci_msigroups[i];
1086		if (msig == NULL) {
1087			bitmap[i] = 0;
1088			if (freegroup == 0)
1089				freegroup = i + 1;
1090			continue;
1091		}
1092		/*
1093		 * If this msigroup has the wrong IPL or there's nothing
1094		 * free, try the next one.
1095		 */
1096		if (msig->msig_ipl != ipl || msig->msig_free_mask == 0) {
1097			bitmap[i] = 0;
1098			continue;
1099		}
1100
1101		bitmap[i] = msig->msig_free_mask;
1102	}
1103	for (u_int i = 0; i < maplen; i++) {
1104		uint32_t mapbits = bitmap[i];
1105		u_int n = ffs(mapbits);
1106		if (n--) {
1107			return PIH_MAKE(i * 32 + n, IST_MSI, 0);
1108		}
1109	}
1110
1111	if (freegroup-- == 0)
1112		return 0;
1113
1114	struct pq3pci_msigroup * const msig =
1115	    kmem_zalloc(sizeof(*msig), KM_SLEEP);
1116	KASSERT(msig != NULL);
1117	pq3pci_msi_group_setup(msig, freegroup, ipl);
1118	u_int n = ffs(msig->msig_free_mask) - 1;
1119	return PIH_MAKE(freegroup * 32 + n, IST_MSI, 0);
1120}
1121
1122static struct pq3pci_msihand *
1123pq3pci_msi_lookup(pci_intr_handle_t handle)
1124{
1125	const int irq = PIH_IRQ(handle);
1126	KASSERT(irq < 256);
1127	struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
1128	KASSERT(msig != NULL);
1129	return &msig->msig_ihands[irq & 31];
1130}
1131
1132static struct pq3pci_msihand *
1133pq3pci_msi_claim(pci_intr_handle_t handle)
1134{
1135	const int irq = PIH_IRQ(handle);
1136	uint32_t irq_mask = __BIT(irq & 31);
1137	KASSERT(irq < 256);
1138	struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
1139	KASSERT(msig != NULL);
1140	struct pq3pci_msihand * const msih = &msig->msig_ihands[irq & 31];
1141	mutex_spin_enter(msig->msig_lock);
1142	KASSERT(msig->msig_free_mask & irq_mask);
1143	msig->msig_free_mask ^= irq_mask;
1144	mutex_spin_exit(msig->msig_lock);
1145	return msih;
1146}
1147
1148static struct pq3pci_intrsource *
1149pq3pci_intr_source_lookup(struct pq3pci_softc *sc, pci_intr_handle_t handle)
1150{
1151	struct pq3pci_intrsource *pis;
1152	SIMPLEQ_FOREACH(pis, &pq3pci_intrsources, pis_link) {
1153		if (pis->pis_handle == handle)
1154			return pis;
1155	}
1156	pis = kmem_zalloc(sizeof(*pis), KM_SLEEP);
1157	pq3pci_intr_source_setup(sc, pis, handle);
1158	return pis;
1159}
1160
1161static pci_intr_handle_t
1162pq3pci_intr_handle_lookup(struct pq3pci_softc *sc,
1163    const struct pci_attach_args *pa)
1164{
1165	prop_dictionary_t entry;
1166
1167	if (sc->sc_pcie) do {
1168		pcireg_t msictl;
1169		int msioff;
1170		if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI,
1171					&msioff, &msictl))
1172			break;
1173		msictl = pci_conf_read(pa->pa_pc, pa->pa_tag, msioff);
1174		msictl &= ~PCI_MSI_CTL_MSI_ENABLE;
1175		msictl &= ~(PCI_MSI_CTL_MME_MASK << PCI_MSI_CTL_MME_SHIFT);
1176		int rmsi = (msictl >> PCI_MSI_CTL_MMC_SHIFT) & PCI_MSI_CTL_MMC_MASK;
1177		pci_conf_write(pa->pa_pc, pa->pa_tag, msioff, msictl);
1178		pci_intr_handle_t handle = pq3pci_msi_alloc(IPL_VM, rmsi);
1179		struct pq3pci_msihand * const msih = pq3pci_msi_lookup(handle);
1180		msih->msih_tag = pa->pa_tag;
1181		msih->msih_msioff = msioff;
1182		return handle;
1183	} while (false);
1184
1185
1186	if (sc->sc_intrmask == 0) {
1187		entry = prop_dictionary_get(sc->sc_intrmap, "000000");
1188	} else {
1189		char prop_name[8];
1190		u_int intrinc = __LOWEST_SET_BIT(sc->sc_intrmask);
1191		pcitag_t tag = (pa->pa_intrpin - PCI_INTERRUPT_PIN_A) * intrinc;
1192
1193		snprintf(prop_name, sizeof(prop_name), "%06x",
1194		    tag & sc->sc_intrmask);
1195
1196#if 0
1197		printf("%s: %#x %#x %u (%u) -> %#x & %#x -> %#x <%s>\n",
1198		    __func__, pa->pa_tag, pa->pa_intrtag, pa->pa_intrpin, pa->pa_rawintrpin,
1199		    tag, sc->sc_intrmask, tag & sc->sc_intrmask, prop_name);
1200#endif
1201
1202		entry = prop_dictionary_get(sc->sc_intrmap, prop_name);
1203	}
1204	KASSERT(entry != NULL);
1205	KASSERT(prop_object_type(entry) == PROP_TYPE_DICTIONARY);
1206
1207	prop_number_t pn_irq = prop_dictionary_get(entry, "interrupt");
1208	KASSERT(pn_irq != NULL);
1209	KASSERT(prop_object_type(pn_irq) == PROP_TYPE_NUMBER);
1210	int irq = prop_number_unsigned_integer_value(pn_irq);
1211	prop_number_t pn_ist = prop_dictionary_get(entry, "type");
1212	KASSERT(pn_ist != NULL);
1213	KASSERT(prop_object_type(pn_ist) == PROP_TYPE_NUMBER);
1214	int ist = prop_number_unsigned_integer_value(pn_ist);
1215
1216	return PIH_MAKE(irq, ist, 0);
1217}
1218
1219static int
1220pq3pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *handlep)
1221{
1222	struct pq3pci_softc * const sc = pa->pa_pc->pc_intr_v;
1223
1224	if (pa->pa_intrpin == PCI_INTERRUPT_PIN_NONE)
1225		return ENOENT;
1226
1227	*handlep = pq3pci_intr_handle_lookup(sc, pa);
1228
1229	return 0;
1230}
1231
1232static const char *
1233pq3pci_intr_string(void *v, pci_intr_handle_t handle)
1234{
1235	if (PIH_IST(handle) == IST_MSI) {
1236		const char (*intr_names)[8] = msi_intr_names[0];
1237		return intr_names[PIH_IRQ(handle)];
1238	}
1239
1240	return intr_string(PIH_IRQ(handle), PIH_IST(handle));
1241}
1242
1243static const struct evcnt *
1244pq3pci_intr_evcnt(void *v, pci_intr_handle_t handle)
1245{
1246	struct pq3pci_softc * const sc = v;
1247	struct pq3pci_intrsource * const pis =
1248	    pq3pci_intr_source_lookup(sc, handle);
1249
1250	KASSERT(pis != NULL);
1251
1252	return &pis->pis_ev;
1253}
1254
1255static void *
1256pq3pci_intr_establish(void *v, pci_intr_handle_t handle, int ipl,
1257	int (*func)(void *), void *arg)
1258{
1259	struct pq3pci_softc * const sc = v;
1260
1261	if (0) {
1262		struct pq3pci_callhand * const pch =
1263		    kmem_zalloc(sizeof(*pch), KM_SLEEP);
1264		KASSERT(pch);
1265		pch->pch_ih.ih_arg = arg;
1266		pch->pch_ih.ih_func = func;
1267		pch->pch_ih.ih_sc = sc;
1268		pch->pch_ipl = ipl;
1269
1270		callout_init(&pch->pch_callout, 0);
1271		callout_reset(&pch->pch_callout, 1, pq3pci_pch_callout, pch);
1272
1273		return pch;
1274	}
1275
1276	const int ist = PIH_IST(handle);
1277
1278	if (ist == IST_MSI) {
1279		pci_chipset_tag_t pc = &sc->sc_pc;
1280		struct pq3pci_msihand * const msih = pq3pci_msi_claim(handle);
1281		pcireg_t cmdsts, msictl;
1282
1283		if (msih == NULL)
1284			return NULL;
1285
1286		struct pq3pci_msigroup * const msig = msih->msih_group;
1287		const pcitag_t tag = msih->msih_tag;
1288
1289		mutex_spin_enter(msig->msig_lock);
1290		msih->msih_ih.ih_class = IH_MSI;
1291		msih->msih_ih.ih_arg = arg;
1292		msih->msih_ih.ih_func = func;
1293		msih->msih_ih.ih_sc = sc;
1294
1295		int off = msih->msih_msioff;
1296		msictl = pci_conf_read(pc, tag, off);
1297
1298		/*
1299		 * The PCSRBAR has already been setup as a 1:1 BAR so we point
1300		 * MSIs at the MSII register in the OpenPIC.
1301		 */
1302		off += 4;
1303		pci_conf_write(pc, tag, off,
1304		    sc->sc_bst->pbs_offset + OPENPIC_BASE + OPENPIC_MSIIR);
1305
1306		/*
1307		 * Upper address is going to be 0.
1308		 */
1309		if (msictl & PCI_MSI_CTL_64BIT_ADDR) {
1310			off += 4;
1311			pci_conf_write(pc, tag, off, 0);
1312		}
1313
1314		/*
1315		 * Set the magic value.  Since PCI writes this to the least
1316		 * significant byte of AD[31:0], let's hope the bridge byte
1317		 * swaps to so it's the most significant bytes or nothing is
1318		 * going to happen.
1319		 */
1320		off += 4;
1321		pci_conf_write(pc, tag, off, PIH_IRQ(handle));
1322
1323		/*
1324		 * Should the driver do this?  How would it know to do it?
1325		 */
1326		if (msictl & PCI_MSI_CTL_PERVEC_MASK) {
1327			off += 4;
1328			pci_conf_write(pc, tag, off, 0);
1329		}
1330
1331		/*
1332		 * Let's make sure he won't raise any INTx.  Technically
1333		 * setting MSI enable will prevent that as well but might
1334		 * as well be as safe as possible.
1335		 */
1336		cmdsts = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
1337		cmdsts |= PCI_COMMAND_INTERRUPT_DISABLE;
1338		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmdsts);
1339
1340#if 1
1341		/*
1342		 * Now we can enable the MSI
1343		 */
1344		msictl |= PCI_MSI_CTL_MSI_ENABLE;
1345		pci_conf_write(pc, tag, msih->msih_msioff, msictl);
1346#endif
1347
1348		mutex_spin_exit(msig->msig_lock);
1349
1350#if 0
1351		struct pq3pci_callhand * const pch =
1352		    kmem_zalloc(sizeof(*pch), KM_SLEEP);
1353		KASSERT(pch);
1354
1355		pch->pch_ih.ih_arg = msig;
1356		pch->pch_ih.ih_func = pq3pci_msi_intr;
1357#if 1
1358		pch->pch_ih.ih_arg = arg;
1359		pch->pch_ih.ih_func = func;
1360#endif
1361		pch->pch_ih.ih_sc = sc;
1362		pch->pch_ipl = ipl;
1363
1364		callout_init(&pch->pch_callout, 0);
1365		callout_reset(&pch->pch_callout, 1, pq3pci_pch_callout, pch);
1366
1367#if 1
1368		return pch;
1369#endif
1370#endif
1371
1372		return msih;
1373	} else {
1374		struct pq3pci_intrsource * const pis =
1375		    pq3pci_intr_source_lookup(sc, handle);
1376		KASSERT(pis != NULL);
1377
1378		struct pq3pci_intrhand * const pih =
1379		    kmem_zalloc(sizeof(*pih), KM_SLEEP);
1380
1381		if (pih == NULL)
1382			return NULL;
1383
1384		pih->pih_ih.ih_class = IH_INTX;
1385		pih->pih_ih.ih_func = func;
1386		pih->pih_ih.ih_arg = arg;
1387		pih->pih_ih.ih_sc = sc;
1388		pih->pih_ipl = ipl;
1389		pih->pih_source = pis;
1390
1391		mutex_spin_enter(pis->pis_lock);
1392		SIMPLEQ_INSERT_TAIL(&pis->pis_ihands, pih, pih_link);
1393		mutex_spin_exit(pis->pis_lock);
1394
1395		return pih;
1396	}
1397}
1398
1399static void
1400pq3pci_intr_disestablish(void *v, void *ih)
1401{
1402	struct pq3pci_genihand * const gih = ih;
1403
1404	if (gih->ih_class == IH_INTX) {
1405		struct pq3pci_intrhand * const pih = ih;
1406		struct pq3pci_intrsource * const pis = pih->pih_source;
1407
1408		mutex_spin_enter(pis->pis_lock);
1409		SIMPLEQ_REMOVE(&pis->pis_ihands, pih, pq3pci_intrhand, pih_link);
1410		mutex_spin_exit(pis->pis_lock);
1411
1412		kmem_free(pih, sizeof(*pih));
1413		return;
1414	}
1415	struct pq3pci_msihand * const msih = ih;
1416	struct pq3pci_msigroup * const msig = msih->msih_group;
1417	struct genppc_pci_chipset * const pc = &msih->msih_ih.ih_sc->sc_pc;
1418	const pcitag_t tag = msih->msih_tag;
1419
1420	mutex_spin_enter(msig->msig_lock);
1421
1422	/*
1423	 * disable the MSI
1424	 */
1425	pcireg_t msictl = pci_conf_read(pc, tag, msih->msih_msioff);
1426	msictl &= ~PCI_MSI_CTL_MSI_ENABLE;
1427	pci_conf_write(pc, tag, msih->msih_msioff, msictl);
1428
1429	msih->msih_ih.ih_func = pq3pci_msi_spurious_intr;
1430	msih->msih_ih.ih_arg = msig;
1431	msih->msih_ih.ih_sc = NULL;
1432	msih->msih_tag = 0;
1433	msih->msih_msioff = 0;
1434	mutex_spin_exit(msig->msig_lock);
1435}
1436
1437static void
1438pq3pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin,
1439	int swiz, int *iline)
1440{
1441}
1442
1443static pci_chipset_tag_t
1444pq3pci_pci_chipset_init(struct pq3pci_softc *sc)
1445{
1446	struct genppc_pci_chipset * const pc = &sc->sc_pc;
1447
1448	pc->pc_conf_v = sc;
1449	pc->pc_attach_hook = pq3pci_attach_hook;
1450        pc->pc_bus_maxdevs = pq3pci_bus_maxdevs;
1451        pc->pc_make_tag = pq3pci_make_tag;
1452        pc->pc_conf_read = pq3pci_conf_read;
1453        pc->pc_conf_write = pq3pci_conf_write;
1454#ifdef PCI_NETBSD_CONFIGURE
1455        pc->pc_conf_hook = pq3pci_conf_hook;
1456#endif
1457
1458        pc->pc_intr_v = sc;
1459        pc->pc_intr_map = pq3pci_intr_map;
1460        pc->pc_intr_string = pq3pci_intr_string;
1461        pc->pc_intr_evcnt = pq3pci_intr_evcnt;
1462        pc->pc_intr_establish = pq3pci_intr_establish;
1463        pc->pc_intr_disestablish = pq3pci_intr_disestablish;
1464        pc->pc_conf_interrupt = pq3pci_conf_interrupt;
1465        pc->pc_decompose_tag = pq3pci_decompose_tag;
1466        pc->pc_conf_hook = pq3pci_conf_hook;
1467
1468	/*
1469	 * This is a horrible kludge but it makes life easier.
1470	 */
1471        pc->pc_addr = (void *)(sc->sc_bsh + PEX_CONFIG_ADDR);
1472        pc->pc_data = (void *)(sc->sc_bsh + PEX_CONFIG_DATA);
1473        pc->pc_bus = 0;
1474        pc->pc_memt = &sc->sc_pci_mem_bst.bs_tag;
1475        pc->pc_iot = &sc->sc_pci_io_bst.bs_tag;
1476
1477	SIMPLEQ_INIT(&pc->pc_pbi);
1478
1479	return pc;
1480}
1481