xref: /netbsd-src/sys/dev/marvell/gtpci.c (revision 13d4bb4cc874de96add7fc4227d38a1d656b03d1)
1*13d4bb4cSthorpej /*	$NetBSD: gtpci.c,v 1.38 2022/09/25 18:45:45 thorpej Exp $	*/
2ff2281b4Smatt /*
3a748aedcSkiyohara  * Copyright (c) 2008, 2009 KIYOHARA Takashi
4ff2281b4Smatt  * All rights reserved.
5ff2281b4Smatt  *
6ff2281b4Smatt  * Redistribution and use in source and binary forms, with or without
7ff2281b4Smatt  * modification, are permitted provided that the following conditions
8ff2281b4Smatt  * are met:
9ff2281b4Smatt  * 1. Redistributions of source code must retain the above copyright
10ff2281b4Smatt  *    notice, this list of conditions and the following disclaimer.
11ff2281b4Smatt  * 2. Redistributions in binary form must reproduce the above copyright
12ff2281b4Smatt  *    notice, this list of conditions and the following disclaimer in the
13ff2281b4Smatt  *    documentation and/or other materials provided with the distribution.
14ff2281b4Smatt  *
15a748aedcSkiyohara  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16a748aedcSkiyohara  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17a748aedcSkiyohara  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18a748aedcSkiyohara  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19a748aedcSkiyohara  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20a748aedcSkiyohara  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21a748aedcSkiyohara  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22a748aedcSkiyohara  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23a748aedcSkiyohara  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24a748aedcSkiyohara  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25ff2281b4Smatt  * POSSIBILITY OF SUCH DAMAGE.
26ff2281b4Smatt  */
27ff2281b4Smatt 
28365cbd94Slukem #include <sys/cdefs.h>
29*13d4bb4cSthorpej __KERNEL_RCSID(0, "$NetBSD: gtpci.c,v 1.38 2022/09/25 18:45:45 thorpej Exp $");
30365cbd94Slukem 
31a748aedcSkiyohara #include "opt_pci.h"
32a748aedcSkiyohara #include "pci.h"
33a748aedcSkiyohara 
34ff2281b4Smatt #include <sys/param.h>
35a2a38285Sad #include <sys/bus.h>
36a748aedcSkiyohara #include <sys/device.h>
37a748aedcSkiyohara #include <sys/errno.h>
38a748aedcSkiyohara 
39a748aedcSkiyohara #include <prop/proplib.h>
40ff2281b4Smatt 
41ff2281b4Smatt #include <dev/pci/pcireg.h>
42ff2281b4Smatt #include <dev/pci/pcivar.h>
43ff2281b4Smatt #include <dev/pci/pciconf.h>
44a748aedcSkiyohara 
45ff2281b4Smatt #include <dev/marvell/gtpcireg.h>
46ff2281b4Smatt #include <dev/marvell/gtpcivar.h>
47a748aedcSkiyohara #include <dev/marvell/marvellreg.h>
48a748aedcSkiyohara #include <dev/marvell/marvellvar.h>
49ff2281b4Smatt 
50a748aedcSkiyohara #include <machine/pci_machdep.h>
51ff2281b4Smatt 
52a748aedcSkiyohara #include "locators.h"
530e4975dfSmatt 
54ff2281b4Smatt 
55a748aedcSkiyohara #define GTPCI_READ(sc, r) \
56a748aedcSkiyohara 	bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, r((sc)->sc_unit))
57a748aedcSkiyohara #define GTPCI_WRITE(sc, r, v) \
58a748aedcSkiyohara 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, r((sc)->sc_unit), (v))
59a748aedcSkiyohara #define GTPCI_WRITE_AC(sc, r, n, v) \
60a748aedcSkiyohara     bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, r((sc)->sc_unit, (n)), (v))
61ff2281b4Smatt 
62ff2281b4Smatt 
63a748aedcSkiyohara static int gtpci_match(device_t, struct cfdata *, void *);
6499747a80Scegger static void gtpci_attach(device_t, device_t, void *);
65ff2281b4Smatt 
66742d392dSkiyohara static void gtpci_init(struct gtpci_softc *, struct gtpci_prot *);
67a748aedcSkiyohara static void gtpci_barinit(struct gtpci_softc *);
68742d392dSkiyohara static void gtpci_protinit(struct gtpci_softc *, struct gtpci_prot *);
69a748aedcSkiyohara #if NPCI > 0
70a748aedcSkiyohara static void gtpci_pci_config(struct gtpci_softc *, bus_space_tag_t,
71a748aedcSkiyohara 			     bus_space_tag_t, bus_dma_tag_t, pci_chipset_tag_t,
72a748aedcSkiyohara 			     u_long, u_long, u_long, u_long, int);
73a748aedcSkiyohara #endif
74a748aedcSkiyohara 
75a748aedcSkiyohara 
76a748aedcSkiyohara CFATTACH_DECL_NEW(gtpci_gt, sizeof(struct gtpci_softc),
77a748aedcSkiyohara     gtpci_match, gtpci_attach, NULL, NULL);
78a748aedcSkiyohara CFATTACH_DECL_NEW(gtpci_mbus, sizeof(struct gtpci_softc),
79ff2281b4Smatt     gtpci_match, gtpci_attach, NULL, NULL);
80ff2281b4Smatt 
81ff2281b4Smatt 
82a748aedcSkiyohara /* ARGSUSED */
83a748aedcSkiyohara static int
gtpci_match(device_t parent,struct cfdata * match,void * aux)84a748aedcSkiyohara gtpci_match(device_t parent, struct cfdata *match, void *aux)
85d914d045Smatt {
86a748aedcSkiyohara 	struct marvell_attach_args *mva = aux;
87d914d045Smatt 
88a748aedcSkiyohara 	if (strcmp(mva->mva_name, match->cf_name) != 0)
89a748aedcSkiyohara 		return 0;
90ff2281b4Smatt 
91049fc261Skiyohara 	if (mva->mva_unit == MVA_UNIT_DEFAULT)
92049fc261Skiyohara 		return 0;
93a748aedcSkiyohara 	switch (mva->mva_model) {
94a748aedcSkiyohara 	case MARVELL_DISCOVERY:
95a748aedcSkiyohara 	case MARVELL_DISCOVERY_II:
96a748aedcSkiyohara 	case MARVELL_DISCOVERY_III:
97a748aedcSkiyohara #if 0	/* XXXXX */
98a748aedcSkiyohara 	case MARVELL_DISCOVERY_LT:
99a748aedcSkiyohara 	case MARVELL_DISCOVERY_V:
100a748aedcSkiyohara 	case MARVELL_DISCOVERY_VI:
101a748aedcSkiyohara #endif
102049fc261Skiyohara 		if (mva->mva_offset != MVA_OFFSET_DEFAULT)
103ff2281b4Smatt 			return 0;
104ff2281b4Smatt 	}
105ff2281b4Smatt 
106a748aedcSkiyohara 	mva->mva_size = GTPCI_SIZE;
107ff2281b4Smatt 	return 1;
108ff2281b4Smatt }
109ff2281b4Smatt 
110a748aedcSkiyohara /* ARGSUSED */
111a748aedcSkiyohara static void
gtpci_attach(device_t parent,device_t self,void * aux)112a748aedcSkiyohara gtpci_attach(device_t parent, device_t self, void *aux)
113ff2281b4Smatt {
114a748aedcSkiyohara 	struct gtpci_softc *sc = device_private(self);
115a748aedcSkiyohara 	struct marvell_attach_args *mva = aux;
116742d392dSkiyohara 	struct gtpci_prot *gtpci_prot;
117a748aedcSkiyohara 	prop_dictionary_t dict = device_properties(self);
118742d392dSkiyohara 	prop_object_t prot;
119742d392dSkiyohara #if NPCI > 0
120a748aedcSkiyohara 	prop_object_t pc, iot, memt;
121a748aedcSkiyohara 	prop_array_t int2gpp;
122a748aedcSkiyohara 	prop_object_t gpp;
123a748aedcSkiyohara 	pci_chipset_tag_t gtpci_chipset;
124a748aedcSkiyohara 	bus_space_tag_t gtpci_io_bs_tag, gtpci_mem_bs_tag;
125a748aedcSkiyohara 	uint64_t iostart = 0, ioend = 0, memstart = 0, memend = 0;
126a748aedcSkiyohara 	int cl_size = 0, intr;
127ff2281b4Smatt #endif
128ff2281b4Smatt 
129a748aedcSkiyohara 	aprint_normal(": Marvell PCI Interface\n");
130a748aedcSkiyohara 	aprint_naive("\n");
131a748aedcSkiyohara 
132742d392dSkiyohara 	prot = prop_dictionary_get(dict, "prot");
133742d392dSkiyohara 	if (prot != NULL) {
134742d392dSkiyohara 		KASSERT(prop_object_type(prot) == PROP_TYPE_DATA);
135742d392dSkiyohara 		gtpci_prot = __UNCONST(prop_data_data_nocopy(prot));
136742d392dSkiyohara 	} else {
137742d392dSkiyohara 		aprint_verbose_dev(self, "no protection property\n");
138742d392dSkiyohara 		gtpci_prot = NULL;
139742d392dSkiyohara 	}
140a748aedcSkiyohara #if NPCI > 0
141a748aedcSkiyohara 	iot = prop_dictionary_get(dict, "io-bus-tag");
14217a4632cSkiyohara 	if (iot != NULL) {
143a748aedcSkiyohara 		KASSERT(prop_object_type(iot) == PROP_TYPE_DATA);
144a748aedcSkiyohara 		gtpci_io_bs_tag = __UNCONST(prop_data_data_nocopy(iot));
14517a4632cSkiyohara 	} else {
14617a4632cSkiyohara 		aprint_error_dev(self, "no io-bus-tag property\n");
14717a4632cSkiyohara 		gtpci_io_bs_tag = NULL;
14817a4632cSkiyohara 	}
149a748aedcSkiyohara 	memt = prop_dictionary_get(dict, "mem-bus-tag");
15017a4632cSkiyohara 	if (memt != NULL) {
151a748aedcSkiyohara 		KASSERT(prop_object_type(memt) == PROP_TYPE_DATA);
152a748aedcSkiyohara 		gtpci_mem_bs_tag = __UNCONST(prop_data_data_nocopy(memt));
15317a4632cSkiyohara 	} else {
15417a4632cSkiyohara 		aprint_error_dev(self, "no mem-bus-tag property\n");
15517a4632cSkiyohara 		gtpci_mem_bs_tag = NULL;
15617a4632cSkiyohara 	}
157a748aedcSkiyohara 	pc = prop_dictionary_get(dict, "pci-chipset");
158a748aedcSkiyohara 	if (pc == NULL) {
159a748aedcSkiyohara 		aprint_error_dev(self, "no pci-chipset property\n");
160a748aedcSkiyohara 		return;
161a748aedcSkiyohara 	}
162a748aedcSkiyohara 	KASSERT(prop_object_type(pc) == PROP_TYPE_DATA);
163a748aedcSkiyohara 	gtpci_chipset = __UNCONST(prop_data_data_nocopy(pc));
164a748aedcSkiyohara #ifdef PCI_NETBSD_CONFIGURE
165a748aedcSkiyohara 	if (!prop_dictionary_get_uint64(dict, "iostart", &iostart)) {
166a748aedcSkiyohara 		aprint_error_dev(self, "no iostart property\n");
167a748aedcSkiyohara 		return;
168a748aedcSkiyohara 	}
169a748aedcSkiyohara 	if (!prop_dictionary_get_uint64(dict, "ioend", &ioend)) {
170a748aedcSkiyohara 		aprint_error_dev(self, "no ioend property\n");
171a748aedcSkiyohara 		return;
172a748aedcSkiyohara 	}
173a748aedcSkiyohara 	if (!prop_dictionary_get_uint64(dict, "memstart", &memstart)) {
174a748aedcSkiyohara 		aprint_error_dev(self, "no memstart property\n");
175a748aedcSkiyohara 		return;
176a748aedcSkiyohara 	}
177a748aedcSkiyohara 	if (!prop_dictionary_get_uint64(dict, "memend", &memend)) {
178a748aedcSkiyohara 		aprint_error_dev(self, "no memend property\n");
179a748aedcSkiyohara 		return;
180a748aedcSkiyohara 	}
181a748aedcSkiyohara 	if (!prop_dictionary_get_uint32(dict, "cache-line-size", &cl_size)) {
182a748aedcSkiyohara 		aprint_error_dev(self, "no cache-line-size property\n");
183a748aedcSkiyohara 		return;
184a748aedcSkiyohara 	}
185a748aedcSkiyohara #endif
186a748aedcSkiyohara #endif
187a748aedcSkiyohara 
188a748aedcSkiyohara 	sc->sc_dev = self;
189a748aedcSkiyohara 	sc->sc_model = mva->mva_model;
190a748aedcSkiyohara 	sc->sc_rev = mva->mva_revision;
191a748aedcSkiyohara 	sc->sc_unit = mva->mva_unit;
192a748aedcSkiyohara 	sc->sc_iot = mva->mva_iot;
193a748aedcSkiyohara 	if (bus_space_subregion(mva->mva_iot, mva->mva_ioh,
1942c444bf7Skiyohara 	    (mva->mva_offset != MVA_OFFSET_DEFAULT) ? mva->mva_offset : 0,
195a748aedcSkiyohara 	    mva->mva_size, &sc->sc_ioh)) {
196a748aedcSkiyohara 		aprint_error_dev(self, "can't map registers\n");
197a748aedcSkiyohara 		return;
198a748aedcSkiyohara 	}
199a748aedcSkiyohara 	sc->sc_pc = gtpci_chipset;
200742d392dSkiyohara 	gtpci_init(sc, gtpci_prot);
201a748aedcSkiyohara 
202a748aedcSkiyohara #if NPCI > 0
203a748aedcSkiyohara 	int2gpp = prop_dictionary_get(dict, "int2gpp");
204a748aedcSkiyohara 	if (int2gpp != NULL) {
205a748aedcSkiyohara 		if (prop_object_type(int2gpp) != PROP_TYPE_ARRAY) {
206a748aedcSkiyohara 			aprint_error_dev(self, "int2gpp not an array\n");
207a748aedcSkiyohara 			return;
208a748aedcSkiyohara 		}
2096913cbefSandvar 		aprint_normal_dev(self, "use interrupt pin:");
210a748aedcSkiyohara 		for (intr = PCI_INTERRUPT_PIN_A;
211a748aedcSkiyohara 		    intr <= PCI_INTERRUPT_PIN_D &&
212a748aedcSkiyohara 					intr < prop_array_count(int2gpp);
213a748aedcSkiyohara 		    intr++) {
214a748aedcSkiyohara 			gpp = prop_array_get(int2gpp, intr);
215a748aedcSkiyohara 			if (prop_object_type(gpp) != PROP_TYPE_NUMBER) {
216a748aedcSkiyohara 				aprint_error_dev(self,
217a748aedcSkiyohara 				    "int2gpp[%d] not an number\n", intr);
218a748aedcSkiyohara 				return;
219a748aedcSkiyohara 			}
220a748aedcSkiyohara 			aprint_normal(" %d",
221a748aedcSkiyohara 			    (int)prop_number_integer_value(gpp));
222a748aedcSkiyohara 		}
223a748aedcSkiyohara 		aprint_normal("\n");
224a748aedcSkiyohara 	}
225a748aedcSkiyohara 
226a748aedcSkiyohara 	gtpci_pci_config(sc, gtpci_io_bs_tag, gtpci_mem_bs_tag, mva->mva_dmat,
227a748aedcSkiyohara 	    gtpci_chipset, iostart, ioend, memstart, memend, cl_size);
228a748aedcSkiyohara #endif
229a748aedcSkiyohara }
230a748aedcSkiyohara 
231a748aedcSkiyohara static void
gtpci_init(struct gtpci_softc * sc,struct gtpci_prot * prot)232742d392dSkiyohara gtpci_init(struct gtpci_softc *sc, struct gtpci_prot *prot)
233a748aedcSkiyohara {
234a748aedcSkiyohara 	uint32_t reg;
235a748aedcSkiyohara 
236a748aedcSkiyohara 	/* First, all disable.  Also WA CQ 4382 (bit15 must set 1)*/
237a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_BARE, GTPCI_BARE_ALLDISABLE | (1 << 15));
238a748aedcSkiyohara 
239a748aedcSkiyohara 	/* Enable Internal Arbiter */
240a748aedcSkiyohara 	reg = GTPCI_READ(sc, GTPCI_AC);
241a748aedcSkiyohara 	reg |= GTPCI_AC_EN;
242a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_AC, reg);
243a748aedcSkiyohara 
244a748aedcSkiyohara 	gtpci_barinit(sc);
245742d392dSkiyohara 	if (prot != NULL)
246742d392dSkiyohara 		gtpci_protinit(sc, prot);
247a748aedcSkiyohara 
248a748aedcSkiyohara 	reg = GTPCI_READ(sc, GTPCI_ADC);
249a748aedcSkiyohara 	reg |= GTPCI_ADC_REMAPWRDIS;
250a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_ADC, reg);
251a748aedcSkiyohara 
252a748aedcSkiyohara 	/* enable CPU-2-PCI ordering */
253a748aedcSkiyohara 	reg = GTPCI_READ(sc, GTPCI_C);
254a748aedcSkiyohara 	reg |= GTPCI_C_CPU2PCIORDERING;
255a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_C, reg);
256a748aedcSkiyohara }
257a748aedcSkiyohara 
258a748aedcSkiyohara static void
gtpci_barinit(struct gtpci_softc * sc)259a748aedcSkiyohara gtpci_barinit(struct gtpci_softc *sc)
260a748aedcSkiyohara {
261a748aedcSkiyohara 	static const struct {
262a748aedcSkiyohara 		int tag;
263a748aedcSkiyohara 		int bars[2];	/* BAR Size registers */
264a748aedcSkiyohara 		int bare;	/* Bits of Base Address Registers Enable */
265a748aedcSkiyohara 		int func;
266a748aedcSkiyohara 		int balow;
267a748aedcSkiyohara 		int bahigh;
268a748aedcSkiyohara 	} maps[] = {
269a748aedcSkiyohara 		{ MARVELL_TAG_SDRAM_CS0,
270a748aedcSkiyohara 		  { GTPCI_CS0BARS(0),	GTPCI_CS0BARS(1) },
271a748aedcSkiyohara 		  GTPCI_BARE_CS0EN,	0, 0x10, 0x14 },
272a748aedcSkiyohara 		{ MARVELL_TAG_SDRAM_CS1,
273a748aedcSkiyohara 		  { GTPCI_CS1BARS(0),	GTPCI_CS1BARS(1) },
274a748aedcSkiyohara 		  GTPCI_BARE_CS1EN,	0, 0x18, 0x1c },
275a748aedcSkiyohara 		{ MARVELL_TAG_SDRAM_CS2,
276a748aedcSkiyohara 		  { GTPCI_CS2BARS(0),	GTPCI_CS2BARS(1) },
277a748aedcSkiyohara 		  GTPCI_BARE_CS2EN,	1, 0x10, 0x14 },
278a748aedcSkiyohara 		{ MARVELL_TAG_SDRAM_CS3,
279a748aedcSkiyohara 		  { GTPCI_CS3BARS(0),	GTPCI_CS3BARS(1) },
280a748aedcSkiyohara 		  GTPCI_BARE_CS3EN,	1, 0x18, 0x1c },
281a748aedcSkiyohara #if 0
282a748aedcSkiyohara 		{ ORION_TARGETID_INTERNALREG,
283a748aedcSkiyohara 		  { -1,			-1 },
284a748aedcSkiyohara 		  GTPCI_BARE_INTMEMEN,	0, 0x20, 0x24 },
285a748aedcSkiyohara 
286a748aedcSkiyohara 		{ ORION_TARGETID_DEVICE_CS0,
287a748aedcSkiyohara 		  { GTPCI_DCS0BARS(0),	GTPCI_DCS0BARS(1) },
288a748aedcSkiyohara 		  GTPCI_BARE_DEVCS0EN,	2, 0x10, 0x14 },
289a748aedcSkiyohara 		{ ORION_TARGETID_DEVICE_CS1,
290a748aedcSkiyohara 		  { GTPCI_DCS1BARS(0),	GTPCI_DCS1BARS(1) },
291a748aedcSkiyohara 		  GTPCI_BARE_DEVCS1EN,	2, 0x18, 0x1c },
292a748aedcSkiyohara 		{ ORION_TARGETID_DEVICE_CS2,
293a748aedcSkiyohara 		  { GTPCI_DCS2BARS(0),	GTPCI_DCS2BARS(1) },
294a748aedcSkiyohara 		  GTPCI_BARE_DEVCS2EN,	2, 0x20, 0x24 },
295a748aedcSkiyohara 		{ ORION_TARGETID_DEVICE_BOOTCS,
296a748aedcSkiyohara 		  { GTPCI_BCSBARS(0),	GTPCI_BCSBARS(1) },
297a748aedcSkiyohara 		  GTPCI_BARE_BOOTCSEN,	3, 0x18, 0x1c },
298a748aedcSkiyohara 		{ P2P Mem0 BAR,
299a748aedcSkiyohara 		  { GTPCI_P2PM0BARS(0),	GTPCI_P2PM0BARS(1) },
300a748aedcSkiyohara 		  GTPCI_BARE_P2PMEM0EN,	4, 0x10, 0x14 },
301a748aedcSkiyohara 		{ P2P I/O BAR,
302a748aedcSkiyohara 		  { GTPCI_P2PIOBARS(0),	GTPCI_P2PIOBARS(1) },
303a748aedcSkiyohara 		  GTPCI_BARE_P2PIO0EN,	4, 0x20, 0x24 },
304a748aedcSkiyohara 		{ Expansion ROM BAR,
305a748aedcSkiyohara 		  { GTPCI_EROMBARS(0),	GTPCI_EROMBARS(1) },
306a748aedcSkiyohara 		  0,				},
307a748aedcSkiyohara #endif
308a748aedcSkiyohara 
309a748aedcSkiyohara 		{ MARVELL_TAG_UNDEFINED,
310a748aedcSkiyohara 		  { -1,			-1 },
311a748aedcSkiyohara 		  -1,				-1, 0x00, 0x00 },
312a748aedcSkiyohara 	};
313a748aedcSkiyohara 	device_t pdev = device_parent(sc->sc_dev);
314a748aedcSkiyohara 	uint64_t base;
315387c0717Smrg 	uint32_t size, bare;
316387c0717Smrg 	int map, rv;
317a748aedcSkiyohara 
318a748aedcSkiyohara 
319a748aedcSkiyohara 	bare = GTPCI_BARE_ALLDISABLE;
320a748aedcSkiyohara 	for (map = 0; maps[map].tag != MARVELL_TAG_UNDEFINED; map++) {
321a748aedcSkiyohara 		rv = marvell_winparams_by_tag(pdev, maps[map].tag, NULL, NULL,
322a748aedcSkiyohara 		    &base, &size);
323a748aedcSkiyohara 		if (rv != 0 || size == 0)
324a748aedcSkiyohara 			continue;
325a748aedcSkiyohara 
326a748aedcSkiyohara 		if (maps[map].bars[sc->sc_unit] != -1)
327a748aedcSkiyohara 			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
328a748aedcSkiyohara 			    maps[map].bars[sc->sc_unit], GTPCI_BARSIZE(size));
329a748aedcSkiyohara 		bare &= ~maps[map].bare;
330a748aedcSkiyohara 
331a748aedcSkiyohara #if 0	/* shall move to pchb(4)? */
332a748aedcSkiyohara 		if (maps[map].func != -1) {
333a748aedcSkiyohara 			pcitag_t tag;
334a748aedcSkiyohara 			pcireg_t reg;
335387c0717Smrg 			int dev = GTPCI_P2PC_DEVNUM(p2pc);
336387c0717Smrg 			int bus = GTPCI_P2PC_BUSNUMBER(p2pc);
337387c0717Smrg 			uint32_t p2pc = GTPCI_READ(sc, GTPCI_P2PC);
338a748aedcSkiyohara 
339a748aedcSkiyohara 			tag = gtpci_make_tag(NULL, bus, dev, maps[map].func);
340a748aedcSkiyohara 			reg = gtpci_conf_read(sc, tag, maps[map].balow);
341a748aedcSkiyohara 			reg &= ~GTPCI_BARLOW_MASK;
342a748aedcSkiyohara 			reg |= GTPCI_BARLOW_BASE(base);
343a748aedcSkiyohara 			gtpci_conf_write(sc, tag, maps[map].balow, reg);
344a748aedcSkiyohara 			reg = gtpci_conf_read(sc, tag, maps[map].bahigh);
345a748aedcSkiyohara 			reg = (base >> 16) >> 16;
346a748aedcSkiyohara 			gtpci_conf_write(sc, tag, maps[map].bahigh, reg);
347a748aedcSkiyohara 		}
348a748aedcSkiyohara #endif
349a748aedcSkiyohara 	}
350a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_BARE, bare);
351a748aedcSkiyohara }
352a748aedcSkiyohara 
353a748aedcSkiyohara static void
gtpci_protinit(struct gtpci_softc * sc,struct gtpci_prot * ac_flags)354742d392dSkiyohara gtpci_protinit(struct gtpci_softc *sc, struct gtpci_prot *ac_flags)
355a748aedcSkiyohara {
356a748aedcSkiyohara 	enum {
357742d392dSkiyohara 		gt642xx = 0,
358742d392dSkiyohara 		mv643xx,
359742d392dSkiyohara 		arm_soc,
360a748aedcSkiyohara 	};
361742d392dSkiyohara 	const struct gtpci_ac_rshift {
362742d392dSkiyohara 		uint32_t base_rshift;
363742d392dSkiyohara 		uint32_t size_rshift;
364742d392dSkiyohara 	} ac_rshifts[] = {
365742d392dSkiyohara 		{ 20, 20, },	/* GT642xx */
366742d392dSkiyohara 		{  0,  0, },	/* MV643xx and after */
367742d392dSkiyohara 		{  0,  0, },	/* ARM SoC */
368a748aedcSkiyohara 	};
369a748aedcSkiyohara 	const uint32_t prot_tags[] = {
370a748aedcSkiyohara 		MARVELL_TAG_SDRAM_CS0,
371a748aedcSkiyohara 		MARVELL_TAG_SDRAM_CS1,
372a748aedcSkiyohara 		MARVELL_TAG_SDRAM_CS2,
373a748aedcSkiyohara 		MARVELL_TAG_SDRAM_CS3,
374a748aedcSkiyohara 		MARVELL_TAG_UNDEFINED
375a748aedcSkiyohara 	};
376a748aedcSkiyohara 	device_t pdev = device_parent(sc->sc_dev);
377a748aedcSkiyohara 	uint64_t acbase, base;
378a748aedcSkiyohara 	uint32_t acsize, size;
379742d392dSkiyohara 	int base_rshift, size_rshift, acbl_flags, acs_flags;
380a748aedcSkiyohara 	int prot, rv, p, t;
381a748aedcSkiyohara 
382a748aedcSkiyohara 	switch (sc->sc_model) {
383a748aedcSkiyohara 	case MARVELL_DISCOVERY:
384742d392dSkiyohara 		p = gt642xx;
385a748aedcSkiyohara 		break;
386a748aedcSkiyohara 
387a748aedcSkiyohara 	case MARVELL_DISCOVERY_II:
388a748aedcSkiyohara 	case MARVELL_DISCOVERY_III:
389a748aedcSkiyohara #if 0
390a748aedcSkiyohara 	case MARVELL_DISCOVERY_LT:
391a748aedcSkiyohara 	case MARVELL_DISCOVERY_V:
392a748aedcSkiyohara 	case MARVELL_DISCOVERY_VI:
393a748aedcSkiyohara #endif
394742d392dSkiyohara 		p = mv643xx;
395a748aedcSkiyohara 		break;
396a748aedcSkiyohara 
397a748aedcSkiyohara 	default:
398742d392dSkiyohara 		p = arm_soc;
399a748aedcSkiyohara 		break;
400a748aedcSkiyohara 	}
401742d392dSkiyohara 	base_rshift = ac_rshifts[p].base_rshift;
402742d392dSkiyohara 	size_rshift = ac_rshifts[p].size_rshift;
403742d392dSkiyohara 	acbl_flags = ac_flags->acbl_flags;
404742d392dSkiyohara 	acs_flags = ac_flags->acs_flags;
405a748aedcSkiyohara 
406a748aedcSkiyohara 	t = 0;
407a748aedcSkiyohara 	for (prot = 0; prot < GTPCI_NPCIAC; prot++) {
408a748aedcSkiyohara 		acbase = acsize = 0;
409a748aedcSkiyohara 
410a748aedcSkiyohara 		for ( ; prot_tags[t] != MARVELL_TAG_UNDEFINED; t++) {
411a748aedcSkiyohara 			rv = marvell_winparams_by_tag(pdev, prot_tags[t],
412a748aedcSkiyohara 			    NULL, NULL, &base, &size);
413a748aedcSkiyohara 			if (rv != 0 || size == 0)
414a748aedcSkiyohara 				continue;
415a748aedcSkiyohara 
416a748aedcSkiyohara 			if (acsize == 0 || base + size == acbase)
417a748aedcSkiyohara 				acbase = base;
418a748aedcSkiyohara 			else if (acbase + acsize != base)
419a748aedcSkiyohara 				break;
420a748aedcSkiyohara 			acsize += size;
421a748aedcSkiyohara 		}
422a748aedcSkiyohara 
423a748aedcSkiyohara 		if (acsize != 0) {
424a748aedcSkiyohara 			GTPCI_WRITE_AC(sc, GTPCI_ACBL, prot,
425742d392dSkiyohara 			   ((acbase & 0xffffffff) >> base_rshift) | acbl_flags);
426a748aedcSkiyohara 			GTPCI_WRITE_AC(sc, GTPCI_ACBH, prot,
427a748aedcSkiyohara 			    (acbase >> 32) & 0xffffffff);
428a748aedcSkiyohara 			GTPCI_WRITE_AC(sc, GTPCI_ACS, prot,
429742d392dSkiyohara 			    ((acsize - 1) >> size_rshift) | acs_flags);
430a748aedcSkiyohara 		} else {
431a748aedcSkiyohara 			GTPCI_WRITE_AC(sc, GTPCI_ACBL, prot, 0);
432a748aedcSkiyohara 			GTPCI_WRITE_AC(sc, GTPCI_ACBH, prot, 0);
433a748aedcSkiyohara 			GTPCI_WRITE_AC(sc, GTPCI_ACS, prot, 0);
434a748aedcSkiyohara 		}
435a748aedcSkiyohara 	}
436a748aedcSkiyohara 	return;
437a748aedcSkiyohara }
438a748aedcSkiyohara 
439a748aedcSkiyohara #if NPCI > 0
440a748aedcSkiyohara static void
gtpci_pci_config(struct gtpci_softc * sc,bus_space_tag_t iot,bus_space_tag_t memt,bus_dma_tag_t dmat,pci_chipset_tag_t pc,u_long iostart,u_long ioend,u_long memstart,u_long memend,int cacheline_size)441a748aedcSkiyohara gtpci_pci_config(struct gtpci_softc *sc, bus_space_tag_t iot,
442a748aedcSkiyohara 		 bus_space_tag_t memt, bus_dma_tag_t dmat, pci_chipset_tag_t pc,
443a748aedcSkiyohara 		 u_long iostart, u_long ioend, u_long memstart, u_long memend,
444a748aedcSkiyohara 		 int cacheline_size)
445a748aedcSkiyohara {
446a748aedcSkiyohara 	struct pcibus_attach_args pba;
447a748aedcSkiyohara 	uint32_t p2pc, command;
448a748aedcSkiyohara 
449a748aedcSkiyohara 	p2pc = GTPCI_READ(sc, GTPCI_P2PC);
450a748aedcSkiyohara 
451a748aedcSkiyohara #ifdef PCI_NETBSD_CONFIGURE
452ca8ce3aeSthorpej 	struct pciconf_resources *pcires = pciconf_resource_init();
45369a3e9b7Schs 
454ca8ce3aeSthorpej 	pciconf_resource_add(pcires, PCICONF_RESOURCE_IO,
455ca8ce3aeSthorpej 	    iostart, (ioend - iostart) + 1);
456ca8ce3aeSthorpej 	pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM,
457ca8ce3aeSthorpej 	    memstart, (memend - memstart) + 1);
458ca8ce3aeSthorpej 
459ca8ce3aeSthorpej 	pci_configure_bus(pc, pcires,
460a748aedcSkiyohara 	    GTPCI_P2PC_BUSNUMBER(p2pc), cacheline_size);
46169a3e9b7Schs 
462ca8ce3aeSthorpej 	pciconf_resource_fini(pcires);
463a748aedcSkiyohara #endif
464a748aedcSkiyohara 
465a748aedcSkiyohara 	pba.pba_iot = iot;
466a748aedcSkiyohara 	pba.pba_memt = memt;
467a748aedcSkiyohara 	pba.pba_dmat = dmat;
468a748aedcSkiyohara 	pba.pba_dmat64 = NULL;
469a748aedcSkiyohara 	pba.pba_pc = pc;
470a748aedcSkiyohara 	if (iot == NULL || memt == NULL) {
471a748aedcSkiyohara 		pba.pba_flags = 0;
472a748aedcSkiyohara 		aprint_error_dev(sc->sc_dev, "");
473a748aedcSkiyohara 		if (iot == NULL)
474a748aedcSkiyohara 			aprint_error("io ");
475a748aedcSkiyohara 		else
476a6b2b839Sdyoung 			pba.pba_flags |= PCI_FLAGS_IO_OKAY;
477a748aedcSkiyohara 		if (iot == NULL && memt == NULL)
478a748aedcSkiyohara 			aprint_error("and ");
479a748aedcSkiyohara 		if (memt == NULL)
480a748aedcSkiyohara 			aprint_error("mem");
481a748aedcSkiyohara 		else
482a6b2b839Sdyoung 			pba.pba_flags |= PCI_FLAGS_MEM_OKAY;
483a748aedcSkiyohara 		aprint_error(" access disabled\n");
484a748aedcSkiyohara 	} else
485a6b2b839Sdyoung 		pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
486a748aedcSkiyohara 	command = GTPCI_READ(sc, GTPCI_C);
487a748aedcSkiyohara 	if (command & GTPCI_C_MRDMUL)
488a748aedcSkiyohara 		pba.pba_flags |= PCI_FLAGS_MRM_OKAY;
489a748aedcSkiyohara 	if (command & GTPCI_C_MRDLINE)
490a748aedcSkiyohara 		pba.pba_flags |= PCI_FLAGS_MRL_OKAY;
491a748aedcSkiyohara 	pba.pba_flags |= PCI_FLAGS_MWI_OKAY;
492a748aedcSkiyohara 	pba.pba_bus = GTPCI_P2PC_BUSNUMBER(p2pc);
493a748aedcSkiyohara 	pba.pba_bridgetag = NULL;
494c7fb772bSthorpej 	config_found(sc->sc_dev, &pba, NULL, CFARGS_NONE);
495a748aedcSkiyohara }
496a748aedcSkiyohara 
497a748aedcSkiyohara 
498ff2281b4Smatt /*
499a748aedcSkiyohara  * Dependent code of PCI Interface of Marvell
500ff2281b4Smatt  */
501ff2281b4Smatt 
502a748aedcSkiyohara /* ARGSUSED */
503ff2281b4Smatt void
gtpci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)504a748aedcSkiyohara gtpci_attach_hook(device_t parent, device_t self,
505a748aedcSkiyohara 		  struct pcibus_attach_args *pba)
506ff2281b4Smatt {
507a748aedcSkiyohara 
508a748aedcSkiyohara 	/* Nothing */
509a748aedcSkiyohara }
510a748aedcSkiyohara 
511a748aedcSkiyohara /*
512a748aedcSkiyohara  * Bit map for configuration register:
513a748aedcSkiyohara  *   [31]    ConfigEn
514a748aedcSkiyohara  *   [30:24] Reserved
515a748aedcSkiyohara  *   [23:16] BusNum
516a748aedcSkiyohara  *   [15:11] DevNum
517a748aedcSkiyohara  *   [10: 8] FunctNum
518a748aedcSkiyohara  *   [ 7: 2] RegNum
519a748aedcSkiyohara  *   [ 1: 0] reserved
520a748aedcSkiyohara  */
521a748aedcSkiyohara 
522a748aedcSkiyohara /* ARGSUSED */
523a748aedcSkiyohara int
gtpci_bus_maxdevs(void * v,int busno)524a748aedcSkiyohara gtpci_bus_maxdevs(void *v, int busno)
525a748aedcSkiyohara {
526a748aedcSkiyohara 
527a748aedcSkiyohara 	return 32;	/* 32 device/bus */
528a748aedcSkiyohara }
529a748aedcSkiyohara 
530a748aedcSkiyohara /* ARGSUSED */
531a748aedcSkiyohara pcitag_t
gtpci_make_tag(void * v,int bus,int dev,int func)532a748aedcSkiyohara gtpci_make_tag(void *v, int bus, int dev, int func)
533a748aedcSkiyohara {
534a748aedcSkiyohara 
535a748aedcSkiyohara #if DIAGNOSTIC
536a748aedcSkiyohara 	if (bus >= 256 || dev >= 32 || func >= 8)
537a748aedcSkiyohara 		panic("pci_make_tag: bad request");
538a748aedcSkiyohara #endif
539a748aedcSkiyohara 
540a748aedcSkiyohara 	return (bus << 16) | (dev << 11) | (func << 8);
541a748aedcSkiyohara }
542a748aedcSkiyohara 
543a748aedcSkiyohara /* ARGSUSED */
544a748aedcSkiyohara void
gtpci_decompose_tag(void * v,pcitag_t tag,int * bp,int * dp,int * fp)545a748aedcSkiyohara gtpci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
546a748aedcSkiyohara {
547a748aedcSkiyohara 
548ff2281b4Smatt 	if (bp != NULL)
549a748aedcSkiyohara 		*bp = (tag >> 16) & 0xff;
550ff2281b4Smatt 	if (dp != NULL)
551a748aedcSkiyohara 		*dp = (tag >> 11) & 0x1f;
552ff2281b4Smatt 	if (fp != NULL)
553a748aedcSkiyohara 		*fp = (tag >> 8) & 0x07;
554ff2281b4Smatt }
555ff2281b4Smatt 
556ff2281b4Smatt pcireg_t
gtpci_conf_read(void * v,pcitag_t tag,int reg)557a748aedcSkiyohara gtpci_conf_read(void *v, pcitag_t tag, int reg)
558ff2281b4Smatt {
559a748aedcSkiyohara 	struct gtpci_softc *sc = v;
560a748aedcSkiyohara 	const pcireg_t addr = tag | reg;
561a748aedcSkiyohara 
562605f564fSmsaitoh 	if ((unsigned int)reg >= PCI_CONF_SIZE)
563605f564fSmsaitoh 		return -1;
564605f564fSmsaitoh 
565a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_CA, addr | GTPCI_CA_CONFIGEN);
566a748aedcSkiyohara 	if ((addr | GTPCI_CA_CONFIGEN) != GTPCI_READ(sc, GTPCI_CA))
567a748aedcSkiyohara 		return -1;
568a748aedcSkiyohara 
569a748aedcSkiyohara 	return GTPCI_READ(sc, GTPCI_CD);
570ff2281b4Smatt }
571ff2281b4Smatt 
572ff2281b4Smatt void
gtpci_conf_write(void * v,pcitag_t tag,int reg,pcireg_t data)573a748aedcSkiyohara gtpci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
574ff2281b4Smatt {
575a748aedcSkiyohara 	struct gtpci_softc *sc = v;
576a748aedcSkiyohara 	pcireg_t addr = tag | (reg & 0xfc);
577a748aedcSkiyohara 
578605f564fSmsaitoh 	if ((unsigned int)reg >= PCI_CONF_SIZE)
579605f564fSmsaitoh 		return;
580605f564fSmsaitoh 
581a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_CA, addr | GTPCI_CA_CONFIGEN);
582a748aedcSkiyohara 	if ((addr | GTPCI_CA_CONFIGEN) != GTPCI_READ(sc, GTPCI_CA))
583a748aedcSkiyohara 		return;
584a748aedcSkiyohara 
585a748aedcSkiyohara 	GTPCI_WRITE(sc, GTPCI_CD, data);
586a748aedcSkiyohara }
587a748aedcSkiyohara 
588a748aedcSkiyohara /* ARGSUSED */
589a748aedcSkiyohara int
gtpci_conf_hook(void * v,int bus,int dev,int func,pcireg_t id)590a8140c3aSmatt gtpci_conf_hook(void *v, int bus, int dev, int func, pcireg_t id)
591a748aedcSkiyohara {
592a748aedcSkiyohara 	/* Oops, We have two PCI buses. */
593a748aedcSkiyohara 	if (dev == 0 &&
594a748aedcSkiyohara 	    PCI_VENDOR(id) == PCI_VENDOR_MARVELL) {
595a748aedcSkiyohara 		switch (PCI_PRODUCT(id)) {
596a748aedcSkiyohara 		case MARVELL_DISCOVERY:
597a748aedcSkiyohara 		case MARVELL_DISCOVERY_II:
598a748aedcSkiyohara 		case MARVELL_DISCOVERY_III:
599a748aedcSkiyohara #if 0
600a748aedcSkiyohara 		case MARVELL_DISCOVERY_LT:
601a748aedcSkiyohara 		case MARVELL_DISCOVERY_V:
602a748aedcSkiyohara 		case MARVELL_DISCOVERY_VI:
603ff2281b4Smatt #endif
604a748aedcSkiyohara 		case MARVELL_ORION_1_88F5180N:
605a748aedcSkiyohara 		case MARVELL_ORION_1_88F5181:
606a748aedcSkiyohara 		case MARVELL_ORION_1_88F5182:
607a748aedcSkiyohara 		case MARVELL_ORION_2_88F5281:
608a748aedcSkiyohara 		case MARVELL_ORION_1_88W8660:
609a748aedcSkiyohara 			/* Don't configure us. */
610a748aedcSkiyohara 			return 0;
611a748aedcSkiyohara 		}
612ff2281b4Smatt 	}
613ff2281b4Smatt 
614a748aedcSkiyohara 	return PCI_CONF_DEFAULT;
615ff2281b4Smatt }
616a748aedcSkiyohara #endif	/* NPCI > 0 */
617