1/*	$NetBSD: mainbus.c,v 1.28 2012/01/27 18:53:00 para Exp $	*/
2
3/*
4 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *      This product includes software developed by Christopher G. Demetriou
17 *	for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.28 2012/01/27 18:53:00 para Exp $");
35
36#include "opt_pci.h"
37#include "pci.h"
38
39#include <sys/param.h>
40#include <sys/extent.h>
41#include <sys/device.h>
42#include <sys/malloc.h>
43#include <sys/systm.h>
44
45#include <machine/autoconf.h>
46#include <machine/bootinfo.h>
47#include <machine/isa_machdep.h>
48
49#include <powerpc/oea/spr.h>
50
51#include <dev/pci/pcivar.h>
52#include <dev/pci/pciconf.h>
53
54int	mainbus_match(device_t, cfdata_t, void *);
55void	mainbus_attach(device_t, device_t, void *);
56int	mainbus_print(void *, const char *);
57
58CFATTACH_DECL_NEW(mainbus, 0,
59    mainbus_match, mainbus_attach, NULL, NULL);
60
61struct powerpc_isa_chipset genppc_ict;
62
63/*
64 * Probe for the mainbus; always succeeds.
65 */
66int
67mainbus_match(device_t parent, cfdata_t match, void *aux)
68{
69
70	return 1;
71}
72
73/*
74 * Attach the mainbus.
75 */
76void
77mainbus_attach(device_t parent, device_t self, void *aux)
78{
79	struct mainbus_attach_args mba;
80	struct pcibus_attach_args pba;
81	struct btinfo_prodfamily *pfam;
82#if defined(PCI_NETBSD_CONFIGURE)
83	struct extent *ioext, *memext;
84#endif
85
86	aprint_naive("\n");
87	aprint_normal("\n");
88
89	mba.ma_name = "cpu";
90	config_found_ia(self, "mainbus", &mba, mainbus_print);
91
92	mba.ma_name = "eumb";
93	mba.ma_bst = &sandpoint_eumb_space_tag;
94	config_found_ia(self, "mainbus", &mba, mainbus_print);
95
96	pfam = lookup_bootinfo(BTINFO_PRODFAMILY);
97	if (pfam != NULL && strcmp(pfam->name, "nhnas") == 0) {
98		/* attach nhpow(4) for NH230/231 only */
99		mba.ma_name = "nhpow";
100		mba.ma_bst = &sandpoint_nhgpio_space_tag;
101		config_found_ia(self, "mainbus", &mba, mainbus_print);
102	}
103
104	mba.ma_name = "cfi";
105	mba.ma_bst = &sandpoint_flash_space_tag;
106	mba.ma_addr = 0xffe00000; /* smallest flash is 2 MiB */
107	config_found_ia(self, "mainbus", &mba, mainbus_print);
108
109	/*
110	 * XXX Note also that the presence of a PCI bus should
111	 * XXX _always_ be checked, and if present the bus should be
112	 * XXX 'found'.  However, because of the structure of the code,
113	 * XXX that's not currently possible.
114	 */
115#if NPCI > 0
116#if defined(PCI_NETBSD_CONFIGURE)
117	ioext  = extent_create("pciio",  0x00001000, 0x0000ffff,
118	    NULL, 0, EX_NOWAIT);
119	memext = extent_create("pcimem", 0x80000000, 0x8fffffff,
120	    NULL, 0, EX_NOWAIT);
121
122	pci_configure_bus(0, ioext, memext, NULL, 0, 32);
123
124	extent_destroy(ioext);
125	extent_destroy(memext);
126#endif
127
128	pba.pba_iot = &sandpoint_io_space_tag;
129	pba.pba_memt = &sandpoint_mem_space_tag;
130	pba.pba_dmat = &pci_bus_dma_tag;
131	pba.pba_dmat64 = NULL;
132	pba.pba_bus = 0;
133	pba.pba_pc = 0;
134	pba.pba_bridgetag = NULL;
135	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
136
137	config_found_ia(self, "pcibus", &pba, pcibusprint);
138#endif
139}
140
141static int	cpu_match(device_t, cfdata_t, void *);
142static void	cpu_attach(device_t, device_t, void *);
143
144CFATTACH_DECL_NEW(cpu, 0, cpu_match, cpu_attach, NULL, NULL);
145
146extern struct cfdriver cpu_cd;
147
148int
149cpu_match(device_t parent, cfdata_t cf, void *aux)
150{
151	struct mainbus_attach_args *mba = aux;
152
153	if (strcmp(mba->ma_name, cpu_cd.cd_name) != 0)
154		return 0;
155
156	if (cpu_info[0].ci_dev != NULL)
157		return 0;
158
159	return 1;
160}
161
162void
163cpu_attach(device_t parent, device_t self, void *aux)
164{
165	static uint8_t mem_to_cpuclk[] = {
166		25, 30, 45, 20, 20, 00, 10, 30,
167		30, 20, 45, 30, 25, 35, 30, 35,
168		20, 25, 20, 30, 35, 40, 40, 20,
169		30, 25, 40, 30, 30, 25, 35, 00
170	};
171	extern u_long ticks_per_sec;
172	struct cpu_info *ci;
173	u_int hid1, vers;
174
175	ci = cpu_attach_common(self, 0);
176	if (ci == NULL)
177		return;
178
179	vers = (mfpvr() >> 16) & 0xffff;
180	if (ci->ci_khz == 0 && vers == MPC8245) {
181		/* calculate speed from bus clock and PLL ratio */
182		asm volatile ("mfspr %0,1009" : "=r"(hid1));
183		ci->ci_khz = ((uint64_t)ticks_per_sec * 4 *
184		    mem_to_cpuclk[hid1 >> 27] + 10) / 10000;
185		aprint_normal_dev(self, "%u.%02u MHz\n",
186		    ci->ci_khz / 1000, (ci->ci_khz / 10) % 100);
187	}
188}
189
190int
191mainbus_print(void *aux, const char *pnp)
192{
193	struct mainbus_attach_args *mba = aux;
194
195	if (pnp)
196		aprint_normal("%s at %s", mba->ma_name, pnp);
197	return UNCONF;
198}
199