xref: /netbsd/sys/arch/powerpc/pci/pchb.c (revision 6550d01e)
1 /*	$NetBSD: pchb.c,v 1.4 2008/04/28 20:23:32 martin 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.4 2008/04/28 20:23:32 martin Exp $");
34 
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 
40 #include <machine/bus.h>
41 #include <machine/pio.h>
42 
43 #include <dev/pci/pcivar.h>
44 #include <dev/pci/pcireg.h>
45 #include <dev/pci/pcidevs.h>
46 #include <dev/pci/agpreg.h>
47 #include <dev/pci/agpvar.h>
48 
49 #include <dev/ic/mpc105reg.h>
50 #include <dev/ic/mpc106reg.h>
51 #include <dev/ic/ibm82660reg.h>
52 
53 #include "agp.h"
54 
55 int	pchbmatch(struct device *, struct cfdata *, void *);
56 void	pchbattach(struct device *, struct device *, void *);
57 
58 CFATTACH_DECL(pchb, sizeof(struct device),
59     pchbmatch, pchbattach, NULL, NULL);
60 
61 int
62 pchbmatch(struct device *parent, struct cfdata *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
78 mpc105_print(struct pci_attach_args *pa, struct device *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("%s: L2 cache: ", self->dv_xname);
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
121 mpc106_print(struct pci_attach_args *pa, struct device *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("%s: L2 cache: ", self->dv_xname);
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
180 ibm82660_print(struct pci_attach_args *pa, struct device *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("%s: L1: %s L2: %s %s\n", self->dv_xname,
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("%s: MCP# assertion %s "
218 	    "TEA# assertion %s\n", self->dv_xname,
219 	    (reg1 & IBM_82660_OPTIONS_1_MCP) ? "enabled" : "disabled",
220 	    (reg1 & IBM_82660_OPTIONS_1_TEA) ? "enabled" : "disabled");
221 	aprint_verbose("%s: PCI/ISA I/O mapping %s\n", self->dv_xname,
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("%s: DRAM %s (%s) SRAM %s\n", self->dv_xname,
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("%s: Snoop mode %s\n", self->dv_xname,
230 	    (reg1 & IBM_82660_OPTIONS_3_SNOOP) ? "603" : "601/604");
231 }
232 
233 void
234 pchbattach(struct device *parent, struct device *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_normal("\n");
245 
246 	/*
247 	 * All we do is print out a description.  Eventually, we
248 	 * might want to add code that does something that's
249 	 * possibly chipset-specific.
250 	 */
251 
252 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
253 	aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo,
254 	    PCI_REVISION(pa->pa_class));
255 
256 	switch (PCI_VENDOR(pa->pa_id)) {
257 	case PCI_VENDOR_IBM:
258 		switch (PCI_PRODUCT(pa->pa_id)) {
259 		case PCI_PRODUCT_IBM_82660:
260 			ibm82660_print(pa, self);
261 			break;
262 		case PCI_PRODUCT_IBM_PYTHON:
263 			python = mapiodev(0xfeff6000, 0x60);
264 			v = 0x88b78e01; /* taken from linux */
265 			out32rb(python+0x30, v);
266 			v = in32rb(python+0x30);
267 			aprint_debug("Reset python reg 30 to 0x%x\n", v);
268 			break;
269 		}
270 		break;
271 	case PCI_VENDOR_MOT:
272 		switch (PCI_PRODUCT(pa->pa_id)) {
273 		case PCI_PRODUCT_MOT_MPC105:
274 			mpc105_print(pa, self);
275 			break;
276 		case PCI_PRODUCT_MOT_MPC106:
277 			mpc106_print(pa, self);
278 			break;
279 		}
280 		break;
281 	}
282 
283 #if NAGP > 0
284 	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
285 			       NULL, NULL) != 0) {
286 		apa.apa_pci_args = *pa;
287 		config_found_ia(self, "agpbus", &apa, agpbusprint);
288 	}
289 #endif /* NAGP */
290 }
291