Commit | Line | Data |
---|---|---|
9724b86f SM |
1 | /* |
2 | * Efika 5K2 platform code | |
3 | * Some code really inspired from the lite5200b platform. | |
4 | * | |
5 | * Copyright (C) 2006 bplan GmbH | |
6 | * | |
7 | * This file is licensed under the terms of the GNU General Public License | |
8 | * version 2. This program is licensed "as is" without any warranty of any | |
9 | * kind, whether express or implied. | |
10 | */ | |
11 | ||
12 | #include <linux/errno.h> | |
13 | #include <linux/kernel.h> | |
14 | #include <linux/slab.h> | |
15 | #include <linux/reboot.h> | |
16 | #include <linux/init.h> | |
17 | #include <linux/utsrelease.h> | |
18 | #include <linux/seq_file.h> | |
19 | #include <linux/string.h> | |
20 | #include <linux/root_dev.h> | |
21 | #include <linux/initrd.h> | |
22 | #include <linux/timer.h> | |
23 | #include <linux/pci.h> | |
24 | ||
25 | #include <asm/io.h> | |
26 | #include <asm/irq.h> | |
27 | #include <asm/sections.h> | |
28 | #include <asm/pci-bridge.h> | |
29 | #include <asm/pgtable.h> | |
30 | #include <asm/prom.h> | |
31 | #include <asm/time.h> | |
32 | #include <asm/machdep.h> | |
33 | #include <asm/rtas.h> | |
34 | #include <asm/of_device.h> | |
35 | #include <asm/of_platform.h> | |
36 | #include <asm/mpc52xx.h> | |
37 | ||
38 | ||
39 | #define EFIKA_PLATFORM_NAME "Efika" | |
40 | ||
41 | ||
42 | /* ------------------------------------------------------------------------ */ | |
43 | /* PCI accesses thru RTAS */ | |
44 | /* ------------------------------------------------------------------------ */ | |
45 | ||
46 | #ifdef CONFIG_PCI | |
47 | ||
48 | /* | |
49 | * Access functions for PCI config space using RTAS calls. | |
50 | */ | |
51 | static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |
52 | int len, u32 * val) | |
53 | { | |
54 | struct pci_controller *hose = bus->sysdata; | |
55 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | |
56 | | (((bus->number - hose->first_busno) & 0xff) << 16) | |
5516b540 | 57 | | (hose->global_number << 24); |
9724b86f SM |
58 | int ret = -1; |
59 | int rval; | |
60 | ||
61 | rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len); | |
62 | *val = ret; | |
63 | return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | |
64 | } | |
65 | ||
66 | static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, | |
67 | int offset, int len, u32 val) | |
68 | { | |
69 | struct pci_controller *hose = bus->sysdata; | |
70 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | |
71 | | (((bus->number - hose->first_busno) & 0xff) << 16) | |
5516b540 | 72 | | (hose->global_number << 24); |
9724b86f SM |
73 | int rval; |
74 | ||
75 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, | |
76 | addr, len, val); | |
77 | return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | |
78 | } | |
79 | ||
80 | static struct pci_ops rtas_pci_ops = { | |
81 | rtas_read_config, | |
82 | rtas_write_config | |
83 | }; | |
84 | ||
85 | ||
86 | void __init efika_pcisetup(void) | |
87 | { | |
88 | const int *bus_range; | |
89 | int len; | |
90 | struct pci_controller *hose; | |
91 | struct device_node *root; | |
92 | struct device_node *pcictrl; | |
93 | ||
94 | root = of_find_node_by_path("/"); | |
95 | if (root == NULL) { | |
96 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | |
97 | ": Unable to find the root node\n"); | |
98 | return; | |
99 | } | |
100 | ||
101 | for (pcictrl = NULL;;) { | |
102 | pcictrl = of_get_next_child(root, pcictrl); | |
103 | if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0)) | |
104 | break; | |
105 | } | |
106 | ||
107 | of_node_put(root); | |
108 | ||
109 | if (pcictrl == NULL) { | |
110 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | |
111 | ": Unable to find the PCI bridge node\n"); | |
112 | return; | |
113 | } | |
114 | ||
e2eb6392 | 115 | bus_range = of_get_property(pcictrl, "bus-range", &len); |
9724b86f SM |
116 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
117 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | |
118 | ": Can't get bus-range for %s\n", pcictrl->full_name); | |
119 | return; | |
120 | } | |
121 | ||
122 | if (bus_range[1] == bus_range[0]) | |
123 | printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d", | |
124 | bus_range[0]); | |
125 | else | |
126 | printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d", | |
127 | bus_range[0], bus_range[1]); | |
128 | printk(" controlled by %s\n", pcictrl->full_name); | |
129 | printk("\n"); | |
130 | ||
dbf8471f | 131 | hose = pcibios_alloc_controller(of_node_get(pcictrl)); |
9724b86f SM |
132 | if (!hose) { |
133 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | |
134 | ": Can't allocate PCI controller structure for %s\n", | |
135 | pcictrl->full_name); | |
136 | return; | |
137 | } | |
138 | ||
9724b86f SM |
139 | hose->first_busno = bus_range[0]; |
140 | hose->last_busno = bus_range[1]; | |
141 | hose->ops = &rtas_pci_ops; | |
142 | ||
143 | pci_process_bridge_OF_ranges(hose, pcictrl, 0); | |
144 | } | |
145 | ||
146 | #else | |
147 | void __init efika_pcisetup(void) | |
148 | {} | |
149 | #endif | |
150 | ||
151 | ||
152 | ||
153 | /* ------------------------------------------------------------------------ */ | |
154 | /* Platform setup */ | |
155 | /* ------------------------------------------------------------------------ */ | |
156 | ||
157 | static void efika_show_cpuinfo(struct seq_file *m) | |
158 | { | |
159 | struct device_node *root; | |
e2eb6392 SR |
160 | const char *revision; |
161 | const char *codegendescription; | |
162 | const char *codegenvendor; | |
9724b86f SM |
163 | |
164 | root = of_find_node_by_path("/"); | |
165 | if (!root) | |
166 | return; | |
167 | ||
e2eb6392 SR |
168 | revision = of_get_property(root, "revision", NULL); |
169 | codegendescription = of_get_property(root, "CODEGEN,description", NULL); | |
170 | codegenvendor = of_get_property(root, "CODEGEN,vendor", NULL); | |
9724b86f SM |
171 | |
172 | if (codegendescription) | |
173 | seq_printf(m, "machine\t\t: %s\n", codegendescription); | |
174 | else | |
175 | seq_printf(m, "machine\t\t: Efika\n"); | |
176 | ||
177 | if (revision) | |
178 | seq_printf(m, "revision\t: %s\n", revision); | |
179 | ||
180 | if (codegenvendor) | |
181 | seq_printf(m, "vendor\t\t: %s\n", codegenvendor); | |
182 | ||
183 | of_node_put(root); | |
184 | } | |
185 | ||
2e1ee1f7 DP |
186 | #ifdef CONFIG_PM |
187 | static void efika_suspend_prepare(void __iomem *mbar) | |
188 | { | |
189 | u8 pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */ | |
190 | u8 level = 1; /* wakeup on high level */ | |
191 | /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */ | |
192 | mpc52xx_set_wakeup_gpio(pin, level); | |
193 | } | |
194 | #endif | |
195 | ||
9724b86f SM |
196 | static void __init efika_setup_arch(void) |
197 | { | |
198 | rtas_initialize(); | |
199 | ||
200 | #ifdef CONFIG_BLK_DEV_INITRD | |
201 | initrd_below_start_ok = 1; | |
202 | ||
203 | if (initrd_start) | |
204 | ROOT_DEV = Root_RAM0; | |
205 | else | |
206 | #endif | |
207 | ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ | |
208 | ||
209 | efika_pcisetup(); | |
210 | ||
2e1ee1f7 DP |
211 | #ifdef CONFIG_PM |
212 | mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare; | |
213 | mpc52xx_pm_init(); | |
214 | #endif | |
215 | ||
9724b86f SM |
216 | if (ppc_md.progress) |
217 | ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0); | |
218 | } | |
219 | ||
220 | static int __init efika_probe(void) | |
221 | { | |
222 | char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), | |
223 | "model", NULL); | |
224 | ||
225 | if (model == NULL) | |
226 | return 0; | |
227 | if (strcmp(model, "EFIKA5K2")) | |
228 | return 0; | |
229 | ||
230 | ISA_DMA_THRESHOLD = ~0L; | |
231 | DMA_MODE_READ = 0x44; | |
232 | DMA_MODE_WRITE = 0x48; | |
233 | ||
234 | return 1; | |
235 | } | |
236 | ||
237 | define_machine(efika) | |
238 | { | |
239 | .name = EFIKA_PLATFORM_NAME, | |
240 | .probe = efika_probe, | |
241 | .setup_arch = efika_setup_arch, | |
242 | .init = mpc52xx_declare_of_platform_devices, | |
243 | .show_cpuinfo = efika_show_cpuinfo, | |
244 | .init_IRQ = mpc52xx_init_irq, | |
245 | .get_irq = mpc52xx_get_irq, | |
246 | .restart = rtas_restart, | |
247 | .power_off = rtas_power_off, | |
248 | .halt = rtas_halt, | |
249 | .set_rtc_time = rtas_set_rtc_time, | |
250 | .get_rtc_time = rtas_get_rtc_time, | |
251 | .progress = rtas_progress, | |
252 | .get_boot_time = rtas_get_boot_time, | |
253 | .calibrate_decr = generic_calibrate_decr, | |
d6658408 | 254 | #ifdef CONFIG_PCI |
9724b86f | 255 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
d6658408 | 256 | #endif |
9724b86f SM |
257 | }; |
258 |