[brcm63xx] add support for user9102 boards (#4537)
[openwrt.git] / target / linux / brcm63xx / files / arch / mips / bcm63xx / dev-enet.c
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
16 static struct resource shared_res[] = {
17         {
18                 .start          = -1, /* filled at runtime */
19                 .end            = -1, /* filled at runtime */
20                 .flags          = IORESOURCE_MEM,
21         },
22 };
23
24 static 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
31 static int shared_device_registered = 0;
32
33 static 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                 .start          = IRQ_ENET0_RXDMA,
46                 .flags          = IORESOURCE_IRQ,
47         },
48         {
49                 .start          = -1, /* filled at runtime */
50                 .start          = IRQ_ENET0_TXDMA,
51                 .flags          = IORESOURCE_IRQ,
52         },
53 };
54
55 static struct bcm63xx_enet_platform_data enet0_pd;
56
57 static struct platform_device bcm63xx_enet0_device = {
58         .name           = "bcm63xx_enet",
59         .id             = 0,
60         .num_resources  = ARRAY_SIZE(enet0_res),
61         .resource       = enet0_res,
62         .dev            = {
63                 .platform_data = &enet0_pd,
64         },
65 };
66
67 static struct resource enet1_res[] = {
68         {
69                 .start          = -1, /* filled at runtime */
70                 .end            = -1, /* filled at runtime */
71                 .flags          = IORESOURCE_MEM,
72         },
73         {
74                 .start          = -1, /* filled at runtime */
75                 .flags          = IORESOURCE_IRQ,
76         },
77         {
78                 .start          = -1, /* filled at runtime */
79                 .flags          = IORESOURCE_IRQ,
80         },
81         {
82                 .start          = -1, /* filled at runtime */
83                 .flags          = IORESOURCE_IRQ,
84         },
85 };
86
87 static struct bcm63xx_enet_platform_data enet1_pd;
88
89 static struct platform_device bcm63xx_enet1_device = {
90         .name           = "bcm63xx_enet",
91         .id             = 1,
92         .num_resources  = ARRAY_SIZE(enet1_res),
93         .resource       = enet1_res,
94         .dev            = {
95                 .platform_data = &enet1_pd,
96         },
97 };
98
99 int __init bcm63xx_enet_register(int unit,
100                                  const struct bcm63xx_enet_platform_data *pd)
101 {
102         struct platform_device *pdev;
103         struct bcm63xx_enet_platform_data *dpd;
104         int ret;
105
106         if (unit > 1)
107                 return -ENODEV;
108
109         if (!shared_device_registered) {
110                 shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
111                 shared_res[0].end = shared_res[0].start;
112                 shared_res[0].end += RSET_ENETDMA_SIZE - 1;
113
114                 ret = platform_device_register(&bcm63xx_enet_shared_device);
115                 if (ret)
116                         return ret;
117                 shared_device_registered = 1;
118         }
119
120         if (unit == 0) {
121                 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
122                 enet0_res[0].end = enet0_res[0].start;
123                 enet0_res[0].end += RSET_ENET_SIZE - 1;
124                 enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
125                 enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
126                 enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
127                 pdev = &bcm63xx_enet0_device;
128         } else {
129                 enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
130                 enet1_res[0].end = enet1_res[0].start;
131                 enet1_res[0].end += RSET_ENET_SIZE - 1;
132                 enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
133                 enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
134                 enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
135                 pdev = &bcm63xx_enet1_device;
136         }
137
138         /* copy given platform data */
139         dpd = pdev->dev.platform_data;
140         memcpy(dpd, pd, sizeof (*pd));
141
142         /* adjust them in case internal phy is used */
143         if (dpd->use_internal_phy) {
144
145                 /* internal phy only exists for enet0 */
146                 if (unit == 1)
147                         return -ENODEV;
148
149                 dpd->phy_id = 1;
150                 dpd->has_phy_interrupt = 1;
151                 dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
152         }
153
154         ret = platform_device_register(pdev);
155         if (ret)
156                 return ret;
157         return 0;
158 }