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