Merge git://git.infradead.org/mtd-2.6
[linux-2.6] / arch / powerpc / platforms / embedded6xx / mpc7448_hpc2.c
1 /*
2  * mpc7448_hpc2.c
3  *
4  * Board setup routines for the Freescale Taiga platform
5  *
6  * Author: Jacob Pan
7  *       jacob.pan@freescale.com
8  * Author: Xianghua Xiao
9  *       x.xiao@freescale.com
10  * Maintainer: Roy Zang <tie-fei.zang@freescale.com>
11  *      Add Flat Device Tree support fot mpc7448hpc2 board
12  *
13  * Copyright 2004-2006 Freescale Semiconductor, Inc.
14  *
15  * This file is licensed under
16  * the terms of the GNU General Public License version 2.  This program
17  * is licensed "as is" without any warranty of any kind, whether express
18  * or implied.
19  */
20
21 #include <linux/config.h>
22 #include <linux/stddef.h>
23 #include <linux/kernel.h>
24 #include <linux/pci.h>
25 #include <linux/kdev_t.h>
26 #include <linux/console.h>
27 #include <linux/delay.h>
28 #include <linux/irq.h>
29 #include <linux/ide.h>
30 #include <linux/seq_file.h>
31 #include <linux/root_dev.h>
32 #include <linux/serial.h>
33 #include <linux/tty.h>
34 #include <linux/serial_core.h>
35
36 #include <asm/system.h>
37 #include <asm/time.h>
38 #include <asm/machdep.h>
39 #include <asm/prom.h>
40 #include <asm/udbg.h>
41 #include <asm/tsi108.h>
42 #include <asm/pci-bridge.h>
43 #include <asm/reg.h>
44 #include <mm/mmu_decl.h>
45 #include "mpc7448_hpc2.h"
46 #include <asm/tsi108_irq.h>
47 #include <asm/mpic.h>
48
49 #undef DEBUG
50 #ifdef DEBUG
51 #define DBG(fmt...) do { printk(fmt); } while(0)
52 #else
53 #define DBG(fmt...) do { } while(0)
54 #endif
55
56 #ifndef CONFIG_PCI
57 isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
58 isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
59 pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
60 #endif
61
62 extern int tsi108_setup_pci(struct device_node *dev);
63 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
64 extern void tsi108_pci_int_init(void);
65 extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused);
66
67 /*
68  * Define all of the IRQ senses and polarities.  Taken from the
69  * mpc7448hpc  manual.
70  * Note:  Likely, this table and the following function should be
71  *        obtained and derived from the OF Device Tree.
72  */
73
74 static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
75         /* External on-board sources */
76         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* INT[0] XINT0 from FPGA */
77         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* INT[1] XINT1 from FPGA */
78         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* INT[2] PHY_INT from both GIGE */
79         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* INT[3] RESERVED */
80         /* Internal Tsi108/109 interrupt sources */
81         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Reserved IRQ */
82         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Reserved IRQ */
83         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Reserved IRQ */
84         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Reserved IRQ */
85         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* DMA0 */
86         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* DMA1 */
87         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* DMA2 */
88         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* DMA3 */
89         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* UART0 */
90         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* UART1 */
91         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* I2C */
92         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* GPIO */
93         (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* GIGE0 */
94         (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* GIGE1 */
95         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Reserved IRQ */
96         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* HLP */
97         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* SDC */
98         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Processor IF */
99         (IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),      /* Reserved IRQ */
100         (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* PCI/X block */
101 };
102
103 int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
104 {
105         if (bus == 0 && PCI_SLOT(devfn) == 0)
106                 return PCIBIOS_DEVICE_NOT_FOUND;
107         else
108                 return PCIBIOS_SUCCESSFUL;
109 }
110
111 /*
112  * find pci slot by devfn in interrupt map of OF tree
113  */
114 u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn)
115 {
116         int i;
117         unsigned int tmp;
118         for (i = 0; i < 4; i++){
119                 tmp = interrupt_map[i*4*7];
120                 if ((tmp >> 11) == (devfn >> 3))
121                         return i;
122         }
123         return i;
124 }
125
126 /*
127  * Scans the interrupt map for pci device
128  */
129 void mpc7448_hpc2_fixup_irq(struct pci_dev *dev)
130 {
131         struct pci_controller *hose;
132         struct device_node *node;
133         unsigned int *interrupt;
134         int busnr;
135         int len;
136         u8 slot;
137         u8 pin;
138
139         /* Lookup the hose */
140         busnr = dev->bus->number;
141         hose = pci_bus_to_hose(busnr);
142         if (!hose)
143                 printk(KERN_ERR "No pci hose found\n");
144
145         /* Check it has an OF node associated */
146         node = (struct device_node *) hose->arch_data;
147         if (!node)
148                 printk(KERN_ERR "No pci node found\n");
149
150         interrupt = (unsigned int *) get_property(node, "interrupt-map", &len);
151         slot = find_slot_by_devfn(interrupt, dev->devfn);
152         pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
153         if (pin == 0 || pin > 4)
154                 pin = 1;
155         pin--;
156         dev->irq  = interrupt[slot*4*7 + pin*7 + 5];
157         DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq);
158 }
159 /* temporary pci irq map fixup*/
160
161 void __init mpc7448_hpc2_pcibios_fixup(void)
162 {
163         struct pci_dev *dev = NULL;
164         for_each_pci_dev(dev) {
165                 mpc7448_hpc2_fixup_irq(dev);
166                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
167         }
168 }
169
170 static void __init mpc7448_hpc2_setup_arch(void)
171 {
172         struct device_node *cpu;
173         struct device_node *np;
174         if (ppc_md.progress)
175                 ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
176
177         cpu = of_find_node_by_type(NULL, "cpu");
178         if (cpu != 0) {
179                 unsigned int *fp;
180
181                 fp = (int *)get_property(cpu, "clock-frequency", NULL);
182                 if (fp != 0)
183                         loops_per_jiffy = *fp / HZ;
184                 else
185                         loops_per_jiffy = 50000000 / HZ;
186                 of_node_put(cpu);
187         }
188         tsi108_csr_vir_base = get_vir_csrbase();
189
190 #ifdef  CONFIG_ROOT_NFS
191         ROOT_DEV = Root_NFS;
192 #else
193         ROOT_DEV = Root_HDA1;
194 #endif
195
196 #ifdef CONFIG_BLK_DEV_INITRD
197         ROOT_DEV = Root_RAM0;
198 #endif
199
200         /* setup PCI host bridge */
201 #ifdef CONFIG_PCI
202         for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
203                 tsi108_setup_pci(np);
204
205         ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
206         if (ppc_md.progress)
207                 ppc_md.progress("tsi108: resources set", 0x100);
208 #endif
209
210         printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n");
211         printk(KERN_INFO
212                "Jointly ported by Freescale and Tundra Semiconductor\n");
213         printk(KERN_INFO
214                "Enabling L2 cache then enabling the HID0 prefetch engine.\n");
215 }
216
217 /*
218  * Interrupt setup and service.  Interrrupts on the mpc7448_hpc2 come
219  * from the four external INT pins, PCI interrupts are routed via
220  * PCI interrupt control registers, it generates internal IRQ23
221  *
222  * Interrupt routing on the Taiga Board:
223  * TSI108:PB_INT[0] -> CPU0:INT#
224  * TSI108:PB_INT[1] -> CPU0:MCP#
225  * TSI108:PB_INT[2] -> N/C
226  * TSI108:PB_INT[3] -> N/C
227  */
228 static void __init mpc7448_hpc2_init_IRQ(void)
229 {
230         struct mpic *mpic;
231         phys_addr_t mpic_paddr = 0;
232         struct device_node *tsi_pic;
233
234         tsi_pic = of_find_node_by_type(NULL, "open-pic");
235         if (tsi_pic) {
236                 unsigned int size;
237                 void *prop = get_property(tsi_pic, "reg", &size);
238                 mpic_paddr = of_translate_address(tsi_pic, prop);
239         }
240
241         if (mpic_paddr == 0) {
242                 printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
243                 return;
244         }
245
246         DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
247             (u32) mpic_paddr);
248
249         mpic = mpic_alloc(mpic_paddr,
250                         MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
251                         MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
252                         0, /* num_sources used */
253                         TSI108_IRQ_BASE,
254                         0, /* num_sources used */
255                         NR_IRQS - 4 /* XXXX */,
256                         mpc7448_hpc2_pic_initsenses,
257                         sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
258
259         BUG_ON(mpic == NULL); /* XXXX */
260
261         mpic_init(mpic);
262         mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
263         tsi108_pci_int_init();
264
265         /* Configure MPIC outputs to CPU0 */
266         tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
267 }
268
269 void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
270 {
271         seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
272         seq_printf(m, "machine\t\t: MPC7448hpc2\n");
273 }
274
275 void mpc7448_hpc2_restart(char *cmd)
276 {
277         local_irq_disable();
278
279         /* Set exception prefix high - to the firmware */
280         _nmask_and_or_msr(0, MSR_IP);
281
282         for (;;) ;              /* Spin until reset happens */
283 }
284
285 void mpc7448_hpc2_power_off(void)
286 {
287         local_irq_disable();
288         for (;;) ;              /* No way to shut power off with software */
289 }
290
291 void mpc7448_hpc2_halt(void)
292 {
293         mpc7448_hpc2_power_off();
294 }
295
296 /*
297  * Called very early, device-tree isn't unflattened
298  */
299 static int __init mpc7448_hpc2_probe(void)
300 {
301         unsigned long root = of_get_flat_dt_root();
302
303         if (!of_flat_dt_is_compatible(root, "mpc74xx"))
304                 return 0;
305         return 1;
306 }
307
308 static int mpc7448_machine_check_exception(struct pt_regs *regs)
309 {
310         extern void tsi108_clear_pci_cfg_error(void);
311         const struct exception_table_entry *entry;
312
313         /* Are we prepared to handle this fault */
314         if ((entry = search_exception_tables(regs->nip)) != NULL) {
315                 tsi108_clear_pci_cfg_error();
316                 regs->msr |= MSR_RI;
317                 regs->nip = entry->fixup;
318                 return 1;
319         }
320         return 0;
321
322 }
323 define_machine(mpc7448_hpc2){
324         .name                   = "MPC7448 HPC2",
325         .probe                  = mpc7448_hpc2_probe,
326         .setup_arch             = mpc7448_hpc2_setup_arch,
327         .init_IRQ               = mpc7448_hpc2_init_IRQ,
328         .show_cpuinfo           = mpc7448_hpc2_show_cpuinfo,
329         .get_irq                = mpic_get_irq,
330         .pcibios_fixup          = mpc7448_hpc2_pcibios_fixup,
331         .restart                = mpc7448_hpc2_restart,
332         .calibrate_decr         = generic_calibrate_decr,
333         .machine_check_exception= mpc7448_machine_check_exception,
334         .progress               = udbg_progress,
335 };