powerpc: Add PCI support for 8540 ADS to powerpc tree
[linux-2.6.git] / arch / powerpc / platforms / 85xx / mpc85xx_ads.c
1 /*
2  * MPC85xx setup and early boot code plus other random bits.
3  *
4  * Maintained by Kumar Gala (see MAINTAINERS for contact information)
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/config.h>
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 #include <linux/root_dev.h>
22
23 #include <asm/system.h>
24 #include <asm/time.h>
25 #include <asm/machdep.h>
26 #include <asm/pci-bridge.h>
27 #include <asm/mpc85xx.h>
28 #include <asm/prom.h>
29 #include <asm/mpic.h>
30 #include <mm/mmu_decl.h>
31 #include <asm/udbg.h>
32
33 #include <sysdev/fsl_soc.h>
34 #include "mpc85xx.h"
35
36 #ifndef CONFIG_PCI
37 unsigned long isa_io_base = 0;
38 unsigned long isa_mem_base = 0;
39 #endif
40
41 /*
42  * Internal interrupts are all Level Sensitive, and Positive Polarity
43  *
44  * Note:  Likely, this table and the following function should be
45  *        obtained and derived from the OF Device Tree.
46  */
47 static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
48         MPC85XX_INTERNAL_IRQ_SENSES,
49         0x0,                    /* External  0: */
50 #if defined(CONFIG_PCI)
51         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* Ext 1: PCI slot 0 */
52         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* Ext 2: PCI slot 1 */
53         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* Ext 3: PCI slot 2 */
54         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* Ext 4: PCI slot 3 */
55 #else
56         0x0,                    /* External  1: */
57         0x0,                    /* External  2: */
58         0x0,                    /* External  3: */
59         0x0,                    /* External  4: */
60 #endif
61         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 5: PHY */
62         0x0,                    /* External  6: */
63         (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 7: PHY */
64         0x0,                    /* External  8: */
65         0x0,                    /* External  9: */
66         0x0,                    /* External 10: */
67         0x0,                    /* External 11: */
68 };
69
70 #ifdef CONFIG_PCI
71 /*
72  * interrupt routing
73  */
74
75 int
76 mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
77 {
78         static char pci_irq_table[][4] =
79             /*
80              * This is little evil, but works around the fact
81              * that revA boards have IDSEL starting at 18
82              * and others boards (older) start at 12
83              *
84              *      PCI IDSEL/INTPIN->INTLINE
85              *       A      B      C      D
86              */
87         {
88                 {PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 2 */
89                 {PIRQD, PIRQA, PIRQB, PIRQC},
90                 {PIRQC, PIRQD, PIRQA, PIRQB},
91                 {PIRQB, PIRQC, PIRQD, PIRQA},   /* IDSEL 5 */
92                 {0, 0, 0, 0},   /* -- */
93                 {0, 0, 0, 0},   /* -- */
94                 {0, 0, 0, 0},   /* -- */
95                 {0, 0, 0, 0},   /* -- */
96                 {0, 0, 0, 0},   /* -- */
97                 {0, 0, 0, 0},   /* -- */
98                 {PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 12 */
99                 {PIRQD, PIRQA, PIRQB, PIRQC},
100                 {PIRQC, PIRQD, PIRQA, PIRQB},
101                 {PIRQB, PIRQC, PIRQD, PIRQA},   /* IDSEL 15 */
102                 {0, 0, 0, 0},   /* -- */
103                 {0, 0, 0, 0},   /* -- */
104                 {PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 18 */
105                 {PIRQD, PIRQA, PIRQB, PIRQC},
106                 {PIRQC, PIRQD, PIRQA, PIRQB},
107                 {PIRQB, PIRQC, PIRQD, PIRQA},   /* IDSEL 21 */
108         };
109
110         const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4;
111         return PCI_IRQ_TABLE_LOOKUP;
112 }
113
114 int
115 mpc85xx_exclude_device(u_char bus, u_char devfn)
116 {
117         if (bus == 0 && PCI_SLOT(devfn) == 0)
118                 return PCIBIOS_DEVICE_NOT_FOUND;
119         else
120                 return PCIBIOS_SUCCESSFUL;
121 }
122
123 #endif /* CONFIG_PCI */
124
125
126 void __init mpc85xx_ads_pic_init(void)
127 {
128         struct mpic *mpic1;
129         phys_addr_t OpenPIC_PAddr;
130
131         /* Determine the Physical Address of the OpenPIC regs */
132         OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET;
133
134         mpic1 = mpic_alloc(OpenPIC_PAddr,
135                            MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
136                            4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250,
137                            mpc85xx_ads_openpic_initsenses,
138                            sizeof(mpc85xx_ads_openpic_initsenses),
139                            " OpenPIC  ");
140         BUG_ON(mpic1 == NULL);
141         mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200);
142         mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280);
143         mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300);
144         mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380);
145         mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400);
146         mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480);
147         mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500);
148         mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580);
149
150         /* dummy mappings to get to 48 */
151         mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600);
152         mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680);
153         mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700);
154         mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780);
155
156         /* External ints */
157         mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000);
158         mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080);
159         mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100);
160         mpic_init(mpic1);
161 }
162
163 /*
164  * Setup the architecture
165  */
166 static void __init mpc85xx_ads_setup_arch(void)
167 {
168         struct device_node *cpu;
169         struct device_node *np;
170
171         if (ppc_md.progress)
172                 ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
173
174         cpu = of_find_node_by_type(NULL, "cpu");
175         if (cpu != 0) {
176                 unsigned int *fp;
177
178                 fp = (int *)get_property(cpu, "clock-frequency", NULL);
179                 if (fp != 0)
180                         loops_per_jiffy = *fp / HZ;
181                 else
182                         loops_per_jiffy = 50000000 / HZ;
183                 of_node_put(cpu);
184         }
185
186 #ifdef CONFIG_PCI
187         for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
188                 add_bridge(np);
189
190         ppc_md.pci_swizzle = common_swizzle;
191         ppc_md.pci_map_irq = mpc85xx_map_irq;
192         ppc_md.pci_exclude_device = mpc85xx_exclude_device;
193 #endif
194
195 #ifdef  CONFIG_ROOT_NFS
196         ROOT_DEV = Root_NFS;
197 #else
198         ROOT_DEV = Root_HDA1;
199 #endif
200 }
201
202 void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
203 {
204         uint pvid, svid, phid1;
205         uint memsize = total_memory;
206
207         pvid = mfspr(SPRN_PVR);
208         svid = mfspr(SPRN_SVR);
209
210         seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
211         seq_printf(m, "Machine\t\t: mpc85xx\n");
212         seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
213         seq_printf(m, "SVR\t\t: 0x%x\n", svid);
214
215         /* Display cpu Pll setting */
216         phid1 = mfspr(SPRN_HID1);
217         seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
218
219         /* Display the amount of memory */
220         seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
221 }
222
223 void __init platform_init(void)
224 {
225         ppc_md.setup_arch = mpc85xx_ads_setup_arch;
226         ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
227
228         ppc_md.init_IRQ = mpc85xx_ads_pic_init;
229         ppc_md.get_irq = mpic_get_irq;
230
231         ppc_md.restart = mpc85xx_restart;
232         ppc_md.power_off = NULL;
233         ppc_md.halt = NULL;
234
235         ppc_md.time_init = NULL;
236         ppc_md.set_rtc_time = NULL;
237         ppc_md.get_rtc_time = NULL;
238         ppc_md.calibrate_decr = generic_calibrate_decr;
239
240         ppc_md.progress = udbg_progress;
241
242         if (ppc_md.progress)
243                 ppc_md.progress("mpc85xx_ads platform_init(): exit", 0);
244 }