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/init.h> |
13 | #include <generated/utsrelease.h> |
14 | #include <linux/pci.h> |
15 | #include <linux/of.h> |
16 | #include <asm/dma.h> |
17 | #include <asm/time.h> |
18 | #include <asm/machdep.h> |
19 | #include <asm/rtas.h> |
20 | #include <asm/mpc52xx.h> |
21 | |
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 | { |
37 | struct pci_controller *hose = pci_bus_to_host(bus); |
38 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
39 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
40 | | (hose->global_number << 24); |
41 | int ret = -1; |
42 | int rval; |
43 | |
44 | rval = rtas_call(rtas_function_token(RTAS_FN_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 | { |
52 | struct pci_controller *hose = pci_bus_to_host(bus); |
53 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
54 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
55 | | (hose->global_number << 24); |
56 | int rval; |
57 | |
58 | rval = rtas_call(rtas_function_token(RTAS_FN_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 = { |
64 | .read = rtas_read_config, |
65 | .write = rtas_write_config, |
66 | }; |
67 | |
68 | |
69 | static void __init efika_pcisetup(void) |
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(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_each_child_of_node(root, pcictrl) |
85 | if (of_node_name_eq(np: pcictrl, name: "pci" )) |
86 | break; |
87 | |
88 | of_node_put(node: root); |
89 | |
90 | if (pcictrl == NULL) { |
91 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
92 | ": Unable to find the PCI bridge node\n" ); |
93 | return; |
94 | } |
95 | |
96 | bus_range = of_get_property(node: pcictrl, name: "bus-range" , lenp: &len); |
97 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
98 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
99 | ": Can't get bus-range for %pOF\n" , pcictrl); |
100 | goto out_put; |
101 | } |
102 | |
103 | if (bus_range[1] == bus_range[0]) |
104 | printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d" , |
105 | bus_range[0]); |
106 | else |
107 | printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d" , |
108 | bus_range[0], bus_range[1]); |
109 | printk(" controlled by %pOF\n" , pcictrl); |
110 | printk("\n" ); |
111 | |
112 | hose = pcibios_alloc_controller(pcictrl); |
113 | if (!hose) { |
114 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
115 | ": Can't allocate PCI controller structure for %pOF\n" , |
116 | pcictrl); |
117 | goto out_put; |
118 | } |
119 | |
120 | hose->first_busno = bus_range[0]; |
121 | hose->last_busno = bus_range[1]; |
122 | hose->ops = &rtas_pci_ops; |
123 | |
124 | pci_process_bridge_OF_ranges(hose, pcictrl, 0); |
125 | return; |
126 | out_put: |
127 | of_node_put(node: pcictrl); |
128 | } |
129 | |
130 | #else |
131 | static void __init efika_pcisetup(void) |
132 | {} |
133 | #endif |
134 | |
135 | |
136 | |
137 | /* ------------------------------------------------------------------------ */ |
138 | /* Platform setup */ |
139 | /* ------------------------------------------------------------------------ */ |
140 | |
141 | static void efika_show_cpuinfo(struct seq_file *m) |
142 | { |
143 | struct device_node *root; |
144 | const char *revision; |
145 | const char *codegendescription; |
146 | const char *codegenvendor; |
147 | |
148 | root = of_find_node_by_path(path: "/" ); |
149 | if (!root) |
150 | return; |
151 | |
152 | revision = of_get_property(node: root, name: "revision" , NULL); |
153 | codegendescription = of_get_property(node: root, name: "CODEGEN,description" , NULL); |
154 | codegenvendor = of_get_property(node: root, name: "CODEGEN,vendor" , NULL); |
155 | |
156 | if (codegendescription) |
157 | seq_printf(m, "machine\t\t: %s\n" , codegendescription); |
158 | else |
159 | seq_printf(m, "machine\t\t: Efika\n" ); |
160 | |
161 | if (revision) |
162 | seq_printf(m, "revision\t: %s\n" , revision); |
163 | |
164 | if (codegenvendor) |
165 | seq_printf(m, "vendor\t\t: %s\n" , codegenvendor); |
166 | |
167 | of_node_put(node: root); |
168 | } |
169 | |
170 | #ifdef CONFIG_PM |
171 | static void efika_suspend_prepare(void __iomem *mbar) |
172 | { |
173 | u8 pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */ |
174 | u8 level = 1; /* wakeup on high level */ |
175 | /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */ |
176 | mpc52xx_set_wakeup_gpio(pin, level); |
177 | } |
178 | #endif |
179 | |
180 | static void __init efika_setup_arch(void) |
181 | { |
182 | rtas_initialize(); |
183 | |
184 | /* Map important registers from the internal memory map */ |
185 | mpc52xx_map_common_devices(); |
186 | |
187 | #ifdef CONFIG_PM |
188 | mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare; |
189 | mpc52xx_pm_init(); |
190 | #endif |
191 | |
192 | if (ppc_md.progress) |
193 | ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n" , 0x0); |
194 | } |
195 | |
196 | static int __init efika_probe(void) |
197 | { |
198 | struct device_node *root = of_find_node_by_path(path: "/" ); |
199 | const char *model = of_get_property(node: root, name: "model" , NULL); |
200 | |
201 | of_node_put(node: root); |
202 | if (model == NULL) |
203 | return 0; |
204 | if (strcmp(model, "EFIKA5K2" )) |
205 | return 0; |
206 | |
207 | DMA_MODE_READ = 0x44; |
208 | DMA_MODE_WRITE = 0x48; |
209 | |
210 | pm_power_off = rtas_power_off; |
211 | |
212 | return 1; |
213 | } |
214 | |
215 | define_machine(efika) |
216 | { |
217 | .name = EFIKA_PLATFORM_NAME, |
218 | .probe = efika_probe, |
219 | .setup_arch = efika_setup_arch, |
220 | .discover_phbs = efika_pcisetup, |
221 | .init = mpc52xx_declare_of_platform_devices, |
222 | .show_cpuinfo = efika_show_cpuinfo, |
223 | .init_IRQ = mpc52xx_init_irq, |
224 | .get_irq = mpc52xx_get_irq, |
225 | .restart = rtas_restart, |
226 | .halt = rtas_halt, |
227 | .set_rtc_time = rtas_set_rtc_time, |
228 | .get_rtc_time = rtas_get_rtc_time, |
229 | .progress = rtas_progress, |
230 | .get_boot_time = rtas_get_boot_time, |
231 | #ifdef CONFIG_PCI |
232 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
233 | #endif |
234 | }; |
235 | |
236 | |