linux/arch/mips/bcm63xx/dev-enet.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   7 */
   8
   9#include <linux/init.h>
  10#include <linux/kernel.h>
  11#include <linux/platform_device.h>
  12#include <bcm63xx_dev_enet.h>
  13#include <bcm63xx_io.h>
  14#include <bcm63xx_regs.h>
  15
  16static struct resource shared_res[] = {
  17        {
  18                .start          = -1, /* filled at runtime */
  19                .end            = -1, /* filled at runtime */
  20                .flags          = IORESOURCE_MEM,
  21        },
  22};
  23
  24static struct platform_device bcm63xx_enet_shared_device = {
  25        .name           = "bcm63xx_enet_shared",
  26        .id             = 0,
  27        .num_resources  = ARRAY_SIZE(shared_res),
  28        .resource       = shared_res,
  29};
  30
  31static int shared_device_registered;
  32
  33static struct resource enet0_res[] = {
  34        {
  35                .start          = -1, /* filled at runtime */
  36                .end            = -1, /* filled at runtime */
  37                .flags          = IORESOURCE_MEM,
  38        },
  39        {
  40                .start          = -1, /* filled at runtime */
  41                .flags          = IORESOURCE_IRQ,
  42        },
  43        {
  44                .start          = -1, /* filled at runtime */
  45                .flags          = IORESOURCE_IRQ,
  46        },
  47        {
  48                .start          = -1, /* filled at runtime */
  49                .flags          = IORESOURCE_IRQ,
  50        },
  51};
  52
  53static struct bcm63xx_enet_platform_data enet0_pd;
  54
  55static struct platform_device bcm63xx_enet0_device = {
  56        .name           = "bcm63xx_enet",
  57        .id             = 0,
  58        .num_resources  = ARRAY_SIZE(enet0_res),
  59        .resource       = enet0_res,
  60        .dev            = {
  61                .platform_data = &enet0_pd,
  62        },
  63};
  64
  65static struct resource enet1_res[] = {
  66        {
  67                .start          = -1, /* filled at runtime */
  68                .end            = -1, /* filled at runtime */
  69                .flags          = IORESOURCE_MEM,
  70        },
  71        {
  72                .start          = -1, /* filled at runtime */
  73                .flags          = IORESOURCE_IRQ,
  74        },
  75        {
  76                .start          = -1, /* filled at runtime */
  77                .flags          = IORESOURCE_IRQ,
  78        },
  79        {
  80                .start          = -1, /* filled at runtime */
  81                .flags          = IORESOURCE_IRQ,
  82        },
  83};
  84
  85static struct bcm63xx_enet_platform_data enet1_pd;
  86
  87static struct platform_device bcm63xx_enet1_device = {
  88        .name           = "bcm63xx_enet",
  89        .id             = 1,
  90        .num_resources  = ARRAY_SIZE(enet1_res),
  91        .resource       = enet1_res,
  92        .dev            = {
  93                .platform_data = &enet1_pd,
  94        },
  95};
  96
  97int __init bcm63xx_enet_register(int unit,
  98                                 const struct bcm63xx_enet_platform_data *pd)
  99{
 100        struct platform_device *pdev;
 101        struct bcm63xx_enet_platform_data *dpd;
 102        int ret;
 103
 104        if (unit > 1)
 105                return -ENODEV;
 106
 107        if (unit == 1 && BCMCPU_IS_6338())
 108                return -ENODEV;
 109
 110        if (!shared_device_registered) {
 111                shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
 112                shared_res[0].end = shared_res[0].start;
 113                if (BCMCPU_IS_6338())
 114                        shared_res[0].end += (RSET_ENETDMA_SIZE / 2)  - 1;
 115                else
 116                        shared_res[0].end += (RSET_ENETDMA_SIZE)  - 1;
 117
 118                ret = platform_device_register(&bcm63xx_enet_shared_device);
 119                if (ret)
 120                        return ret;
 121                shared_device_registered = 1;
 122        }
 123
 124        if (unit == 0) {
 125                enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
 126                enet0_res[0].end = enet0_res[0].start;
 127                enet0_res[0].end += RSET_ENET_SIZE - 1;
 128                enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
 129                enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
 130                enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
 131                pdev = &bcm63xx_enet0_device;
 132        } else {
 133                enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
 134                enet1_res[0].end = enet1_res[0].start;
 135                enet1_res[0].end += RSET_ENET_SIZE - 1;
 136                enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
 137                enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
 138                enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
 139                pdev = &bcm63xx_enet1_device;
 140        }
 141
 142        /* copy given platform data */
 143        dpd = pdev->dev.platform_data;
 144        memcpy(dpd, pd, sizeof(*pd));
 145
 146        /* adjust them in case internal phy is used */
 147        if (dpd->use_internal_phy) {
 148
 149                /* internal phy only exists for enet0 */
 150                if (unit == 1)
 151                        return -ENODEV;
 152
 153                dpd->phy_id = 1;
 154                dpd->has_phy_interrupt = 1;
 155                dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
 156        }
 157
 158        ret = platform_device_register(pdev);
 159        if (ret)
 160                return ret;
 161        return 0;
 162}
 163