blob: df5bf66869422dbbae3a9c001e01a43fd360b76f [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
107int __init bcm63xx_enet_register(int unit,
108 const struct bcm63xx_enet_platform_data *pd)
109{
110 struct platform_device *pdev;
111 struct bcm63xx_enet_platform_data *dpd;
112 int ret;
113
114 if (unit > 1)
115 return -ENODEV;
116
Florian Fainelli7f13f652010-07-21 22:59:26 +0200117 if (unit == 1 && BCMCPU_IS_6338())
118 return -ENODEV;
119
Maxime Bizon9b1fc552009-08-18 13:23:40 +0100120 if (!shared_device_registered) {
121 shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
122 shared_res[0].end = shared_res[0].start;
Maxime Bizon0ae99b52013-06-04 22:53:34 +0100123 shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
124
125 shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
126 shared_res[1].end = shared_res[1].start;
127 shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1;
128
129 shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
130 shared_res[2].end = shared_res[2].start;
131 shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1;
Maxime Bizon9b1fc552009-08-18 13:23:40 +0100132
133 ret = platform_device_register(&bcm63xx_enet_shared_device);
134 if (ret)
135 return ret;
136 shared_device_registered = 1;
137 }
138
139 if (unit == 0) {
140 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
141 enet0_res[0].end = enet0_res[0].start;
142 enet0_res[0].end += RSET_ENET_SIZE - 1;
143 enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
144 enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
145 enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
146 pdev = &bcm63xx_enet0_device;
147 } else {
148 enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
149 enet1_res[0].end = enet1_res[0].start;
150 enet1_res[0].end += RSET_ENET_SIZE - 1;
151 enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
152 enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
153 enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
154 pdev = &bcm63xx_enet1_device;
155 }
156
157 /* copy given platform data */
158 dpd = pdev->dev.platform_data;
159 memcpy(dpd, pd, sizeof(*pd));
160
161 /* adjust them in case internal phy is used */
162 if (dpd->use_internal_phy) {
163
164 /* internal phy only exists for enet0 */
165 if (unit == 1)
166 return -ENODEV;
167
168 dpd->phy_id = 1;
169 dpd->has_phy_interrupt = 1;
170 dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
171 }
172
173 ret = platform_device_register(pdev);
174 if (ret)
175 return ret;
176 return 0;
177}