1 /* $NetBSD: vme_pcc.c,v 1.24 2009/03/14 21:04:13 dsl Exp $ */
4 * Copyright (c) 1996-2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe and Steve C. Woodford.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * VME support specific to the Type 1 VMEchip found on the
36 * For a manual on the MVME-147, call: 408.991.8634. (Yes, this
37 * is the Sunnyvale sales office.)
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: vme_pcc.c,v 1.24 2009/03/14 21:04:13 dsl Exp $");
43 #include <sys/param.h>
44 #include <sys/kernel.h>
45 #include <sys/systm.h>
46 #include <sys/device.h>
47 #include <sys/malloc.h>
48 #include <sys/kcore.h>
50 #include <machine/cpu.h>
51 #include <machine/bus.h>
53 #include <dev/vme/vmereg.h>
54 #include <dev/vme/vmevar.h>
56 #include <mvme68k/dev/pccreg.h>
57 #include <mvme68k/dev/pccvar.h>
59 #include <dev/mvme/mvmebus.h>
60 #include <mvme68k/dev/vme_pccreg.h>
61 #include <mvme68k/dev/vme_pccvar.h>
64 int vme_pcc_match(struct device
*, struct cfdata
*, void *);
65 void vme_pcc_attach(struct device
*, struct device
*, void *);
67 CFATTACH_DECL(vmepcc
, sizeof(struct vme_pcc_softc
),
68 vme_pcc_match
, vme_pcc_attach
, NULL
, NULL
);
70 extern struct cfdriver vmepcc_cd
;
72 extern phys_ram_seg_t mem_clusters
[];
73 static int vme_pcc_attached
;
75 void vme_pcc_intr_establish(void *, int, int, int, int,
76 int (*)(void *), void *, struct evcnt
*);
77 void vme_pcc_intr_disestablish(void *, int, int, int, struct evcnt
*);
80 static struct mvmebus_range vme_pcc_masters
[] = {
82 MVMEBUS_AM_CAP_DATA
| MVMEBUS_AM_CAP_PROG
|
83 MVMEBUS_AM_CAP_SUPER
| MVMEBUS_AM_CAP_USER
,
84 VME_D32
| VME_D16
| VME_D8
,
85 VME1_A24D32_LOC_START
,
91 MVMEBUS_AM_CAP_DATA
| MVMEBUS_AM_CAP_PROG
|
92 MVMEBUS_AM_CAP_SUPER
| MVMEBUS_AM_CAP_USER
,
93 VME_D32
| VME_D16
| VME_D8
,
94 VME1_A32D32_LOC_START
,
100 MVMEBUS_AM_CAP_DATA
| MVMEBUS_AM_CAP_PROG
|
101 MVMEBUS_AM_CAP_SUPER
| MVMEBUS_AM_CAP_USER
,
103 VME1_A24D16_LOC_START
,
109 MVMEBUS_AM_CAP_DATA
| MVMEBUS_AM_CAP_PROG
|
110 MVMEBUS_AM_CAP_SUPER
| MVMEBUS_AM_CAP_USER
,
112 VME1_A32D16_LOC_START
,
118 MVMEBUS_AM_CAP_DATA
|
119 MVMEBUS_AM_CAP_SUPER
| MVMEBUS_AM_CAP_USER
,
121 VME1_A16D16_LOC_START
,
126 #define VME1_NMASTERS (sizeof(vme_pcc_masters)/sizeof(struct mvmebus_range))
131 vme_pcc_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
133 struct pcc_attach_args
*pa
;
137 /* Only one VME chip, please. */
138 if (vme_pcc_attached
)
141 if (strcmp(pa
->pa_name
, vmepcc_cd
.cd_name
))
148 vme_pcc_attach(struct device
*parent
, struct device
*self
, void *aux
)
150 struct pcc_attach_args
*pa
;
151 struct vme_pcc_softc
*sc
;
155 sc
= (struct vme_pcc_softc
*) self
;
158 /* Map the VMEchip's registers */
159 bus_space_map(pa
->pa_bust
, pa
->pa_offset
, VME1REG_SIZE
, 0,
162 /* Initialise stuff used by the mvme68k common VMEbus front-end */
163 sc
->sc_mvmebus
.sc_bust
= pa
->pa_bust
;
164 sc
->sc_mvmebus
.sc_dmat
= pa
->pa_dmat
;
165 sc
->sc_mvmebus
.sc_chip
= sc
;
166 sc
->sc_mvmebus
.sc_nmasters
= VME1_NMASTERS
;
167 sc
->sc_mvmebus
.sc_masters
= &vme_pcc_masters
[0];
168 sc
->sc_mvmebus
.sc_nslaves
= VME1_NSLAVES
;
169 sc
->sc_mvmebus
.sc_slaves
= &sc
->sc_slave
[0];
170 sc
->sc_mvmebus
.sc_intr_establish
= vme_pcc_intr_establish
;
171 sc
->sc_mvmebus
.sc_intr_disestablish
= vme_pcc_intr_disestablish
;
173 /* Initialize the chip. */
174 reg
= vme1_reg_read(sc
, VME1REG_SCON
) & ~VME1_SCON_SYSFAIL
;
175 vme1_reg_write(sc
, VME1REG_SCON
, reg
);
177 printf(": Type 1 VMEchip, scon jumper %s\n",
178 (reg
& VME1_SCON_SWITCH
) ? "enabled" : "disabled");
181 * Adjust the start address of the first range in vme_pcc_masters[]
182 * according to how much onboard memory exists. Disable the first
183 * range if onboard memory >= 16Mb, and adjust the start of the
184 * second range (A32D32).
186 vme_pcc_masters
[0].vr_vmestart
= (vme_addr_t
) mem_clusters
[0].size
;
187 if (mem_clusters
[0].size
>= 0x01000000) {
188 vme_pcc_masters
[0].vr_am
= MVMEBUS_AM_DISABLED
;
189 vme_pcc_masters
[1].vr_vmestart
+=
190 (vme_addr_t
) (mem_clusters
[0].size
- 0x01000000);
194 reg
= vme1_reg_read(sc
, VME1REG_SLADDRMOD
);
195 if ((reg
& VME1_SLMOD_DATA
) != 0)
196 am
|= MVMEBUS_AM_CAP_DATA
;
197 if ((reg
& VME1_SLMOD_PRGRM
) != 0)
198 am
|= MVMEBUS_AM_CAP_PROG
;
199 if ((reg
& VME1_SLMOD_SUPER
) != 0)
200 am
|= MVMEBUS_AM_CAP_SUPER
;
201 if ((reg
& VME1_SLMOD_USER
) != 0)
202 am
|= MVMEBUS_AM_CAP_USER
;
203 if ((reg
& VME1_SLMOD_BLOCK
) != 0)
204 am
|= MVMEBUS_AM_CAP_BLK
;
207 if ((reg
& VME1_SLMOD_SHORT
) != 0) {
208 sc
->sc_slave
[VME1_SLAVE_A16
].vr_am
= am
| VME_AM_A16
;
209 sc
->sc_slave
[VME1_SLAVE_A16
].vr_mask
= 0xffffu
;
212 sc
->sc_slave
[VME1_SLAVE_A16
].vr_am
= MVMEBUS_AM_DISABLED
;
214 if (pcc_slave_base_addr
< 0x01000000u
&& (reg
& VME1_SLMOD_STND
) != 0) {
215 sc
->sc_slave
[VME1_SLAVE_A24
].vr_am
= am
| VME_AM_A24
;
216 sc
->sc_slave
[VME1_SLAVE_A24
].vr_datasize
= VME_D32
|
218 sc
->sc_slave
[VME1_SLAVE_A24
].vr_mask
= 0xffffffu
;
219 sc
->sc_slave
[VME1_SLAVE_A24
].vr_locstart
= 0;
220 sc
->sc_slave
[VME1_SLAVE_A24
].vr_vmestart
= pcc_slave_base_addr
;
221 sc
->sc_slave
[VME1_SLAVE_A24
].vr_vmeend
= (pcc_slave_base_addr
+
222 mem_clusters
[0].size
- 1) & 0x00ffffffu
;
224 sc
->sc_slave
[VME1_SLAVE_A24
].vr_am
= MVMEBUS_AM_DISABLED
;
226 if ((reg
& VME1_SLMOD_EXTED
) != 0) {
227 sc
->sc_slave
[VME1_SLAVE_A32
].vr_am
= am
| VME_AM_A32
;
228 sc
->sc_slave
[VME1_SLAVE_A32
].vr_datasize
= VME_D32
|
230 sc
->sc_slave
[VME1_SLAVE_A32
].vr_mask
= 0xffffffffu
;
231 sc
->sc_slave
[VME1_SLAVE_A32
].vr_locstart
= 0;
232 sc
->sc_slave
[VME1_SLAVE_A32
].vr_vmestart
= pcc_slave_base_addr
;
233 sc
->sc_slave
[VME1_SLAVE_A32
].vr_vmeend
=
234 pcc_slave_base_addr
+ mem_clusters
[0].size
- 1;
236 sc
->sc_slave
[VME1_SLAVE_A32
].vr_am
= MVMEBUS_AM_DISABLED
;
238 vme_pcc_attached
= 1;
240 mvmebus_attach(&sc
->sc_mvmebus
);
244 vme_pcc_intr_establish(void *csc
, int prior
, int level
, int vector
, int first
, int (*func
)(void *), void *arg
, struct evcnt
*evcnt
)
246 struct vme_pcc_softc
*sc
= csc
;
249 panic("vme_pcc_intr_establish: CPU priority != VMEbus irq level");
251 isrlink_vectored(func
, arg
, prior
, vector
, evcnt
);
254 evcnt_attach_dynamic(evcnt
, EVCNT_TYPE_INTR
,
255 isrlink_evcnt(prior
), sc
->sc_mvmebus
.sc_dev
.dv_xname
,
256 mvmebus_irq_name
[level
]);
259 * There had better not be another VMEbus master responding
260 * to this interrupt level...
262 vme1_reg_write(sc
, VME1REG_IRQEN
,
263 vme1_reg_read(sc
, VME1REG_IRQEN
) | VME1_IRQ_VME(level
));
268 vme_pcc_intr_disestablish(void *csc
, int level
, int vector
, int last
, struct evcnt
*evcnt
)
270 struct vme_pcc_softc
*sc
= csc
;
272 isrunlink_vectored(vector
);
275 vme1_reg_write(sc
, VME1REG_IRQEN
,
276 vme1_reg_read(sc
, VME1REG_IRQEN
) & ~VME1_IRQ_VME(level
));