xref: /openbsd/sys/arch/alpha/pci/mcpcia.c (revision 404b540a)
1 /* $OpenBSD: mcpcia.c,v 1.4 2009/03/30 21:43:13 kettenis Exp $ */
2 /* $NetBSD: mcpcia.c,v 1.20 2007/03/04 05:59:11 christos Exp $ */
3 
4 /*-
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1998 by Matthew Jacob
36  * NASA AMES Research Center.
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice immediately at the beginning of the file, without modification,
44  *    this list of conditions, and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. The name of the author may not be used to endorse or promote products
49  *    derived from this software without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
55  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61  * SUCH DAMAGE.
62  */
63 
64 /*
65  * MCPCIA mcbus to PCI bus adapter
66  * found on AlphaServer 4100 systems.
67  */
68 
69 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/device.h>
73 #include <sys/malloc.h>
74 
75 #include <machine/autoconf.h>
76 #include <machine/rpb.h>
77 #include <machine/sysarch.h>
78 
79 #include <alpha/mcbus/mcbusreg.h>
80 #include <alpha/mcbus/mcbusvar.h>
81 #include <alpha/pci/mcpciareg.h>
82 #include <alpha/pci/mcpciavar.h>
83 #include <alpha/pci/pci_kn300.h>
84 
85 #define KV(_addr)	((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr)))
86 #define	MCPCIA_SYSBASE(mc)	\
87 	((((unsigned long) (mc)->cc_gid) << MCBUS_GID_SHIFT) | \
88 	 (((unsigned long) (mc)->cc_mid) << MCBUS_MID_SHIFT) | \
89 	 (MCBUS_IOSPACE))
90 
91 #define	MCPCIA_PROBE(mid, gid)	\
92 	badaddr((void *)KV(((((unsigned long) gid) << MCBUS_GID_SHIFT) | \
93 	 (((unsigned long) mid) << MCBUS_MID_SHIFT) | \
94 	 (MCBUS_IOSPACE) | MCPCIA_PCI_BRIDGE | _MCPCIA_PCI_REV)), \
95 	sizeof(u_int32_t))
96 
97 int	mcpciamatch (struct device *, void *, void *);
98 void	mcpciaattach (struct device *, struct device *, void *);
99 void	mcpcia_config_cleanup (void);
100 
101 int	mcpciaprint (void *, const char *);
102 
103 struct cfattach mcpcia_ca = {
104 	sizeof(struct mcpcia_softc), mcpciamatch, mcpciaattach
105 };
106 
107 struct cfdriver mcpcia_cd = {
108         NULL, "mcpcia", DV_DULL,
109 };
110 
111 /*
112  * We have one statically-allocated mcpcia_config structure; this is
113  * the one used for the console (which, coincidentally, is the only
114  * MCPCIA with an EISA adapter attached to it).
115  */
116 struct mcpcia_config mcpcia_console_configuration;
117 
118 int
119 mcpciaprint(aux, pnp)
120        void *aux;
121        const char *pnp;
122 {
123        register struct pcibus_attach_args *pba = aux;
124        /* only PCIs can attach to MCPCIA for now */
125        if (pnp)
126                printf("%s at %s", pba->pba_busname, pnp);
127        printf(" bus %d", pba->pba_bus);
128        return (UNCONF);
129 }
130 
131 int
132 mcpciamatch(parent, cf, aux)
133 	struct device *parent;
134 	void *cf;
135 	void *aux;
136 {
137 	struct mcbus_dev_attach_args *ma = aux;
138 
139 	if (ma->ma_type == MCBUS_TYPE_PCI)
140 		return (1);
141 
142 	return (0);
143 }
144 
145 void
146 mcpciaattach(parent, self, aux)
147 	struct device *parent;
148 	struct device *self;
149 	void *aux;
150 {
151 	static int first = 1;
152 	struct mcbus_dev_attach_args *ma = aux;
153 	struct mcpcia_softc *mcp = (struct mcpcia_softc *)self;
154 	struct mcpcia_config *ccp;
155 	struct pcibus_attach_args pba;
156 	u_int32_t ctl;
157 
158 	/*
159 	 * Make sure this MCPCIA exists...
160 	 */
161 	if (MCPCIA_PROBE(ma->ma_mid, ma->ma_gid)) {
162 		mcp->mcpcia_cc = NULL;
163 		printf(" (not present)\n");
164 		return;
165 	}
166 	printf("\n");
167 
168 	/*
169 	 * Determine if we're the console's MCPCIA.
170 	 */
171 	if (ma->ma_mid == mcpcia_console_configuration.cc_mid &&
172 	    ma->ma_gid == mcpcia_console_configuration.cc_gid)
173 		ccp = &mcpcia_console_configuration;
174 	else {
175 		ccp = malloc(sizeof(*ccp), M_DEVBUF, M_WAITOK | M_ZERO);
176 
177 		ccp->cc_mid = ma->ma_mid;
178 		ccp->cc_gid = ma->ma_gid;
179 	}
180 	mcp->mcpcia_cc = ccp;
181 	ccp->cc_sc = mcp;
182 
183 	/* This initializes cc_sysbase so we can do register access. */
184 	mcpcia_init0(ccp, 1);
185 
186 	ctl = REGVAL(MCPCIA_PCI_REV(ccp));
187 	printf("%s: Horse Revision %d, %s Handed Saddle Revision %d,"
188 	    " CAP Revision %d\n", mcp->mcpcia_dev.dv_xname, HORSE_REV(ctl),
189 	    (SADDLE_TYPE(ctl) & 1)? "Right": "Left", SADDLE_REV(ctl),
190 	    CAP_REV(ctl));
191 
192 	mcpcia_dma_init(ccp);
193 
194 	/*
195 	 * Set up interrupts
196 	 */
197 	pci_kn300_pickintr(ccp, first);
198 	first = 0;
199 
200 	/*
201 	 * Attach PCI bus
202 	 */
203 	bzero(&pba, sizeof(pba));
204 	pba.pba_busname = "pci";
205 	pba.pba_iot = &ccp->cc_iot;
206 	pba.pba_memt = &ccp->cc_memt;
207 	pba.pba_dmat =
208 	    alphabus_dma_get_tag(&ccp->cc_dmat_direct, ALPHA_BUS_PCI);
209 	pba.pba_pc = &ccp->cc_pc;
210 	pba.pba_domain = pci_ndomains++;
211 	pba.pba_bus = 0;
212 
213 	config_found(self, &pba, mcpciaprint);
214 
215 	/*
216 	 * Clear any errors that may have occurred during the probe
217 	 * sequence.
218 	 */
219 	REGVAL(MCPCIA_CAP_ERR(ccp)) = 0xFFFFFFFF;
220 	alpha_mb();
221 }
222 
223 void
224 mcpcia_init()
225 {
226 	struct mcpcia_config *ccp = &mcpcia_console_configuration;
227 	int i;
228 
229 	/*
230 	 * Look for all of the MCPCIAs on the system.  One of them
231 	 * will have an EISA attached to it.  This MCPCIA is the
232 	 * only one that can be used for the console.  Once we find
233 	 * that one, initialize it.
234 	 */
235 	for (i = 0; i < MCPCIA_PER_MCBUS; i++) {
236 		ccp->cc_mid = mcbus_mcpcia_probe_order[i];
237 		/*
238 		 * XXX If we ever support more than one MCBUS, we'll
239 		 * XXX have to probe for them, and map them to unit
240 		 * XXX numbers.
241 		 */
242 		ccp->cc_gid = MCBUS_GID_FROM_INSTANCE(0);
243 		ccp->cc_sysbase = MCPCIA_SYSBASE(ccp);
244 
245 		if (badaddr((void *)ALPHA_PHYS_TO_K0SEG(MCPCIA_PCI_REV(ccp)),
246 		    sizeof(u_int32_t)))
247 			continue;
248 
249 		if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp)))) {
250 			mcpcia_init0(ccp, 0);
251 			return;
252 		}
253 	}
254 
255 	panic("mcpcia_init: unable to find EISA bus");
256 }
257 
258 void
259 mcpcia_init0(ccp, mallocsafe)
260 	struct mcpcia_config *ccp;
261 	int mallocsafe;
262 {
263 	u_int32_t ctl;
264 
265 	snprintf(ccp->pc_io_ex_name, sizeof ccp->pc_io_ex_name,
266 	    "mcpcia%d_bus_io", ccp->cc_mid);
267 	snprintf(ccp->pc_mem_dex_name, sizeof ccp->pc_mem_dex_name,
268 	    "mcpciad%d_bus_mem", ccp->cc_mid);
269 	snprintf(ccp->pc_mem_dex_name, sizeof ccp->pc_mem_sex_name,
270 	    "mcpcias%d_bus_mem", ccp->cc_mid);
271 
272 	if (!ccp->cc_initted) {
273 		/* don't do these twice since they set up extents */
274 		mcpcia_bus_io_init(&ccp->cc_iot, ccp);
275 		mcpcia_bus_mem_init(&ccp->cc_memt, ccp);
276 	}
277 	ccp->cc_mallocsafe = mallocsafe;
278 
279 	mcpcia_pci_init(&ccp->cc_pc, ccp);
280 
281         /*
282          * Establish a precalculated base for convenience's sake.
283          */
284         ccp->cc_sysbase = MCPCIA_SYSBASE(ccp);
285 
286         /*
287          * Disable interrupts and clear errors prior to probing
288          */
289         REGVAL(MCPCIA_INT_MASK0(ccp)) = 0;
290         REGVAL(MCPCIA_INT_MASK1(ccp)) = 0;
291         REGVAL(MCPCIA_CAP_ERR(ccp)) = 0xFFFFFFFF;
292         alpha_mb();
293 
294         if (ccp == &mcpcia_console_configuration) {
295                 /*
296                  * Use this opportunity to also find out the MID and CPU
297                  * type of the currently running CPU (that's us, billybob....)
298                  */
299                 ctl = REGVAL(MCPCIA_WHOAMI(ccp));
300                 mcbus_primary.mcbus_cpu_mid = MCBUS_CPU_MID(ctl);
301                 if ((MCBUS_CPU_INFO(ctl) & CPU_Fill_Err) == 0 &&
302                     mcbus_primary.mcbus_valid == 0) {
303                         mcbus_primary.mcbus_bcache =
304                             MCBUS_CPU_INFO(ctl) & CPU_BCacheMask;
305                         mcbus_primary.mcbus_valid = 1;
306                 }
307                 alpha_mb();
308         }
309 
310 	alpha_pci_chipset = &ccp->cc_pc;
311 	alpha_pci_chipset->pc_name = "mcpcia";
312 	alpha_pci_chipset->pc_hae_mask = 0;
313 	alpha_pci_chipset->pc_dense = MCPCIA_PCI_DENSE;
314 
315         ccp->cc_initted = 1;
316 }
317 
318 void
319 mcpcia_config_cleanup()
320 {
321 	volatile u_int32_t ctl;
322 	struct mcpcia_softc *mcp;
323 	struct mcpcia_config *ccp;
324 	int i;
325 	extern struct cfdriver mcpcia_cd;
326 
327 	/*
328 	 * Turn on Hard, Soft error interrupts. Maybe i2c too.
329 	 */
330 	for (i = 0; i < mcpcia_cd.cd_ndevs; i++) {
331 		if ((mcp = mcpcia_cd.cd_devs[i]) == NULL)
332 			continue;
333 
334 		ccp = mcp->mcpcia_cc;
335 		if (ccp == NULL)
336 			continue;
337 
338 		ctl = REGVAL(MCPCIA_INT_MASK0(ccp));
339 		ctl |= MCPCIA_GEN_IENABL;
340 		REGVAL(MCPCIA_INT_MASK0(ccp)) = ctl;
341 		alpha_mb();
342 
343 		/* force stall while write completes */
344 		ctl = REGVAL(MCPCIA_INT_MASK0(ccp));
345 	}
346 }
347