blob: 6cbaee0f6d709987b49f0c30c2f55b058dbedf10 [file] [log] [blame]
Maxime Bizon9b1fc552009-08-18 13:23:40 +01001/*
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 },
Maxime Bizon0ae99b52013-06-04 22:53:34 +010022 {
23 .start = -1, /* filled at runtime */
24 .end = -1, /* filled at runtime */
25 .flags = IORESOURCE_MEM,
26 },
27 {
28 .start = -1, /* filled at runtime */
29 .end = -1, /* filled at runtime */
30 .flags = IORESOURCE_MEM,
31 },
Maxime Bizon9b1fc552009-08-18 13:23:40 +010032};
33
34static struct platform_device bcm63xx_enet_shared_device = {
35 .name = "bcm63xx_enet_shared",
36 .id = 0,
37 .num_resources = ARRAY_SIZE(shared_res),
38 .resource = shared_res,
39};
40
41static int shared_device_registered;
42
43static struct resource enet0_res[] = {
44 {
45 .start = -1, /* filled at runtime */
46 .end = -1, /* filled at runtime */
47 .flags = IORESOURCE_MEM,
48 },
49 {
50 .start = -1, /* filled at runtime */
51 .flags = IORESOURCE_IRQ,
52 },
53 {
54 .start = -1, /* filled at runtime */
55 .flags = IORESOURCE_IRQ,
56 },
57 {
58 .start = -1, /* filled at runtime */
59 .flags = IORESOURCE_IRQ,
60 },
61};
62
63static struct bcm63xx_enet_platform_data enet0_pd;
64
65static struct platform_device bcm63xx_enet0_device = {
66 .name = "bcm63xx_enet",
67 .id = 0,
68 .num_resources = ARRAY_SIZE(enet0_res),
69 .resource = enet0_res,
70 .dev = {
71 .platform_data = &enet0_pd,
72 },
73};
74
75static struct resource enet1_res[] = {
76 {
77 .start = -1, /* filled at runtime */
78 .end = -1, /* filled at runtime */
79 .flags = IORESOURCE_MEM,
80 },
81 {
82 .start = -1, /* filled at runtime */
83 .flags = IORESOURCE_IRQ,
84 },
85 {
86 .start = -1, /* filled at runtime */
87 .flags = IORESOURCE_IRQ,
88 },
89 {
90 .start = -1, /* filled at runtime */
91 .flags = IORESOURCE_IRQ,
92 },
93};
94
95static struct bcm63xx_enet_platform_data enet1_pd;
96
97static struct platform_device bcm63xx_enet1_device = {
98 .name = "bcm63xx_enet",
99 .id = 1,
100 .num_resources = ARRAY_SIZE(enet1_res),
101 .resource = enet1_res,
102 .dev = {
103 .platform_data = &enet1_pd,
104 },
105};
106
Maxime Bizon6f00a022013-06-04 22:53:35 +0100107static struct resource enetsw_res[] = {
108 {
109 /* start & end filled at runtime */
110 .flags = IORESOURCE_MEM,
111 },
112 {
113 /* start filled at runtime */
114 .flags = IORESOURCE_IRQ,
115 },
116 {
117 /* start filled at runtime */
118 .flags = IORESOURCE_IRQ,
119 },
120};
121
122static struct bcm63xx_enetsw_platform_data enetsw_pd;
123
124static struct platform_device bcm63xx_enetsw_device = {
125 .name = "bcm63xx_enetsw",
126 .num_resources = ARRAY_SIZE(enetsw_res),
127 .resource = enetsw_res,
128 .dev = {
129 .platform_data = &enetsw_pd,
130 },
131};
132
133static int __init register_shared(void)
134{
135 int ret, chan_count;
136
137 if (shared_device_registered)
138 return 0;
139
140 shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
141 shared_res[0].end = shared_res[0].start;
142 shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
143
144 if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
145 chan_count = 32;
146 else
147 chan_count = 16;
148
149 shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
150 shared_res[1].end = shared_res[1].start;
151 shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1;
152
153 shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
154 shared_res[2].end = shared_res[2].start;
155 shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1;
156
157 ret = platform_device_register(&bcm63xx_enet_shared_device);
158 if (ret)
159 return ret;
160 shared_device_registered = 1;
161
162 return 0;
163}
164
Maxime Bizon9b1fc552009-08-18 13:23:40 +0100165int __init bcm63xx_enet_register(int unit,
166 const struct bcm63xx_enet_platform_data *pd)
167{
168 struct platform_device *pdev;
169 struct bcm63xx_enet_platform_data *dpd;
170 int ret;
171
172 if (unit > 1)
173 return -ENODEV;
174
Florian Fainelli7f13f652010-07-21 22:59:26 +0200175 if (unit == 1 && BCMCPU_IS_6338())
176 return -ENODEV;
177
Maxime Bizon6f00a022013-06-04 22:53:35 +0100178 ret = register_shared();
179 if (ret)
180 return ret;
Maxime Bizon9b1fc552009-08-18 13:23:40 +0100181
182 if (unit == 0) {
183 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
184 enet0_res[0].end = enet0_res[0].start;
185 enet0_res[0].end += RSET_ENET_SIZE - 1;
186 enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
187 enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
188 enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
189 pdev = &bcm63xx_enet0_device;
190 } else {
191 enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
192 enet1_res[0].end = enet1_res[0].start;
193 enet1_res[0].end += RSET_ENET_SIZE - 1;
194 enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
195 enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
196 enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
197 pdev = &bcm63xx_enet1_device;
198 }
199
200 /* copy given platform data */
201 dpd = pdev->dev.platform_data;
202 memcpy(dpd, pd, sizeof(*pd));
203
204 /* adjust them in case internal phy is used */
205 if (dpd->use_internal_phy) {
206
207 /* internal phy only exists for enet0 */
208 if (unit == 1)
209 return -ENODEV;
210
211 dpd->phy_id = 1;
212 dpd->has_phy_interrupt = 1;
213 dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
214 }
215
216 ret = platform_device_register(pdev);
217 if (ret)
218 return ret;
219 return 0;
220}
Maxime Bizon6f00a022013-06-04 22:53:35 +0100221
222int __init
223bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
224{
225 int ret;
226
227 if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
228 return -ENODEV;
229
230 ret = register_shared();
231 if (ret)
232 return ret;
233
234 enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
235 enetsw_res[0].end = enetsw_res[0].start;
236 enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
237 enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
238 enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
239 if (!enetsw_res[2].start)
240 enetsw_res[2].start = -1;
241
242 memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
243
244 if (BCMCPU_IS_6328())
245 enetsw_pd.num_ports = ENETSW_PORTS_6328;
246 else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
247 enetsw_pd.num_ports = ENETSW_PORTS_6368;
248
249 ret = platform_device_register(&bcm63xx_enetsw_device);
250 if (ret)
251 return ret;
252
253 return 0;
254}