diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-14 21:55:27 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-14 21:55:27 -0400 |
commit | 5b0504c0d795d6b0a904ff861c043d7a231f67a4 (patch) | |
tree | c988e8b614c55d0dae2be4b750a03eb0a4f4d355 /arch/powerpc | |
parent | 930074b6b9c4895d20cdadba5aff97907e28728d (diff) | |
parent | 77a76369475801ab8cbb338b9d8cfa92a491badb (diff) |
Merge commit 'gcl/gcl-next'
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/boot/dts/mpc5121ads.dts | 310 | ||||
-rw-r--r-- | arch/powerpc/boot/dts/tqm5200.dts | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/Kconfig | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/Makefile | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/clock.c | 729 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc5121_ads.c | 69 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc5121_ads.h | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | 204 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc5121_generic.c | 58 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc512x.h | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/512x/mpc512x_shared.c | 83 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_pci.c | 3 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/bestcomm.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/gen_bd.c | 95 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/gen_bd.h | 5 | ||||
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/sram.c | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 133 |
17 files changed, 1554 insertions, 207 deletions
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts index 94ad7b2b241e..1f9036c317b4 100644 --- a/arch/powerpc/boot/dts/mpc5121ads.dts +++ b/arch/powerpc/boot/dts/mpc5121ads.dts | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MPC5121E MDS Device Tree Source | 2 | * MPC5121E ADS Device Tree Source |
3 | * | 3 | * |
4 | * Copyright 2007 Freescale Semiconductor Inc. | 4 | * Copyright 2007,2008 Freescale Semiconductor Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -17,6 +17,10 @@ | |||
17 | #address-cells = <1>; | 17 | #address-cells = <1>; |
18 | #size-cells = <1>; | 18 | #size-cells = <1>; |
19 | 19 | ||
20 | aliases { | ||
21 | pci = &pci; | ||
22 | }; | ||
23 | |||
20 | cpus { | 24 | cpus { |
21 | #address-cells = <1>; | 25 | #address-cells = <1>; |
22 | #size-cells = <0>; | 26 | #size-cells = <0>; |
@@ -39,8 +43,41 @@ | |||
39 | reg = <0x00000000 0x10000000>; // 256MB at 0 | 43 | reg = <0x00000000 0x10000000>; // 256MB at 0 |
40 | }; | 44 | }; |
41 | 45 | ||
46 | mbx@20000000 { | ||
47 | compatible = "fsl,mpc5121-mbx"; | ||
48 | reg = <0x20000000 0x4000>; | ||
49 | interrupts = <66 0x8>; | ||
50 | interrupt-parent = < &ipic >; | ||
51 | }; | ||
52 | |||
53 | sram@30000000 { | ||
54 | compatible = "fsl,mpc5121-sram"; | ||
55 | reg = <0x30000000 0x20000>; // 128K at 0x30000000 | ||
56 | }; | ||
57 | |||
58 | nfc@40000000 { | ||
59 | compatible = "fsl,mpc5121-nfc"; | ||
60 | reg = <0x40000000 0x100000>; // 1M at 0x40000000 | ||
61 | interrupts = <6 8>; | ||
62 | interrupt-parent = < &ipic >; | ||
63 | #address-cells = <1>; | ||
64 | #size-cells = <1>; | ||
65 | bank-width = <1>; | ||
66 | // ADS has two Hynix 512MB Nand flash chips in a single | ||
67 | // stacked package . | ||
68 | chips = <2>; | ||
69 | nand0@0 { | ||
70 | label = "nand0"; | ||
71 | reg = <0x00000000 0x02000000>; // first 32 MB of chip 0 | ||
72 | }; | ||
73 | nand1@20000000 { | ||
74 | label = "nand1"; | ||
75 | reg = <0x20000000 0x02000000>; // first 32 MB of chip 1 | ||
76 | }; | ||
77 | }; | ||
78 | |||
42 | localbus@80000020 { | 79 | localbus@80000020 { |
43 | compatible = "fsl,mpc5121ads-localbus"; | 80 | compatible = "fsl,mpc5121-localbus"; |
44 | #address-cells = <2>; | 81 | #address-cells = <2>; |
45 | #size-cells = <1>; | 82 | #size-cells = <1>; |
46 | reg = <0x80000020 0x40>; | 83 | reg = <0x80000020 0x40>; |
@@ -51,14 +88,51 @@ | |||
51 | flash@0,0 { | 88 | flash@0,0 { |
52 | compatible = "cfi-flash"; | 89 | compatible = "cfi-flash"; |
53 | reg = <0 0x0 0x4000000>; | 90 | reg = <0 0x0 0x4000000>; |
91 | #address-cells = <1>; | ||
92 | #size-cells = <1>; | ||
54 | bank-width = <4>; | 93 | bank-width = <4>; |
55 | device-width = <1>; | 94 | device-width = <2>; |
95 | protected@0 { | ||
96 | label = "protected"; | ||
97 | reg = <0x00000000 0x00040000>; // first sector is protected | ||
98 | read-only; | ||
99 | }; | ||
100 | filesystem@40000 { | ||
101 | label = "filesystem"; | ||
102 | reg = <0x00040000 0x03c00000>; // 60M for filesystem | ||
103 | }; | ||
104 | kernel@3c40000 { | ||
105 | label = "kernel"; | ||
106 | reg = <0x03c40000 0x00280000>; // 2.5M for kernel | ||
107 | }; | ||
108 | device-tree@3ec0000 { | ||
109 | label = "device-tree"; | ||
110 | reg = <0x03ec0000 0x00040000>; // one sector for device tree | ||
111 | }; | ||
112 | u-boot@3f00000 { | ||
113 | label = "u-boot"; | ||
114 | reg = <0x03f00000 0x00100000>; // 1M for u-boot | ||
115 | read-only; | ||
116 | }; | ||
56 | }; | 117 | }; |
57 | 118 | ||
58 | board-control@2,0 { | 119 | board-control@2,0 { |
59 | compatible = "fsl,mpc5121ads-cpld"; | 120 | compatible = "fsl,mpc5121ads-cpld"; |
60 | reg = <0x2 0x0 0x8000>; | 121 | reg = <0x2 0x0 0x8000>; |
61 | }; | 122 | }; |
123 | |||
124 | cpld_pic: pic@2,a { | ||
125 | compatible = "fsl,mpc5121ads-cpld-pic"; | ||
126 | interrupt-controller; | ||
127 | #interrupt-cells = <2>; | ||
128 | reg = <0x2 0xa 0x5>; | ||
129 | interrupt-parent = < &ipic >; | ||
130 | // irq routing | ||
131 | // all irqs but touch screen are routed to irq0 (ipic 48) | ||
132 | // touch screen is statically routed to irq1 (ipic 17) | ||
133 | // so don't use it here | ||
134 | interrupts = <48 0x8>; | ||
135 | }; | ||
62 | }; | 136 | }; |
63 | 137 | ||
64 | soc@80000000 { | 138 | soc@80000000 { |
@@ -85,38 +159,252 @@ | |||
85 | reg = <0xc00 0x100>; | 159 | reg = <0xc00 0x100>; |
86 | }; | 160 | }; |
87 | 161 | ||
88 | // 512x PSCs are not 52xx PSCs compatible | 162 | rtc@a00 { // Real time clock |
163 | compatible = "fsl,mpc5121-rtc"; | ||
164 | reg = <0xa00 0x100>; | ||
165 | interrupts = <79 0x8 80 0x8>; | ||
166 | interrupt-parent = < &ipic >; | ||
167 | }; | ||
168 | |||
169 | clock@f00 { // Clock control | ||
170 | compatible = "fsl,mpc5121-clock"; | ||
171 | reg = <0xf00 0x100>; | ||
172 | }; | ||
173 | |||
174 | pmc@1000{ //Power Management Controller | ||
175 | compatible = "fsl,mpc5121-pmc"; | ||
176 | reg = <0x1000 0x100>; | ||
177 | interrupts = <83 0x2>; | ||
178 | interrupt-parent = < &ipic >; | ||
179 | }; | ||
180 | |||
181 | gpio@1100 { | ||
182 | compatible = "fsl,mpc5121-gpio"; | ||
183 | reg = <0x1100 0x100>; | ||
184 | interrupts = <78 0x8>; | ||
185 | interrupt-parent = < &ipic >; | ||
186 | }; | ||
187 | |||
188 | mscan@1300 { | ||
189 | compatible = "fsl,mpc5121-mscan"; | ||
190 | cell-index = <0>; | ||
191 | interrupts = <12 0x8>; | ||
192 | interrupt-parent = < &ipic >; | ||
193 | reg = <0x1300 0x80>; | ||
194 | }; | ||
195 | |||
196 | mscan@1380 { | ||
197 | compatible = "fsl,mpc5121-mscan"; | ||
198 | cell-index = <1>; | ||
199 | interrupts = <13 0x8>; | ||
200 | interrupt-parent = < &ipic >; | ||
201 | reg = <0x1380 0x80>; | ||
202 | }; | ||
203 | |||
204 | i2c@1700 { | ||
205 | #address-cells = <1>; | ||
206 | #size-cells = <0>; | ||
207 | compatible = "fsl,mpc5121-i2c", "fsl-i2c"; | ||
208 | cell-index = <0>; | ||
209 | reg = <0x1700 0x20>; | ||
210 | interrupts = <9 0x8>; | ||
211 | interrupt-parent = < &ipic >; | ||
212 | fsl5200-clocking; | ||
213 | }; | ||
214 | |||
215 | i2c@1720 { | ||
216 | #address-cells = <1>; | ||
217 | #size-cells = <0>; | ||
218 | compatible = "fsl,mpc5121-i2c", "fsl-i2c"; | ||
219 | cell-index = <1>; | ||
220 | reg = <0x1720 0x20>; | ||
221 | interrupts = <10 0x8>; | ||
222 | interrupt-parent = < &ipic >; | ||
223 | fsl5200-clocking; | ||
224 | }; | ||
225 | |||
226 | i2c@1740 { | ||
227 | #address-cells = <1>; | ||
228 | #size-cells = <0>; | ||
229 | compatible = "fsl,mpc5121-i2c", "fsl-i2c"; | ||
230 | cell-index = <2>; | ||
231 | reg = <0x1740 0x20>; | ||
232 | interrupts = <11 0x8>; | ||
233 | interrupt-parent = < &ipic >; | ||
234 | fsl5200-clocking; | ||
235 | }; | ||
236 | |||
237 | i2ccontrol@1760 { | ||
238 | compatible = "fsl,mpc5121-i2c-ctrl"; | ||
239 | reg = <0x1760 0x8>; | ||
240 | }; | ||
241 | |||
242 | axe@2000 { | ||
243 | compatible = "fsl,mpc5121-axe"; | ||
244 | reg = <0x2000 0x100>; | ||
245 | interrupts = <42 0x8>; | ||
246 | interrupt-parent = < &ipic >; | ||
247 | }; | ||
248 | |||
249 | display@2100 { | ||
250 | compatible = "fsl,mpc5121-diu", "fsl-diu"; | ||
251 | reg = <0x2100 0x100>; | ||
252 | interrupts = <64 0x8>; | ||
253 | interrupt-parent = < &ipic >; | ||
254 | }; | ||
255 | |||
256 | mdio@2800 { | ||
257 | compatible = "fsl,mpc5121-fec-mdio"; | ||
258 | reg = <0x2800 0x800>; | ||
259 | #address-cells = <1>; | ||
260 | #size-cells = <0>; | ||
261 | phy: ethernet-phy@0 { | ||
262 | reg = <1>; | ||
263 | device_type = "ethernet-phy"; | ||
264 | }; | ||
265 | }; | ||
266 | |||
267 | ethernet@2800 { | ||
268 | device_type = "network"; | ||
269 | compatible = "fsl,mpc5121-fec"; | ||
270 | reg = <0x2800 0x800>; | ||
271 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
272 | interrupts = <4 0x8>; | ||
273 | interrupt-parent = < &ipic >; | ||
274 | phy-handle = < &phy >; | ||
275 | fsl,align-tx-packets = <4>; | ||
276 | }; | ||
277 | |||
278 | // 5121e has two dr usb modules | ||
279 | // mpc5121_ads only uses USB0 | ||
280 | |||
281 | // USB1 using external ULPI PHY | ||
282 | //usb@3000 { | ||
283 | // compatible = "fsl,mpc5121-usb2-dr", "fsl-usb2-dr"; | ||
284 | // reg = <0x3000 0x1000>; | ||
285 | // #address-cells = <1>; | ||
286 | // #size-cells = <0>; | ||
287 | // interrupt-parent = < &ipic >; | ||
288 | // interrupts = <43 0x8>; | ||
289 | // dr_mode = "otg"; | ||
290 | // phy_type = "ulpi"; | ||
291 | // port1; | ||
292 | //}; | ||
293 | |||
294 | // USB0 using internal UTMI PHY | ||
295 | usb@4000 { | ||
296 | compatible = "fsl,mpc5121-usb2-dr", "fsl-usb2-dr"; | ||
297 | reg = <0x4000 0x1000>; | ||
298 | #address-cells = <1>; | ||
299 | #size-cells = <0>; | ||
300 | interrupt-parent = < &ipic >; | ||
301 | interrupts = <44 0x8>; | ||
302 | dr_mode = "otg"; | ||
303 | phy_type = "utmi_wide"; | ||
304 | port0; | ||
305 | }; | ||
306 | |||
307 | // IO control | ||
308 | ioctl@a000 { | ||
309 | compatible = "fsl,mpc5121-ioctl"; | ||
310 | reg = <0xA000 0x1000>; | ||
311 | }; | ||
312 | |||
313 | pata@10200 { | ||
314 | compatible = "fsl,mpc5121-pata"; | ||
315 | reg = <0x10200 0x100>; | ||
316 | interrupts = <5 0x8>; | ||
317 | interrupt-parent = < &ipic >; | ||
318 | }; | ||
319 | |||
320 | // 512x PSCs are not 52xx PSC compatible | ||
89 | // PSC3 serial port A aka ttyPSC0 | 321 | // PSC3 serial port A aka ttyPSC0 |
90 | serial@11300 { | 322 | serial@11300 { |
91 | device_type = "serial"; | 323 | device_type = "serial"; |
92 | compatible = "fsl,mpc5121-psc-uart"; | 324 | compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc"; |
93 | // Logical port assignment needed until driver | 325 | // Logical port assignment needed until driver |
94 | // learns to use aliases | 326 | // learns to use aliases |
95 | port-number = <0>; | 327 | port-number = <0>; |
96 | cell-index = <3>; | 328 | cell-index = <3>; |
97 | reg = <0x11300 0x100>; | 329 | reg = <0x11300 0x100>; |
98 | interrupts = <0x28 0x8>; // actually the fifo irq | 330 | interrupts = <40 0x8>; |
99 | interrupt-parent = < &ipic >; | 331 | interrupt-parent = < &ipic >; |
332 | rx-fifo-size = <16>; | ||
333 | tx-fifo-size = <16>; | ||
100 | }; | 334 | }; |
101 | 335 | ||
102 | // PSC4 serial port B aka ttyPSC1 | 336 | // PSC4 serial port B aka ttyPSC1 |
103 | serial@11400 { | 337 | serial@11400 { |
104 | device_type = "serial"; | 338 | device_type = "serial"; |
105 | compatible = "fsl,mpc5121-psc-uart"; | 339 | compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc"; |
106 | // Logical port assignment needed until driver | 340 | // Logical port assignment needed until driver |
107 | // learns to use aliases | 341 | // learns to use aliases |
108 | port-number = <1>; | 342 | port-number = <1>; |
109 | cell-index = <4>; | 343 | cell-index = <4>; |
110 | reg = <0x11400 0x100>; | 344 | reg = <0x11400 0x100>; |
111 | interrupts = <0x28 0x8>; // actually the fifo irq | 345 | interrupts = <40 0x8>; |
112 | interrupt-parent = < &ipic >; | 346 | interrupt-parent = < &ipic >; |
347 | rx-fifo-size = <16>; | ||
348 | tx-fifo-size = <16>; | ||
113 | }; | 349 | }; |
114 | 350 | ||
115 | pscsfifo@11f00 { | 351 | // PSC5 in ac97 mode |
352 | ac97@11500 { | ||
353 | compatible = "fsl,mpc5121-psc-ac97", "fsl,mpc5121-psc"; | ||
354 | cell-index = <5>; | ||
355 | reg = <0x11500 0x100>; | ||
356 | interrupts = <40 0x8>; | ||
357 | interrupt-parent = < &ipic >; | ||
358 | fsl,mode = "ac97-slave"; | ||
359 | rx-fifo-size = <384>; | ||
360 | tx-fifo-size = <384>; | ||
361 | }; | ||
362 | |||
363 | pscfifo@11f00 { | ||
116 | compatible = "fsl,mpc5121-psc-fifo"; | 364 | compatible = "fsl,mpc5121-psc-fifo"; |
117 | reg = <0x11f00 0x100>; | 365 | reg = <0x11f00 0x100>; |
118 | interrupts = <0x28 0x8>; | 366 | interrupts = <40 0x8>; |
119 | interrupt-parent = < &ipic >; | 367 | interrupt-parent = < &ipic >; |
120 | }; | 368 | }; |
369 | |||
370 | dma@14000 { | ||
371 | compatible = "fsl,mpc5121-dma2"; | ||
372 | reg = <0x14000 0x1800>; | ||
373 | interrupts = <65 0x8>; | ||
374 | interrupt-parent = < &ipic >; | ||
375 | }; | ||
376 | |||
377 | }; | ||
378 | |||
379 | pci: pci@80008500 { | ||
380 | interrupt-map-mask = <0xf800 0x0 0x0 0x7>; | ||
381 | interrupt-map = < | ||
382 | // IDSEL 0x15 - Slot 1 PCI | ||
383 | 0xa800 0x0 0x0 0x1 &cpld_pic 0x0 0x8 | ||
384 | 0xa800 0x0 0x0 0x2 &cpld_pic 0x1 0x8 | ||
385 | 0xa800 0x0 0x0 0x3 &cpld_pic 0x2 0x8 | ||
386 | 0xa800 0x0 0x0 0x4 &cpld_pic 0x3 0x8 | ||
387 | |||
388 | // IDSEL 0x16 - Slot 2 MiniPCI | ||
389 | 0xb000 0x0 0x0 0x1 &cpld_pic 0x4 0x8 | ||
390 | 0xb000 0x0 0x0 0x2 &cpld_pic 0x5 0x8 | ||
391 | |||
392 | // IDSEL 0x17 - Slot 3 MiniPCI | ||
393 | 0xb800 0x0 0x0 0x1 &cpld_pic 0x6 0x8 | ||
394 | 0xb800 0x0 0x0 0x2 &cpld_pic 0x7 0x8 | ||
395 | >; | ||
396 | interrupt-parent = < &ipic >; | ||
397 | interrupts = <1 0x8>; | ||
398 | bus-range = <0 0>; | ||
399 | ranges = <0x42000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 | ||
400 | 0x02000000 0x0 0xb0000000 0xb0000000 0x0 0x10000000 | ||
401 | 0x01000000 0x0 0x00000000 0x84000000 0x0 0x01000000>; | ||
402 | clock-frequency = <0>; | ||
403 | #interrupt-cells = <1>; | ||
404 | #size-cells = <2>; | ||
405 | #address-cells = <3>; | ||
406 | reg = <0x80008500 0x100>; | ||
407 | compatible = "fsl,mpc5121-pci"; | ||
408 | device_type = "pci"; | ||
121 | }; | 409 | }; |
122 | }; | 410 | }; |
diff --git a/arch/powerpc/boot/dts/tqm5200.dts b/arch/powerpc/boot/dts/tqm5200.dts index 773a68e00058..3008bf8830c1 100644 --- a/arch/powerpc/boot/dts/tqm5200.dts +++ b/arch/powerpc/boot/dts/tqm5200.dts | |||
@@ -70,6 +70,20 @@ | |||
70 | fsl,has-wdt; | 70 | fsl,has-wdt; |
71 | }; | 71 | }; |
72 | 72 | ||
73 | can@900 { | ||
74 | compatible = "fsl,mpc5200-mscan"; | ||
75 | interrupts = <2 17 0>; | ||
76 | interrupt-parent = <&mpc5200_pic>; | ||
77 | reg = <0x900 0x80>; | ||
78 | }; | ||
79 | |||
80 | can@980 { | ||
81 | compatible = "fsl,mpc5200-mscan"; | ||
82 | interrupts = <2 18 0>; | ||
83 | interrupt-parent = <&mpc5200_pic>; | ||
84 | reg = <0x980 0x80>; | ||
85 | }; | ||
86 | |||
73 | gpio@b00 { | 87 | gpio@b00 { |
74 | compatible = "fsl,mpc5200-gpio"; | 88 | compatible = "fsl,mpc5200-gpio"; |
75 | reg = <0xb00 0x40>; | 89 | reg = <0xb00 0x40>; |
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig index 4c0da0c079e9..c62f893ede19 100644 --- a/arch/powerpc/platforms/512x/Kconfig +++ b/arch/powerpc/platforms/512x/Kconfig | |||
@@ -2,18 +2,29 @@ config PPC_MPC512x | |||
2 | bool | 2 | bool |
3 | select FSL_SOC | 3 | select FSL_SOC |
4 | select IPIC | 4 | select IPIC |
5 | default n | 5 | select PPC_CLOCK |
6 | 6 | ||
7 | config PPC_MPC5121 | 7 | config PPC_MPC5121 |
8 | bool | 8 | bool |
9 | select PPC_MPC512x | 9 | select PPC_MPC512x |
10 | default n | ||
11 | 10 | ||
12 | config MPC5121_ADS | 11 | config MPC5121_ADS |
13 | bool "Freescale MPC5121E ADS" | 12 | bool "Freescale MPC5121E ADS" |
14 | depends on PPC_MULTIPLATFORM && PPC32 | 13 | depends on PPC_MULTIPLATFORM && PPC32 |
15 | select DEFAULT_UIMAGE | 14 | select DEFAULT_UIMAGE |
16 | select PPC_MPC5121 | 15 | select PPC_MPC5121 |
16 | select MPC5121_ADS_CPLD | ||
17 | help | 17 | help |
18 | This option enables support for the MPC5121E ADS board. | 18 | This option enables support for the MPC5121E ADS board. |
19 | default n | 19 | |
20 | config MPC5121_GENERIC | ||
21 | bool "Generic support for simple MPC5121 based boards" | ||
22 | depends on PPC_MULTIPLATFORM && PPC32 | ||
23 | select DEFAULT_UIMAGE | ||
24 | select PPC_MPC5121 | ||
25 | help | ||
26 | This option enables support for simple MPC5121 based boards | ||
27 | which do not need custom platform specific setup. | ||
28 | |||
29 | Compatible boards include: Protonic LVT base boards (ZANMCU | ||
30 | and VICVT2). | ||
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile index 232c89f2039a..90be2f5717e6 100644 --- a/arch/powerpc/platforms/512x/Makefile +++ b/arch/powerpc/platforms/512x/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the Freescale PowerPC 512x linux kernel. | 2 | # Makefile for the Freescale PowerPC 512x linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o | 4 | obj-y += clock.o mpc512x_shared.o |
5 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o | ||
6 | obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o | ||
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c new file mode 100644 index 000000000000..f416014ee727 --- /dev/null +++ b/arch/powerpc/platforms/512x/clock.c | |||
@@ -0,0 +1,729 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby <jrigby@freescale.com> | ||
5 | * | ||
6 | * Implements the clk api defined in include/linux/clk.h | ||
7 | * | ||
8 | * Original based on linux/arch/arm/mach-integrator/clock.c | ||
9 | * | ||
10 | * Copyright (C) 2004 ARM Limited. | ||
11 | * Written by Deep Blue Solutions Limited. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #include <linux/of_platform.h> | ||
27 | #include <asm/mpc512x.h> | ||
28 | #include <asm/clk_interface.h> | ||
29 | |||
30 | #undef CLK_DEBUG | ||
31 | |||
32 | static int clocks_initialized; | ||
33 | |||
34 | #define CLK_HAS_RATE 0x1 /* has rate in MHz */ | ||
35 | #define CLK_HAS_CTRL 0x2 /* has control reg and bit */ | ||
36 | |||
37 | struct clk { | ||
38 | struct list_head node; | ||
39 | char name[32]; | ||
40 | int flags; | ||
41 | struct device *dev; | ||
42 | unsigned long rate; | ||
43 | struct module *owner; | ||
44 | void (*calc) (struct clk *); | ||
45 | struct clk *parent; | ||
46 | int reg, bit; /* CLK_HAS_CTRL */ | ||
47 | int div_shift; /* only used by generic_div_clk_calc */ | ||
48 | }; | ||
49 | |||
50 | static LIST_HEAD(clocks); | ||
51 | static DEFINE_MUTEX(clocks_mutex); | ||
52 | |||
53 | static struct clk *mpc5121_clk_get(struct device *dev, const char *id) | ||
54 | { | ||
55 | struct clk *p, *clk = ERR_PTR(-ENOENT); | ||
56 | int dev_match = 0; | ||
57 | int id_match = 0; | ||
58 | |||
59 | if (dev == NULL && id == NULL) | ||
60 | return NULL; | ||
61 | |||
62 | mutex_lock(&clocks_mutex); | ||
63 | list_for_each_entry(p, &clocks, node) { | ||
64 | if (dev && dev == p->dev) | ||
65 | dev_match++; | ||
66 | if (strcmp(id, p->name) == 0) | ||
67 | id_match++; | ||
68 | if ((dev_match || id_match) && try_module_get(p->owner)) { | ||
69 | clk = p; | ||
70 | break; | ||
71 | } | ||
72 | } | ||
73 | mutex_unlock(&clocks_mutex); | ||
74 | |||
75 | return clk; | ||
76 | } | ||
77 | |||
78 | #ifdef CLK_DEBUG | ||
79 | static void dump_clocks(void) | ||
80 | { | ||
81 | struct clk *p; | ||
82 | |||
83 | mutex_lock(&clocks_mutex); | ||
84 | printk(KERN_INFO "CLOCKS:\n"); | ||
85 | list_for_each_entry(p, &clocks, node) { | ||
86 | printk(KERN_INFO " %s %ld", p->name, p->rate); | ||
87 | if (p->parent) | ||
88 | printk(KERN_INFO " %s %ld", p->parent->name, | ||
89 | p->parent->rate); | ||
90 | if (p->flags & CLK_HAS_CTRL) | ||
91 | printk(KERN_INFO " reg/bit %d/%d", p->reg, p->bit); | ||
92 | printk("\n"); | ||
93 | } | ||
94 | mutex_unlock(&clocks_mutex); | ||
95 | } | ||
96 | #define DEBUG_CLK_DUMP() dump_clocks() | ||
97 | #else | ||
98 | #define DEBUG_CLK_DUMP() | ||
99 | #endif | ||
100 | |||
101 | |||
102 | static void mpc5121_clk_put(struct clk *clk) | ||
103 | { | ||
104 | module_put(clk->owner); | ||
105 | } | ||
106 | |||
107 | #define NRPSC 12 | ||
108 | |||
109 | struct mpc512x_clockctl { | ||
110 | u32 spmr; /* System PLL Mode Reg */ | ||
111 | u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ | ||
112 | u32 scfr1; /* System Clk Freq Reg 1 */ | ||
113 | u32 scfr2; /* System Clk Freq Reg 2 */ | ||
114 | u32 reserved; | ||
115 | u32 bcr; /* Bread Crumb Reg */ | ||
116 | u32 pccr[NRPSC]; /* PSC Clk Ctrl Reg 0-11 */ | ||
117 | u32 spccr; /* SPDIF Clk Ctrl Reg */ | ||
118 | u32 cccr; /* CFM Clk Ctrl Reg */ | ||
119 | u32 dccr; /* DIU Clk Cnfg Reg */ | ||
120 | }; | ||
121 | |||
122 | struct mpc512x_clockctl __iomem *clockctl; | ||
123 | |||
124 | static int mpc5121_clk_enable(struct clk *clk) | ||
125 | { | ||
126 | unsigned int mask; | ||
127 | |||
128 | if (clk->flags & CLK_HAS_CTRL) { | ||
129 | mask = in_be32(&clockctl->sccr[clk->reg]); | ||
130 | mask |= 1 << clk->bit; | ||
131 | out_be32(&clockctl->sccr[clk->reg], mask); | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void mpc5121_clk_disable(struct clk *clk) | ||
137 | { | ||
138 | unsigned int mask; | ||
139 | |||
140 | if (clk->flags & CLK_HAS_CTRL) { | ||
141 | mask = in_be32(&clockctl->sccr[clk->reg]); | ||
142 | mask &= ~(1 << clk->bit); | ||
143 | out_be32(&clockctl->sccr[clk->reg], mask); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static unsigned long mpc5121_clk_get_rate(struct clk *clk) | ||
148 | { | ||
149 | if (clk->flags & CLK_HAS_RATE) | ||
150 | return clk->rate; | ||
151 | else | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate) | ||
156 | { | ||
157 | return rate; | ||
158 | } | ||
159 | |||
160 | static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate) | ||
161 | { | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int clk_register(struct clk *clk) | ||
166 | { | ||
167 | mutex_lock(&clocks_mutex); | ||
168 | list_add(&clk->node, &clocks); | ||
169 | mutex_unlock(&clocks_mutex); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static unsigned long spmf_mult(void) | ||
174 | { | ||
175 | /* | ||
176 | * Convert spmf to multiplier | ||
177 | */ | ||
178 | static int spmf_to_mult[] = { | ||
179 | 68, 1, 12, 16, | ||
180 | 20, 24, 28, 32, | ||
181 | 36, 40, 44, 48, | ||
182 | 52, 56, 60, 64 | ||
183 | }; | ||
184 | int spmf = (clockctl->spmr >> 24) & 0xf; | ||
185 | return spmf_to_mult[spmf]; | ||
186 | } | ||
187 | |||
188 | static unsigned long sysdiv_div_x_2(void) | ||
189 | { | ||
190 | /* | ||
191 | * Convert sysdiv to divisor x 2 | ||
192 | * Some divisors have fractional parts so | ||
193 | * multiply by 2 then divide by this value | ||
194 | */ | ||
195 | static int sysdiv_to_div_x_2[] = { | ||
196 | 4, 5, 6, 7, | ||
197 | 8, 9, 10, 14, | ||
198 | 12, 16, 18, 22, | ||
199 | 20, 24, 26, 30, | ||
200 | 28, 32, 34, 38, | ||
201 | 36, 40, 42, 46, | ||
202 | 44, 48, 50, 54, | ||
203 | 52, 56, 58, 62, | ||
204 | 60, 64, 66, | ||
205 | }; | ||
206 | int sysdiv = (clockctl->scfr2 >> 26) & 0x3f; | ||
207 | return sysdiv_to_div_x_2[sysdiv]; | ||
208 | } | ||
209 | |||
210 | static unsigned long ref_to_sys(unsigned long rate) | ||
211 | { | ||
212 | rate *= spmf_mult(); | ||
213 | rate *= 2; | ||
214 | rate /= sysdiv_div_x_2(); | ||
215 | |||
216 | return rate; | ||
217 | } | ||
218 | |||
219 | static unsigned long sys_to_ref(unsigned long rate) | ||
220 | { | ||
221 | rate *= sysdiv_div_x_2(); | ||
222 | rate /= 2; | ||
223 | rate /= spmf_mult(); | ||
224 | |||
225 | return rate; | ||
226 | } | ||
227 | |||
228 | static long ips_to_ref(unsigned long rate) | ||
229 | { | ||
230 | int ips_div = (clockctl->scfr1 >> 23) & 0x7; | ||
231 | |||
232 | rate *= ips_div; /* csb_clk = ips_clk * ips_div */ | ||
233 | rate *= 2; /* sys_clk = csb_clk * 2 */ | ||
234 | return sys_to_ref(rate); | ||
235 | } | ||
236 | |||
237 | static unsigned long devtree_getfreq(char *clockname) | ||
238 | { | ||
239 | struct device_node *np; | ||
240 | const unsigned int *prop; | ||
241 | unsigned int val = 0; | ||
242 | |||
243 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr"); | ||
244 | if (np) { | ||
245 | prop = of_get_property(np, clockname, NULL); | ||
246 | if (prop) | ||
247 | val = *prop; | ||
248 | of_node_put(np); | ||
249 | } | ||
250 | return val; | ||
251 | } | ||
252 | |||
253 | static void ref_clk_calc(struct clk *clk) | ||
254 | { | ||
255 | unsigned long rate; | ||
256 | |||
257 | rate = devtree_getfreq("bus-frequency"); | ||
258 | if (rate == 0) { | ||
259 | printk(KERN_ERR "No bus-frequency in dev tree\n"); | ||
260 | clk->rate = 0; | ||
261 | return; | ||
262 | } | ||
263 | clk->rate = ips_to_ref(rate); | ||
264 | } | ||
265 | |||
266 | static struct clk ref_clk = { | ||
267 | .name = "ref_clk", | ||
268 | .calc = ref_clk_calc, | ||
269 | }; | ||
270 | |||
271 | |||
272 | static void sys_clk_calc(struct clk *clk) | ||
273 | { | ||
274 | clk->rate = ref_to_sys(ref_clk.rate); | ||
275 | } | ||
276 | |||
277 | static struct clk sys_clk = { | ||
278 | .name = "sys_clk", | ||
279 | .calc = sys_clk_calc, | ||
280 | }; | ||
281 | |||
282 | static void diu_clk_calc(struct clk *clk) | ||
283 | { | ||
284 | int diudiv_x_2 = clockctl->scfr1 & 0xff; | ||
285 | unsigned long rate; | ||
286 | |||
287 | rate = sys_clk.rate; | ||
288 | |||
289 | rate *= 2; | ||
290 | rate /= diudiv_x_2; | ||
291 | |||
292 | clk->rate = rate; | ||
293 | } | ||
294 | |||
295 | static void half_clk_calc(struct clk *clk) | ||
296 | { | ||
297 | clk->rate = clk->parent->rate / 2; | ||
298 | } | ||
299 | |||
300 | static void generic_div_clk_calc(struct clk *clk) | ||
301 | { | ||
302 | int div = (clockctl->scfr1 >> clk->div_shift) & 0x7; | ||
303 | |||
304 | clk->rate = clk->parent->rate / div; | ||
305 | } | ||
306 | |||
307 | static void unity_clk_calc(struct clk *clk) | ||
308 | { | ||
309 | clk->rate = clk->parent->rate; | ||
310 | } | ||
311 | |||
312 | static struct clk csb_clk = { | ||
313 | .name = "csb_clk", | ||
314 | .calc = half_clk_calc, | ||
315 | .parent = &sys_clk, | ||
316 | }; | ||
317 | |||
318 | static void e300_clk_calc(struct clk *clk) | ||
319 | { | ||
320 | int spmf = (clockctl->spmr >> 16) & 0xf; | ||
321 | int ratex2 = clk->parent->rate * spmf; | ||
322 | |||
323 | clk->rate = ratex2 / 2; | ||
324 | } | ||
325 | |||
326 | static struct clk e300_clk = { | ||
327 | .name = "e300_clk", | ||
328 | .calc = e300_clk_calc, | ||
329 | .parent = &csb_clk, | ||
330 | }; | ||
331 | |||
332 | static struct clk ips_clk = { | ||
333 | .name = "ips_clk", | ||
334 | .calc = generic_div_clk_calc, | ||
335 | .parent = &csb_clk, | ||
336 | .div_shift = 23, | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * Clocks controlled by SCCR1 (.reg = 0) | ||
341 | */ | ||
342 | static struct clk lpc_clk = { | ||
343 | .name = "lpc_clk", | ||
344 | .flags = CLK_HAS_CTRL, | ||
345 | .reg = 0, | ||
346 | .bit = 30, | ||
347 | .calc = generic_div_clk_calc, | ||
348 | .parent = &ips_clk, | ||
349 | .div_shift = 11, | ||
350 | }; | ||
351 | |||
352 | static struct clk nfc_clk = { | ||
353 | .name = "nfc_clk", | ||
354 | .flags = CLK_HAS_CTRL, | ||
355 | .reg = 0, | ||
356 | .bit = 29, | ||
357 | .calc = generic_div_clk_calc, | ||
358 | .parent = &ips_clk, | ||
359 | .div_shift = 8, | ||
360 | }; | ||
361 | |||
362 | static struct clk pata_clk = { | ||
363 | .name = "pata_clk", | ||
364 | .flags = CLK_HAS_CTRL, | ||
365 | .reg = 0, | ||
366 | .bit = 28, | ||
367 | .calc = unity_clk_calc, | ||
368 | .parent = &ips_clk, | ||
369 | }; | ||
370 | |||
371 | /* | ||
372 | * PSC clocks (bits 27 - 16) | ||
373 | * are setup elsewhere | ||
374 | */ | ||
375 | |||
376 | static struct clk sata_clk = { | ||
377 | .name = "sata_clk", | ||
378 | .flags = CLK_HAS_CTRL, | ||
379 | .reg = 0, | ||
380 | .bit = 14, | ||
381 | .calc = unity_clk_calc, | ||
382 | .parent = &ips_clk, | ||
383 | }; | ||
384 | |||
385 | static struct clk fec_clk = { | ||
386 | .name = "fec_clk", | ||
387 | .flags = CLK_HAS_CTRL, | ||
388 | .reg = 0, | ||
389 | .bit = 13, | ||
390 | .calc = unity_clk_calc, | ||
391 | .parent = &ips_clk, | ||
392 | }; | ||
393 | |||
394 | static struct clk pci_clk = { | ||
395 | .name = "pci_clk", | ||
396 | .flags = CLK_HAS_CTRL, | ||
397 | .reg = 0, | ||
398 | .bit = 11, | ||
399 | .calc = generic_div_clk_calc, | ||
400 | .parent = &csb_clk, | ||
401 | .div_shift = 20, | ||
402 | }; | ||
403 | |||
404 | /* | ||
405 | * Clocks controlled by SCCR2 (.reg = 1) | ||
406 | */ | ||
407 | static struct clk diu_clk = { | ||
408 | .name = "diu_clk", | ||
409 | .flags = CLK_HAS_CTRL, | ||
410 | .reg = 1, | ||
411 | .bit = 31, | ||
412 | .calc = diu_clk_calc, | ||
413 | }; | ||
414 | |||
415 | static struct clk axe_clk = { | ||
416 | .name = "axe_clk", | ||
417 | .flags = CLK_HAS_CTRL, | ||
418 | .reg = 1, | ||
419 | .bit = 30, | ||
420 | .calc = unity_clk_calc, | ||
421 | .parent = &csb_clk, | ||
422 | }; | ||
423 | |||
424 | static struct clk usb1_clk = { | ||
425 | .name = "usb1_clk", | ||
426 | .flags = CLK_HAS_CTRL, | ||
427 | .reg = 1, | ||
428 | .bit = 28, | ||
429 | .calc = unity_clk_calc, | ||
430 | .parent = &csb_clk, | ||
431 | }; | ||
432 | |||
433 | static struct clk usb2_clk = { | ||
434 | .name = "usb2_clk", | ||
435 | .flags = CLK_HAS_CTRL, | ||
436 | .reg = 1, | ||
437 | .bit = 27, | ||
438 | .calc = unity_clk_calc, | ||
439 | .parent = &csb_clk, | ||
440 | }; | ||
441 | |||
442 | static struct clk i2c_clk = { | ||
443 | .name = "i2c_clk", | ||
444 | .flags = CLK_HAS_CTRL, | ||
445 | .reg = 1, | ||
446 | .bit = 26, | ||
447 | .calc = unity_clk_calc, | ||
448 | .parent = &ips_clk, | ||
449 | }; | ||
450 | |||
451 | static struct clk mscan_clk = { | ||
452 | .name = "mscan_clk", | ||
453 | .flags = CLK_HAS_CTRL, | ||
454 | .reg = 1, | ||
455 | .bit = 25, | ||
456 | .calc = unity_clk_calc, | ||
457 | .parent = &ips_clk, | ||
458 | }; | ||
459 | |||
460 | static struct clk sdhc_clk = { | ||
461 | .name = "sdhc_clk", | ||
462 | .flags = CLK_HAS_CTRL, | ||
463 | .reg = 1, | ||
464 | .bit = 24, | ||
465 | .calc = unity_clk_calc, | ||
466 | .parent = &ips_clk, | ||
467 | }; | ||
468 | |||
469 | static struct clk mbx_bus_clk = { | ||
470 | .name = "mbx_bus_clk", | ||
471 | .flags = CLK_HAS_CTRL, | ||
472 | .reg = 1, | ||
473 | .bit = 22, | ||
474 | .calc = half_clk_calc, | ||
475 | .parent = &csb_clk, | ||
476 | }; | ||
477 | |||
478 | static struct clk mbx_clk = { | ||
479 | .name = "mbx_clk", | ||
480 | .flags = CLK_HAS_CTRL, | ||
481 | .reg = 1, | ||
482 | .bit = 21, | ||
483 | .calc = unity_clk_calc, | ||
484 | .parent = &csb_clk, | ||
485 | }; | ||
486 | |||
487 | static struct clk mbx_3d_clk = { | ||
488 | .name = "mbx_3d_clk", | ||
489 | .flags = CLK_HAS_CTRL, | ||
490 | .reg = 1, | ||
491 | .bit = 20, | ||
492 | .calc = generic_div_clk_calc, | ||
493 | .parent = &mbx_bus_clk, | ||
494 | .div_shift = 14, | ||
495 | }; | ||
496 | |||
497 | static void psc_mclk_in_calc(struct clk *clk) | ||
498 | { | ||
499 | clk->rate = devtree_getfreq("psc_mclk_in"); | ||
500 | if (!clk->rate) | ||
501 | clk->rate = 25000000; | ||
502 | } | ||
503 | |||
504 | static struct clk psc_mclk_in = { | ||
505 | .name = "psc_mclk_in", | ||
506 | .calc = psc_mclk_in_calc, | ||
507 | }; | ||
508 | |||
509 | static struct clk spdif_txclk = { | ||
510 | .name = "spdif_txclk", | ||
511 | .flags = CLK_HAS_CTRL, | ||
512 | .reg = 1, | ||
513 | .bit = 23, | ||
514 | }; | ||
515 | |||
516 | static struct clk spdif_rxclk = { | ||
517 | .name = "spdif_rxclk", | ||
518 | .flags = CLK_HAS_CTRL, | ||
519 | .reg = 1, | ||
520 | .bit = 23, | ||
521 | }; | ||
522 | |||
523 | static void ac97_clk_calc(struct clk *clk) | ||
524 | { | ||
525 | /* ac97 bit clock is always 24.567 MHz */ | ||
526 | clk->rate = 24567000; | ||
527 | } | ||
528 | |||
529 | static struct clk ac97_clk = { | ||
530 | .name = "ac97_clk_in", | ||
531 | .calc = ac97_clk_calc, | ||
532 | }; | ||
533 | |||
534 | struct clk *rate_clks[] = { | ||
535 | &ref_clk, | ||
536 | &sys_clk, | ||
537 | &diu_clk, | ||
538 | &csb_clk, | ||
539 | &e300_clk, | ||
540 | &ips_clk, | ||
541 | &fec_clk, | ||
542 | &sata_clk, | ||
543 | &pata_clk, | ||
544 | &nfc_clk, | ||
545 | &lpc_clk, | ||
546 | &mbx_bus_clk, | ||
547 | &mbx_clk, | ||
548 | &mbx_3d_clk, | ||
549 | &axe_clk, | ||
550 | &usb1_clk, | ||
551 | &usb2_clk, | ||
552 | &i2c_clk, | ||
553 | &mscan_clk, | ||
554 | &sdhc_clk, | ||
555 | &pci_clk, | ||
556 | &psc_mclk_in, | ||
557 | &spdif_txclk, | ||
558 | &spdif_rxclk, | ||
559 | &ac97_clk, | ||
560 | NULL | ||
561 | }; | ||
562 | |||
563 | static void rate_clk_init(struct clk *clk) | ||
564 | { | ||
565 | if (clk->calc) { | ||
566 | clk->calc(clk); | ||
567 | clk->flags |= CLK_HAS_RATE; | ||
568 | clk_register(clk); | ||
569 | } else { | ||
570 | printk(KERN_WARNING | ||
571 | "Could not initialize clk %s without a calc routine\n", | ||
572 | clk->name); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | static void rate_clks_init(void) | ||
577 | { | ||
578 | struct clk **cpp, *clk; | ||
579 | |||
580 | cpp = rate_clks; | ||
581 | while ((clk = *cpp++)) | ||
582 | rate_clk_init(clk); | ||
583 | } | ||
584 | |||
585 | /* | ||
586 | * There are two clk enable registers with 32 enable bits each | ||
587 | * psc clocks and device clocks are all stored in dev_clks | ||
588 | */ | ||
589 | struct clk dev_clks[2][32]; | ||
590 | |||
591 | /* | ||
592 | * Given a psc number return the dev_clk | ||
593 | * associated with it | ||
594 | */ | ||
595 | static struct clk *psc_dev_clk(int pscnum) | ||
596 | { | ||
597 | int reg, bit; | ||
598 | struct clk *clk; | ||
599 | |||
600 | reg = 0; | ||
601 | bit = 27 - pscnum; | ||
602 | |||
603 | clk = &dev_clks[reg][bit]; | ||
604 | clk->reg = 0; | ||
605 | clk->bit = bit; | ||
606 | return clk; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * PSC clock rate calculation | ||
611 | */ | ||
612 | static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np) | ||
613 | { | ||
614 | unsigned long mclk_src = sys_clk.rate; | ||
615 | unsigned long mclk_div; | ||
616 | |||
617 | /* | ||
618 | * Can only change value of mclk divider | ||
619 | * when the divider is disabled. | ||
620 | * | ||
621 | * Zero is not a valid divider so minimum | ||
622 | * divider is 1 | ||
623 | * | ||
624 | * disable/set divider/enable | ||
625 | */ | ||
626 | out_be32(&clockctl->pccr[pscnum], 0); | ||
627 | out_be32(&clockctl->pccr[pscnum], 0x00020000); | ||
628 | out_be32(&clockctl->pccr[pscnum], 0x00030000); | ||
629 | |||
630 | if (clockctl->pccr[pscnum] & 0x80) { | ||
631 | clk->rate = spdif_rxclk.rate; | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | switch ((clockctl->pccr[pscnum] >> 14) & 0x3) { | ||
636 | case 0: | ||
637 | mclk_src = sys_clk.rate; | ||
638 | break; | ||
639 | case 1: | ||
640 | mclk_src = ref_clk.rate; | ||
641 | break; | ||
642 | case 2: | ||
643 | mclk_src = psc_mclk_in.rate; | ||
644 | break; | ||
645 | case 3: | ||
646 | mclk_src = spdif_txclk.rate; | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | mclk_div = ((clockctl->pccr[pscnum] >> 17) & 0x7fff) + 1; | ||
651 | clk->rate = mclk_src / mclk_div; | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Find all psc nodes in device tree and assign a clock | ||
656 | * with name "psc%d_mclk" and dev pointing at the device | ||
657 | * returned from of_find_device_by_node | ||
658 | */ | ||
659 | static void psc_clks_init(void) | ||
660 | { | ||
661 | struct device_node *np; | ||
662 | const u32 *cell_index; | ||
663 | struct of_device *ofdev; | ||
664 | |||
665 | for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") { | ||
666 | cell_index = of_get_property(np, "cell-index", NULL); | ||
667 | if (cell_index) { | ||
668 | int pscnum = *cell_index; | ||
669 | struct clk *clk = psc_dev_clk(pscnum); | ||
670 | |||
671 | clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL; | ||
672 | ofdev = of_find_device_by_node(np); | ||
673 | clk->dev = &ofdev->dev; | ||
674 | /* | ||
675 | * AC97 is special rate clock does | ||
676 | * not go through normal path | ||
677 | */ | ||
678 | if (strcmp("ac97", np->name) == 0) | ||
679 | clk->rate = ac97_clk.rate; | ||
680 | else | ||
681 | psc_calc_rate(clk, pscnum, np); | ||
682 | sprintf(clk->name, "psc%d_mclk", pscnum); | ||
683 | clk_register(clk); | ||
684 | clk_enable(clk); | ||
685 | } | ||
686 | } | ||
687 | } | ||
688 | |||
689 | static struct clk_interface mpc5121_clk_functions = { | ||
690 | .clk_get = mpc5121_clk_get, | ||
691 | .clk_enable = mpc5121_clk_enable, | ||
692 | .clk_disable = mpc5121_clk_disable, | ||
693 | .clk_get_rate = mpc5121_clk_get_rate, | ||
694 | .clk_put = mpc5121_clk_put, | ||
695 | .clk_round_rate = mpc5121_clk_round_rate, | ||
696 | .clk_set_rate = mpc5121_clk_set_rate, | ||
697 | .clk_set_parent = NULL, | ||
698 | .clk_get_parent = NULL, | ||
699 | }; | ||
700 | |||
701 | static int | ||
702 | mpc5121_clk_init(void) | ||
703 | { | ||
704 | struct device_node *np; | ||
705 | |||
706 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock"); | ||
707 | if (np) { | ||
708 | clockctl = of_iomap(np, 0); | ||
709 | of_node_put(np); | ||
710 | } | ||
711 | |||
712 | if (!clockctl) { | ||
713 | printk(KERN_ERR "Could not map clock control registers\n"); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | rate_clks_init(); | ||
718 | psc_clks_init(); | ||
719 | |||
720 | /* leave clockctl mapped forever */ | ||
721 | /*iounmap(clockctl); */ | ||
722 | DEBUG_CLK_DUMP(); | ||
723 | clocks_initialized++; | ||
724 | clk_functions = mpc5121_clk_functions; | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | |||
729 | arch_initcall(mpc5121_clk_init); | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c index 50bd3a319022..5ebf6939a697 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | 2 | * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 | 4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 |
5 | * | 5 | * |
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/irq.h> | ||
19 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
20 | 19 | ||
21 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
@@ -23,65 +22,22 @@ | |||
23 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
24 | #include <asm/time.h> | 23 | #include <asm/time.h> |
25 | 24 | ||
26 | /** | 25 | #include "mpc512x.h" |
27 | * mpc512x_find_ips_freq - Find the IPS bus frequency for a device | 26 | #include "mpc5121_ads.h" |
28 | * @node: device node | ||
29 | * | ||
30 | * Returns IPS bus frequency, or 0 if the bus frequency cannot be found. | ||
31 | */ | ||
32 | unsigned long | ||
33 | mpc512x_find_ips_freq(struct device_node *node) | ||
34 | { | ||
35 | struct device_node *np; | ||
36 | const unsigned int *p_ips_freq = NULL; | ||
37 | |||
38 | of_node_get(node); | ||
39 | while (node) { | ||
40 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
41 | if (p_ips_freq) | ||
42 | break; | ||
43 | |||
44 | np = of_get_parent(node); | ||
45 | of_node_put(node); | ||
46 | node = np; | ||
47 | } | ||
48 | if (node) | ||
49 | of_node_put(node); | ||
50 | |||
51 | return p_ips_freq ? *p_ips_freq : 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
54 | |||
55 | static struct of_device_id __initdata of_bus_ids[] = { | ||
56 | { .name = "soc", }, | ||
57 | { .name = "localbus", }, | ||
58 | {}, | ||
59 | }; | ||
60 | 27 | ||
61 | static void __init mpc5121_ads_declare_of_platform_devices(void) | 28 | static void __init mpc5121_ads_setup_arch(void) |
62 | { | 29 | { |
63 | /* Find every child of the SOC node and add it to of_platform */ | 30 | printk(KERN_INFO "MPC5121 ADS board from Freescale Semiconductor\n"); |
64 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | 31 | /* |
65 | printk(KERN_ERR __FILE__ ": " | 32 | * cpld regs are needed early |
66 | "Error while probing of_platform bus\n"); | 33 | */ |
34 | mpc5121_ads_cpld_map(); | ||
67 | } | 35 | } |
68 | 36 | ||
69 | static void __init mpc5121_ads_init_IRQ(void) | 37 | static void __init mpc5121_ads_init_IRQ(void) |
70 | { | 38 | { |
71 | struct device_node *np; | 39 | mpc512x_init_IRQ(); |
72 | 40 | mpc5121_ads_cpld_pic_init(); | |
73 | np = of_find_compatible_node(NULL, NULL, "fsl,ipic"); | ||
74 | if (!np) | ||
75 | return; | ||
76 | |||
77 | ipic_init(np, 0); | ||
78 | of_node_put(np); | ||
79 | |||
80 | /* | ||
81 | * Initialize the default interrupt mapping priorities, | ||
82 | * in case the boot rom changed something on us. | ||
83 | */ | ||
84 | ipic_set_default_priority(); | ||
85 | } | 41 | } |
86 | 42 | ||
87 | /* | 43 | /* |
@@ -97,7 +53,8 @@ static int __init mpc5121_ads_probe(void) | |||
97 | define_machine(mpc5121_ads) { | 53 | define_machine(mpc5121_ads) { |
98 | .name = "MPC5121 ADS", | 54 | .name = "MPC5121 ADS", |
99 | .probe = mpc5121_ads_probe, | 55 | .probe = mpc5121_ads_probe, |
100 | .init = mpc5121_ads_declare_of_platform_devices, | 56 | .setup_arch = mpc5121_ads_setup_arch, |
57 | .init = mpc512x_declare_of_platform_devices, | ||
101 | .init_IRQ = mpc5121_ads_init_IRQ, | 58 | .init_IRQ = mpc5121_ads_init_IRQ, |
102 | .get_irq = ipic_get_irq, | 59 | .get_irq = ipic_get_irq, |
103 | .calibrate_decr = generic_calibrate_decr, | 60 | .calibrate_decr = generic_calibrate_decr, |
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.h b/arch/powerpc/platforms/512x/mpc5121_ads.h new file mode 100644 index 000000000000..662076cfee2f --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * Prototypes for ADS5121 specific code | ||
10 | */ | ||
11 | |||
12 | #ifndef __MPC512ADS_H__ | ||
13 | #define __MPC512ADS_H__ | ||
14 | extern void __init mpc5121_ads_cpld_map(void); | ||
15 | extern void __init mpc5121_ads_cpld_pic_init(void); | ||
16 | #endif /* __MPC512ADS_H__ */ | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c new file mode 100644 index 000000000000..a6ce80566625 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com> | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121ADS CPLD irq handling | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #undef DEBUG | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <asm/prom.h> | ||
22 | |||
23 | static struct device_node *cpld_pic_node; | ||
24 | static struct irq_host *cpld_pic_host; | ||
25 | |||
26 | /* | ||
27 | * Bits to ignore in the misc_status register | ||
28 | * 0x10 touch screen pendown is hard routed to irq1 | ||
29 | * 0x02 pci status is read from pci status register | ||
30 | */ | ||
31 | #define MISC_IGNORE 0x12 | ||
32 | |||
33 | /* | ||
34 | * Nothing to ignore in pci status register | ||
35 | */ | ||
36 | #define PCI_IGNORE 0x00 | ||
37 | |||
38 | struct cpld_pic { | ||
39 | u8 pci_mask; | ||
40 | u8 pci_status; | ||
41 | u8 route; | ||
42 | u8 misc_mask; | ||
43 | u8 misc_status; | ||
44 | u8 misc_control; | ||
45 | }; | ||
46 | |||
47 | static struct cpld_pic __iomem *cpld_regs; | ||
48 | |||
49 | static void __iomem * | ||
50 | irq_to_pic_mask(unsigned int irq) | ||
51 | { | ||
52 | return irq <= 7 ? &cpld_regs->pci_mask : &cpld_regs->misc_mask; | ||
53 | } | ||
54 | |||
55 | static unsigned int | ||
56 | irq_to_pic_bit(unsigned int irq) | ||
57 | { | ||
58 | return 1 << (irq & 0x7); | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | cpld_mask_irq(unsigned int irq) | ||
63 | { | ||
64 | unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq; | ||
65 | void __iomem *pic_mask = irq_to_pic_mask(cpld_irq); | ||
66 | |||
67 | out_8(pic_mask, | ||
68 | in_8(pic_mask) | irq_to_pic_bit(cpld_irq)); | ||
69 | } | ||
70 | |||
71 | static void | ||
72 | cpld_unmask_irq(unsigned int irq) | ||
73 | { | ||
74 | unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq; | ||
75 | void __iomem *pic_mask = irq_to_pic_mask(cpld_irq); | ||
76 | |||
77 | out_8(pic_mask, | ||
78 | in_8(pic_mask) & ~irq_to_pic_bit(cpld_irq)); | ||
79 | } | ||
80 | |||
81 | static struct irq_chip cpld_pic = { | ||
82 | .typename = " CPLD PIC ", | ||
83 | .mask = cpld_mask_irq, | ||
84 | .ack = cpld_mask_irq, | ||
85 | .unmask = cpld_unmask_irq, | ||
86 | }; | ||
87 | |||
88 | static int | ||
89 | cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp, | ||
90 | u8 __iomem *maskp) | ||
91 | { | ||
92 | int cpld_irq; | ||
93 | u8 status = in_8(statusp); | ||
94 | u8 mask = in_8(maskp); | ||
95 | |||
96 | /* ignore don't cares and masked irqs */ | ||
97 | status |= (ignore | mask); | ||
98 | |||
99 | if (status == 0xff) | ||
100 | return NO_IRQ_IGNORE; | ||
101 | |||
102 | cpld_irq = ffz(status) + offset; | ||
103 | |||
104 | return irq_linear_revmap(cpld_pic_host, cpld_irq); | ||
105 | } | ||
106 | |||
107 | static void | ||
108 | cpld_pic_cascade(unsigned int irq, struct irq_desc *desc) | ||
109 | { | ||
110 | irq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status, | ||
111 | &cpld_regs->pci_mask); | ||
112 | if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) { | ||
113 | generic_handle_irq(irq); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | irq = cpld_pic_get_irq(8, MISC_IGNORE, &cpld_regs->misc_status, | ||
118 | &cpld_regs->misc_mask); | ||
119 | if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) { | ||
120 | generic_handle_irq(irq); | ||
121 | return; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | static int | ||
126 | cpld_pic_host_match(struct irq_host *h, struct device_node *node) | ||
127 | { | ||
128 | return cpld_pic_node == node; | ||
129 | } | ||
130 | |||
131 | static int | ||
132 | cpld_pic_host_map(struct irq_host *h, unsigned int virq, | ||
133 | irq_hw_number_t hw) | ||
134 | { | ||
135 | get_irq_desc(virq)->status |= IRQ_LEVEL; | ||
136 | set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static struct | ||
141 | irq_host_ops cpld_pic_host_ops = { | ||
142 | .match = cpld_pic_host_match, | ||
143 | .map = cpld_pic_host_map, | ||
144 | }; | ||
145 | |||
146 | void __init | ||
147 | mpc5121_ads_cpld_map(void) | ||
148 | { | ||
149 | struct device_node *np = NULL; | ||
150 | |||
151 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld-pic"); | ||
152 | if (!np) { | ||
153 | printk(KERN_ERR "CPLD PIC init: can not find cpld-pic node\n"); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | cpld_regs = of_iomap(np, 0); | ||
158 | of_node_put(np); | ||
159 | } | ||
160 | |||
161 | void __init | ||
162 | mpc5121_ads_cpld_pic_init(void) | ||
163 | { | ||
164 | unsigned int cascade_irq; | ||
165 | struct device_node *np = NULL; | ||
166 | |||
167 | pr_debug("cpld_ic_init\n"); | ||
168 | |||
169 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld-pic"); | ||
170 | if (!np) { | ||
171 | printk(KERN_ERR "CPLD PIC init: can not find cpld-pic node\n"); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | if (!cpld_regs) | ||
176 | goto end; | ||
177 | |||
178 | cascade_irq = irq_of_parse_and_map(np, 0); | ||
179 | if (cascade_irq == NO_IRQ) | ||
180 | goto end; | ||
181 | |||
182 | /* | ||
183 | * statically route touch screen pendown through 1 | ||
184 | * and ignore it here | ||
185 | * route all others through our cascade irq | ||
186 | */ | ||
187 | out_8(&cpld_regs->route, 0xfd); | ||
188 | out_8(&cpld_regs->pci_mask, 0xff); | ||
189 | /* unmask pci ints in misc mask */ | ||
190 | out_8(&cpld_regs->misc_mask, ~(MISC_IGNORE)); | ||
191 | |||
192 | cpld_pic_node = of_node_get(np); | ||
193 | |||
194 | cpld_pic_host = | ||
195 | irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, 16, &cpld_pic_host_ops, 16); | ||
196 | if (!cpld_pic_host) { | ||
197 | printk(KERN_ERR "CPLD PIC: failed to allocate irq host!\n"); | ||
198 | goto end; | ||
199 | } | ||
200 | |||
201 | set_irq_chained_handler(cascade_irq, cpld_pic_cascade); | ||
202 | end: | ||
203 | of_node_put(np); | ||
204 | } | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c new file mode 100644 index 000000000000..2479de9e2d12 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_generic.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com> | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 SoC setup | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | |||
19 | #include <asm/machdep.h> | ||
20 | #include <asm/ipic.h> | ||
21 | #include <asm/prom.h> | ||
22 | #include <asm/time.h> | ||
23 | |||
24 | #include "mpc512x.h" | ||
25 | |||
26 | /* | ||
27 | * list of supported boards | ||
28 | */ | ||
29 | static char *board[] __initdata = { | ||
30 | "prt,prtlvt", | ||
31 | NULL | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * Called very early, MMU is off, device-tree isn't unflattened | ||
36 | */ | ||
37 | static int __init mpc5121_generic_probe(void) | ||
38 | { | ||
39 | unsigned long node = of_get_flat_dt_root(); | ||
40 | int i = 0; | ||
41 | |||
42 | while (board[i]) { | ||
43 | if (of_flat_dt_is_compatible(node, board[i])) | ||
44 | break; | ||
45 | i++; | ||
46 | } | ||
47 | |||
48 | return board[i] != NULL; | ||
49 | } | ||
50 | |||
51 | define_machine(mpc5121_generic) { | ||
52 | .name = "MPC5121 generic", | ||
53 | .probe = mpc5121_generic_probe, | ||
54 | .init = mpc512x_declare_of_platform_devices, | ||
55 | .init_IRQ = mpc512x_init_IRQ, | ||
56 | .get_irq = ipic_get_irq, | ||
57 | .calibrate_decr = generic_calibrate_decr, | ||
58 | }; | ||
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h new file mode 100644 index 000000000000..9c03693cb009 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc512x.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * Prototypes for MPC512x shared code | ||
10 | */ | ||
11 | |||
12 | #ifndef __MPC512X_H__ | ||
13 | #define __MPC512X_H__ | ||
14 | extern unsigned long mpc512x_find_ips_freq(struct device_node *node); | ||
15 | extern void __init mpc512x_init_IRQ(void); | ||
16 | void __init mpc512x_declare_of_platform_devices(void); | ||
17 | #endif /* __MPC512X_H__ */ | ||
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c new file mode 100644 index 000000000000..d8cd579f3191 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby <jrigby@freescale.com> | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC512x Shared code | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | |||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/ipic.h> | ||
22 | #include <asm/prom.h> | ||
23 | #include <asm/time.h> | ||
24 | |||
25 | #include "mpc512x.h" | ||
26 | |||
27 | unsigned long | ||
28 | mpc512x_find_ips_freq(struct device_node *node) | ||
29 | { | ||
30 | struct device_node *np; | ||
31 | const unsigned int *p_ips_freq = NULL; | ||
32 | |||
33 | of_node_get(node); | ||
34 | while (node) { | ||
35 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
36 | if (p_ips_freq) | ||
37 | break; | ||
38 | |||
39 | np = of_get_parent(node); | ||
40 | of_node_put(node); | ||
41 | node = np; | ||
42 | } | ||
43 | if (node) | ||
44 | of_node_put(node); | ||
45 | |||
46 | return p_ips_freq ? *p_ips_freq : 0; | ||
47 | } | ||
48 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
49 | |||
50 | void __init mpc512x_init_IRQ(void) | ||
51 | { | ||
52 | struct device_node *np; | ||
53 | |||
54 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-ipic"); | ||
55 | if (!np) | ||
56 | return; | ||
57 | |||
58 | ipic_init(np, 0); | ||
59 | of_node_put(np); | ||
60 | |||
61 | /* | ||
62 | * Initialize the default interrupt mapping priorities, | ||
63 | * in case the boot rom changed something on us. | ||
64 | */ | ||
65 | ipic_set_default_priority(); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Nodes to do bus probe on, soc and localbus | ||
70 | */ | ||
71 | static struct of_device_id __initdata of_bus_ids[] = { | ||
72 | { .compatible = "fsl,mpc5121-immr", }, | ||
73 | { .compatible = "fsl,mpc5121-localbus", }, | ||
74 | {}, | ||
75 | }; | ||
76 | |||
77 | void __init mpc512x_declare_of_platform_devices(void) | ||
78 | { | ||
79 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | ||
80 | printk(KERN_ERR __FILE__ ": " | ||
81 | "Error while probing of_platform bus\n"); | ||
82 | } | ||
83 | |||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index e3428ddd9040..5a382bb15f62 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c | |||
@@ -63,6 +63,7 @@ | |||
63 | 63 | ||
64 | #define MPC52xx_PCI_TCR_P 0x01000000 | 64 | #define MPC52xx_PCI_TCR_P 0x01000000 |
65 | #define MPC52xx_PCI_TCR_LD 0x00010000 | 65 | #define MPC52xx_PCI_TCR_LD 0x00010000 |
66 | #define MPC52xx_PCI_TCR_WCT8 0x00000008 | ||
66 | 67 | ||
67 | #define MPC52xx_PCI_TBATR_DISABLE 0x0 | 68 | #define MPC52xx_PCI_TBATR_DISABLE 0x0 |
68 | #define MPC52xx_PCI_TBATR_ENABLE 0x1 | 69 | #define MPC52xx_PCI_TBATR_ENABLE 0x1 |
@@ -313,7 +314,7 @@ mpc52xx_pci_setup(struct pci_controller *hose, | |||
313 | out_be32(&pci_regs->tbatr1, | 314 | out_be32(&pci_regs->tbatr1, |
314 | MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM ); | 315 | MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM ); |
315 | 316 | ||
316 | out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD); | 317 | out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD | MPC52xx_PCI_TCR_WCT8); |
317 | 318 | ||
318 | tmp = in_be32(&pci_regs->gscr); | 319 | tmp = in_be32(&pci_regs->gscr); |
319 | #if 0 | 320 | #if 0 |
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c index 64ec7d629363..446c9ea85b30 100644 --- a/arch/powerpc/sysdev/bestcomm/bestcomm.c +++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c | |||
@@ -443,7 +443,7 @@ mpc52xx_bcom_probe(struct of_device *op, const struct of_device_id *match) | |||
443 | 443 | ||
444 | /* Done ! */ | 444 | /* Done ! */ |
445 | printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n", | 445 | printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n", |
446 | bcom_eng->regs_base); | 446 | (long)bcom_eng->regs_base); |
447 | 447 | ||
448 | return 0; | 448 | return 0; |
449 | 449 | ||
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c index 8d33eafbb3f4..a3a134c35b0a 100644 --- a/arch/powerpc/sysdev/bestcomm/gen_bd.c +++ b/arch/powerpc/sysdev/bestcomm/gen_bd.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | 21 | ||
22 | #include <asm/mpc52xx.h> | 22 | #include <asm/mpc52xx.h> |
23 | #include <asm/mpc52xx_psc.h> | ||
23 | 24 | ||
24 | #include "bestcomm.h" | 25 | #include "bestcomm.h" |
25 | #include "bestcomm_priv.h" | 26 | #include "bestcomm_priv.h" |
@@ -253,6 +254,100 @@ bcom_gen_bd_tx_release(struct bcom_task *tsk) | |||
253 | } | 254 | } |
254 | EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release); | 255 | EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release); |
255 | 256 | ||
257 | /* --------------------------------------------------------------------- | ||
258 | * PSC support code | ||
259 | */ | ||
260 | |||
261 | /** | ||
262 | * bcom_psc_parameters - Bestcomm initialization value table for PSC devices | ||
263 | * | ||
264 | * This structure is only used internally. It is a lookup table for PSC | ||
265 | * specific parameters to bestcomm tasks. | ||
266 | */ | ||
267 | static struct bcom_psc_params { | ||
268 | int rx_initiator; | ||
269 | int rx_ipr; | ||
270 | int tx_initiator; | ||
271 | int tx_ipr; | ||
272 | } bcom_psc_params[] = { | ||
273 | [0] = { | ||
274 | .rx_initiator = BCOM_INITIATOR_PSC1_RX, | ||
275 | .rx_ipr = BCOM_IPR_PSC1_RX, | ||
276 | .tx_initiator = BCOM_INITIATOR_PSC1_TX, | ||
277 | .tx_ipr = BCOM_IPR_PSC1_TX, | ||
278 | }, | ||
279 | [1] = { | ||
280 | .rx_initiator = BCOM_INITIATOR_PSC2_RX, | ||
281 | .rx_ipr = BCOM_IPR_PSC2_RX, | ||
282 | .tx_initiator = BCOM_INITIATOR_PSC2_TX, | ||
283 | .tx_ipr = BCOM_IPR_PSC2_TX, | ||
284 | }, | ||
285 | [2] = { | ||
286 | .rx_initiator = BCOM_INITIATOR_PSC3_RX, | ||
287 | .rx_ipr = BCOM_IPR_PSC3_RX, | ||
288 | .tx_initiator = BCOM_INITIATOR_PSC3_TX, | ||
289 | .tx_ipr = BCOM_IPR_PSC3_TX, | ||
290 | }, | ||
291 | [3] = { | ||
292 | .rx_initiator = BCOM_INITIATOR_PSC4_RX, | ||
293 | .rx_ipr = BCOM_IPR_PSC4_RX, | ||
294 | .tx_initiator = BCOM_INITIATOR_PSC4_TX, | ||
295 | .tx_ipr = BCOM_IPR_PSC4_TX, | ||
296 | }, | ||
297 | [4] = { | ||
298 | .rx_initiator = BCOM_INITIATOR_PSC5_RX, | ||
299 | .rx_ipr = BCOM_IPR_PSC5_RX, | ||
300 | .tx_initiator = BCOM_INITIATOR_PSC5_TX, | ||
301 | .tx_ipr = BCOM_IPR_PSC5_TX, | ||
302 | }, | ||
303 | [5] = { | ||
304 | .rx_initiator = BCOM_INITIATOR_PSC6_RX, | ||
305 | .rx_ipr = BCOM_IPR_PSC6_RX, | ||
306 | .tx_initiator = BCOM_INITIATOR_PSC6_TX, | ||
307 | .tx_ipr = BCOM_IPR_PSC6_TX, | ||
308 | }, | ||
309 | }; | ||
310 | |||
311 | /** | ||
312 | * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port | ||
313 | * @psc_num: Number of the PSC to allocate a task for | ||
314 | * @queue_len: number of buffer descriptors to allocate for the task | ||
315 | * @fifo: physical address of FIFO register | ||
316 | * @maxbufsize: Maximum receive data size in bytes. | ||
317 | * | ||
318 | * Allocate a bestcomm task structure for receiving data from a PSC. | ||
319 | */ | ||
320 | struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len, | ||
321 | phys_addr_t fifo, int maxbufsize) | ||
322 | { | ||
323 | if (psc_num >= MPC52xx_PSC_MAXNUM) | ||
324 | return NULL; | ||
325 | |||
326 | return bcom_gen_bd_rx_init(queue_len, fifo, | ||
327 | bcom_psc_params[psc_num].rx_initiator, | ||
328 | bcom_psc_params[psc_num].rx_ipr, | ||
329 | maxbufsize); | ||
330 | } | ||
331 | EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init); | ||
332 | |||
333 | /** | ||
334 | * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port | ||
335 | * @psc_num: Number of the PSC to allocate a task for | ||
336 | * @queue_len: number of buffer descriptors to allocate for the task | ||
337 | * @fifo: physical address of FIFO register | ||
338 | * | ||
339 | * Allocate a bestcomm task structure for transmitting data to a PSC. | ||
340 | */ | ||
341 | struct bcom_task * | ||
342 | bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo) | ||
343 | { | ||
344 | struct psc; | ||
345 | return bcom_gen_bd_tx_init(queue_len, fifo, | ||
346 | bcom_psc_params[psc_num].tx_initiator, | ||
347 | bcom_psc_params[psc_num].tx_ipr); | ||
348 | } | ||
349 | EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init); | ||
350 | |||
256 | 351 | ||
257 | MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver"); | 352 | MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver"); |
258 | MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>"); | 353 | MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>"); |
diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.h b/arch/powerpc/sysdev/bestcomm/gen_bd.h index 5b6fa803c6aa..de47260e69da 100644 --- a/arch/powerpc/sysdev/bestcomm/gen_bd.h +++ b/arch/powerpc/sysdev/bestcomm/gen_bd.h | |||
@@ -44,5 +44,10 @@ extern void | |||
44 | bcom_gen_bd_tx_release(struct bcom_task *tsk); | 44 | bcom_gen_bd_tx_release(struct bcom_task *tsk); |
45 | 45 | ||
46 | 46 | ||
47 | /* PSC support utility wrappers */ | ||
48 | struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len, | ||
49 | phys_addr_t fifo, int maxbufsize); | ||
50 | struct bcom_task * bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, | ||
51 | phys_addr_t fifo); | ||
47 | #endif /* __BESTCOMM_GEN_BD_H__ */ | 52 | #endif /* __BESTCOMM_GEN_BD_H__ */ |
48 | 53 | ||
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c index 99784383a843..5d74ef7a651f 100644 --- a/arch/powerpc/sysdev/bestcomm/sram.c +++ b/arch/powerpc/sysdev/bestcomm/sram.c | |||
@@ -86,7 +86,7 @@ int bcom_sram_init(struct device_node *sram_node, char *owner) | |||
86 | if (!bcom_sram->base_virt) { | 86 | if (!bcom_sram->base_virt) { |
87 | printk(KERN_ERR "%s: bcom_sram_init: " | 87 | printk(KERN_ERR "%s: bcom_sram_init: " |
88 | "Map error SRAM zone 0x%08lx (0x%0x)!\n", | 88 | "Map error SRAM zone 0x%08lx (0x%0x)!\n", |
89 | owner, bcom_sram->base_phys, bcom_sram->size ); | 89 | owner, (long)bcom_sram->base_phys, bcom_sram->size ); |
90 | rv = -ENOMEM; | 90 | rv = -ENOMEM; |
91 | goto error_release; | 91 | goto error_release; |
92 | } | 92 | } |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index ca54563d5c7e..ebcec7362f95 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -414,139 +414,6 @@ err: | |||
414 | 414 | ||
415 | arch_initcall(gfar_of_init); | 415 | arch_initcall(gfar_of_init); |
416 | 416 | ||
417 | #ifdef CONFIG_I2C_BOARDINFO | ||
418 | #include <linux/i2c.h> | ||
419 | struct i2c_driver_device { | ||
420 | char *of_device; | ||
421 | char *i2c_type; | ||
422 | }; | ||
423 | |||
424 | static struct i2c_driver_device i2c_devices[] __initdata = { | ||
425 | {"ricoh,rs5c372a", "rs5c372a"}, | ||
426 | {"ricoh,rs5c372b", "rs5c372b"}, | ||
427 | {"ricoh,rv5c386", "rv5c386"}, | ||
428 | {"ricoh,rv5c387a", "rv5c387a"}, | ||
429 | {"dallas,ds1307", "ds1307"}, | ||
430 | {"dallas,ds1337", "ds1337"}, | ||
431 | {"dallas,ds1338", "ds1338"}, | ||
432 | {"dallas,ds1339", "ds1339"}, | ||
433 | {"dallas,ds1340", "ds1340"}, | ||
434 | {"stm,m41t00", "m41t00"}, | ||
435 | {"dallas,ds1374", "ds1374"}, | ||
436 | {"cirrus,cs4270", "cs4270"}, | ||
437 | }; | ||
438 | |||
439 | static int __init of_find_i2c_driver(struct device_node *node, | ||
440 | struct i2c_board_info *info) | ||
441 | { | ||
442 | int i; | ||
443 | |||
444 | for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { | ||
445 | if (!of_device_is_compatible(node, i2c_devices[i].of_device)) | ||
446 | continue; | ||
447 | if (strlcpy(info->type, i2c_devices[i].i2c_type, | ||
448 | I2C_NAME_SIZE) >= I2C_NAME_SIZE) | ||
449 | return -ENOMEM; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | pr_warning("fsl_soc.c: unrecognized i2c node %s\n", | ||
454 | (const char *) of_get_property(node, "compatible", NULL)); | ||
455 | |||
456 | return -ENODEV; | ||
457 | } | ||
458 | |||
459 | static void __init of_register_i2c_devices(struct device_node *adap_node, | ||
460 | int bus_num) | ||
461 | { | ||
462 | struct device_node *node = NULL; | ||
463 | |||
464 | while ((node = of_get_next_child(adap_node, node))) { | ||
465 | struct i2c_board_info info = {}; | ||
466 | const u32 *addr; | ||
467 | int len; | ||
468 | |||
469 | addr = of_get_property(node, "reg", &len); | ||
470 | if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) { | ||
471 | printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n"); | ||
472 | continue; | ||
473 | } | ||
474 | |||
475 | info.irq = irq_of_parse_and_map(node, 0); | ||
476 | if (info.irq == NO_IRQ) | ||
477 | info.irq = -1; | ||
478 | |||
479 | if (of_find_i2c_driver(node, &info) < 0) | ||
480 | continue; | ||
481 | |||
482 | info.addr = *addr; | ||
483 | |||
484 | i2c_register_board_info(bus_num, &info, 1); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | static int __init fsl_i2c_of_init(void) | ||
489 | { | ||
490 | struct device_node *np; | ||
491 | unsigned int i = 0; | ||
492 | struct platform_device *i2c_dev; | ||
493 | int ret; | ||
494 | |||
495 | for_each_compatible_node(np, NULL, "fsl-i2c") { | ||
496 | struct resource r[2]; | ||
497 | struct fsl_i2c_platform_data i2c_data; | ||
498 | const unsigned char *flags = NULL; | ||
499 | int idx; | ||
500 | const u32 *iprop; | ||
501 | |||
502 | memset(&r, 0, sizeof(r)); | ||
503 | memset(&i2c_data, 0, sizeof(i2c_data)); | ||
504 | |||
505 | ret = of_address_to_resource(np, 0, &r[0]); | ||
506 | if (ret) | ||
507 | goto err; | ||
508 | |||
509 | of_irq_to_resource(np, 0, &r[1]); | ||
510 | |||
511 | iprop = of_get_property(np, "cell-index", NULL); | ||
512 | idx = iprop ? *iprop : i; | ||
513 | |||
514 | i2c_dev = platform_device_register_simple("fsl-i2c", idx, r, 2); | ||
515 | if (IS_ERR(i2c_dev)) { | ||
516 | ret = PTR_ERR(i2c_dev); | ||
517 | goto err; | ||
518 | } | ||
519 | |||
520 | i2c_data.device_flags = 0; | ||
521 | flags = of_get_property(np, "dfsrr", NULL); | ||
522 | if (flags) | ||
523 | i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; | ||
524 | |||
525 | flags = of_get_property(np, "fsl5200-clocking", NULL); | ||
526 | if (flags) | ||
527 | i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; | ||
528 | |||
529 | ret = | ||
530 | platform_device_add_data(i2c_dev, &i2c_data, | ||
531 | sizeof(struct | ||
532 | fsl_i2c_platform_data)); | ||
533 | if (ret) | ||
534 | goto unreg; | ||
535 | |||
536 | of_register_i2c_devices(np, idx); | ||
537 | i++; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | |||
542 | unreg: | ||
543 | platform_device_unregister(i2c_dev); | ||
544 | err: | ||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | arch_initcall(fsl_i2c_of_init); | ||
549 | #endif | ||
550 | 417 | ||
551 | #ifdef CONFIG_PPC_83xx | 418 | #ifdef CONFIG_PPC_83xx |
552 | static int __init mpc83xx_wdt_init(void) | 419 | static int __init mpc83xx_wdt_init(void) |