vrc4173bcu.c revision 1.1 1 /* $NetBSD: vrc4173bcu.c,v 1.1 2001/06/13 07:32:48 enami Exp $ */
2
3 /*-
4 * Copyright (c) 2001 Enami Tsugutomo.
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 REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32
33 #include <machine/bus.h>
34
35 #include <dev/pci/pcivar.h>
36 #include <dev/pci/pcidevs.h>
37
38 #include <hpcmips/vr/vrc4173bcuvar.h>
39 #include <hpcmips/vr/vrc4173icureg.h>
40
41 #define VRC4173BCU_BADR 0x10
42 #ifdef DEBUG
43 #define DPRINTF(args) printf args
44 #else
45 #define DPRINTF(args)
46 #endif
47
48 static int vrc4173bcu_match(struct device *, struct cfdata *, void *);
49 static void vrc4173bcu_attach(struct device *, struct device *, void *);
50 static int vrc4173bcu_print(void *, const char *);
51
52 int vrcintr_port = 1; /* GPIO port to which VRCINT is
53 connected to. XXX. */
54
55 struct cfattach vrc4173bcu_ca = {
56 sizeof(struct vrc4173bcu_softc), vrc4173bcu_match, vrc4173bcu_attach,
57 };
58
59 int
60 vrc4173bcu_match(struct device *parent, struct cfdata *match, void *aux)
61 {
62 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
63
64 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NEC &&
65 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NEC_VRC4173_BCU)
66 return (1);
67
68 return (0);
69 }
70
71 void
72 vrc4173bcu_attach(struct device *parent, struct device *self, void *aux)
73 {
74 struct vrc4173bcu_softc *sc = (struct vrc4173bcu_softc *)self;
75 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
76 pci_chipset_tag_t pc = pa->pa_pc;
77 pcitag_t tag = pa->pa_tag;
78 pcireg_t csr;
79 char devinfo[256];
80 int i;
81 #ifdef DEBUG
82 char buf[80];
83 u_int16_t reg;
84 #endif
85
86 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
87 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
88
89 #if 0
90 printf("%s: ", sc->sc_dev.dv_xname);
91 pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
92 #endif
93
94 csr = pci_conf_read(pc, tag, VRC4173BCU_BADR);
95 DPRINTF(("%s: base addr = 0x%08x\n", sc->sc_dev.dv_xname, csr));
96
97 /* Map I/O registers */
98 if (pci_mapreg_map(pa, VRC4173BCU_BADR, PCI_MAPREG_TYPE_IO, 0,
99 &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size)) {
100 printf("%s: can't map mem space\n", sc->sc_dev.dv_xname);
101 return;
102 }
103
104 sc->sc_pc = pc;
105
106 /* Enable the device. */
107 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
108 DPRINTF(("%s: csr = 0x%08x", sc->sc_dev.dv_xname, csr));
109 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
110 csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE);
111 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
112 DPRINTF((" -> 0x%08x\n", csr));
113
114 csr = pci_conf_read(pc, tag, VRC4173BCU_BADR);
115 DPRINTF(("%s: base addr = %x@0x%08x\n", sc->sc_dev.dv_xname,
116 (int)sc->sc_size, csr));
117 DPRINTF(("%s: iot = 0x%08x, ioh = 0x%08x\n", sc->sc_dev.dv_xname,
118 (int)sc->sc_iot, sc->sc_ioh));
119
120 /*
121 * Map I/O space for ICU.
122 */
123 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
124 VRC4173ICU_IOBASE, VRC4173ICU_IOSIZE, &sc->sc_icuh)) {
125 printf(": can't map ICU i/o space\n");
126 return;
127 }
128
129 #ifdef DEBUG
130 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_SYSINT1);
131 bitmask_snprintf(reg,
132 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
133 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
134 buf, sizeof(buf));
135 printf("%s: SYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf);
136
137 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MKIUINT);
138 bitmask_snprintf(reg,
139 "\20\1SCANINT\2KDATRDY\3KDATLOST\4B3\5B4\6B5\7B6\10B7"
140 "\11B8\12B9\13B10\14B11\15B12\16B13\17B14\20B15",
141 buf, sizeof(buf));
142 printf("%s: MKIUINT = 0x%s\n", sc->sc_dev.dv_xname, buf);
143
144 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1);
145 bitmask_snprintf(reg,
146 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
147 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
148 buf, sizeof(buf));
149 printf("%s: MSYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf);
150
151 #if 1
152 reg = VRC4173ICU_USBINTR | VRC4173ICU_PIUINTR | VRC4173ICU_KIUINTR |
153 VRC4173ICU_DOZEPIUINTR;
154 bus_space_write_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1, reg);
155
156 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_MSYSINT1);
157 bitmask_snprintf(reg,
158 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
159 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
160 buf, sizeof(buf));
161 printf("%s: MSYSINT1 = 0x%s\n", sc->sc_dev.dv_xname, buf);
162 #endif
163 #endif
164
165 for (i = 0; i < VRC4173BCU_NINTRHAND; i++)
166 sc->sc_intrhand[i].ih_func = NULL;
167
168 /*
169 * Attach sub units found in vrc4173. XXX.
170 */
171 config_found(self, "vrc4173cmu", vrc4173bcu_print);
172 config_found(self, "vrc4173giu", vrc4173bcu_print);
173 config_found(self, "vrc4173piu", vrc4173bcu_print);
174 config_found(self, "vrc4173kiu", vrc4173bcu_print);
175 config_found(self, "vrc4173aiu", vrc4173bcu_print);
176 config_found(self, "vrc4173ps2u", vrc4173bcu_print);
177
178 /*
179 * Establish VRCINT interrupt. Normally connected to one of
180 * GPIO pin in VR41xx. XXX.
181 */
182 sc->sc_ih = pci_vrcintr_establish(pc, vrcintr_port,
183 vrc4173bcu_intr, sc);
184 if (sc->sc_ih != NULL)
185 printf("%s: interrupting at %p\n", sc->sc_dev.dv_xname,
186 sc->sc_ih);
187 }
188
189 int
190 vrc4173bcu_print(void *aux, const char *pnp)
191 {
192 const char *name = aux;
193
194 if (pnp)
195 printf("%s at %s", name, pnp);
196
197 return (UNCONF);
198 }
199
200 int
201 vrc4173bcu_intr(void *arg)
202 {
203 struct vrc4173bcu_softc *sc = (struct vrc4173bcu_softc *)arg;
204 struct intrhand *ih;
205 u_int16_t reg;
206 int i, handled;
207
208 reg = bus_space_read_2(sc->sc_iot, sc->sc_icuh, VRC4173ICU_SYSINT1);
209 if (reg == 0)
210 return (0);
211
212 #if 0
213 {
214 char buf[80];
215 bitmask_snprintf(reg,
216 "\20\1USB\2PCMCIA2\3PCMCIA1\4PS2CH2\5PS2CH1\6PIU\7AIU\10KIU"
217 "\11GIU\12AC97\13AC97-1\14B11\15B12\16DOZEPIU\17B14\20B15",
218 buf, sizeof(buf));
219 printf("%s: %s\n", sc->sc_dev.dv_xname, buf);
220 }
221 #endif
222 for (handled = i = 0; i < VRC4173BCU_NINTRHAND; i++) {
223 ih = &sc->sc_intrhand[i];
224 if (ih->ih_func != NULL && (reg & (1 << i)) != 0) {
225 handled = 1;
226 (*ih->ih_func)(ih->ih_arg);
227 }
228 }
229
230 return (handled);
231 }
232
233 void *
234 vrc4173bcu_intr_establish(struct vrc4173bcu_softc *sc, int kind,
235 int (*func)(void *), void *arg)
236 {
237 struct intrhand *ih;
238
239 DPRINTF(("vrc4173bcu_intr_establish: %d, %p, %p\n", kind, func, arg));
240 if (kind < 0 || kind >= VRC4173BCU_NINTRHAND)
241 return (NULL);
242
243 ih = &sc->sc_intrhand[kind];
244 if (ih->ih_func != NULL)
245 return (NULL);
246
247 ih->ih_func = func;
248 ih->ih_arg = arg;
249 return (ih);
250 }
251
252 void
253 vrc4173bcu_intr_disestablish(struct vrc4173bcu_softc *sc, void *ihp)
254 {
255 struct intrhand *ih = ihp;
256
257 if (ih < &sc->sc_intrhand[0] ||
258 ih >= &sc->sc_intrhand[VRC4173BCU_NINTRHAND])
259 return;
260
261 ih->ih_func = NULL;
262 }
263
264 int
265 vrc4173bcu_pci_bus_devorder(pci_chipset_tag_t pc, int busno, char *devs)
266 {
267 int i;
268
269 *devs++ = 19; /* Find BCU (device 19) first. */
270 for (i = 0; i < 32; i++)
271 if (i != 19)
272 *devs++ = i;
273 return (i);
274 }
275
276 int
277 vrc4173bcu_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
278 {
279 pci_chipset_tag_t pc = pa->pa_pc;
280 pcitag_t intrtag = pa->pa_intrtag;
281 int bus, dev, func;
282 #ifdef DEBUG
283 int line = pa->pa_intrline;
284 int pin = pa->pa_intrpin;
285 #endif
286
287 pci_decompose_tag(pc, intrtag, &bus, &dev, &func);
288 DPRINTF(("%s(%d, %d, %d): line = %d, pin = %d\n", pc->pc_dev->dv_xname,
289 bus, dev, func, line, pin));
290
291 *ihp = -1;
292 switch (dev) {
293 case 1: /* CARDU0 */
294 *ihp = VRC4173ICU_PCMCIA1INTR;
295 break;
296 case 2: /* CARDU1 */
297 *ihp = VRC4173ICU_PCMCIA2INTR;
298 break;
299 case 19: /* VRC4173 */
300 switch (func) {
301 case 2:
302 *ihp = VRC4173ICU_USBINTR;
303 break;
304 }
305 break;
306 }
307
308 return (*ihp == -1);
309 }
310
311 const char *
312 vrc4173bcu_pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
313 {
314 static char irqstr[8 + sizeof("vrc4173 intr")];
315
316 snprintf(irqstr, sizeof(irqstr), "vrc4173 intr %d", (int)ih);
317 return (irqstr);
318 }
319
320 const struct evcnt *
321 vrc4173bcu_pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
322 {
323
324 /* XXX for now, no evcnt parent reported */
325 return (NULL);
326 }
327
328