aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/40x/Kconfig16
-rw-r--r--arch/powerpc/platforms/512x/Kconfig20
-rw-r--r--arch/powerpc/platforms/512x/Makefile1
-rw-r--r--arch/powerpc/platforms/512x/clock.c18
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_ads.c2
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_generic.c2
-rw-r--r--arch/powerpc/platforms/512x/mpc512x.h2
-rw-r--r--arch/powerpc/platforms/512x/mpc512x_shared.c284
-rw-r--r--arch/powerpc/platforms/512x/pdm360ng.c129
-rw-r--r--arch/powerpc/platforms/52xx/lite5200_pm.c3
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pm.c3
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/83xx/Makefile1
-rw-r--r--arch/powerpc/platforms/83xx/mpc830x_rdb.c94
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c279
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c148
-rw-r--r--arch/powerpc/platforms/85xx/smp.c67
-rw-r--r--arch/powerpc/platforms/85xx/tqm85xx.c21
-rw-r--r--arch/powerpc/platforms/8xx/Kconfig6
-rw-r--r--arch/powerpc/platforms/8xx/Makefile1
-rw-r--r--arch/powerpc/platforms/8xx/tqm8xx_setup.c156
-rw-r--r--arch/powerpc/platforms/iseries/vio.c3
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_32.c8
-rw-r--r--arch/powerpc/platforms/powermac/feature.c6
-rw-r--r--arch/powerpc/platforms/ps3/htab.c2
-rw-r--r--arch/powerpc/platforms/pseries/Makefile4
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c1
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c3
-rw-r--r--arch/powerpc/platforms/pseries/event_sources.c23
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c7
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c22
-rw-r--r--arch/powerpc/platforms/pseries/ras.c5
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c4
-rw-r--r--arch/powerpc/platforms/pseries/suspend.c214
-rw-r--r--arch/powerpc/platforms/pseries/xics.c2
37 files changed, 1388 insertions, 186 deletions
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index ec64264f7a50..b72176434ebe 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -71,22 +71,6 @@ config MAKALU
71 help 71 help
72 This option enables support for the AMCC PPC405EX board. 72 This option enables support for the AMCC PPC405EX board.
73 73
74#config REDWOOD_5
75# bool "Redwood-5"
76# depends on 40x
77# default n
78# select STB03xxx
79# help
80# This option enables support for the IBM STB04 evaluation board.
81
82#config REDWOOD_6
83# bool "Redwood-6"
84# depends on 40x
85# default n
86# select STB03xxx
87# help
88# This option enables support for the IBM STBx25xx evaluation board.
89
90#config SYCAMORE 74#config SYCAMORE
91# bool "Sycamore" 75# bool "Sycamore"
92# depends on 40x 76# depends on 40x
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index 4dac9b0525a4..27b0651221d1 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,32 +1,34 @@
1config PPC_MPC512x 1config PPC_MPC512x
2 bool 2 bool "512x-based boards"
3 depends on 6xx
3 select FSL_SOC 4 select FSL_SOC
4 select IPIC 5 select IPIC
5 select PPC_CLOCK 6 select PPC_CLOCK
6 select PPC_PCI_CHOICE 7 select PPC_PCI_CHOICE
7 select FSL_PCI if PCI 8 select FSL_PCI if PCI
8 9
9config PPC_MPC5121
10 bool
11 select PPC_MPC512x
12
13config MPC5121_ADS 10config MPC5121_ADS
14 bool "Freescale MPC5121E ADS" 11 bool "Freescale MPC5121E ADS"
15 depends on 6xx 12 depends on PPC_MPC512x
16 select DEFAULT_UIMAGE 13 select DEFAULT_UIMAGE
17 select PPC_MPC5121
18 select MPC5121_ADS_CPLD 14 select MPC5121_ADS_CPLD
19 help 15 help
20 This option enables support for the MPC5121E ADS board. 16 This option enables support for the MPC5121E ADS board.
21 17
22config MPC5121_GENERIC 18config MPC5121_GENERIC
23 bool "Generic support for simple MPC5121 based boards" 19 bool "Generic support for simple MPC5121 based boards"
24 depends on 6xx 20 depends on PPC_MPC512x
25 select DEFAULT_UIMAGE 21 select DEFAULT_UIMAGE
26 select PPC_MPC5121
27 help 22 help
28 This option enables support for simple MPC5121 based boards 23 This option enables support for simple MPC5121 based boards
29 which do not need custom platform specific setup. 24 which do not need custom platform specific setup.
30 25
31 Compatible boards include: Protonic LVT base boards (ZANMCU 26 Compatible boards include: Protonic LVT base boards (ZANMCU
32 and VICVT2). 27 and VICVT2).
28
29config PDM360NG
30 bool "ifm PDM360NG board"
31 depends on PPC_MPC512x
32 select DEFAULT_UIMAGE
33 help
34 This option enables support for the PDM360NG board.
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 90be2f5717e6..4efc1c4b6fb5 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -4,3 +4,4 @@
4obj-y += clock.o mpc512x_shared.o 4obj-y += clock.o mpc512x_shared.o
5obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o 5obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o
6obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o 6obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o
7obj-$(CONFIG_PDM360NG) += pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index 65e2d6729c1b..5b243bd3eb3b 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -292,6 +292,15 @@ static void diu_clk_calc(struct clk *clk)
292 clk->rate = rate; 292 clk->rate = rate;
293} 293}
294 294
295static void viu_clk_calc(struct clk *clk)
296{
297 unsigned long rate;
298
299 rate = sys_clk.rate;
300 rate /= 2;
301 clk->rate = rate;
302}
303
295static void half_clk_calc(struct clk *clk) 304static void half_clk_calc(struct clk *clk)
296{ 305{
297 clk->rate = clk->parent->rate / 2; 306 clk->rate = clk->parent->rate / 2;
@@ -412,6 +421,14 @@ static struct clk diu_clk = {
412 .calc = diu_clk_calc, 421 .calc = diu_clk_calc,
413}; 422};
414 423
424static struct clk viu_clk = {
425 .name = "viu_clk",
426 .flags = CLK_HAS_CTRL,
427 .reg = 1,
428 .bit = 18,
429 .calc = viu_clk_calc,
430};
431
415static struct clk axe_clk = { 432static struct clk axe_clk = {
416 .name = "axe_clk", 433 .name = "axe_clk",
417 .flags = CLK_HAS_CTRL, 434 .flags = CLK_HAS_CTRL,
@@ -535,6 +552,7 @@ struct clk *rate_clks[] = {
535 &ref_clk, 552 &ref_clk,
536 &sys_clk, 553 &sys_clk,
537 &diu_clk, 554 &diu_clk,
555 &viu_clk,
538 &csb_clk, 556 &csb_clk,
539 &e300_clk, 557 &e300_clk,
540 &ips_clk, 558 &ips_clk,
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index ee6ae129c25c..dcef6ade48e1 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -42,6 +42,7 @@ static void __init mpc5121_ads_setup_arch(void)
42 for_each_compatible_node(np, "pci", "fsl,mpc5121-pci") 42 for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
43 mpc83xx_add_bridge(np); 43 mpc83xx_add_bridge(np);
44#endif 44#endif
45 mpc512x_setup_diu();
45} 46}
46 47
47static void __init mpc5121_ads_init_IRQ(void) 48static void __init mpc5121_ads_init_IRQ(void)
@@ -65,6 +66,7 @@ define_machine(mpc5121_ads) {
65 .probe = mpc5121_ads_probe, 66 .probe = mpc5121_ads_probe,
66 .setup_arch = mpc5121_ads_setup_arch, 67 .setup_arch = mpc5121_ads_setup_arch,
67 .init = mpc512x_init, 68 .init = mpc512x_init,
69 .init_early = mpc512x_init_diu,
68 .init_IRQ = mpc5121_ads_init_IRQ, 70 .init_IRQ = mpc5121_ads_init_IRQ,
69 .get_irq = ipic_get_irq, 71 .get_irq = ipic_get_irq,
70 .calibrate_decr = generic_calibrate_decr, 72 .calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
index a6c0e3a2615d..e487eb06ec6b 100644
--- a/arch/powerpc/platforms/512x/mpc5121_generic.c
+++ b/arch/powerpc/platforms/512x/mpc5121_generic.c
@@ -52,6 +52,8 @@ define_machine(mpc5121_generic) {
52 .name = "MPC5121 generic", 52 .name = "MPC5121 generic",
53 .probe = mpc5121_generic_probe, 53 .probe = mpc5121_generic_probe,
54 .init = mpc512x_init, 54 .init = mpc512x_init,
55 .init_early = mpc512x_init_diu,
56 .setup_arch = mpc512x_setup_diu,
55 .init_IRQ = mpc512x_init_IRQ, 57 .init_IRQ = mpc512x_init_IRQ,
56 .get_irq = ipic_get_irq, 58 .get_irq = ipic_get_irq,
57 .calibrate_decr = generic_calibrate_decr, 59 .calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index b2daca0d1488..1ab6d11d0b19 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -16,4 +16,6 @@ extern void __init mpc512x_init(void);
16extern int __init mpc5121_clk_init(void); 16extern int __init mpc5121_clk_init(void);
17void __init mpc512x_declare_of_platform_devices(void); 17void __init mpc512x_declare_of_platform_devices(void);
18extern void mpc512x_restart(char *cmd); 18extern void mpc512x_restart(char *cmd);
19extern void mpc512x_init_diu(void);
20extern void mpc512x_setup_diu(void);
19#endif /* __MPC512X_H__ */ 21#endif /* __MPC512X_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 707e572b7c40..e41ebbdb3e12 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -16,7 +16,11 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/irq.h> 17#include <linux/irq.h>
18#include <linux/of_platform.h> 18#include <linux/of_platform.h>
19#include <linux/fsl-diu-fb.h>
20#include <linux/bootmem.h>
21#include <sysdev/fsl_soc.h>
19 22
23#include <asm/cacheflush.h>
20#include <asm/machdep.h> 24#include <asm/machdep.h>
21#include <asm/ipic.h> 25#include <asm/ipic.h>
22#include <asm/prom.h> 26#include <asm/prom.h>
@@ -54,6 +58,286 @@ void mpc512x_restart(char *cmd)
54 ; 58 ;
55} 59}
56 60
61struct fsl_diu_shared_fb {
62 u8 gamma[0x300]; /* 32-bit aligned! */
63 struct diu_ad ad0; /* 32-bit aligned! */
64 phys_addr_t fb_phys;
65 size_t fb_len;
66 bool in_use;
67};
68
69unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
70 int monitor_port)
71{
72 switch (bits_per_pixel) {
73 case 32:
74 return 0x88883316;
75 case 24:
76 return 0x88082219;
77 case 16:
78 return 0x65053118;
79 }
80 return 0x00000400;
81}
82
83void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
84{
85}
86
87void mpc512x_set_monitor_port(int monitor_port)
88{
89}
90
91#define DIU_DIV_MASK 0x000000ff
92void mpc512x_set_pixel_clock(unsigned int pixclock)
93{
94 unsigned long bestval, bestfreq, speed, busfreq;
95 unsigned long minpixclock, maxpixclock, pixval;
96 struct mpc512x_ccm __iomem *ccm;
97 struct device_node *np;
98 u32 temp;
99 long err;
100 int i;
101
102 np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
103 if (!np) {
104 pr_err("Can't find clock control module.\n");
105 return;
106 }
107
108 ccm = of_iomap(np, 0);
109 of_node_put(np);
110 if (!ccm) {
111 pr_err("Can't map clock control module reg.\n");
112 return;
113 }
114
115 np = of_find_node_by_type(NULL, "cpu");
116 if (np) {
117 const unsigned int *prop =
118 of_get_property(np, "bus-frequency", NULL);
119
120 of_node_put(np);
121 if (prop) {
122 busfreq = *prop;
123 } else {
124 pr_err("Can't get bus-frequency property\n");
125 return;
126 }
127 } else {
128 pr_err("Can't find 'cpu' node.\n");
129 return;
130 }
131
132 /* Pixel Clock configuration */
133 pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
134 speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
135
136 /* Calculate the pixel clock with the smallest error */
137 /* calculate the following in steps to avoid overflow */
138 pr_debug("DIU pixclock in ps - %d\n", pixclock);
139 temp = (1000000000 / pixclock) * 1000;
140 pixclock = temp;
141 pr_debug("DIU pixclock freq - %u\n", pixclock);
142
143 temp = temp / 20; /* pixclock * 0.05 */
144 pr_debug("deviation = %d\n", temp);
145 minpixclock = pixclock - temp;
146 maxpixclock = pixclock + temp;
147 pr_debug("DIU minpixclock - %lu\n", minpixclock);
148 pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
149 pixval = speed/pixclock;
150 pr_debug("DIU pixval = %lu\n", pixval);
151
152 err = LONG_MAX;
153 bestval = pixval;
154 pr_debug("DIU bestval = %lu\n", bestval);
155
156 bestfreq = 0;
157 for (i = -1; i <= 1; i++) {
158 temp = speed / (pixval+i);
159 pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
160 i, pixval, temp);
161 if ((temp < minpixclock) || (temp > maxpixclock))
162 pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
163 minpixclock, maxpixclock);
164 else if (abs(temp - pixclock) < err) {
165 pr_debug("Entered the else if block %d\n", i);
166 err = abs(temp - pixclock);
167 bestval = pixval + i;
168 bestfreq = temp;
169 }
170 }
171
172 pr_debug("DIU chose = %lx\n", bestval);
173 pr_debug("DIU error = %ld\n NomPixClk ", err);
174 pr_debug("DIU: Best Freq = %lx\n", bestfreq);
175 /* Modify DIU_DIV in CCM SCFR1 */
176 temp = in_be32(&ccm->scfr1);
177 pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
178 temp &= ~DIU_DIV_MASK;
179 temp |= (bestval & DIU_DIV_MASK);
180 out_be32(&ccm->scfr1, temp);
181 pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
182 iounmap(ccm);
183}
184
185ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
186{
187 return sprintf(buf, "0 - 5121 LCD\n");
188}
189
190int mpc512x_set_sysfs_monitor_port(int val)
191{
192 return 0;
193}
194
195static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
196
197#if defined(CONFIG_FB_FSL_DIU) || \
198 defined(CONFIG_FB_FSL_DIU_MODULE)
199static inline void mpc512x_free_bootmem(struct page *page)
200{
201 __ClearPageReserved(page);
202 BUG_ON(PageTail(page));
203 BUG_ON(atomic_read(&page->_count) > 1);
204 atomic_set(&page->_count, 1);
205 __free_page(page);
206 totalram_pages++;
207}
208
209void mpc512x_release_bootmem(void)
210{
211 unsigned long addr = diu_shared_fb.fb_phys & PAGE_MASK;
212 unsigned long size = diu_shared_fb.fb_len;
213 unsigned long start, end;
214
215 if (diu_shared_fb.in_use) {
216 start = PFN_UP(addr);
217 end = PFN_DOWN(addr + size);
218
219 for (; start < end; start++)
220 mpc512x_free_bootmem(pfn_to_page(start));
221
222 diu_shared_fb.in_use = false;
223 }
224 diu_ops.release_bootmem = NULL;
225}
226#endif
227
228/*
229 * Check if DIU was pre-initialized. If so, perform steps
230 * needed to continue displaying through the whole boot process.
231 * Move area descriptor and gamma table elsewhere, they are
232 * destroyed by bootmem allocator otherwise. The frame buffer
233 * address range will be reserved in setup_arch() after bootmem
234 * allocator is up.
235 */
236void __init mpc512x_init_diu(void)
237{
238 struct device_node *np;
239 struct diu __iomem *diu_reg;
240 phys_addr_t desc;
241 void __iomem *vaddr;
242 unsigned long mode, pix_fmt, res, bpp;
243 unsigned long dst;
244
245 np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
246 if (!np) {
247 pr_err("No DIU node\n");
248 return;
249 }
250
251 diu_reg = of_iomap(np, 0);
252 of_node_put(np);
253 if (!diu_reg) {
254 pr_err("Can't map DIU\n");
255 return;
256 }
257
258 mode = in_be32(&diu_reg->diu_mode);
259 if (mode != MFB_MODE1) {
260 pr_info("%s: DIU OFF\n", __func__);
261 goto out;
262 }
263
264 desc = in_be32(&diu_reg->desc[0]);
265 vaddr = ioremap(desc, sizeof(struct diu_ad));
266 if (!vaddr) {
267 pr_err("Can't map DIU area desc.\n");
268 goto out;
269 }
270 memcpy(&diu_shared_fb.ad0, vaddr, sizeof(struct diu_ad));
271 /* flush fb area descriptor */
272 dst = (unsigned long)&diu_shared_fb.ad0;
273 flush_dcache_range(dst, dst + sizeof(struct diu_ad) - 1);
274
275 res = in_be32(&diu_reg->disp_size);
276 pix_fmt = in_le32(vaddr);
277 bpp = ((pix_fmt >> 16) & 0x3) + 1;
278 diu_shared_fb.fb_phys = in_le32(vaddr + 4);
279 diu_shared_fb.fb_len = ((res & 0xfff0000) >> 16) * (res & 0xfff) * bpp;
280 diu_shared_fb.in_use = true;
281 iounmap(vaddr);
282
283 desc = in_be32(&diu_reg->gamma);
284 vaddr = ioremap(desc, sizeof(diu_shared_fb.gamma));
285 if (!vaddr) {
286 pr_err("Can't map DIU area desc.\n");
287 diu_shared_fb.in_use = false;
288 goto out;
289 }
290 memcpy(&diu_shared_fb.gamma, vaddr, sizeof(diu_shared_fb.gamma));
291 /* flush gamma table */
292 dst = (unsigned long)&diu_shared_fb.gamma;
293 flush_dcache_range(dst, dst + sizeof(diu_shared_fb.gamma) - 1);
294
295 iounmap(vaddr);
296 out_be32(&diu_reg->gamma, virt_to_phys(&diu_shared_fb.gamma));
297 out_be32(&diu_reg->desc[1], 0);
298 out_be32(&diu_reg->desc[2], 0);
299 out_be32(&diu_reg->desc[0], virt_to_phys(&diu_shared_fb.ad0));
300
301out:
302 iounmap(diu_reg);
303}
304
305void __init mpc512x_setup_diu(void)
306{
307 int ret;
308
309 /*
310 * We do not allocate and configure new area for bitmap buffer
311 * because it would requere copying bitmap data (splash image)
312 * and so negatively affect boot time. Instead we reserve the
313 * already configured frame buffer area so that it won't be
314 * destroyed. The starting address of the area to reserve and
315 * also it's length is passed to reserve_bootmem(). It will be
316 * freed later on first open of fbdev, when splash image is not
317 * needed any more.
318 */
319 if (diu_shared_fb.in_use) {
320 ret = reserve_bootmem(diu_shared_fb.fb_phys,
321 diu_shared_fb.fb_len,
322 BOOTMEM_EXCLUSIVE);
323 if (ret) {
324 pr_err("%s: reserve bootmem failed\n", __func__);
325 diu_shared_fb.in_use = false;
326 }
327 }
328
329#if defined(CONFIG_FB_FSL_DIU) || \
330 defined(CONFIG_FB_FSL_DIU_MODULE)
331 diu_ops.get_pixel_format = mpc512x_get_pixel_format;
332 diu_ops.set_gamma_table = mpc512x_set_gamma_table;
333 diu_ops.set_monitor_port = mpc512x_set_monitor_port;
334 diu_ops.set_pixel_clock = mpc512x_set_pixel_clock;
335 diu_ops.show_monitor_port = mpc512x_show_monitor_port;
336 diu_ops.set_sysfs_monitor_port = mpc512x_set_sysfs_monitor_port;
337 diu_ops.release_bootmem = mpc512x_release_bootmem;
338#endif
339}
340
57void __init mpc512x_init_IRQ(void) 341void __init mpc512x_init_IRQ(void)
58{ 342{
59 struct device_node *np; 343 struct device_node *np;
diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
new file mode 100644
index 000000000000..0575e858291c
--- /dev/null
+++ b/arch/powerpc/platforms/512x/pdm360ng.c
@@ -0,0 +1,129 @@
1/*
2 * Copyright (C) 2010 DENX Software Engineering
3 *
4 * Anatolij Gustschin, <agust@denx.de>
5 *
6 * PDM360NG board setup
7 *
8 * This is free software; you can redistribute it and/or modify it
9 * 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 */
14
15#include <linux/kernel.h>
16#include <linux/io.h>
17#include <linux/of_platform.h>
18
19#include <asm/machdep.h>
20#include <asm/ipic.h>
21
22#include "mpc512x.h"
23
24#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
25 defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
26#include <linux/interrupt.h>
27#include <linux/spi/ads7846.h>
28#include <linux/spi/spi.h>
29#include <linux/notifier.h>
30
31static void *pdm360ng_gpio_base;
32
33static int pdm360ng_get_pendown_state(void)
34{
35 u32 reg;
36
37 reg = in_be32(pdm360ng_gpio_base + 0xc);
38 if (reg & 0x40)
39 setbits32(pdm360ng_gpio_base + 0xc, 0x40);
40
41 reg = in_be32(pdm360ng_gpio_base + 0x8);
42
43 /* return 1 if pen is down */
44 return (reg & 0x40) == 0;
45}
46
47static struct ads7846_platform_data pdm360ng_ads7846_pdata = {
48 .model = 7845,
49 .get_pendown_state = pdm360ng_get_pendown_state,
50 .irq_flags = IRQF_TRIGGER_LOW,
51};
52
53static int __init pdm360ng_penirq_init(void)
54{
55 struct device_node *np;
56
57 np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-gpio");
58 if (!np) {
59 pr_err("%s: Can't find 'mpc5121-gpio' node\n", __func__);
60 return -ENODEV;
61 }
62
63 pdm360ng_gpio_base = of_iomap(np, 0);
64 of_node_put(np);
65 if (!pdm360ng_gpio_base) {
66 pr_err("%s: Can't map gpio regs.\n", __func__);
67 return -ENODEV;
68 }
69 out_be32(pdm360ng_gpio_base + 0xc, 0xffffffff);
70 setbits32(pdm360ng_gpio_base + 0x18, 0x2000);
71 setbits32(pdm360ng_gpio_base + 0x10, 0x40);
72
73 return 0;
74}
75
76static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
77 unsigned long event, void *__dev)
78{
79 struct device *dev = __dev;
80
81 if ((event == BUS_NOTIFY_ADD_DEVICE) &&
82 of_device_is_compatible(dev->of_node, "ti,ads7846")) {
83 dev->platform_data = &pdm360ng_ads7846_pdata;
84 return NOTIFY_OK;
85 }
86 return NOTIFY_DONE;
87}
88
89static struct notifier_block pdm360ng_touchscreen_nb = {
90 .notifier_call = pdm360ng_touchscreen_notifier_call,
91};
92
93static void __init pdm360ng_touchscreen_init(void)
94{
95 if (pdm360ng_penirq_init())
96 return;
97
98 bus_register_notifier(&spi_bus_type, &pdm360ng_touchscreen_nb);
99}
100#else
101static inline void __init pdm360ng_touchscreen_init(void)
102{
103}
104#endif /* CONFIG_TOUCHSCREEN_ADS7846 */
105
106void __init pdm360ng_init(void)
107{
108 mpc512x_init();
109 pdm360ng_touchscreen_init();
110}
111
112static int __init pdm360ng_probe(void)
113{
114 unsigned long root = of_get_flat_dt_root();
115
116 return of_flat_dt_is_compatible(root, "ifm,pdm360ng");
117}
118
119define_machine(pdm360ng) {
120 .name = "PDM360NG",
121 .probe = pdm360ng_probe,
122 .setup_arch = mpc512x_setup_diu,
123 .init = pdm360ng_init,
124 .init_early = mpc512x_init_diu,
125 .init_IRQ = mpc512x_init_IRQ,
126 .get_irq = ipic_get_irq,
127 .calibrate_decr = generic_calibrate_decr,
128 .restart = mpc512x_restart,
129};
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c
index b5c753db125e..80234e5921f5 100644
--- a/arch/powerpc/platforms/52xx/lite5200_pm.c
+++ b/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -216,9 +216,6 @@ static int lite5200_pm_enter(suspend_state_t state)
216 216
217 lite5200_restore_regs(); 217 lite5200_restore_regs();
218 218
219 /* restart jiffies */
220 wakeup_decrementer();
221
222 iounmap(mbar); 219 iounmap(mbar);
223 return 0; 220 return 0;
224} 221}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index 76722532bd95..568cef636275 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -171,9 +171,6 @@ int mpc52xx_pm_enter(suspend_state_t state)
171 /* restore SRAM */ 171 /* restore SRAM */
172 memcpy(sram, saved_sram, sram_size); 172 memcpy(sram, saved_sram, sram_size);
173 173
174 /* restart jiffies */
175 wakeup_decrementer();
176
177 /* reenable interrupts in PIC */ 174 /* reenable interrupts in PIC */
178 out_be32(&intr->main_mask, intr_main_mask); 175 out_be32(&intr->main_mask, intr_main_mask);
179 176
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index f49a2548c5ff..021763a32c2f 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -9,6 +9,14 @@ menuconfig PPC_83xx
9 9
10if PPC_83xx 10if PPC_83xx
11 11
12config MPC830x_RDB
13 bool "Freescale MPC830x RDB"
14 select DEFAULT_UIMAGE
15 select PPC_MPC831x
16 select FSL_GTM
17 help
18 This option enables support for the MPC8308 RDB board.
19
12config MPC831x_RDB 20config MPC831x_RDB
13 bool "Freescale MPC831x RDB" 21 bool "Freescale MPC831x RDB"
14 select DEFAULT_UIMAGE 22 select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index e139c36572ec..6e8bbbbcfdf8 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -4,6 +4,7 @@
4obj-y := misc.o usb.o 4obj-y := misc.o usb.o
5obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o 5obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
6obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o 6obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
7obj-$(CONFIG_MPC830x_RDB) += mpc830x_rdb.o
7obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o 8obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
8obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o 9obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
9obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o 10obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
new file mode 100644
index 000000000000..ac102ee9abe8
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
@@ -0,0 +1,94 @@
1/*
2 * arch/powerpc/platforms/83xx/mpc830x_rdb.c
3 *
4 * Description: MPC830x RDB board specific routines.
5 * This file is based on mpc831x_rdb.c
6 *
7 * Copyright (C) Freescale Semiconductor, Inc. 2009. All rights reserved.
8 * Copyright (C) 2010. Ilya Yanok, Emcraft Systems, yanok@emcraft.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/pci.h>
17#include <linux/of_platform.h>
18#include <asm/time.h>
19#include <asm/ipic.h>
20#include <asm/udbg.h>
21#include <sysdev/fsl_pci.h>
22#include <sysdev/fsl_soc.h>
23#include "mpc83xx.h"
24
25/*
26 * Setup the architecture
27 */
28static void __init mpc830x_rdb_setup_arch(void)
29{
30#ifdef CONFIG_PCI
31 struct device_node *np;
32#endif
33
34 if (ppc_md.progress)
35 ppc_md.progress("mpc830x_rdb_setup_arch()", 0);
36
37#ifdef CONFIG_PCI
38 for_each_compatible_node(np, "pci", "fsl,mpc8308-pcie")
39 mpc83xx_add_bridge(np);
40#endif
41 mpc831x_usb_cfg();
42}
43
44static void __init mpc830x_rdb_init_IRQ(void)
45{
46 struct device_node *np;
47
48 np = of_find_node_by_type(NULL, "ipic");
49 if (!np)
50 return;
51
52 ipic_init(np, 0);
53
54 /* Initialize the default interrupt mapping priorities,
55 * in case the boot rom changed something on us.
56 */
57 ipic_set_default_priority();
58}
59
60/*
61 * Called very early, MMU is off, device-tree isn't unflattened
62 */
63static int __init mpc830x_rdb_probe(void)
64{
65 unsigned long root = of_get_flat_dt_root();
66
67 return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
68 of_flat_dt_is_compatible(root, "fsl,mpc8308rdb");
69}
70
71static struct of_device_id __initdata of_bus_ids[] = {
72 { .compatible = "simple-bus" },
73 { .compatible = "gianfar" },
74 {},
75};
76
77static int __init declare_of_platform_devices(void)
78{
79 of_platform_bus_probe(NULL, of_bus_ids, NULL);
80 return 0;
81}
82machine_device_initcall(mpc830x_rdb, declare_of_platform_devices);
83
84define_machine(mpc830x_rdb) {
85 .name = "MPC830x RDB",
86 .probe = mpc830x_rdb_probe,
87 .setup_arch = mpc830x_rdb_setup_arch,
88 .init_IRQ = mpc830x_rdb_init_IRQ,
89 .get_irq = ipic_get_irq,
90 .restart = mpc83xx_restart,
91 .time_init = mpc83xx_time_init,
92 .calibrate_decr = generic_calibrate_decr,
93 .progress = udbg_progress,
94};
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 3a2ade2e443f..bea1f5905ad4 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -65,6 +65,14 @@ config MPC85xx_RDB
65 help 65 help
66 This option enables support for the MPC85xx RDB (P2020 RDB) board 66 This option enables support for the MPC85xx RDB (P2020 RDB) board
67 67
68config P1022_DS
69 bool "Freescale P1022 DS"
70 select DEFAULT_UIMAGE
71 select CONFIG_PHYS_64BIT # The DTS has 36-bit addresses
72 select SWIOTLB
73 help
74 This option enables support for the Freescale P1022DS reference board.
75
68config SOCRATES 76config SOCRATES
69 bool "Socrates" 77 bool "Socrates"
70 select DEFAULT_UIMAGE 78 select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 387c128f2c8c..a2ec3f8f4d06 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o
10obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o 10obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o
11obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o 11obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
12obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o 12obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
13obj-$(CONFIG_P1022_DS) += p1022_ds.o
13obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o 14obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o
14obj-$(CONFIG_STX_GP3) += stx_gp3.o 15obj-$(CONFIG_STX_GP3) += stx_gp3.o
15obj-$(CONFIG_TQM85xx) += tqm85xx.o 16obj-$(CONFIG_TQM85xx) += tqm85xx.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 494513682d70..da64be19d099 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -158,51 +158,108 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
158extern void __init mpc85xx_smp_init(void); 158extern void __init mpc85xx_smp_init(void);
159#endif 159#endif
160 160
161static void __init mpc85xx_mds_setup_arch(void) 161#ifdef CONFIG_QUICC_ENGINE
162static struct of_device_id mpc85xx_qe_ids[] __initdata = {
163 { .type = "qe", },
164 { .compatible = "fsl,qe", },
165 { },
166};
167
168static void __init mpc85xx_publish_qe_devices(void)
162{ 169{
163 struct device_node *np; 170 struct device_node *np;
164 static u8 __iomem *bcsr_regs = NULL;
165#ifdef CONFIG_PCI
166 struct pci_controller *hose;
167#endif
168 dma_addr_t max = 0xffffffff;
169 171
170 if (ppc_md.progress) 172 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
171 ppc_md.progress("mpc85xx_mds_setup_arch()", 0); 173 if (!of_device_is_available(np)) {
174 of_node_put(np);
175 return;
176 }
177
178 of_platform_bus_probe(NULL, mpc85xx_qe_ids, NULL);
179}
180
181static void __init mpc85xx_mds_reset_ucc_phys(void)
182{
183 struct device_node *np;
184 static u8 __iomem *bcsr_regs;
172 185
173 /* Map BCSR area */ 186 /* Map BCSR area */
174 np = of_find_node_by_name(NULL, "bcsr"); 187 np = of_find_node_by_name(NULL, "bcsr");
175 if (np != NULL) { 188 if (!np)
176 struct resource res; 189 return;
177 190
178 of_address_to_resource(np, 0, &res); 191 bcsr_regs = of_iomap(np, 0);
179 bcsr_regs = ioremap(res.start, res.end - res.start +1); 192 of_node_put(np);
180 of_node_put(np); 193 if (!bcsr_regs)
181 } 194 return;
182 195
183#ifdef CONFIG_PCI 196 if (machine_is(mpc8568_mds)) {
184 for_each_node_by_type(np, "pci") { 197#define BCSR_UCC1_GETH_EN (0x1 << 7)
185 if (of_device_is_compatible(np, "fsl,mpc8540-pci") || 198#define BCSR_UCC2_GETH_EN (0x1 << 7)
186 of_device_is_compatible(np, "fsl,mpc8548-pcie")) { 199#define BCSR_UCC1_MODE_MSK (0x3 << 4)
187 struct resource rsrc; 200#define BCSR_UCC2_MODE_MSK (0x3 << 0)
188 of_address_to_resource(np, 0, &rsrc);
189 if ((rsrc.start & 0xfffff) == 0x8000)
190 fsl_add_bridge(np, 1);
191 else
192 fsl_add_bridge(np, 0);
193 201
194 hose = pci_find_hose_for_OF_device(np); 202 /* Turn off UCC1 & UCC2 */
195 max = min(max, hose->dma_window_base_cur + 203 clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
196 hose->dma_window_size); 204 clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
205
206 /* Mode is RGMII, all bits clear */
207 clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
208 BCSR_UCC2_MODE_MSK);
209
210 /* Turn UCC1 & UCC2 on */
211 setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
212 setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
213 } else if (machine_is(mpc8569_mds)) {
214#define BCSR7_UCC12_GETHnRST (0x1 << 2)
215#define BCSR8_UEM_MARVELL_RST (0x1 << 1)
216#define BCSR_UCC_RGMII (0x1 << 6)
217#define BCSR_UCC_RTBI (0x1 << 5)
218 /*
219 * U-Boot mangles interrupt polarity for Marvell PHYs,
220 * so reset built-in and UEM Marvell PHYs, this puts
221 * the PHYs into their normal state.
222 */
223 clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
224 setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
225
226 setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
227 clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
228
229 for (np = NULL; (np = of_find_compatible_node(np,
230 "network",
231 "ucc_geth")) != NULL;) {
232 const unsigned int *prop;
233 int ucc_num;
234
235 prop = of_get_property(np, "cell-index", NULL);
236 if (prop == NULL)
237 continue;
238
239 ucc_num = *prop - 1;
240
241 prop = of_get_property(np, "phy-connection-type", NULL);
242 if (prop == NULL)
243 continue;
244
245 if (strcmp("rtbi", (const char *)prop) == 0)
246 clrsetbits_8(&bcsr_regs[7 + ucc_num],
247 BCSR_UCC_RGMII, BCSR_UCC_RTBI);
197 } 248 }
249 } else if (machine_is(p1021_mds)) {
250#define BCSR11_ENET_MICRST (0x1 << 5)
251 /* Reset Micrel PHY */
252 clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
253 setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
198 } 254 }
199#endif
200 255
201#ifdef CONFIG_SMP 256 iounmap(bcsr_regs);
202 mpc85xx_smp_init(); 257}
203#endif 258
259static void __init mpc85xx_mds_qe_init(void)
260{
261 struct device_node *np;
204 262
205#ifdef CONFIG_QUICC_ENGINE
206 np = of_find_compatible_node(NULL, NULL, "fsl,qe"); 263 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
207 if (!np) { 264 if (!np) {
208 np = of_find_node_by_name(NULL, "qe"); 265 np = of_find_node_by_name(NULL, "qe");
@@ -210,6 +267,11 @@ static void __init mpc85xx_mds_setup_arch(void)
210 return; 267 return;
211 } 268 }
212 269
270 if (!of_device_is_available(np)) {
271 of_node_put(np);
272 return;
273 }
274
213 qe_reset(); 275 qe_reset();
214 of_node_put(np); 276 of_node_put(np);
215 277
@@ -224,70 +286,7 @@ static void __init mpc85xx_mds_setup_arch(void)
224 par_io_of_config(ucc); 286 par_io_of_config(ucc);
225 } 287 }
226 288
227 if (bcsr_regs) { 289 mpc85xx_mds_reset_ucc_phys();
228 if (machine_is(mpc8568_mds)) {
229#define BCSR_UCC1_GETH_EN (0x1 << 7)
230#define BCSR_UCC2_GETH_EN (0x1 << 7)
231#define BCSR_UCC1_MODE_MSK (0x3 << 4)
232#define BCSR_UCC2_MODE_MSK (0x3 << 0)
233
234 /* Turn off UCC1 & UCC2 */
235 clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
236 clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
237
238 /* Mode is RGMII, all bits clear */
239 clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
240 BCSR_UCC2_MODE_MSK);
241
242 /* Turn UCC1 & UCC2 on */
243 setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
244 setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
245 } else if (machine_is(mpc8569_mds)) {
246#define BCSR7_UCC12_GETHnRST (0x1 << 2)
247#define BCSR8_UEM_MARVELL_RST (0x1 << 1)
248#define BCSR_UCC_RGMII (0x1 << 6)
249#define BCSR_UCC_RTBI (0x1 << 5)
250 /*
251 * U-Boot mangles interrupt polarity for Marvell PHYs,
252 * so reset built-in and UEM Marvell PHYs, this puts
253 * the PHYs into their normal state.
254 */
255 clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
256 setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
257
258 setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
259 clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
260
261 for (np = NULL; (np = of_find_compatible_node(np,
262 "network",
263 "ucc_geth")) != NULL;) {
264 const unsigned int *prop;
265 int ucc_num;
266
267 prop = of_get_property(np, "cell-index", NULL);
268 if (prop == NULL)
269 continue;
270
271 ucc_num = *prop - 1;
272
273 prop = of_get_property(np, "phy-connection-type", NULL);
274 if (prop == NULL)
275 continue;
276
277 if (strcmp("rtbi", (const char *)prop) == 0)
278 clrsetbits_8(&bcsr_regs[7 + ucc_num],
279 BCSR_UCC_RGMII, BCSR_UCC_RTBI);
280 }
281
282 } else if (machine_is(p1021_mds)) {
283#define BCSR11_ENET_MICRST (0x1 << 5)
284 /* Reset Micrel PHY */
285 clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
286 setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
287 }
288
289 iounmap(bcsr_regs);
290 }
291 290
292 if (machine_is(p1021_mds)) { 291 if (machine_is(p1021_mds)) {
293#define MPC85xx_PMUXCR_OFFSET 0x60 292#define MPC85xx_PMUXCR_OFFSET 0x60
@@ -322,8 +321,72 @@ static void __init mpc85xx_mds_setup_arch(void)
322 } 321 }
323 322
324 } 323 }
324}
325
326static void __init mpc85xx_mds_qeic_init(void)
327{
328 struct device_node *np;
329
330 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
331 if (!of_device_is_available(np)) {
332 of_node_put(np);
333 return;
334 }
335
336 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
337 if (!np) {
338 np = of_find_node_by_type(NULL, "qeic");
339 if (!np)
340 return;
341 }
342
343 if (machine_is(p1021_mds))
344 qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
345 qe_ic_cascade_high_mpic);
346 else
347 qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
348 of_node_put(np);
349}
350#else
351static void __init mpc85xx_publish_qe_devices(void) { }
352static void __init mpc85xx_mds_qe_init(void) { }
353static void __init mpc85xx_mds_qeic_init(void) { }
325#endif /* CONFIG_QUICC_ENGINE */ 354#endif /* CONFIG_QUICC_ENGINE */
326 355
356static void __init mpc85xx_mds_setup_arch(void)
357{
358#ifdef CONFIG_PCI
359 struct pci_controller *hose;
360#endif
361 dma_addr_t max = 0xffffffff;
362
363 if (ppc_md.progress)
364 ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
365
366#ifdef CONFIG_PCI
367 for_each_node_by_type(np, "pci") {
368 if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
369 of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
370 struct resource rsrc;
371 of_address_to_resource(np, 0, &rsrc);
372 if ((rsrc.start & 0xfffff) == 0x8000)
373 fsl_add_bridge(np, 1);
374 else
375 fsl_add_bridge(np, 0);
376
377 hose = pci_find_hose_for_OF_device(np);
378 max = min(max, hose->dma_window_base_cur +
379 hose->dma_window_size);
380 }
381 }
382#endif
383
384#ifdef CONFIG_SMP
385 mpc85xx_smp_init();
386#endif
387
388 mpc85xx_mds_qe_init();
389
327#ifdef CONFIG_SWIOTLB 390#ifdef CONFIG_SWIOTLB
328 if (memblock_end_of_DRAM() > max) { 391 if (memblock_end_of_DRAM() > max) {
329 ppc_swiotlb_enable = 1; 392 ppc_swiotlb_enable = 1;
@@ -369,8 +432,6 @@ static struct of_device_id mpc85xx_ids[] = {
369 { .type = "soc", }, 432 { .type = "soc", },
370 { .compatible = "soc", }, 433 { .compatible = "soc", },
371 { .compatible = "simple-bus", }, 434 { .compatible = "simple-bus", },
372 { .type = "qe", },
373 { .compatible = "fsl,qe", },
374 { .compatible = "gianfar", }, 435 { .compatible = "gianfar", },
375 { .compatible = "fsl,rapidio-delta", }, 436 { .compatible = "fsl,rapidio-delta", },
376 { .compatible = "fsl,mpc8548-guts", }, 437 { .compatible = "fsl,mpc8548-guts", },
@@ -382,8 +443,6 @@ static struct of_device_id p1021_ids[] = {
382 { .type = "soc", }, 443 { .type = "soc", },
383 { .compatible = "soc", }, 444 { .compatible = "soc", },
384 { .compatible = "simple-bus", }, 445 { .compatible = "simple-bus", },
385 { .type = "qe", },
386 { .compatible = "fsl,qe", },
387 { .compatible = "gianfar", }, 446 { .compatible = "gianfar", },
388 {}, 447 {},
389}; 448};
@@ -395,16 +454,16 @@ static int __init mpc85xx_publish_devices(void)
395 if (machine_is(mpc8569_mds)) 454 if (machine_is(mpc8569_mds))
396 simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio"); 455 simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
397 456
398 /* Publish the QE devices */
399 of_platform_bus_probe(NULL, mpc85xx_ids, NULL); 457 of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
458 mpc85xx_publish_qe_devices();
400 459
401 return 0; 460 return 0;
402} 461}
403 462
404static int __init p1021_publish_devices(void) 463static int __init p1021_publish_devices(void)
405{ 464{
406 /* Publish the QE devices */
407 of_platform_bus_probe(NULL, p1021_ids, NULL); 465 of_platform_bus_probe(NULL, p1021_ids, NULL);
466 mpc85xx_publish_qe_devices();
408 467
409 return 0; 468 return 0;
410} 469}
@@ -441,21 +500,7 @@ static void __init mpc85xx_mds_pic_init(void)
441 of_node_put(np); 500 of_node_put(np);
442 501
443 mpic_init(mpic); 502 mpic_init(mpic);
444 503 mpc85xx_mds_qeic_init();
445#ifdef CONFIG_QUICC_ENGINE
446 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
447 if (!np) {
448 np = of_find_node_by_type(NULL, "qeic");
449 if (!np)
450 return;
451 }
452 if (machine_is(p1021_mds))
453 qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
454 qe_ic_cascade_high_mpic);
455 else
456 qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
457 of_node_put(np);
458#endif /* CONFIG_QUICC_ENGINE */
459} 504}
460 505
461static int __init mpc85xx_mds_probe(void) 506static int __init mpc85xx_mds_probe(void)
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
new file mode 100644
index 000000000000..e1467c937450
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -0,0 +1,148 @@
1/*
2 * P1022DS board specific routines
3 *
4 * Authors: Travis Wheatley <travis.wheatley@freescale.com>
5 * Dave Liu <daveliu@freescale.com>
6 * Timur Tabi <timur@freescale.com>
7 *
8 * Copyright 2010 Freescale Semiconductor, Inc.
9 *
10 * This file is taken from the Freescale P1022DS BSP, with modifications:
11 * 1) No DIU support (pending rewrite of DIU code)
12 * 2) No AMP support
13 * 3) No PCI endpoint support
14 *
15 * This file is licensed under the terms of the GNU General Public License
16 * version 2. This program is licensed "as is" without any warranty of any
17 * kind, whether express or implied.
18 */
19
20#include <linux/pci.h>
21#include <linux/of_platform.h>
22#include <linux/lmb.h>
23
24#include <asm/mpic.h>
25#include <asm/swiotlb.h>
26
27#include <sysdev/fsl_soc.h>
28#include <sysdev/fsl_pci.h>
29
30void __init p1022_ds_pic_init(void)
31{
32 struct mpic *mpic;
33 struct resource r;
34 struct device_node *np;
35
36 np = of_find_node_by_type(NULL, "open-pic");
37 if (!np) {
38 pr_err("Could not find open-pic node\n");
39 return;
40 }
41
42 if (of_address_to_resource(np, 0, &r)) {
43 pr_err("Failed to map mpic register space\n");
44 of_node_put(np);
45 return;
46 }
47
48 mpic = mpic_alloc(np, r.start,
49 MPIC_PRIMARY | MPIC_WANTS_RESET |
50 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
51 MPIC_SINGLE_DEST_CPU,
52 0, 256, " OpenPIC ");
53
54 BUG_ON(mpic == NULL);
55 of_node_put(np);
56
57 mpic_init(mpic);
58}
59
60#ifdef CONFIG_SMP
61void __init mpc85xx_smp_init(void);
62#endif
63
64/*
65 * Setup the architecture
66 */
67static void __init p1022_ds_setup_arch(void)
68{
69#ifdef CONFIG_PCI
70 struct device_node *np;
71#endif
72 dma_addr_t max = 0xffffffff;
73
74 if (ppc_md.progress)
75 ppc_md.progress("p1022_ds_setup_arch()", 0);
76
77#ifdef CONFIG_PCI
78 for_each_compatible_node(np, "pci", "fsl,p1022-pcie") {
79 struct resource rsrc;
80 struct pci_controller *hose;
81
82 of_address_to_resource(np, 0, &rsrc);
83
84 if ((rsrc.start & 0xfffff) == 0x8000)
85 fsl_add_bridge(np, 1);
86 else
87 fsl_add_bridge(np, 0);
88
89 hose = pci_find_hose_for_OF_device(np);
90 max = min(max, hose->dma_window_base_cur +
91 hose->dma_window_size);
92 }
93#endif
94
95#ifdef CONFIG_SMP
96 mpc85xx_smp_init();
97#endif
98
99#ifdef CONFIG_SWIOTLB
100 if (lmb_end_of_DRAM() > max) {
101 ppc_swiotlb_enable = 1;
102 set_pci_dma_ops(&swiotlb_dma_ops);
103 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
104 }
105#endif
106
107 pr_info("Freescale P1022 DS reference board\n");
108}
109
110static struct of_device_id __initdata p1022_ds_ids[] = {
111 { .type = "soc", },
112 { .compatible = "soc", },
113 { .compatible = "simple-bus", },
114 { .compatible = "gianfar", },
115 {},
116};
117
118static int __init p1022_ds_publish_devices(void)
119{
120 return of_platform_bus_probe(NULL, p1022_ds_ids, NULL);
121}
122machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
123
124machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
125
126/*
127 * Called very early, device-tree isn't unflattened
128 */
129static int __init p1022_ds_probe(void)
130{
131 unsigned long root = of_get_flat_dt_root();
132
133 return of_flat_dt_is_compatible(root, "fsl,p1022ds");
134}
135
136define_machine(p1022_ds) {
137 .name = "P1022 DS",
138 .probe = p1022_ds_probe,
139 .setup_arch = p1022_ds_setup_arch,
140 .init_IRQ = p1022_ds_pic_init,
141#ifdef CONFIG_PCI
142 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
143#endif
144 .get_irq = mpic_get_irq,
145 .restart = fsl_rstcr_restart,
146 .calibrate_decr = generic_calibrate_decr,
147 .progress = udbg_progress,
148};
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index a15f582300d8..a6b106557be4 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -15,6 +15,7 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/of.h> 17#include <linux/of.h>
18#include <linux/kexec.h>
18 19
19#include <asm/machdep.h> 20#include <asm/machdep.h>
20#include <asm/pgtable.h> 21#include <asm/pgtable.h>
@@ -24,6 +25,7 @@
24#include <asm/dbell.h> 25#include <asm/dbell.h>
25 26
26#include <sysdev/fsl_soc.h> 27#include <sysdev/fsl_soc.h>
28#include <sysdev/mpic.h>
27 29
28extern void __early_start(void); 30extern void __early_start(void);
29 31
@@ -99,12 +101,70 @@ static void __init
99smp_85xx_setup_cpu(int cpu_nr) 101smp_85xx_setup_cpu(int cpu_nr)
100{ 102{
101 mpic_setup_this_cpu(); 103 mpic_setup_this_cpu();
104 if (cpu_has_feature(CPU_FTR_DBELL))
105 doorbell_setup_this_cpu();
102} 106}
103 107
104struct smp_ops_t smp_85xx_ops = { 108struct smp_ops_t smp_85xx_ops = {
105 .kick_cpu = smp_85xx_kick_cpu, 109 .kick_cpu = smp_85xx_kick_cpu,
110#ifdef CONFIG_KEXEC
111 .give_timebase = smp_generic_give_timebase,
112 .take_timebase = smp_generic_take_timebase,
113#endif
106}; 114};
107 115
116#ifdef CONFIG_KEXEC
117static int kexec_down_cpus = 0;
118
119void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
120{
121 mpic_teardown_this_cpu(1);
122
123 /* When crashing, this gets called on all CPU's we only
124 * take down the non-boot cpus */
125 if (smp_processor_id() != boot_cpuid)
126 {
127 local_irq_disable();
128 kexec_down_cpus++;
129
130 while (1);
131 }
132}
133
134static void mpc85xx_smp_kexec_down(void *arg)
135{
136 if (ppc_md.kexec_cpu_down)
137 ppc_md.kexec_cpu_down(0,1);
138}
139
140static void mpc85xx_smp_machine_kexec(struct kimage *image)
141{
142 int timeout = 2000;
143 int i;
144
145 set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
146
147 smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
148
149 while ( (kexec_down_cpus != (num_online_cpus() - 1)) &&
150 ( timeout > 0 ) )
151 {
152 timeout--;
153 }
154
155 if ( !timeout )
156 printk(KERN_ERR "Unable to bring down secondary cpu(s)");
157
158 for (i = 0; i < num_present_cpus(); i++)
159 {
160 if ( i == smp_processor_id() ) continue;
161 mpic_reset_core(i);
162 }
163
164 default_machine_kexec(image);
165}
166#endif /* CONFIG_KEXEC */
167
108void __init mpc85xx_smp_init(void) 168void __init mpc85xx_smp_init(void)
109{ 169{
110 struct device_node *np; 170 struct device_node *np;
@@ -117,9 +177,14 @@ void __init mpc85xx_smp_init(void)
117 } 177 }
118 178
119 if (cpu_has_feature(CPU_FTR_DBELL)) 179 if (cpu_has_feature(CPU_FTR_DBELL))
120 smp_85xx_ops.message_pass = smp_dbell_message_pass; 180 smp_85xx_ops.message_pass = doorbell_message_pass;
121 181
122 BUG_ON(!smp_85xx_ops.message_pass); 182 BUG_ON(!smp_85xx_ops.message_pass);
123 183
124 smp_ops = &smp_85xx_ops; 184 smp_ops = &smp_85xx_ops;
185
186#ifdef CONFIG_KEXEC
187 ppc_md.kexec_cpu_down = mpc85xx_smp_kexec_cpu_down;
188 ppc_md.machine_kexec = mpc85xx_smp_machine_kexec;
189#endif
125} 190}
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 5b0ab9966e90..8f29bbce5360 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -151,6 +151,27 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m)
151 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); 151 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
152} 152}
153 153
154static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev)
155{
156 unsigned int val;
157
158 /* Do not do the fixup on other platforms! */
159 if (!machine_is(tqm85xx))
160 return;
161
162 dev_info(&pdev->dev, "Using TI 1520 fixup on TQM85xx\n");
163
164 /*
165 * Enable P2CCLK bit in system control register
166 * to enable CLOCK output to power chip
167 */
168 pci_read_config_dword(pdev, 0x80, &val);
169 pci_write_config_dword(pdev, 0x80, val | (1 << 27));
170
171}
172DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520,
173 tqm85xx_ti1520_fixup);
174
154static struct of_device_id __initdata of_bus_ids[] = { 175static struct of_device_id __initdata of_bus_ids[] = {
155 { .compatible = "simple-bus", }, 176 { .compatible = "simple-bus", },
156 { .compatible = "gianfar", }, 177 { .compatible = "gianfar", },
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index 48a920a98e7b..dd35ce081cff 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -55,6 +55,12 @@ config PPC_MGSUVD
55 help 55 help
56 This enables support for the Keymile MGSUVD board. 56 This enables support for the Keymile MGSUVD board.
57 57
58config TQM8XX
59 bool "TQM8XX"
60 select CPM1
61 help
62 support for the mpc8xx based boards from TQM.
63
58endchoice 64endchoice
59 65
60menu "Freescale Ethernet driver platform-specific options" 66menu "Freescale Ethernet driver platform-specific options"
diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile
index bdbfd7496018..a491fe6b94fc 100644
--- a/arch/powerpc/platforms/8xx/Makefile
+++ b/arch/powerpc/platforms/8xx/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o
7obj-$(CONFIG_PPC_EP88XC) += ep88xc.o 7obj-$(CONFIG_PPC_EP88XC) += ep88xc.o
8obj-$(CONFIG_PPC_ADDER875) += adder875.o 8obj-$(CONFIG_PPC_ADDER875) += adder875.o
9obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o 9obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o
10obj-$(CONFIG_TQM8XX) += tqm8xx_setup.o
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
new file mode 100644
index 000000000000..b71c650fbb11
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
@@ -0,0 +1,156 @@
1/*
2 * Platform setup for the MPC8xx based boards from TQM.
3 *
4 * Heiko Schocher <hs@denx.de>
5 * Copyright 2010 DENX Software Engineering GmbH
6 *
7 * based on:
8 * Vitaly Bordug <vbordug@ru.mvista.com>
9 *
10 * Copyright 2005 MontaVista Software Inc.
11 *
12 * Heavily modified by Scott Wood <scottwood@freescale.com>
13 * Copyright 2007 Freescale Semiconductor, Inc.
14 *
15 * This file is licensed under the terms of the GNU General Public License
16 * version 2. This program is licensed "as is" without any warranty of any
17 * kind, whether express or implied.
18 */
19
20#include <linux/init.h>
21#include <linux/module.h>
22#include <linux/param.h>
23#include <linux/string.h>
24#include <linux/ioport.h>
25#include <linux/device.h>
26#include <linux/delay.h>
27
28#include <linux/fs_enet_pd.h>
29#include <linux/fs_uart_pd.h>
30#include <linux/fsl_devices.h>
31#include <linux/mii.h>
32#include <linux/of_platform.h>
33
34#include <asm/delay.h>
35#include <asm/io.h>
36#include <asm/machdep.h>
37#include <asm/page.h>
38#include <asm/processor.h>
39#include <asm/system.h>
40#include <asm/time.h>
41#include <asm/mpc8xx.h>
42#include <asm/8xx_immap.h>
43#include <asm/cpm1.h>
44#include <asm/fs_pd.h>
45#include <asm/udbg.h>
46
47#include "mpc8xx.h"
48
49struct cpm_pin {
50 int port, pin, flags;
51};
52
53static struct __initdata cpm_pin tqm8xx_pins[] = {
54 /* SMC1 */
55 {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
56 {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
57
58 /* SCC1 */
59 {CPM_PORTA, 5, CPM_PIN_INPUT}, /* CLK1 */
60 {CPM_PORTA, 7, CPM_PIN_INPUT}, /* CLK2 */
61 {CPM_PORTA, 14, CPM_PIN_INPUT}, /* TX */
62 {CPM_PORTA, 15, CPM_PIN_INPUT}, /* RX */
63 {CPM_PORTC, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TENA */
64 {CPM_PORTC, 10, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO},
65 {CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO},
66};
67
68static struct __initdata cpm_pin tqm8xx_fec_pins[] = {
69 /* MII */
70 {CPM_PORTD, 3, CPM_PIN_OUTPUT},
71 {CPM_PORTD, 4, CPM_PIN_OUTPUT},
72 {CPM_PORTD, 5, CPM_PIN_OUTPUT},
73 {CPM_PORTD, 6, CPM_PIN_OUTPUT},
74 {CPM_PORTD, 7, CPM_PIN_OUTPUT},
75 {CPM_PORTD, 8, CPM_PIN_OUTPUT},
76 {CPM_PORTD, 9, CPM_PIN_OUTPUT},
77 {CPM_PORTD, 10, CPM_PIN_OUTPUT},
78 {CPM_PORTD, 11, CPM_PIN_OUTPUT},
79 {CPM_PORTD, 12, CPM_PIN_OUTPUT},
80 {CPM_PORTD, 13, CPM_PIN_OUTPUT},
81 {CPM_PORTD, 14, CPM_PIN_OUTPUT},
82 {CPM_PORTD, 15, CPM_PIN_OUTPUT},
83};
84
85static void __init init_pins(int n, struct cpm_pin *pin)
86{
87 int i;
88
89 for (i = 0; i < n; i++) {
90 cpm1_set_pin(pin->port, pin->pin, pin->flags);
91 pin++;
92 }
93}
94
95static void __init init_ioports(void)
96{
97 struct device_node *dnode;
98 struct property *prop;
99 int len;
100
101 init_pins(ARRAY_SIZE(tqm8xx_pins), &tqm8xx_pins[0]);
102
103 cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
104
105 dnode = of_find_node_by_name(NULL, "aliases");
106 if (dnode == NULL)
107 return;
108 prop = of_find_property(dnode, "ethernet1", &len);
109 if (prop == NULL)
110 return;
111
112 /* init FEC pins */
113 init_pins(ARRAY_SIZE(tqm8xx_fec_pins), &tqm8xx_fec_pins[0]);
114}
115
116static void __init tqm8xx_setup_arch(void)
117{
118 cpm_reset();
119 init_ioports();
120}
121
122static int __init tqm8xx_probe(void)
123{
124 unsigned long node = of_get_flat_dt_root();
125
126 return of_flat_dt_is_compatible(node, "tqc,tqm8xx");
127}
128
129static struct of_device_id __initdata of_bus_ids[] = {
130 { .name = "soc", },
131 { .name = "cpm", },
132 { .name = "localbus", },
133 { .compatible = "simple-bus" },
134 {},
135};
136
137static int __init declare_of_platform_devices(void)
138{
139 of_platform_bus_probe(NULL, of_bus_ids, NULL);
140
141 return 0;
142}
143machine_device_initcall(tqm8xx, declare_of_platform_devices);
144
145define_machine(tqm8xx) {
146 .name = "TQM8xx",
147 .probe = tqm8xx_probe,
148 .setup_arch = tqm8xx_setup_arch,
149 .init_IRQ = mpc8xx_pics_init,
150 .get_irq = mpc8xx_get_irq,
151 .restart = mpc8xx_restart,
152 .calibrate_decr = mpc8xx_calibrate_decr,
153 .set_rtc_time = mpc8xx_set_rtc_time,
154 .get_rtc_time = mpc8xx_get_rtc_time,
155 .progress = udbg_progress,
156};
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 00b6730bc48f..b6db7cef83b4 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -87,12 +87,11 @@ static struct device_node *new_node(const char *path,
87 87
88 if (!np) 88 if (!np)
89 return NULL; 89 return NULL;
90 np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL); 90 np->full_name = kstrdup(path, GFP_KERNEL);
91 if (!np->full_name) { 91 if (!np->full_name) {
92 kfree(np); 92 kfree(np);
93 return NULL; 93 return NULL;
94 } 94 }
95 strcpy(np->full_name, path);
96 of_node_set_flag(np, OF_DYNAMIC); 95 of_node_set_flag(np, OF_DYNAMIC);
97 kref_init(&np->kref); 96 kref_init(&np->kref);
98 np->parent = of_node_get(parent); 97 np->parent = of_node_get(parent);
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 1e9eba175ff0..415ca6d6b273 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -310,8 +310,12 @@ static int pmu_set_cpu_speed(int low_speed)
310 /* Restore low level PMU operations */ 310 /* Restore low level PMU operations */
311 pmu_unlock(); 311 pmu_unlock();
312 312
313 /* Restore decrementer */ 313 /*
314 wakeup_decrementer(); 314 * Restore decrementer; we'll take a decrementer interrupt
315 * as soon as interrupts are re-enabled and the generic
316 * clockevents code will reprogram it with the right value.
317 */
318 set_dec(1);
315 319
316 /* Restore interrupts */ 320 /* Restore interrupts */
317 mpic_cpu_set_priority(pic_prio); 321 mpic_cpu_set_priority(pic_prio);
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 75eec031e7a2..39df6ab1735a 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2193,7 +2193,11 @@ static struct pmac_mb_def pmac_mb_defs[] = {
2193 PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 2193 PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2194 PMAC_MB_MAY_SLEEP, 2194 PMAC_MB_MAY_SLEEP,
2195 }, 2195 },
2196 { "iMac,1", "iMac (first generation)", 2196 { "PowerMac10,2", "Mac mini (Late 2005)",
2197 PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2198 PMAC_MB_MAY_SLEEP,
2199 },
2200 { "iMac,1", "iMac (first generation)",
2197 PMAC_TYPE_ORIG_IMAC, paddington_features, 2201 PMAC_TYPE_ORIG_IMAC, paddington_features,
2198 0 2202 0
2199 }, 2203 },
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 2c0ed87f2024..3124cf791ebb 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -136,7 +136,7 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
136 * As lv1_read_htab_entries() does not give us the RPN, we can 136 * As lv1_read_htab_entries() does not give us the RPN, we can
137 * not synthesize the new hpte_r value here, and therefore can 137 * not synthesize the new hpte_r value here, and therefore can
138 * not update the hpte with lv1_insert_htab_entry(), so we 138 * not update the hpte with lv1_insert_htab_entry(), so we
139 * insted invalidate it and ask the caller to update it via 139 * instead invalidate it and ask the caller to update it via
140 * ps3_hpte_insert() by returning a -1 value. 140 * ps3_hpte_insert() by returning a -1 value.
141 */ 141 */
142 if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { 142 if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 3dbef309bc8d..046ace9c4381 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -26,3 +26,7 @@ obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
26obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o 26obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
27obj-$(CONFIG_CMM) += cmm.o 27obj-$(CONFIG_CMM) += cmm.o
28obj-$(CONFIG_DTL) += dtl.o 28obj-$(CONFIG_DTL) += dtl.o
29
30ifeq ($(CONFIG_PPC_PSERIES),y)
31obj-$(CONFIG_SUSPEND) += suspend.o
32endif
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index d71e58584086..227c1c3d585e 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -463,6 +463,7 @@ static int dlpar_offline_cpu(struct device_node *dn)
463 break; 463 break;
464 464
465 if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { 465 if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) {
466 set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
466 cpu_maps_update_done(); 467 cpu_maps_update_done();
467 rc = cpu_down(cpu); 468 rc = cpu_down(cpu);
468 if (rc) 469 if (rc)
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index 30b987b73c20..8ed0d2d0e1b5 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -288,8 +288,7 @@ void __init pci_addr_cache_build(void)
288 288
289 spin_lock_init(&pci_io_addr_cache_root.piar_lock); 289 spin_lock_init(&pci_io_addr_cache_root.piar_lock);
290 290
291 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 291 for_each_pci_dev(dev) {
292
293 pci_addr_cache_insert_device(dev); 292 pci_addr_cache_insert_device(dev);
294 293
295 dn = pci_device_to_OF_node(dev); 294 dn = pci_device_to_OF_node(dev);
diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c
index e889c9d9586a..2605c310166a 100644
--- a/arch/powerpc/platforms/pseries/event_sources.c
+++ b/arch/powerpc/platforms/pseries/event_sources.c
@@ -41,9 +41,12 @@ void request_event_sources_irqs(struct device_node *np,
41 if (count > 15) 41 if (count > 15)
42 break; 42 break;
43 virqs[count] = irq_create_mapping(NULL, *(opicprop++)); 43 virqs[count] = irq_create_mapping(NULL, *(opicprop++));
44 if (virqs[count] == NO_IRQ) 44 if (virqs[count] == NO_IRQ) {
45 printk(KERN_ERR "Unable to allocate interrupt " 45 pr_err("event-sources: Unable to allocate "
46 "number for %s\n", np->full_name); 46 "interrupt number for %s\n",
47 np->full_name);
48 WARN_ON(1);
49 }
47 else 50 else
48 count++; 51 count++;
49 52
@@ -59,9 +62,12 @@ void request_event_sources_irqs(struct device_node *np,
59 virqs[count] = irq_create_of_mapping(oirq.controller, 62 virqs[count] = irq_create_of_mapping(oirq.controller,
60 oirq.specifier, 63 oirq.specifier,
61 oirq.size); 64 oirq.size);
62 if (virqs[count] == NO_IRQ) 65 if (virqs[count] == NO_IRQ) {
63 printk(KERN_ERR "Unable to allocate interrupt " 66 pr_err("event-sources: Unable to allocate "
64 "number for %s\n", np->full_name); 67 "interrupt number for %s\n",
68 np->full_name);
69 WARN_ON(1);
70 }
65 else 71 else
66 count++; 72 count++;
67 } 73 }
@@ -70,8 +76,9 @@ void request_event_sources_irqs(struct device_node *np,
70 /* Now request them */ 76 /* Now request them */
71 for (i = 0; i < count; i++) { 77 for (i = 0; i < count; i++) {
72 if (request_irq(virqs[i], handler, 0, name, NULL)) { 78 if (request_irq(virqs[i], handler, 0, name, NULL)) {
73 printk(KERN_ERR "Unable to request interrupt %d for " 79 pr_err("event-sources: Unable to request interrupt "
74 "%s\n", virqs[i], np->full_name); 80 "%d for %s\n", virqs[i], np->full_name);
81 WARN_ON(1);
75 return; 82 return;
76 } 83 }
77 } 84 }
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 8f85f399ab9f..fd50ccd4bac1 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -116,6 +116,9 @@ static void pseries_mach_cpu_die(void)
116 116
117 if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { 117 if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
118 set_cpu_current_state(cpu, CPU_STATE_INACTIVE); 118 set_cpu_current_state(cpu, CPU_STATE_INACTIVE);
119 if (ppc_md.suspend_disable_cpu)
120 ppc_md.suspend_disable_cpu();
121
119 cede_latency_hint = 2; 122 cede_latency_hint = 2;
120 123
121 get_lppaca()->idle = 1; 124 get_lppaca()->idle = 1;
@@ -190,12 +193,12 @@ static void pseries_cpu_die(unsigned int cpu)
190 193
191 if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) { 194 if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
192 cpu_status = 1; 195 cpu_status = 1;
193 for (tries = 0; tries < 1000; tries++) { 196 for (tries = 0; tries < 5000; tries++) {
194 if (get_cpu_current_state(cpu) == CPU_STATE_INACTIVE) { 197 if (get_cpu_current_state(cpu) == CPU_STATE_INACTIVE) {
195 cpu_status = 0; 198 cpu_status = 0;
196 break; 199 break;
197 } 200 }
198 cpu_relax(); 201 msleep(1);
199 } 202 }
200 } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) { 203 } else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) {
201 204
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index deab5f946090..bc8803664140 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -69,7 +69,7 @@ static int pseries_remove_memory(struct device_node *np)
69 const char *type; 69 const char *type;
70 const unsigned int *regs; 70 const unsigned int *regs;
71 unsigned long base; 71 unsigned long base;
72 unsigned int memblock_size; 72 unsigned int lmb_size;
73 int ret = -EINVAL; 73 int ret = -EINVAL;
74 74
75 /* 75 /*
@@ -87,9 +87,9 @@ static int pseries_remove_memory(struct device_node *np)
87 return ret; 87 return ret;
88 88
89 base = *(unsigned long *)regs; 89 base = *(unsigned long *)regs;
90 memblock_size = regs[3]; 90 lmb_size = regs[3];
91 91
92 ret = pseries_remove_memblock(base, memblock_size); 92 ret = pseries_remove_memblock(base, lmb_size);
93 return ret; 93 return ret;
94} 94}
95 95
@@ -98,7 +98,7 @@ static int pseries_add_memory(struct device_node *np)
98 const char *type; 98 const char *type;
99 const unsigned int *regs; 99 const unsigned int *regs;
100 unsigned long base; 100 unsigned long base;
101 unsigned int memblock_size; 101 unsigned int lmb_size;
102 int ret = -EINVAL; 102 int ret = -EINVAL;
103 103
104 /* 104 /*
@@ -116,36 +116,36 @@ static int pseries_add_memory(struct device_node *np)
116 return ret; 116 return ret;
117 117
118 base = *(unsigned long *)regs; 118 base = *(unsigned long *)regs;
119 memblock_size = regs[3]; 119 lmb_size = regs[3];
120 120
121 /* 121 /*
122 * Update memory region to represent the memory add 122 * Update memory region to represent the memory add
123 */ 123 */
124 ret = memblock_add(base, memblock_size); 124 ret = memblock_add(base, lmb_size);
125 return (ret < 0) ? -EINVAL : 0; 125 return (ret < 0) ? -EINVAL : 0;
126} 126}
127 127
128static int pseries_drconf_memory(unsigned long *base, unsigned int action) 128static int pseries_drconf_memory(unsigned long *base, unsigned int action)
129{ 129{
130 struct device_node *np; 130 struct device_node *np;
131 const unsigned long *memblock_size; 131 const unsigned long *lmb_size;
132 int rc; 132 int rc;
133 133
134 np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); 134 np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
135 if (!np) 135 if (!np)
136 return -EINVAL; 136 return -EINVAL;
137 137
138 memblock_size = of_get_property(np, "ibm,memblock-size", NULL); 138 lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
139 if (!memblock_size) { 139 if (!lmb_size) {
140 of_node_put(np); 140 of_node_put(np);
141 return -EINVAL; 141 return -EINVAL;
142 } 142 }
143 143
144 if (action == PSERIES_DRCONF_MEM_ADD) { 144 if (action == PSERIES_DRCONF_MEM_ADD) {
145 rc = memblock_add(*base, *memblock_size); 145 rc = memblock_add(*base, *lmb_size);
146 rc = (rc < 0) ? -EINVAL : 0; 146 rc = (rc < 0) ? -EINVAL : 0;
147 } else if (action == PSERIES_DRCONF_MEM_REMOVE) { 147 } else if (action == PSERIES_DRCONF_MEM_REMOVE) {
148 rc = pseries_remove_memblock(*base, *memblock_size); 148 rc = pseries_remove_memblock(*base, *lmb_size);
149 } else { 149 } else {
150 rc = -EINVAL; 150 rc = -EINVAL;
151 } 151 }
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 41a3e9a039ed..a4fc6da87c2e 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -61,7 +61,6 @@ static int ras_check_exception_token;
61 61
62#define EPOW_SENSOR_TOKEN 9 62#define EPOW_SENSOR_TOKEN 9
63#define EPOW_SENSOR_INDEX 0 63#define EPOW_SENSOR_INDEX 0
64#define RAS_VECTOR_OFFSET 0x500
65 64
66static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); 65static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
67static irqreturn_t ras_error_interrupt(int irq, void *dev_id); 66static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
@@ -121,7 +120,7 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
121 spin_lock(&ras_log_buf_lock); 120 spin_lock(&ras_log_buf_lock);
122 121
123 status = rtas_call(ras_check_exception_token, 6, 1, NULL, 122 status = rtas_call(ras_check_exception_token, 6, 1, NULL,
124 RAS_VECTOR_OFFSET, 123 RTAS_VECTOR_EXTERNAL_INTERRUPT,
125 irq_map[irq].hwirq, 124 irq_map[irq].hwirq,
126 RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, 125 RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
127 critical, __pa(&ras_log_buf), 126 critical, __pa(&ras_log_buf),
@@ -156,7 +155,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
156 spin_lock(&ras_log_buf_lock); 155 spin_lock(&ras_log_buf_lock);
157 156
158 status = rtas_call(ras_check_exception_token, 6, 1, NULL, 157 status = rtas_call(ras_check_exception_token, 6, 1, NULL,
159 RAS_VECTOR_OFFSET, 158 RTAS_VECTOR_EXTERNAL_INTERRUPT,
160 irq_map[irq].hwirq, 159 irq_map[irq].hwirq,
161 RTAS_INTERNAL_ERROR, 1 /*Time Critical */, 160 RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
162 __pa(&ras_log_buf), 161 __pa(&ras_log_buf),
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 1a58637bcea5..57ddbb43b33a 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -118,12 +118,10 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
118 if (!np) 118 if (!np)
119 goto out_err; 119 goto out_err;
120 120
121 np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL); 121 np->full_name = kstrdup(path, GFP_KERNEL);
122 if (!np->full_name) 122 if (!np->full_name)
123 goto out_err; 123 goto out_err;
124 124
125 strcpy(np->full_name, path);
126
127 np->properties = proplist; 125 np->properties = proplist;
128 of_node_set_flag(np, OF_DYNAMIC); 126 of_node_set_flag(np, OF_DYNAMIC);
129 kref_init(&np->kref); 127 kref_init(&np->kref);
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c
new file mode 100644
index 000000000000..ed72098bb4e3
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/suspend.c
@@ -0,0 +1,214 @@
1/*
2 * Copyright (C) 2010 Brian King IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/delay.h>
20#include <linux/suspend.h>
21#include <asm/firmware.h>
22#include <asm/hvcall.h>
23#include <asm/machdep.h>
24#include <asm/mmu.h>
25#include <asm/rtas.h>
26
27static u64 stream_id;
28static struct sys_device suspend_sysdev;
29static DECLARE_COMPLETION(suspend_work);
30static struct rtas_suspend_me_data suspend_data;
31static atomic_t suspending;
32
33/**
34 * pseries_suspend_begin - First phase of hibernation
35 *
36 * Check to ensure we are in a valid state to hibernate
37 *
38 * Return value:
39 * 0 on success / other on failure
40 **/
41static int pseries_suspend_begin(suspend_state_t state)
42{
43 long vasi_state, rc;
44 unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
45
46 /* Make sure the state is valid */
47 rc = plpar_hcall(H_VASI_STATE, retbuf, stream_id);
48
49 vasi_state = retbuf[0];
50
51 if (rc) {
52 pr_err("pseries_suspend_begin: vasi_state returned %ld\n",rc);
53 return rc;
54 } else if (vasi_state == H_VASI_ENABLED) {
55 return -EAGAIN;
56 } else if (vasi_state != H_VASI_SUSPENDING) {
57 pr_err("pseries_suspend_begin: vasi_state returned state %ld\n",
58 vasi_state);
59 return -EIO;
60 }
61
62 return 0;
63}
64
65/**
66 * pseries_suspend_cpu - Suspend a single CPU
67 *
68 * Makes the H_JOIN call to suspend the CPU
69 *
70 **/
71static int pseries_suspend_cpu(void)
72{
73 if (atomic_read(&suspending))
74 return rtas_suspend_cpu(&suspend_data);
75 return 0;
76}
77
78/**
79 * pseries_suspend_enter - Final phase of hibernation
80 *
81 * Return value:
82 * 0 on success / other on failure
83 **/
84static int pseries_suspend_enter(suspend_state_t state)
85{
86 int rc = rtas_suspend_last_cpu(&suspend_data);
87
88 atomic_set(&suspending, 0);
89 atomic_set(&suspend_data.done, 1);
90 return rc;
91}
92
93/**
94 * pseries_prepare_late - Prepare to suspend all other CPUs
95 *
96 * Return value:
97 * 0 on success / other on failure
98 **/
99static int pseries_prepare_late(void)
100{
101 atomic_set(&suspending, 1);
102 atomic_set(&suspend_data.working, 0);
103 atomic_set(&suspend_data.done, 0);
104 atomic_set(&suspend_data.error, 0);
105 suspend_data.complete = &suspend_work;
106 INIT_COMPLETION(suspend_work);
107 return 0;
108}
109
110/**
111 * store_hibernate - Initiate partition hibernation
112 * @classdev: sysdev class struct
113 * @attr: class device attribute struct
114 * @buf: buffer
115 * @count: buffer size
116 *
117 * Write the stream ID received from the HMC to this file
118 * to trigger hibernating the partition
119 *
120 * Return value:
121 * number of bytes printed to buffer / other on failure
122 **/
123static ssize_t store_hibernate(struct sysdev_class *classdev,
124 struct sysdev_class_attribute *attr,
125 const char *buf, size_t count)
126{
127 int rc;
128
129 if (!capable(CAP_SYS_ADMIN))
130 return -EPERM;
131
132 stream_id = simple_strtoul(buf, NULL, 16);
133
134 do {
135 rc = pseries_suspend_begin(PM_SUSPEND_MEM);
136 if (rc == -EAGAIN)
137 ssleep(1);
138 } while (rc == -EAGAIN);
139
140 if (!rc)
141 rc = pm_suspend(PM_SUSPEND_MEM);
142
143 stream_id = 0;
144
145 if (!rc)
146 rc = count;
147 return rc;
148}
149
150static SYSDEV_CLASS_ATTR(hibernate, S_IWUSR, NULL, store_hibernate);
151
152static struct sysdev_class suspend_sysdev_class = {
153 .name = "power",
154};
155
156static struct platform_suspend_ops pseries_suspend_ops = {
157 .valid = suspend_valid_only_mem,
158 .begin = pseries_suspend_begin,
159 .prepare_late = pseries_prepare_late,
160 .enter = pseries_suspend_enter,
161};
162
163/**
164 * pseries_suspend_sysfs_register - Register with sysfs
165 *
166 * Return value:
167 * 0 on success / other on failure
168 **/
169static int pseries_suspend_sysfs_register(struct sys_device *sysdev)
170{
171 int rc;
172
173 if ((rc = sysdev_class_register(&suspend_sysdev_class)))
174 return rc;
175
176 sysdev->id = 0;
177 sysdev->cls = &suspend_sysdev_class;
178
179 if ((rc = sysdev_class_create_file(&suspend_sysdev_class, &attr_hibernate)))
180 goto class_unregister;
181
182 return 0;
183
184class_unregister:
185 sysdev_class_unregister(&suspend_sysdev_class);
186 return rc;
187}
188
189/**
190 * pseries_suspend_init - initcall for pSeries suspend
191 *
192 * Return value:
193 * 0 on success / other on failure
194 **/
195static int __init pseries_suspend_init(void)
196{
197 int rc;
198
199 if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR))
200 return 0;
201
202 suspend_data.token = rtas_token("ibm,suspend-me");
203 if (suspend_data.token == RTAS_UNKNOWN_SERVICE)
204 return 0;
205
206 if ((rc = pseries_suspend_sysfs_register(&suspend_sysdev)))
207 return rc;
208
209 ppc_md.suspend_disable_cpu = pseries_suspend_cpu;
210 suspend_set_ops(&pseries_suspend_ops);
211 return 0;
212}
213
214__initcall(pseries_suspend_init);
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index f19d19468393..5b22b07c8f67 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -549,8 +549,6 @@ static irqreturn_t xics_ipi_dispatch(int cpu)
549{ 549{
550 unsigned long *tgt = &per_cpu(xics_ipi_message, cpu); 550 unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
551 551
552 WARN_ON(cpu_is_offline(cpu));
553
554 mb(); /* order mmio clearing qirr */ 552 mb(); /* order mmio clearing qirr */
555 while (*tgt) { 553 while (*tgt) {
556 if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) { 554 if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) {