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
6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/platform_device.h>
12 #include <linux/export.h>
13 #include <bcm63xx_dev_enet.h>
14 #include <bcm63xx_io.h>
15 #include <bcm63xx_regs.h>
17 #ifdef BCMCPU_RUNTIME_DETECT
18 static const unsigned long bcm6348_regs_enetdmac
[] = {
19 [ENETDMAC_CHANCFG
] = ENETDMAC_CHANCFG_REG
,
20 [ENETDMAC_IR
] = ENETDMAC_IR_REG
,
21 [ENETDMAC_IRMASK
] = ENETDMAC_IRMASK_REG
,
22 [ENETDMAC_MAXBURST
] = ENETDMAC_MAXBURST_REG
,
25 static const unsigned long bcm6345_regs_enetdmac
[] = {
26 [ENETDMAC_CHANCFG
] = ENETDMA_6345_CHANCFG_REG
,
27 [ENETDMAC_IR
] = ENETDMA_6345_IR_REG
,
28 [ENETDMAC_IRMASK
] = ENETDMA_6345_IRMASK_REG
,
29 [ENETDMAC_MAXBURST
] = ENETDMA_6345_MAXBURST_REG
,
30 [ENETDMAC_BUFALLOC
] = ENETDMA_6345_BUFALLOC_REG
,
31 [ENETDMAC_RSTART
] = ENETDMA_6345_RSTART_REG
,
32 [ENETDMAC_FC
] = ENETDMA_6345_FC_REG
,
33 [ENETDMAC_LEN
] = ENETDMA_6345_LEN_REG
,
36 const unsigned long *bcm63xx_regs_enetdmac
;
37 EXPORT_SYMBOL(bcm63xx_regs_enetdmac
);
39 static __init
void bcm63xx_enetdmac_regs_init(void)
42 bcm63xx_regs_enetdmac
= bcm6345_regs_enetdmac
;
44 bcm63xx_regs_enetdmac
= bcm6348_regs_enetdmac
;
47 static __init
void bcm63xx_enetdmac_regs_init(void) { }
50 static struct resource shared_res
[] = {
52 .start
= -1, /* filled at runtime */
53 .end
= -1, /* filled at runtime */
54 .flags
= IORESOURCE_MEM
,
57 .start
= -1, /* filled at runtime */
58 .end
= -1, /* filled at runtime */
59 .flags
= IORESOURCE_MEM
,
62 .start
= -1, /* filled at runtime */
63 .end
= -1, /* filled at runtime */
64 .flags
= IORESOURCE_MEM
,
68 static struct platform_device bcm63xx_enet_shared_device
= {
69 .name
= "bcm63xx_enet_shared",
71 .num_resources
= ARRAY_SIZE(shared_res
),
72 .resource
= shared_res
,
75 static int shared_device_registered
;
77 static struct resource enet0_res
[] = {
79 .start
= -1, /* filled at runtime */
80 .end
= -1, /* filled at runtime */
81 .flags
= IORESOURCE_MEM
,
84 .start
= -1, /* filled at runtime */
85 .flags
= IORESOURCE_IRQ
,
88 .start
= -1, /* filled at runtime */
89 .flags
= IORESOURCE_IRQ
,
92 .start
= -1, /* filled at runtime */
93 .flags
= IORESOURCE_IRQ
,
97 static struct bcm63xx_enet_platform_data enet0_pd
;
99 static struct platform_device bcm63xx_enet0_device
= {
100 .name
= "bcm63xx_enet",
102 .num_resources
= ARRAY_SIZE(enet0_res
),
103 .resource
= enet0_res
,
105 .platform_data
= &enet0_pd
,
109 static struct resource enet1_res
[] = {
111 .start
= -1, /* filled at runtime */
112 .end
= -1, /* filled at runtime */
113 .flags
= IORESOURCE_MEM
,
116 .start
= -1, /* filled at runtime */
117 .flags
= IORESOURCE_IRQ
,
120 .start
= -1, /* filled at runtime */
121 .flags
= IORESOURCE_IRQ
,
124 .start
= -1, /* filled at runtime */
125 .flags
= IORESOURCE_IRQ
,
129 static struct bcm63xx_enet_platform_data enet1_pd
;
131 static struct platform_device bcm63xx_enet1_device
= {
132 .name
= "bcm63xx_enet",
134 .num_resources
= ARRAY_SIZE(enet1_res
),
135 .resource
= enet1_res
,
137 .platform_data
= &enet1_pd
,
141 static struct resource enetsw_res
[] = {
143 /* start & end filled at runtime */
144 .flags
= IORESOURCE_MEM
,
147 /* start filled at runtime */
148 .flags
= IORESOURCE_IRQ
,
151 /* start filled at runtime */
152 .flags
= IORESOURCE_IRQ
,
156 static struct bcm63xx_enetsw_platform_data enetsw_pd
;
158 static struct platform_device bcm63xx_enetsw_device
= {
159 .name
= "bcm63xx_enetsw",
160 .num_resources
= ARRAY_SIZE(enetsw_res
),
161 .resource
= enetsw_res
,
163 .platform_data
= &enetsw_pd
,
167 static int __init
register_shared(void)
171 if (shared_device_registered
)
174 bcm63xx_enetdmac_regs_init();
176 shared_res
[0].start
= bcm63xx_regset_address(RSET_ENETDMA
);
177 shared_res
[0].end
= shared_res
[0].start
;
178 if (BCMCPU_IS_6345())
179 shared_res
[0].end
+= (RSET_6345_ENETDMA_SIZE
) - 1;
181 shared_res
[0].end
+= (RSET_ENETDMA_SIZE
) - 1;
183 if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
185 else if (BCMCPU_IS_6345())
190 shared_res
[1].start
= bcm63xx_regset_address(RSET_ENETDMAC
);
191 shared_res
[1].end
= shared_res
[1].start
;
192 shared_res
[1].end
+= RSET_ENETDMAC_SIZE(chan_count
) - 1;
194 shared_res
[2].start
= bcm63xx_regset_address(RSET_ENETDMAS
);
195 shared_res
[2].end
= shared_res
[2].start
;
196 shared_res
[2].end
+= RSET_ENETDMAS_SIZE(chan_count
) - 1;
198 ret
= platform_device_register(&bcm63xx_enet_shared_device
);
201 shared_device_registered
= 1;
206 int __init
bcm63xx_enet_register(int unit
,
207 const struct bcm63xx_enet_platform_data
*pd
)
209 struct platform_device
*pdev
;
210 struct bcm63xx_enet_platform_data
*dpd
;
216 if (unit
== 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
219 ret
= register_shared();
224 enet0_res
[0].start
= bcm63xx_regset_address(RSET_ENET0
);
225 enet0_res
[0].end
= enet0_res
[0].start
;
226 enet0_res
[0].end
+= RSET_ENET_SIZE
- 1;
227 enet0_res
[1].start
= bcm63xx_get_irq_number(IRQ_ENET0
);
228 enet0_res
[2].start
= bcm63xx_get_irq_number(IRQ_ENET0_RXDMA
);
229 enet0_res
[3].start
= bcm63xx_get_irq_number(IRQ_ENET0_TXDMA
);
230 pdev
= &bcm63xx_enet0_device
;
232 enet1_res
[0].start
= bcm63xx_regset_address(RSET_ENET1
);
233 enet1_res
[0].end
= enet1_res
[0].start
;
234 enet1_res
[0].end
+= RSET_ENET_SIZE
- 1;
235 enet1_res
[1].start
= bcm63xx_get_irq_number(IRQ_ENET1
);
236 enet1_res
[2].start
= bcm63xx_get_irq_number(IRQ_ENET1_RXDMA
);
237 enet1_res
[3].start
= bcm63xx_get_irq_number(IRQ_ENET1_TXDMA
);
238 pdev
= &bcm63xx_enet1_device
;
241 /* copy given platform data */
242 dpd
= pdev
->dev
.platform_data
;
243 memcpy(dpd
, pd
, sizeof(*pd
));
245 /* adjust them in case internal phy is used */
246 if (dpd
->use_internal_phy
) {
248 /* internal phy only exists for enet0 */
253 dpd
->has_phy_interrupt
= 1;
254 dpd
->phy_interrupt
= bcm63xx_get_irq_number(IRQ_ENET_PHY
);
257 dpd
->dma_chan_en_mask
= ENETDMAC_CHANCFG_EN_MASK
;
258 dpd
->dma_chan_int_mask
= ENETDMAC_IR_PKTDONE_MASK
;
259 if (BCMCPU_IS_6345()) {
260 dpd
->dma_chan_en_mask
|= ENETDMAC_CHANCFG_CHAINING_MASK
;
261 dpd
->dma_chan_en_mask
|= ENETDMAC_CHANCFG_WRAP_EN_MASK
;
262 dpd
->dma_chan_en_mask
|= ENETDMAC_CHANCFG_FLOWC_EN_MASK
;
263 dpd
->dma_chan_int_mask
|= ENETDMA_IR_BUFDONE_MASK
;
264 dpd
->dma_chan_int_mask
|= ENETDMA_IR_NOTOWNER_MASK
;
265 dpd
->dma_chan_width
= ENETDMA_6345_CHAN_WIDTH
;
266 dpd
->dma_desc_shift
= ENETDMA_6345_DESC_SHIFT
;
268 dpd
->dma_has_sram
= true;
269 dpd
->dma_chan_width
= ENETDMA_CHAN_WIDTH
;
272 ret
= platform_device_register(pdev
);
279 bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data
*pd
)
283 if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
286 ret
= register_shared();
290 enetsw_res
[0].start
= bcm63xx_regset_address(RSET_ENETSW
);
291 enetsw_res
[0].end
= enetsw_res
[0].start
;
292 enetsw_res
[0].end
+= RSET_ENETSW_SIZE
- 1;
293 enetsw_res
[1].start
= bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0
);
294 enetsw_res
[2].start
= bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0
);
295 if (!enetsw_res
[2].start
)
296 enetsw_res
[2].start
= -1;
298 memcpy(bcm63xx_enetsw_device
.dev
.platform_data
, pd
, sizeof(*pd
));
300 if (BCMCPU_IS_6328())
301 enetsw_pd
.num_ports
= ENETSW_PORTS_6328
;
302 else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
303 enetsw_pd
.num_ports
= ENETSW_PORTS_6368
;
305 enetsw_pd
.dma_has_sram
= true;
306 enetsw_pd
.dma_chan_width
= ENETDMA_CHAN_WIDTH
;
307 enetsw_pd
.dma_chan_en_mask
= ENETDMAC_CHANCFG_EN_MASK
;
308 enetsw_pd
.dma_chan_int_mask
= ENETDMAC_IR_PKTDONE_MASK
;
310 ret
= platform_device_register(&bcm63xx_enetsw_device
);