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