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