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