1/*
2 * Board setup routines for Force PowerPMC-250 Processor PMC
3 *
4 * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
5 * Borrowed heavily from prpmc750_*.c by
6 * 	Matt Porter <mporter@mvista.com>
7 *
8 * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
9 * the terms of the GNU General Public License version 2.  This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13
14#include <linux/stddef.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/reboot.h>
19#include <linux/pci.h>
20#include <linux/kdev_t.h>
21#include <linux/types.h>
22#include <linux/major.h>
23#include <linux/initrd.h>
24#include <linux/console.h>
25#include <linux/delay.h>
26#include <linux/slab.h>
27#include <linux/seq_file.h>
28#include <linux/ide.h>
29#include <linux/root_dev.h>
30
31#include <asm/byteorder.h>
32#include <asm/system.h>
33#include <asm/pgtable.h>
34#include <asm/page.h>
35#include <asm/dma.h>
36#include <asm/io.h>
37#include <asm/irq.h>
38#include <asm/machdep.h>
39#include <asm/time.h>
40#include <platforms/powerpmc250.h>
41#include <asm/open_pic.h>
42#include <asm/pci-bridge.h>
43#include <asm/mpc10x.h>
44#include <asm/uaccess.h>
45#include <asm/bootinfo.h>
46
47extern void powerpmc250_find_bridges(void);
48extern unsigned long loops_per_jiffy;
49
50static u_char powerpmc250_openpic_initsenses[] __initdata =
51{
52    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53    1,	/* PMC INTA (also MPC107 output interrupt INTA) */
54    1,	/* PMC INTB (also I82559 Ethernet controller) */
55    1,	/* PMC INTC */
56    1,	/* PMC INTD */
57    0,	/* DUART interrupt (active high) */
58};
59
60static int
61powerpmc250_show_cpuinfo(struct seq_file *m)
62{
63	seq_printf(m,"machine\t\t: Force PowerPMC250\n");
64
65	return 0;
66}
67
68static void __init
69powerpmc250_setup_arch(void)
70{
71	/* init to some ~sane value until calibrate_delay() runs */
72	loops_per_jiffy = 50000000/HZ;
73
74	/* Lookup PCI host bridges */
75	powerpmc250_find_bridges();
76
77#ifdef CONFIG_BLK_DEV_INITRD
78	if (initrd_start)
79		ROOT_DEV = Root_RAM0;
80	else
81#endif
82#ifdef CONFIG_ROOT_NFS
83		ROOT_DEV = Root_NFS;
84#else
85		ROOT_DEV = Root_SDA2;
86#endif
87
88	printk("Force PowerPMC250 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
89}
90
91
92static void __init
93powerpmc250_calibrate_decr(void)
94{
95	unsigned long freq;
96	int divisor = 4;
97
98	//freq = powerpmc250_get_bus_speed();
99#warning hardcoded bus freq
100	freq = 100000000;
101
102	tb_ticks_per_jiffy = freq / (HZ * divisor);
103	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
104}
105
106static void
107powerpmc250_restart(char *cmd)
108{
109	local_irq_disable();
110	/* Hard reset */
111	writeb(0x11, 0xfe000332);
112	while(1);
113}
114
115static void
116powerpmc250_halt(void)
117{
118	local_irq_disable();
119	while (1);
120}
121
122static void
123powerpmc250_power_off(void)
124{
125	powerpmc250_halt();
126}
127
128static void __init
129powerpmc250_init_IRQ(void)
130{
131
132	OpenPIC_InitSenses = powerpmc250_openpic_initsenses;
133	OpenPIC_NumInitSenses = sizeof(powerpmc250_openpic_initsenses);
134	mpc10x_set_openpic();
135}
136
137/*
138 * Set BAT 3 to map 0xf0000000 to end of physical memory space.
139 */
140static __inline__ void
141powerpmc250_set_bat(void)
142{
143	unsigned long   bat3u, bat3l;
144	static int	mapping_set = 0;
145
146	if (!mapping_set)
147	{
148		__asm__ __volatile__(
149				" lis %0,0xf000\n \
150				ori %1,%0,0x002a\n \
151				ori %0,%0,0x1ffe\n \
152				mtspr 0x21e,%0\n \
153				mtspr 0x21f,%1\n \
154				isync\n \
155				sync "
156				: "=r" (bat3u), "=r" (bat3l));
157
158		mapping_set = 1;
159	}
160	return;
161}
162
163static unsigned long __init
164powerpmc250_find_end_of_memory(void)
165{
166	/* Cover I/O space with a BAT */
167	/* yuck, better hope your ram size is a power of 2  -- paulus */
168	powerpmc250_set_bat();
169
170	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
171}
172
173static void __init
174powerpmc250_map_io(void)
175{
176	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
177}
178
179void __init
180platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
181	      unsigned long r6, unsigned long r7)
182{
183	parse_bootinfo(find_bootinfo());
184
185#ifdef CONFIG_BLK_DEV_INITRD
186	if ( r4 )
187	{
188		initrd_start = r4 + KERNELBASE;
189		initrd_end = r5 + KERNELBASE;
190	}
191#endif
192
193	/* Copy cmd_line parameters */
194	if ( r6)
195	{
196		*(char *)(r7 + KERNELBASE) = 0;
197		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
198	}
199
200	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
201	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
202	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
203
204	ppc_md.setup_arch	= powerpmc250_setup_arch;
205	ppc_md.show_cpuinfo	= powerpmc250_show_cpuinfo;
206	ppc_md.init_IRQ		= powerpmc250_init_IRQ;
207	ppc_md.get_irq		= openpic_get_irq;
208
209	ppc_md.find_end_of_memory = powerpmc250_find_end_of_memory;
210	ppc_md.setup_io_mappings = powerpmc250_map_io;
211
212	ppc_md.restart		= powerpmc250_restart;
213	ppc_md.power_off	= powerpmc250_power_off;
214	ppc_md.halt		= powerpmc250_halt;
215
216	/* PowerPMC250 has no timekeeper part */
217	ppc_md.time_init	= NULL;
218	ppc_md.get_rtc_time	= NULL;
219	ppc_md.set_rtc_time	= NULL;
220	ppc_md.calibrate_decr	= powerpmc250_calibrate_decr;
221}
222
223
224/*
225 * (This used to be arch/ppc/platforms/powerpmc250_pci.c)
226 *
227 * PCI support for Force PowerPMC250
228 *
229 */
230
231#undef DEBUG
232#ifdef DEBUG
233#define DBG(x...) printk(x)
234#else
235#define DBG(x...)
236#endif /* DEBUG */
237
238static inline int __init
239powerpmc250_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
240{
241	static char pci_irq_table[][4] =
242	/*
243	 *      PCI IDSEL/INTPIN->INTLINE
244	 *      A       B       C       D
245	 */
246	{
247		{17,	0,	0,	0},	/* Device 11 - 82559 */
248		{0,	0,	0,	0},	/* 12 */
249		{0,	0,	0,	0},	/* 13 */
250		{0,	0,	0,	0},	/* 14 */
251		{0,	0,	0,	0},	/* 15 */
252		{16,	17,	18,	19},	/* Device 16 - PMC A1?? */
253		};
254	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
255	return PCI_IRQ_TABLE_LOOKUP;
256};
257
258static int
259powerpmc250_exclude_device(u_char bus, u_char devfn)
260{
261
262	if ((bus == 0) && (PCI_SLOT(devfn) == 13 || PCI_SLOT(devfn) == 14)) {
263		return PCIBIOS_DEVICE_NOT_FOUND;
264	}
265	else {
266		return PCIBIOS_SUCCESSFUL;
267	}
268}
269
270void __init
271powerpmc250_find_bridges(void)
272{
273	struct pci_controller* hose;
274
275	hose = pcibios_alloc_controller();
276	if (!hose){
277		printk("Can't allocate PCI 'hose' structure!!!\n");
278		return;
279	}
280
281	hose->first_busno = 0;
282	hose->last_busno = 0xff;
283
284	if (mpc10x_bridge_init(hose,
285			MPC10X_MEM_MAP_B,
286			MPC10X_MEM_MAP_B,
287			MPC10X_MAPB_EUMB_BASE) == 0) {
288
289		hose->mem_resources[0].end = 0xffffffff;
290
291		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
292
293		/* ppc_md.pcibios_fixup = pcore_pcibios_fixup; */
294		ppc_md.pci_swizzle = common_swizzle;
295
296		ppc_md.pci_exclude_device = powerpmc250_exclude_device;
297		ppc_md.pci_map_irq = powerpmc250_map_irq;
298	} else {
299		if (ppc_md.progress)
300			ppc_md.progress("Bridge init failed", 0x100);
301		printk("Host bridge init failed\n");
302	}
303
304}
305