1 /* $OpenBSD: mcpcia.c,v 1.7 2022/03/13 08:04:13 mpi 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 const 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
mcpciaprint(aux,pnp)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
mcpciamatch(parent,cf,aux)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
mcpciaattach(parent,self,aux)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
mcpcia_init()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
mcpcia_init0(ccp,mallocsafe)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
mcpcia_config_cleanup()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