isa_machdep.c revision 1.13
1/*	$NetBSD: isa_machdep.c,v 1.13 2001/04/30 11:42:18 takemura Exp $	*/
2
3/*
4 * Copyright (c) 1999, by UCHIYAMA Yasushi
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. The name of the developer may NOT be used to endorse or promote products
13 *    derived from this software without specific prior written permission.
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/param.h>
29#include <sys/systm.h>
30#include <sys/device.h>
31#include <sys/reboot.h>
32
33#include <machine/bus.h>
34
35#include <dev/isa/isavar.h>
36#include <dev/isa/isareg.h>
37
38#include <machine/platid.h>
39#include <machine/platid_mask.h>
40
41#include <dev/hpc/hpciovar.h>
42
43#include <hpcmips/hpcmips/machdep.h>
44#include "opt_vr41xx.h"
45#include <hpcmips/vr/vrcpudef.h>
46#include <hpcmips/vr/vripreg.h>
47#include <hpcmips/vr/vripvar.h>
48
49#include "locators.h"
50
51#define VRISADEBUG
52
53#ifdef VRISADEBUG
54#ifndef VRISADEBUG_CONF
55#define VRISADEBUG_CONF 0
56#endif /* VRISADEBUG_CONF */
57int vrisa_debug = VRISADEBUG_CONF;
58#define DPRINTF(arg) if (vrisa_debug) printf arg;
59#define DBITDISP32(mask) if (vrisa_debug) bitdisp32(mask);
60#define VPRINTF(arg) if (bootverbose || vrisa_debug) printf arg;
61#else /* VRISADEBUG */
62#define DPRINTF(arg)
63#define DBITDISP32(mask)
64#define VPRINTF(arg) if (bootverbose) printf arg;
65#endif /* VRISADEBUG */
66
67/*
68 * intrrupt no. encoding:
69 *
70 * 0x0000000f ISA IRQ#
71 * 0x00ff0000 GPIO port#
72 * 0x01000000 interrupt signal hold/through	(1:hold/0:though)
73 * 0x02000000 interrupt detection level		(1:low /0:high	)
74 * 0x04000000 interrupt detection trigger	(1:edge/0:level	)
75 */
76#define INTR_IRQ(i)	(((i)>> 0) & 0x0f)
77#define INTR_PORT(i)	(((i)>>16) & 0xff)
78#define INTR_MODE(i)	(((i)>>24) & 0x07)
79#define INTR_NIRQS	16
80
81int	vrisabprint __P((void*, const char*));
82int	vrisabmatch __P((struct device*, struct cfdata*, void*));
83void	vrisabattach __P((struct device*, struct device*, void*));
84
85struct vrisab_softc {
86	struct device sc_dev;
87	hpcio_chip_t sc_hc;
88	int sc_intr_map[INTR_NIRQS]; /* ISA <-> GIU inerrupt line mapping */
89	struct hpcmips_isa_chipset sc_isa_ic;
90};
91
92struct cfattach vrisab_ca = {
93	sizeof(struct vrisab_softc), vrisabmatch, vrisabattach
94};
95
96#ifdef DEBUG_FIND_PCIC
97#include <mips/cpuregs.h>
98#warning DEBUG_FIND_PCIC
99static void __find_pcic __P((void));
100#endif
101
102#ifdef DEBUG_FIND_COMPORT
103#include <mips/cpuregs.h>
104#include <dev/ic/ns16550reg.h>
105#include <dev/ic/comreg.h>
106#warning DEBUG_FIND_COMPORT
107static void __find_comport __P((void));
108#endif
109
110
111int
112vrisabmatch(parent, match, aux)
113	struct device *parent;
114	struct cfdata *match;
115	void *aux;
116{
117	struct hpcio_attach_args *haa = aux;
118	platid_mask_t mask;
119
120	if (strcmp(haa->haa_busname, match->cf_driver->cd_name))
121		return 0;
122	if (match->cf_loc[HPCIOIFCF_PLATFORM] == HPCIOIFCF_PLATFORM_DEFAULT)
123		return 1;
124	mask = PLATID_DEREF(match->cf_loc[HPCIOIFCF_PLATFORM]);
125	if (platid_match(&platid, &mask))
126		return 2;
127	return 0;
128}
129
130void
131vrisabattach(parent, self, aux)
132	struct device *parent;
133	struct device *self;
134	void *aux;
135{
136	struct hpcio_attach_args *haa = aux;
137	struct vrisab_softc *sc = (void*)self;
138	struct isabus_attach_args iba;
139	bus_addr_t offset;
140	int i;
141
142	sc->sc_hc = (*haa->haa_getchip)(haa->haa_sc, VRIP_IOCHIP_VRGIU);
143	sc->sc_isa_ic.ic_sc = sc;
144
145	iba.iba_busname = "isa";
146	iba.iba_ic	= &sc->sc_isa_ic;
147	iba.iba_dmat    = 0; /* XXX not yet */
148
149	/* Allocate ISA memory space */
150	iba.iba_memt    = hpcmips_alloc_bus_space_tag();
151	strcpy(iba.iba_memt->t_name, "ISA mem");
152	offset = sc->sc_dev.dv_cfdata->cf_loc[VRISABIFCF_ISAMEMOFFSET];
153	iba.iba_memt->t_base = VR_ISA_MEM_BASE + offset;
154	iba.iba_memt->t_size = VR_ISA_MEM_SIZE - offset;
155	hpcmips_init_bus_space_extent(iba.iba_memt);
156
157	/* Allocate ISA port space */
158	iba.iba_iot     = hpcmips_alloc_bus_space_tag();
159	strcpy(iba.iba_iot->t_name, "ISA port");
160	/* Platform dependent setting. */
161	offset = sc->sc_dev.dv_cfdata->cf_loc[VRISABIFCF_ISAPORTOFFSET];
162	iba.iba_iot->t_base = VR_ISA_PORT_BASE + offset;
163	iba.iba_iot->t_size = VR_ISA_PORT_SIZE - offset;
164
165	hpcmips_init_bus_space_extent(iba.iba_iot);
166
167#ifdef DEBUG_FIND_PCIC
168#warning DEBUG_FIND_PCIC
169	__find_pcic();
170#else
171	/* Initialize ISA IRQ <-> GPIO mapping */
172	for (i = 0; i < INTR_NIRQS; i++)
173		sc->sc_intr_map[i] = -1;
174	printf (":ISA port %#x-%#x mem %#x-%#x\n",
175		iba.iba_iot->t_base, iba.iba_iot->t_base + iba.iba_iot->t_size,
176		iba.iba_memt->t_base, iba.iba_memt->t_base + iba.iba_memt->t_size);
177	config_found(self, &iba, vrisabprint);
178#endif
179
180#ifdef DEBUG_FIND_COMPORT
181#warning DEBUG_FIND_COMPORT
182	__find_comport();
183#endif
184}
185
186int
187vrisabprint(aux, pnp)
188	void *aux;
189	const char *pnp;
190{
191	if (pnp)
192		return (QUIET);
193	return (UNCONF);
194}
195
196void
197isa_attach_hook(parent, self, iba)
198	struct device *parent, *self;
199	struct isabus_attach_args *iba;
200{
201}
202
203const struct evcnt *
204isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
205{
206
207	/* XXX for now, no evcnt parent reported */
208	return NULL;
209}
210
211void *
212isa_intr_establish(ic, intr, type, level, ih_fun, ih_arg)
213	isa_chipset_tag_t ic;
214	int intr;
215	int type;  /* XXX not yet */
216	int level;  /* XXX not yet */
217	int (*ih_fun) __P((void*));
218	void *ih_arg;
219{
220	struct vrisab_softc *sc = ic->ic_sc;
221	int port, irq, mode;
222
223	static int intr_modes[8] = {
224		HPCIO_INTR_LEVEL_HIGH_THROUGH,
225		HPCIO_INTR_LEVEL_HIGH_HOLD,
226		HPCIO_INTR_LEVEL_LOW_THROUGH,
227		HPCIO_INTR_LEVEL_LOW_HOLD,
228		HPCIO_INTR_EDGE_THROUGH,
229		HPCIO_INTR_EDGE_HOLD,
230		HPCIO_INTR_EDGE_THROUGH,
231		HPCIO_INTR_EDGE_HOLD,
232	};
233#ifdef VRISADEBUG
234	static char* intr_mode_names[8] = {
235		"level high through",
236		"level high hold",
237		"level low through",
238		"level low hold",
239		"edge through",
240		"edge hold",
241		"edge through",
242		"edge hold",
243	};
244#endif /* VRISADEBUG */
245	/*
246	 * ISA IRQ <-> GPIO port mapping
247	 */
248	irq = INTR_IRQ(intr);
249	if (sc->sc_intr_map[irq] != -1) {
250		/* already mapped */
251		intr = sc->sc_intr_map[irq];
252	} else {
253		/* not mapped yet */
254		sc->sc_intr_map[irq] = intr; /* Register it */
255	}
256	mode = INTR_MODE(intr);
257	port = INTR_PORT(intr);
258
259	VPRINTF(("ISA IRQ %d -> GPIO port %d, %s\n",
260	       irq, port, intr_mode_names[mode]));
261
262	/* Call Vr routine */
263	return hpcio_intr_establish(sc->sc_hc, port, intr_modes[mode],
264				    ih_fun, ih_arg);
265}
266
267void
268isa_intr_disestablish(ic, arg)
269	isa_chipset_tag_t ic;
270	void *arg;
271{
272	struct vrisab_softc *sc = ic->ic_sc;
273	/* Call Vr routine */
274	hpcio_intr_disestablish(sc->sc_hc, arg);
275}
276
277int
278isa_intr_alloc(ic, mask, type, irq)
279	isa_chipset_tag_t ic;
280	int mask;
281	int type;
282	int *irq;
283{
284	/* XXX not coded yet. this is temporary XXX */
285	DPRINTF(("isa_intr_alloc:"));
286	DBITDISP32(mask);
287	*irq = (ffs(mask) -1); /* XXX */
288	return 0;
289}
290
291
292#ifdef DEBUG_FIND_PCIC
293#warning DEBUG_FIND_PCIC
294static void
295__find_pcic(void)
296{
297	int i, j, step, found;
298	u_int32_t addr;
299	u_int8_t reg;
300	int __read_revid (u_int32_t port)
301		{
302			addr = MIPS_PHYS_TO_KSEG1(i + port);
303			printf("%#x\r", i);
304			for (found = 0, j = 0; j < 0x100; j += 0x40) {
305				*((volatile u_int8_t*)addr) = j;
306				reg = *((volatile u_int8_t*)(addr + 1));
307#ifdef DEBUG_FIND_PCIC_I82365SL_ONLY
308				if (reg == 0x82 || reg == 0x83) {
309#else
310				if ((reg & 0xc0) == 0x80) {
311#endif
312					found++;
313				}
314			}
315			if (found)
316				printf("\nfound %d socket at %#x (base from %#x)\n", found, addr,
317				       i + port - VR_ISA_PORT_BASE);
318		};
319	step = 0x1000000;
320	printf("\nFinding PCIC. Trying ISA port %#x-%#x step %#x\n",
321	       VR_ISA_PORT_BASE, VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE, step);
322	for (i = VR_ISA_PORT_BASE; i < VR_ISA_PORT_BASE+VR_ISA_PORT_SIZE; i+= step) {
323		__read_revid (0x3e0);
324		__read_revid (0x3e2);
325	}
326}
327#endif
328
329
330#ifdef DEBUG_FIND_COMPORT
331#warning DEBUG_FIND_COMPORT
332
333static int probe_com __P((u_int32_t));
334
335static int  probe_com( port_addr )
336	u_int32_t	port_addr;
337{
338	u_int32_t	addr;
339	u_int8_t	ubtmp1;
340	u_int8_t	ubtmp2;
341
342	addr = MIPS_PHYS_TO_KSEG1( port_addr );
343
344	*((volatile u_int8_t*)(addr + com_cfcr)) = LCR_8BITS;
345	*((volatile u_int8_t*)(addr + com_iir)) = 0;
346
347	ubtmp1 = *((volatile u_int8_t*)(addr + com_cfcr));
348	ubtmp2 = *((volatile u_int8_t*)(addr + com_iir));
349
350	if( (ubtmp1 != LCR_8BITS) || ((ubtmp2 & 0x38) != 0) ){
351		return( 0 );
352	}
353
354	return( 1 );
355}
356
357static void
358__find_comport(void)
359{
360	int	found;
361	u_int32_t	port;
362	u_int32_t	step;
363
364	found = 0;
365	step = 0x08;
366
367	printf("Searching COM port. Trying ISA port %#x-%#x step %#x\n",
368		   VR_ISA_PORT_BASE, VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE - 1, step );
369
370	for( port = VR_ISA_PORT_BASE ; port < (VR_ISA_PORT_BASE + VR_ISA_PORT_SIZE) ; port += step ){
371		if( probe_com( port ) ){
372			found++;
373			printf("found %d at %#x\n",found,port);
374		}
375	}
376}
377#endif
378