vrc4173bcu.c revision 1.3
1/*	$NetBSD: vrc4173bcu.c,v 1.3 2001/10/22 13:44:05 takemura Exp $	*/
2
3/*-
4 * Copyright (c) 2001 Enami Tsugutomo.
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 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/device.h>
32
33#include <machine/bus.h>
34
35#include <dev/pci/pcivar.h>
36#include <dev/pci/pcidevs.h>
37
38#include <machine/platid.h>
39#include <machine/platid_mask.h>
40
41#include <hpcmips/vr/vrc4173bcuvar.h>
42#include <hpcmips/vr/vrc4173icureg.h>
43#include <hpcmips/vr/vrc4173cmureg.h>
44
45#define	VRC4173BCU_BADR		0x10
46#ifdef DEBUG
47#define	DPRINTF(args)	printf args
48#else
49#define	DPRINTF(args)
50#endif
51
52#define USE_WINCE_CLKMASK	(~0)
53
54static int	vrc4173bcu_match(struct device *, struct cfdata *, void *);
55static void	vrc4173bcu_attach(struct device *, struct device *, void *);
56static int	vrc4173bcu_print(void *, const char *);
57
58int vrcintr_port = 1;		/* GPIO port to which VRCINT is
59				   connected to.  XXX. */
60
61struct cfattach vrc4173bcu_ca = {
62	sizeof(struct vrc4173bcu_softc), vrc4173bcu_match, vrc4173bcu_attach,
63};
64
65static struct vrc4173bcu_platdep {
66	platid_t *platid;
67	u_int32_t clkmask;
68} platdep_table[] = {
69	{
70		&platid_wild,
71		USE_WINCE_CLKMASK,	/* XXX */
72	},
73};
74
75int
76vrc4173bcu_match(struct device *parent, struct cfdata *match, void *aux)
77{
78	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
79
80	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NEC &&
81	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NEC_VRC4173_BCU)
82		return (1);
83
84	return (0);
85}
86
87void
88vrc4173bcu_attach(struct device *parent, struct device *self, void *aux)
89{
90	struct vrc4173bcu_softc *sc = (struct vrc4173bcu_softc *)self;
91	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
92	pci_chipset_tag_t pc = pa->pa_pc;
93	pcitag_t tag = pa->pa_tag;
94	pcireg_t csr;
95	char devinfo[256];
96	int i;
97	u_int16_t reg;
98	struct vrc4173bcu_platdep *platdep_info;
99#ifdef DEBUG
100	char buf[80];
101#endif
102
103	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
104	printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
105
106#if 0
107	printf("%s: ", sc->sc_dev.dv_xname);
108	pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
109#endif
110
111	csr = pci_conf_read(pc, tag, VRC4173BCU_BADR);
112	DPRINTF(("%s: base addr = 0x%08x\n", sc->sc_dev.dv_xname, csr));
113
114	platdep_info = platid_search(&platid, platdep_table,
115	    sizeof(platdep_table)/sizeof(*platdep_table),
116	    sizeof(*platdep_table));
117
118	/* Map I/O registers */
119	if (pci_mapreg_map(pa, VRC4173BCU_BADR, PCI_MAPREG_TYPE_IO, 0,
120	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size)) {
121		printf("%s: can't map mem space\n", sc->sc_dev.dv_xname);
122		return;
123	}
124
125	sc->sc_pc = pc;
126
127	/* Enable the device. */
128	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
129	DPRINTF(("%s: csr = 0x%08x", sc->sc_dev.dv_xname, csr));
130	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
131	    csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE);
132	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
133	DPRINTF((" -> 0x%08x\n", csr));
134
135	csr = pci_conf_read(pc, tag, VRC4173BCU_BADR);
136	DPRINTF(("%s: base addr = %x@0x%08x\n", sc->sc_dev.dv_xname,
137	    (int)sc->sc_size, csr));
138	DPRINTF(("%s: iot = 0x%08x, ioh = 0x%08x\n", sc->sc_dev.dv_xname,
139	    (int)sc->sc_iot, sc->sc_ioh));
140
141	/*
142	 * Map I/O space for ICU.
143	 */
144	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
145	    VRC4173ICU_IOBASE, VRC4173ICU_IOSIZE, &sc->sc_icuh)) {
146		printf(": can't map ICU i/o space\n");
147		return;
148	}
149
150	/*
151	 * Map I/O space for CMU.
152	 */
153	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
154	    VRC4173CMU_IOBASE, VRC4173CMU_IOSIZE, &sc->sc_cmuh)) {
155		printf(": can't map CMU i/o space\n");
156		return;
157	}
158
159	/* assert all reset bits */
160	bus_space_write_2(sc->sc_iot, sc->sc_cmuh, VRC4173CMU_SRST,
161	    VRC4173CMU_SRST_AC97 | VRC4173CMU_SRST_USB |
162	    VRC4173CMU_SRST_CARD2 | VRC4173CMU_SRST_CARD1);
163
164	/* set clock mask */
165	if (platdep_info->clkmask == USE_WINCE_CLKMASK) {
166		reg = bus_space_read_2(sc->sc_iot, sc->sc_cmuh,
167		    VRC4173CMU_SRST);
168		printf("%s: default clock mask is %04x\n",
169		    sc->sc_dev.dv_xname, reg);
170	} else {
171		bus_space_write_2(sc->sc_iot, sc->sc_cmuh,
172		    VRC4173CMU_CLKMSK, platdep_info->clkmask);
173	}
174
175	/* clear reset bit */
176	bus_space_write_2(sc->sc_iot, sc->sc_cmuh, VRC4173CMU_SRST, 0);
177
178#ifdef DEBUG
179	reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_SYSINT1);
180	bitmask_snprintf(reg,
181	    "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
182	    "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
183	    buf, sizeof(buf));
184	printf("%s: SYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf);
185
186	reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MKIUINT);
187	bitmask_snprintf(reg,
188	    "\20\1SCANINT\2KDATRDY\3KDATLOST\4B3\5B4\6B5\7B6\10B7"
189	    "\11B8\12B9\13B10\14B11\15B12\16B13\17B14\20B15",
190	    buf, sizeof(buf));
191	printf("%s: MKIUINT = 0x%s\n", sc->sc_dev.dv_xname, buf);
192
193	reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1);
194	bitmask_snprintf(reg,
195	    "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
196	    "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
197	    buf, sizeof(buf));
198	printf("%s: MSYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf);
199
200#if 1
201	reg = VRC4173ICU_USBINTR | VRC4173ICU_PIUINTR | VRC4173ICU_KIUINTR |
202	    VRC4173ICU_DOZEPIUINTR;
203	bus_space_write_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1, reg);
204
205	reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1);
206	bitmask_snprintf(reg,
207	    "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
208	    "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
209	    buf, sizeof(buf));
210	printf("%s: MSYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf);
211#endif
212#endif
213
214	for (i = 0; i < VRC4173BCU_NINTRHAND; i++)
215		sc->sc_intrhand[i].ih_func = NULL;
216
217	/*
218	 * Attach sub units found in vrc4173.  XXX.
219	 */
220	config_found(self, "vrc4173cmu", vrc4173bcu_print);
221	config_found(self, "vrc4173giu", vrc4173bcu_print);
222	config_found(self, "vrc4173piu", vrc4173bcu_print);
223	config_found(self, "vrc4173kiu", vrc4173bcu_print);
224	config_found(self, "vrc4173aiu", vrc4173bcu_print);
225	config_found(self, "vrc4173ps2u", vrc4173bcu_print);
226
227	/*
228	 * Establish VRCINT interrupt.  Normally connected to one of
229	 * GPIO pin in VR41xx.  XXX.
230	 */
231	sc->sc_ih = pci_vrcintr_establish(pc, vrcintr_port,
232	    vrc4173bcu_intr, sc);
233	if (sc->sc_ih != NULL)
234		printf("%s: interrupting at %p\n", sc->sc_dev.dv_xname,
235		    sc->sc_ih);
236}
237
238int
239vrc4173bcu_print(void *aux, const char *pnp)
240{
241	const char *name = aux;
242
243	if (pnp)
244		printf("%s at %s", name, pnp);
245
246	return (UNCONF);
247}
248
249int
250vrc4173bcu_intr(void *arg)
251{
252	struct vrc4173bcu_softc *sc = (struct vrc4173bcu_softc *)arg;
253	struct intrhand *ih;
254	u_int16_t reg;
255	int i, handled;
256
257	reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_SYSINT1);
258	if (reg == 0)
259		return (0);
260
261#if 0
262    {
263	char buf[80];
264	bitmask_snprintf(reg,
265	    "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
266	    "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
267	    buf, sizeof(buf));
268	printf("%s: %s\n", sc->sc_dev.dv_xname, buf);
269    }
270#endif
271	for (handled = i = 0; i < VRC4173BCU_NINTRHAND; i++) {
272		ih = &sc->sc_intrhand[i];
273		if (ih->ih_func != NULL && (reg & (1 << i)) != 0) {
274			handled = 1;
275			(*ih->ih_func)(ih->ih_arg);
276		}
277	}
278
279	return (handled);
280}
281
282void *
283vrc4173bcu_intr_establish(struct vrc4173bcu_softc *sc, int kind,
284    int (*func)(void *), void *arg)
285{
286	struct intrhand *ih;
287
288	DPRINTF(("vrc4173bcu_intr_establish: %d, %p, %p\n", kind, func, arg));
289	if (kind < 0 || kind >= VRC4173BCU_NINTRHAND)
290		return (NULL);
291
292	ih = &sc->sc_intrhand[kind];
293	if (ih->ih_func != NULL)
294		return (NULL);
295
296	ih->ih_func = func;
297	ih->ih_arg = arg;
298	return (ih);
299}
300
301void
302vrc4173bcu_intr_disestablish(struct vrc4173bcu_softc *sc, void *ihp)
303{
304	struct intrhand *ih = ihp;
305
306	if (ih < &sc->sc_intrhand[0] ||
307	    ih >= &sc->sc_intrhand[VRC4173BCU_NINTRHAND])
308		return;
309
310	ih->ih_func = NULL;
311}
312
313int
314vrc4173bcu_pci_bus_devorder(pci_chipset_tag_t pc, int busno, char *devs)
315{
316	int i, bcudev;
317
318	/*
319	 * XXX, we must attach Vrc4173 BCU first.
320	 */
321
322	/* search for BCU */
323	for (bcudev = 0; bcudev < 32; bcudev++) {
324		pcitag_t tag;
325		pcireg_t id;
326		tag = pci_make_tag(pc, 0, bcudev, 0);
327		id = pci_conf_read(pc, tag, PCI_ID_REG);
328		if (PCI_VENDOR(id) == PCI_VENDOR_NEC &&
329		    PCI_PRODUCT(id) ==PCI_PRODUCT_NEC_VRC4173_BCU)
330			break;
331	}
332	if (32 <= bcudev)
333		bcudev = 0;	/* not found */
334
335	*devs++ = bcudev;	/* scan BCU first */
336	for (i = 0; i < 32; i++)
337		if (i != bcudev)
338			*devs++ = i;
339	return (i);
340}
341
342int
343vrc4173bcu_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
344{
345	pci_chipset_tag_t pc = pa->pa_pc;
346	pcitag_t intrtag = pa->pa_intrtag;
347	int bus, dev, func;
348#ifdef DEBUG
349	int line = pa->pa_intrline;
350	int pin = pa->pa_intrpin;
351#endif
352
353	pci_decompose_tag(pc, intrtag, &bus, &dev, &func);
354	DPRINTF(("%s(%d, %d, %d): line = %d, pin = %d\n", pc->pc_dev->dv_xname,
355	    bus, dev, func, line, pin));
356
357	*ihp = -1;
358	switch (dev) {
359	case 1:				/* CARDU0 */
360		*ihp = VRC4173ICU_PCMCIA1INTR;
361		break;
362	case 2:				/* CARDU1 */
363		*ihp = VRC4173ICU_PCMCIA2INTR;
364		break;
365	case 19:			/* VRC4173 */
366		switch (func) {
367		case 2:
368			*ihp = VRC4173ICU_USBINTR;
369			break;
370		}
371		break;
372	}
373
374	return (*ihp == -1);
375}
376
377const char *
378vrc4173bcu_pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
379{
380	static char irqstr[8 + sizeof("vrc4173 intr")];
381
382	snprintf(irqstr, sizeof(irqstr), "vrc4173 intr %d", (int)ih);
383	return (irqstr);
384}
385
386const struct evcnt *
387vrc4173bcu_pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
388{
389
390	/* XXX for now, no evcnt parent reported */
391	return (NULL);
392}
393
394