xref: /openbsd/sys/arch/alpha/pci/mcpcia.c (revision 09467b48)
1 /* $OpenBSD: mcpcia.c,v 1.6 2012/12/05 23:20:10 deraadt 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/param.h>
70 #include <sys/systm.h>
71 #include <sys/device.h>
72 #include <sys/malloc.h>
73 
74 #include <machine/autoconf.h>
75 #include <machine/rpb.h>
76 #include <machine/sysarch.h>
77 
78 #include <alpha/mcbus/mcbusreg.h>
79 #include <alpha/mcbus/mcbusvar.h>
80 #include <alpha/pci/mcpciareg.h>
81 #include <alpha/pci/mcpciavar.h>
82 #include <alpha/pci/pci_kn300.h>
83 
84 #define KV(_addr)	((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr)))
85 #define	MCPCIA_SYSBASE(mc)	\
86 	((((unsigned long) (mc)->cc_gid) << MCBUS_GID_SHIFT) | \
87 	 (((unsigned long) (mc)->cc_mid) << MCBUS_MID_SHIFT) | \
88 	 (MCBUS_IOSPACE))
89 
90 #define	MCPCIA_PROBE(mid, gid)	\
91 	badaddr((void *)KV(((((unsigned long) gid) << MCBUS_GID_SHIFT) | \
92 	 (((unsigned long) mid) << MCBUS_MID_SHIFT) | \
93 	 (MCBUS_IOSPACE) | MCPCIA_PCI_BRIDGE | _MCPCIA_PCI_REV)), \
94 	sizeof(u_int32_t))
95 
96 int	mcpciamatch (struct device *, void *, void *);
97 void	mcpciaattach (struct device *, struct device *, void *);
98 void	mcpcia_config_cleanup (void);
99 
100 int	mcpciaprint (void *, const char *);
101 
102 struct cfattach mcpcia_ca = {
103 	sizeof(struct mcpcia_softc), mcpciamatch, mcpciaattach
104 };
105 
106 struct cfdriver mcpcia_cd = {
107         NULL, "mcpcia", DV_DULL,
108 };
109 
110 /*
111  * We have one statically-allocated mcpcia_config structure; this is
112  * the one used for the console (which, coincidentally, is the only
113  * MCPCIA with an EISA adapter attached to it).
114  */
115 struct mcpcia_config mcpcia_console_configuration;
116 
117 int
118 mcpciaprint(aux, pnp)
119        void *aux;
120        const char *pnp;
121 {
122        register struct pcibus_attach_args *pba = aux;
123        /* only PCIs can attach to MCPCIA for now */
124        if (pnp)
125                printf("%s at %s", pba->pba_busname, pnp);
126        printf(" bus %d", pba->pba_bus);
127        return (UNCONF);
128 }
129 
130 int
131 mcpciamatch(parent, cf, aux)
132 	struct device *parent;
133 	void *cf;
134 	void *aux;
135 {
136 	struct mcbus_dev_attach_args *ma = aux;
137 
138 	if (ma->ma_type == MCBUS_TYPE_PCI)
139 		return (1);
140 
141 	return (0);
142 }
143 
144 void
145 mcpciaattach(parent, self, aux)
146 	struct device *parent;
147 	struct device *self;
148 	void *aux;
149 {
150 	static int first = 1;
151 	struct mcbus_dev_attach_args *ma = aux;
152 	struct mcpcia_softc *mcp = (struct mcpcia_softc *)self;
153 	struct mcpcia_config *ccp;
154 	struct pcibus_attach_args pba;
155 	u_int32_t ctl;
156 
157 	/*
158 	 * Make sure this MCPCIA exists...
159 	 */
160 	if (MCPCIA_PROBE(ma->ma_mid, ma->ma_gid)) {
161 		mcp->mcpcia_cc = NULL;
162 		printf(" (not present)\n");
163 		return;
164 	}
165 	printf("\n");
166 
167 	/*
168 	 * Determine if we're the console's MCPCIA.
169 	 */
170 	if (ma->ma_mid == mcpcia_console_configuration.cc_mid &&
171 	    ma->ma_gid == mcpcia_console_configuration.cc_gid)
172 		ccp = &mcpcia_console_configuration;
173 	else {
174 		ccp = malloc(sizeof(*ccp), M_DEVBUF, M_WAITOK | M_ZERO);
175 
176 		ccp->cc_mid = ma->ma_mid;
177 		ccp->cc_gid = ma->ma_gid;
178 	}
179 	mcp->mcpcia_cc = ccp;
180 	ccp->cc_sc = mcp;
181 
182 	/* This initializes cc_sysbase so we can do register access. */
183 	mcpcia_init0(ccp, 1);
184 
185 	ctl = REGVAL(MCPCIA_PCI_REV(ccp));
186 	printf("%s: Horse rev %d, %s handed Saddle rev %d, CAP rev %d\n",
187 	    mcp->mcpcia_dev.dv_xname, HORSE_REV(ctl),
188 	    (SADDLE_TYPE(ctl) & 1) ? "right" : "left", SADDLE_REV(ctl),
189 	    CAP_REV(ctl));
190 
191 	mcpcia_dma_init(ccp);
192 
193 	/*
194 	 * Set up interrupts
195 	 */
196 	pci_kn300_pickintr(ccp, first);
197 	first = 0;
198 
199 	/*
200 	 * Attach PCI bus
201 	 */
202 	bzero(&pba, sizeof(pba));
203 	pba.pba_busname = "pci";
204 	pba.pba_iot = &ccp->cc_iot;
205 	pba.pba_memt = &ccp->cc_memt;
206 	pba.pba_dmat =
207 	    alphabus_dma_get_tag(&ccp->cc_dmat_direct, ALPHA_BUS_PCI);
208 	pba.pba_pc = &ccp->cc_pc;
209 	pba.pba_domain = pci_ndomains++;
210 	pba.pba_bus = 0;
211 
212 	config_found(self, &pba, mcpciaprint);
213 
214 	/*
215 	 * Clear any errors that may have occurred during the probe
216 	 * sequence.
217 	 */
218 	REGVAL(MCPCIA_CAP_ERR(ccp)) = 0xFFFFFFFF;
219 	alpha_mb();
220 }
221 
222 void
223 mcpcia_init()
224 {
225 	struct mcpcia_config *ccp = &mcpcia_console_configuration;
226 	int i;
227 
228 	/*
229 	 * Look for all of the MCPCIAs on the system.  One of them
230 	 * will have an EISA attached to it.  This MCPCIA is the
231 	 * only one that can be used for the console.  Once we find
232 	 * that one, initialize it.
233 	 */
234 	for (i = 0; i < MCPCIA_PER_MCBUS; i++) {
235 		ccp->cc_mid = mcbus_mcpcia_probe_order[i];
236 		/*
237 		 * XXX If we ever support more than one MCBUS, we'll
238 		 * XXX have to probe for them, and map them to unit
239 		 * XXX numbers.
240 		 */
241 		ccp->cc_gid = MCBUS_GID_FROM_INSTANCE(0);
242 		ccp->cc_sysbase = MCPCIA_SYSBASE(ccp);
243 
244 		if (badaddr((void *)ALPHA_PHYS_TO_K0SEG(MCPCIA_PCI_REV(ccp)),
245 		    sizeof(u_int32_t)))
246 			continue;
247 
248 		if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp)))) {
249 			mcpcia_init0(ccp, 0);
250 			return;
251 		}
252 	}
253 
254 	panic("mcpcia_init: unable to find EISA bus");
255 }
256 
257 void
258 mcpcia_init0(ccp, mallocsafe)
259 	struct mcpcia_config *ccp;
260 	int mallocsafe;
261 {
262 	u_int32_t ctl;
263 
264 	snprintf(ccp->pc_io_ex_name, sizeof ccp->pc_io_ex_name,
265 	    "mcpcia%d_bus_io", ccp->cc_mid);
266 	snprintf(ccp->pc_mem_dex_name, sizeof ccp->pc_mem_dex_name,
267 	    "mcpciad%d_bus_mem", ccp->cc_mid);
268 	snprintf(ccp->pc_mem_dex_name, sizeof ccp->pc_mem_sex_name,
269 	    "mcpcias%d_bus_mem", ccp->cc_mid);
270 
271 	if (!ccp->cc_initted) {
272 		/* don't do these twice since they set up extents */
273 		mcpcia_bus_io_init(&ccp->cc_iot, ccp);
274 		mcpcia_bus_mem_init(&ccp->cc_memt, ccp);
275 	}
276 	ccp->cc_mallocsafe = mallocsafe;
277 
278 	mcpcia_pci_init(&ccp->cc_pc, ccp);
279 
280         /*
281          * Establish a precalculated base for convenience's sake.
282          */
283         ccp->cc_sysbase = MCPCIA_SYSBASE(ccp);
284 
285         /*
286          * Disable interrupts and clear errors prior to probing
287          */
288         REGVAL(MCPCIA_INT_MASK0(ccp)) = 0;
289         REGVAL(MCPCIA_INT_MASK1(ccp)) = 0;
290         REGVAL(MCPCIA_CAP_ERR(ccp)) = 0xFFFFFFFF;
291         alpha_mb();
292 
293         if (ccp == &mcpcia_console_configuration) {
294                 /*
295                  * Use this opportunity to also find out the MID and CPU
296                  * type of the currently running CPU (that's us, billybob....)
297                  */
298                 ctl = REGVAL(MCPCIA_WHOAMI(ccp));
299                 mcbus_primary.mcbus_cpu_mid = MCBUS_CPU_MID(ctl);
300                 if ((MCBUS_CPU_INFO(ctl) & CPU_Fill_Err) == 0 &&
301                     mcbus_primary.mcbus_valid == 0) {
302                         mcbus_primary.mcbus_bcache =
303                             MCBUS_CPU_INFO(ctl) & CPU_BCacheMask;
304                         mcbus_primary.mcbus_valid = 1;
305                 }
306                 alpha_mb();
307         }
308 
309 	alpha_pci_chipset = &ccp->cc_pc;
310 	alpha_pci_chipset->pc_name = "mcpcia";
311 	alpha_pci_chipset->pc_hae_mask = 0;
312 	alpha_pci_chipset->pc_dense = MCPCIA_PCI_DENSE;
313 
314         ccp->cc_initted = 1;
315 }
316 
317 void
318 mcpcia_config_cleanup()
319 {
320 	volatile u_int32_t ctl;
321 	struct mcpcia_softc *mcp;
322 	struct mcpcia_config *ccp;
323 	int i;
324 	extern struct cfdriver mcpcia_cd;
325 
326 	/*
327 	 * Turn on Hard, Soft error interrupts. Maybe i2c too.
328 	 */
329 	for (i = 0; i < mcpcia_cd.cd_ndevs; i++) {
330 		if ((mcp = mcpcia_cd.cd_devs[i]) == NULL)
331 			continue;
332 
333 		ccp = mcp->mcpcia_cc;
334 		if (ccp == NULL)
335 			continue;
336 
337 		ctl = REGVAL(MCPCIA_INT_MASK0(ccp));
338 		ctl |= MCPCIA_GEN_IENABL;
339 		REGVAL(MCPCIA_INT_MASK0(ccp)) = ctl;
340 		alpha_mb();
341 
342 		/* force stall while write completes */
343 		ctl = REGVAL(MCPCIA_INT_MASK0(ccp));
344 	}
345 }
346