aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS4
-rw-r--r--Makefile1
-rw-r--r--arch/powerpc/boot/dts/mpc5121ads.dts310
-rw-r--r--arch/powerpc/boot/dts/tqm5200.dts14
-rw-r--r--arch/powerpc/platforms/512x/Kconfig17
-rw-r--r--arch/powerpc/platforms/512x/Makefile4
-rw-r--r--arch/powerpc/platforms/512x/clock.c729
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_ads.c69
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_ads.h16
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_ads_cpld.c204
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_generic.c58
-rw-r--r--arch/powerpc/platforms/512x/mpc512x.h17
-rw-r--r--arch/powerpc/platforms/512x/mpc512x_shared.c83
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c3
-rw-r--r--arch/powerpc/sysdev/bestcomm/bestcomm.c2
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.c95
-rw-r--r--arch/powerpc/sysdev/bestcomm/gen_bd.h5
-rw-r--r--arch/powerpc/sysdev/bestcomm/sram.c2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c133
-rw-r--r--drivers/ata/pata_mpc52xx.c2
-rw-r--r--drivers/i2c/busses/i2c-mpc.c104
-rw-r--r--drivers/of/of_i2c.c1
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c2
-rw-r--r--drivers/watchdog/mpc5200_wdt.c2
24 files changed, 1620 insertions, 257 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 56a2f678019e..8619861dd345 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2503,13 +2503,11 @@ W: http://www.penguinppc.org/
2503L: linuxppc-dev@ozlabs.org 2503L: linuxppc-dev@ozlabs.org
2504S: Maintained 2504S: Maintained
2505 2505
2506LINUX FOR POWERPC EMBEDDED MPC52XX 2506LINUX FOR POWERPC EMBEDDED MPC5XXX
2507P: Sylvain Munaut 2507P: Sylvain Munaut
2508M: tnt@246tNt.com 2508M: tnt@246tNt.com
2509P: Grant Likely 2509P: Grant Likely
2510M: grant.likely@secretlab.ca 2510M: grant.likely@secretlab.ca
2511W: http://www.246tNt.com/mpc52xx/
2512W: http://www.penguinppc.org/
2513L: linuxppc-dev@ozlabs.org 2511L: linuxppc-dev@ozlabs.org
2514S: Maintained 2512S: Maintained
2515 2513
diff --git a/Makefile b/Makefile
index e3c5eb66ec52..7c917e930835 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
1FRED=42
1VERSION = 2 2VERSION = 2
2PATCHLEVEL = 6 3PATCHLEVEL = 6
3SUBLEVEL = 26 4SUBLEVEL = 26
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
7config PPC_MPC5121 7config PPC_MPC5121
8 bool 8 bool
9 select PPC_MPC512x 9 select PPC_MPC512x
10 default n
11 10
12config MPC5121_ADS 11config 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
20config 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#
4obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o 4obj-y += clock.o mpc512x_shared.o
5obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o
6obj-$(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
32static 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
37struct 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
50static LIST_HEAD(clocks);
51static DEFINE_MUTEX(clocks_mutex);
52
53static 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
79static 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
102static void mpc5121_clk_put(struct clk *clk)
103{
104 module_put(clk->owner);
105}
106
107#define NRPSC 12
108
109struct 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
122struct mpc512x_clockctl __iomem *clockctl;
123
124static 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
136static 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
147static 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
155static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
156{
157 return rate;
158}
159
160static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
161{
162 return 0;
163}
164
165static 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
173static 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
188static 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
210static 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
219static 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
228static 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
237static 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
253static 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
266static struct clk ref_clk = {
267 .name = "ref_clk",
268 .calc = ref_clk_calc,
269};
270
271
272static void sys_clk_calc(struct clk *clk)
273{
274 clk->rate = ref_to_sys(ref_clk.rate);
275}
276
277static struct clk sys_clk = {
278 .name = "sys_clk",
279 .calc = sys_clk_calc,
280};
281
282static 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
295static void half_clk_calc(struct clk *clk)
296{
297 clk->rate = clk->parent->rate / 2;
298}
299
300static 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
307static void unity_clk_calc(struct clk *clk)
308{
309 clk->rate = clk->parent->rate;
310}
311
312static struct clk csb_clk = {
313 .name = "csb_clk",
314 .calc = half_clk_calc,
315 .parent = &sys_clk,
316};
317
318static 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
326static struct clk e300_clk = {
327 .name = "e300_clk",
328 .calc = e300_clk_calc,
329 .parent = &csb_clk,
330};
331
332static 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 */
342static 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
352static 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
362static 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
376static 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
385static 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
394static 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 */
407static 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
415static 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
424static 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
433static 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
442static 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
451static 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
460static 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
469static 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
478static 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
487static 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
497static 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
504static struct clk psc_mclk_in = {
505 .name = "psc_mclk_in",
506 .calc = psc_mclk_in_calc,
507};
508
509static struct clk spdif_txclk = {
510 .name = "spdif_txclk",
511 .flags = CLK_HAS_CTRL,
512 .reg = 1,
513 .bit = 23,
514};
515
516static struct clk spdif_rxclk = {
517 .name = "spdif_rxclk",
518 .flags = CLK_HAS_CTRL,
519 .reg = 1,
520 .bit = 23,
521};
522
523static void ac97_clk_calc(struct clk *clk)
524{
525 /* ac97 bit clock is always 24.567 MHz */
526 clk->rate = 24567000;
527}
528
529static struct clk ac97_clk = {
530 .name = "ac97_clk_in",
531 .calc = ac97_clk_calc,
532};
533
534struct 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
563static 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
576static 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 */
589struct clk dev_clks[2][32];
590
591/*
592 * Given a psc number return the dev_clk
593 * associated with it
594 */
595static 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 */
612static 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 */
659static 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
689static 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
701static int
702mpc5121_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
729arch_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 */
32unsigned long
33mpc512x_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}
53EXPORT_SYMBOL(mpc512x_find_ips_freq);
54
55static struct of_device_id __initdata of_bus_ids[] = {
56 { .name = "soc", },
57 { .name = "localbus", },
58 {},
59};
60 27
61static void __init mpc5121_ads_declare_of_platform_devices(void) 28static 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
69static void __init mpc5121_ads_init_IRQ(void) 37static 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)
97define_machine(mpc5121_ads) { 53define_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__
14extern void __init mpc5121_ads_cpld_map(void);
15extern 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
23static struct device_node *cpld_pic_node;
24static 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
38struct 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
47static struct cpld_pic __iomem *cpld_regs;
48
49static void __iomem *
50irq_to_pic_mask(unsigned int irq)
51{
52 return irq <= 7 ? &cpld_regs->pci_mask : &cpld_regs->misc_mask;
53}
54
55static unsigned int
56irq_to_pic_bit(unsigned int irq)
57{
58 return 1 << (irq & 0x7);
59}
60
61static void
62cpld_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
71static void
72cpld_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
81static 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
88static int
89cpld_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
107static void
108cpld_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
125static int
126cpld_pic_host_match(struct irq_host *h, struct device_node *node)
127{
128 return cpld_pic_node == node;
129}
130
131static int
132cpld_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
140static struct
141irq_host_ops cpld_pic_host_ops = {
142 .match = cpld_pic_host_match,
143 .map = cpld_pic_host_map,
144};
145
146void __init
147mpc5121_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
161void __init
162mpc5121_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);
202end:
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 */
29static char *board[] __initdata = {
30 "prt,prtlvt",
31 NULL
32};
33
34/*
35 * Called very early, MMU is off, device-tree isn't unflattened
36 */
37static 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
51define_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__
14extern unsigned long mpc512x_find_ips_freq(struct device_node *node);
15extern void __init mpc512x_init_IRQ(void);
16void __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
27unsigned long
28mpc512x_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}
48EXPORT_SYMBOL(mpc512x_find_ips_freq);
49
50void __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 */
71static struct of_device_id __initdata of_bus_ids[] = {
72 { .compatible = "fsl,mpc5121-immr", },
73 { .compatible = "fsl,mpc5121-localbus", },
74 {},
75};
76
77void __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}
254EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release); 255EXPORT_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 */
267static 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 */
320struct 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}
331EXPORT_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 */
341struct bcom_task *
342bcom_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}
349EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
350
256 351
257MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver"); 352MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
258MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>"); 353MODULE_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
44bcom_gen_bd_tx_release(struct bcom_task *tsk); 44bcom_gen_bd_tx_release(struct bcom_task *tsk);
45 45
46 46
47/* PSC support utility wrappers */
48struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
49 phys_addr_t fifo, int maxbufsize);
50struct 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
415arch_initcall(gfar_of_init); 415arch_initcall(gfar_of_init);
416 416
417#ifdef CONFIG_I2C_BOARDINFO
418#include <linux/i2c.h>
419struct i2c_driver_device {
420 char *of_device;
421 char *i2c_type;
422};
423
424static 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
439static 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
459static 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
488static 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
542unreg:
543 platform_device_unregister(i2c_dev);
544err:
545 return ret;
546}
547
548arch_initcall(fsl_i2c_of_init);
549#endif
550 417
551#ifdef CONFIG_PPC_83xx 418#ifdef CONFIG_PPC_83xx
552static int __init mpc83xx_wdt_init(void) 419static int __init mpc83xx_wdt_init(void)
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index bc79df6e7cb0..a9e827356d06 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -16,10 +16,10 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/libata.h> 18#include <linux/libata.h>
19#include <linux/of_platform.h>
19 20
20#include <asm/types.h> 21#include <asm/types.h>
21#include <asm/prom.h> 22#include <asm/prom.h>
22#include <asm/of_platform.h>
23#include <asm/mpc52xx.h> 23#include <asm/mpc52xx.h>
24 24
25 25
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a076129de7e8..4fdfb62d6f38 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -17,7 +17,8 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/platform_device.h> 20#include <linux/of_platform.h>
21#include <linux/of_i2c.h>
21 22
22#include <asm/io.h> 23#include <asm/io.h>
23#include <linux/fsl_devices.h> 24#include <linux/fsl_devices.h>
@@ -25,13 +26,13 @@
25#include <linux/interrupt.h> 26#include <linux/interrupt.h>
26#include <linux/delay.h> 27#include <linux/delay.h>
27 28
28#define MPC_I2C_ADDR 0x00 29#define DRV_NAME "mpc-i2c"
30
29#define MPC_I2C_FDR 0x04 31#define MPC_I2C_FDR 0x04
30#define MPC_I2C_CR 0x08 32#define MPC_I2C_CR 0x08
31#define MPC_I2C_SR 0x0c 33#define MPC_I2C_SR 0x0c
32#define MPC_I2C_DR 0x10 34#define MPC_I2C_DR 0x10
33#define MPC_I2C_DFSRR 0x14 35#define MPC_I2C_DFSRR 0x14
34#define MPC_I2C_REGION 0x20
35 36
36#define CCR_MEN 0x80 37#define CCR_MEN 0x80
37#define CCR_MIEN 0x40 38#define CCR_MIEN 0x40
@@ -315,102 +316,117 @@ static struct i2c_adapter mpc_ops = {
315 .timeout = 1, 316 .timeout = 1,
316}; 317};
317 318
318static int fsl_i2c_probe(struct platform_device *pdev) 319static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match)
319{ 320{
320 int result = 0; 321 int result = 0;
321 struct mpc_i2c *i2c; 322 struct mpc_i2c *i2c;
322 struct fsl_i2c_platform_data *pdata;
323 struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
324
325 pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
326 323
327 i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); 324 i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
328 if (!i2c) 325 if (!i2c)
329 return -ENOMEM; 326 return -ENOMEM;
330 327
331 i2c->irq = platform_get_irq(pdev, 0); 328 if (of_get_property(op->node, "dfsrr", NULL))
332 if (i2c->irq < 0) 329 i2c->flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
333 i2c->irq = NO_IRQ; /* Use polling */
334 330
335 i2c->flags = pdata->device_flags; 331 if (of_device_is_compatible(op->node, "fsl,mpc5200-i2c") ||
336 init_waitqueue_head(&i2c->queue); 332 of_device_is_compatible(op->node, "mpc5200-i2c"))
333 i2c->flags |= FSL_I2C_DEV_CLOCK_5200;
337 334
338 i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION); 335 init_waitqueue_head(&i2c->queue);
339 336
337 i2c->base = of_iomap(op->node, 0);
340 if (!i2c->base) { 338 if (!i2c->base) {
341 printk(KERN_ERR "i2c-mpc - failed to map controller\n"); 339 printk(KERN_ERR "i2c-mpc - failed to map controller\n");
342 result = -ENOMEM; 340 result = -ENOMEM;
343 goto fail_map; 341 goto fail_map;
344 } 342 }
345 343
346 if (i2c->irq != NO_IRQ) 344 i2c->irq = irq_of_parse_and_map(op->node, 0);
347 if ((result = request_irq(i2c->irq, mpc_i2c_isr, 345 if (i2c->irq != NO_IRQ) { /* i2c->irq = NO_IRQ implies polling */
348 IRQF_SHARED, "i2c-mpc", i2c)) < 0) { 346 result = request_irq(i2c->irq, mpc_i2c_isr,
349 printk(KERN_ERR 347 IRQF_SHARED, "i2c-mpc", i2c);
350 "i2c-mpc - failed to attach interrupt\n"); 348 if (result < 0) {
351 goto fail_irq; 349 printk(KERN_ERR "i2c-mpc - failed to attach interrupt\n");
350 goto fail_request;
352 } 351 }
353 352 }
353
354 mpc_i2c_setclock(i2c); 354 mpc_i2c_setclock(i2c);
355 platform_set_drvdata(pdev, i2c); 355
356 dev_set_drvdata(&op->dev, i2c);
356 357
357 i2c->adap = mpc_ops; 358 i2c->adap = mpc_ops;
358 i2c->adap.nr = pdev->id;
359 i2c_set_adapdata(&i2c->adap, i2c); 359 i2c_set_adapdata(&i2c->adap, i2c);
360 i2c->adap.dev.parent = &pdev->dev; 360 i2c->adap.dev.parent = &op->dev;
361 if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) { 361
362 result = i2c_add_adapter(&i2c->adap);
363 if (result < 0) {
362 printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); 364 printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
363 goto fail_add; 365 goto fail_add;
364 } 366 }
367 of_register_i2c_devices(&i2c->adap, op->node);
365 368
366 return result; 369 return result;
367 370
368 fail_add: 371 fail_add:
369 if (i2c->irq != NO_IRQ) 372 dev_set_drvdata(&op->dev, NULL);
370 free_irq(i2c->irq, i2c); 373 free_irq(i2c->irq, i2c);
371 fail_irq: 374 fail_request:
372 iounmap(i2c->base); 375 irq_dispose_mapping(i2c->irq);
373 fail_map: 376 iounmap(i2c->base);
377 fail_map:
374 kfree(i2c); 378 kfree(i2c);
375 return result; 379 return result;
376}; 380};
377 381
378static int fsl_i2c_remove(struct platform_device *pdev) 382static int __devexit fsl_i2c_remove(struct of_device *op)
379{ 383{
380 struct mpc_i2c *i2c = platform_get_drvdata(pdev); 384 struct mpc_i2c *i2c = dev_get_drvdata(&op->dev);
381 385
382 i2c_del_adapter(&i2c->adap); 386 i2c_del_adapter(&i2c->adap);
383 platform_set_drvdata(pdev, NULL); 387 dev_set_drvdata(&op->dev, NULL);
384 388
385 if (i2c->irq != NO_IRQ) 389 if (i2c->irq != NO_IRQ)
386 free_irq(i2c->irq, i2c); 390 free_irq(i2c->irq, i2c);
387 391
392 irq_dispose_mapping(i2c->irq);
388 iounmap(i2c->base); 393 iounmap(i2c->base);
389 kfree(i2c); 394 kfree(i2c);
390 return 0; 395 return 0;
391}; 396};
392 397
393/* work with hotplug and coldplug */ 398static const struct of_device_id mpc_i2c_of_match[] = {
394MODULE_ALIAS("platform:fsl-i2c"); 399 {.compatible = "fsl-i2c",},
400 {},
401};
402MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
403
395 404
396/* Structure for a device driver */ 405/* Structure for a device driver */
397static struct platform_driver fsl_i2c_driver = { 406static struct of_platform_driver mpc_i2c_driver = {
398 .probe = fsl_i2c_probe, 407 .match_table = mpc_i2c_of_match,
399 .remove = fsl_i2c_remove, 408 .probe = fsl_i2c_probe,
400 .driver = { 409 .remove = __devexit_p(fsl_i2c_remove),
401 .owner = THIS_MODULE, 410 .driver = {
402 .name = "fsl-i2c", 411 .owner = THIS_MODULE,
412 .name = DRV_NAME,
403 }, 413 },
404}; 414};
405 415
406static int __init fsl_i2c_init(void) 416static int __init fsl_i2c_init(void)
407{ 417{
408 return platform_driver_register(&fsl_i2c_driver); 418 int rv;
419
420 rv = of_register_platform_driver(&mpc_i2c_driver);
421 if (rv)
422 printk(KERN_ERR DRV_NAME
423 " of_register_platform_driver failed (%i)\n", rv);
424 return rv;
409} 425}
410 426
411static void __exit fsl_i2c_exit(void) 427static void __exit fsl_i2c_exit(void)
412{ 428{
413 platform_driver_unregister(&fsl_i2c_driver); 429 of_unregister_platform_driver(&mpc_i2c_driver);
414} 430}
415 431
416module_init(fsl_i2c_init); 432module_init(fsl_i2c_init);
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index b2ccdcbeb896..5c015d310d4a 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_i2c.h>
16#include <linux/module.h> 17#include <linux/module.h>
17 18
18struct i2c_driver_device { 19struct i2c_driver_device {
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 681d62325d3d..604e5f0a2d95 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -17,7 +17,7 @@
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18 18
19#if defined(CONFIG_PPC_MERGE) 19#if defined(CONFIG_PPC_MERGE)
20#include <asm/of_platform.h> 20#include <linux/of_platform.h>
21#else 21#else
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#endif 23#endif
diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c
index 80a91d4cea11..77c1c2ae2cc2 100644
--- a/drivers/watchdog/mpc5200_wdt.c
+++ b/drivers/watchdog/mpc5200_wdt.c
@@ -4,7 +4,7 @@
4#include <linux/watchdog.h> 4#include <linux/watchdog.h>
5#include <linux/io.h> 5#include <linux/io.h>
6#include <linux/spinlock.h> 6#include <linux/spinlock.h>
7#include <asm/of_platform.h> 7#include <linux/of_platform.h>
8#include <asm/uaccess.h> 8#include <asm/uaccess.h>
9#include <asm/mpc52xx.h> 9#include <asm/mpc52xx.h>
10 10