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