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