diff options
Diffstat (limited to 'arch/powerpc/platforms')
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 @@ | |||
1 | config PPC_MPC512x | 1 | config 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 | ||
9 | config PPC_MPC5121 | ||
10 | bool | ||
11 | select PPC_MPC512x | ||
12 | |||
13 | config MPC5121_ADS | 10 | config 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 | ||
22 | config MPC5121_GENERIC | 18 | config 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 | |||
29 | config 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 @@ | |||
4 | obj-y += clock.o mpc512x_shared.o | 4 | obj-y += clock.o mpc512x_shared.o |
5 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o | 5 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o |
6 | obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o | 6 | obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o |
7 | obj-$(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 | ||
295 | static 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 | |||
295 | static void half_clk_calc(struct clk *clk) | 304 | static 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 | ||
424 | static 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 | |||
415 | static struct clk axe_clk = { | 432 | static 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 | ||
47 | static void __init mpc5121_ads_init_IRQ(void) | 48 | static 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); | |||
16 | extern int __init mpc5121_clk_init(void); | 16 | extern int __init mpc5121_clk_init(void); |
17 | void __init mpc512x_declare_of_platform_devices(void); | 17 | void __init mpc512x_declare_of_platform_devices(void); |
18 | extern void mpc512x_restart(char *cmd); | 18 | extern void mpc512x_restart(char *cmd); |
19 | extern void mpc512x_init_diu(void); | ||
20 | extern 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 | ||
61 | struct 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 | |||
69 | unsigned 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 | |||
83 | void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | void mpc512x_set_monitor_port(int monitor_port) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | #define DIU_DIV_MASK 0x000000ff | ||
92 | void 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 | |||
185 | ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf) | ||
186 | { | ||
187 | return sprintf(buf, "0 - 5121 LCD\n"); | ||
188 | } | ||
189 | |||
190 | int mpc512x_set_sysfs_monitor_port(int val) | ||
191 | { | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static 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) | ||
199 | static 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 | |||
209 | void 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 | */ | ||
236 | void __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 | |||
301 | out: | ||
302 | iounmap(diu_reg); | ||
303 | } | ||
304 | |||
305 | void __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 | |||
57 | void __init mpc512x_init_IRQ(void) | 341 | void __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 | |||
31 | static void *pdm360ng_gpio_base; | ||
32 | |||
33 | static 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 | |||
47 | static 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 | |||
53 | static 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 | |||
76 | static 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 | |||
89 | static struct notifier_block pdm360ng_touchscreen_nb = { | ||
90 | .notifier_call = pdm360ng_touchscreen_notifier_call, | ||
91 | }; | ||
92 | |||
93 | static 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 | ||
101 | static inline void __init pdm360ng_touchscreen_init(void) | ||
102 | { | ||
103 | } | ||
104 | #endif /* CONFIG_TOUCHSCREEN_ADS7846 */ | ||
105 | |||
106 | void __init pdm360ng_init(void) | ||
107 | { | ||
108 | mpc512x_init(); | ||
109 | pdm360ng_touchscreen_init(); | ||
110 | } | ||
111 | |||
112 | static 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 | |||
119 | define_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 | ||
10 | if PPC_83xx | 10 | if PPC_83xx |
11 | 11 | ||
12 | config 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 | |||
12 | config MPC831x_RDB | 20 | config 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 @@ | |||
4 | obj-y := misc.o usb.o | 4 | obj-y := misc.o usb.o |
5 | obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o | 5 | obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o |
6 | obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o | 6 | obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o |
7 | obj-$(CONFIG_MPC830x_RDB) += mpc830x_rdb.o | ||
7 | obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o | 8 | obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o |
8 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o | 9 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o |
9 | obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o | 10 | obj-$(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 | */ | ||
28 | static 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 | |||
44 | static 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 | */ | ||
63 | static 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 | |||
71 | static struct of_device_id __initdata of_bus_ids[] = { | ||
72 | { .compatible = "simple-bus" }, | ||
73 | { .compatible = "gianfar" }, | ||
74 | {}, | ||
75 | }; | ||
76 | |||
77 | static int __init declare_of_platform_devices(void) | ||
78 | { | ||
79 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
80 | return 0; | ||
81 | } | ||
82 | machine_device_initcall(mpc830x_rdb, declare_of_platform_devices); | ||
83 | |||
84 | define_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 | ||
68 | config 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 | |||
68 | config SOCRATES | 76 | config 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 | |||
10 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o | 10 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o |
11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o | 11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o |
12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o | 12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o |
13 | obj-$(CONFIG_P1022_DS) += p1022_ds.o | ||
13 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o | 14 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o |
14 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | 15 | obj-$(CONFIG_STX_GP3) += stx_gp3.o |
15 | obj-$(CONFIG_TQM85xx) += tqm85xx.o | 16 | obj-$(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) | |||
158 | extern void __init mpc85xx_smp_init(void); | 158 | extern void __init mpc85xx_smp_init(void); |
159 | #endif | 159 | #endif |
160 | 160 | ||
161 | static void __init mpc85xx_mds_setup_arch(void) | 161 | #ifdef CONFIG_QUICC_ENGINE |
162 | static struct of_device_id mpc85xx_qe_ids[] __initdata = { | ||
163 | { .type = "qe", }, | ||
164 | { .compatible = "fsl,qe", }, | ||
165 | { }, | ||
166 | }; | ||
167 | |||
168 | static 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 | |||
181 | static 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 | |
259 | static 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 | |||
326 | static 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 | ||
351 | static void __init mpc85xx_publish_qe_devices(void) { } | ||
352 | static void __init mpc85xx_mds_qe_init(void) { } | ||
353 | static void __init mpc85xx_mds_qeic_init(void) { } | ||
325 | #endif /* CONFIG_QUICC_ENGINE */ | 354 | #endif /* CONFIG_QUICC_ENGINE */ |
326 | 355 | ||
356 | static 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 | ||
404 | static int __init p1021_publish_devices(void) | 463 | static 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 | ||
461 | static int __init mpc85xx_mds_probe(void) | 506 | static 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 | |||
30 | void __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 | ||
61 | void __init mpc85xx_smp_init(void); | ||
62 | #endif | ||
63 | |||
64 | /* | ||
65 | * Setup the architecture | ||
66 | */ | ||
67 | static 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 | |||
110 | static struct of_device_id __initdata p1022_ds_ids[] = { | ||
111 | { .type = "soc", }, | ||
112 | { .compatible = "soc", }, | ||
113 | { .compatible = "simple-bus", }, | ||
114 | { .compatible = "gianfar", }, | ||
115 | {}, | ||
116 | }; | ||
117 | |||
118 | static int __init p1022_ds_publish_devices(void) | ||
119 | { | ||
120 | return of_platform_bus_probe(NULL, p1022_ds_ids, NULL); | ||
121 | } | ||
122 | machine_device_initcall(p1022_ds, p1022_ds_publish_devices); | ||
123 | |||
124 | machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier); | ||
125 | |||
126 | /* | ||
127 | * Called very early, device-tree isn't unflattened | ||
128 | */ | ||
129 | static 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 | |||
136 | define_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 | ||
28 | extern void __early_start(void); | 30 | extern void __early_start(void); |
29 | 31 | ||
@@ -99,12 +101,70 @@ static void __init | |||
99 | smp_85xx_setup_cpu(int cpu_nr) | 101 | smp_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 | ||
104 | struct smp_ops_t smp_85xx_ops = { | 108 | struct 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 | ||
117 | static int kexec_down_cpus = 0; | ||
118 | |||
119 | void 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 | |||
134 | static 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 | |||
140 | static 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 | |||
108 | void __init mpc85xx_smp_init(void) | 168 | void __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 | ||
154 | static 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 | } | ||
172 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, | ||
173 | tqm85xx_ti1520_fixup); | ||
174 | |||
154 | static struct of_device_id __initdata of_bus_ids[] = { | 175 | static 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 | ||
58 | config TQM8XX | ||
59 | bool "TQM8XX" | ||
60 | select CPM1 | ||
61 | help | ||
62 | support for the mpc8xx based boards from TQM. | ||
63 | |||
58 | endchoice | 64 | endchoice |
59 | 65 | ||
60 | menu "Freescale Ethernet driver platform-specific options" | 66 | menu "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 | |||
7 | obj-$(CONFIG_PPC_EP88XC) += ep88xc.o | 7 | obj-$(CONFIG_PPC_EP88XC) += ep88xc.o |
8 | obj-$(CONFIG_PPC_ADDER875) += adder875.o | 8 | obj-$(CONFIG_PPC_ADDER875) += adder875.o |
9 | obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o | 9 | obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o |
10 | obj-$(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 | |||
49 | struct cpm_pin { | ||
50 | int port, pin, flags; | ||
51 | }; | ||
52 | |||
53 | static 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 | |||
68 | static 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 | |||
85 | static 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 | |||
95 | static 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 | |||
116 | static void __init tqm8xx_setup_arch(void) | ||
117 | { | ||
118 | cpm_reset(); | ||
119 | init_ioports(); | ||
120 | } | ||
121 | |||
122 | static 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 | |||
129 | static struct of_device_id __initdata of_bus_ids[] = { | ||
130 | { .name = "soc", }, | ||
131 | { .name = "cpm", }, | ||
132 | { .name = "localbus", }, | ||
133 | { .compatible = "simple-bus" }, | ||
134 | {}, | ||
135 | }; | ||
136 | |||
137 | static int __init declare_of_platform_devices(void) | ||
138 | { | ||
139 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | machine_device_initcall(tqm8xx, declare_of_platform_devices); | ||
144 | |||
145 | define_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 | |||
26 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o | 26 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o |
27 | obj-$(CONFIG_CMM) += cmm.o | 27 | obj-$(CONFIG_CMM) += cmm.o |
28 | obj-$(CONFIG_DTL) += dtl.o | 28 | obj-$(CONFIG_DTL) += dtl.o |
29 | |||
30 | ifeq ($(CONFIG_PPC_PSERIES),y) | ||
31 | obj-$(CONFIG_SUSPEND) += suspend.o | ||
32 | endif | ||
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 | ||
128 | static int pseries_drconf_memory(unsigned long *base, unsigned int action) | 128 | static 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 | ||
66 | static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); | 65 | static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); |
67 | static irqreturn_t ras_error_interrupt(int irq, void *dev_id); | 66 | static 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 | |||
27 | static u64 stream_id; | ||
28 | static struct sys_device suspend_sysdev; | ||
29 | static DECLARE_COMPLETION(suspend_work); | ||
30 | static struct rtas_suspend_me_data suspend_data; | ||
31 | static 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 | **/ | ||
41 | static 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 | **/ | ||
71 | static 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 | **/ | ||
84 | static 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 | **/ | ||
99 | static 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 | **/ | ||
123 | static 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 | |||
150 | static SYSDEV_CLASS_ATTR(hibernate, S_IWUSR, NULL, store_hibernate); | ||
151 | |||
152 | static struct sysdev_class suspend_sysdev_class = { | ||
153 | .name = "power", | ||
154 | }; | ||
155 | |||
156 | static 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 | **/ | ||
169 | static 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 | |||
184 | class_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 | **/ | ||
195 | static 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)) { |