Merge tag 'for-5.15/parisc' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[linux-2.6-microblaze.git] / 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 <linux/export.h>
13 #include <bcm63xx_dev_enet.h>
14 #include <bcm63xx_io.h>
15 #include <bcm63xx_regs.h>
16
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,
22 };
23
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,
33 };
34
35 const unsigned long *bcm63xx_regs_enetdmac;
36 EXPORT_SYMBOL(bcm63xx_regs_enetdmac);
37
38 static __init void bcm63xx_enetdmac_regs_init(void)
39 {
40         if (BCMCPU_IS_6345())
41                 bcm63xx_regs_enetdmac = bcm6345_regs_enetdmac;
42         else
43                 bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
44 }
45
46 static struct resource shared_res[] = {
47         {
48                 .start          = -1, /* filled at runtime */
49                 .end            = -1, /* filled at runtime */
50                 .flags          = IORESOURCE_MEM,
51         },
52         {
53                 .start          = -1, /* filled at runtime */
54                 .end            = -1, /* filled at runtime */
55                 .flags          = IORESOURCE_MEM,
56         },
57         {
58                 .start          = -1, /* filled at runtime */
59                 .end            = -1, /* filled at runtime */
60                 .flags          = IORESOURCE_MEM,
61         },
62 };
63
64 static struct platform_device bcm63xx_enet_shared_device = {
65         .name           = "bcm63xx_enet_shared",
66         .id             = 0,
67         .num_resources  = ARRAY_SIZE(shared_res),
68         .resource       = shared_res,
69 };
70
71 static int shared_device_registered;
72
73 static u64 enet_dmamask = DMA_BIT_MASK(32);
74
75 static struct resource enet0_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
95 static struct bcm63xx_enet_platform_data enet0_pd;
96
97 static struct platform_device bcm63xx_enet0_device = {
98         .name           = "bcm63xx_enet",
99         .id             = 0,
100         .num_resources  = ARRAY_SIZE(enet0_res),
101         .resource       = enet0_res,
102         .dev            = {
103                 .platform_data = &enet0_pd,
104                 .dma_mask = &enet_dmamask,
105                 .coherent_dma_mask = DMA_BIT_MASK(32),
106         },
107 };
108
109 static struct resource enet1_res[] = {
110         {
111                 .start          = -1, /* filled at runtime */
112                 .end            = -1, /* filled at runtime */
113                 .flags          = IORESOURCE_MEM,
114         },
115         {
116                 .start          = -1, /* filled at runtime */
117                 .flags          = IORESOURCE_IRQ,
118         },
119         {
120                 .start          = -1, /* filled at runtime */
121                 .flags          = IORESOURCE_IRQ,
122         },
123         {
124                 .start          = -1, /* filled at runtime */
125                 .flags          = IORESOURCE_IRQ,
126         },
127 };
128
129 static struct bcm63xx_enet_platform_data enet1_pd;
130
131 static struct platform_device bcm63xx_enet1_device = {
132         .name           = "bcm63xx_enet",
133         .id             = 1,
134         .num_resources  = ARRAY_SIZE(enet1_res),
135         .resource       = enet1_res,
136         .dev            = {
137                 .platform_data = &enet1_pd,
138                 .dma_mask = &enet_dmamask,
139                 .coherent_dma_mask = DMA_BIT_MASK(32),
140         },
141 };
142
143 static struct resource enetsw_res[] = {
144         {
145                 /* start & end filled at runtime */
146                 .flags          = IORESOURCE_MEM,
147         },
148         {
149                 /* start filled at runtime */
150                 .flags          = IORESOURCE_IRQ,
151         },
152         {
153                 /* start filled at runtime */
154                 .flags          = IORESOURCE_IRQ,
155         },
156 };
157
158 static struct bcm63xx_enetsw_platform_data enetsw_pd;
159
160 static struct platform_device bcm63xx_enetsw_device = {
161         .name           = "bcm63xx_enetsw",
162         .num_resources  = ARRAY_SIZE(enetsw_res),
163         .resource       = enetsw_res,
164         .dev            = {
165                 .platform_data = &enetsw_pd,
166                 .dma_mask = &enet_dmamask,
167                 .coherent_dma_mask = DMA_BIT_MASK(32),
168         },
169 };
170
171 static int __init register_shared(void)
172 {
173         int ret, chan_count;
174
175         if (shared_device_registered)
176                 return 0;
177
178         bcm63xx_enetdmac_regs_init();
179
180         shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
181         shared_res[0].end = shared_res[0].start;
182         if (BCMCPU_IS_6345())
183                 shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1;
184         else
185                 shared_res[0].end += (RSET_ENETDMA_SIZE)  - 1;
186
187         if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
188                 chan_count = 32;
189         else if (BCMCPU_IS_6345())
190                 chan_count = 8;
191         else
192                 chan_count = 16;
193
194         shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
195         shared_res[1].end = shared_res[1].start;
196         shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count)  - 1;
197
198         shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
199         shared_res[2].end = shared_res[2].start;
200         shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count)  - 1;
201
202         ret = platform_device_register(&bcm63xx_enet_shared_device);
203         if (ret)
204                 return ret;
205         shared_device_registered = 1;
206
207         return 0;
208 }
209
210 int __init bcm63xx_enet_register(int unit,
211                                  const struct bcm63xx_enet_platform_data *pd)
212 {
213         struct platform_device *pdev;
214         struct bcm63xx_enet_platform_data *dpd;
215         int ret;
216
217         if (unit > 1)
218                 return -ENODEV;
219
220         if (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
221                 return -ENODEV;
222
223         ret = register_shared();
224         if (ret)
225                 return ret;
226
227         if (unit == 0) {
228                 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
229                 enet0_res[0].end = enet0_res[0].start;
230                 enet0_res[0].end += RSET_ENET_SIZE - 1;
231                 enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
232                 enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
233                 enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
234                 pdev = &bcm63xx_enet0_device;
235         } else {
236                 enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
237                 enet1_res[0].end = enet1_res[0].start;
238                 enet1_res[0].end += RSET_ENET_SIZE - 1;
239                 enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
240                 enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
241                 enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
242                 pdev = &bcm63xx_enet1_device;
243         }
244
245         /* copy given platform data */
246         dpd = pdev->dev.platform_data;
247         memcpy(dpd, pd, sizeof(*pd));
248
249         /* adjust them in case internal phy is used */
250         if (dpd->use_internal_phy) {
251
252                 /* internal phy only exists for enet0 */
253                 if (unit == 1)
254                         return -ENODEV;
255
256                 dpd->phy_id = 1;
257                 dpd->has_phy_interrupt = 1;
258                 dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
259         }
260
261         dpd->dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
262         dpd->dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
263         if (BCMCPU_IS_6345()) {
264                 dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_CHAINING_MASK;
265                 dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_WRAP_EN_MASK;
266                 dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_FLOWC_EN_MASK;
267                 dpd->dma_chan_int_mask |= ENETDMA_IR_BUFDONE_MASK;
268                 dpd->dma_chan_int_mask |= ENETDMA_IR_NOTOWNER_MASK;
269                 dpd->dma_chan_width = ENETDMA_6345_CHAN_WIDTH;
270                 dpd->dma_desc_shift = ENETDMA_6345_DESC_SHIFT;
271         } else {
272                 dpd->dma_has_sram = true;
273                 dpd->dma_chan_width = ENETDMA_CHAN_WIDTH;
274         }
275
276         if (unit == 0) {
277                 dpd->rx_chan = 0;
278                 dpd->tx_chan = 1;
279         } else {
280                 dpd->rx_chan = 2;
281                 dpd->tx_chan = 3;
282         }
283
284         ret = platform_device_register(pdev);
285         if (ret)
286                 return ret;
287         return 0;
288 }
289
290 int __init
291 bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
292 {
293         int ret;
294
295         if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
296                 return -ENODEV;
297
298         ret = register_shared();
299         if (ret)
300                 return ret;
301
302         enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
303         enetsw_res[0].end = enetsw_res[0].start;
304         enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
305         enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
306         enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
307         if (!enetsw_res[2].start)
308                 enetsw_res[2].start = -1;
309
310         memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
311
312         if (BCMCPU_IS_6328())
313                 enetsw_pd.num_ports = ENETSW_PORTS_6328;
314         else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
315                 enetsw_pd.num_ports = ENETSW_PORTS_6368;
316
317         enetsw_pd.dma_has_sram = true;
318         enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH;
319         enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
320         enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
321
322         ret = platform_device_register(&bcm63xx_enetsw_device);
323         if (ret)
324                 return ret;
325
326         return 0;
327 }