lasi.c revision 1.12
1/*	$OpenBSD: lasi.c,v 1.12 2003/04/08 20:37:39 miod Exp $	*/
2
3/*
4 * Copyright (c) 1998-2002 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#ifdef DEBUG
150		printf("lasiattach: can't map IO space\n");
151#else
152		printf("\n");
153#endif
154		return;
155	}
156
157	sc->sc_trs = (struct lasi_trs *)ca->ca_hpa;
158	sc->sc_hw = (struct lasi_hwr *)(ca->ca_hpa + 0xc000);
159
160	/* XXX should we reset the chip here? */
161
162	printf(": rev %d.%d\n", (sc->sc_hw->lasi_version & 0xf0) >> 4,
163	    sc->sc_hw->lasi_version & 0xf);
164
165	/* interrupts guts */
166	s = splhigh();
167	sc->sc_trs->lasi_iar = cpu_gethpa(0) | (31 - ca->ca_irq);
168	sc->sc_trs->lasi_icr = 0;
169	sc->sc_trs->lasi_imr = ~0U;
170	in = sc->sc_trs->lasi_irr;
171	sc->sc_trs->lasi_imr = 0;
172	splx(s);
173
174	sc->sc_ic.gsc_type = gsc_lasi;
175	sc->sc_ic.gsc_dv = sc;
176	sc->sc_ic.gsc_base = sc->sc_trs;
177
178	sc->ga.ga_ca = *ca;	/* clone from us */
179	if (!sc->sc_phantomassed) {
180		sc->ga.ga_dp.dp_bc[0] = sc->ga.ga_dp.dp_bc[1];
181		sc->ga.ga_dp.dp_bc[1] = sc->ga.ga_dp.dp_bc[2];
182		sc->ga.ga_dp.dp_bc[2] = sc->ga.ga_dp.dp_bc[3];
183		sc->ga.ga_dp.dp_bc[3] = sc->ga.ga_dp.dp_bc[4];
184		sc->ga.ga_dp.dp_bc[4] = sc->ga.ga_dp.dp_bc[5];
185		sc->ga.ga_dp.dp_bc[5] = sc->ga.ga_dp.dp_mod;
186		sc->ga.ga_dp.dp_mod = 0;
187	}
188	if (sc->sc_dev.dv_unit)
189		config_defer(self, lasi_gsc_attach);
190	else {
191		extern void (*cold_hook)(int);
192
193		lasi_gsc_attach(self);
194		cold_hook = lasi_cold_hook;
195	}
196}
197
198void
199lasi_gsc_attach(self)
200	struct device *self;
201{
202	struct lasi_softc *sc = (struct lasi_softc *)self;
203
204	sc->ga.ga_name = "gsc";
205	sc->ga.ga_hpamask = LASI_IOMASK;
206	sc->ga.ga_ic = &sc->sc_ic;
207	config_found(self, &sc->ga, gscprint);
208}
209
210void
211lasi_cold_hook(on)
212	int on;
213{
214	register struct lasi_softc *sc = lasi_cd.cd_devs[0];
215
216	if (!sc)
217		return;
218
219	switch (on) {
220	case HPPA_COLD_COLD:
221		sc->sc_hw->lasi_power = LASI_BLINK;
222		break;
223	case HPPA_COLD_HOT:
224		sc->sc_hw->lasi_power = 0;
225		break;
226	case HPPA_COLD_OFF:
227		sc->sc_hw->lasi_power = LASI_OFF;
228		break;
229	}
230}
231