1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
3 *
4 * Author: Li Yang <LeoLi@freescale.com>
5 *	   Yin Olivia <Hong-hua.Yin@freescale.com>
6 *
7 * Description:
8 * MPC8360E MDS board specific routines.
9 *
10 * Changelog:
11 * Jun 21, 2006	Initial version
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under  the terms of  the GNU General  Public License as published by the
15 * Free Software Foundation;  either version 2 of the  License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/stddef.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/errno.h>
23#include <linux/reboot.h>
24#include <linux/pci.h>
25#include <linux/kdev_t.h>
26#include <linux/major.h>
27#include <linux/console.h>
28#include <linux/delay.h>
29#include <linux/seq_file.h>
30#include <linux/root_dev.h>
31#include <linux/initrd.h>
32
33#include <asm/of_device.h>
34#include <asm/of_platform.h>
35#include <asm/system.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/irq.h>
43#include <asm/prom.h>
44#include <asm/udbg.h>
45#include <sysdev/fsl_soc.h>
46#include <asm/qe.h>
47#include <asm/qe_ic.h>
48
49#include "mpc83xx.h"
50
51#undef DEBUG
52#ifdef DEBUG
53#define DBG(fmt...) udbg_printf(fmt)
54#else
55#define DBG(fmt...)
56#endif
57
58#ifndef CONFIG_PCI
59unsigned long isa_io_base = 0;
60unsigned long isa_mem_base = 0;
61#endif
62
63static u8 *bcsr_regs = NULL;
64
65/* ************************************************************************
66 *
67 * Setup the architecture
68 *
69 */
70static void __init mpc836x_mds_setup_arch(void)
71{
72	struct device_node *np;
73
74	if (ppc_md.progress)
75		ppc_md.progress("mpc836x_mds_setup_arch()", 0);
76
77	/* Map BCSR area */
78	np = of_find_node_by_name(NULL, "bcsr");
79	if (np != 0) {
80		struct resource res;
81
82		of_address_to_resource(np, 0, &res);
83		bcsr_regs = ioremap(res.start, res.end - res.start +1);
84		of_node_put(np);
85	}
86
87#ifdef CONFIG_PCI
88	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
89		add_bridge(np);
90	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
91#endif
92
93#ifdef CONFIG_QUICC_ENGINE
94	qe_reset();
95
96	if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
97		par_io_init(np);
98		of_node_put(np);
99
100		for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
101			par_io_of_config(np);
102	}
103
104	if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
105			!= NULL){
106		/* Reset the Ethernet PHY */
107		bcsr_regs[9] &= ~0x20;
108		udelay(1000);
109		bcsr_regs[9] |= 0x20;
110		iounmap(bcsr_regs);
111		of_node_put(np);
112	}
113
114#endif				/* CONFIG_QUICC_ENGINE */
115}
116
117static struct of_device_id mpc836x_ids[] = {
118	{ .type = "soc", },
119	{ .compatible = "soc", },
120	{ .type = "qe", },
121	{ .type = "mdio", },
122	{},
123};
124
125static int __init mpc836x_declare_of_platform_devices(void)
126{
127	if (!machine_is(mpc836x_mds))
128		return 0;
129
130	/* Publish the QE devices */
131	of_platform_bus_probe(NULL, mpc836x_ids, NULL);
132
133	return 0;
134}
135device_initcall(mpc836x_declare_of_platform_devices);
136
137static void __init mpc836x_mds_init_IRQ(void)
138{
139	struct device_node *np;
140
141	np = of_find_node_by_type(NULL, "ipic");
142	if (!np)
143		return;
144
145	ipic_init(np, 0);
146
147	/* Initialize the default interrupt mapping priorities,
148	 * in case the boot rom changed something on us.
149	 */
150	ipic_set_default_priority();
151	of_node_put(np);
152
153#ifdef CONFIG_QUICC_ENGINE
154	np = of_find_node_by_type(NULL, "qeic");
155	if (!np)
156		return;
157
158	qe_ic_init(np, 0);
159	of_node_put(np);
160#endif				/* CONFIG_QUICC_ENGINE */
161}
162
163#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
164extern ulong ds1374_get_rtc_time(void);
165extern int ds1374_set_rtc_time(ulong);
166
167static int __init mpc8360_rtc_hookup(void)
168{
169	struct timespec tv;
170
171	if (!machine_is(mpc836x_mds))
172		return 0;
173
174	ppc_md.get_rtc_time = ds1374_get_rtc_time;
175	ppc_md.set_rtc_time = ds1374_set_rtc_time;
176
177	tv.tv_nsec = 0;
178	tv.tv_sec = (ppc_md.get_rtc_time) ();
179	do_settimeofday(&tv);
180
181	return 0;
182}
183
184late_initcall(mpc8360_rtc_hookup);
185#endif
186
187/*
188 * Called very early, MMU is off, device-tree isn't unflattened
189 */
190static int __init mpc836x_mds_probe(void)
191{
192        unsigned long root = of_get_flat_dt_root();
193
194        return of_flat_dt_is_compatible(root, "MPC836xMDS");
195}
196
197define_machine(mpc836x_mds) {
198	.name		= "MPC836x MDS",
199	.probe		= mpc836x_mds_probe,
200	.setup_arch	= mpc836x_mds_setup_arch,
201	.init_IRQ	= mpc836x_mds_init_IRQ,
202	.get_irq	= ipic_get_irq,
203	.restart	= mpc83xx_restart,
204	.time_init	= mpc83xx_time_init,
205	.calibrate_decr	= generic_calibrate_decr,
206	.progress	= udbg_progress,
207};
208