pci_machdep.c revision 1.36
1/*	$NetBSD: pci_machdep.c,v 1.36 2014/07/29 21:21:44 skrll Exp $	*/
2
3/*
4 * Copyright (c) 2000 Soren S. Jorvang.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.36 2014/07/29 21:21:44 skrll Exp $");
30
31#define _MIPS_BUS_DMA_PRIVATE
32
33#include <sys/param.h>
34#include <sys/bus.h>
35#include <sys/errno.h>
36#include <sys/device.h>
37#include <sys/extent.h>
38#include <sys/intr.h>
39#include <sys/systm.h>
40#include <sys/time.h>
41
42#include <dev/pci/pcivar.h>
43#include <dev/pci/pcireg.h>
44#include <dev/pci/pcidevs.h>
45#include <dev/pci/pciconf.h>
46#include <dev/pci/pciide_apollo_reg.h>
47
48#include <cobalt/dev/gtreg.h>
49
50/*
51 * PCI doesn't have any special needs; just use
52 * the generic versions of these functions.
53 */
54struct mips_bus_dma_tag pci_bus_dma_tag = {
55	._dmamap_ops = _BUS_DMAMAP_OPS_INITIALIZER,
56	._dmamem_ops = _BUS_DMAMEM_OPS_INITIALIZER,
57	._dmatag_ops = _BUS_DMATAG_OPS_INITIALIZER,
58};
59
60void
61pci_attach_hook(device_t parent, device_t self, struct pcibus_attach_args *pba)
62{
63	/* XXX */
64
65	return;
66}
67
68int
69pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
70{
71
72	return 32;
73}
74
75pcitag_t
76pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
77{
78
79	return (bus << 16) | (device << 11) | (function << 8);
80}
81
82void
83pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
84{
85
86	if (bp != NULL)
87		*bp = (tag >> 16) & 0xff;
88	if (dp != NULL)
89		*dp = (tag >> 11) & 0x1f;
90	if (fp != NULL)
91		*fp = (tag >> 8) & 0x07;
92}
93
94pcireg_t
95pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
96{
97	pcireg_t data;
98	int bus, dev, func;
99
100	KASSERT(pc != NULL);
101
102	pci_decompose_tag(pc, tag, &bus, &dev, &func);
103
104	/*
105	 * 2700 hardware wedges on accesses to device 6.
106	 */
107	if (bus == 0 && dev == 6)
108		return 0;
109	/*
110	 * 2800 hardware wedges on accesses to device 31.
111	 */
112	if (bus == 0 && dev == 31)
113		return 0;
114
115	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR,
116	    PCICFG_ENABLE | tag | reg);
117	data = bus_space_read_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_DATA);
118	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR, 0);
119
120	return data;
121}
122
123void
124pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
125{
126
127	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR,
128	    PCICFG_ENABLE | tag | reg);
129	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_DATA, data);
130	bus_space_write_4(pc->pc_bst, pc->pc_bsh, GT_PCICFG_ADDR, 0);
131}
132
133int
134pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
135{
136	pci_chipset_tag_t pc = pa->pa_pc;
137	pcitag_t intrtag = pa->pa_intrtag;
138	int pin = pa->pa_intrpin;
139	int line = pa->pa_intrline;
140	int bus, dev, func;
141
142	pci_decompose_tag(pc, intrtag, &bus, &dev, &func);
143
144	/*
145	 * The interrupt lines of the internal Tulips are connected
146	 * directly to the CPU.
147	 */
148	if (cobalt_id == COBALT_ID_QUBE2700) {
149		if (bus == 0 && dev == 7 && pin == PCI_INTERRUPT_PIN_A) {
150			/* tulip is connected to CPU INT2 on Qube2700 */
151			*ihp = NICU_INT + 2;
152			return 0;
153		}
154	} else {
155		if (bus == 0 && dev == 7 && pin == PCI_INTERRUPT_PIN_A) {
156			/* the primary tulip is connected to CPU INT1 */
157			*ihp = NICU_INT + 1;
158			return 0;
159		}
160		if (bus == 0 && dev == 12 && pin == PCI_INTERRUPT_PIN_A) {
161			/* the secondary tulip is connected to CPU INT2 */
162			*ihp = NICU_INT + 2;
163			return 0;
164		}
165	}
166
167	/* sanity check */
168	if (line == 0 || line >= NICU_INT)
169		return -1;
170
171	*ihp = line;
172	return 0;
173}
174
175const char *
176pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char *buf, size_t len)
177{
178	if (ih >= NICU_INT)
179		snprintf(buf, len, "level %d", ih - NICU_INT);
180	else
181		snprintf(buf, len, "irq %d", ih);
182
183	return buf;
184}
185
186const struct evcnt *
187pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
188{
189
190	/* XXX for now, no evcnt parent reported */
191	return NULL;
192}
193
194int
195pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih,
196		 int attr, uint64_t data)
197{
198
199	switch (attr) {
200	case PCI_INTR_MPSAFE:
201		return 0;
202	default:
203		return ENODEV;
204	}
205}
206
207void *
208pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
209    int (*func)(void *), void *arg)
210{
211
212	if (ih >= NICU_INT)
213		return cpu_intr_establish(ih - NICU_INT, level, func, arg);
214	else
215		return icu_intr_establish(ih, IST_LEVEL, level, func, arg);
216}
217
218void
219pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
220{
221
222	/* Try both, only the valid one will disestablish. */
223	cpu_intr_disestablish(cookie);
224	icu_intr_disestablish(cookie);
225}
226
227void
228pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin, int swiz,
229    int *iline)
230{
231
232	/*
233	 * Use irq 9 on all devices on the Qube's PCI slot.
234	 * XXX doesn't handle devices over PCI-PCI bridges
235	 */
236	if (bus == 0 && dev == 10 && pin != PCI_INTERRUPT_PIN_NONE)
237		*iline = 9;
238}
239
240int
241pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func, pcireg_t id)
242{
243
244	/* ignore bogus IDs */
245	if (PCI_VENDOR(id) == 0)
246		return 0;
247
248	/* 2700 hardware wedges on accesses to device 6. */
249	if (bus == 0 && dev == 6)
250		return 0;
251
252	/* 2800 hardware wedges on accesses to device 31. */
253	if (bus == 0 && dev == 31)
254		return 0;
255
256	/* Don't configure the bridge and PCI probe. */
257	if (PCI_VENDOR(id) == PCI_VENDOR_MARVELL &&
258	    PCI_PRODUCT(id) == PCI_PRODUCT_MARVELL_GT64011)
259	        return 0;
260
261	/* Don't configure on-board VIA VT82C586 (pcib, uhci) */
262	if (bus == 0 && dev == 9 && (func == 0 || func == 2))
263		return 0;
264
265	/* Enable viaide secondary port. Some firmware doesn't enable it. */
266	if (bus == 0 && dev == 9 && func == 1) {
267		pcitag_t tag;
268		pcireg_t csr;
269
270#define	APO_VIAIDECONF	(APO_VIA_REGBASE + 0x00)
271
272		tag = pci_make_tag(pc, bus, dev, func);
273		csr = pci_conf_read(pc, tag, APO_VIAIDECONF);
274		pci_conf_write(pc, tag, APO_VIAIDECONF,
275		    csr | APO_IDECONF_EN(1));
276	}
277	return PCI_CONF_DEFAULT & ~(PCI_COMMAND_SERR_ENABLE |
278	    PCI_COMMAND_PARITY_ENABLE);
279}
280