vrc4172pci.c revision 1.1
1/*	$NetBSD: vrc4172pci.c,v 1.1 2002/03/22 09:18:09 takemura Exp $	*/
2
3/*-
4 * Copyright (c) 2002 TAKEMURA Shin
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/device.h>
35
36#include <machine/bus.h>
37#include <machine/bus_space_hpcmips.h>
38#include <machine/bus_dma_hpcmips.h>
39#include <machine/config_hook.h>
40#include <machine/platid.h>
41#include <machine/platid_mask.h>
42
43#include <dev/pci/pcivar.h>
44#include <dev/pci/pcidevs.h>
45#include <dev/pci/pciidereg.h>
46
47#include <hpcmips/vr/icureg.h>
48#include <hpcmips/vr/vripif.h>
49#include <hpcmips/vr/vrc4172pcireg.h>
50
51#include "pci.h"
52
53#ifdef DEBUG
54#define	DPRINTF(args)	printf args
55#else
56#define	DPRINTF(args)
57#endif
58
59struct vrc4172pci_softc {
60	struct device sc_dev;
61
62	bus_space_tag_t sc_iot;
63	bus_space_handle_t sc_ioh;
64
65	struct hpcmips_pci_chipset sc_pc;
66};
67
68static int	vrc4172pci_match(struct device *, struct cfdata *, void *);
69static void	vrc4172pci_attach(struct device *, struct device *, void *);
70#if NPCI > 0
71static int	vrc4172pci_print(void *, const char *);
72#endif
73static void	vrc4172pci_attach_hook(struct device *, struct device *,
74		    struct pcibus_attach_args *);
75static int	vrc4172pci_bus_maxdevs(pci_chipset_tag_t, int);
76static int	vrc4172pci_bus_devorder(pci_chipset_tag_t, int, char *);
77static pcitag_t	vrc4172pci_make_tag(pci_chipset_tag_t, int, int, int);
78static void	vrc4172pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *,
79		    int *, int *);
80static pcireg_t	vrc4172pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
81static void	vrc4172pci_conf_write(pci_chipset_tag_t, pcitag_t, int,
82		    pcireg_t);
83static int	vrc4172pci_intr_map(struct pci_attach_args *,
84		    pci_intr_handle_t *);
85static const char *vrc4172pci_intr_string(pci_chipset_tag_t,pci_intr_handle_t);
86static const struct evcnt *vrc4172pci_intr_evcnt(pci_chipset_tag_t,
87		    pci_intr_handle_t);
88static void	*vrc4172pci_intr_establish(pci_chipset_tag_t,
89		    pci_intr_handle_t, int, int (*)(void *), void *);
90static void	vrc4172pci_intr_disestablish(pci_chipset_tag_t, void *);
91
92struct cfattach vrc4172pci_ca = {
93	sizeof(struct vrc4172pci_softc), vrc4172pci_match, vrc4172pci_attach
94};
95
96static inline void
97vrc4172pci_write(struct vrc4172pci_softc *sc, int offset, u_int32_t val)
98{
99
100	bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val);
101}
102
103static inline u_int32_t
104vrc4172pci_read(struct vrc4172pci_softc *sc, int offset)
105{
106
107	return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset));
108}
109
110static int
111vrc4172pci_match(struct device *parent, struct cfdata *match, void *aux)
112{
113
114	return (1);
115}
116
117static void
118vrc4172pci_attach(struct device *parent, struct device *self, void *aux)
119{
120	struct vrc4172pci_softc *sc = (struct vrc4172pci_softc *)self;
121	pci_chipset_tag_t pc = &sc->sc_pc;
122	struct vrip_attach_args *va = aux;
123#if NPCI > 0
124	struct pcibus_attach_args pba;
125#endif
126
127	sc->sc_iot = va->va_iot;
128	if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 0,
129	    &sc->sc_ioh)) {
130		printf(": couldn't map io space\n");
131		return;
132	}
133	printf("\n");
134
135	pc->pc_dev = &sc->sc_dev;
136	pc->pc_attach_hook = vrc4172pci_attach_hook;
137	pc->pc_bus_maxdevs = vrc4172pci_bus_maxdevs;
138	pc->pc_bus_devorder = vrc4172pci_bus_devorder;
139	pc->pc_make_tag = vrc4172pci_make_tag;
140	pc->pc_decompose_tag = vrc4172pci_decompose_tag;
141	pc->pc_conf_read = vrc4172pci_conf_read;
142	pc->pc_conf_write = vrc4172pci_conf_write;
143	pc->pc_intr_map = vrc4172pci_intr_map;
144	pc->pc_intr_string = vrc4172pci_intr_string;
145	pc->pc_intr_evcnt = vrc4172pci_intr_evcnt;
146	pc->pc_intr_establish = vrc4172pci_intr_establish;
147	pc->pc_intr_disestablish = vrc4172pci_intr_disestablish;
148
149#if 0
150	{
151		int i;
152
153		for (i = 0; i < 2; i++)
154			printf("%s: ID_REG(0, 0, %d) = 0x%08x\n",
155			    sc->sc_dev.dv_xname, i,
156			    pci_conf_read(pc, pci_make_tag(pc, 0, 0, i),
157				PCI_ID_REG));
158	}
159#endif
160
161#if NPCI > 0
162	memset(&pba, 0, sizeof(pba));
163	pba.pba_busname = "pci";
164	pba.pba_iot = sc->sc_iot;
165	pba.pba_memt = sc->sc_iot;
166	pba.pba_dmat = &hpcmips_default_bus_dma_tag.bdt;
167	pba.pba_bus = 0;
168	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
169	    PCI_FLAGS_MRL_OKAY;
170	pba.pba_pc = pc;
171
172	config_found(self, &pba, vrc4172pci_print);
173#endif
174}
175
176#if NPCI > 0
177static int
178vrc4172pci_print(void *aux, const char *pnp)
179{
180	struct pcibus_attach_args *pba = aux;
181
182	if (pnp != NULL)
183		printf("%s at %s", pba->pba_busname, pnp);
184	else
185		printf(" bus %d", pba->pba_bus);
186
187	return (UNCONF);
188}
189#endif
190
191void
192vrc4172pci_attach_hook(struct device *parent, struct device *self,
193    struct pcibus_attach_args *pba)
194{
195
196	return;
197}
198
199int
200vrc4172pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
201{
202
203	return (1);	/* Vrc4172 has only one device */
204}
205
206int
207vrc4172pci_bus_devorder(pci_chipset_tag_t pc, int busno, char *devs)
208{
209	int i;
210
211	*devs++ = 0;
212	for (i = 1; i < 32; i++)
213		*devs++ = -1;
214
215	return (1);
216}
217
218pcitag_t
219vrc4172pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
220{
221
222	return ((bus << 16) | (device << 11) | (function << 8));
223}
224
225void
226vrc4172pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp,
227    int *fp)
228{
229
230	if (bp != NULL)
231		*bp = (tag >> 16) & 0xff;
232	if (dp != NULL)
233		*dp = (tag >> 11) & 0x1f;
234	if (fp != NULL)
235		*fp = (tag >> 8) & 0x07;
236}
237
238pcireg_t
239vrc4172pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
240{
241	struct vrc4172pci_softc *sc = (struct vrc4172pci_softc *)pc->pc_dev;
242	u_int32_t val;
243
244	tag |= VRC4172PCI_CONFADDR_CONFIGEN;
245
246	vrc4172pci_write(sc, VRC4172PCI_CONFAREG, tag | reg);
247	val = vrc4172pci_read(sc, VRC4172PCI_CONFDREG);
248#if 0
249	printf("%s: conf_read: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n",
250	    sc->sc_dev.dv_xname, (u_int32_t)tag, reg, val);
251#endif
252
253	return (val);
254}
255
256void
257vrc4172pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg,
258    pcireg_t data)
259{
260	struct vrc4172pci_softc *sc = (struct vrc4172pci_softc *)pc->pc_dev;
261
262#if 0
263	printf("%s: conf_write: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n",
264	    sc->sc_dev.dv_xname, (u_int32_t)tag, reg, (u_int32_t)data);
265#endif
266	tag |= VRC4172PCI_CONFADDR_CONFIGEN;
267
268	vrc4172pci_write(sc, VRC4172PCI_CONFAREG, tag | reg);
269	vrc4172pci_write(sc, VRC4172PCI_CONFDREG, data);
270}
271
272int
273vrc4172pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
274{
275	pci_chipset_tag_t pc = pa->pa_pc;
276	pcitag_t intrtag = pa->pa_intrtag;
277	int bus, dev, func;
278
279	pci_decompose_tag(pc, intrtag, &bus, &dev, &func);
280	DPRINTF(("%s(%d, %d, %d): line = %d, pin = %d\n", pc->pc_dev->dv_xname,
281	    bus, dev, func, pa->pa_intrline, pa->pa_intrpin));
282
283	*ihp = CONFIG_HOOK_PCIINTR_ID(bus, dev, func);
284
285	return (0);
286}
287
288const char *
289vrc4172pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
290{
291	static char irqstr[sizeof("pciintr") + 16];
292
293	snprintf(irqstr, sizeof(irqstr), "pciintr %d:%d:%d",
294	    CONFIG_HOOK_PCIINTR_BUS((int)ih),
295	    CONFIG_HOOK_PCIINTR_DEVICE((int)ih),
296	    CONFIG_HOOK_PCIINTR_FUNCTION((int)ih));
297
298	return (irqstr);
299}
300
301const struct evcnt *
302vrc4172pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
303{
304
305	return (NULL);
306}
307
308void *
309vrc4172pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
310    int level, int (*func)(void *), void *arg)
311{
312
313	if (ih == -1)
314		return (NULL);
315	DPRINTF(("vrc4172pci_intr_establish: %lx\n", ih));
316
317	return (config_hook(CONFIG_HOOK_PCIINTR, ih, CONFIG_HOOK_EXCLUSIVE,
318	    (int (*)(void *, int, long, void *))func, arg));
319}
320
321void
322vrc4172pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
323{
324
325	DPRINTF(("vrc4172pci_intr_disestablish: %p\n", cookie));
326	config_unhook(cookie);
327}
328