diff options
Diffstat (limited to 'arch/powerpc/platforms/celleb')
-rw-r--r-- | arch/powerpc/platforms/celleb/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/Makefile | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/beat.c | 106 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/beat.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/beat_syscall.h | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/beat_wrapper.h | 68 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/htab.c | 152 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/interrupt.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/io-workarounds.c | 279 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/pci.c | 98 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/pci.h | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/scc.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/scc_epci.c | 88 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/scc_sio.c | 56 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/setup.c | 27 |
15 files changed, 773 insertions, 133 deletions
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig index 2db1e293433e..04748d410fc9 100644 --- a/arch/powerpc/platforms/celleb/Kconfig +++ b/arch/powerpc/platforms/celleb/Kconfig | |||
@@ -2,6 +2,7 @@ config PPC_CELLEB | |||
2 | bool "Toshiba's Cell Reference Set 'Celleb' Architecture" | 2 | bool "Toshiba's Cell Reference Set 'Celleb' Architecture" |
3 | depends on PPC_MULTIPLATFORM && PPC64 | 3 | depends on PPC_MULTIPLATFORM && PPC64 |
4 | select PPC_CELL | 4 | select PPC_CELL |
5 | select PPC_INDIRECT_IO | ||
5 | select PPC_OF_PLATFORM_PCI | 6 | select PPC_OF_PLATFORM_PCI |
6 | select HAS_TXX9_SERIAL | 7 | select HAS_TXX9_SERIAL |
7 | select PPC_UDBG_BEAT | 8 | select PPC_UDBG_BEAT |
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile index 5240046d8671..889d43f715ea 100644 --- a/arch/powerpc/platforms/celleb/Makefile +++ b/arch/powerpc/platforms/celleb/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-y += interrupt.o iommu.o setup.o \ | 1 | obj-y += interrupt.o iommu.o setup.o \ |
2 | htab.o beat.o pci.o \ | 2 | htab.o beat.o hvCall.o pci.o \ |
3 | scc_epci.o scc_uhc.o hvCall.o | 3 | scc_epci.o scc_uhc.o \ |
4 | io-workarounds.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_SMP) += smp.o | 6 | obj-$(CONFIG_SMP) += smp.o |
6 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o | 7 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o |
diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/celleb/beat.c index 99341ce8a697..93ebb7d85120 100644 --- a/arch/powerpc/platforms/celleb/beat.c +++ b/arch/powerpc/platforms/celleb/beat.c | |||
@@ -22,16 +22,24 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/irqreturn.h> | ||
27 | #include <linux/reboot.h> | ||
25 | 28 | ||
26 | #include <asm/hvconsole.h> | 29 | #include <asm/hvconsole.h> |
27 | #include <asm/time.h> | 30 | #include <asm/time.h> |
31 | #include <asm/machdep.h> | ||
32 | #include <asm/firmware.h> | ||
28 | 33 | ||
29 | #include "beat_wrapper.h" | 34 | #include "beat_wrapper.h" |
30 | #include "beat.h" | 35 | #include "beat.h" |
36 | #include "interrupt.h" | ||
37 | |||
38 | static int beat_pm_poweroff_flag; | ||
31 | 39 | ||
32 | void beat_restart(char *cmd) | 40 | void beat_restart(char *cmd) |
33 | { | 41 | { |
34 | beat_shutdown_logical_partition(1); | 42 | beat_shutdown_logical_partition(!beat_pm_poweroff_flag); |
35 | } | 43 | } |
36 | 44 | ||
37 | void beat_power_off(void) | 45 | void beat_power_off(void) |
@@ -158,6 +166,102 @@ int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2) | |||
158 | return beat_put_characters_to_console(vterm, len, (u8*)db); | 166 | return beat_put_characters_to_console(vterm, len, (u8*)db); |
159 | } | 167 | } |
160 | 168 | ||
169 | void beat_power_save(void) | ||
170 | { | ||
171 | beat_pause(0); | ||
172 | } | ||
173 | |||
174 | #ifdef CONFIG_KEXEC | ||
175 | void beat_kexec_cpu_down(int crash, int secondary) | ||
176 | { | ||
177 | beatic_deinit_IRQ(); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | static irqreturn_t beat_power_event(int virq, void *arg) | ||
182 | { | ||
183 | printk(KERN_DEBUG "Beat: power button pressed\n"); | ||
184 | beat_pm_poweroff_flag = 1; | ||
185 | ctrl_alt_del(); | ||
186 | return IRQ_HANDLED; | ||
187 | } | ||
188 | |||
189 | static irqreturn_t beat_reset_event(int virq, void *arg) | ||
190 | { | ||
191 | printk(KERN_DEBUG "Beat: reset button pressed\n"); | ||
192 | beat_pm_poweroff_flag = 0; | ||
193 | ctrl_alt_del(); | ||
194 | return IRQ_HANDLED; | ||
195 | } | ||
196 | |||
197 | static struct beat_event_list { | ||
198 | const char *typecode; | ||
199 | irq_handler_t handler; | ||
200 | unsigned int virq; | ||
201 | } beat_event_list[] = { | ||
202 | { "power", beat_power_event, 0 }, | ||
203 | { "reset", beat_reset_event, 0 }, | ||
204 | }; | ||
205 | |||
206 | static int __init beat_register_event(void) | ||
207 | { | ||
208 | u64 path[4], data[2]; | ||
209 | int rc, i; | ||
210 | unsigned int virq; | ||
211 | |||
212 | for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) { | ||
213 | struct beat_event_list *ev = &beat_event_list[i]; | ||
214 | |||
215 | if (beat_construct_event_receive_port(data) != 0) { | ||
216 | printk(KERN_ERR "Beat: " | ||
217 | "cannot construct event receive port for %s\n", | ||
218 | ev->typecode); | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | virq = irq_create_mapping(NULL, data[0]); | ||
223 | if (virq == NO_IRQ) { | ||
224 | printk(KERN_ERR "Beat: failed to get virtual IRQ" | ||
225 | " for event receive port for %s\n", | ||
226 | ev->typecode); | ||
227 | beat_destruct_event_receive_port(data[0]); | ||
228 | return -EIO; | ||
229 | } | ||
230 | ev->virq = virq; | ||
231 | |||
232 | rc = request_irq(virq, ev->handler, IRQF_DISABLED, | ||
233 | ev->typecode, NULL); | ||
234 | if (rc != 0) { | ||
235 | printk(KERN_ERR "Beat: failed to request virtual IRQ" | ||
236 | " for event receive port for %s\n", | ||
237 | ev->typecode); | ||
238 | beat_destruct_event_receive_port(data[0]); | ||
239 | return rc; | ||
240 | } | ||
241 | |||
242 | path[0] = 0x1000000065780000ul; /* 1,ex */ | ||
243 | path[1] = 0x627574746f6e0000ul; /* button */ | ||
244 | path[2] = 0; | ||
245 | strncpy((char *)&path[2], ev->typecode, 8); | ||
246 | path[3] = 0; | ||
247 | data[1] = 0; | ||
248 | |||
249 | beat_create_repository_node(path, data); | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int __init beat_event_init(void) | ||
255 | { | ||
256 | if (!firmware_has_feature(FW_FEATURE_BEAT)) | ||
257 | return -EINVAL; | ||
258 | |||
259 | beat_pm_poweroff_flag = 0; | ||
260 | return beat_register_event(); | ||
261 | } | ||
262 | |||
263 | device_initcall(beat_event_init); | ||
264 | |||
161 | EXPORT_SYMBOL(beat_get_term_char); | 265 | EXPORT_SYMBOL(beat_get_term_char); |
162 | EXPORT_SYMBOL(beat_put_term_char); | 266 | EXPORT_SYMBOL(beat_put_term_char); |
163 | EXPORT_SYMBOL(beat_halt_code); | 267 | EXPORT_SYMBOL(beat_halt_code); |
diff --git a/arch/powerpc/platforms/celleb/beat.h b/arch/powerpc/platforms/celleb/beat.h index 2b16bf3bee89..b2e292df13ca 100644 --- a/arch/powerpc/platforms/celleb/beat.h +++ b/arch/powerpc/platforms/celleb/beat.h | |||
@@ -36,5 +36,7 @@ ssize_t beat_nvram_get_size(void); | |||
36 | ssize_t beat_nvram_read(char *, size_t, loff_t *); | 36 | ssize_t beat_nvram_read(char *, size_t, loff_t *); |
37 | ssize_t beat_nvram_write(char *, size_t, loff_t *); | 37 | ssize_t beat_nvram_write(char *, size_t, loff_t *); |
38 | int beat_set_xdabr(unsigned long); | 38 | int beat_set_xdabr(unsigned long); |
39 | void beat_power_save(void); | ||
40 | void beat_kexec_cpu_down(int, int); | ||
39 | 41 | ||
40 | #endif /* _CELLEB_BEAT_H */ | 42 | #endif /* _CELLEB_BEAT_H */ |
diff --git a/arch/powerpc/platforms/celleb/beat_syscall.h b/arch/powerpc/platforms/celleb/beat_syscall.h index 14e16974773f..8580dc7e1798 100644 --- a/arch/powerpc/platforms/celleb/beat_syscall.h +++ b/arch/powerpc/platforms/celleb/beat_syscall.h | |||
@@ -157,4 +157,8 @@ | |||
157 | #define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1) | 157 | #define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1) |
158 | #define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1) | 158 | #define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1) |
159 | #define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1) | 159 | #define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1) |
160 | #define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1) | ||
161 | #define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1) | ||
162 | #define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1) | ||
163 | #define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1) | ||
160 | #endif | 164 | #endif |
diff --git a/arch/powerpc/platforms/celleb/beat_wrapper.h b/arch/powerpc/platforms/celleb/beat_wrapper.h index 76ea0a6a9011..cbc1487df7de 100644 --- a/arch/powerpc/platforms/celleb/beat_wrapper.h +++ b/arch/powerpc/platforms/celleb/beat_wrapper.h | |||
@@ -98,6 +98,37 @@ static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot, | |||
98 | return ret; | 98 | return ret; |
99 | } | 99 | } |
100 | 100 | ||
101 | static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group, | ||
102 | u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot) | ||
103 | { | ||
104 | u64 dummy[1]; | ||
105 | s64 ret; | ||
106 | |||
107 | ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group, | ||
108 | hpte_v, hpte_r, mask_v, value_v); | ||
109 | *slot = dummy[0]; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group, | ||
114 | u64 va, u64 pss) | ||
115 | { | ||
116 | return beat_hcall_norets(HV_invalidate_htab_entry3, | ||
117 | htab_id, group, va, pss); | ||
118 | } | ||
119 | |||
120 | static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group, | ||
121 | u64 va, u64 pss, u64 ptel_mask, u64 ptel_value) | ||
122 | { | ||
123 | return beat_hcall_norets(HV_update_htab_permission3, | ||
124 | htab_id, group, va, pss, ptel_mask, ptel_value); | ||
125 | } | ||
126 | |||
127 | static inline s64 beat_clear_htab3(u64 htab_id) | ||
128 | { | ||
129 | return beat_hcall_norets(HV_clear_htab3, htab_id); | ||
130 | } | ||
131 | |||
101 | static inline void beat_shutdown_logical_partition(u64 code) | 132 | static inline void beat_shutdown_logical_partition(u64 code) |
102 | { | 133 | { |
103 | (void)beat_hcall_norets(HV_shutdown_logical_partition, code); | 134 | (void)beat_hcall_norets(HV_shutdown_logical_partition, code); |
@@ -217,4 +248,41 @@ static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr, | |||
217 | ioid, flags); | 248 | ioid, flags); |
218 | } | 249 | } |
219 | 250 | ||
251 | static inline s64 beat_construct_event_receive_port(u64 *port) | ||
252 | { | ||
253 | u64 dummy[1]; | ||
254 | s64 ret; | ||
255 | |||
256 | ret = beat_hcall1(HV_construct_event_receive_port, dummy); | ||
257 | *port = dummy[0]; | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static inline s64 beat_destruct_event_receive_port(u64 port) | ||
262 | { | ||
263 | s64 ret; | ||
264 | |||
265 | ret = beat_hcall_norets(HV_destruct_event_receive_port, port); | ||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static inline s64 beat_create_repository_node(u64 path[4], u64 data[2]) | ||
270 | { | ||
271 | s64 ret; | ||
272 | |||
273 | ret = beat_hcall_norets(HV_create_repository_node2, | ||
274 | path[0], path[1], path[2], path[3], data[0], data[1]); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4], | ||
279 | u64 data[2]) | ||
280 | { | ||
281 | s64 ret; | ||
282 | |||
283 | ret = beat_hcall2(HV_get_repository_node_value2, data, | ||
284 | lpid, path[0], path[1], path[2], path[3]); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
220 | #endif | 288 | #endif |
diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c index 279d7339e170..fbf27c74ebda 100644 --- a/arch/powerpc/platforms/celleb/htab.c +++ b/arch/powerpc/platforms/celleb/htab.c | |||
@@ -90,7 +90,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group) | |||
90 | static long beat_lpar_hpte_insert(unsigned long hpte_group, | 90 | static long beat_lpar_hpte_insert(unsigned long hpte_group, |
91 | unsigned long va, unsigned long pa, | 91 | unsigned long va, unsigned long pa, |
92 | unsigned long rflags, unsigned long vflags, | 92 | unsigned long rflags, unsigned long vflags, |
93 | int psize) | 93 | int psize, int ssize) |
94 | { | 94 | { |
95 | unsigned long lpar_rc; | 95 | unsigned long lpar_rc; |
96 | unsigned long slot; | 96 | unsigned long slot; |
@@ -105,7 +105,8 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group, | |||
105 | "rflags=%lx, vflags=%lx, psize=%d)\n", | 105 | "rflags=%lx, vflags=%lx, psize=%d)\n", |
106 | hpte_group, va, pa, rflags, vflags, psize); | 106 | hpte_group, va, pa, rflags, vflags, psize); |
107 | 107 | ||
108 | hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; | 108 | hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) | |
109 | vflags | HPTE_V_VALID; | ||
109 | hpte_r = hpte_encode_r(pa, psize) | rflags; | 110 | hpte_r = hpte_encode_r(pa, psize) | rflags; |
110 | 111 | ||
111 | if (!(vflags & HPTE_V_BOLTED)) | 112 | if (!(vflags & HPTE_V_BOLTED)) |
@@ -184,12 +185,12 @@ static void beat_lpar_hptab_clear(void) | |||
184 | static long beat_lpar_hpte_updatepp(unsigned long slot, | 185 | static long beat_lpar_hpte_updatepp(unsigned long slot, |
185 | unsigned long newpp, | 186 | unsigned long newpp, |
186 | unsigned long va, | 187 | unsigned long va, |
187 | int psize, int local) | 188 | int psize, int ssize, int local) |
188 | { | 189 | { |
189 | unsigned long lpar_rc; | 190 | unsigned long lpar_rc; |
190 | unsigned long dummy0, dummy1, want_v; | 191 | unsigned long dummy0, dummy1, want_v; |
191 | 192 | ||
192 | want_v = hpte_encode_v(va, psize); | 193 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
193 | 194 | ||
194 | DBG_LOW(" update: " | 195 | DBG_LOW(" update: " |
195 | "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", | 196 | "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", |
@@ -225,8 +226,8 @@ static long beat_lpar_hpte_find(unsigned long va, int psize) | |||
225 | long slot; | 226 | long slot; |
226 | unsigned long want_v, hpte_v; | 227 | unsigned long want_v, hpte_v; |
227 | 228 | ||
228 | hash = hpt_hash(va, mmu_psize_defs[psize].shift); | 229 | hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M); |
229 | want_v = hpte_encode_v(va, psize); | 230 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
230 | 231 | ||
231 | for (j = 0; j < 2; j++) { | 232 | for (j = 0; j < 2; j++) { |
232 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 233 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
@@ -251,11 +252,11 @@ static long beat_lpar_hpte_find(unsigned long va, int psize) | |||
251 | 252 | ||
252 | static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, | 253 | static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, |
253 | unsigned long ea, | 254 | unsigned long ea, |
254 | int psize) | 255 | int psize, int ssize) |
255 | { | 256 | { |
256 | unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1; | 257 | unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1; |
257 | 258 | ||
258 | vsid = get_kernel_vsid(ea); | 259 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); |
259 | va = (vsid << 28) | (ea & 0x0fffffff); | 260 | va = (vsid << 28) | (ea & 0x0fffffff); |
260 | 261 | ||
261 | spin_lock(&beat_htab_lock); | 262 | spin_lock(&beat_htab_lock); |
@@ -270,7 +271,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, | |||
270 | } | 271 | } |
271 | 272 | ||
272 | static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | 273 | static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, |
273 | int psize, int local) | 274 | int psize, int ssize, int local) |
274 | { | 275 | { |
275 | unsigned long want_v; | 276 | unsigned long want_v; |
276 | unsigned long lpar_rc; | 277 | unsigned long lpar_rc; |
@@ -279,7 +280,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
279 | 280 | ||
280 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", | 281 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", |
281 | slot, va, psize, local); | 282 | slot, va, psize, local); |
282 | want_v = hpte_encode_v(va, psize); | 283 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
283 | 284 | ||
284 | spin_lock_irqsave(&beat_htab_lock, flags); | 285 | spin_lock_irqsave(&beat_htab_lock, flags); |
285 | dummy1 = beat_lpar_hpte_getword0(slot); | 286 | dummy1 = beat_lpar_hpte_getword0(slot); |
@@ -306,3 +307,134 @@ void __init hpte_init_beat(void) | |||
306 | ppc_md.hpte_remove = beat_lpar_hpte_remove; | 307 | ppc_md.hpte_remove = beat_lpar_hpte_remove; |
307 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear; | 308 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear; |
308 | } | 309 | } |
310 | |||
311 | static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, | ||
312 | unsigned long va, unsigned long pa, | ||
313 | unsigned long rflags, unsigned long vflags, | ||
314 | int psize, int ssize) | ||
315 | { | ||
316 | unsigned long lpar_rc; | ||
317 | unsigned long slot; | ||
318 | unsigned long hpte_v, hpte_r; | ||
319 | |||
320 | /* same as iseries */ | ||
321 | if (vflags & HPTE_V_SECONDARY) | ||
322 | return -1; | ||
323 | |||
324 | if (!(vflags & HPTE_V_BOLTED)) | ||
325 | DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " | ||
326 | "rflags=%lx, vflags=%lx, psize=%d)\n", | ||
327 | hpte_group, va, pa, rflags, vflags, psize); | ||
328 | |||
329 | hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) | | ||
330 | vflags | HPTE_V_VALID; | ||
331 | hpte_r = hpte_encode_r(pa, psize) | rflags; | ||
332 | |||
333 | if (!(vflags & HPTE_V_BOLTED)) | ||
334 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); | ||
335 | |||
336 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) | ||
337 | hpte_r &= ~_PAGE_COHERENT; | ||
338 | |||
339 | /* insert into not-volted entry */ | ||
340 | lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r, | ||
341 | HPTE_V_BOLTED, 0, &slot); | ||
342 | /* | ||
343 | * Since we try and ioremap PHBs we don't own, the pte insert | ||
344 | * will fail. However we must catch the failure in hash_page | ||
345 | * or we will loop forever, so return -2 in this case. | ||
346 | */ | ||
347 | if (unlikely(lpar_rc != 0)) { | ||
348 | if (!(vflags & HPTE_V_BOLTED)) | ||
349 | DBG_LOW(" lpar err %lx\n", lpar_rc); | ||
350 | return -2; | ||
351 | } | ||
352 | if (!(vflags & HPTE_V_BOLTED)) | ||
353 | DBG_LOW(" -> slot: %lx\n", slot); | ||
354 | |||
355 | /* We have to pass down the secondary bucket bit here as well */ | ||
356 | return (slot ^ hpte_group) & 15; | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and | ||
361 | * the low 3 bits of flags happen to line up. So no transform is needed. | ||
362 | * We can probably optimize here and assume the high bits of newpp are | ||
363 | * already zero. For now I am paranoid. | ||
364 | */ | ||
365 | static long beat_lpar_hpte_updatepp_v3(unsigned long slot, | ||
366 | unsigned long newpp, | ||
367 | unsigned long va, | ||
368 | int psize, int ssize, int local) | ||
369 | { | ||
370 | unsigned long lpar_rc; | ||
371 | unsigned long want_v; | ||
372 | unsigned long pss; | ||
373 | |||
374 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); | ||
375 | pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc; | ||
376 | |||
377 | DBG_LOW(" update: " | ||
378 | "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", | ||
379 | want_v & HPTE_V_AVPN, slot, psize, newpp); | ||
380 | |||
381 | lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp); | ||
382 | |||
383 | if (lpar_rc == 0xfffffff7) { | ||
384 | DBG_LOW("not found !\n"); | ||
385 | return -1; | ||
386 | } | ||
387 | |||
388 | DBG_LOW("ok\n"); | ||
389 | |||
390 | BUG_ON(lpar_rc != 0); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va, | ||
396 | int psize, int ssize, int local) | ||
397 | { | ||
398 | unsigned long want_v; | ||
399 | unsigned long lpar_rc; | ||
400 | unsigned long pss; | ||
401 | |||
402 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", | ||
403 | slot, va, psize, local); | ||
404 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); | ||
405 | pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc; | ||
406 | |||
407 | lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss); | ||
408 | |||
409 | /* E_busy can be valid output: page may be already replaced */ | ||
410 | BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7); | ||
411 | } | ||
412 | |||
413 | static int64_t _beat_lpar_hptab_clear_v3(void) | ||
414 | { | ||
415 | return beat_clear_htab3(0); | ||
416 | } | ||
417 | |||
418 | static void beat_lpar_hptab_clear_v3(void) | ||
419 | { | ||
420 | _beat_lpar_hptab_clear_v3(); | ||
421 | } | ||
422 | |||
423 | void __init hpte_init_beat_v3(void) | ||
424 | { | ||
425 | if (_beat_lpar_hptab_clear_v3() == 0) { | ||
426 | ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate_v3; | ||
427 | ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp_v3; | ||
428 | ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; | ||
429 | ppc_md.hpte_insert = beat_lpar_hpte_insert_v3; | ||
430 | ppc_md.hpte_remove = beat_lpar_hpte_remove; | ||
431 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear_v3; | ||
432 | } else { | ||
433 | ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate; | ||
434 | ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp; | ||
435 | ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; | ||
436 | ppc_md.hpte_insert = beat_lpar_hpte_insert; | ||
437 | ppc_md.hpte_remove = beat_lpar_hpte_remove; | ||
438 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear; | ||
439 | } | ||
440 | } | ||
diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/celleb/interrupt.c index 98e6665681d3..c7c68ca70c82 100644 --- a/arch/powerpc/platforms/celleb/interrupt.c +++ b/arch/powerpc/platforms/celleb/interrupt.c | |||
@@ -175,11 +175,18 @@ static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct, | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static int beatic_pic_host_match(struct irq_host *h, struct device_node *np) | ||
179 | { | ||
180 | /* Match all */ | ||
181 | return 1; | ||
182 | } | ||
183 | |||
178 | static struct irq_host_ops beatic_pic_host_ops = { | 184 | static struct irq_host_ops beatic_pic_host_ops = { |
179 | .map = beatic_pic_host_map, | 185 | .map = beatic_pic_host_map, |
180 | .remap = beatic_pic_host_remap, | 186 | .remap = beatic_pic_host_remap, |
181 | .unmap = beatic_pic_host_unmap, | 187 | .unmap = beatic_pic_host_unmap, |
182 | .xlate = beatic_pic_host_xlate, | 188 | .xlate = beatic_pic_host_xlate, |
189 | .match = beatic_pic_host_match, | ||
183 | }; | 190 | }; |
184 | 191 | ||
185 | /* | 192 | /* |
@@ -242,7 +249,7 @@ void __init beatic_init_IRQ(void) | |||
242 | ppc_md.get_irq = beatic_get_irq; | 249 | ppc_md.get_irq = beatic_get_irq; |
243 | 250 | ||
244 | /* Allocate an irq host */ | 251 | /* Allocate an irq host */ |
245 | beatic_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, | 252 | beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, |
246 | &beatic_pic_host_ops, | 253 | &beatic_pic_host_ops, |
247 | 0); | 254 | 0); |
248 | BUG_ON(beatic_host == NULL); | 255 | BUG_ON(beatic_host == NULL); |
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c new file mode 100644 index 000000000000..2b912140bcbb --- /dev/null +++ b/arch/powerpc/platforms/celleb/io-workarounds.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * Support for Celleb io workarounds | ||
3 | * | ||
4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION | ||
5 | * | ||
6 | * This file is based to arch/powerpc/platform/cell/io-workarounds.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | */ | ||
22 | |||
23 | #undef DEBUG | ||
24 | |||
25 | #include <linux/of_device.h> | ||
26 | #include <linux/irq.h> | ||
27 | |||
28 | #include <asm/io.h> | ||
29 | #include <asm/prom.h> | ||
30 | #include <asm/machdep.h> | ||
31 | #include <asm/pci-bridge.h> | ||
32 | #include <asm/ppc-pci.h> | ||
33 | |||
34 | #include "pci.h" | ||
35 | |||
36 | #define MAX_CELLEB_PCI_BUS 4 | ||
37 | |||
38 | void *celleb_dummy_page_va; | ||
39 | |||
40 | static struct celleb_pci_bus { | ||
41 | struct pci_controller *phb; | ||
42 | void (*dummy_read)(struct pci_controller *); | ||
43 | } celleb_pci_busses[MAX_CELLEB_PCI_BUS]; | ||
44 | |||
45 | static int celleb_pci_count = 0; | ||
46 | |||
47 | static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr, | ||
48 | unsigned long paddr) | ||
49 | { | ||
50 | int i, j; | ||
51 | struct resource *res; | ||
52 | |||
53 | for (i = 0; i < celleb_pci_count; i++) { | ||
54 | struct celleb_pci_bus *bus = &celleb_pci_busses[i]; | ||
55 | struct pci_controller *phb = bus->phb; | ||
56 | if (paddr) | ||
57 | for (j = 0; j < 3; j++) { | ||
58 | res = &phb->mem_resources[j]; | ||
59 | if (paddr >= res->start && paddr <= res->end) | ||
60 | return bus; | ||
61 | } | ||
62 | res = &phb->io_resource; | ||
63 | if (vaddr && vaddr >= res->start && vaddr <= res->end) | ||
64 | return bus; | ||
65 | } | ||
66 | return NULL; | ||
67 | } | ||
68 | |||
69 | static void celleb_io_flush(const PCI_IO_ADDR addr) | ||
70 | { | ||
71 | struct celleb_pci_bus *bus; | ||
72 | int token; | ||
73 | |||
74 | token = PCI_GET_ADDR_TOKEN(addr); | ||
75 | |||
76 | if (token && token <= celleb_pci_count) | ||
77 | bus = &celleb_pci_busses[token - 1]; | ||
78 | else { | ||
79 | unsigned long vaddr, paddr; | ||
80 | pte_t *ptep; | ||
81 | |||
82 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | ||
83 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) | ||
84 | return; | ||
85 | |||
86 | ptep = find_linux_pte(init_mm.pgd, vaddr); | ||
87 | if (ptep == NULL) | ||
88 | paddr = 0; | ||
89 | else | ||
90 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | ||
91 | bus = celleb_pci_find(vaddr, paddr); | ||
92 | |||
93 | if (bus == NULL) | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | if (bus->dummy_read) | ||
98 | bus->dummy_read(bus->phb); | ||
99 | } | ||
100 | |||
101 | static u8 celleb_readb(const PCI_IO_ADDR addr) | ||
102 | { | ||
103 | u8 val; | ||
104 | val = __do_readb(addr); | ||
105 | celleb_io_flush(addr); | ||
106 | return val; | ||
107 | } | ||
108 | |||
109 | static u16 celleb_readw(const PCI_IO_ADDR addr) | ||
110 | { | ||
111 | u16 val; | ||
112 | val = __do_readw(addr); | ||
113 | celleb_io_flush(addr); | ||
114 | return val; | ||
115 | } | ||
116 | |||
117 | static u32 celleb_readl(const PCI_IO_ADDR addr) | ||
118 | { | ||
119 | u32 val; | ||
120 | val = __do_readl(addr); | ||
121 | celleb_io_flush(addr); | ||
122 | return val; | ||
123 | } | ||
124 | |||
125 | static u64 celleb_readq(const PCI_IO_ADDR addr) | ||
126 | { | ||
127 | u64 val; | ||
128 | val = __do_readq(addr); | ||
129 | celleb_io_flush(addr); | ||
130 | return val; | ||
131 | } | ||
132 | |||
133 | static u16 celleb_readw_be(const PCI_IO_ADDR addr) | ||
134 | { | ||
135 | u16 val; | ||
136 | val = __do_readw_be(addr); | ||
137 | celleb_io_flush(addr); | ||
138 | return val; | ||
139 | } | ||
140 | |||
141 | static u32 celleb_readl_be(const PCI_IO_ADDR addr) | ||
142 | { | ||
143 | u32 val; | ||
144 | val = __do_readl_be(addr); | ||
145 | celleb_io_flush(addr); | ||
146 | return val; | ||
147 | } | ||
148 | |||
149 | static u64 celleb_readq_be(const PCI_IO_ADDR addr) | ||
150 | { | ||
151 | u64 val; | ||
152 | val = __do_readq_be(addr); | ||
153 | celleb_io_flush(addr); | ||
154 | return val; | ||
155 | } | ||
156 | |||
157 | static void celleb_readsb(const PCI_IO_ADDR addr, | ||
158 | void *buf, unsigned long count) | ||
159 | { | ||
160 | __do_readsb(addr, buf, count); | ||
161 | celleb_io_flush(addr); | ||
162 | } | ||
163 | |||
164 | static void celleb_readsw(const PCI_IO_ADDR addr, | ||
165 | void *buf, unsigned long count) | ||
166 | { | ||
167 | __do_readsw(addr, buf, count); | ||
168 | celleb_io_flush(addr); | ||
169 | } | ||
170 | |||
171 | static void celleb_readsl(const PCI_IO_ADDR addr, | ||
172 | void *buf, unsigned long count) | ||
173 | { | ||
174 | __do_readsl(addr, buf, count); | ||
175 | celleb_io_flush(addr); | ||
176 | } | ||
177 | |||
178 | static void celleb_memcpy_fromio(void *dest, | ||
179 | const PCI_IO_ADDR src, | ||
180 | unsigned long n) | ||
181 | { | ||
182 | __do_memcpy_fromio(dest, src, n); | ||
183 | celleb_io_flush(src); | ||
184 | } | ||
185 | |||
186 | static void __iomem *celleb_ioremap(unsigned long addr, | ||
187 | unsigned long size, | ||
188 | unsigned long flags) | ||
189 | { | ||
190 | struct celleb_pci_bus *bus; | ||
191 | void __iomem *res = __ioremap(addr, size, flags); | ||
192 | int busno; | ||
193 | |||
194 | bus = celleb_pci_find(0, addr); | ||
195 | if (bus != NULL) { | ||
196 | busno = bus - celleb_pci_busses; | ||
197 | PCI_SET_ADDR_TOKEN(res, busno + 1); | ||
198 | } | ||
199 | return res; | ||
200 | } | ||
201 | |||
202 | static void celleb_iounmap(volatile void __iomem *addr) | ||
203 | { | ||
204 | return __iounmap(PCI_FIX_ADDR(addr)); | ||
205 | } | ||
206 | |||
207 | static struct ppc_pci_io celleb_pci_io __initdata = { | ||
208 | .readb = celleb_readb, | ||
209 | .readw = celleb_readw, | ||
210 | .readl = celleb_readl, | ||
211 | .readq = celleb_readq, | ||
212 | .readw_be = celleb_readw_be, | ||
213 | .readl_be = celleb_readl_be, | ||
214 | .readq_be = celleb_readq_be, | ||
215 | .readsb = celleb_readsb, | ||
216 | .readsw = celleb_readsw, | ||
217 | .readsl = celleb_readsl, | ||
218 | .memcpy_fromio = celleb_memcpy_fromio, | ||
219 | }; | ||
220 | |||
221 | void __init celleb_pci_add_one(struct pci_controller *phb, | ||
222 | void (*dummy_read)(struct pci_controller *)) | ||
223 | { | ||
224 | struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count]; | ||
225 | struct device_node *np = phb->arch_data; | ||
226 | |||
227 | if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) { | ||
228 | printk(KERN_ERR "Too many pci bridges, workarounds" | ||
229 | " disabled for %s\n", np->full_name); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | celleb_pci_count++; | ||
234 | |||
235 | bus->phb = phb; | ||
236 | bus->dummy_read = dummy_read; | ||
237 | } | ||
238 | |||
239 | static struct of_device_id celleb_pci_workaround_match[] __initdata = { | ||
240 | { | ||
241 | .name = "pci-pseudo", | ||
242 | .data = fake_pci_workaround_init, | ||
243 | }, { | ||
244 | .name = "epci", | ||
245 | .data = epci_workaround_init, | ||
246 | }, { | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | int __init celleb_pci_workaround_init(void) | ||
251 | { | ||
252 | struct pci_controller *phb; | ||
253 | struct device_node *node; | ||
254 | const struct of_device_id *match; | ||
255 | void (*init_func)(struct pci_controller *); | ||
256 | |||
257 | celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
258 | if (!celleb_dummy_page_va) { | ||
259 | printk(KERN_ERR "Celleb: dummy read disabled." | ||
260 | "Alloc celleb_dummy_page_va failed\n"); | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | list_for_each_entry(phb, &hose_list, list_node) { | ||
265 | node = phb->arch_data; | ||
266 | match = of_match_node(celleb_pci_workaround_match, node); | ||
267 | |||
268 | if (match) { | ||
269 | init_func = match->data; | ||
270 | (*init_func)(phb); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | ppc_pci_io = celleb_pci_io; | ||
275 | ppc_md.ioremap = celleb_ioremap; | ||
276 | ppc_md.iounmap = celleb_iounmap; | ||
277 | |||
278 | return 0; | ||
279 | } | ||
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c index e9ac19c4bba4..6bc32fda7a6b 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/celleb/pci.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/bootmem.h> | 32 | #include <linux/bootmem.h> |
33 | #include <linux/pci_regs.h> | 33 | #include <linux/pci_regs.h> |
34 | #include <linux/of_device.h> | ||
34 | 35 | ||
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -242,8 +243,8 @@ static int celleb_fake_pci_write_config(struct pci_bus *bus, | |||
242 | } | 243 | } |
243 | 244 | ||
244 | static struct pci_ops celleb_fake_pci_ops = { | 245 | static struct pci_ops celleb_fake_pci_ops = { |
245 | celleb_fake_pci_read_config, | 246 | .read = celleb_fake_pci_read_config, |
246 | celleb_fake_pci_write_config | 247 | .write = celleb_fake_pci_write_config, |
247 | }; | 248 | }; |
248 | 249 | ||
249 | static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, | 250 | static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, |
@@ -288,8 +289,8 @@ static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, | |||
288 | celleb_config_write_fake(config, PCI_COMMAND, 2, val); | 289 | celleb_config_write_fake(config, PCI_COMMAND, 2, val); |
289 | } | 290 | } |
290 | 291 | ||
291 | static int __devinit celleb_setup_fake_pci_device(struct device_node *node, | 292 | static int __init celleb_setup_fake_pci_device(struct device_node *node, |
292 | struct pci_controller *hose) | 293 | struct pci_controller *hose) |
293 | { | 294 | { |
294 | unsigned int rlen; | 295 | unsigned int rlen; |
295 | int num_base_addr = 0; | 296 | int num_base_addr = 0; |
@@ -327,10 +328,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, | |||
327 | 328 | ||
328 | size = 256; | 329 | size = 256; |
329 | config = &private->fake_config[devno][fn]; | 330 | config = &private->fake_config[devno][fn]; |
330 | if (mem_init_done) | 331 | *config = alloc_maybe_bootmem(size, GFP_KERNEL); |
331 | *config = kzalloc(size, GFP_KERNEL); | ||
332 | else | ||
333 | *config = alloc_bootmem(size); | ||
334 | if (*config == NULL) { | 332 | if (*config == NULL) { |
335 | printk(KERN_ERR "PCI: " | 333 | printk(KERN_ERR "PCI: " |
336 | "not enough memory for fake configuration space\n"); | 334 | "not enough memory for fake configuration space\n"); |
@@ -341,10 +339,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, | |||
341 | 339 | ||
342 | size = sizeof(struct celleb_pci_resource); | 340 | size = sizeof(struct celleb_pci_resource); |
343 | res = &private->res[devno][fn]; | 341 | res = &private->res[devno][fn]; |
344 | if (mem_init_done) | 342 | *res = alloc_maybe_bootmem(size, GFP_KERNEL); |
345 | *res = kzalloc(size, GFP_KERNEL); | ||
346 | else | ||
347 | *res = alloc_bootmem(size); | ||
348 | if (*res == NULL) { | 343 | if (*res == NULL) { |
349 | printk(KERN_ERR | 344 | printk(KERN_ERR |
350 | "PCI: not enough memory for resource data space\n"); | 345 | "PCI: not enough memory for resource data space\n"); |
@@ -418,8 +413,8 @@ error: | |||
418 | return 1; | 413 | return 1; |
419 | } | 414 | } |
420 | 415 | ||
421 | static int __devinit phb_set_bus_ranges(struct device_node *dev, | 416 | static int __init phb_set_bus_ranges(struct device_node *dev, |
422 | struct pci_controller *phb) | 417 | struct pci_controller *phb) |
423 | { | 418 | { |
424 | const int *bus_range; | 419 | const int *bus_range; |
425 | unsigned int len; | 420 | unsigned int len; |
@@ -434,46 +429,65 @@ static int __devinit phb_set_bus_ranges(struct device_node *dev, | |||
434 | return 0; | 429 | return 0; |
435 | } | 430 | } |
436 | 431 | ||
437 | static void __devinit celleb_alloc_private_mem(struct pci_controller *hose) | 432 | static void __init celleb_alloc_private_mem(struct pci_controller *hose) |
438 | { | 433 | { |
439 | if (mem_init_done) | 434 | hose->private_data = |
440 | hose->private_data = | 435 | alloc_maybe_bootmem(sizeof(struct celleb_pci_private), |
441 | kzalloc(sizeof(struct celleb_pci_private), GFP_KERNEL); | 436 | GFP_KERNEL); |
442 | else | ||
443 | hose->private_data = | ||
444 | alloc_bootmem(sizeof(struct celleb_pci_private)); | ||
445 | } | 437 | } |
446 | 438 | ||
447 | int __devinit celleb_setup_phb(struct pci_controller *phb) | 439 | static int __init celleb_setup_fake_pci(struct device_node *dev, |
440 | struct pci_controller *phb) | ||
448 | { | 441 | { |
449 | const char *name; | ||
450 | struct device_node *dev = phb->arch_data; | ||
451 | struct device_node *node; | 442 | struct device_node *node; |
452 | unsigned int rlen; | ||
453 | 443 | ||
454 | name = of_get_property(dev, "name", &rlen); | 444 | phb->ops = &celleb_fake_pci_ops; |
455 | if (!name) | 445 | celleb_alloc_private_mem(phb); |
456 | return 1; | ||
457 | 446 | ||
458 | pr_debug("PCI: celleb_setup_phb() %s\n", name); | 447 | for (node = of_get_next_child(dev, NULL); |
459 | phb_set_bus_ranges(dev, phb); | 448 | node != NULL; node = of_get_next_child(dev, node)) |
460 | phb->buid = 1; | 449 | celleb_setup_fake_pci_device(node, phb); |
450 | |||
451 | return 0; | ||
452 | } | ||
461 | 453 | ||
462 | if (strcmp(name, "epci") == 0) { | 454 | void __init fake_pci_workaround_init(struct pci_controller *phb) |
463 | phb->ops = &celleb_epci_ops; | 455 | { |
464 | return celleb_setup_epci(dev, phb); | 456 | /** |
457 | * We will add fake pci bus to scc_pci_bus for the purpose to improve | ||
458 | * I/O Macro performance. But device-tree and device drivers | ||
459 | * are not ready to use address with a token. | ||
460 | */ | ||
461 | |||
462 | /* celleb_pci_add_one(phb, NULL); */ | ||
463 | } | ||
465 | 464 | ||
466 | } else if (strcmp(name, "pci-pseudo") == 0) { | 465 | static struct of_device_id celleb_phb_match[] __initdata = { |
467 | phb->ops = &celleb_fake_pci_ops; | 466 | { |
468 | celleb_alloc_private_mem(phb); | 467 | .name = "pci-pseudo", |
469 | for (node = of_get_next_child(dev, NULL); | 468 | .data = celleb_setup_fake_pci, |
470 | node != NULL; node = of_get_next_child(dev, node)) | 469 | }, { |
471 | celleb_setup_fake_pci_device(node, phb); | 470 | .name = "epci", |
471 | .data = celleb_setup_epci, | ||
472 | }, { | ||
473 | }, | ||
474 | }; | ||
472 | 475 | ||
473 | } else | 476 | int __init celleb_setup_phb(struct pci_controller *phb) |
477 | { | ||
478 | struct device_node *dev = phb->arch_data; | ||
479 | const struct of_device_id *match; | ||
480 | int (*setup_func)(struct device_node *, struct pci_controller *); | ||
481 | |||
482 | match = of_match_node(celleb_phb_match, dev); | ||
483 | if (!match) | ||
474 | return 1; | 484 | return 1; |
475 | 485 | ||
476 | return 0; | 486 | phb_set_bus_ranges(dev, phb); |
487 | phb->buid = 1; | ||
488 | |||
489 | setup_func = match->data; | ||
490 | return (*setup_func)(dev, phb); | ||
477 | } | 491 | } |
478 | 492 | ||
479 | int celleb_pci_probe_mode(struct pci_bus *bus) | 493 | int celleb_pci_probe_mode(struct pci_bus *bus) |
diff --git a/arch/powerpc/platforms/celleb/pci.h b/arch/powerpc/platforms/celleb/pci.h index 5340e348e297..5d5544ffeddb 100644 --- a/arch/powerpc/platforms/celleb/pci.h +++ b/arch/powerpc/platforms/celleb/pci.h | |||
@@ -25,11 +25,18 @@ | |||
25 | 25 | ||
26 | #include <asm/pci-bridge.h> | 26 | #include <asm/pci-bridge.h> |
27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
28 | #include <asm/ppc-pci.h> | ||
28 | 29 | ||
29 | extern int celleb_setup_phb(struct pci_controller *); | 30 | extern int celleb_setup_phb(struct pci_controller *); |
30 | extern int celleb_pci_probe_mode(struct pci_bus *); | 31 | extern int celleb_pci_probe_mode(struct pci_bus *); |
31 | 32 | ||
32 | extern struct pci_ops celleb_epci_ops; | ||
33 | extern int celleb_setup_epci(struct device_node *, struct pci_controller *); | 33 | extern int celleb_setup_epci(struct device_node *, struct pci_controller *); |
34 | 34 | ||
35 | extern void *celleb_dummy_page_va; | ||
36 | extern int __init celleb_pci_workaround_init(void); | ||
37 | extern void __init celleb_pci_add_one(struct pci_controller *, | ||
38 | void (*)(struct pci_controller *)); | ||
39 | extern void fake_pci_workaround_init(struct pci_controller *); | ||
40 | extern void epci_workaround_init(struct pci_controller *); | ||
41 | |||
35 | #endif /* _CELLEB_PCI_H */ | 42 | #endif /* _CELLEB_PCI_H */ |
diff --git a/arch/powerpc/platforms/celleb/scc.h b/arch/powerpc/platforms/celleb/scc.h index e9ce8a7c1882..6be1542a6e66 100644 --- a/arch/powerpc/platforms/celleb/scc.h +++ b/arch/powerpc/platforms/celleb/scc.h | |||
@@ -53,7 +53,7 @@ | |||
53 | #define SCC_EPCI_STATUS 0x808 | 53 | #define SCC_EPCI_STATUS 0x808 |
54 | #define SCC_EPCI_ABTSET 0x80c | 54 | #define SCC_EPCI_ABTSET 0x80c |
55 | #define SCC_EPCI_WATRP 0x810 | 55 | #define SCC_EPCI_WATRP 0x810 |
56 | #define SCC_EPCI_DUMMYRADR 0x814 | 56 | #define SCC_EPCI_DUMYRADR 0x814 |
57 | #define SCC_EPCI_SWRESP 0x818 | 57 | #define SCC_EPCI_SWRESP 0x818 |
58 | #define SCC_EPCI_CNTOPT 0x81c | 58 | #define SCC_EPCI_CNTOPT 0x81c |
59 | #define SCC_EPCI_ECMODE 0xf00 | 59 | #define SCC_EPCI_ECMODE 0xf00 |
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c index c4b011094bd6..9d076426676c 100644 --- a/arch/powerpc/platforms/celleb/scc_epci.c +++ b/arch/powerpc/platforms/celleb/scc_epci.c | |||
@@ -43,7 +43,11 @@ | |||
43 | 43 | ||
44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") | 44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") |
45 | 45 | ||
46 | static inline volatile void __iomem *celleb_epci_get_epci_base( | 46 | struct epci_private { |
47 | dma_addr_t dummy_page_da; | ||
48 | }; | ||
49 | |||
50 | static inline PCI_IO_ADDR celleb_epci_get_epci_base( | ||
47 | struct pci_controller *hose) | 51 | struct pci_controller *hose) |
48 | { | 52 | { |
49 | /* | 53 | /* |
@@ -55,7 +59,7 @@ static inline volatile void __iomem *celleb_epci_get_epci_base( | |||
55 | return hose->cfg_addr; | 59 | return hose->cfg_addr; |
56 | } | 60 | } |
57 | 61 | ||
58 | static inline volatile void __iomem *celleb_epci_get_epci_cfg( | 62 | static inline PCI_IO_ADDR celleb_epci_get_epci_cfg( |
59 | struct pci_controller *hose) | 63 | struct pci_controller *hose) |
60 | { | 64 | { |
61 | /* | 65 | /* |
@@ -67,20 +71,11 @@ static inline volatile void __iomem *celleb_epci_get_epci_cfg( | |||
67 | return hose->cfg_data; | 71 | return hose->cfg_data; |
68 | } | 72 | } |
69 | 73 | ||
70 | #if 0 /* test code for epci dummy read */ | 74 | static void scc_epci_dummy_read(struct pci_controller *hose) |
71 | static void celleb_epci_dummy_read(struct pci_dev *dev) | ||
72 | { | 75 | { |
73 | volatile void __iomem *epci_base; | 76 | PCI_IO_ADDR epci_base; |
74 | struct device_node *node; | ||
75 | struct pci_controller *hose; | ||
76 | u32 val; | 77 | u32 val; |
77 | 78 | ||
78 | node = (struct device_node *)dev->bus->sysdata; | ||
79 | hose = pci_find_hose_for_OF_device(node); | ||
80 | |||
81 | if (!hose) | ||
82 | return; | ||
83 | |||
84 | epci_base = celleb_epci_get_epci_base(hose); | 79 | epci_base = celleb_epci_get_epci_base(hose); |
85 | 80 | ||
86 | val = in_be32(epci_base + SCC_EPCI_WATRP); | 81 | val = in_be32(epci_base + SCC_EPCI_WATRP); |
@@ -88,21 +83,45 @@ static void celleb_epci_dummy_read(struct pci_dev *dev) | |||
88 | 83 | ||
89 | return; | 84 | return; |
90 | } | 85 | } |
91 | #endif | 86 | |
87 | void __init epci_workaround_init(struct pci_controller *hose) | ||
88 | { | ||
89 | PCI_IO_ADDR epci_base; | ||
90 | PCI_IO_ADDR reg; | ||
91 | struct epci_private *private = hose->private_data; | ||
92 | |||
93 | BUG_ON(!private); | ||
94 | |||
95 | private->dummy_page_da = dma_map_single(hose->parent, | ||
96 | celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); | ||
97 | if (private->dummy_page_da == DMA_ERROR_CODE) { | ||
98 | printk(KERN_ERR "EPCI: dummy read disabled." | ||
99 | "Map dummy page failed.\n"); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | celleb_pci_add_one(hose, scc_epci_dummy_read); | ||
104 | epci_base = celleb_epci_get_epci_base(hose); | ||
105 | |||
106 | reg = epci_base + SCC_EPCI_DUMYRADR; | ||
107 | out_be32(reg, private->dummy_page_da); | ||
108 | } | ||
92 | 109 | ||
93 | static inline void clear_and_disable_master_abort_interrupt( | 110 | static inline void clear_and_disable_master_abort_interrupt( |
94 | struct pci_controller *hose) | 111 | struct pci_controller *hose) |
95 | { | 112 | { |
96 | volatile void __iomem *epci_base, *reg; | 113 | PCI_IO_ADDR epci_base; |
114 | PCI_IO_ADDR reg; | ||
97 | epci_base = celleb_epci_get_epci_base(hose); | 115 | epci_base = celleb_epci_get_epci_base(hose); |
98 | reg = epci_base + PCI_COMMAND; | 116 | reg = epci_base + PCI_COMMAND; |
99 | out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16)); | 117 | out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16)); |
100 | } | 118 | } |
101 | 119 | ||
102 | static int celleb_epci_check_abort(struct pci_controller *hose, | 120 | static int celleb_epci_check_abort(struct pci_controller *hose, |
103 | volatile void __iomem *addr) | 121 | PCI_IO_ADDR addr) |
104 | { | 122 | { |
105 | volatile void __iomem *reg, *epci_base; | 123 | PCI_IO_ADDR reg; |
124 | PCI_IO_ADDR epci_base; | ||
106 | u32 val; | 125 | u32 val; |
107 | 126 | ||
108 | iob(); | 127 | iob(); |
@@ -132,12 +151,12 @@ static int celleb_epci_check_abort(struct pci_controller *hose, | |||
132 | return PCIBIOS_SUCCESSFUL; | 151 | return PCIBIOS_SUCCESSFUL; |
133 | } | 152 | } |
134 | 153 | ||
135 | static volatile void __iomem *celleb_epci_make_config_addr( | 154 | static PCI_IO_ADDR celleb_epci_make_config_addr( |
136 | struct pci_bus *bus, | 155 | struct pci_bus *bus, |
137 | struct pci_controller *hose, | 156 | struct pci_controller *hose, |
138 | unsigned int devfn, int where) | 157 | unsigned int devfn, int where) |
139 | { | 158 | { |
140 | volatile void __iomem *addr; | 159 | PCI_IO_ADDR addr; |
141 | 160 | ||
142 | if (bus != hose->bus) | 161 | if (bus != hose->bus) |
143 | addr = celleb_epci_get_epci_cfg(hose) + | 162 | addr = celleb_epci_get_epci_cfg(hose) + |
@@ -157,7 +176,8 @@ static volatile void __iomem *celleb_epci_make_config_addr( | |||
157 | static int celleb_epci_read_config(struct pci_bus *bus, | 176 | static int celleb_epci_read_config(struct pci_bus *bus, |
158 | unsigned int devfn, int where, int size, u32 * val) | 177 | unsigned int devfn, int where, int size, u32 * val) |
159 | { | 178 | { |
160 | volatile void __iomem *epci_base, *addr; | 179 | PCI_IO_ADDR epci_base; |
180 | PCI_IO_ADDR addr; | ||
161 | struct device_node *node; | 181 | struct device_node *node; |
162 | struct pci_controller *hose; | 182 | struct pci_controller *hose; |
163 | 183 | ||
@@ -220,7 +240,8 @@ static int celleb_epci_read_config(struct pci_bus *bus, | |||
220 | static int celleb_epci_write_config(struct pci_bus *bus, | 240 | static int celleb_epci_write_config(struct pci_bus *bus, |
221 | unsigned int devfn, int where, int size, u32 val) | 241 | unsigned int devfn, int where, int size, u32 val) |
222 | { | 242 | { |
223 | volatile void __iomem *epci_base, *addr; | 243 | PCI_IO_ADDR epci_base; |
244 | PCI_IO_ADDR addr; | ||
224 | struct device_node *node; | 245 | struct device_node *node; |
225 | struct pci_controller *hose; | 246 | struct pci_controller *hose; |
226 | 247 | ||
@@ -278,15 +299,16 @@ static int celleb_epci_write_config(struct pci_bus *bus, | |||
278 | } | 299 | } |
279 | 300 | ||
280 | struct pci_ops celleb_epci_ops = { | 301 | struct pci_ops celleb_epci_ops = { |
281 | celleb_epci_read_config, | 302 | .read = celleb_epci_read_config, |
282 | celleb_epci_write_config, | 303 | .write = celleb_epci_write_config, |
283 | }; | 304 | }; |
284 | 305 | ||
285 | /* to be moved in FW */ | 306 | /* to be moved in FW */ |
286 | static int __devinit celleb_epci_init(struct pci_controller *hose) | 307 | static int __init celleb_epci_init(struct pci_controller *hose) |
287 | { | 308 | { |
288 | u32 val; | 309 | u32 val; |
289 | volatile void __iomem *reg, *epci_base; | 310 | PCI_IO_ADDR reg; |
311 | PCI_IO_ADDR epci_base; | ||
290 | int hwres = 0; | 312 | int hwres = 0; |
291 | 313 | ||
292 | epci_base = celleb_epci_get_epci_base(hose); | 314 | epci_base = celleb_epci_get_epci_base(hose); |
@@ -403,7 +425,7 @@ static int __devinit celleb_epci_init(struct pci_controller *hose) | |||
403 | return 0; | 425 | return 0; |
404 | } | 426 | } |
405 | 427 | ||
406 | int __devinit celleb_setup_epci(struct device_node *node, | 428 | int __init celleb_setup_epci(struct device_node *node, |
407 | struct pci_controller *hose) | 429 | struct pci_controller *hose) |
408 | { | 430 | { |
409 | struct resource r; | 431 | struct resource r; |
@@ -440,10 +462,24 @@ int __devinit celleb_setup_epci(struct device_node *node, | |||
440 | r.start, (unsigned long)hose->cfg_data, | 462 | r.start, (unsigned long)hose->cfg_data, |
441 | (r.end - r.start + 1)); | 463 | (r.end - r.start + 1)); |
442 | 464 | ||
465 | hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL); | ||
466 | if (hose->private_data == NULL) { | ||
467 | printk(KERN_ERR "EPCI: no memory for private data.\n"); | ||
468 | goto error; | ||
469 | } | ||
470 | |||
471 | hose->ops = &celleb_epci_ops; | ||
443 | celleb_epci_init(hose); | 472 | celleb_epci_init(hose); |
444 | 473 | ||
445 | return 0; | 474 | return 0; |
446 | 475 | ||
447 | error: | 476 | error: |
477 | kfree(hose->private_data); | ||
478 | |||
479 | if (hose->cfg_addr) | ||
480 | iounmap(hose->cfg_addr); | ||
481 | |||
482 | if (hose->cfg_data) | ||
483 | iounmap(hose->cfg_data); | ||
448 | return 1; | 484 | return 1; |
449 | } | 485 | } |
diff --git a/arch/powerpc/platforms/celleb/scc_sio.c b/arch/powerpc/platforms/celleb/scc_sio.c index bcd25f54d986..610008211ca1 100644 --- a/arch/powerpc/platforms/celleb/scc_sio.c +++ b/arch/powerpc/platforms/celleb/scc_sio.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * setup serial port in SCC | 2 | * setup serial port in SCC |
3 | * | 3 | * |
4 | * (C) Copyright 2006 TOSHIBA CORPORATION | 4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -28,58 +28,58 @@ | |||
28 | 28 | ||
29 | /* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024 | 29 | /* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024 |
30 | mmio=0xfff000-0x1000,0xff2000-0x1000 */ | 30 | mmio=0xfff000-0x1000,0xff2000-0x1000 */ |
31 | static int txx9_serial_bitmap = 0; | 31 | static int txx9_serial_bitmap __initdata = 0; |
32 | 32 | ||
33 | static struct { | 33 | static struct { |
34 | uint32_t offset; | 34 | uint32_t offset; |
35 | uint32_t index; | 35 | uint32_t index; |
36 | } txx9_scc_tab[3] = { | 36 | } txx9_scc_tab[3] __initdata = { |
37 | { 0x300, 0 }, /* 0xFFF300 */ | 37 | { 0x300, 0 }, /* 0xFFF300 */ |
38 | { 0x400, 0 }, /* 0xFFF400 */ | 38 | { 0x400, 0 }, /* 0xFFF400 */ |
39 | { 0x800, 1 } /* 0xFF2800 */ | 39 | { 0x800, 1 } /* 0xFF2800 */ |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static int txx9_serial_init(void) | 42 | static int __init txx9_serial_init(void) |
43 | { | 43 | { |
44 | extern int early_serial_txx9_setup(struct uart_port *port); | 44 | extern int early_serial_txx9_setup(struct uart_port *port); |
45 | struct device_node *node; | 45 | struct device_node *node = NULL; |
46 | int i; | 46 | int i; |
47 | struct uart_port req; | 47 | struct uart_port req; |
48 | struct of_irq irq; | 48 | struct of_irq irq; |
49 | struct resource res; | 49 | struct resource res; |
50 | 50 | ||
51 | node = of_find_node_by_path("/ioif1/sio"); | 51 | while ((node = of_find_compatible_node(node, |
52 | if (!node) | 52 | "serial", "toshiba,sio-scc")) != NULL) { |
53 | return 0; | 53 | for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) { |
54 | if (!(txx9_serial_bitmap & (1<<i))) | ||
55 | continue; | ||
54 | 56 | ||
55 | for(i = 0; i < sizeof(txx9_scc_tab)/sizeof(txx9_scc_tab[0]); i++) { | 57 | if (of_irq_map_one(node, i, &irq)) |
56 | if (!(txx9_serial_bitmap & (1<<i))) | 58 | continue; |
57 | continue; | 59 | if (of_address_to_resource(node, |
60 | txx9_scc_tab[i].index, &res)) | ||
61 | continue; | ||
58 | 62 | ||
59 | if (of_irq_map_one(node, i, &irq)) | 63 | memset(&req, 0, sizeof(req)); |
60 | continue; | 64 | req.line = i; |
61 | if (of_address_to_resource(node, txx9_scc_tab[i].index, &res)) | 65 | req.iotype = UPIO_MEM; |
62 | continue; | 66 | req.mapbase = res.start + txx9_scc_tab[i].offset; |
63 | |||
64 | memset(&req, 0, sizeof(req)); | ||
65 | req.line = i; | ||
66 | req.iotype = UPIO_MEM; | ||
67 | req.mapbase = res.start + txx9_scc_tab[i].offset; | ||
68 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE | 67 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE |
69 | req.membase = ioremap(req.mapbase, 0x24); | 68 | req.membase = ioremap(req.mapbase, 0x24); |
70 | #endif | 69 | #endif |
71 | req.irq = irq_create_of_mapping(irq.controller, | 70 | req.irq = irq_create_of_mapping(irq.controller, |
72 | irq.specifier, irq.size); | 71 | irq.specifier, irq.size); |
73 | req.flags |= UPF_IOREMAP | UPF_BUGGY_UART /*HAVE_CTS_LINE*/; | 72 | req.flags |= UPF_IOREMAP | UPF_BUGGY_UART |
74 | req.uartclk = 83300000; | 73 | /*HAVE_CTS_LINE*/; |
75 | early_serial_txx9_setup(&req); | 74 | req.uartclk = 83300000; |
75 | early_serial_txx9_setup(&req); | ||
76 | } | ||
76 | } | 77 | } |
77 | 78 | ||
78 | of_node_put(node); | ||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int txx9_serial_config(char *ptr) | 82 | static int __init txx9_serial_config(char *ptr) |
83 | { | 83 | { |
84 | int i; | 84 | int i; |
85 | 85 | ||
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index 5e9f7f163571..1769d755eff3 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c | |||
@@ -73,7 +73,7 @@ static void celleb_show_cpuinfo(struct seq_file *m) | |||
73 | of_node_put(root); | 73 | of_node_put(root); |
74 | } | 74 | } |
75 | 75 | ||
76 | static int celleb_machine_type_hack(char *ptr) | 76 | static int __init celleb_machine_type_hack(char *ptr) |
77 | { | 77 | { |
78 | strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type)); | 78 | strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type)); |
79 | celleb_machine_type[sizeof(celleb_machine_type)-1] = 0; | 79 | celleb_machine_type[sizeof(celleb_machine_type)-1] = 0; |
@@ -101,21 +101,11 @@ static void __init celleb_setup_arch(void) | |||
101 | /* init to some ~sane value until calibrate_delay() runs */ | 101 | /* init to some ~sane value until calibrate_delay() runs */ |
102 | loops_per_jiffy = 50000000; | 102 | loops_per_jiffy = 50000000; |
103 | 103 | ||
104 | if (ROOT_DEV == 0) { | ||
105 | printk("No ramdisk, default root is /dev/hda2\n"); | ||
106 | ROOT_DEV = Root_HDA2; | ||
107 | } | ||
108 | |||
109 | #ifdef CONFIG_DUMMY_CONSOLE | 104 | #ifdef CONFIG_DUMMY_CONSOLE |
110 | conswitchp = &dummy_con; | 105 | conswitchp = &dummy_con; |
111 | #endif | 106 | #endif |
112 | } | 107 | } |
113 | 108 | ||
114 | static void beat_power_save(void) | ||
115 | { | ||
116 | beat_pause(0); | ||
117 | } | ||
118 | |||
119 | static int __init celleb_probe(void) | 109 | static int __init celleb_probe(void) |
120 | { | 110 | { |
121 | unsigned long root = of_get_flat_dt_root(); | 111 | unsigned long root = of_get_flat_dt_root(); |
@@ -124,18 +114,11 @@ static int __init celleb_probe(void) | |||
124 | return 0; | 114 | return 0; |
125 | 115 | ||
126 | powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; | 116 | powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; |
127 | hpte_init_beat(); | 117 | hpte_init_beat_v3(); |
128 | return 1; | 118 | return 1; |
129 | } | 119 | } |
130 | 120 | ||
131 | #ifdef CONFIG_KEXEC | 121 | static struct of_device_id celleb_bus_ids[] __initdata = { |
132 | static void celleb_kexec_cpu_down(int crash, int secondary) | ||
133 | { | ||
134 | beatic_deinit_IRQ(); | ||
135 | } | ||
136 | #endif | ||
137 | |||
138 | static struct of_device_id celleb_bus_ids[] = { | ||
139 | { .type = "scc", }, | 122 | { .type = "scc", }, |
140 | { .type = "ioif", }, /* old style */ | 123 | { .type = "ioif", }, /* old style */ |
141 | {}, | 124 | {}, |
@@ -149,6 +132,8 @@ static int __init celleb_publish_devices(void) | |||
149 | /* Publish OF platform devices for southbridge IOs */ | 132 | /* Publish OF platform devices for southbridge IOs */ |
150 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); | 133 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); |
151 | 134 | ||
135 | celleb_pci_workaround_init(); | ||
136 | |||
152 | return 0; | 137 | return 0; |
153 | } | 138 | } |
154 | device_initcall(celleb_publish_devices); | 139 | device_initcall(celleb_publish_devices); |
@@ -175,7 +160,7 @@ define_machine(celleb) { | |||
175 | .pci_probe_mode = celleb_pci_probe_mode, | 160 | .pci_probe_mode = celleb_pci_probe_mode, |
176 | .pci_setup_phb = celleb_setup_phb, | 161 | .pci_setup_phb = celleb_setup_phb, |
177 | #ifdef CONFIG_KEXEC | 162 | #ifdef CONFIG_KEXEC |
178 | .kexec_cpu_down = celleb_kexec_cpu_down, | 163 | .kexec_cpu_down = beat_kexec_cpu_down, |
179 | .machine_kexec = default_machine_kexec, | 164 | .machine_kexec = default_machine_kexec, |
180 | .machine_kexec_prepare = default_machine_kexec_prepare, | 165 | .machine_kexec_prepare = default_machine_kexec_prepare, |
181 | .machine_crash_shutdown = default_machine_crash_shutdown, | 166 | .machine_crash_shutdown = default_machine_crash_shutdown, |