at v2.6.35 527 lines 12 kB view raw
1/* 2 * Platform device setup for Marvell mv64360/mv64460 host bridges (Discovery) 3 * 4 * Author: Dale Farnsworth <dale@farnsworth.org> 5 * 6 * 2007 (c) MontaVista, Software, Inc. This file is licensed under 7 * the terms of the GNU General Public License version 2. This program 8 * is licensed "as is" without any warranty of any kind, whether express 9 * or implied. 10 */ 11 12#include <linux/stddef.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/console.h> 16#include <linux/mv643xx.h> 17#include <linux/platform_device.h> 18#include <linux/of_platform.h> 19#include <linux/dma-mapping.h> 20 21#include <asm/prom.h> 22 23/* 24 * These functions provide the necessary setup for the mv64x60 drivers. 25 * These drivers are unusual in that they work on both the MIPS and PowerPC 26 * architectures. Because of that, the drivers do not support the normal 27 * PowerPC of_platform_bus_type. They support platform_bus_type instead. 28 */ 29 30static struct of_device_id __initdata of_mv64x60_devices[] = { 31 { .compatible = "marvell,mv64306-devctrl", }, 32 {} 33}; 34 35/* 36 * Create MPSC platform devices 37 */ 38static int __init mv64x60_mpsc_register_shared_pdev(struct device_node *np) 39{ 40 struct platform_device *pdev; 41 struct resource r[2]; 42 struct mpsc_shared_pdata pdata; 43 const phandle *ph; 44 struct device_node *mpscrouting, *mpscintr; 45 int err; 46 47 ph = of_get_property(np, "mpscrouting", NULL); 48 mpscrouting = of_find_node_by_phandle(*ph); 49 if (!mpscrouting) 50 return -ENODEV; 51 52 err = of_address_to_resource(mpscrouting, 0, &r[0]); 53 of_node_put(mpscrouting); 54 if (err) 55 return err; 56 57 ph = of_get_property(np, "mpscintr", NULL); 58 mpscintr = of_find_node_by_phandle(*ph); 59 if (!mpscintr) 60 return -ENODEV; 61 62 err = of_address_to_resource(mpscintr, 0, &r[1]); 63 of_node_put(mpscintr); 64 if (err) 65 return err; 66 67 memset(&pdata, 0, sizeof(pdata)); 68 69 pdev = platform_device_alloc(MPSC_SHARED_NAME, 0); 70 if (!pdev) 71 return -ENOMEM; 72 73 err = platform_device_add_resources(pdev, r, 2); 74 if (err) 75 goto error; 76 77 err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 78 if (err) 79 goto error; 80 81 err = platform_device_add(pdev); 82 if (err) 83 goto error; 84 85 return 0; 86 87error: 88 platform_device_put(pdev); 89 return err; 90} 91 92 93static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id) 94{ 95 struct resource r[5]; 96 struct mpsc_pdata pdata; 97 struct platform_device *pdev; 98 const unsigned int *prop; 99 const phandle *ph; 100 struct device_node *sdma, *brg; 101 int err; 102 int port_number; 103 104 /* only register the shared platform device the first time through */ 105 if (id == 0 && (err = mv64x60_mpsc_register_shared_pdev(np))) 106 return err; 107 108 memset(r, 0, sizeof(r)); 109 110 err = of_address_to_resource(np, 0, &r[0]); 111 if (err) 112 return err; 113 114 of_irq_to_resource(np, 0, &r[4]); 115 116 ph = of_get_property(np, "sdma", NULL); 117 sdma = of_find_node_by_phandle(*ph); 118 if (!sdma) 119 return -ENODEV; 120 121 of_irq_to_resource(sdma, 0, &r[3]); 122 err = of_address_to_resource(sdma, 0, &r[1]); 123 of_node_put(sdma); 124 if (err) 125 return err; 126 127 ph = of_get_property(np, "brg", NULL); 128 brg = of_find_node_by_phandle(*ph); 129 if (!brg) 130 return -ENODEV; 131 132 err = of_address_to_resource(brg, 0, &r[2]); 133 of_node_put(brg); 134 if (err) 135 return err; 136 137 prop = of_get_property(np, "cell-index", NULL); 138 if (!prop) 139 return -ENODEV; 140 port_number = *(int *)prop; 141 142 memset(&pdata, 0, sizeof(pdata)); 143 144 pdata.cache_mgmt = 1; /* All current revs need this set */ 145 146 pdata.max_idle = 40; /* default */ 147 prop = of_get_property(np, "max_idle", NULL); 148 if (prop) 149 pdata.max_idle = *prop; 150 151 prop = of_get_property(brg, "current-speed", NULL); 152 if (prop) 153 pdata.default_baud = *prop; 154 155 /* Default is 8 bits, no parity, no flow control */ 156 pdata.default_bits = 8; 157 pdata.default_parity = 'n'; 158 pdata.default_flow = 'n'; 159 160 prop = of_get_property(np, "chr_1", NULL); 161 if (prop) 162 pdata.chr_1_val = *prop; 163 164 prop = of_get_property(np, "chr_2", NULL); 165 if (prop) 166 pdata.chr_2_val = *prop; 167 168 prop = of_get_property(np, "chr_10", NULL); 169 if (prop) 170 pdata.chr_10_val = *prop; 171 172 prop = of_get_property(np, "mpcr", NULL); 173 if (prop) 174 pdata.mpcr_val = *prop; 175 176 prop = of_get_property(brg, "bcr", NULL); 177 if (prop) 178 pdata.bcr_val = *prop; 179 180 pdata.brg_can_tune = 1; /* All current revs need this set */ 181 182 prop = of_get_property(brg, "clock-src", NULL); 183 if (prop) 184 pdata.brg_clk_src = *prop; 185 186 prop = of_get_property(brg, "clock-frequency", NULL); 187 if (prop) 188 pdata.brg_clk_freq = *prop; 189 190 pdev = platform_device_alloc(MPSC_CTLR_NAME, port_number); 191 if (!pdev) 192 return -ENOMEM; 193 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 194 195 err = platform_device_add_resources(pdev, r, 5); 196 if (err) 197 goto error; 198 199 err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 200 if (err) 201 goto error; 202 203 err = platform_device_add(pdev); 204 if (err) 205 goto error; 206 207 return 0; 208 209error: 210 platform_device_put(pdev); 211 return err; 212} 213 214/* 215 * Create mv64x60_eth platform devices 216 */ 217static struct platform_device * __init mv64x60_eth_register_shared_pdev( 218 struct device_node *np, int id) 219{ 220 struct platform_device *pdev; 221 struct resource r[1]; 222 int err; 223 224 err = of_address_to_resource(np, 0, &r[0]); 225 if (err) 226 return ERR_PTR(err); 227 228 pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id, 229 r, 1); 230 return pdev; 231} 232 233static int __init mv64x60_eth_device_setup(struct device_node *np, int id, 234 struct platform_device *shared_pdev) 235{ 236 struct resource r[1]; 237 struct mv643xx_eth_platform_data pdata; 238 struct platform_device *pdev; 239 struct device_node *phy; 240 const u8 *mac_addr; 241 const int *prop; 242 const phandle *ph; 243 int err; 244 245 memset(r, 0, sizeof(r)); 246 of_irq_to_resource(np, 0, &r[0]); 247 248 memset(&pdata, 0, sizeof(pdata)); 249 250 pdata.shared = shared_pdev; 251 252 prop = of_get_property(np, "reg", NULL); 253 if (!prop) 254 return -ENODEV; 255 pdata.port_number = *prop; 256 257 mac_addr = of_get_mac_address(np); 258 if (mac_addr) 259 memcpy(pdata.mac_addr, mac_addr, 6); 260 261 prop = of_get_property(np, "speed", NULL); 262 if (prop) 263 pdata.speed = *prop; 264 265 prop = of_get_property(np, "tx_queue_size", NULL); 266 if (prop) 267 pdata.tx_queue_size = *prop; 268 269 prop = of_get_property(np, "rx_queue_size", NULL); 270 if (prop) 271 pdata.rx_queue_size = *prop; 272 273 prop = of_get_property(np, "tx_sram_addr", NULL); 274 if (prop) 275 pdata.tx_sram_addr = *prop; 276 277 prop = of_get_property(np, "tx_sram_size", NULL); 278 if (prop) 279 pdata.tx_sram_size = *prop; 280 281 prop = of_get_property(np, "rx_sram_addr", NULL); 282 if (prop) 283 pdata.rx_sram_addr = *prop; 284 285 prop = of_get_property(np, "rx_sram_size", NULL); 286 if (prop) 287 pdata.rx_sram_size = *prop; 288 289 ph = of_get_property(np, "phy", NULL); 290 if (!ph) 291 return -ENODEV; 292 293 phy = of_find_node_by_phandle(*ph); 294 if (phy == NULL) 295 return -ENODEV; 296 297 prop = of_get_property(phy, "reg", NULL); 298 if (prop) 299 pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop); 300 301 of_node_put(phy); 302 303 pdev = platform_device_alloc(MV643XX_ETH_NAME, id); 304 if (!pdev) 305 return -ENOMEM; 306 307 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 308 err = platform_device_add_resources(pdev, r, 1); 309 if (err) 310 goto error; 311 312 err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 313 if (err) 314 goto error; 315 316 err = platform_device_add(pdev); 317 if (err) 318 goto error; 319 320 return 0; 321 322error: 323 platform_device_put(pdev); 324 return err; 325} 326 327/* 328 * Create mv64x60_i2c platform devices 329 */ 330static int __init mv64x60_i2c_device_setup(struct device_node *np, int id) 331{ 332 struct resource r[2]; 333 struct platform_device *pdev; 334 struct mv64xxx_i2c_pdata pdata; 335 const unsigned int *prop; 336 int err; 337 338 memset(r, 0, sizeof(r)); 339 340 err = of_address_to_resource(np, 0, &r[0]); 341 if (err) 342 return err; 343 344 of_irq_to_resource(np, 0, &r[1]); 345 346 memset(&pdata, 0, sizeof(pdata)); 347 348 pdata.freq_m = 8; /* default */ 349 prop = of_get_property(np, "freq_m", NULL); 350 if (prop) 351 pdata.freq_m = *prop; 352 353 pdata.freq_m = 3; /* default */ 354 prop = of_get_property(np, "freq_n", NULL); 355 if (prop) 356 pdata.freq_n = *prop; 357 358 pdata.timeout = 1000; /* default: 1 second */ 359 360 pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id); 361 if (!pdev) 362 return -ENOMEM; 363 364 err = platform_device_add_resources(pdev, r, 2); 365 if (err) 366 goto error; 367 368 err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 369 if (err) 370 goto error; 371 372 err = platform_device_add(pdev); 373 if (err) 374 goto error; 375 376 return 0; 377 378error: 379 platform_device_put(pdev); 380 return err; 381} 382 383/* 384 * Create mv64x60_wdt platform devices 385 */ 386static int __init mv64x60_wdt_device_setup(struct device_node *np, int id) 387{ 388 struct resource r; 389 struct platform_device *pdev; 390 struct mv64x60_wdt_pdata pdata; 391 const unsigned int *prop; 392 int err; 393 394 err = of_address_to_resource(np, 0, &r); 395 if (err) 396 return err; 397 398 memset(&pdata, 0, sizeof(pdata)); 399 400 pdata.timeout = 10; /* Default: 10 seconds */ 401 402 np = of_get_parent(np); 403 if (!np) 404 return -ENODEV; 405 406 prop = of_get_property(np, "clock-frequency", NULL); 407 of_node_put(np); 408 if (!prop) 409 return -ENODEV; 410 pdata.bus_clk = *prop / 1000000; /* wdt driver wants freq in MHz */ 411 412 pdev = platform_device_alloc(MV64x60_WDT_NAME, id); 413 if (!pdev) 414 return -ENOMEM; 415 416 err = platform_device_add_resources(pdev, &r, 1); 417 if (err) 418 goto error; 419 420 err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); 421 if (err) 422 goto error; 423 424 err = platform_device_add(pdev); 425 if (err) 426 goto error; 427 428 return 0; 429 430error: 431 platform_device_put(pdev); 432 return err; 433} 434 435static int __init mv64x60_device_setup(void) 436{ 437 struct device_node *np, *np2; 438 struct platform_device *pdev; 439 int id, id2; 440 int err; 441 442 id = 0; 443 for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") { 444 err = mv64x60_mpsc_device_setup(np, id++); 445 if (err) 446 printk(KERN_ERR "Failed to initialize MV64x60 " 447 "serial device %s: error %d.\n", 448 np->full_name, err); 449 } 450 451 id = 0; 452 id2 = 0; 453 for_each_compatible_node(np, NULL, "marvell,mv64360-eth-group") { 454 pdev = mv64x60_eth_register_shared_pdev(np, id++); 455 if (IS_ERR(pdev)) { 456 err = PTR_ERR(pdev); 457 printk(KERN_ERR "Failed to initialize MV64x60 " 458 "network block %s: error %d.\n", 459 np->full_name, err); 460 continue; 461 } 462 for_each_child_of_node(np, np2) { 463 if (!of_device_is_compatible(np2, 464 "marvell,mv64360-eth")) 465 continue; 466 err = mv64x60_eth_device_setup(np2, id2++, pdev); 467 if (err) 468 printk(KERN_ERR "Failed to initialize " 469 "MV64x60 network device %s: " 470 "error %d.\n", 471 np2->full_name, err); 472 } 473 } 474 475 id = 0; 476 for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") { 477 err = mv64x60_i2c_device_setup(np, id++); 478 if (err) 479 printk(KERN_ERR "Failed to initialize MV64x60 I2C " 480 "bus %s: error %d.\n", 481 np->full_name, err); 482 } 483 484 /* support up to one watchdog timer */ 485 np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt"); 486 if (np) { 487 if ((err = mv64x60_wdt_device_setup(np, id))) 488 printk(KERN_ERR "Failed to initialize MV64x60 " 489 "Watchdog %s: error %d.\n", 490 np->full_name, err); 491 of_node_put(np); 492 } 493 494 /* Now add every node that is on the device bus */ 495 for_each_compatible_node(np, NULL, "marvell,mv64360") 496 of_platform_bus_probe(np, of_mv64x60_devices, NULL); 497 498 return 0; 499} 500arch_initcall(mv64x60_device_setup); 501 502static int __init mv64x60_add_mpsc_console(void) 503{ 504 struct device_node *np = NULL; 505 const char *prop; 506 507 prop = of_get_property(of_chosen, "linux,stdout-path", NULL); 508 if (prop == NULL) 509 goto not_mpsc; 510 511 np = of_find_node_by_path(prop); 512 if (!np) 513 goto not_mpsc; 514 515 if (!of_device_is_compatible(np, "marvell,mv64360-mpsc")) 516 goto not_mpsc; 517 518 prop = of_get_property(np, "cell-index", NULL); 519 if (!prop) 520 goto not_mpsc; 521 522 add_preferred_console("ttyMM", *(int *)prop, NULL); 523 524not_mpsc: 525 return 0; 526} 527console_initcall(mv64x60_add_mpsc_console);