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 | |
| parent | 930074b6b9c4895d20cdadba5aff97907e28728d (diff) | |
| parent | 77a76369475801ab8cbb338b9d8cfa92a491badb (diff) | |
Merge commit 'gcl/gcl-next'
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/ | |||
| 2503 | L: linuxppc-dev@ozlabs.org | 2503 | L: linuxppc-dev@ozlabs.org |
| 2504 | S: Maintained | 2504 | S: Maintained |
| 2505 | 2505 | ||
| 2506 | LINUX FOR POWERPC EMBEDDED MPC52XX | 2506 | LINUX FOR POWERPC EMBEDDED MPC5XXX |
| 2507 | P: Sylvain Munaut | 2507 | P: Sylvain Munaut |
| 2508 | M: tnt@246tNt.com | 2508 | M: tnt@246tNt.com |
| 2509 | P: Grant Likely | 2509 | P: Grant Likely |
| 2510 | M: grant.likely@secretlab.ca | 2510 | M: grant.likely@secretlab.ca |
| 2511 | W: http://www.246tNt.com/mpc52xx/ | ||
| 2512 | W: http://www.penguinppc.org/ | ||
| 2513 | L: linuxppc-dev@ozlabs.org | 2511 | L: linuxppc-dev@ozlabs.org |
| 2514 | S: Maintained | 2512 | S: Maintained |
| 2515 | 2513 | ||
| @@ -1,3 +1,4 @@ | |||
| 1 | FRED=42 | ||
| 1 | VERSION = 2 | 2 | VERSION = 2 |
| 2 | PATCHLEVEL = 6 | 3 | PATCHLEVEL = 6 |
| 3 | SUBLEVEL = 26 | 4 | SUBLEVEL = 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 | ||
| 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) |
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 | ||
| 318 | static int fsl_i2c_probe(struct platform_device *pdev) | 319 | static 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 | ||
| 378 | static int fsl_i2c_remove(struct platform_device *pdev) | 382 | static 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 */ | 398 | static const struct of_device_id mpc_i2c_of_match[] = { |
| 394 | MODULE_ALIAS("platform:fsl-i2c"); | 399 | {.compatible = "fsl-i2c",}, |
| 400 | {}, | ||
| 401 | }; | ||
| 402 | MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); | ||
| 403 | |||
| 395 | 404 | ||
| 396 | /* Structure for a device driver */ | 405 | /* Structure for a device driver */ |
| 397 | static struct platform_driver fsl_i2c_driver = { | 406 | static 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 | ||
| 406 | static int __init fsl_i2c_init(void) | 416 | static 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 | ||
| 411 | static void __exit fsl_i2c_exit(void) | 427 | static 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 | ||
| 416 | module_init(fsl_i2c_init); | 432 | module_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 | ||
| 18 | struct i2c_driver_device { | 19 | struct 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 | ||
