1 /* $NetBSD: vrc4172pci.c,v 1.9.2.4 2004/09/21 13:16:13 skrll Exp $ */
4 * Copyright (c) 2002 TAKEMURA Shin
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: vrc4172pci.c,v 1.9.2.4 2004/09/21 13:16:13 skrll Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
39 #include <machine/bus.h>
40 #include <machine/bus_space_hpcmips.h>
41 #include <machine/bus_dma_hpcmips.h>
42 #include <machine/config_hook.h>
43 #include <machine/platid.h>
44 #include <machine/platid_mask.h>
46 #include <dev/pci/pcivar.h>
47 #include <dev/pci/pcidevs.h>
48 #include <dev/pci/pciidereg.h>
50 #include <hpcmips/vr/icureg.h>
51 #include <hpcmips/vr/vripif.h>
52 #include <hpcmips/vr/vrc4172pcireg.h>
55 #include "opt_vrc4172pci.h"
58 #define DPRINTF(args) printf args
60 #define DPRINTF(args) while (0) {}
63 struct vrc4172pci_softc
{
66 bus_space_tag_t sc_iot
;
67 bus_space_handle_t sc_ioh
;
69 struct hpcmips_pci_chipset sc_pc
;
70 #ifdef VRC4172PCI_MCR700_SUPPORT
71 pcireg_t sc_fake_baseaddr
;
72 hpcio_chip_t sc_iochip
;
74 hpcio_intr_handle_t sc_ih
;
76 #endif /* VRC4172PCI_MCR700_SUPPORT */
79 static int vrc4172pci_match(struct device
*, struct cfdata
*, void *);
80 static void vrc4172pci_attach(struct device
*, struct device
*, void *);
81 static void vrc4172pci_attach_hook(struct device
*, struct device
*,
82 struct pcibus_attach_args
*);
83 static int vrc4172pci_bus_maxdevs(pci_chipset_tag_t
, int);
84 static int vrc4172pci_bus_devorder(pci_chipset_tag_t
, int, char *);
85 static pcitag_t
vrc4172pci_make_tag(pci_chipset_tag_t
, int, int, int);
86 static void vrc4172pci_decompose_tag(pci_chipset_tag_t
, pcitag_t
, int *,
88 static pcireg_t
vrc4172pci_conf_read(pci_chipset_tag_t
, pcitag_t
, int);
89 static void vrc4172pci_conf_write(pci_chipset_tag_t
, pcitag_t
, int,
91 static int vrc4172pci_intr_map(struct pci_attach_args
*,
93 static const char *vrc4172pci_intr_string(pci_chipset_tag_t
,pci_intr_handle_t
);
94 static const struct evcnt
*vrc4172pci_intr_evcnt(pci_chipset_tag_t
,
96 static void *vrc4172pci_intr_establish(pci_chipset_tag_t
,
97 pci_intr_handle_t
, int, int (*)(void *), void *);
98 static void vrc4172pci_intr_disestablish(pci_chipset_tag_t
, void *);
99 #ifdef VRC4172PCI_MCR700_SUPPORT
101 static int vrc4172pci_mcr700_intr(void *arg
);
105 CFATTACH_DECL(vrc4172pci
, sizeof(struct vrc4172pci_softc
),
106 vrc4172pci_match
, vrc4172pci_attach
, NULL
, NULL
);
109 vrc4172pci_write(struct vrc4172pci_softc
*sc
, int offset
, u_int32_t val
)
112 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, offset
, val
);
115 static inline u_int32_t
116 vrc4172pci_read(struct vrc4172pci_softc
*sc
, int offset
)
120 if (bus_space_peek(sc
->sc_iot
, sc
->sc_ioh
, offset
, 4, &res
) < 0) {
128 vrc4172pci_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
135 vrc4172pci_attach(struct device
*parent
, struct device
*self
, void *aux
)
137 struct vrc4172pci_softc
*sc
= (struct vrc4172pci_softc
*)self
;
138 pci_chipset_tag_t pc
= &sc
->sc_pc
;
139 struct vrip_attach_args
*va
= aux
;
141 struct pcibus_attach_args pba
;
144 sc
->sc_iot
= va
->va_iot
;
145 if (bus_space_map(sc
->sc_iot
, va
->va_addr
, va
->va_size
, 0,
147 printf(": couldn't map io space\n");
152 #ifdef VRC4172PCI_MCR700_SUPPORT
153 if (platid_match(&platid
, &platid_mask_MACH_NEC_MCR_700
) ||
154 platid_match(&platid
, &platid_mask_MACH_NEC_MCR_700A
) ||
155 platid_match(&platid
, &platid_mask_MACH_NEC_MCR_730
) ||
156 platid_match(&platid
, &platid_mask_MACH_NEC_MCR_730A
)) {
157 /* power USB controller on MC-R700 */
158 sc
->sc_iochip
= va
->va_gpio_chips
[VRIP_IOCHIP_VRGIU
];
159 hpcio_portwrite(sc
->sc_iochip
, 45, 1);
160 sc
->sc_fake_baseaddr
= 0x0afe0000;
162 sc
->sc_ih
= hpcio_intr_establish(sc
->sc_iochip
, 1,
163 HPCIO_INTR_EDGE
|HPCIO_INTR_HOLD
,
164 vrc4172pci_mcr700_intr
, sc
);
167 #endif /* VRC4172PCI_MCR700_SUPPORT */
169 pc
->pc_dev
= &sc
->sc_dev
;
170 pc
->pc_attach_hook
= vrc4172pci_attach_hook
;
171 pc
->pc_bus_maxdevs
= vrc4172pci_bus_maxdevs
;
172 pc
->pc_bus_devorder
= vrc4172pci_bus_devorder
;
173 pc
->pc_make_tag
= vrc4172pci_make_tag
;
174 pc
->pc_decompose_tag
= vrc4172pci_decompose_tag
;
175 pc
->pc_conf_read
= vrc4172pci_conf_read
;
176 pc
->pc_conf_write
= vrc4172pci_conf_write
;
177 pc
->pc_intr_map
= vrc4172pci_intr_map
;
178 pc
->pc_intr_string
= vrc4172pci_intr_string
;
179 pc
->pc_intr_evcnt
= vrc4172pci_intr_evcnt
;
180 pc
->pc_intr_establish
= vrc4172pci_intr_establish
;
181 pc
->pc_intr_disestablish
= vrc4172pci_intr_disestablish
;
187 for (i
= 0; i
< 2; i
++)
188 printf("%s: ID_REG(0, 0, %d) = 0x%08x\n",
189 sc
->sc_dev
.dv_xname
, i
,
190 pci_conf_read(pc
, pci_make_tag(pc
, 0, 0, i
),
196 memset(&pba
, 0, sizeof(pba
));
197 pba
.pba_iot
= sc
->sc_iot
;
198 pba
.pba_memt
= sc
->sc_iot
;
199 pba
.pba_dmat
= &hpcmips_default_bus_dma_tag
.bdt
;
200 pba
.pba_dmat64
= NULL
;
202 pba
.pba_bridgetag
= NULL
;
203 pba
.pba_flags
= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
|
207 config_found_ia(self
, "pcibus", &pba
, pcibusprint
);
212 vrc4172pci_attach_hook(struct device
*parent
, struct device
*self
,
213 struct pcibus_attach_args
*pba
)
220 vrc4172pci_bus_maxdevs(pci_chipset_tag_t pc
, int busno
)
223 return (1); /* Vrc4172 has only one device */
227 vrc4172pci_bus_devorder(pci_chipset_tag_t pc
, int busno
, char *devs
)
232 for (i
= 1; i
< 32; i
++)
239 vrc4172pci_make_tag(pci_chipset_tag_t pc
, int bus
, int device
, int function
)
242 return ((bus
<< 16) | (device
<< 11) | (function
<< 8));
246 vrc4172pci_decompose_tag(pci_chipset_tag_t pc
, pcitag_t tag
, int *bp
, int *dp
,
251 *bp
= (tag
>> 16) & 0xff;
253 *dp
= (tag
>> 11) & 0x1f;
255 *fp
= (tag
>> 8) & 0x07;
259 vrc4172pci_conf_read(pci_chipset_tag_t pc
, pcitag_t tag
, int reg
)
261 struct vrc4172pci_softc
*sc
= (struct vrc4172pci_softc
*)pc
->pc_dev
;
264 #ifdef VRC4172PCI_MCR700_SUPPORT
265 if (sc
->sc_fake_baseaddr
!= 0 &&
266 tag
== vrc4172pci_make_tag(pc
, 0, 0, 1) &&
267 reg
== PCI_MAPREG_START
) {
268 val
= sc
->sc_fake_baseaddr
;
271 #endif /* VRC4172PCI_MCR700_SUPPORT */
273 tag
|= VRC4172PCI_CONFADDR_CONFIGEN
;
275 vrc4172pci_write(sc
, VRC4172PCI_CONFAREG
, tag
| reg
);
276 val
= vrc4172pci_read(sc
, VRC4172PCI_CONFDREG
);
278 #ifdef VRC4172PCI_MCR700_SUPPORT
281 DPRINTF(("%s: conf_read: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n",
282 sc
->sc_dev
.dv_xname
, (u_int32_t
)tag
, reg
, val
));
288 vrc4172pci_conf_write(pci_chipset_tag_t pc
, pcitag_t tag
, int reg
,
291 struct vrc4172pci_softc
*sc
= (struct vrc4172pci_softc
*)pc
->pc_dev
;
293 DPRINTF(("%s: conf_write: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n",
294 sc
->sc_dev
.dv_xname
, (u_int32_t
)tag
, reg
, (u_int32_t
)data
));
296 #ifdef VRC4172PCI_MCR700_SUPPORT
297 if (sc
->sc_fake_baseaddr
!= 0 &&
298 tag
== vrc4172pci_make_tag(pc
, 0, 0, 1) &&
299 reg
== PCI_MAPREG_START
) {
300 sc
->sc_fake_baseaddr
= (data
& 0xfffff000);
303 #endif /* VRC4172PCI_MCR700_SUPPORT */
305 tag
|= VRC4172PCI_CONFADDR_CONFIGEN
;
307 vrc4172pci_write(sc
, VRC4172PCI_CONFAREG
, tag
| reg
);
308 vrc4172pci_write(sc
, VRC4172PCI_CONFDREG
, data
);
312 vrc4172pci_intr_map(struct pci_attach_args
*pa
, pci_intr_handle_t
*ihp
)
314 pci_chipset_tag_t pc
= pa
->pa_pc
;
315 pcitag_t intrtag
= pa
->pa_intrtag
;
318 pci_decompose_tag(pc
, intrtag
, &bus
, &dev
, &func
);
319 DPRINTF(("%s(%d, %d, %d): line = %d, pin = %d\n", pc
->pc_dev
->dv_xname
,
320 bus
, dev
, func
, pa
->pa_intrline
, pa
->pa_intrpin
));
322 *ihp
= CONFIG_HOOK_PCIINTR_ID(bus
, dev
, func
);
328 vrc4172pci_intr_string(pci_chipset_tag_t pc
, pci_intr_handle_t ih
)
330 static char irqstr
[sizeof("pciintr") + 16];
332 snprintf(irqstr
, sizeof(irqstr
), "pciintr %d:%d:%d",
333 CONFIG_HOOK_PCIINTR_BUS((int)ih
),
334 CONFIG_HOOK_PCIINTR_DEVICE((int)ih
),
335 CONFIG_HOOK_PCIINTR_FUNCTION((int)ih
));
341 vrc4172pci_intr_evcnt(pci_chipset_tag_t pc
, pci_intr_handle_t ih
)
348 vrc4172pci_intr_establish(pci_chipset_tag_t pc
, pci_intr_handle_t ih
,
349 int level
, int (*func
)(void *), void *arg
)
354 DPRINTF(("vrc4172pci_intr_establish: %lx\n", ih
));
356 return (config_hook(CONFIG_HOOK_PCIINTR
, ih
, CONFIG_HOOK_EXCLUSIVE
,
357 (int (*)(void *, int, long, void *))func
, arg
));
361 vrc4172pci_intr_disestablish(pci_chipset_tag_t pc
, void *cookie
)
364 DPRINTF(("vrc4172pci_intr_disestablish: %p\n", cookie
));
365 config_unhook(cookie
);
368 #ifdef VRC4172PCI_MCR700_SUPPORT
371 vrc4172pci_mcr700_intr(void *arg
)
373 struct vrc4172pci_softc
*sc
= arg
;
375 hpcio_intr_clear(sc
->sc_iochip
, sc
->sc_ih
);
376 printf("USB port %s\n", hpcio_portread(sc
->sc_iochip
, 1) ? "ON" : "OFF");
377 hpcio_portwrite(sc
->sc_iochip
, 45, hpcio_portread(sc
->sc_iochip
, 1));
382 #endif /* VRC4172PCI_MCR700_SUPPORT */