linux/arch/powerpc/sysdev/mv64x60_dev.c
<<
>>
Prefs
   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[2];
 218        int err;
 219
 220        err = of_address_to_resource(np, 0, &r[0]);
 221        if (err)
 222                return ERR_PTR(err);
 223
 224        /* register an orion mdio bus driver */
 225        r[1].start = r[0].start + 0x4;
 226        r[1].end = r[0].start + 0x84 - 1;
 227        r[1].flags = IORESOURCE_MEM;
 228
 229        if (id == 0) {
 230                pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1);
 231                if (IS_ERR(pdev))
 232                        return pdev;
 233        }
 234
 235        pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
 236                                               &r[0], 1);
 237
 238        return pdev;
 239}
 240
 241static int __init mv64x60_eth_device_setup(struct device_node *np, int id,
 242                                           struct platform_device *shared_pdev)
 243{
 244        struct resource r[1];
 245        struct mv643xx_eth_platform_data pdata;
 246        struct platform_device *pdev;
 247        struct device_node *phy;
 248        const u8 *mac_addr;
 249        const int *prop;
 250        const phandle *ph;
 251        int err;
 252
 253        memset(r, 0, sizeof(r));
 254        of_irq_to_resource(np, 0, &r[0]);
 255
 256        memset(&pdata, 0, sizeof(pdata));
 257
 258        pdata.shared = shared_pdev;
 259
 260        prop = of_get_property(np, "reg", NULL);
 261        if (!prop)
 262                return -ENODEV;
 263        pdata.port_number = *prop;
 264
 265        mac_addr = of_get_mac_address(np);
 266        if (mac_addr)
 267                memcpy(pdata.mac_addr, mac_addr, 6);
 268
 269        prop = of_get_property(np, "speed", NULL);
 270        if (prop)
 271                pdata.speed = *prop;
 272
 273        prop = of_get_property(np, "tx_queue_size", NULL);
 274        if (prop)
 275                pdata.tx_queue_size = *prop;
 276
 277        prop = of_get_property(np, "rx_queue_size", NULL);
 278        if (prop)
 279                pdata.rx_queue_size = *prop;
 280
 281        prop = of_get_property(np, "tx_sram_addr", NULL);
 282        if (prop)
 283                pdata.tx_sram_addr = *prop;
 284
 285        prop = of_get_property(np, "tx_sram_size", NULL);
 286        if (prop)
 287                pdata.tx_sram_size = *prop;
 288
 289        prop = of_get_property(np, "rx_sram_addr", NULL);
 290        if (prop)
 291                pdata.rx_sram_addr = *prop;
 292
 293        prop = of_get_property(np, "rx_sram_size", NULL);
 294        if (prop)
 295                pdata.rx_sram_size = *prop;
 296
 297        ph = of_get_property(np, "phy", NULL);
 298        if (!ph)
 299                return -ENODEV;
 300
 301        phy = of_find_node_by_phandle(*ph);
 302        if (phy == NULL)
 303                return -ENODEV;
 304
 305        prop = of_get_property(phy, "reg", NULL);
 306        if (prop)
 307                pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop);
 308
 309        of_node_put(phy);
 310
 311        pdev = platform_device_alloc(MV643XX_ETH_NAME, id);
 312        if (!pdev)
 313                return -ENOMEM;
 314
 315        pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 316        err = platform_device_add_resources(pdev, r, 1);
 317        if (err)
 318                goto error;
 319
 320        err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
 321        if (err)
 322                goto error;
 323
 324        err = platform_device_add(pdev);
 325        if (err)
 326                goto error;
 327
 328        return 0;
 329
 330error:
 331        platform_device_put(pdev);
 332        return err;
 333}
 334
 335/*
 336 * Create mv64x60_i2c platform devices
 337 */
 338static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
 339{
 340        struct resource r[2];
 341        struct platform_device *pdev;
 342        struct mv64xxx_i2c_pdata pdata;
 343        const unsigned int *prop;
 344        int err;
 345
 346        memset(r, 0, sizeof(r));
 347
 348        err = of_address_to_resource(np, 0, &r[0]);
 349        if (err)
 350                return err;
 351
 352        of_irq_to_resource(np, 0, &r[1]);
 353
 354        memset(&pdata, 0, sizeof(pdata));
 355
 356        pdata.freq_m = 8;       /* default */
 357        prop = of_get_property(np, "freq_m", NULL);
 358        if (prop)
 359                pdata.freq_m = *prop;
 360
 361        pdata.freq_n = 3;       /* default */
 362        prop = of_get_property(np, "freq_n", NULL);
 363        if (prop)
 364                pdata.freq_n = *prop;
 365
 366        pdata.timeout = 1000;                           /* default: 1 second */
 367
 368        pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id);
 369        if (!pdev)
 370                return -ENOMEM;
 371
 372        err = platform_device_add_resources(pdev, r, 2);
 373        if (err)
 374                goto error;
 375
 376        err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
 377        if (err)
 378                goto error;
 379
 380        err = platform_device_add(pdev);
 381        if (err)
 382                goto error;
 383
 384        return 0;
 385
 386error:
 387        platform_device_put(pdev);
 388        return err;
 389}
 390
 391/*
 392 * Create mv64x60_wdt platform devices
 393 */
 394static int __init mv64x60_wdt_device_setup(struct device_node *np, int id)
 395{
 396        struct resource r;
 397        struct platform_device *pdev;
 398        struct mv64x60_wdt_pdata pdata;
 399        const unsigned int *prop;
 400        int err;
 401
 402        err = of_address_to_resource(np, 0, &r);
 403        if (err)
 404                return err;
 405
 406        memset(&pdata, 0, sizeof(pdata));
 407
 408        pdata.timeout = 10;                     /* Default: 10 seconds */
 409
 410        np = of_get_parent(np);
 411        if (!np)
 412                return -ENODEV;
 413
 414        prop = of_get_property(np, "clock-frequency", NULL);
 415        of_node_put(np);
 416        if (!prop)
 417                return -ENODEV;
 418        pdata.bus_clk = *prop / 1000000; /* wdt driver wants freq in MHz */
 419
 420        pdev = platform_device_alloc(MV64x60_WDT_NAME, id);
 421        if (!pdev)
 422                return -ENOMEM;
 423
 424        err = platform_device_add_resources(pdev, &r, 1);
 425        if (err)
 426                goto error;
 427
 428        err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
 429        if (err)
 430                goto error;
 431
 432        err = platform_device_add(pdev);
 433        if (err)
 434                goto error;
 435
 436        return 0;
 437
 438error:
 439        platform_device_put(pdev);
 440        return err;
 441}
 442
 443static int __init mv64x60_device_setup(void)
 444{
 445        struct device_node *np, *np2;
 446        struct platform_device *pdev;
 447        int id, id2;
 448        int err;
 449
 450        id = 0;
 451        for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
 452                err = mv64x60_mpsc_device_setup(np, id++);
 453                if (err)
 454                        printk(KERN_ERR "Failed to initialize MV64x60 "
 455                                        "serial device %s: error %d.\n",
 456                                        np->full_name, err);
 457        }
 458
 459        id = 0;
 460        id2 = 0;
 461        for_each_compatible_node(np, NULL, "marvell,mv64360-eth-group") {
 462                pdev = mv64x60_eth_register_shared_pdev(np, id++);
 463                if (IS_ERR(pdev)) {
 464                        err = PTR_ERR(pdev);
 465                        printk(KERN_ERR "Failed to initialize MV64x60 "
 466                                        "network block %s: error %d.\n",
 467                                        np->full_name, err);
 468                        continue;
 469                }
 470                for_each_child_of_node(np, np2) {
 471                        if (!of_device_is_compatible(np2,
 472                                        "marvell,mv64360-eth"))
 473                                continue;
 474                        err = mv64x60_eth_device_setup(np2, id2++, pdev);
 475                        if (err)
 476                                printk(KERN_ERR "Failed to initialize "
 477                                                "MV64x60 network device %s: "
 478                                                "error %d.\n",
 479                                                np2->full_name, err);
 480                }
 481        }
 482
 483        id = 0;
 484        for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
 485                err = mv64x60_i2c_device_setup(np, id++);
 486                if (err)
 487                        printk(KERN_ERR "Failed to initialize MV64x60 I2C "
 488                                        "bus %s: error %d.\n",
 489                                        np->full_name, err);
 490        }
 491
 492        /* support up to one watchdog timer */
 493        np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
 494        if (np) {
 495                if ((err = mv64x60_wdt_device_setup(np, id)))
 496                        printk(KERN_ERR "Failed to initialize MV64x60 "
 497                                        "Watchdog %s: error %d.\n",
 498                                        np->full_name, err);
 499                of_node_put(np);
 500        }
 501
 502        /* Now add every node that is on the device bus */
 503        for_each_compatible_node(np, NULL, "marvell,mv64360")
 504                of_platform_bus_probe(np, of_mv64x60_devices, NULL);
 505
 506        return 0;
 507}
 508arch_initcall(mv64x60_device_setup);
 509
 510static int __init mv64x60_add_mpsc_console(void)
 511{
 512        struct device_node *np = NULL;
 513        const char *prop;
 514
 515        prop = of_get_property(of_chosen, "linux,stdout-path", NULL);
 516        if (prop == NULL)
 517                goto not_mpsc;
 518
 519        np = of_find_node_by_path(prop);
 520        if (!np)
 521                goto not_mpsc;
 522
 523        if (!of_device_is_compatible(np, "marvell,mv64360-mpsc"))
 524                goto not_mpsc;
 525
 526        prop = of_get_property(np, "cell-index", NULL);
 527        if (!prop)
 528                goto not_mpsc;
 529
 530        add_preferred_console("ttyMM", *(int *)prop, NULL);
 531
 532not_mpsc:
 533        return 0;
 534}
 535console_initcall(mv64x60_add_mpsc_console);
 536