xref: /netbsd-src/sys/arch/powerpc/pci/pchb.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1 /*	$NetBSD: pchb.c,v 1.12 2021/08/07 16:19:03 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 2007 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Tim Rightnour
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  *
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.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.12 2021/08/07 16:19:03 thorpej Exp $");
34 
35 #include "agp.h"
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 
42 #include <sys/bus.h>
43 #include <machine/pio.h>
44 
45 #include <dev/pci/pcivar.h>
46 #include <dev/pci/pcireg.h>
47 #include <dev/pci/pcidevs.h>
48 #include <dev/pci/agpreg.h>
49 #include <dev/pci/agpvar.h>
50 
51 #include <dev/ic/mpc105reg.h>
52 #include <dev/ic/mpc106reg.h>
53 #include <dev/ic/ibm82660reg.h>
54 
55 int	pchbmatch(device_t, cfdata_t, void *);
56 void	pchbattach(device_t, device_t, void *);
57 
58 CFATTACH_DECL_NEW(pchb, 0,
59     pchbmatch, pchbattach, NULL, NULL);
60 
61 int
pchbmatch(device_t parent,cfdata_t cf,void * aux)62 pchbmatch(device_t parent, cfdata_t cf, void *aux)
63 {
64 	struct pci_attach_args *pa = aux;
65 
66 	/*
67 	 * Match all known PCI host chipsets.
68 	 */
69 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
70 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) {
71 		return (1);
72 	}
73 
74 	return (0);
75 }
76 
77 static void
mpc105_print(struct pci_attach_args * pa,device_t self)78 mpc105_print(struct pci_attach_args *pa, device_t self)
79 {
80 	pcireg_t reg1, reg2;
81 	const char *s1;
82 
83 	reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, MPC105_PICR1);
84 	reg2 = pci_conf_read(pa->pa_pc, pa->pa_tag, MPC105_PICR2);
85 	aprint_normal_dev(self, "L2 cache: ");
86 
87 	switch (reg2 & MPC105_PICR2_L2_SIZE) {
88 	case MPC105_PICR2_L2_SIZE_256K:
89 		s1 = "256K";
90 		break;
91 	case MPC105_PICR2_L2_SIZE_512K:
92 		s1 = "512K";
93 		break;
94 	case MPC105_PICR2_L2_SIZE_1M:
95 		s1 = "1M";
96 		break;
97 	default:
98 		s1 = "reserved size";
99 		break;
100 	}
101 
102 	aprint_normal("%s, ", s1);
103 	switch (reg1 & MPC105_PICR1_L2_MP) {
104 	case MPC105_PICR1_L2_MP_NONE:
105 		s1 = "uniprocessor/none";
106 		break;
107 	case MPC105_PICR1_L2_MP_WT:
108 		s1 = "write-through";
109 		break;
110 	case MPC105_PICR1_L2_MP_WB:
111 		s1 = "write-back";
112 		break;
113 	case MPC105_PICR1_L2_MP_MP:
114 		s1 = "multiprocessor";
115 		break;
116 	}
117 	aprint_normal("%s mode\n", s1);
118 }
119 
120 static void
mpc106_print(struct pci_attach_args * pa,device_t self)121 mpc106_print(struct pci_attach_args *pa, device_t self)
122 {
123 	pcireg_t reg1, reg2;
124 	const char *s1;
125 
126 	reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, MPC106_PICR1);
127 	reg2 = pci_conf_read(pa->pa_pc, pa->pa_tag, MPC106_PICR2);
128 	aprint_normal_dev(self, "L2 cache: ");
129 
130 	switch (reg2 & MPC106_PICR2_L2_SIZE) {
131 	case MPC106_PICR2_L2_SIZE_256K:
132 		s1 = "256K";
133 		break;
134 	case MPC106_PICR2_L2_SIZE_512K:
135 		s1 = "512K";
136 		break;
137 	case MPC106_PICR2_L2_SIZE_1M:
138 		s1 = "1M";
139 		break;
140 	default:
141 		s1 = "reserved size";
142 		break;
143 	}
144 
145 	aprint_normal("%s, ", s1);
146 	switch (reg1 & MPC106_PICR1_EXT_L2_EN) {
147 	case 0:
148 		switch (reg1 & MPC106_PICR1_L2_MP) {
149 		case MPC106_PICR1_L2_MP_NONE:
150 			s1 = "uniprocessor/none";
151 			break;
152 		case MPC106_PICR1_L2_MP_WT:
153 			s1 = "internally controlled write-through";
154 			break;
155 		case MPC106_PICR1_L2_MP_WB:
156 			s1 = "internally controlled write-back";
157 			break;
158 		case MPC106_PICR1_L2_MP_MP:
159 			s1 = "multiprocessor/none";
160 			break;
161 		}
162 		break;
163 	case 1:
164 		switch (reg1 & MPC106_PICR1_L2_MP) {
165 		case MPC106_PICR1_L2_MP_NONE:
166 			s1 = "uniprocessor/external";
167 			break;
168 		case MPC106_PICR1_L2_MP_MP:
169 			s1 = "multiprocessors/external";
170 			break;
171 		default:
172 			s1 = "reserved";
173 			break;
174 		}
175 	}
176 	aprint_normal("%s mode\n", s1);
177 }
178 
179 static void
ibm82660_print(struct pci_attach_args * pa,device_t self)180 ibm82660_print(struct pci_attach_args *pa, device_t self)
181 {
182 	pcireg_t reg1;
183 #ifdef PREP_BUS_SPACE_IO
184 	pcireg_t reg2;
185 #endif
186 	const char *s1, *s2;
187 
188 	reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag,
189 	    IBM_82660_CACHE_STATUS);
190 #ifdef PREP_BUS_SPACE_IO
191 	reg2 = in32rb(PREP_BUS_SPACE_IO+IBM_82660_SYSTEM_CTRL);
192 	if (reg2 & IBM_82660_SYSTEM_CTRL_L2_EN) {
193 		if (reg1 & IBM_82660_CACHE_STATUS_L2_EN)
194 			s1 = "internal enabled";
195 		else
196 			s1 = "enabled";
197 		if (reg2 & IBM_82660_SYSTEM_CTRL_L2_MI)
198 			s2 = " (normal operation)";
199 		else
200 			s2 = " (miss updates inhibited)";
201 	} else {
202 		s1 = "disabled";
203 		s2 = "";
204 	}
205 #else
206 	if (reg1 & IBM_82660_CACHE_STATUS_L2_EN)
207 		s1 = "enabled";
208 	else
209 		s1 = "disabled";
210 	s2 = "";
211 #endif
212 	aprint_normal_dev(self, "L1 %s L2 %s%s\n",
213 	    (reg1 & IBM_82660_CACHE_STATUS_L1_EN) ? "enabled" : "disabled",
214 	    s1, s2);
215 
216 	reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, IBM_82660_OPTIONS_1);
217 	aprint_verbose_dev(self, "MCP# assertion %s "
218 	    "TEA# assertion %s\n",
219 	    (reg1 & IBM_82660_OPTIONS_1_MCP) ? "enabled" : "disabled",
220 	    (reg1 & IBM_82660_OPTIONS_1_TEA) ? "enabled" : "disabled");
221 	aprint_verbose_dev(self, "PCI/ISA I/O mapping %s\n",
222 	    (reg1 & IBM_82660_OPTIONS_1_ISA) ? "contiguous" : "non-contiguous");
223 
224 	reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, IBM_82660_OPTIONS_3);
225 	aprint_normal_dev(self, "DRAM %s (%s) SRAM %s\n",
226 	    (reg1 & IBM_82660_OPTIONS_3_DRAM) ? "EDO" : "standard",
227 	    (reg1 & IBM_82660_OPTIONS_3_ECC) ? "ECC" : "parity",
228 	    (reg1 & IBM_82660_OPTIONS_3_SRAM) ? "sync" : "async");
229 	aprint_verbose_dev(self, "Snoop mode %s\n",
230 	    (reg1 & IBM_82660_OPTIONS_3_SNOOP) ? "603" : "601/604");
231 }
232 
233 void
pchbattach(device_t parent,device_t self,void * aux)234 pchbattach(device_t parent, device_t self, void *aux)
235 {
236 	struct pci_attach_args *pa = aux;
237 	char devinfo[256];
238 #if NAGP > 0
239 	struct agpbus_attach_args apa;
240 #endif
241 	volatile unsigned char *python;
242 	uint32_t v;
243 
244 	aprint_naive("\n");
245 	aprint_normal("\n");
246 
247 	/*
248 	 * All we do is print out a description.  Eventually, we
249 	 * might want to add code that does something that's
250 	 * possibly chipset-specific.
251 	 */
252 
253 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
254 	aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo,
255 	    PCI_REVISION(pa->pa_class));
256 
257 	switch (PCI_VENDOR(pa->pa_id)) {
258 	case PCI_VENDOR_IBM:
259 		switch (PCI_PRODUCT(pa->pa_id)) {
260 		case PCI_PRODUCT_IBM_82660:
261 			ibm82660_print(pa, self);
262 			break;
263 		case PCI_PRODUCT_IBM_PYTHON:
264 			python = mapiodev(0xfeff6000, 0x60, false);
265 			v = 0x88b78e01; /* taken from linux */
266 			out32rb(python+0x30, v);
267 			v = in32rb(python+0x30);
268 			aprint_debug("Reset python reg 30 to 0x%x\n", v);
269 			break;
270 		}
271 		break;
272 	case PCI_VENDOR_MOT:
273 		switch (PCI_PRODUCT(pa->pa_id)) {
274 		case PCI_PRODUCT_MOT_MPC105:
275 			mpc105_print(pa, self);
276 			break;
277 		case PCI_PRODUCT_MOT_MPC106:
278 			mpc106_print(pa, self);
279 			break;
280 		}
281 		break;
282 	}
283 
284 #if NAGP > 0
285 	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
286 			       NULL, NULL) != 0) {
287 		apa.apa_pci_args = *pa;
288 		config_found(self, &apa, agpbusprint,
289 		    CFARGS(.iattr = "agpbus"));
290 	}
291 #endif /* NAGP */
292 }
293