1/*	$NetBSD: pchb.c,v 1.10 2011/06/22 18:06:34 matt Exp $	*/
2
3/*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
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#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.10 2011/06/22 18:06:34 matt Exp $");
33
34#include "pci.h"
35#include "opt_pci.h"
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/device.h>
41#include <sys/extent.h>
42#include <sys/malloc.h>
43
44#define _IBM4XX_BUS_DMA_PRIVATE
45
46#include <powerpc/ibm4xx/ibm405gp.h>
47#include <powerpc/ibm4xx/pci_machdep.h>
48#include <powerpc/ibm4xx/dev/plbvar.h>
49
50#include <dev/pci/pcivar.h>
51#include <dev/pci/pcireg.h>
52#include <dev/pci/pcidevs.h>
53#include <dev/pci/pciconf.h>
54
55static int	pchbmatch(device_t, cfdata_t, void *);
56static void	pchbattach(device_t, device_t, void *);
57static int	pchbprint(void *, const char *);
58
59CFATTACH_DECL_NEW(pchb, 0,
60    pchbmatch, pchbattach, NULL, NULL);
61
62static int pcifound = 0;
63
64/* IO window located @ e8000000 and maps to 0-0xffff */
65static struct powerpc_bus_space pchb_io_tag = {
66	_BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_IO_TYPE,
67	IBM405GP_PLB_PCI_IO_START,		/* offset */
68	IBM405GP_PCI_PCI_IO_START,		/* extent base */
69	IBM405GP_PCI_PCI_IO_START + 0xffff,	/* extent limit */
70};
71
72/* PCI memory window is directly mapped */
73static struct powerpc_bus_space pchb_mem_tag = {
74	_BUS_SPACE_LITTLE_ENDIAN | _BUS_SPACE_MEM_TYPE,
75	0x00000000,					/* offset */
76	IBM405GP_PCI_MEM_START,			/* extent base */
77	IBM405GP_PCI_MEM_START + 0x1fffffff,	/* extent limit */
78};
79
80
81static int
82pchbmatch(device_t parent, cfdata_t cf, void *aux)
83{
84	struct plb_attach_args *paa = aux;
85	/* XXX chipset tag unused by walnut, so just pass 0 */
86	pci_chipset_tag_t pc = ibm4xx_get_pci_chipset_tag();
87	pcitag_t tag;
88	int class, id;
89
90	/* match only pchb devices */
91	if (strcmp(paa->plb_name, cf->cf_name) != 0)
92		return 0;
93
94	ibm4xx_pci_machdep_init();
95	tag = pci_make_tag(pc, 0, 0, 0);
96
97	class = pci_conf_read(pc, tag, PCI_CLASS_REG);
98	id = pci_conf_read(pc, tag, PCI_ID_REG);
99
100	/*
101	 * Match all known PCI host chipsets.
102	 */
103	if (PCI_CLASS(class) == PCI_CLASS_BRIDGE &&
104	    PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_HOST) {
105		switch (PCI_VENDOR(id)) {
106		case PCI_VENDOR_IBM:
107			switch (PCI_PRODUCT(id)) {
108			case PCI_PRODUCT_IBM_405GP:
109				return (!pcifound);
110			}
111			break;
112		}
113	}
114	return (0);
115}
116
117static void
118pchbattach(device_t parent, device_t self, void *aux)
119{
120	struct plb_attach_args *paa = aux;
121	struct pcibus_attach_args pba;
122	char devinfo[256];
123#ifdef PCI_CONFIGURE_VERBOSE
124	extern int pci_conf_debug;
125
126	pci_conf_debug = 1;
127#endif
128	pci_chipset_tag_t pc = ibm4xx_get_pci_chipset_tag();
129	pcitag_t tag;
130	int class, id;
131
132	ibm4xx_pci_machdep_init();
133	tag = pci_make_tag(pc, 0, 0, 0);
134
135	class = pci_conf_read(pc, tag, PCI_CLASS_REG);
136	id = pci_conf_read(pc, tag, PCI_ID_REG);
137
138	aprint_normal("\n");
139	pcifound++;
140	/*
141	 * All we do is print out a description.  Eventually, we
142	 * might want to add code that does something that's
143	 * possibly chipset-specific.
144	 */
145
146	pci_devinfo(id, class, 0, devinfo, sizeof(devinfo));
147	aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo,
148	    PCI_REVISION(class));
149
150	ibm4xx_pci_machdep_init(); /* Redundant... */
151	ibm4xx_setup_pci();
152#ifdef PCI_CONFIGURE_VERBOSE
153	ibm4xx_show_pci_map();
154#endif
155
156	if (bus_space_init(&pchb_io_tag, "pchbio", NULL, 0))
157		panic("pchbattach: can't init IO tag");
158	if (bus_space_init(&pchb_mem_tag, "pchbmem", NULL, 0))
159		panic("pchbattach: can't init MEM tag");
160
161#ifdef PCI_NETBSD_CONFIGURE
162	struct extent *memext = extent_create("pcimem",
163	    IBM405GP_PCI_MEM_START,
164	    IBM405GP_PCI_MEM_START + 0x1fffffff, NULL, 0,
165	    EX_NOWAIT);
166	struct extent *ioext = extent_create("pciio",
167	    IBM405GP_PCI_PCI_IO_START,
168	    IBM405GP_PCI_PCI_IO_START + 0xffff, NULL, 0, EX_NOWAIT);
169	pci_configure_bus(pc, ioext, memext, NULL, 0, 32);
170	extent_destroy(ioext);
171	extent_destroy(memext);
172#endif /* PCI_NETBSD_CONFIGURE */
173
174#ifdef PCI_CONFIGURE_VERBOSE
175	printf("running config_found PCI\n");
176#endif
177	/* IO window located @ e8000000 and maps to 0-0xffff */
178	pba.pba_iot = &pchb_io_tag;
179	/* PCI memory window is directly mapped */
180	pba.pba_memt = &pchb_mem_tag;
181	pba.pba_dmat = paa->plb_dmat;
182	pba.pba_dmat64 = NULL;
183	pba.pba_pc = pc;
184	pba.pba_bus = 0;
185	pba.pba_bridgetag = NULL;
186	pba.pba_flags = PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY;
187	config_found_ia(self, "pcibus", &pba, pchbprint);
188}
189
190
191static int
192pchbprint(void *aux, const char *p)
193{
194
195	if (p == NULL)
196		return (UNCONF);
197	return (QUIET);
198}
199
200#if 0
201static void
202scan_pci_bus(void)
203{
204	pci_chipset_tag_t pc = ibm4xx_get_pci_chipset_tag();
205	pcitag_t tag;
206	int i, x;
207
208	for (i=0;i<32;i++){
209		tag = pci_make_tag(pc, 0, i, 0);
210		x = pci_conf_read(pc, tag, 0);
211		printf("%d tag=%08x : %08x\n", i, tag, x);
212#if 0
213		if (PCI_VENDOR(x) == PCI_VENDOR_INTEL
214		    && PCI_PRODUCT(x) == PCI_PRODUCT_INTEL_80960_RP) {
215			/* Do not configure PCI bus analyzer */
216			continue;
217		}
218		x = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
219		x |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
220		pci_conf_write(0, tag, PCI_COMMAND_STATUS_REG, x);
221#endif
222	}
223}
224#endif
225