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