Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6] / arch / powerpc / platforms / 86xx / mpc86xx_hpcn.c
1 /*
2  * MPC86xx HPCN board specific routines
3  *
4  * Recode: ZHANG WEI <wei.zhang@freescale.com>
5  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
6  *
7  * Copyright 2006 Freescale Semiconductor Inc.
8  *
9  * This program is free software; you can redistribute  it and/or modify it
10  * under  the terms of  the GNU General  Public License as published by the
11  * Free Software Foundation;  either version 2 of the  License, or (at your
12  * option) any later version.
13  */
14
15 #include <linux/stddef.h>
16 #include <linux/kernel.h>
17 #include <linux/pci.h>
18 #include <linux/kdev_t.h>
19 #include <linux/delay.h>
20 #include <linux/seq_file.h>
21
22 #include <asm/system.h>
23 #include <asm/time.h>
24 #include <asm/machdep.h>
25 #include <asm/pci-bridge.h>
26 #include <asm/mpc86xx.h>
27 #include <asm/prom.h>
28 #include <mm/mmu_decl.h>
29 #include <asm/udbg.h>
30 #include <asm/i8259.h>
31
32 #include <asm/mpic.h>
33
34 #include <sysdev/fsl_pci.h>
35 #include <sysdev/fsl_soc.h>
36
37 #include "mpc86xx.h"
38 #include "mpc8641_hpcn.h"
39
40 #undef DEBUG
41
42 #ifdef DEBUG
43 #define DBG(fmt...) do { printk(KERN_ERR fmt); } while(0)
44 #else
45 #define DBG(fmt...) do { } while(0)
46 #endif
47
48 #ifdef CONFIG_PCI
49 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
50 {
51         unsigned int cascade_irq = i8259_irq();
52         if (cascade_irq != NO_IRQ)
53                 generic_handle_irq(cascade_irq);
54         desc->chip->eoi(irq);
55 }
56 #endif  /* CONFIG_PCI */
57
58 void __init
59 mpc86xx_hpcn_init_irq(void)
60 {
61         struct mpic *mpic1;
62         struct device_node *np;
63         struct resource res;
64 #ifdef CONFIG_PCI
65         struct device_node *cascade_node = NULL;
66         int cascade_irq;
67 #endif
68
69         /* Determine PIC address. */
70         np = of_find_node_by_type(NULL, "open-pic");
71         if (np == NULL)
72                 return;
73         of_address_to_resource(np, 0, &res);
74
75         /* Alloc mpic structure and per isu has 16 INT entries. */
76         mpic1 = mpic_alloc(np, res.start,
77                         MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
78                         0, 256, " MPIC     ");
79         BUG_ON(mpic1 == NULL);
80
81         mpic_init(mpic1);
82
83 #ifdef CONFIG_PCI
84         /* Initialize i8259 controller */
85         for_each_node_by_type(np, "interrupt-controller")
86                 if (of_device_is_compatible(np, "chrp,iic")) {
87                         cascade_node = np;
88                         break;
89                 }
90         if (cascade_node == NULL) {
91                 printk(KERN_DEBUG "mpc86xxhpcn: no ISA interrupt controller\n");
92                 return;
93         }
94
95         cascade_irq = irq_of_parse_and_map(cascade_node, 0);
96         if (cascade_irq == NO_IRQ) {
97                 printk(KERN_ERR "mpc86xxhpcn: failed to map cascade interrupt");
98                 return;
99         }
100         DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
101
102         i8259_init(cascade_node, 0);
103         of_node_put(cascade_node);
104
105         set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
106 #endif
107 }
108
109 #ifdef CONFIG_PCI
110 extern int uses_fsl_uli_m1575;
111 extern int uli_exclude_device(struct pci_controller *hose,
112                                 u_char bus, u_char devfn);
113
114 static int mpc86xx_exclude_device(struct pci_controller *hose,
115                                    u_char bus, u_char devfn)
116 {
117         struct device_node* node;       
118         struct resource rsrc;
119
120         node = (struct device_node *)hose->arch_data;
121         of_address_to_resource(node, 0, &rsrc);
122
123         if ((rsrc.start & 0xfffff) == 0x8000) {
124                 return uli_exclude_device(hose, bus, devfn);
125         }
126
127         return PCIBIOS_SUCCESSFUL;
128 }
129 #endif /* CONFIG_PCI */
130
131
132 static void __init
133 mpc86xx_hpcn_setup_arch(void)
134 {
135         struct device_node *np;
136
137         if (ppc_md.progress)
138                 ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
139
140         np = of_find_node_by_type(NULL, "cpu");
141         if (np != 0) {
142                 const unsigned int *fp;
143
144                 fp = of_get_property(np, "clock-frequency", NULL);
145                 if (fp != 0)
146                         loops_per_jiffy = *fp / HZ;
147                 else
148                         loops_per_jiffy = 50000000 / HZ;
149                 of_node_put(np);
150         }
151
152 #ifdef CONFIG_PCI
153         for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) {
154                 struct resource rsrc;
155                 of_address_to_resource(np, 0, &rsrc);
156                 if ((rsrc.start & 0xfffff) == 0x8000)
157                         fsl_add_bridge(np, 1);
158                 else
159                         fsl_add_bridge(np, 0);
160         }
161         uses_fsl_uli_m1575 = 1;
162         ppc_md.pci_exclude_device = mpc86xx_exclude_device;
163
164 #endif
165
166         printk("MPC86xx HPCN board from Freescale Semiconductor\n");
167
168 #ifdef CONFIG_SMP
169         mpc86xx_smp_init();
170 #endif
171 }
172
173
174 void
175 mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
176 {
177         struct device_node *root;
178         uint memsize = total_memory;
179         const char *model = "";
180         uint svid = mfspr(SPRN_SVR);
181
182         seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
183
184         root = of_find_node_by_path("/");
185         if (root)
186                 model = of_get_property(root, "model", NULL);
187         seq_printf(m, "Machine\t\t: %s\n", model);
188         of_node_put(root);
189
190         seq_printf(m, "SVR\t\t: 0x%x\n", svid);
191         seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
192 }
193
194
195 /*
196  * Called very early, device-tree isn't unflattened
197  */
198 static int __init mpc86xx_hpcn_probe(void)
199 {
200         unsigned long root = of_get_flat_dt_root();
201
202         if (of_flat_dt_is_compatible(root, "mpc86xx"))
203                 return 1;       /* Looks good */
204
205         return 0;
206 }
207
208
209 void
210 mpc86xx_restart(char *cmd)
211 {
212         void __iomem *rstcr;
213
214         rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
215
216         local_irq_disable();
217
218         /* Assert reset request to Reset Control Register */
219         out_be32(rstcr, 0x2);
220
221         /* not reached */
222 }
223
224
225 long __init
226 mpc86xx_time_init(void)
227 {
228         unsigned int temp;
229
230         /* Set the time base to zero */
231         mtspr(SPRN_TBWL, 0);
232         mtspr(SPRN_TBWU, 0);
233
234         temp = mfspr(SPRN_HID0);
235         temp |= HID0_TBEN;
236         mtspr(SPRN_HID0, temp);
237         asm volatile("isync");
238
239         return 0;
240 }
241
242 define_machine(mpc86xx_hpcn) {
243         .name                   = "MPC86xx HPCN",
244         .probe                  = mpc86xx_hpcn_probe,
245         .setup_arch             = mpc86xx_hpcn_setup_arch,
246         .init_IRQ               = mpc86xx_hpcn_init_irq,
247         .show_cpuinfo           = mpc86xx_hpcn_show_cpuinfo,
248         .get_irq                = mpic_get_irq,
249         .restart                = mpc86xx_restart,
250         .time_init              = mpc86xx_time_init,
251         .calibrate_decr         = generic_calibrate_decr,
252         .progress               = udbg_progress,
253         .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
254 };