lasi.c revision 1.17
1/*	$OpenBSD: lasi.c,v 1.17 2003/08/28 15:24:19 mickey Exp $	*/
2
3/*
4 * Copyright (c) 1998-2003 Michael Shalayeff
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. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Michael Shalayeff.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF MIND,
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#undef LASIDEBUG
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/device.h>
38#include <sys/reboot.h>
39
40#include <machine/bus.h>
41#include <machine/iomod.h>
42#include <machine/reg.h>
43#include <machine/autoconf.h>
44
45#include <hppa/dev/cpudevs.h>
46
47#include <hppa/gsc/gscbusvar.h>
48
49#define	LASI_IOMASK	0xfff00000
50
51struct lasi_hwr {
52	u_int32_t lasi_power;
53#define	LASI_BLINK	0x01
54#define	LASI_OFF	0x02
55	u_int32_t lasi_error;
56	u_int32_t lasi_version;
57	u_int32_t lasi_reset;
58	u_int32_t lasi_arbmask;
59};
60
61struct lasi_trs {
62	u_int32_t lasi_irr;	/* int requset register */
63	u_int32_t lasi_imr;	/* int mask register */
64	u_int32_t lasi_ipr;	/* int pending register */
65	u_int32_t lasi_icr;	/* int command? register */
66	u_int32_t lasi_iar;	/* int acquire? register */
67};
68
69struct lasi_softc {
70	struct device sc_dev;
71	struct gscbus_ic sc_ic;
72	int sc_phantomassed;
73
74	struct lasi_hwr volatile *sc_hw;
75	struct lasi_trs volatile *sc_trs;
76	struct gsc_attach_args ga;	/* for deferred attach */
77};
78
79int	lasimatch(struct device *, void *, void *);
80void	lasiattach(struct device *, struct device *, void *);
81void	lasi_mainbus_attach(struct device *, struct device *, void *);
82void	lasi_phantomas_attach(struct device *, struct device *, void *);
83void	lasi_gsc_attach(struct device *);
84
85struct cfattach lasi_mainbus_ca = {
86	sizeof(struct lasi_softc), lasimatch, lasi_mainbus_attach
87};
88
89struct cfattach lasi_phantomas_ca = {
90	sizeof(struct lasi_softc), lasimatch, lasi_phantomas_attach
91};
92
93struct cfdriver lasi_cd = {
94	NULL, "lasi", DV_DULL
95};
96
97void lasi_cold_hook(int on);
98
99int
100lasimatch(parent, cfdata, aux)
101	struct device *parent;
102	void *cfdata;
103	void *aux;
104{
105	register struct confargs *ca = aux;
106	/* register struct cfdata *cf = cfdata; */
107
108	if (ca->ca_type.iodc_type != HPPA_TYPE_BHA ||
109	    ca->ca_type.iodc_sv_model != HPPA_BHA_LASI)
110		return 0;
111
112	return 1;
113}
114
115void
116lasi_mainbus_attach(parent, self, aux)
117	struct device *parent;
118	struct device *self;
119	void *aux;
120{
121	lasiattach(parent, self, aux);
122}
123
124void
125lasi_phantomas_attach(parent, self, aux)
126	struct device *parent;
127	struct device *self;
128	void *aux;
129{
130	struct lasi_softc *sc = (struct lasi_softc *)self;
131
132	sc->sc_phantomassed = 1;
133	lasiattach(parent, self, aux);
134}
135
136void
137lasiattach(parent, self, aux)
138	struct device *parent;
139	struct device *self;
140	void *aux;
141{
142	struct lasi_softc *sc = (struct lasi_softc *)self;
143	struct confargs *ca = aux;
144	bus_space_handle_t ioh;
145	int s, in;
146
147	if (bus_space_map(ca->ca_iot, ca->ca_hpa + 0xc000,
148	    IOMOD_HPASIZE, 0, &ioh)) {
149		printf(": can't map IO space\n");
150		return;
151	}
152
153	sc->sc_trs = (struct lasi_trs *)ca->ca_hpa;
154	sc->sc_hw = (struct lasi_hwr *)(ca->ca_hpa + 0xc000);
155
156	/* XXX should we reset the chip here? */
157
158	printf(": rev %d.%d\n", (sc->sc_hw->lasi_version & 0xf0) >> 4,
159	    sc->sc_hw->lasi_version & 0xf);
160
161	/* interrupts guts */
162	s = splhigh();
163	sc->sc_trs->lasi_iar = cpu_gethpa(0) | (31 - ca->ca_irq);
164	sc->sc_trs->lasi_icr = 0;
165	sc->sc_trs->lasi_imr = ~0U;
166	in = sc->sc_trs->lasi_irr;
167	sc->sc_trs->lasi_imr = 0;
168	splx(s);
169
170	sc->sc_ic.gsc_type = gsc_lasi;
171	sc->sc_ic.gsc_dv = sc;
172	sc->sc_ic.gsc_base = sc->sc_trs;
173
174#ifdef USELEDS
175	/* figure out the leds address */
176	switch (cpu_hvers) {
177	case HPPA_BOARD_HP712_60:
178	case HPPA_BOARD_HP712_80:
179	case HPPA_BOARD_HP712_100:
180	case HPPA_BOARD_HP743I_64:
181	case HPPA_BOARD_HP743I_100:
182	case HPPA_BOARD_HP712_120:
183		break;	/* only has one led. works different */
184
185	case HPPA_BOARD_HP715_64:
186	case HPPA_BOARD_HP715_80:
187	case HPPA_BOARD_HP715_100:
188	case HPPA_BOARD_HP715_100XC:
189	case HPPA_BOARD_HP725_100:
190	case HPPA_BOARD_HP725_120:
191		if (bus_space_map(ca->ca_iot, ca->ca_hpa - 0x20000,
192		    4, 0, (bus_space_handle_t *)&machine_ledaddr))
193			machine_ledaddr = NULL;
194		machine_ledword = 1;
195		break;
196
197	case HPPA_BOARD_HP800_A180C:
198	case HPPA_BOARD_HP778_B180L:
199	case HPPA_BOARD_HP780_C100:
200	case HPPA_BOARD_HP780_C110:
201	case HPPA_BOARD_HP779_C132L:
202	case HPPA_BOARD_HP779_C160L:
203	case HPPA_BOARD_HP779_C180L:
204	case HPPA_BOARD_HP779_C160L1:
205	case HPPA_BOARD_HP770_J200:
206	case HPPA_BOARD_HP770_J210:
207		if (bus_space_map(ca->ca_iot, 0xf0190000,
208		    4, 0, (bus_space_handle_t *)&machine_ledaddr))
209			machine_ledaddr = NULL;
210		machine_ledword = 1;
211		break;
212
213	default:
214		machine_ledaddr = (u_int8_t *)sc->sc_hw;
215		machine_ledword = 1;
216		break;
217	}
218#endif
219
220	sc->ga.ga_ca = *ca;	/* clone from us */
221	if (!sc->sc_phantomassed) {
222		sc->ga.ga_dp.dp_bc[0] = sc->ga.ga_dp.dp_bc[1];
223		sc->ga.ga_dp.dp_bc[1] = sc->ga.ga_dp.dp_bc[2];
224		sc->ga.ga_dp.dp_bc[2] = sc->ga.ga_dp.dp_bc[3];
225		sc->ga.ga_dp.dp_bc[3] = sc->ga.ga_dp.dp_bc[4];
226		sc->ga.ga_dp.dp_bc[4] = sc->ga.ga_dp.dp_bc[5];
227		sc->ga.ga_dp.dp_bc[5] = sc->ga.ga_dp.dp_mod;
228		sc->ga.ga_dp.dp_mod = 0;
229	}
230	if (sc->sc_dev.dv_unit)
231		config_defer(self, lasi_gsc_attach);
232	else {
233		extern void (*cold_hook)(int);
234
235		lasi_gsc_attach(self);
236		/* could be already set by power(4) */
237		if (!cold_hook)
238			cold_hook = lasi_cold_hook;
239	}
240}
241
242void
243lasi_gsc_attach(self)
244	struct device *self;
245{
246	struct lasi_softc *sc = (struct lasi_softc *)self;
247
248	sc->ga.ga_name = "gsc";
249	sc->ga.ga_hpamask = LASI_IOMASK;
250	sc->ga.ga_ic = &sc->sc_ic;
251	config_found(self, &sc->ga, gscprint);
252}
253
254void
255lasi_cold_hook(on)
256	int on;
257{
258	register struct lasi_softc *sc = lasi_cd.cd_devs[0];
259
260	if (!sc)
261		return;
262
263	switch (on) {
264	case HPPA_COLD_COLD:
265		sc->sc_hw->lasi_power = LASI_BLINK;
266		break;
267	case HPPA_COLD_HOT:
268		sc->sc_hw->lasi_power = 0;
269		break;
270	case HPPA_COLD_OFF:
271		sc->sc_hw->lasi_power = LASI_OFF;
272		break;
273	}
274}
275