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