aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/bcm63xx
diff options
context:
space:
mode:
authorMaxime Bizon <mbizon@freebox.fr>2013-06-04 17:53:35 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-10 17:28:28 -0400
commit6f00a0229627ca189529cad3f9154ac2f9e5c7db (patch)
tree20b010b5faa5fca26951f3f3575da92a9cf317fc /arch/mips/bcm63xx
parent0ae99b5fede6f3a8d252d50bb4aba29544295219 (diff)
bcm63xx_enet: add support for Broadcom BCM63xx integrated gigabit switch
Newer Broadcom BCM63xx SoCs: 6328, 6362 and 6368 have an integrated switch which needs to be driven slightly differently from the traditional external switches. This patch introduces changes in arch/mips/bcm63xx in order to: - register a bcm63xx_enetsw driver instead of bcm63xx_enet driver - update DMA channels configuration & state RAM base addresses - add a new platform data configuration knob to define the number of ports per switch/device and force link on some ports - define the required switch registers On the driver side, the following changes are required: - the switch ports need to be polled to ensure the link is up and running and RX/TX can properly work - basic switch configuration needs to be performed for the switch to forward packets to the CPU - update the MIB counters since the integrated Signed-off-by: Maxime Bizon <mbizon@freebox.fr> Signed-off-by: Jonas Gorski <jogo@openwrt.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r--arch/mips/bcm63xx/boards/board_bcm963xx.c4
-rw-r--r--arch/mips/bcm63xx/dev-enet.c113
2 files changed, 99 insertions, 18 deletions
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index a9505c4867e8..9c0ddafafb6c 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -845,6 +845,10 @@ int __init board_register_devices(void)
845 !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr)) 845 !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
846 bcm63xx_enet_register(1, &board.enet1); 846 bcm63xx_enet_register(1, &board.enet1);
847 847
848 if (board.has_enetsw &&
849 !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
850 bcm63xx_enetsw_register(&board.enetsw);
851
848 if (board.has_usbd) 852 if (board.has_usbd)
849 bcm63xx_usbd_register(&board.usbd); 853 bcm63xx_usbd_register(&board.usbd);
850 854
diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c
index df5bf6686942..6cbaee0f6d70 100644
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -104,6 +104,64 @@ static struct platform_device bcm63xx_enet1_device = {
104 }, 104 },
105}; 105};
106 106
107static 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
107int __init bcm63xx_enet_register(int unit, 165int __init bcm63xx_enet_register(int unit,
108 const struct bcm63xx_enet_platform_data *pd) 166 const struct bcm63xx_enet_platform_data *pd)
109{ 167{
@@ -117,24 +175,9 @@ int __init bcm63xx_enet_register(int unit,
117 if (unit == 1 && BCMCPU_IS_6338()) 175 if (unit == 1 && BCMCPU_IS_6338())
118 return -ENODEV; 176 return -ENODEV;
119 177
120 if (!shared_device_registered) { 178 ret = register_shared();
121 shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); 179 if (ret)
122 shared_res[0].end = shared_res[0].start; 180 return ret;
123 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;
132
133 ret = platform_device_register(&bcm63xx_enet_shared_device);
134 if (ret)
135 return ret;
136 shared_device_registered = 1;
137 }
138 181
139 if (unit == 0) { 182 if (unit == 0) {
140 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0); 183 enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
@@ -175,3 +218,37 @@ int __init bcm63xx_enet_register(int unit,
175 return ret; 218 return ret;
176 return 0; 219 return 0;
177} 220}
221
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}