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 static const unsigned long bcm6348_regs_enetdmac
[] = {
18 [ENETDMAC_CHANCFG
] = ENETDMAC_CHANCFG_REG
,
19 [ENETDMAC_IR
] = ENETDMAC_IR_REG
,
20 [ENETDMAC_IRMASK
] = ENETDMAC_IRMASK_REG
,
21 [ENETDMAC_MAXBURST
] = ENETDMAC_MAXBURST_REG
,
24 static const unsigned long bcm6345_regs_enetdmac
[] = {
25 [ENETDMAC_CHANCFG
] = ENETDMA_6345_CHANCFG_REG
,
26 [ENETDMAC_IR
] = ENETDMA_6345_IR_REG
,
27 [ENETDMAC_IRMASK
] = ENETDMA_6345_IRMASK_REG
,
28 [ENETDMAC_MAXBURST
] = ENETDMA_6345_MAXBURST_REG
,
29 [ENETDMAC_BUFALLOC
] = ENETDMA_6345_BUFALLOC_REG
,
30 [ENETDMAC_RSTART
] = ENETDMA_6345_RSTART_REG
,
31 [ENETDMAC_FC
] = ENETDMA_6345_FC_REG
,
32 [ENETDMAC_LEN
] = ENETDMA_6345_LEN_REG
,
35 const unsigned long *bcm63xx_regs_enetdmac
;
36 EXPORT_SYMBOL(bcm63xx_regs_enetdmac
);
38 static __init
void bcm63xx_enetdmac_regs_init(void)
41 bcm63xx_regs_enetdmac
= bcm6345_regs_enetdmac
;
43 bcm63xx_regs_enetdmac
= bcm6348_regs_enetdmac
;
46 static struct resource shared_res
[] = {
48 .start
= -1, /* filled at runtime */
49 .end
= -1, /* filled at runtime */
50 .flags
= IORESOURCE_MEM
,
53 .start
= -1, /* filled at runtime */
54 .end
= -1, /* filled at runtime */
55 .flags
= IORESOURCE_MEM
,
58 .start
= -1, /* filled at runtime */
59 .end
= -1, /* filled at runtime */
60 .flags
= IORESOURCE_MEM
,
64 static struct platform_device bcm63xx_enet_shared_device
= {
65 .name
= "bcm63xx_enet_shared",
67 .num_resources
= ARRAY_SIZE(shared_res
),
68 .resource
= shared_res
,
71 static int shared_device_registered
;
73 static struct resource enet0_res
[] = {
75 .start
= -1, /* filled at runtime */
76 .end
= -1, /* filled at runtime */
77 .flags
= IORESOURCE_MEM
,
80 .start
= -1, /* filled at runtime */
81 .flags
= IORESOURCE_IRQ
,
84 .start
= -1, /* filled at runtime */
85 .flags
= IORESOURCE_IRQ
,
88 .start
= -1, /* filled at runtime */
89 .flags
= IORESOURCE_IRQ
,
93 static struct bcm63xx_enet_platform_data enet0_pd
;
95 static struct platform_device bcm63xx_enet0_device
= {
96 .name
= "bcm63xx_enet",
98 .num_resources
= ARRAY_SIZE(enet0_res
),
99 .resource
= enet0_res
,
101 .platform_data
= &enet0_pd
,
105 static struct resource enet1_res
[] = {
107 .start
= -1, /* filled at runtime */
108 .end
= -1, /* filled at runtime */
109 .flags
= IORESOURCE_MEM
,
112 .start
= -1, /* filled at runtime */
113 .flags
= IORESOURCE_IRQ
,
116 .start
= -1, /* filled at runtime */
117 .flags
= IORESOURCE_IRQ
,
120 .start
= -1, /* filled at runtime */
121 .flags
= IORESOURCE_IRQ
,
125 static struct bcm63xx_enet_platform_data enet1_pd
;
127 static struct platform_device bcm63xx_enet1_device
= {
128 .name
= "bcm63xx_enet",
130 .num_resources
= ARRAY_SIZE(enet1_res
),
131 .resource
= enet1_res
,
133 .platform_data
= &enet1_pd
,
137 static struct resource enetsw_res
[] = {
139 /* start & end filled at runtime */
140 .flags
= IORESOURCE_MEM
,
143 /* start filled at runtime */
144 .flags
= IORESOURCE_IRQ
,
147 /* start filled at runtime */
148 .flags
= IORESOURCE_IRQ
,
152 static struct bcm63xx_enetsw_platform_data enetsw_pd
;
154 static struct platform_device bcm63xx_enetsw_device
= {
155 .name
= "bcm63xx_enetsw",
156 .num_resources
= ARRAY_SIZE(enetsw_res
),
157 .resource
= enetsw_res
,
159 .platform_data
= &enetsw_pd
,
163 static int __init
register_shared(void)
167 if (shared_device_registered
)
170 bcm63xx_enetdmac_regs_init();
172 shared_res
[0].start
= bcm63xx_regset_address(RSET_ENETDMA
);
173 shared_res
[0].end
= shared_res
[0].start
;
174 if (BCMCPU_IS_6345())
175 shared_res
[0].end
+= (RSET_6345_ENETDMA_SIZE
) - 1;
177 shared_res
[0].end
+= (RSET_ENETDMA_SIZE
) - 1;
179 if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
181 else if (BCMCPU_IS_6345())
186 shared_res
[1].start
= bcm63xx_regset_address(RSET_ENETDMAC
);
187 shared_res
[1].end
= shared_res
[1].start
;
188 shared_res
[1].end
+= RSET_ENETDMAC_SIZE(chan_count
) - 1;
190 shared_res
[2].start
= bcm63xx_regset_address(RSET_ENETDMAS
);
191 shared_res
[2].end
= shared_res
[2].start
;
192 shared_res
[2].end
+= RSET_ENETDMAS_SIZE(chan_count
) - 1;
194 ret
= platform_device_register(&bcm63xx_enet_shared_device
);
197 shared_device_registered
= 1;
202 int __init
bcm63xx_enet_register(int unit
,
203 const struct bcm63xx_enet_platform_data
*pd
)
205 struct platform_device
*pdev
;
206 struct bcm63xx_enet_platform_data
*dpd
;
212 if (unit
== 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
215 ret
= register_shared();
220 enet0_res
[0].start
= bcm63xx_regset_address(RSET_ENET0
);
221 enet0_res
[0].end
= enet0_res
[0].start
;
222 enet0_res
[0].end
+= RSET_ENET_SIZE
- 1;
223 enet0_res
[1].start
= bcm63xx_get_irq_number(IRQ_ENET0
);
224 enet0_res
[2].start
= bcm63xx_get_irq_number(IRQ_ENET0_RXDMA
);
225 enet0_res
[3].start
= bcm63xx_get_irq_number(IRQ_ENET0_TXDMA
);
226 pdev
= &bcm63xx_enet0_device
;
228 enet1_res
[0].start
= bcm63xx_regset_address(RSET_ENET1
);
229 enet1_res
[0].end
= enet1_res
[0].start
;
230 enet1_res
[0].end
+= RSET_ENET_SIZE
- 1;
231 enet1_res
[1].start
= bcm63xx_get_irq_number(IRQ_ENET1
);
232 enet1_res
[2].start
= bcm63xx_get_irq_number(IRQ_ENET1_RXDMA
);
233 enet1_res
[3].start
= bcm63xx_get_irq_number(IRQ_ENET1_TXDMA
);
234 pdev
= &bcm63xx_enet1_device
;
237 /* copy given platform data */
238 dpd
= pdev
->dev
.platform_data
;
239 memcpy(dpd
, pd
, sizeof(*pd
));
241 /* adjust them in case internal phy is used */
242 if (dpd
->use_internal_phy
) {
244 /* internal phy only exists for enet0 */
249 dpd
->has_phy_interrupt
= 1;
250 dpd
->phy_interrupt
= bcm63xx_get_irq_number(IRQ_ENET_PHY
);
253 dpd
->dma_chan_en_mask
= ENETDMAC_CHANCFG_EN_MASK
;
254 dpd
->dma_chan_int_mask
= ENETDMAC_IR_PKTDONE_MASK
;
255 if (BCMCPU_IS_6345()) {
256 dpd
->dma_chan_en_mask
|= ENETDMAC_CHANCFG_CHAINING_MASK
;
257 dpd
->dma_chan_en_mask
|= ENETDMAC_CHANCFG_WRAP_EN_MASK
;
258 dpd
->dma_chan_en_mask
|= ENETDMAC_CHANCFG_FLOWC_EN_MASK
;
259 dpd
->dma_chan_int_mask
|= ENETDMA_IR_BUFDONE_MASK
;
260 dpd
->dma_chan_int_mask
|= ENETDMA_IR_NOTOWNER_MASK
;
261 dpd
->dma_chan_width
= ENETDMA_6345_CHAN_WIDTH
;
262 dpd
->dma_desc_shift
= ENETDMA_6345_DESC_SHIFT
;
264 dpd
->dma_has_sram
= true;
265 dpd
->dma_chan_width
= ENETDMA_CHAN_WIDTH
;
268 ret
= platform_device_register(pdev
);
275 bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data
*pd
)
279 if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
282 ret
= register_shared();
286 enetsw_res
[0].start
= bcm63xx_regset_address(RSET_ENETSW
);
287 enetsw_res
[0].end
= enetsw_res
[0].start
;
288 enetsw_res
[0].end
+= RSET_ENETSW_SIZE
- 1;
289 enetsw_res
[1].start
= bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0
);
290 enetsw_res
[2].start
= bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0
);
291 if (!enetsw_res
[2].start
)
292 enetsw_res
[2].start
= -1;
294 memcpy(bcm63xx_enetsw_device
.dev
.platform_data
, pd
, sizeof(*pd
));
296 if (BCMCPU_IS_6328())
297 enetsw_pd
.num_ports
= ENETSW_PORTS_6328
;
298 else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
299 enetsw_pd
.num_ports
= ENETSW_PORTS_6368
;
301 enetsw_pd
.dma_has_sram
= true;
302 enetsw_pd
.dma_chan_width
= ENETDMA_CHAN_WIDTH
;
303 enetsw_pd
.dma_chan_en_mask
= ENETDMAC_CHANCFG_EN_MASK
;
304 enetsw_pd
.dma_chan_int_mask
= ENETDMAC_IR_PKTDONE_MASK
;
306 ret
= platform_device_register(&bcm63xx_enetsw_device
);