1/*
2 * MPC834x SYS board specific routines
3 *
4 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
5 *
6 * Copyright 2005 Freescale Semiconductor Inc.
7 *
8 * This program is free software; you can redistribute  it and/or modify it
9 * under  the terms of  the GNU General  Public License as published by the
10 * Free Software Foundation;  either version 2 of the  License, or (at your
11 * option) any later version.
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/major.h>
22#include <linux/console.h>
23#include <linux/delay.h>
24#include <linux/seq_file.h>
25#include <linux/root_dev.h>
26#include <linux/serial.h>
27#include <linux/tty.h>	/* for linux/serial_core.h */
28#include <linux/serial_core.h>
29#include <linux/initrd.h>
30#include <linux/module.h>
31#include <linux/fsl_devices.h>
32
33#include <asm/system.h>
34#include <asm/pgtable.h>
35#include <asm/page.h>
36#include <asm/atomic.h>
37#include <asm/time.h>
38#include <asm/io.h>
39#include <asm/machdep.h>
40#include <asm/ipic.h>
41#include <asm/bootinfo.h>
42#include <asm/pci-bridge.h>
43#include <asm/mpc83xx.h>
44#include <asm/irq.h>
45#include <asm/kgdb.h>
46#include <asm/ppc_sys.h>
47#include <mm/mmu_decl.h>
48
49#include <syslib/ppc83xx_setup.h>
50
51#ifndef CONFIG_PCI
52unsigned long isa_io_base = 0;
53unsigned long isa_mem_base = 0;
54#endif
55
56extern unsigned long total_memory;	/* in mm/init */
57
58unsigned char __res[sizeof (bd_t)];
59
60#ifdef CONFIG_PCI
61int
62mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
63{
64	static char pci_irq_table[][4] =
65	    /*
66	     *      PCI IDSEL/INTPIN->INTLINE
67	     *       A      B      C      D
68	     */
69	{
70		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x11 */
71		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x12 */
72		{PIRQD, PIRQA, PIRQB, PIRQC},	/* idsel 0x13 */
73		{0, 0, 0, 0},
74		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x15 */
75		{PIRQD, PIRQA, PIRQB, PIRQC},	/* idsel 0x16 */
76		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x17 */
77		{PIRQB, PIRQC, PIRQD, PIRQA},	/* idsel 0x18 */
78		{0, 0, 0, 0},			/* idsel 0x19 */
79		{0, 0, 0, 0},			/* idsel 0x20 */
80	};
81
82	const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
83	return PCI_IRQ_TABLE_LOOKUP;
84}
85
86int
87mpc83xx_exclude_device(u_char bus, u_char devfn)
88{
89	return PCIBIOS_SUCCESSFUL;
90}
91#endif /* CONFIG_PCI */
92
93/* ************************************************************************
94 *
95 * Setup the architecture
96 *
97 */
98static void __init
99mpc834x_sys_setup_arch(void)
100{
101	bd_t *binfo = (bd_t *) __res;
102	unsigned int freq;
103	struct gianfar_platform_data *pdata;
104	struct gianfar_mdio_data *mdata;
105
106	/* get the core frequency */
107	freq = binfo->bi_intfreq;
108
109	/* Set loops_per_jiffy to a half-way reasonable value,
110	   for use until calibrate_delay gets called. */
111	loops_per_jiffy = freq / HZ;
112
113#ifdef CONFIG_PCI
114	/* setup PCI host bridges */
115	mpc83xx_setup_hose();
116#endif
117	mpc83xx_early_serial_map();
118
119	/* setup the board related info for the MDIO bus */
120	mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC83xx_MDIO);
121
122	mdata->irq[0] = MPC83xx_IRQ_EXT1;
123	mdata->irq[1] = MPC83xx_IRQ_EXT2;
124	mdata->irq[2] = PHY_POLL;
125	mdata->irq[31] = PHY_POLL;
126
127	/* setup the board related information for the enet controllers */
128	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
129	if (pdata) {
130		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
131		pdata->bus_id = 0;
132		pdata->phy_id = 0;
133		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
134	}
135
136	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
137	if (pdata) {
138		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
139		pdata->bus_id = 0;
140		pdata->phy_id = 1;
141		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
142	}
143
144#ifdef CONFIG_BLK_DEV_INITRD
145	if (initrd_start)
146		ROOT_DEV = Root_RAM0;
147	else
148#endif
149#ifdef  CONFIG_ROOT_NFS
150		ROOT_DEV = Root_NFS;
151#else
152		ROOT_DEV = Root_HDA1;
153#endif
154}
155
156static void __init
157mpc834x_sys_map_io(void)
158{
159	/* we steal the lowest ioremap addr for virt space */
160	io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
161}
162
163int
164mpc834x_sys_show_cpuinfo(struct seq_file *m)
165{
166	uint pvid, svid, phid1;
167	bd_t *binfo = (bd_t *) __res;
168	unsigned int freq;
169
170	/* get the core frequency */
171	freq = binfo->bi_intfreq;
172
173	pvid = mfspr(SPRN_PVR);
174	svid = mfspr(SPRN_SVR);
175
176	seq_printf(m, "Vendor\t\t: Freescale Inc.\n");
177	seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name);
178	seq_printf(m, "core clock\t: %d MHz\n"
179			"bus  clock\t: %d MHz\n",
180			(int)(binfo->bi_intfreq / 1000000),
181			(int)(binfo->bi_busfreq / 1000000));
182	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
183	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
184
185	/* Display cpu Pll setting */
186	phid1 = mfspr(SPRN_HID1);
187	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
188
189	/* Display the amount of memory */
190	seq_printf(m, "Memory\t\t: %d MB\n", (int)(binfo->bi_memsize / (1024 * 1024)));
191
192	return 0;
193}
194
195
196void __init
197mpc834x_sys_init_IRQ(void)
198{
199	bd_t *binfo = (bd_t *) __res;
200
201	u8 senses[8] = {
202		0,			/* EXT 0 */
203		IRQ_SENSE_LEVEL,	/* EXT 1 */
204		IRQ_SENSE_LEVEL,	/* EXT 2 */
205		0,			/* EXT 3 */
206#ifdef CONFIG_PCI
207		IRQ_SENSE_LEVEL,	/* EXT 4 */
208		IRQ_SENSE_LEVEL,	/* EXT 5 */
209		IRQ_SENSE_LEVEL,	/* EXT 6 */
210		IRQ_SENSE_LEVEL,	/* EXT 7 */
211#else
212		0,			/* EXT 4 */
213		0,			/* EXT 5 */
214		0,			/* EXT 6 */
215		0,			/* EXT 7 */
216#endif
217	};
218
219	ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
220
221	/* Initialize the default interrupt mapping priorities,
222	 * in case the boot rom changed something on us.
223	 */
224	ipic_set_default_priority();
225}
226
227#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
228extern ulong	ds1374_get_rtc_time(void);
229extern int	ds1374_set_rtc_time(ulong);
230
231static int __init
232mpc834x_rtc_hookup(void)
233{
234	struct timespec	tv;
235
236	ppc_md.get_rtc_time = ds1374_get_rtc_time;
237	ppc_md.set_rtc_time = ds1374_set_rtc_time;
238
239	tv.tv_nsec = 0;
240	tv.tv_sec = (ppc_md.get_rtc_time)();
241	do_settimeofday(&tv);
242
243	return 0;
244}
245late_initcall(mpc834x_rtc_hookup);
246#endif
247static __inline__ void
248mpc834x_sys_set_bat(void)
249{
250	/* we steal the lowest ioremap addr for virt space */
251	mb();
252	mtspr(SPRN_DBAT1U, VIRT_IMMRBAR | 0x1e);
253	mtspr(SPRN_DBAT1L, immrbar | 0x2a);
254	mb();
255}
256
257void __init
258platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
259	      unsigned long r6, unsigned long r7)
260{
261	bd_t *binfo = (bd_t *) __res;
262
263	/* parse_bootinfo must always be called first */
264	parse_bootinfo(find_bootinfo());
265
266	/*
267	 * If we were passed in a board information, copy it into the
268	 * residual data area.
269	 */
270	if (r3) {
271		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
272		       sizeof (bd_t));
273	}
274
275#if defined(CONFIG_BLK_DEV_INITRD)
276	/*
277	 * If the init RAM disk has been configured in, and there's a valid
278	 * starting address for it, set it up.
279	 */
280	if (r4) {
281		initrd_start = r4 + KERNELBASE;
282		initrd_end = r5 + KERNELBASE;
283	}
284#endif /* CONFIG_BLK_DEV_INITRD */
285
286	/* Copy the kernel command line arguments to a safe place. */
287	if (r6) {
288		*(char *) (r7 + KERNELBASE) = 0;
289		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
290	}
291
292	immrbar = binfo->bi_immr_base;
293
294	mpc834x_sys_set_bat();
295
296#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
297	{
298		struct uart_port p;
299
300		memset(&p, 0, sizeof (p));
301		p.iotype = UPIO_MEM;
302		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500);
303		p.uartclk = binfo->bi_busfreq;
304
305		gen550_init(0, &p);
306
307		memset(&p, 0, sizeof (p));
308		p.iotype = UPIO_MEM;
309		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600);
310		p.uartclk = binfo->bi_busfreq;
311
312		gen550_init(1, &p);
313	}
314#endif
315
316	identify_ppc_sys_by_id(mfspr(SPRN_SVR));
317
318	/* setup the PowerPC module struct */
319	ppc_md.setup_arch = mpc834x_sys_setup_arch;
320	ppc_md.show_cpuinfo = mpc834x_sys_show_cpuinfo;
321
322	ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
323	ppc_md.get_irq = ipic_get_irq;
324
325	ppc_md.restart = mpc83xx_restart;
326	ppc_md.power_off = mpc83xx_power_off;
327	ppc_md.halt = mpc83xx_halt;
328
329	ppc_md.find_end_of_memory = mpc83xx_find_end_of_memory;
330	ppc_md.setup_io_mappings  = mpc834x_sys_map_io;
331
332	ppc_md.time_init = mpc83xx_time_init;
333	ppc_md.set_rtc_time = NULL;
334	ppc_md.get_rtc_time = NULL;
335	ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
336
337	ppc_md.early_serial_map = mpc83xx_early_serial_map;
338#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
339	ppc_md.progress = gen550_progress;
340#endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
341
342	if (ppc_md.progress)
343		ppc_md.progress("mpc834x_sys_init(): exit", 0);
344
345	return;
346}
347