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 SM |
12 | #include <linux/init.h> |
13 | #include <linux/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); | |
102 | return; | |
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 | ||
dbf8471f | 114 | hose = pcibios_alloc_controller(of_node_get(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); | |
119 | return; | |
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); | |
127 | } | |
128 | ||
129 | #else | |
d3e0e028 | 130 | static void __init efika_pcisetup(void) |
9724b86f SM |
131 | {} |
132 | #endif | |
133 | ||
134 | ||
135 | ||
136 | /* ------------------------------------------------------------------------ */ | |
137 | /* Platform setup */ | |
138 | /* ------------------------------------------------------------------------ */ | |
139 | ||
140 | static void efika_show_cpuinfo(struct seq_file *m) | |
141 | { | |
142 | struct device_node *root; | |
e2eb6392 SR |
143 | const char *revision; |
144 | const char *codegendescription; | |
145 | const char *codegenvendor; | |
9724b86f SM |
146 | |
147 | root = of_find_node_by_path("/"); | |
148 | if (!root) | |
149 | return; | |
150 | ||
e2eb6392 SR |
151 | revision = of_get_property(root, "revision", NULL); |
152 | codegendescription = of_get_property(root, "CODEGEN,description", NULL); | |
153 | codegenvendor = of_get_property(root, "CODEGEN,vendor", NULL); | |
9724b86f SM |
154 | |
155 | if (codegendescription) | |
156 | seq_printf(m, "machine\t\t: %s\n", codegendescription); | |
157 | else | |
158 | seq_printf(m, "machine\t\t: Efika\n"); | |
159 | ||
160 | if (revision) | |
161 | seq_printf(m, "revision\t: %s\n", revision); | |
162 | ||
163 | if (codegenvendor) | |
164 | seq_printf(m, "vendor\t\t: %s\n", codegenvendor); | |
165 | ||
166 | of_node_put(root); | |
167 | } | |
168 | ||
2e1ee1f7 DP |
169 | #ifdef CONFIG_PM |
170 | static void efika_suspend_prepare(void __iomem *mbar) | |
171 | { | |
172 | u8 pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */ | |
173 | u8 level = 1; /* wakeup on high level */ | |
174 | /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */ | |
175 | mpc52xx_set_wakeup_gpio(pin, level); | |
176 | } | |
177 | #endif | |
178 | ||
9724b86f SM |
179 | static void __init efika_setup_arch(void) |
180 | { | |
181 | rtas_initialize(); | |
182 | ||
c8004a28 GL |
183 | /* Map important registers from the internal memory map */ |
184 | mpc52xx_map_common_devices(); | |
185 | ||
9724b86f SM |
186 | efika_pcisetup(); |
187 | ||
2e1ee1f7 DP |
188 | #ifdef CONFIG_PM |
189 | mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare; | |
190 | mpc52xx_pm_init(); | |
191 | #endif | |
192 | ||
9724b86f SM |
193 | if (ppc_md.progress) |
194 | ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0); | |
195 | } | |
196 | ||
197 | static int __init efika_probe(void) | |
198 | { | |
199 | char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), | |
200 | "model", NULL); | |
201 | ||
202 | if (model == NULL) | |
203 | return 0; | |
204 | if (strcmp(model, "EFIKA5K2")) | |
205 | return 0; | |
206 | ||
207 | ISA_DMA_THRESHOLD = ~0L; | |
208 | DMA_MODE_READ = 0x44; | |
209 | DMA_MODE_WRITE = 0x48; | |
210 | ||
211 | return 1; | |
212 | } | |
213 | ||
214 | define_machine(efika) | |
215 | { | |
216 | .name = EFIKA_PLATFORM_NAME, | |
217 | .probe = efika_probe, | |
218 | .setup_arch = efika_setup_arch, | |
219 | .init = mpc52xx_declare_of_platform_devices, | |
220 | .show_cpuinfo = efika_show_cpuinfo, | |
221 | .init_IRQ = mpc52xx_init_irq, | |
222 | .get_irq = mpc52xx_get_irq, | |
223 | .restart = rtas_restart, | |
224 | .power_off = rtas_power_off, | |
225 | .halt = rtas_halt, | |
226 | .set_rtc_time = rtas_set_rtc_time, | |
227 | .get_rtc_time = rtas_get_rtc_time, | |
228 | .progress = rtas_progress, | |
229 | .get_boot_time = rtas_get_boot_time, | |
230 | .calibrate_decr = generic_calibrate_decr, | |
d6658408 | 231 | #ifdef CONFIG_PCI |
9724b86f | 232 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
d6658408 | 233 | #endif |
9724b86f SM |
234 | }; |
235 |