| @@ -1,41 +1,41 @@ | | | @@ -1,41 +1,41 @@ |
1 | /* $NetBSD: if_mvgbe.c,v 1.12 2011/09/01 14:46:23 jakllsch Exp $ */ | | 1 | /* $NetBSD: if_mvgbe.c,v 1.13 2011/09/06 19:38:23 rjs Exp $ */ |
2 | /* | | 2 | /* |
3 | * Copyright (c) 2007, 2008 KIYOHARA Takashi | | 3 | * Copyright (c) 2007, 2008 KIYOHARA Takashi |
4 | * All rights reserved. | | 4 | * All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | | 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | | 18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
19 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 19 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | | 23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
24 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 24 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 | * POSSIBILITY OF SUCH DAMAGE. | | 25 | * POSSIBILITY OF SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | #include <sys/cdefs.h> | | 27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.12 2011/09/01 14:46:23 jakllsch Exp $"); | | 28 | __KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.13 2011/09/06 19:38:23 rjs Exp $"); |
29 | | | 29 | |
30 | #include "rnd.h" | | 30 | #include "rnd.h" |
31 | | | 31 | |
32 | #include <sys/param.h> | | 32 | #include <sys/param.h> |
33 | #include <sys/bus.h> | | 33 | #include <sys/bus.h> |
34 | #include <sys/device.h> | | 34 | #include <sys/device.h> |
35 | #include <sys/endian.h> | | 35 | #include <sys/endian.h> |
36 | #include <sys/errno.h> | | 36 | #include <sys/errno.h> |
37 | #include <sys/kmem.h> | | 37 | #include <sys/kmem.h> |
38 | #include <sys/mutex.h> | | 38 | #include <sys/mutex.h> |
39 | #include <sys/sockio.h> | | 39 | #include <sys/sockio.h> |
40 | | | 40 | |
41 | #include <dev/marvell/marvellreg.h> | | 41 | #include <dev/marvell/marvellreg.h> |
| @@ -180,27 +180,27 @@ struct mvgbe_chain_data { | | | @@ -180,27 +180,27 @@ struct mvgbe_chain_data { |
180 | struct mvgbe_ring_data { | | 180 | struct mvgbe_ring_data { |
181 | struct mvgbe_tx_desc mvgbe_tx_ring[MVGBE_TX_RING_CNT]; | | 181 | struct mvgbe_tx_desc mvgbe_tx_ring[MVGBE_TX_RING_CNT]; |
182 | struct mvgbe_rx_desc mvgbe_rx_ring[MVGBE_RX_RING_CNT]; | | 182 | struct mvgbe_rx_desc mvgbe_rx_ring[MVGBE_RX_RING_CNT]; |
183 | }; | | 183 | }; |
184 | | | 184 | |
185 | struct mvgbec_softc { | | 185 | struct mvgbec_softc { |
186 | device_t sc_dev; | | 186 | device_t sc_dev; |
187 | | | 187 | |
188 | bus_space_tag_t sc_iot; | | 188 | bus_space_tag_t sc_iot; |
189 | bus_space_handle_t sc_ioh; | | 189 | bus_space_handle_t sc_ioh; |
190 | | | 190 | |
191 | kmutex_t sc_mtx; | | 191 | kmutex_t sc_mtx; |
192 | | | 192 | |
193 | int sc_fix_tqtb; | | 193 | int sc_flags; |
194 | }; | | 194 | }; |
195 | | | 195 | |
196 | struct mvgbe_softc { | | 196 | struct mvgbe_softc { |
197 | device_t sc_dev; | | 197 | device_t sc_dev; |
198 | int sc_port; | | 198 | int sc_port; |
199 | | | 199 | |
200 | bus_space_tag_t sc_iot; | | 200 | bus_space_tag_t sc_iot; |
201 | bus_space_handle_t sc_ioh; | | 201 | bus_space_handle_t sc_ioh; |
202 | bus_space_handle_t sc_dafh; /* dest address filter handle */ | | 202 | bus_space_handle_t sc_dafh; /* dest address filter handle */ |
203 | bus_dma_tag_t sc_dmat; | | 203 | bus_dma_tag_t sc_dmat; |
204 | | | 204 | |
205 | struct ethercom sc_ethercom; | | 205 | struct ethercom sc_ethercom; |
206 | struct mii_data sc_mii; | | 206 | struct mii_data sc_mii; |
| @@ -276,41 +276,42 @@ CFATTACH_DECL_NEW(mvgbec_mbus, sizeof(st | | | @@ -276,41 +276,42 @@ CFATTACH_DECL_NEW(mvgbec_mbus, sizeof(st |
276 | | | 276 | |
277 | CFATTACH_DECL_NEW(mvgbe, sizeof(struct mvgbe_softc), | | 277 | CFATTACH_DECL_NEW(mvgbe, sizeof(struct mvgbe_softc), |
278 | mvgbe_match, mvgbe_attach, NULL, NULL); | | 278 | mvgbe_match, mvgbe_attach, NULL, NULL); |
279 | | | 279 | |
280 | device_t mvgbec0 = NULL; | | 280 | device_t mvgbec0 = NULL; |
281 | | | 281 | |
282 | struct mvgbe_port { | | 282 | struct mvgbe_port { |
283 | int model; | | 283 | int model; |
284 | int unit; | | 284 | int unit; |
285 | int ports; | | 285 | int ports; |
286 | int irqs[3]; | | 286 | int irqs[3]; |
287 | int flags; | | 287 | int flags; |
288 | #define FLAGS_FIX_TQTB (1 << 0) | | 288 | #define FLAGS_FIX_TQTB (1 << 0) |
| | | 289 | #define FLAGS_FIX_MTU (1 << 1) |
289 | } mvgbe_ports[] = { | | 290 | } mvgbe_ports[] = { |
290 | { MARVELL_DISCOVERY_II, 0, 3, { 32, 33, 34 }, 0 }, | | 291 | { MARVELL_DISCOVERY_II, 0, 3, { 32, 33, 34 }, 0 }, |
291 | { MARVELL_DISCOVERY_III, 0, 3, { 32, 33, 34 }, 0 }, | | 292 | { MARVELL_DISCOVERY_III, 0, 3, { 32, 33, 34 }, 0 }, |
292 | #if 0 | | 293 | #if 0 |
293 | { MARVELL_DISCOVERY_LT, 0, ?, { }, 0 }, | | 294 | { MARVELL_DISCOVERY_LT, 0, ?, { }, 0 }, |
294 | { MARVELL_DISCOVERY_V, 0, ?, { }, 0 }, | | 295 | { MARVELL_DISCOVERY_V, 0, ?, { }, 0 }, |
295 | { MARVELL_DISCOVERY_VI, 0, ?, { }, 0 }, | | 296 | { MARVELL_DISCOVERY_VI, 0, ?, { }, 0 }, |
296 | #endif | | 297 | #endif |
297 | { MARVELL_ORION_1_88F5082, 0, 1, { 21 }, 0 }, | | 298 | { MARVELL_ORION_1_88F5082, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
298 | { MARVELL_ORION_1_88F5180N, 0, 1, { 21 }, 0 }, | | 299 | { MARVELL_ORION_1_88F5180N, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
299 | { MARVELL_ORION_1_88F5181, 0, 1, { 21 }, 0 }, | | 300 | { MARVELL_ORION_1_88F5181, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
300 | { MARVELL_ORION_1_88F5182, 0, 1, { 21 }, 0 }, | | 301 | { MARVELL_ORION_1_88F5182, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
301 | { MARVELL_ORION_2_88F5281, 0, 1, { 21 }, 0 }, | | 302 | { MARVELL_ORION_2_88F5281, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
302 | { MARVELL_ORION_1_88F6082, 0, 1, { 21 }, 0 }, | | 303 | { MARVELL_ORION_1_88F6082, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
303 | { MARVELL_ORION_1_88W8660, 0, 1, { 21 }, 0 }, | | 304 | { MARVELL_ORION_1_88W8660, 0, 1, { 21 }, FLAGS_FIX_MTU }, |
304 | | | 305 | |
305 | { MARVELL_KIRKWOOD_88F6180, 0, 1, { 11 }, FLAGS_FIX_TQTB }, | | 306 | { MARVELL_KIRKWOOD_88F6180, 0, 1, { 11 }, FLAGS_FIX_TQTB }, |
306 | { MARVELL_KIRKWOOD_88F6192, 0, 1, { 11 }, FLAGS_FIX_TQTB }, | | 307 | { MARVELL_KIRKWOOD_88F6192, 0, 1, { 11 }, FLAGS_FIX_TQTB }, |
307 | { MARVELL_KIRKWOOD_88F6192, 1, 1, { 14 }, FLAGS_FIX_TQTB }, | | 308 | { MARVELL_KIRKWOOD_88F6192, 1, 1, { 14 }, FLAGS_FIX_TQTB }, |
308 | { MARVELL_KIRKWOOD_88F6281, 0, 1, { 11 }, FLAGS_FIX_TQTB }, | | 309 | { MARVELL_KIRKWOOD_88F6281, 0, 1, { 11 }, FLAGS_FIX_TQTB }, |
309 | { MARVELL_KIRKWOOD_88F6281, 1, 1, { 15 }, FLAGS_FIX_TQTB }, | | 310 | { MARVELL_KIRKWOOD_88F6281, 1, 1, { 15 }, FLAGS_FIX_TQTB }, |
310 | | | 311 | |
311 | { MARVELL_MV78XX0_MV78100, 0, 1, { 40 }, FLAGS_FIX_TQTB }, | | 312 | { MARVELL_MV78XX0_MV78100, 0, 1, { 40 }, FLAGS_FIX_TQTB }, |
312 | { MARVELL_MV78XX0_MV78100, 1, 1, { 44 }, FLAGS_FIX_TQTB }, | | 313 | { MARVELL_MV78XX0_MV78100, 1, 1, { 44 }, FLAGS_FIX_TQTB }, |
313 | { MARVELL_MV78XX0_MV78200, 0, 1, { 40 }, FLAGS_FIX_TQTB }, | | 314 | { MARVELL_MV78XX0_MV78200, 0, 1, { 40 }, FLAGS_FIX_TQTB }, |
314 | { MARVELL_MV78XX0_MV78200, 1, 1, { 44 }, FLAGS_FIX_TQTB }, | | 315 | { MARVELL_MV78XX0_MV78200, 1, 1, { 44 }, FLAGS_FIX_TQTB }, |
315 | { MARVELL_MV78XX0_MV78200, 2, 1, { 48 }, FLAGS_FIX_TQTB }, | | 316 | { MARVELL_MV78XX0_MV78200, 2, 1, { 48 }, FLAGS_FIX_TQTB }, |
316 | { MARVELL_MV78XX0_MV78200, 3, 1, { 52 }, FLAGS_FIX_TQTB }, | | 317 | { MARVELL_MV78XX0_MV78200, 3, 1, { 52 }, FLAGS_FIX_TQTB }, |
| @@ -370,27 +371,27 @@ mvgbec_attach(device_t parent, device_t | | | @@ -370,27 +371,27 @@ mvgbec_attach(device_t parent, device_t |
370 | | | 371 | |
371 | /* Disable and clear Gigabit Ethernet Unit interrupts */ | | 372 | /* Disable and clear Gigabit Ethernet Unit interrupts */ |
372 | MVGBE_WRITE(sc, MVGBE_EUIM, 0); | | 373 | MVGBE_WRITE(sc, MVGBE_EUIM, 0); |
373 | MVGBE_WRITE(sc, MVGBE_EUIC, 0); | | 374 | MVGBE_WRITE(sc, MVGBE_EUIC, 0); |
374 | | | 375 | |
375 | mvgbec_wininit(sc); | | 376 | mvgbec_wininit(sc); |
376 | | | 377 | |
377 | memset(&gbea, 0, sizeof(gbea)); | | 378 | memset(&gbea, 0, sizeof(gbea)); |
378 | for (i = 0; i < __arraycount(mvgbe_ports); i++) { | | 379 | for (i = 0; i < __arraycount(mvgbe_ports); i++) { |
379 | if (mvgbe_ports[i].model != mva->mva_model || | | 380 | if (mvgbe_ports[i].model != mva->mva_model || |
380 | mvgbe_ports[i].unit != mva->mva_unit) | | 381 | mvgbe_ports[i].unit != mva->mva_unit) |
381 | continue; | | 382 | continue; |
382 | | | 383 | |
383 | sc->sc_fix_tqtb = mvgbe_ports[i].flags & FLAGS_FIX_TQTB; | | 384 | sc->sc_flags = mvgbe_ports[i].flags; |
384 | | | 385 | |
385 | for (j = 0; j < mvgbe_ports[i].ports; j++) { | | 386 | for (j = 0; j < mvgbe_ports[i].ports; j++) { |
386 | gbea.mva_name = "mvgbe"; | | 387 | gbea.mva_name = "mvgbe"; |
387 | gbea.mva_model = mva->mva_model; | | 388 | gbea.mva_model = mva->mva_model; |
388 | gbea.mva_iot = sc->sc_iot; | | 389 | gbea.mva_iot = sc->sc_iot; |
389 | gbea.mva_ioh = sc->sc_ioh; | | 390 | gbea.mva_ioh = sc->sc_ioh; |
390 | gbea.mva_unit = j; | | 391 | gbea.mva_unit = j; |
391 | gbea.mva_dmat = mva->mva_dmat; | | 392 | gbea.mva_dmat = mva->mva_dmat; |
392 | gbea.mva_irq = mvgbe_ports[i].irqs[j]; | | 393 | gbea.mva_irq = mvgbe_ports[i].irqs[j]; |
393 | child = config_found_sm_loc(sc->sc_dev, "mvgbec", NULL, | | 394 | child = config_found_sm_loc(sc->sc_dev, "mvgbec", NULL, |
394 | &gbea, mvgbec_print, mvgbec_search); | | 395 | &gbea, mvgbec_print, mvgbec_search); |
395 | if (child) { | | 396 | if (child) { |
396 | port = device_private(child); | | 397 | port = device_private(child); |
| @@ -970,43 +971,44 @@ mvgbe_init(struct ifnet *ifp) | | | @@ -970,43 +971,44 @@ mvgbe_init(struct ifnet *ifp) |
970 | | | 971 | |
971 | /* Init TX/RX descriptors */ | | 972 | /* Init TX/RX descriptors */ |
972 | if (mvgbe_init_tx_ring(sc) == ENOBUFS) { | | 973 | if (mvgbe_init_tx_ring(sc) == ENOBUFS) { |
973 | aprint_error_ifnet(ifp, | | 974 | aprint_error_ifnet(ifp, |
974 | "initialization failed: no memory for tx buffers\n"); | | 975 | "initialization failed: no memory for tx buffers\n"); |
975 | return ENOBUFS; | | 976 | return ENOBUFS; |
976 | } | | 977 | } |
977 | if (mvgbe_init_rx_ring(sc) == ENOBUFS) { | | 978 | if (mvgbe_init_rx_ring(sc) == ENOBUFS) { |
978 | aprint_error_ifnet(ifp, | | 979 | aprint_error_ifnet(ifp, |
979 | "initialization failed: no memory for rx buffers\n"); | | 980 | "initialization failed: no memory for rx buffers\n"); |
980 | return ENOBUFS; | | 981 | return ENOBUFS; |
981 | } | | 982 | } |
982 | | | 983 | |
983 | MVGBE_WRITE(sc, MVGBE_MTU, 0); /* hw reset value is wrong */ | | 984 | if (csc->sc_flags & FLAGS_FIX_MTU) |
| | | 985 | MVGBE_WRITE(sc, MVGBE_MTU, 0); /* hw reset value is wrong */ |
984 | MVGBE_WRITE(sc, MVGBE_PSC, | | 986 | MVGBE_WRITE(sc, MVGBE_PSC, |
985 | MVGBE_PSC_ANFC | /* Enable Auto-Neg Flow Ctrl */ | | 987 | MVGBE_PSC_ANFC | /* Enable Auto-Neg Flow Ctrl */ |
986 | MVGBE_PSC_RESERVED | /* Must be set to 1 */ | | 988 | MVGBE_PSC_RESERVED | /* Must be set to 1 */ |
987 | MVGBE_PSC_FLFAIL | /* Do NOT Force Link Fail */ | | 989 | MVGBE_PSC_FLFAIL | /* Do NOT Force Link Fail */ |
988 | MVGBE_PSC_MRU(MVGBE_PSC_MRU_9022) | /* we want 9k */ | | 990 | MVGBE_PSC_MRU(MVGBE_PSC_MRU_9022) | /* we want 9k */ |
989 | MVGBE_PSC_SETFULLDX); /* Set_FullDx */ | | 991 | MVGBE_PSC_SETFULLDX); /* Set_FullDx */ |
990 | /* XXXX: mvgbe(4) always use RGMII. */ | | 992 | /* XXXX: mvgbe(4) always use RGMII. */ |
991 | MVGBE_WRITE(sc, MVGBE_PSC1, | | 993 | MVGBE_WRITE(sc, MVGBE_PSC1, |
992 | MVGBE_READ(sc, MVGBE_PSC1) | MVGBE_PSC1_RGMIIEN); | | 994 | MVGBE_READ(sc, MVGBE_PSC1) | MVGBE_PSC1_RGMIIEN); |
993 | /* XXXX: Also always Weighted Round-Robin Priority Mode */ | | 995 | /* XXXX: Also always Weighted Round-Robin Priority Mode */ |
994 | MVGBE_WRITE(sc, MVGBE_TQFPC, MVGBE_TQFPC_EN(0)); | | 996 | MVGBE_WRITE(sc, MVGBE_TQFPC, MVGBE_TQFPC_EN(0)); |
995 | | | 997 | |
996 | MVGBE_WRITE(sc, MVGBE_CRDP(0), MVGBE_RX_RING_ADDR(sc, 0)); | | 998 | MVGBE_WRITE(sc, MVGBE_CRDP(0), MVGBE_RX_RING_ADDR(sc, 0)); |
997 | MVGBE_WRITE(sc, MVGBE_TCQDP, MVGBE_TX_RING_ADDR(sc, 0)); | | 999 | MVGBE_WRITE(sc, MVGBE_TCQDP, MVGBE_TX_RING_ADDR(sc, 0)); |
998 | | | 1000 | |
999 | if (csc->sc_fix_tqtb) { | | 1001 | if (csc->sc_flags & FLAGS_FIX_TQTB) { |
1000 | /* | | 1002 | /* |
1001 | * Queue 0 (offset 0x72700) must be programmed to 0x3fffffff. | | 1003 | * Queue 0 (offset 0x72700) must be programmed to 0x3fffffff. |
1002 | * And offset 0x72704 must be programmed to 0x03ffffff. | | 1004 | * And offset 0x72704 must be programmed to 0x03ffffff. |
1003 | * Queue 1 through 7 must be programmed to 0x0. | | 1005 | * Queue 1 through 7 must be programmed to 0x0. |
1004 | */ | | 1006 | */ |
1005 | MVGBE_WRITE(sc, MVGBE_TQTBCOUNT(0), 0x3fffffff); | | 1007 | MVGBE_WRITE(sc, MVGBE_TQTBCOUNT(0), 0x3fffffff); |
1006 | MVGBE_WRITE(sc, MVGBE_TQTBCONFIG(0), 0x03ffffff); | | 1008 | MVGBE_WRITE(sc, MVGBE_TQTBCONFIG(0), 0x03ffffff); |
1007 | for (i = 1; i < 8; i++) { | | 1009 | for (i = 1; i < 8; i++) { |
1008 | MVGBE_WRITE(sc, MVGBE_TQTBCOUNT(i), 0x0); | | 1010 | MVGBE_WRITE(sc, MVGBE_TQTBCOUNT(i), 0x0); |
1009 | MVGBE_WRITE(sc, MVGBE_TQTBCONFIG(i), 0x0); | | 1011 | MVGBE_WRITE(sc, MVGBE_TQTBCONFIG(i), 0x0); |
1010 | } | | 1012 | } |
1011 | } else | | 1013 | } else |
1012 | for (i = 1; i < 8; i++) { | | 1014 | for (i = 1; i < 8; i++) { |