| @@ -1,1995 +1,1991 @@ | | | @@ -1,1995 +1,1991 @@ |
1 | /* $NetBSD: if_scx.c,v 1.40 2023/05/21 00:35:38 nisimura Exp $ */ | | 1 | /* $NetBSD: if_scx.c,v 1.41 2023/06/13 00:15:52 nisimura Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Tohru Nishimura. | | 8 | * by Tohru Nishimura. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #define NOT_MP_SAFE 0 | | 32 | #define NOT_MP_SAFE 0 |
33 | | | 33 | |
34 | /* | | 34 | /* |
35 | * Socionext SC2A11 SynQuacer NetSec GbE driver | | 35 | * Socionext SC2A11 SynQuacer NetSec GbE driver |
36 | * | | 36 | * |
37 | * Multiple Tx and Rx queues exist inside and dedicated descriptor | | 37 | * Multiple Tx and Rx queues exist inside and dedicated descriptor |
38 | * fields specifies which queue is to use. Three internal micro-processors | | 38 | * fields specifies which queue is to use. Three internal micro-processors |
39 | * to handle incoming frames, outgoing frames and packet data crypto | | 39 | * to handle incoming frames, outgoing frames and packet data crypto |
40 | * processing. uP programs are stored in an external flash memory and | | 40 | * processing. uP programs are stored in an external flash memory and |
41 | * have to be loaded by device driver. | | 41 | * have to be loaded by device driver. |
42 | * NetSec uses Synopsys DesignWare Core EMAC. DWC implementation | | 42 | * NetSec uses Synopsys DesignWare Core EMAC. DWC implementation |
43 | * register (0x20) is known to have 0x10.36 and feature register (0x1058) | | 43 | * register (0x20) is known to have 0x10.36 and feature register (0x1058) |
44 | * reports 0x11056f37. | | 44 | * reports 0x11056f37. |
45 | * <24> alternative/enhanced desc format | | 45 | * <24> alternative/enhanced desc format |
46 | * <18> receive IP type 2 checksum offload | | 46 | * <18> receive IP type 2 checksum offload |
47 | * <16> transmit checksum offload | | 47 | * <16> transmit checksum offload |
48 | * <11> event counter (mac management counter, MMC) | | 48 | * <11> event counter (mac management counter, MMC) |
49 | */ | | 49 | */ |
50 | | | 50 | |
51 | #include <sys/cdefs.h> | | 51 | #include <sys/cdefs.h> |
52 | __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.40 2023/05/21 00:35:38 nisimura Exp $"); | | 52 | __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.41 2023/06/13 00:15:52 nisimura Exp $"); |
53 | | | 53 | |
54 | #include <sys/param.h> | | 54 | #include <sys/param.h> |
55 | #include <sys/bus.h> | | 55 | #include <sys/bus.h> |
56 | #include <sys/intr.h> | | 56 | #include <sys/intr.h> |
57 | #include <sys/device.h> | | 57 | #include <sys/device.h> |
58 | #include <sys/callout.h> | | 58 | #include <sys/callout.h> |
59 | #include <sys/mbuf.h> | | 59 | #include <sys/mbuf.h> |
60 | #include <sys/errno.h> | | 60 | #include <sys/errno.h> |
61 | #include <sys/rndsource.h> | | 61 | #include <sys/rndsource.h> |
62 | #include <sys/kernel.h> | | 62 | #include <sys/kernel.h> |
63 | #include <sys/systm.h> | | 63 | #include <sys/systm.h> |
64 | | | 64 | |
65 | #include <net/if.h> | | 65 | #include <net/if.h> |
66 | #include <net/if_media.h> | | 66 | #include <net/if_media.h> |
67 | #include <net/if_dl.h> | | 67 | #include <net/if_dl.h> |
68 | #include <net/if_ether.h> | | 68 | #include <net/if_ether.h> |
69 | #include <dev/mii/mii.h> | | 69 | #include <dev/mii/mii.h> |
70 | #include <dev/mii/miivar.h> | | 70 | #include <dev/mii/miivar.h> |
71 | #include <net/bpf.h> | | 71 | #include <net/bpf.h> |
72 | | | 72 | |
73 | #include <dev/fdt/fdtvar.h> | | 73 | #include <dev/fdt/fdtvar.h> |
74 | #include <dev/acpi/acpireg.h> | | 74 | #include <dev/acpi/acpireg.h> |
75 | #include <dev/acpi/acpivar.h> | | 75 | #include <dev/acpi/acpivar.h> |
76 | #include <dev/acpi/acpi_intr.h> | | 76 | #include <dev/acpi/acpi_intr.h> |
77 | | | 77 | |
78 | /* SC2A11 GbE 64-bit paddr descriptor */ | | 78 | /* SC2A11 GbE has 64-bit paddr descriptor */ |
79 | struct tdes { | | 79 | struct tdes { |
80 | uint32_t t0, t1, t2, t3; | | 80 | uint32_t t0, t1, t2, t3; |
81 | }; | | 81 | }; |
82 | struct rdes { | | 82 | struct rdes { |
83 | uint32_t r0, r1, r2, r3; | | 83 | uint32_t r0, r1, r2, r3; |
84 | }; | | 84 | }; |
85 | #define T0_OWN (1U<<31) /* desc is ready to Tx */ | | 85 | #define T0_OWN (1U<<31) /* desc is ready to Tx */ |
86 | #define T0_LD (1U<<30) /* last descriptor in array */ | | 86 | #define T0_LD (1U<<30) /* last descriptor in array */ |
87 | #define T0_DRID (24) /* 29:24 desc ring id */ | | 87 | #define T0_DRID (24) /* 29:24 desc ring id */ |
88 | #define T0_PT (1U<<21) /* 23:21 "pass-through" */ | | 88 | #define T0_PT (1U<<21) /* 23:21 "pass-through" */ |
89 | #define T0_TDRID (16) /* 20:16 target desc ring id: GMAC=15 */ | | 89 | #define T0_TDRID (16) /* 20:16 target desc ring id: GMAC=15 */ |
90 | #define T0_CC (1U<<15) /* ??? */ | | 90 | #define T0_CC (1U<<15) /* ??? */ |
91 | #define T0_FS (1U<<9) /* first segment of frame */ | | 91 | #define T0_FS (1U<<9) /* first segment of frame */ |
92 | #define T0_LS (1U<<8) /* last segment of frame */ | | 92 | #define T0_LS (1U<<8) /* last segment of frame */ |
93 | #define T0_CSUM (1U<<7) /* enable check sum offload */ | | 93 | #define T0_CSUM (1U<<7) /* enable check sum offload */ |
94 | #define T0_TSO (1U<<6) /* enable TCP segment offload */ | | 94 | #define T0_TSO (1U<<6) /* enable TCP segment offload */ |
95 | #define T0_TRS (1U<<4) /* 5:4 "TRS" ??? */ | | 95 | #define T0_TRS (1U<<4) /* 5:4 "TRS" ??? */ |
96 | /* T1 frame segment address 63:32 */ | | 96 | /* T1 frame segment address 63:32 */ |
97 | /* T2 frame segment address 31:0 */ | | 97 | /* T2 frame segment address 31:0 */ |
98 | /* T3 31:16 TCP segment length, 15:0 frame segment length to transmit */ | | 98 | /* T3 31:16 TCP segment length, 15:0 frame segment length to transmit */ |
99 | #define R0_OWN (1U<<31) /* desc is empty */ | | 99 | #define R0_OWN (1U<<31) /* desc is empty */ |
100 | #define R0_LD (1U<<30) /* last descriptor in array */ | | 100 | #define R0_LD (1U<<30) /* last descriptor in array */ |
101 | #define R0_SDRID (24) /* 29:24 source desc ring id */ | | 101 | #define R0_SDRID (24) /* 29:24 source desc ring id */ |
102 | #define R0_FR (1U<<23) /* found fragmented */ | | 102 | #define R0_FR (1U<<23) /* found fragmented */ |
103 | #define R0_ER (1U<<21) /* Rx error indication */ | | 103 | #define R0_ER (1U<<21) /* Rx error indication */ |
104 | #define R0_ERR (3U<<16) /* 18:16 receive error code */ | | 104 | #define R0_ERR (3U<<16) /* 18:16 receive error code */ |
105 | #define R0_TDRID (12) /* 15:12 target desc ring id */ | | 105 | #define R0_TDRID (12) /* 15:12 target desc ring id */ |
106 | #define R0_FS (1U<<9) /* first segment of frame */ | | 106 | #define R0_FS (1U<<9) /* first segment of frame */ |
107 | #define R0_LS (1U<<8) /* last segment of frame */ | | 107 | #define R0_LS (1U<<8) /* last segment of frame */ |
108 | #define R0_CSUM (3U<<6) /* 7:6 checksum status */ | | 108 | #define R0_CSUM (3U<<6) /* 7:6 checksum status, 0: undone */ |
109 | #define R0_CERR (2U<<6) /* 0: undone, 1: found ok, 2: bad */ | | 109 | #define R0_CERR (2U<<6) /* 2: found bad */ |
| | | 110 | #define R0_COK (1U<<6) /* 1: found ok */ |
110 | /* R1 frame address 63:32 */ | | 111 | /* R1 frame address 63:32 */ |
111 | /* R2 frame address 31:0 */ | | 112 | /* R2 frame address 31:0 */ |
112 | /* R3 31:16 received frame length, 15:0 buffer length to receive */ | | 113 | /* R3 31:16 received frame length, 15:0 buffer length to receive */ |
113 | | | 114 | |
114 | /* | | 115 | /* |
115 | * SC2A11 registers. 0x100 - 1204 | | 116 | * SC2A11 registers. 0x100 - 1204 |
116 | */ | | 117 | */ |
117 | #define SWRESET 0x104 | | 118 | #define SWRESET 0x104 |
118 | #define SRST_RUN (1U<<31) /* instruct start, 0 to stop */ | | 119 | #define SRST_RUN (1U<<31) /* instruct start, 0 to stop */ |
119 | #define COMINIT 0x120 | | 120 | #define COMINIT 0x120 |
120 | #define INIT_DB (1U<<2) /* ???; self clear when done */ | | 121 | #define INIT_DB (1U<<2) /* ???; self clear when done */ |
121 | #define INIT_CLS (1U<<1) /* ???; self clear when done */ | | 122 | #define INIT_CLS (1U<<1) /* ???; self clear when done */ |
122 | #define PKTCTRL 0x140 /* pkt engine control */ | | 123 | #define PKTCTRL 0x140 /* pkt engine control */ |
123 | #define MODENRM (1U<<28) /* change mode to normal */ | | 124 | #define MODENRM (1U<<28) /* set operational mode to 'normal' */ |
124 | #define ENJUMBO (1U<<27) /* allow jumbo frame */ | | 125 | #define ENJUMBO (1U<<27) /* allow jumbo frame */ |
125 | #define RPTCSUMERR (1U<<3) /* log Rx checksum error */ | | 126 | #define RPTCSUMERR (1U<<3) /* log Rx checksum error */ |
126 | #define RPTHDCOMP (1U<<2) /* log HD incomplete condition */ | | 127 | #define RPTHDCOMP (1U<<2) /* log header incomplete condition */ |
127 | #define RPTHDERR (1U<<1) /* log HD error */ | | 128 | #define RPTHDERR (1U<<1) /* log header error */ |
128 | #define DROPNOMATCH (1U<<0) /* drop no match frames */ | | 129 | #define DROPNOMATCH (1U<<0) /* drop no match frames */ |
129 | #define xINTSR 0x200 /* aggregated interrupt status */ | | 130 | #define xINTSR 0x200 /* aggregated interrupt status */ |
130 | #define IRQ_UCODE (1U<<20) /* ucode load completed; W1C */ | | 131 | #define IRQ_UCODE (1U<<20) /* ucode load completed; W1C */ |
131 | #define IRQ_MAC (1U<<19) /* ??? */ | | 132 | #define IRQ_MAC (1U<<19) /* ??? */ |
132 | #define IRQ_PKT (1U<<18) /* ??? */ | | 133 | #define IRQ_PKT (1U<<18) /* ??? */ |
133 | #define IRQ_BOOTCODE (1U<<5) /* ??? */ | | 134 | #define IRQ_BOOTCODE (1U<<5) /* ??? */ |
134 | #define IRQ_XDONE (1U<<4) /* ??? mode change completed */ | | 135 | #define IRQ_XDONE (1U<<4) /* ??? mode change completed */ |
135 | #define IRQ_RX (1U<<1) /* top level Rx interrupt */ | | 136 | #define IRQ_RX (1U<<1) /* top level Rx interrupt */ |
136 | #define IRQ_TX (1U<<0) /* top level Tx interrupt */ | | 137 | #define IRQ_TX (1U<<0) /* top level Tx interrupt */ |
137 | #define xINTAEN 0x204 /* INT_A enable */ | | 138 | #define xINTAEN 0x204 /* INT_A enable */ |
138 | #define xINTAE_SET 0x234 /* bit to set */ | | 139 | #define xINTAE_SET 0x234 /* bit to set */ |
139 | #define xINTAE_CLR 0x238 /* bit to clr */ | | 140 | #define xINTAE_CLR 0x238 /* bit to clr */ |
140 | #define xINTBEN 0x23c /* INT_B enable */ | | 141 | #define xINTBEN 0x23c /* INT_B enable */ |
141 | #define xINTBE_SET 0x240 /* bit to set */ | | 142 | #define xINTBE_SET 0x240 /* bit to set */ |
142 | #define xINTBE_CLR 0x244 /* bit to clr */ | | 143 | #define xINTBE_CLR 0x244 /* bit to clr */ |
143 | #define TXISR 0x400 /* transmit status; W1C */ | | 144 | #define TXISR 0x400 /* transmit status; W1C */ |
144 | #define TXIEN 0x404 /* tx interrupt enable */ | | 145 | #define TXIEN 0x404 /* tx interrupt enable */ |
145 | #define TXIE_SET 0x428 /* bit to set */ | | 146 | #define TXIE_SET 0x428 /* bit to set */ |
146 | #define TXIE_CLR 0x42c /* bit to clr */ | | 147 | #define TXIE_CLR 0x42c /* bit to clr */ |
147 | #define TXI_NTOWNR (1U<<17) /* ??? desc array got empty */ | | 148 | #define TXI_NTOWNR (1U<<17) /* ??? desc array got empty */ |
148 | #define TXI_TR_ERR (1U<<16) /* tx error */ | | 149 | #define TXI_TR_ERR (1U<<16) /* xmit error */ |
149 | #define TXI_TXDONE (1U<<15) /* tx completed */ | | 150 | #define TXI_TXDONE (1U<<15) /* xmit completed */ |
150 | #define TXI_TMREXP (1U<<14) /* coalesce timer expired */ | | 151 | #define TXI_TMREXP (1U<<14) /* coalesce guard timer expired */ |
151 | #define RXISR 0x440 /* receive status; W1C */ | | 152 | #define RXISR 0x440 /* receive status; W1C */ |
152 | #define RXIEN 0x444 /* rx interrupt enable */ | | 153 | #define RXIEN 0x444 /* rx interrupt enable */ |
153 | #define RXIE_SET 0x468 /* bit to set */ | | 154 | #define RXIE_SET 0x468 /* bit to set */ |
154 | #define RXIE_CLR 0x46c /* bit to clr */ | | 155 | #define RXIE_CLR 0x46c /* bit to clr */ |
155 | #define RXI_RC_ERR (1U<<16) /* rx error */ | | 156 | #define RXI_RC_ERR (1U<<16) /* recv error */ |
156 | #define RXI_PKTCNT (1U<<15) /* rx counter has new value */ | | 157 | #define RXI_PKTCNT (1U<<15) /* recv counter has new value */ |
157 | #define RXI_TMREXP (1U<<14) /* coalesce timer expired */ | | 158 | #define RXI_TMREXP (1U<<14) /* coalesce guard timer expired */ |
158 | /* 13 sets of special purpose desc interrupt handling register exist */ | | 159 | /* 13 sets of special purpose desc interrupt handling register exist */ |
159 | #define TDBA_LO 0x408 /* tdes array base addr 31:0 */ | | 160 | #define TDBA_LO 0x408 /* tdes array base addr 31:0 */ |
160 | #define TDBA_HI 0x434 /* tdes array base addr 63:32 */ | | 161 | #define TDBA_HI 0x434 /* tdes array base addr 63:32 */ |
161 | #define RDBA_LO 0x448 /* rdes array base addr 31:0 */ | | 162 | #define RDBA_LO 0x448 /* rdes array base addr 31:0 */ |
162 | #define RDBA_HI 0x474 /* rdes array base addr 63:32 */ | | 163 | #define RDBA_HI 0x474 /* rdes array base addr 63:32 */ |
163 | /* 13 pairs of special purpose desc array base address register exist */ | | 164 | /* 13 pairs of special purpose desc array base address register exist */ |
164 | #define TXCONF 0x430 | | 165 | #define TXCONF 0x430 |
165 | #define RXCONF 0x470 | | 166 | #define RXCONF 0x470 |
166 | #define DESCNF_UP (1U<<31) /* up-and-running */ | | 167 | #define DESCNF_UP (1U<<31) /* 'up-and-running' */ |
167 | #define DESCNF_CHRST (1U<<30) /* channel reset */ | | 168 | #define DESCNF_CHRST (1U<<30) /* channel reset */ |
168 | #define DESCNF_TMR (1U<<4) /* coalesce timer mode select */ | | 169 | #define DESCNF_TMR (1U<<4) /* coalesce timer mode select */ |
169 | #define DESCNF_LE (1) /* little endian desc format */ | | 170 | #define DESCNF_LE (1) /* little endian desc format */ |
170 | #define TXSUBMIT 0x410 /* submit frame(s) to transmit */ | | 171 | #define TXSUBMIT 0x410 /* submit frame(s) to transmit */ |
171 | #define TXCLSCMAX 0x418 /* tx intr coalesce upper bound */ | | 172 | #define TXCOALESC 0x418 /* tx intr coalesce upper bound */ |
172 | #define RXCLSCMAX 0x458 /* rx intr coalesce upper bound */ | | 173 | #define RXCOALESC 0x458 /* rx intr coalesce upper bound */ |
173 | #define TXITIMER 0x420 /* coalesce timer usec, MSB to use */ | | 174 | #define TCLSCTIME 0x420 /* tintr guard time usec, MSB to on */ |
174 | #define RXITIMER 0x460 /* coalesce timer usec, MSB to use */ | | 175 | #define RCLSCTIME 0x460 /* rintr guard time usec, MSB to on */ |
175 | #define TXDONECNT 0x414 /* tx completed count, auto-zero */ | | 176 | #define TXDONECNT 0x414 /* tx completed count, auto-zero */ |
176 | #define RXDONECNT 0x454 /* rx available count, auto-zero */ | | 177 | #define RXAVAILCNT 0x454 /* rx available count, auto-zero */ |
177 | #define DMACTL_TMR 0x20c /* engine DMA timer value */ | | 178 | #define DMACTL_TMR 0x20c /* engine DMA timer value */ |
178 | #define UCODE_H2M 0x210 /* host2media engine ucode port */ | | 179 | #define UCODE_H2M 0x210 /* host2media engine ucode port */ |
179 | #define UCODE_M2H 0x21c /* media2host engine ucode port */ | | 180 | #define UCODE_M2H 0x21c /* media2host engine ucode port */ |
180 | #define CORESTAT 0x218 /* engine run state */ | | 181 | #define CORESTAT 0x218 /* engine run state */ |
181 | #define PKTSTOP (1U<<2) | | 182 | #define PKTSTOP (1U<<2) /* pkt engine stopped */ |
182 | #define M2HSTOP (1U<<1) | | 183 | #define M2HSTOP (1U<<1) /* M2H engine stopped */ |
183 | #define H2MSTOP (1U<<0) | | 184 | #define H2MSTOP (1U<<0) /* H2M engine stopped */ |
184 | #define DMACTL_H2M 0x214 /* host2media engine control */ | | 185 | #define DMACTL_H2M 0x214 /* host2media engine control */ |
185 | #define DMACTL_M2H 0x220 /* media2host engine control */ | | 186 | #define DMACTL_M2H 0x220 /* media2host engine control */ |
186 | #define DMACTL_STOP (1U<<0) /* instruct stop; self-clear */ | | 187 | #define DMACTL_STOP (1U<<0) /* instruct stop; self-clear */ |
| | | 188 | #define M2H_MODE_TRANS (1U<<20) /* initiate M2H mode change */ |
187 | #define UCODE_PKT 0x0d0 /* packet engine ucode port */ | | 189 | #define UCODE_PKT 0x0d0 /* packet engine ucode port */ |
188 | #define CLKEN 0x100 /* clock distribution enable */ | | 190 | #define CLKEN 0x100 /* clock distribution enable */ |
189 | #define CLK_G (1U<<5) /* feed clk domain E */ | | 191 | #define CLK_G (1U<<5) /* feed clk domain G */ |
190 | #define CLK_C (1U<<1) /* feed clk domain C */ | | 192 | #define CLK_C (1U<<1) /* feed clk domain C */ |
191 | #define CLK_D (1U<<0) /* feed clk domain D */ | | 193 | #define CLK_D (1U<<0) /* feed clk domain D */ |
192 | #define CLK_ALL 0x23 /* all above; 0x24 ??? 0x3f ??? */ | | | |
193 | | | 194 | |
194 | /* GMAC register indirect access. thru MACCMD/MACDATA operation */ | | 195 | /* GMAC register indirect access. thru MACCMD/MACDATA operation */ |
195 | #define MACDATA 0x11c0 /* gmac register rd/wr data */ | | 196 | #define MACDATA 0x11c0 /* gmac register rd/wr data */ |
196 | #define MACCMD 0x11c4 /* gmac register operation */ | | 197 | #define MACCMD 0x11c4 /* gmac register operation */ |
197 | #define CMD_IOWR (1U<<28) /* write op */ | | 198 | #define CMD_IOWR (1U<<28) /* write op */ |
198 | #define CMD_BUSY (1U<<31) /* busy bit */ | | 199 | #define CMD_BUSY (1U<<31) /* busy bit */ |
199 | #define MACSTAT 0x1024 /* gmac status; ??? */ | | 200 | #define MACSTAT 0x1024 /* gmac status; ??? */ |
200 | #define MACINTE 0x1028 /* interrupt enable; ??? */ | | 201 | #define MACINTE 0x1028 /* interrupt enable; ??? */ |
201 | | | 202 | |
202 | #define FLOWTHR 0x11cc /* flow control threshold */ | | 203 | #define FLOWTHR 0x11cc /* flow control threshold */ |
203 | /* 31:16 pause threshold, 15:0 resume threshold */ | | 204 | /* 31:16 pause threshold, 15:0 resume threshold */ |
204 | #define INTF_SEL 0x11d4 /* ??? */ | | 205 | #define INTF_SEL 0x11d4 /* phy interface type */ |
| | | 206 | #define INTF_GMII 0 |
| | | 207 | #define INTF_RGMII 1 |
| | | 208 | #define INTF_RMII 4 |
205 | | | 209 | |
206 | #define DESC_INIT 0x11fc /* write 1 for desc init, SC */ | | 210 | #define DESC_INIT 0x11fc /* write 1 for desc init, SC */ |
207 | #define DESC_SRST 0x1204 /* write 1 for desc sw reset, SC */ | | 211 | #define DESC_SRST 0x1204 /* write 1 for desc sw reset, SC */ |
208 | #define MODE_TRANS 0x500 /* mode change completion status */ | | 212 | #define MODE_TRANS 0x500 /* mode change completion status */ |
209 | #define N2T_DONE (1U<<20) /* normal->taiki change completed */ | | 213 | #define N2T_DONE (1U<<20) /* normal->taiki change completed */ |
210 | #define T2N_DONE (1U<<19) /* taiki->normal change completed */ | | 214 | #define T2N_DONE (1U<<19) /* taiki->normal change completed */ |
211 | #define MACADRH 0x10c /* ??? */ | | 215 | #define MACADRH 0x10c /* ??? */ |
212 | #define MACADRL 0x110 /* ??? */ | | 216 | #define MACADRL 0x110 /* ??? */ |
213 | #define MCVER 0x22c /* micro controller version */ | | 217 | #define MCVER 0x22c /* micro controller version */ |
214 | #define HWVER 0x230 /* hardware version */ | | 218 | #define HWVER 0x230 /* hardware version */ |
215 | | | 219 | |
216 | /* | | 220 | /* |
217 | * GMAC registers are mostly identical to Synopsys DesignWare Core | | 221 | * GMAC registers are mostly identical to Synopsys DesignWare Core |
218 | * Ethernet. These must be handled by indirect access. | | 222 | * Ethernet. These must be handled by indirect access. |
219 | */ | | 223 | */ |
220 | #define GMACMCR 0x0000 /* MAC configuration */ | | 224 | #define GMACMCR 0x0000 /* MAC configuration */ |
221 | #define MCR_IBN (1U<<30) /* ??? */ | | 225 | #define MCR_IBN (1U<<30) /* watch in-band-signal */ |
222 | #define MCR_CST (1U<<25) /* strip CRC */ | | 226 | #define MCR_CST (1U<<25) /* strip CRC */ |
223 | #define MCR_TC (1U<<24) /* keep RGMII PHY notified */ | | 227 | #define MCR_TC (1U<<24) /* keep RGMII PHY notified */ |
224 | #define MCR_WD (1U<<23) /* allow long >2048 tx frame */ | | 228 | #define MCR_WD (1U<<23) /* allow long >2048 tx frame */ |
225 | #define MCR_JE (1U<<20) /* allow ~9018 tx jumbo frame */ | | 229 | #define MCR_JE (1U<<20) /* allow ~9018 tx jumbo frame */ |
226 | #define MCR_IFG (7U<<17) /* 19:17 IFG value 0~7 */ | | 230 | #define MCR_IFG (7U<<17) /* 19:17 IFG value 0~7 */ |
227 | #define MCR_DCRS (1U<<16) /* ignore (G)MII HDX Tx error */ | | 231 | #define MCR_DCRS (1U<<16) /* ignore (G)MII HDX Tx error */ |
228 | #define MCR_PS (1U<<15) /* 1: MII 10/100, 0: GMII 1000 */ | | 232 | #define MCR_PS (1U<<15) /* 1: MII 10/100, 0: GMII 1000 */ |
229 | #define MCR_FES (1U<<14) /* force speed 100 */ | | 233 | #define MCR_FES (1U<<14) /* force speed 100 */ |
230 | #define MCR_DO (1U<<13) /* don't receive my own HDX Tx frames */ | | 234 | #define MCR_DO (1U<<13) /* don't receive my own HDX Tx frames */ |
231 | #define MCR_LOOP (1U<<12) /* run loop back */ | | 235 | #define MCR_LOOP (1U<<12) /* run loop back */ |
232 | #define MCR_USEFDX (1U<<11) /* force full duplex */ | | 236 | #define MCR_USEFDX (1U<<11) /* force full duplex */ |
233 | #define MCR_IPCEN (1U<<10) /* handle checksum */ | | 237 | #define MCR_IPCEN (1U<<10) /* handle checksum */ |
234 | #define MCR_DR (1U<<9) /* attempt no tx retry, send once */ | | 238 | #define MCR_DR (1U<<9) /* attempt no tx retry, send once */ |
235 | #define MCR_LUD (1U<<8) /* link condition report when RGMII */ | | 239 | #define MCR_LUD (1U<<8) /* link condition report when RGMII */ |
236 | #define MCR_ACS (1U<<7) /* auto pad strip CRC */ | | 240 | #define MCR_ACS (1U<<7) /* auto pad auto strip CRC */ |
237 | #define MCR_DC (1U<<4) /* report excessive tx deferral */ | | 241 | #define MCR_DC (1U<<4) /* report excessive tx deferral */ |
238 | #define MCR_TE (1U<<3) /* run Tx MAC engine, 0 to stop */ | | 242 | #define MCR_TE (1U<<3) /* run Tx MAC engine, 0 to stop */ |
239 | #define MCR_RE (1U<<2) /* run Rx MAC engine, 0 to stop */ | | 243 | #define MCR_RE (1U<<2) /* run Rx MAC engine, 0 to stop */ |
240 | #define MCR_PREA (3U) /* 1:0 preamble len. 0~2 */ | | 244 | #define MCR_PREA (3U) /* 1:0 preamble len. 0~2 */ |
241 | #define GMACAFR 0x0004 /* frame DA/SA address filter */ | | 245 | #define GMACAFR 0x0004 /* frame DA/SA address filter */ |
242 | #define AFR_RA (1U<<31) /* accept all irrespective of filt. */ | | 246 | #define AFR_RA (1U<<31) /* accept all irrespective of filt. */ |
243 | #define AFR_HPF (1U<<10) /* hash+perfect filter, or hash only */ | | 247 | #define AFR_HPF (1U<<10) /* hash+perfect filter, or hash only */ |
244 | #define AFR_SAF (1U<<9) /* source address filter */ | | 248 | #define AFR_SAF (1U<<9) /* source address filter */ |
245 | #define AFR_SAIF (1U<<8) /* SA inverse filtering */ | | 249 | #define AFR_SAIF (1U<<8) /* SA inverse filtering */ |
246 | #define AFR_PCF (2U<<6) /* ??? */ | | 250 | #define AFR_PCF (2U<<6) /* ??? */ |
247 | #define AFR_DBF (1U<<5) /* reject broadcast frame */ | | 251 | #define AFR_DBF (1U<<5) /* reject broadcast frame */ |
248 | #define AFR_PM (1U<<4) /* accept all multicast frame */ | | 252 | #define AFR_PM (1U<<4) /* accept all multicast frame */ |
249 | #define AFR_DAIF (1U<<3) /* DA inverse filtering */ | | 253 | #define AFR_DAIF (1U<<3) /* DA inverse filtering */ |
250 | #define AFR_MHTE (1U<<2) /* use multicast hash table */ | | 254 | #define AFR_MHTE (1U<<2) /* use multicast hash table */ |
251 | #define AFR_UHTE (1U<<1) /* use hash table for unicast */ | | 255 | #define AFR_UHTE (1U<<1) /* use hash table for unicast */ |
252 | #define AFR_PR (1U<<0) /* run promisc mode */ | | 256 | #define AFR_PR (1U<<0) /* run promisc mode */ |
253 | #define GMACGAR 0x0010 /* MDIO operation */ | | 257 | #define GMACGAR 0x0010 /* MDIO operation */ |
254 | #define GAR_PHY (11) /* 15:11 mii phy */ | | 258 | #define GAR_PHY (11) /* 15:11 mii phy */ |
255 | #define GAR_REG (6) /* 10:6 mii reg */ | | 259 | #define GAR_REG (6) /* 10:6 mii reg */ |
256 | #define GAR_CLK (2) /* 5:2 mdio clock tick ratio */ | | 260 | #define GAR_CLK (2) /* 5:2 mdio clock tick ratio */ |
257 | #define GAR_IOWR (1U<<1) /* MDIO write op */ | | 261 | #define GAR_IOWR (1U<<1) /* MDIO write op */ |
258 | #define GAR_BUSY (1U<<0) /* busy bit */ | | 262 | #define GAR_BUSY (1U<<0) /* busy bit */ |
259 | #define GAR_MDIO_25_35MHZ 2 | | 263 | #define GAR_MDIO_25_35MHZ 2 |
260 | #define GAR_MDIO_35_60MHZ 3 | | 264 | #define GAR_MDIO_35_60MHZ 3 |
261 | #define GAR_MDIO_60_100MHZ 0 | | 265 | #define GAR_MDIO_60_100MHZ 0 |
262 | #define GAR_MDIO_100_150MHZ 1 | | 266 | #define GAR_MDIO_100_150MHZ 1 |
263 | #define GAR_MDIO_150_250MHZ 4 | | 267 | #define GAR_MDIO_150_250MHZ 4 |
264 | #define GAR_MDIO_250_300MHZ 5 | | 268 | #define GAR_MDIO_250_300MHZ 5 |
265 | #define GMACGDR 0x0014 /* MDIO rd/wr data */ | | 269 | #define GMACGDR 0x0014 /* MDIO rd/wr data */ |
266 | #define GMACFCR 0x0018 /* 802.3x flowcontrol */ | | 270 | #define GMACFCR 0x0018 /* 802.3x flowcontrol */ |
267 | /* 31:16 pause timer value, 5:4 pause timer threshold */ | | 271 | /* 31:16 pause timer value, 5:4 pause timer threshold */ |
268 | #define FCR_RFE (1U<<2) /* accept PAUSE to throttle Tx */ | | 272 | #define FCR_RFE (1U<<2) /* accept PAUSE to throttle Tx */ |
269 | #define FCR_TFE (1U<<1) /* generate PAUSE to moderate Rx lvl */ | | 273 | #define FCR_TFE (1U<<1) /* generate PAUSE to moderate Rx lvl */ |
270 | #define GMACIMPL 0x0020 /* implementation id */ | | 274 | #define GMACIMPL 0x0020 /* implementation id */ |
271 | #define GMACISR 0x0038 /* interrupt status indication */ | | 275 | #define GMACISR 0x0038 /* interrupt status indication */ |
272 | #define GMACIMR 0x003c /* interrupt mask to inhibit */ | | 276 | #define GMACIMR 0x003c /* interrupt mask to inhibit */ |
273 | #define ISR_TS (1U<<9) /* time stamp operation detected */ | | 277 | #define ISR_TS (1U<<9) /* time stamp operation detected */ |
274 | #define ISR_CO (1U<<7) /* Rx checksum offload completed */ | | 278 | #define ISR_CO (1U<<7) /* Rx checksum offload completed */ |
275 | #define ISR_TX (1U<<6) /* Tx completed */ | | 279 | #define ISR_TX (1U<<6) /* Tx completed */ |
276 | #define ISR_RX (1U<<5) /* Rx completed */ | | 280 | #define ISR_RX (1U<<5) /* Rx completed */ |
277 | #define ISR_ANY (1U<<4) /* any of above 5-7 report */ | | 281 | #define ISR_ANY (1U<<4) /* any of above 5-7 report */ |
278 | #define ISR_LC (1U<<0) /* link status change detected */ | | 282 | #define ISR_LC (1U<<0) /* link status change detected */ |
279 | #define GMACMAH0 0x0040 /* my own MAC address 47:32 */ | | 283 | #define GMACMAH0 0x0040 /* my own MAC address 47:32 */ |
280 | #define GMACMAL0 0x0044 /* my own MAC address 31:0 */ | | 284 | #define GMACMAL0 0x0044 /* my own MAC address 31:0 */ |
281 | #define GMACMAH(i) ((i)*8+0x40) /* supplemental MAC addr 1-15 */ | | 285 | #define GMACMAH(i) ((i)*8+0x40) /* supplemental MAC addr 1-15 */ |
282 | #define GMACMAL(i) ((i)*8+0x44) /* 31:0 MAC address low part */ | | 286 | #define GMACMAL(i) ((i)*8+0x44) /* 31:0 MAC address low part */ |
283 | /* MAH bit-31: slot in use, 30: SA to match, 29:24 byte-wise don'care */ | | 287 | /* MAH bit-31: slot in use, 30: SA to match, 29:24 byte-wise don'care */ |
284 | #define GMACAMAH(i) ((i)*8+0x800) /* supplemental MAC addr 16-31 */ | | 288 | #define GMACAMAH(i) ((i)*8+0x800) /* supplemental MAC addr 16-31 */ |
285 | #define GMACAMAL(i) ((i)*8+0x804) /* 31: MAC address low part */ | | 289 | #define GMACAMAL(i) ((i)*8+0x804) /* 31: MAC address low part */ |
286 | /* supplimental MAH bit-31: slot in use, no other bit is effective */ | | 290 | /* supplimental MAH bit-31: slot in use, no other bit is effective */ |
287 | #define GMACMHTH 0x0008 /* 64bit multicast hash table 63:32 */ | | 291 | #define GMACMHTH 0x0008 /* 64bit multicast hash table 63:32 */ |
288 | #define GMACMHTL 0x000c /* 64bit multicast hash table 31:0 */ | | 292 | #define GMACMHTL 0x000c /* 64bit multicast hash table 31:0 */ |
289 | #define GMACMHT(i) ((i)*4+0x500) /* 256-bit alternative mcast hash 0-7 */ | | 293 | #define GMACMHT(i) ((i)*4+0x500) /* 256-bit alternative mcast hash 0-7 */ |
290 | #define GMACVTAG 0x001c /* VLAN tag control */ | | 294 | #define GMACVTAG 0x001c /* VLAN tag control */ |
291 | #define VTAG_HASH (1U<<19) /* use VLAN tag hash table */ | | 295 | #define VTAG_HASH (1U<<19) /* use VLAN tag hash table */ |
292 | #define VTAG_SVLAN (1U<<18) /* handle type 0x88A8 SVLAN frame */ | | 296 | #define VTAG_SVLAN (1U<<18) /* handle type 0x88A8 SVLAN frame */ |
293 | #define VTAG_INV (1U<<17) /* run inverse match logic */ | | 297 | #define VTAG_INV (1U<<17) /* run inverse match logic */ |
294 | #define VTAG_ETV (1U<<16) /* use only 12bit VID field to match */ | | 298 | #define VTAG_ETV (1U<<16) /* use only 12bit VID field to match */ |
295 | /* 15:0 concat of PRIO+CFI+VID */ | | 299 | /* 15:0 concat of PRIO+CFI+VID */ |
296 | #define GMACVHT 0x0588 /* 16-bit VLAN tag hash */ | | 300 | #define GMACVHT 0x0588 /* 16-bit VLAN tag hash */ |
297 | #define GMACMIISR 0x00d8 /* resolved RGMII/SGMII link status */ | | 301 | #define GMACMIISR 0x00d8 /* resolved RGMII/SGMII link status */ |
298 | #define MIISR_LUP (1U<<3) /* link up(1)/down(0) report */ | | 302 | #define MIISR_LUP (1U<<3) /* link up(1)/down(0) report */ |
299 | #define MIISR_SPD (3U<<1) /* 2:1 speed 10(0)/100(1)/1000(2) */ | | 303 | #define MIISR_SPD (3U<<1) /* 2:1 speed 10(0)/100(1)/1000(2) */ |
300 | #define MIISR_FDX (1U<<0) /* fdx detected */ | | 304 | #define MIISR_FDX (1U<<0) /* fdx detected */ |
301 | | | 305 | |
302 | #define GMACLPIS 0x0030 /* LPI control & status */ | | 306 | #define GMACLPIS 0x0030 /* LPI control & status */ |
303 | #define LPIS_TXA (1U<<19) /* complete Tx in progress and LPI */ | | 307 | #define LPIS_TXA (1U<<19) /* complete Tx in progress and LPI */ |
304 | #define LPIS_PLS (1U<<17) | | 308 | #define LPIS_PLS (1U<<17) |
305 | #define LPIS_EN (1U<<16) /* 1: enter LPI mode, 0: exit */ | | 309 | #define LPIS_EN (1U<<16) /* 1: enter LPI mode, 0: exit */ |
306 | #define LPIS_TEN (1U<<0) /* Tx LPI report */ | | 310 | #define LPIS_TEN (1U<<0) /* Tx LPI report */ |
307 | #define GMACLPIC 0x0034 /* LPI timer control */ | | 311 | #define GMACLPIC 0x0034 /* LPI timer control */ |
308 | #define LPIC_LST (5) /* 16:5 ??? */ | | 312 | #define LPIC_LST (5) /* 16:5 ??? */ |
309 | #define LPIC_TWT (0) /* 15:0 ??? */ | | 313 | #define LPIC_TWT (0) /* 15:0 ??? */ |
310 | /* 0x700-764 Time Stamp control */ | | 314 | /* 0x700-764 Time Stamp control */ |
311 | | | 315 | |
312 | #define GMACBMR 0x1000 /* DMA bus mode control */ | | 316 | #define GMACBMR 0x1000 /* DMA bus mode control */ |
313 | /* 24 8xPBL multiply by 8 for RPBL & PBL values | | 317 | /* 24 8xPBL multiply by 8 for RPBL & PBL values |
314 | * 23 USP 1 to use RPBL for Rx DMA burst, 0 to share PBL by Rx and Tx | | 318 | * 23 USP 1 to use RPBL for Rx DMA burst, 0 to share PBL by Rx and Tx |
315 | * 22:17 RPBL | | 319 | * 22:17 RPBL |
316 | * 16 FB fixed burst | | 320 | * 16 FB fixed burst |
317 | * 15:14 priority between Rx and Tx | | 321 | * 15:14 priority between Rx and Tx |
318 | * 3 rxtx ratio 41 | | 322 | * 3 rxtx ratio 41 |
319 | * 2 rxtx ratio 31 | | 323 | * 2 rxtx ratio 31 |
320 | * 1 rxtx ratio 21 | | 324 | * 1 rxtx ratio 21 |
321 | * 0 rxtx ratio 11 | | 325 | * 0 rxtx ratio 11 |
322 | * 13:8 PBL possible DMA burst length | | 326 | * 13:8 PBL possible DMA burst length |
323 | * 7 ATDS select 32-byte descriptor format for advanced features | | 327 | * 7 ATDS select 32-byte descriptor format for advanced features |
324 | * 6:2 DSL descriptor skip length, 0 for adjuscent, counted on bus width | | 328 | * 6:2 DSL descriptor skip length, 0 for adjuscent, counted on bus width |
325 | * 0 MAC reset op. self-clear | | 329 | * 0 MAC reset op. self-clear |
326 | */ | | 330 | */ |
327 | #define BMR_RST (1) /* reset op. self clear when done */ | | 331 | #define BMR_RST (1) /* reset op. self clear when done */ |
328 | #define GMACTPD 0x1004 /* write any to resume tdes */ | | 332 | #define GMACTPD 0x1004 /* write any to resume tdes */ |
329 | #define GMACRPD 0x1008 /* write any to resume rdes */ | | 333 | #define GMACRPD 0x1008 /* write any to resume rdes */ |
330 | #define GMACRDLA 0x100c /* rdes base address 32bit paddr */ | | 334 | #define GMACRDLA 0x100c /* rdes base address 32bit paddr */ |
331 | #define GMACTDLA 0x1010 /* tdes base address 32bit paddr */ | | 335 | #define GMACTDLA 0x1010 /* tdes base address 32bit paddr */ |
332 | #define GMACDSR 0x1014 /* DMA status detail report; W1C */ | | 336 | #define GMACDSR 0x1014 /* DMA status detail report; W1C */ |
333 | #define GMACDIE 0x101c /* DMA interrupt enable */ | | 337 | #define GMACDIE 0x101c /* DMA interrupt enable */ |
334 | #define DMAI_LPI (1U<<30) /* LPI interrupt */ | | 338 | #define DMAI_LPI (1U<<30) /* LPI interrupt */ |
335 | #define DMAI_TTI (1U<<29) /* timestamp trigger interrupt */ | | 339 | #define DMAI_TTI (1U<<29) /* timestamp trigger interrupt */ |
336 | #define DMAI_GMI (1U<<27) /* management counter interrupt */ | | 340 | #define DMAI_GMI (1U<<27) /* management counter interrupt */ |
337 | #define DMAI_GLI (1U<<26) /* xMII link change detected */ | | 341 | #define DMAI_GLI (1U<<26) /* xMII link change detected */ |
338 | #define DMAI_EB (23) /* 25:23 DMA bus error detected */ | | 342 | #define DMAI_EB (23) /* 25:23 DMA bus error detected */ |
339 | #define DMAI_TS (20) /* 22:20 Tx DMA state report */ | | 343 | #define DMAI_TS (20) /* 22:20 Tx DMA state report */ |
340 | #define DMAI_RS (17) /* 29:17 Rx DMA state report */ | | 344 | #define DMAI_RS (17) /* 29:17 Rx DMA state report */ |
341 | #define DMAI_NIS (1U<<16) /* normal interrupt summary; W1C */ | | 345 | #define DMAI_NIS (1U<<16) /* normal interrupt summary; W1C */ |
342 | #define DMAI_AIS (1U<<15) /* abnormal interrupt summary; W1C */ | | 346 | #define DMAI_AIS (1U<<15) /* abnormal interrupt summary; W1C */ |
343 | #define DMAI_ERI (1U<<14) /* the first Rx buffer is filled */ | | 347 | #define DMAI_ERI (1U<<14) /* the first Rx buffer is filled */ |
344 | #define DMAI_FBI (1U<<13) /* DMA bus error detected */ | | 348 | #define DMAI_FBI (1U<<13) /* DMA bus error detected */ |
345 | #define DMAI_ETI (1U<<10) /* single frame Tx completed */ | | 349 | #define DMAI_ETI (1U<<10) /* single frame Tx completed */ |
346 | #define DMAI_RWT (1U<<9) /* longer than 2048 frame received */ | | 350 | #define DMAI_RWT (1U<<9) /* longer than 2048 frame received */ |
347 | #define DMAI_RPS (1U<<8) /* Rx process is now stopped */ | | 351 | #define DMAI_RPS (1U<<8) /* Rx process is now stopped */ |
348 | #define DMAI_RU (1U<<7) /* Rx descriptor not available */ | | 352 | #define DMAI_RU (1U<<7) /* Rx descriptor not available */ |
349 | #define DMAI_RI (1U<<6) /* frame Rx completed by !R1_DIC */ | | 353 | #define DMAI_RI (1U<<6) /* frame Rx completed by !R1_DIC */ |
350 | #define DMAI_UNF (1U<<5) /* Tx underflow detected */ | | 354 | #define DMAI_UNF (1U<<5) /* Tx underflow detected */ |
351 | #define DMAI_OVF (1U<<4) /* receive buffer overflow detected */ | | 355 | #define DMAI_OVF (1U<<4) /* receive buffer overflow detected */ |
352 | #define DMAI_TJT (1U<<3) /* longer than 2048 frame sent */ | | 356 | #define DMAI_TJT (1U<<3) /* longer than 2048 frame sent */ |
353 | #define DMAI_TU (1U<<2) /* Tx descriptor not available */ | | 357 | #define DMAI_TU (1U<<2) /* Tx descriptor not available */ |
354 | #define DMAI_TPS (1U<<1) /* transmission is stopped */ | | 358 | #define DMAI_TPS (1U<<1) /* transmission is stopped */ |
355 | #define DMAI_TI (1U<<0) /* frame Tx completed by T0_IC */ | | 359 | #define DMAI_TI (1U<<0) /* frame Tx completed by T0_IC */ |
356 | #define GMACOMR 0x1018 /* DMA operation mode */ | | 360 | #define GMACOMR 0x1018 /* DMA operation mode */ |
357 | #define OMR_RSF (1U<<25) /* 1: Rx store&forward, 0: immed. */ | | 361 | #define OMR_RSF (1U<<25) /* 1: Rx store&forward, 0: immed. */ |
358 | #define OMR_TSF (1U<<21) /* 1: Tx store&forward, 0: immed. */ | | 362 | #define OMR_TSF (1U<<21) /* 1: Tx store&forward, 0: immed. */ |
359 | #define OMR_TTC (14) /* 16:14 Tx threshold */ | | 363 | #define OMR_TTC (14) /* 16:14 Tx threshold */ |
360 | #define OMR_ST (1U<<13) /* run Tx DMA engine, 0 to stop */ | | 364 | #define OMR_ST (1U<<13) /* run Tx DMA engine, 0 to stop */ |
361 | #define OMR_RFD (11) /* 12:11 Rx FIFO fill level */ | | 365 | #define OMR_RFD (11) /* 12:11 Rx FIFO fill level */ |
362 | #define OMR_EFC (1U<<8) /* transmit PAUSE to throttle Rx lvl. */ | | 366 | #define OMR_EFC (1U<<8) /* transmit PAUSE to throttle Rx lvl. */ |
363 | #define OMR_FEF (1U<<7) /* allow to receive error frames */ | | 367 | #define OMR_FEF (1U<<7) /* allow to receive error frames */ |
364 | #define OMR_SR (1U<<1) /* run Rx DMA engine, 0 to stop */ | | 368 | #define OMR_SR (1U<<1) /* run Rx DMA engine, 0 to stop */ |
365 | #define GMACEVCS 0x1020 /* missed frame or ovf detected */ | | 369 | #define GMACEVCS 0x1020 /* missed frame or ovf detected */ |
366 | #define GMACRWDT 0x1024 /* enable rx watchdog timer interrupt */ | | 370 | #define GMACRWDT 0x1024 /* enable rx watchdog timer interrupt */ |
367 | #define GMACAXIB 0x1028 /* AXI bus mode control */ | | 371 | #define GMACAXIB 0x1028 /* AXI bus mode control */ |
368 | #define GMACAXIS 0x102c /* AXI status report */ | | 372 | #define GMACAXIS 0x102c /* AXI status report */ |
369 | /* 0x1048 current tx desc address */ | | 373 | /* 0x1048 current tx desc address */ |
370 | /* 0x104c current rx desc address */ | | 374 | /* 0x104c current rx desc address */ |
371 | /* 0x1050 current tx buffer address */ | | 375 | /* 0x1050 current tx buffer address */ |
372 | /* 0x1054 current rx buffer address */ | | 376 | /* 0x1054 current rx buffer address */ |
373 | #define HWFEA 0x1058 /* DWC feature report */ | | 377 | #define HWFEA 0x1058 /* DWC feature report */ |
374 | #define FEA_EXDESC (1U<<24) /* alternative/enhanced desc layout */ | | 378 | #define FEA_EXDESC (1U<<24) /* alternative/enhanced desc layout */ |
375 | #define FEA_2COE (1U<<18) /* Rx type 2 IP checksum offload */ | | 379 | #define FEA_2COE (1U<<18) /* Rx type 2 IP checksum offload */ |
376 | #define FEA_1COE (1U<<17) /* Rx type 1 IP checksum offload */ | | 380 | #define FEA_1COE (1U<<17) /* Rx type 1 IP checksum offload */ |
377 | #define FEA_TXOE (1U<<16) /* Tx checksum offload */ | | 381 | #define FEA_TXOE (1U<<16) /* Tx checksum offload */ |
378 | #define FEA_MMC (1U<<11) /* RMON event counter */ | | 382 | #define FEA_MMC (1U<<11) /* RMON event counter */ |
379 | | | 383 | |
380 | #define GMACEVCTL 0x0100 /* event counter control */ | | 384 | #define GMACEVCTL 0x0100 /* event counter control */ |
381 | #define EVC_FHP (1U<<5) /* full-half preset */ | | 385 | #define EVC_FHP (1U<<5) /* full-half preset */ |
382 | #define EVC_CP (1U<<4) /* counter preset */ | | 386 | #define EVC_CP (1U<<4) /* counter preset */ |
383 | #define EVC_MCF (1U<<3) /* counter freeze */ | | 387 | #define EVC_MCF (1U<<3) /* counter freeze */ |
384 | #define EVC_ROR (1U<<2) /* auto-zero on counter read */ | | 388 | #define EVC_ROR (1U<<2) /* auto-zero on counter read */ |
385 | #define EVC_CSR (1U<<1) /* counter stop rollover */ | | 389 | #define EVC_CSR (1U<<1) /* counter stop rollover */ |
386 | #define EVC_CR (1U<<0) /* reset counters */ | | 390 | #define EVC_CR (1U<<0) /* reset counters */ |
387 | #define GMACEVCNT(i) ((i)*4+0x114) /* 80 event counters 0x114 - 0x284 */ | | 391 | #define GMACEVCNT(i) ((i)*4+0x114) /* 80 event counters 0x114 - 0x284 */ |
388 | | | 392 | |
389 | /* 0x400-4ac L3/L4 control */ | | 393 | /* 0x400-4ac L3/L4 control */ |
390 | | | 394 | |
391 | /* | | 395 | /* |
392 | * flash memory layout | | 396 | * flash memory layout |
393 | * 0x00 - 07 48-bit MAC station address. 4 byte wise in BE order. | | 397 | * 0x00 - 07 48-bit MAC station address. 4 byte wise in BE order. |
394 | * 0x08 - 0b H->MAC xfer engine program start addr 63:32. | | 398 | * 0x08 - 0b H->MAC xfer engine program start addr 63:32. |
395 | * 0x0c - 0f H2M program addr 31:0 (these are absolute addr, not offset) | | 399 | * 0x0c - 0f H2M program addr 31:0 (these are absolute addr, not offset) |
396 | * 0x10 - 13 H2M program length in 4 byte count. | | 400 | * 0x10 - 13 H2M program length in 4 byte count. |
397 | * 0x14 - 0b M->HOST xfer engine program start addr 63:32. | | 401 | * 0x14 - 0b M->HOST xfer engine program start addr 63:32. |
398 | * 0x18 - 0f M2H program addr 31:0 (absolute addr, not relative) | | 402 | * 0x18 - 0f M2H program addr 31:0 (absolute addr, not relative) |
399 | * 0x1c - 13 M2H program length in 4 byte count. | | 403 | * 0x1c - 13 M2H program length in 4 byte count. |
400 | * 0x20 - 23 packet engine program addr 31:0, (absolute addr, not offset) | | 404 | * 0x20 - 23 packet engine program addr 31:0, (absolute addr, not offset) |
401 | * 0x24 - 27 packet program length in 4 byte count. | | 405 | * 0x24 - 27 packet program length in 4 byte count. |
402 | * | | 406 | * |
403 | * above ucode are loaded via mapped reg 0x210, 0x21c and 0x0c0. | | 407 | * above ucode are loaded via mapped reg 0x210, 0x21c and 0x0c0. |
404 | */ | | 408 | */ |
405 | | | 409 | |
406 | #define _BMR 0x00412080 /* XXX TBD */ | | 410 | #define _BMR 0x00412080 /* XXX TBD */ |
407 | #define _BMR0 0x00020181 /* XXX TBD */ | | 411 | /* NetSec uses local RAM to handle GMAC desc arrays */ |
408 | /* NetSec uses local RAM to handle GMAC desc arrays and frame buffers */ | | | |
409 | #define _RDLA 0x18000 | | 412 | #define _RDLA 0x18000 |
410 | #define _TDLA 0x1c000 | | 413 | #define _TDLA 0x1c000 |
411 | #define _MCR_FDX 0x0000280c /* XXX TBD */ | | 414 | /* lower address region is used for intermediate frame data buffers */ |
412 | #define _MCR_HDX 0x0001a00c /* XXX TBD */ | | | |
413 | | | 415 | |
414 | /* | | 416 | /* |
415 | * all below are software constraction. | | 417 | * all below are software construction. |
416 | */ | | 418 | */ |
417 | #define MD_NTXDESC 128 | | 419 | #define MD_NTXDESC 128 |
418 | #define MD_NRXDESC 64 | | 420 | #define MD_NRXDESC 64 |
419 | | | 421 | |
420 | #define MD_NTXSEGS 16 | | 422 | #define MD_NTXSEGS 16 |
421 | #define MD_TXQUEUELEN 8 | | 423 | #define MD_TXQUEUELEN 8 |
422 | #define MD_TXQUEUELEN_MASK (MD_TXQUEUELEN - 1) | | 424 | #define MD_TXQUEUELEN_MASK (MD_TXQUEUELEN - 1) |
423 | #define MD_TXQUEUE_GC (MD_TXQUEUELEN / 4) | | 425 | #define MD_TXQUEUE_GC (MD_TXQUEUELEN / 4) |
424 | #define MD_NTXDESC_MASK (MD_NTXDESC - 1) | | 426 | #define MD_NTXDESC_MASK (MD_NTXDESC - 1) |
425 | #define MD_NEXTTX(x) (((x) + 1) & MD_NTXDESC_MASK) | | 427 | #define MD_NEXTTX(x) (((x) + 1) & MD_NTXDESC_MASK) |
426 | #define MD_NEXTTXS(x) (((x) + 1) & MD_TXQUEUELEN_MASK) | | 428 | #define MD_NEXTTXS(x) (((x) + 1) & MD_TXQUEUELEN_MASK) |
427 | | | 429 | |
428 | #define MD_NRXDESC_MASK (MD_NRXDESC - 1) | | 430 | #define MD_NRXDESC_MASK (MD_NRXDESC - 1) |
429 | #define MD_NEXTRX(x) (((x) + 1) & MD_NRXDESC_MASK) | | 431 | #define MD_NEXTRX(x) (((x) + 1) & MD_NRXDESC_MASK) |
430 | | | 432 | |
431 | struct control_data { | | 433 | struct control_data { |
432 | struct tdes cd_txdescs[MD_NTXDESC]; | | 434 | struct tdes cd_txdescs[MD_NTXDESC]; |
433 | struct rdes cd_rxdescs[MD_NRXDESC]; | | 435 | struct rdes cd_rxdescs[MD_NRXDESC]; |
434 | }; | | 436 | }; |
435 | #define SCX_CDOFF(x) offsetof(struct control_data, x) | | 437 | #define SCX_CDOFF(x) offsetof(struct control_data, x) |
436 | #define SCX_CDTXOFF(x) SCX_CDOFF(cd_txdescs[(x)]) | | 438 | #define SCX_CDTXOFF(x) SCX_CDOFF(cd_txdescs[(x)]) |
437 | #define SCX_CDRXOFF(x) SCX_CDOFF(cd_rxdescs[(x)]) | | 439 | #define SCX_CDRXOFF(x) SCX_CDOFF(cd_rxdescs[(x)]) |
438 | | | 440 | |
439 | struct scx_txsoft { | | 441 | struct scx_txsoft { |
440 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ | | 442 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ |
441 | bus_dmamap_t txs_dmamap; /* our DMA map */ | | 443 | bus_dmamap_t txs_dmamap; /* our DMA map */ |
442 | int txs_firstdesc; /* first descriptor in packet */ | | 444 | int txs_firstdesc; /* first descriptor in packet */ |
443 | int txs_lastdesc; /* last descriptor in packet */ | | 445 | int txs_lastdesc; /* last descriptor in packet */ |
444 | int txs_ndesc; /* # of descriptors used */ | | 446 | int txs_ndesc; /* # of descriptors used */ |
445 | }; | | 447 | }; |
446 | | | 448 | |
447 | struct scx_rxsoft { | | 449 | struct scx_rxsoft { |
448 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ | | 450 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ |
449 | bus_dmamap_t rxs_dmamap; /* our DMA map */ | | 451 | bus_dmamap_t rxs_dmamap; /* our DMA map */ |
450 | }; | | 452 | }; |
451 | | | 453 | |
452 | struct scx_softc { | | 454 | struct scx_softc { |
453 | device_t sc_dev; /* generic device information */ | | 455 | device_t sc_dev; /* generic device information */ |
454 | bus_space_tag_t sc_st; /* bus space tag */ | | 456 | bus_space_tag_t sc_st; /* bus space tag */ |
455 | bus_space_handle_t sc_sh; /* bus space handle */ | | 457 | bus_space_handle_t sc_sh; /* bus space handle */ |
456 | bus_size_t sc_sz; /* csr map size */ | | 458 | bus_size_t sc_sz; /* csr map size */ |
457 | bus_space_handle_t sc_eesh; /* eeprom section handle */ | | 459 | bus_space_handle_t sc_eesh; /* eeprom section handle */ |
458 | bus_size_t sc_eesz; /* eeprom map size */ | | 460 | bus_size_t sc_eesz; /* eeprom map size */ |
459 | bus_dma_tag_t sc_dmat; /* bus DMA tag */ | | 461 | bus_dma_tag_t sc_dmat; /* bus DMA tag */ |
460 | struct ethercom sc_ethercom; /* Ethernet common data */ | | 462 | struct ethercom sc_ethercom; /* Ethernet common data */ |
461 | struct mii_data sc_mii; /* MII */ | | 463 | struct mii_data sc_mii; /* MII */ |
462 | callout_t sc_callout; /* PHY monitor callout */ | | 464 | callout_t sc_callout; /* PHY monitor callout */ |
463 | bus_dma_segment_t sc_seg; /* descriptor store seg */ | | 465 | bus_dma_segment_t sc_seg; /* descriptor store seg */ |
464 | int sc_nseg; /* descriptor store nseg */ | | 466 | int sc_nseg; /* descriptor store nseg */ |
465 | void *sc_ih; /* interrupt cookie */ | | 467 | void *sc_ih; /* interrupt cookie */ |
466 | int sc_phy_id; /* PHY address */ | | 468 | int sc_phy_id; /* PHY address */ |
467 | int sc_flowflags; /* 802.3x PAUSE flow control */ | | 469 | int sc_flowflags; /* 802.3x PAUSE flow control */ |
468 | uint32_t sc_mdclk; /* GAR 5:2 clock selection */ | | 470 | uint32_t sc_mdclk; /* GAR 5:2 clock selection */ |
469 | uint32_t sc_t0cotso; /* T0_CSUM | T0_TSO to run */ | | 471 | uint32_t sc_t0cotso; /* T0_CSUM | T0_TSO to run */ |
470 | int sc_miigmii; /* 1: MII/GMII, 0: RGMII */ | | 472 | int sc_miigmii; /* 1: MII/GMII, 0: RGMII */ |
471 | int sc_phandle; /* fdt phandle */ | | 473 | int sc_phandle; /* fdt phandle */ |
472 | uint64_t sc_freq; | | 474 | uint64_t sc_freq; |
473 | uint32_t sc_maxsize; | | 475 | uint32_t sc_maxsize; |
474 | | | 476 | |
475 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ | | 477 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ |
476 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr | | 478 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr |
477 | | | 479 | |
478 | struct control_data *sc_control_data; | | 480 | struct control_data *sc_control_data; |
479 | #define sc_txdescs sc_control_data->cd_txdescs | | 481 | #define sc_txdescs sc_control_data->cd_txdescs |
480 | #define sc_rxdescs sc_control_data->cd_rxdescs | | 482 | #define sc_rxdescs sc_control_data->cd_rxdescs |
481 | | | 483 | |
482 | struct scx_txsoft sc_txsoft[MD_TXQUEUELEN]; | | 484 | struct scx_txsoft sc_txsoft[MD_TXQUEUELEN]; |
483 | struct scx_rxsoft sc_rxsoft[MD_NRXDESC]; | | 485 | struct scx_rxsoft sc_rxsoft[MD_NRXDESC]; |
484 | int sc_txfree; /* number of free Tx descriptors */ | | 486 | int sc_txfree; /* number of free Tx descriptors */ |
485 | int sc_txnext; /* next ready Tx descriptor */ | | 487 | int sc_txnext; /* next ready Tx descriptor */ |
486 | int sc_txsfree; /* number of free Tx jobs */ | | 488 | int sc_txsfree; /* number of free Tx jobs */ |
487 | int sc_txsnext; /* next ready Tx job */ | | 489 | int sc_txsnext; /* next ready Tx job */ |
488 | int sc_txsdirty; /* dirty Tx jobs */ | | 490 | int sc_txsdirty; /* dirty Tx jobs */ |
489 | int sc_rxptr; /* next ready Rx descriptor/descsoft */ | | 491 | int sc_rxptr; /* next ready Rx descriptor/descsoft */ |
490 | | | 492 | |
491 | krndsource_t rnd_source; /* random source */ | | 493 | krndsource_t rnd_source; /* random source */ |
492 | #ifdef GMAC_EVENT_COUNTERS | | 494 | #ifdef GMAC_EVENT_COUNTERS |
493 | /* 80 event counters exist */ | | 495 | /* 80 event counters exist */ |
494 | #endif | | 496 | #endif |
495 | }; | | 497 | }; |
496 | | | 498 | |
497 | #define SCX_CDTXADDR(sc, x) ((sc)->sc_cddma + SCX_CDTXOFF((x))) | | 499 | #define SCX_CDTXADDR(sc, x) ((sc)->sc_cddma + SCX_CDTXOFF((x))) |
498 | #define SCX_CDRXADDR(sc, x) ((sc)->sc_cddma + SCX_CDRXOFF((x))) | | 500 | #define SCX_CDRXADDR(sc, x) ((sc)->sc_cddma + SCX_CDRXOFF((x))) |
499 | | | 501 | |
500 | #define SCX_CDTXSYNC(sc, x, n, ops) \ | | 502 | #define SCX_CDTXSYNC(sc, x, n, ops) \ |
501 | do { \ | | 503 | do { \ |
502 | int __x, __n; \ | | 504 | int __x, __n; \ |
503 | \ | | 505 | \ |
504 | __x = (x); \ | | 506 | __x = (x); \ |
505 | __n = (n); \ | | 507 | __n = (n); \ |
506 | \ | | 508 | \ |
507 | /* If it will wrap around, sync to the end of the ring. */ \ | | 509 | /* If it will wrap around, sync to the end of the ring. */ \ |
508 | if ((__x + __n) > MD_NTXDESC) { \ | | 510 | if ((__x + __n) > MD_NTXDESC) { \ |
509 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 511 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
510 | SCX_CDTXOFF(__x), sizeof(struct tdes) * \ | | 512 | SCX_CDTXOFF(__x), sizeof(struct tdes) * \ |
511 | (MD_NTXDESC - __x), (ops)); \ | | 513 | (MD_NTXDESC - __x), (ops)); \ |
512 | __n -= (MD_NTXDESC - __x); \ | | 514 | __n -= (MD_NTXDESC - __x); \ |
513 | __x = 0; \ | | 515 | __x = 0; \ |
514 | } \ | | 516 | } \ |
515 | \ | | 517 | \ |
516 | /* Now sync whatever is left. */ \ | | 518 | /* Now sync whatever is left. */ \ |
517 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 519 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
518 | SCX_CDTXOFF(__x), sizeof(struct tdes) * __n, (ops)); \ | | 520 | SCX_CDTXOFF(__x), sizeof(struct tdes) * __n, (ops)); \ |
519 | } while (/*CONSTCOND*/0) | | 521 | } while (/*CONSTCOND*/0) |
520 | | | 522 | |
521 | #define SCX_CDRXSYNC(sc, x, ops) \ | | 523 | #define SCX_CDRXSYNC(sc, x, ops) \ |
522 | do { \ | | 524 | do { \ |
523 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 525 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
524 | SCX_CDRXOFF((x)), sizeof(struct rdes), (ops)); \ | | 526 | SCX_CDRXOFF((x)), sizeof(struct rdes), (ops)); \ |
525 | } while (/*CONSTCOND*/0) | | 527 | } while (/*CONSTCOND*/0) |
526 | | | 528 | |
527 | #define SCX_INIT_RXDESC(sc, x) \ | | 529 | #define SCX_INIT_RXDESC(sc, x) \ |
528 | do { \ | | 530 | do { \ |
529 | struct scx_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \ | | 531 | struct scx_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \ |
530 | struct rdes *__rxd = &(sc)->sc_rxdescs[(x)]; \ | | 532 | struct rdes *__rxd = &(sc)->sc_rxdescs[(x)]; \ |
531 | struct mbuf *__m = __rxs->rxs_mbuf; \ | | 533 | struct mbuf *__m = __rxs->rxs_mbuf; \ |
532 | bus_addr_t __p = __rxs->rxs_dmamap->dm_segs[0].ds_addr; \ | | 534 | bus_addr_t __p = __rxs->rxs_dmamap->dm_segs[0].ds_addr; \ |
533 | bus_size_t __z = __rxs->rxs_dmamap->dm_segs[0].ds_len; \ | | 535 | bus_size_t __z = __rxs->rxs_dmamap->dm_segs[0].ds_len; \ |
534 | __m->m_data = __m->m_ext.ext_buf; \ | | 536 | __m->m_data = __m->m_ext.ext_buf; \ |
535 | __rxd->r3 = htole32(__z); \ | | 537 | __rxd->r3 = htole32(__z - 4); \ |
536 | __rxd->r2 = htole32(BUS_ADDR_LO32(__p)); \ | | 538 | __rxd->r2 = htole32(BUS_ADDR_LO32(__p)); \ |
537 | __rxd->r1 = htole32(BUS_ADDR_HI32(__p)); \ | | 539 | __rxd->r1 = htole32(BUS_ADDR_HI32(__p)); \ |
538 | __rxd->r0 &= htole32(R0_LD); \ | | 540 | __rxd->r0 &= htole32(R0_LD); \ |
539 | __rxd->r0 |= htole32(R0_OWN); \ | | 541 | __rxd->r0 |= htole32(R0_OWN); \ |
540 | } while (/*CONSTCOND*/0) | | 542 | } while (/*CONSTCOND*/0) |
541 | | | 543 | |
542 | /* memory mapped CSR register access */ | | 544 | /* memory mapped CSR register access */ |
543 | #define CSR_READ(sc,off) \ | | 545 | #define CSR_READ(sc,off) \ |
544 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (off)) | | 546 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (off)) |
545 | #define CSR_WRITE(sc,off,val) \ | | 547 | #define CSR_WRITE(sc,off,val) \ |
546 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (off), (val)) | | 548 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (off), (val)) |
547 | | | 549 | |
548 | /* flash memory access */ | | 550 | /* flash memory access */ |
549 | #define EE_READ(sc,off) \ | | 551 | #define EE_READ(sc,off) \ |
550 | bus_space_read_4((sc)->sc_st, (sc)->sc_eesh, (off)) | | 552 | bus_space_read_4((sc)->sc_st, (sc)->sc_eesh, (off)) |
551 | | | 553 | |
552 | static int scx_fdt_match(device_t, cfdata_t, void *); | | 554 | static int scx_fdt_match(device_t, cfdata_t, void *); |
553 | static void scx_fdt_attach(device_t, device_t, void *); | | 555 | static void scx_fdt_attach(device_t, device_t, void *); |
554 | static int scx_acpi_match(device_t, cfdata_t, void *); | | 556 | static int scx_acpi_match(device_t, cfdata_t, void *); |
555 | static void scx_acpi_attach(device_t, device_t, void *); | | 557 | static void scx_acpi_attach(device_t, device_t, void *); |
556 | | | 558 | |
557 | CFATTACH_DECL_NEW(scx_fdt, sizeof(struct scx_softc), | | 559 | CFATTACH_DECL_NEW(scx_fdt, sizeof(struct scx_softc), |
558 | scx_fdt_match, scx_fdt_attach, NULL, NULL); | | 560 | scx_fdt_match, scx_fdt_attach, NULL, NULL); |
559 | | | 561 | |
560 | CFATTACH_DECL_NEW(scx_acpi, sizeof(struct scx_softc), | | 562 | CFATTACH_DECL_NEW(scx_acpi, sizeof(struct scx_softc), |
561 | scx_acpi_match, scx_acpi_attach, NULL, NULL); | | 563 | scx_acpi_match, scx_acpi_attach, NULL, NULL); |
562 | | | 564 | |
563 | static void scx_attach_i(struct scx_softc *); | | 565 | static void scx_attach_i(struct scx_softc *); |
564 | static void scx_reset(struct scx_softc *); | | 566 | static void scx_reset(struct scx_softc *); |
565 | static int scx_init(struct ifnet *); | | | |
566 | static void scx_stop(struct ifnet *, int); | | 567 | static void scx_stop(struct ifnet *, int); |
| | | 568 | static int scx_init(struct ifnet *); |
567 | static int scx_ioctl(struct ifnet *, u_long, void *); | | 569 | static int scx_ioctl(struct ifnet *, u_long, void *); |
568 | static void scx_set_rcvfilt(struct scx_softc *); | | 570 | static void scx_set_rcvfilt(struct scx_softc *); |
569 | static void scx_start(struct ifnet *); | | 571 | static void scx_start(struct ifnet *); |
570 | static void scx_watchdog(struct ifnet *); | | 572 | static void scx_watchdog(struct ifnet *); |
571 | static int scx_intr(void *); | | 573 | static int scx_intr(void *); |
572 | static void txreap(struct scx_softc *); | | 574 | static void txreap(struct scx_softc *); |
573 | static void rxintr(struct scx_softc *); | | 575 | static void rxfill(struct scx_softc *); |
574 | static int add_rxbuf(struct scx_softc *, int); | | 576 | static int add_rxbuf(struct scx_softc *, int); |
575 | static void rxdrain(struct scx_softc *sc); | | 577 | static void rxdrain(struct scx_softc *sc); |
576 | static void mii_statchg(struct ifnet *); | | 578 | static void mii_statchg(struct ifnet *); |
577 | static void scx_ifmedia_sts(struct ifnet *, struct ifmediareq *); | | 579 | static void scx_ifmedia_sts(struct ifnet *, struct ifmediareq *); |
578 | static int mii_readreg(device_t, int, int, uint16_t *); | | 580 | static int mii_readreg(device_t, int, int, uint16_t *); |
579 | static int mii_writereg(device_t, int, int, uint16_t); | | 581 | static int mii_writereg(device_t, int, int, uint16_t); |
580 | static void phy_tick(void *); | | 582 | static void phy_tick(void *); |
581 | static void dump_hwfeature(struct scx_softc *); | | 583 | static void dump_hwfeature(struct scx_softc *); |
582 | | | 584 | |
583 | static void stopuengine(struct scx_softc *); | | 585 | static void resetuengine(struct scx_softc *); |
584 | static void startuengine(struct scx_softc *); | | | |
585 | static void loaducode(struct scx_softc *); | | 586 | static void loaducode(struct scx_softc *); |
586 | static void injectucode(struct scx_softc *, int, bus_addr_t, bus_size_t); | | 587 | static void injectucode(struct scx_softc *, int, bus_addr_t, bus_size_t); |
587 | | | 588 | |
588 | static int get_mdioclk(uint32_t); | | 589 | static int get_mdioclk(uint32_t); |
589 | | | 590 | |
590 | #define WAIT_FOR_SET(sc, reg, set, fail) \ | | 591 | #define WAIT_FOR_SET(sc, reg, set) \ |
591 | wait_for_bits(sc, reg, set, ~0, fail) | | 592 | wait_for_bits(sc, reg, set, ~0, 0) |
592 | #define WAIT_FOR_CLR(sc, reg, clr, fail) \ | | 593 | #define WAIT_FOR_CLR(sc, reg, clr) \ |
593 | wait_for_bits(sc, reg, 0, clr, fail) | | 594 | wait_for_bits(sc, reg, 0, clr, 0) |
594 | | | 595 | |
595 | static int | | 596 | static int |
596 | wait_for_bits(struct scx_softc *sc, int reg, | | 597 | wait_for_bits(struct scx_softc *sc, int reg, |
597 | uint32_t set, uint32_t clr, uint32_t fail) | | 598 | uint32_t set, uint32_t clr, uint32_t fail) |
598 | { | | 599 | { |
599 | uint32_t val; | | 600 | uint32_t val; |
600 | int ntries; | | 601 | int ntries; |
601 | | | 602 | |
602 | for (ntries = 0; ntries < 1000; ntries++) { | | 603 | for (ntries = 0; ntries < 1000; ntries++) { |
603 | val = CSR_READ(sc, reg); | | 604 | val = CSR_READ(sc, reg); |
604 | if ((val & set) || !(val & clr)) | | 605 | if ((val & set) || !(val & clr)) |
605 | return 0; | | 606 | return 0; |
606 | if (val & fail) | | 607 | if (val & fail) |
607 | return 1; | | 608 | return 1; |
608 | DELAY(1); | | 609 | DELAY(1); |
609 | } | | 610 | } |
610 | return 1; | | 611 | return 1; |
611 | } | | 612 | } |
612 | | | 613 | |
613 | /* GMAC register indirect access */ | | 614 | /* GMAC register indirect access */ |
614 | static int | | 615 | static int |
615 | mac_read(struct scx_softc *sc, int reg) | | 616 | mac_read(struct scx_softc *sc, int reg) |
616 | { | | 617 | { |
617 | | | 618 | |
618 | CSR_WRITE(sc, MACCMD, reg | CMD_BUSY); | | 619 | CSR_WRITE(sc, MACCMD, reg | CMD_BUSY); |
619 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY, 0); | | 620 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY); |
620 | return CSR_READ(sc, MACDATA); | | 621 | return CSR_READ(sc, MACDATA); |
621 | } | | 622 | } |
622 | | | 623 | |
623 | static void | | 624 | static void |
624 | mac_write(struct scx_softc *sc, int reg, int val) | | 625 | mac_write(struct scx_softc *sc, int reg, int val) |
625 | { | | 626 | { |
626 | | | 627 | |
627 | CSR_WRITE(sc, MACDATA, val); | | 628 | CSR_WRITE(sc, MACDATA, val); |
628 | CSR_WRITE(sc, MACCMD, reg | CMD_IOWR | CMD_BUSY); | | 629 | CSR_WRITE(sc, MACCMD, reg | CMD_IOWR | CMD_BUSY); |
629 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY, 0); | | 630 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY); |
630 | } | | 631 | } |
631 | | | 632 | |
632 | /* dig and decode "clock-frequency" value for a given clkname */ | | 633 | /* dig and decode "clock-frequency" value for a given clkname */ |
633 | static int | | 634 | static int |
634 | get_clk_freq(int phandle, const char *clkname) | | 635 | get_clk_freq(int phandle, const char *clkname) |
635 | { | | 636 | { |
636 | u_int index, n, cells; | | 637 | u_int index, n, cells; |
637 | const u_int *p; | | 638 | const u_int *p; |
638 | int err, len, resid; | | 639 | int err, len, resid; |
639 | unsigned int freq = 0; | | 640 | unsigned int freq = 0; |
640 | | | 641 | |
641 | err = fdtbus_get_index(phandle, "clock-names", clkname, &index); | | 642 | err = fdtbus_get_index(phandle, "clock-names", clkname, &index); |
642 | if (err == -1) | | 643 | if (err == -1) |
643 | return -1; | | 644 | return -1; |
644 | p = fdtbus_get_prop(phandle, "clocks", &len); | | 645 | p = fdtbus_get_prop(phandle, "clocks", &len); |
645 | if (p == NULL) | | 646 | if (p == NULL) |
646 | return -1; | | 647 | return -1; |
647 | for (n = 0, resid = len; resid > 0; n++) { | | 648 | for (n = 0, resid = len; resid > 0; n++) { |
648 | const int cc_phandle = | | 649 | const int cc_phandle = |
649 | fdtbus_get_phandle_from_native(be32toh(p[0])); | | 650 | fdtbus_get_phandle_from_native(be32toh(p[0])); |
650 | if (of_getprop_uint32(cc_phandle, "#clock-cells", &cells)) | | 651 | if (of_getprop_uint32(cc_phandle, "#clock-cells", &cells)) |
651 | return -1; | | 652 | return -1; |
652 | if (n == index) { | | 653 | if (n == index) { |
653 | if (of_getprop_uint32(cc_phandle, | | 654 | if (of_getprop_uint32(cc_phandle, |
654 | "clock-frequency", &freq)) | | 655 | "clock-frequency", &freq)) |
655 | return -1; | | 656 | return -1; |
656 | return freq; | | 657 | return freq; |
657 | } | | 658 | } |
658 | resid -= (cells + 1) * 4; | | 659 | resid -= (cells + 1) * 4; |
659 | p += (cells + 1) * 4; | | 660 | p += (cells + 1) * 4; |
660 | } | | 661 | } |
661 | return -1; | | 662 | return -1; |
662 | } | | 663 | } |
663 | | | 664 | |
664 | #define ATTACH_DEBUG 1 | | 665 | #define ATTACH_DEBUG 1 |
665 | | | 666 | |
666 | static const struct device_compatible_entry compat_data[] = { | | 667 | static const struct device_compatible_entry compat_data[] = { |
667 | { .compat = "socionext,synquacer-netsec" }, | | 668 | { .compat = "socionext,synquacer-netsec" }, |
668 | DEVICE_COMPAT_EOL | | 669 | DEVICE_COMPAT_EOL |
669 | }; | | 670 | }; |
670 | static const struct device_compatible_entry compatible[] = { | | 671 | static const struct device_compatible_entry compatible[] = { |
671 | { .compat = "SCX0001" }, | | 672 | { .compat = "SCX0001" }, |
672 | DEVICE_COMPAT_EOL | | 673 | DEVICE_COMPAT_EOL |
673 | }; | | 674 | }; |
674 | | | 675 | |
675 | static int | | 676 | static int |
676 | scx_fdt_match(device_t parent, cfdata_t cf, void *aux) | | 677 | scx_fdt_match(device_t parent, cfdata_t cf, void *aux) |
677 | { | | 678 | { |
678 | struct fdt_attach_args * const faa = aux; | | 679 | struct fdt_attach_args * const faa = aux; |
679 | | | 680 | |
680 | return of_compatible_match(faa->faa_phandle, compat_data); | | 681 | return of_compatible_match(faa->faa_phandle, compat_data); |
681 | } | | 682 | } |
682 | | | 683 | |
683 | static void | | 684 | static void |
684 | scx_fdt_attach(device_t parent, device_t self, void *aux) | | 685 | scx_fdt_attach(device_t parent, device_t self, void *aux) |
685 | { | | 686 | { |
686 | struct scx_softc * const sc = device_private(self); | | 687 | struct scx_softc * const sc = device_private(self); |
687 | struct fdt_attach_args * const faa = aux; | | 688 | struct fdt_attach_args * const faa = aux; |
688 | const int phandle = faa->faa_phandle; | | 689 | const int phandle = faa->faa_phandle; |
689 | bus_space_handle_t bsh; | | 690 | bus_space_handle_t bsh; |
690 | bus_space_handle_t eebsh; | | 691 | bus_space_handle_t eebsh; |
691 | bus_addr_t addr[2]; | | 692 | bus_addr_t addr[2]; |
692 | bus_size_t size[2]; | | 693 | bus_size_t size[2]; |
693 | void *intrh; | | 694 | void *intrh; |
694 | char intrstr[128]; | | 695 | char intrstr[128]; |
695 | int phy_phandle; | | 696 | int phy_phandle; |
696 | const char *phy_mode; | | 697 | const char *phy_mode; |
697 | bus_addr_t phy_id; | | 698 | bus_addr_t phy_id; |
698 | long ref_clk; | | 699 | long ref_clk; |
699 | | | 700 | |
700 | if (fdtbus_get_reg(phandle, 0, addr+0, size+0) != 0 | | 701 | if (fdtbus_get_reg(phandle, 0, addr+0, size+0) != 0 |
701 | || bus_space_map(faa->faa_bst, addr[0], size[0], 0, &bsh) != 0) { | | 702 | || bus_space_map(faa->faa_bst, addr[0], size[0], 0, &bsh) != 0) { |
702 | aprint_error(": unable to map registers\n"); | | 703 | aprint_error(": unable to map registers\n"); |
703 | return; | | 704 | return; |
704 | } | | 705 | } |
705 | if (fdtbus_get_reg(phandle, 1, addr+1, size+1) != 0 | | 706 | if (fdtbus_get_reg(phandle, 1, addr+1, size+1) != 0 |
706 | || bus_space_map(faa->faa_bst, addr[1], size[1], 0, &eebsh) != 0) { | | 707 | || bus_space_map(faa->faa_bst, addr[1], size[1], 0, &eebsh) != 0) { |
707 | aprint_error(": unable to map device eeprom\n"); | | 708 | aprint_error(": unable to map device eeprom\n"); |
708 | goto fail; | | 709 | goto fail; |
709 | } | | 710 | } |
710 | if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { | | 711 | if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { |
711 | aprint_error(": failed to decode interrupt\n"); | | 712 | aprint_error(": failed to decode interrupt\n"); |
712 | goto fail; | | 713 | goto fail; |
713 | } | | 714 | } |
714 | | | 715 | |
715 | phy_mode = fdtbus_get_string(phandle, "phy-mode"); | | 716 | phy_mode = fdtbus_get_string(phandle, "phy-mode"); |
716 | if (phy_mode == NULL) | | 717 | if (phy_mode == NULL) |
717 | aprint_error(": missing 'phy-mode' property\n"); | | 718 | aprint_error(": missing 'phy-mode' property\n"); |
718 | phy_phandle = fdtbus_get_phandle(phandle, "phy-handle"); | | 719 | phy_phandle = fdtbus_get_phandle(phandle, "phy-handle"); |
719 | if (phy_phandle == -1 | | 720 | if (phy_phandle == -1 |
720 | || fdtbus_get_reg(phy_phandle, 0, &phy_id, NULL) != 0) | | 721 | || fdtbus_get_reg(phy_phandle, 0, &phy_id, NULL) != 0) |
721 | phy_id = MII_PHY_ANY; | | 722 | phy_id = MII_PHY_ANY; |
722 | ref_clk = get_clk_freq(phandle, "phy_ref_clk"); | | 723 | ref_clk = get_clk_freq(phandle, "phy_ref_clk"); |
723 | if (ref_clk == -1) | | 724 | if (ref_clk == -1) |
724 | ref_clk = 250 * 1000 * 1000; | | 725 | ref_clk = 250 * 1000 * 1000; |
725 | | | 726 | |
726 | #if ATTACH_DEBUG == 1 | | 727 | #if ATTACH_DEBUG == 1 |
727 | aprint_normal("\n"); | | 728 | aprint_normal("\n"); |
728 | aprint_normal_dev(self, | | 729 | aprint_normal_dev(self, |
729 | "[FDT] phy mode %s, phy id %d, freq %ld\n", | | 730 | "[FDT] phy mode %s, phy id %d, freq %ld\n", |
730 | phy_mode, (int)phy_id, ref_clk); | | 731 | phy_mode, (int)phy_id, ref_clk); |
731 | aprint_normal("%s", device_xname(self)); | | 732 | aprint_normal("%s", device_xname(self)); |
732 | #endif | | 733 | #endif |
733 | | | 734 | |
734 | intrh = fdtbus_intr_establish(phandle, 0, IPL_NET, | | 735 | intrh = fdtbus_intr_establish(phandle, 0, IPL_NET, |
735 | NOT_MP_SAFE, scx_intr, sc); | | 736 | NOT_MP_SAFE, scx_intr, sc); |
736 | if (intrh == NULL) { | | 737 | if (intrh == NULL) { |
737 | aprint_error(": couldn't establish interrupt\n"); | | 738 | aprint_error(": couldn't establish interrupt\n"); |
738 | goto fail; | | 739 | goto fail; |
739 | } | | 740 | } |
740 | aprint_normal(" interrupt on %s", intrstr); | | 741 | aprint_normal(" interrupt on %s", intrstr); |
741 | | | 742 | |
742 | sc->sc_dev = self; | | 743 | sc->sc_dev = self; |
743 | sc->sc_st = faa->faa_bst; | | 744 | sc->sc_st = faa->faa_bst; |
744 | sc->sc_sh = bsh; | | 745 | sc->sc_sh = bsh; |
745 | sc->sc_sz = size[0]; | | 746 | sc->sc_sz = size[0]; |
746 | sc->sc_eesh = eebsh; | | 747 | sc->sc_eesh = eebsh; |
747 | sc->sc_eesz = size[1]; | | 748 | sc->sc_eesz = size[1]; |
748 | sc->sc_ih = intrh; | | 749 | sc->sc_ih = intrh; |
749 | sc->sc_dmat = faa->faa_dmat; | | 750 | sc->sc_dmat = faa->faa_dmat; |
750 | sc->sc_phandle = phandle; | | 751 | sc->sc_phandle = phandle; |
751 | sc->sc_phy_id = phy_id; | | 752 | sc->sc_phy_id = phy_id; |
752 | sc->sc_freq = ref_clk; | | 753 | sc->sc_freq = ref_clk; |
753 | | | 754 | |
754 | scx_attach_i(sc); | | 755 | scx_attach_i(sc); |
755 | | | 756 | |
756 | return; | | 757 | return; |
757 | fail: | | 758 | fail: |
758 | if (sc->sc_eesz) | | 759 | if (sc->sc_eesz) |
759 | bus_space_unmap(sc->sc_st, sc->sc_eesh, sc->sc_eesz); | | 760 | bus_space_unmap(sc->sc_st, sc->sc_eesh, sc->sc_eesz); |
760 | if (sc->sc_sz) | | 761 | if (sc->sc_sz) |
761 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); | | 762 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); |
762 | return; | | 763 | return; |
763 | } | | 764 | } |
764 | | | 765 | |
765 | static int | | 766 | static int |
766 | scx_acpi_match(device_t parent, cfdata_t cf, void *aux) | | 767 | scx_acpi_match(device_t parent, cfdata_t cf, void *aux) |
767 | { | | 768 | { |
768 | struct acpi_attach_args *aa = aux; | | 769 | struct acpi_attach_args *aa = aux; |
769 | | | 770 | |
770 | return acpi_compatible_match(aa, compatible); | | 771 | return acpi_compatible_match(aa, compatible); |
771 | } | | 772 | } |
772 | | | 773 | |
773 | #define HWFEA_DEBUG 1 | | 774 | #define HWFEA_DEBUG 1 |
774 | | | 775 | |
775 | static void | | 776 | static void |
776 | scx_acpi_attach(device_t parent, device_t self, void *aux) | | 777 | scx_acpi_attach(device_t parent, device_t self, void *aux) |
777 | { | | 778 | { |
778 | struct scx_softc * const sc = device_private(self); | | 779 | struct scx_softc * const sc = device_private(self); |
779 | struct acpi_attach_args * const aa = aux; | | 780 | struct acpi_attach_args * const aa = aux; |
780 | ACPI_HANDLE handle = aa->aa_node->ad_handle; | | 781 | ACPI_HANDLE handle = aa->aa_node->ad_handle; |
781 | bus_space_handle_t bsh, eebsh; | | 782 | bus_space_handle_t bsh, eebsh; |
782 | struct acpi_resources res; | | 783 | struct acpi_resources res; |
783 | struct acpi_mem *mem, *mem1; | | 784 | struct acpi_mem *mem, *mem1; |
784 | struct acpi_irq *irq; | | 785 | struct acpi_irq *irq; |
785 | ACPI_INTEGER max_spd, max_frame, phy_id, phy_freq; | | 786 | ACPI_INTEGER max_spd, max_frame, phy_id, phy_freq; |
786 | ACPI_STATUS rv; | | 787 | ACPI_STATUS rv; |
787 | void *intrh; | | 788 | void *intrh; |
788 | | | 789 | |
789 | rv = acpi_resource_parse(self, handle, "_CRS", | | 790 | rv = acpi_resource_parse(self, handle, "_CRS", |
790 | &res, &acpi_resource_parse_ops_default); | | 791 | &res, &acpi_resource_parse_ops_default); |
791 | if (ACPI_FAILURE(rv)) | | 792 | if (ACPI_FAILURE(rv)) |
792 | return; | | 793 | return; |
793 | mem = acpi_res_mem(&res, 0); | | 794 | mem = acpi_res_mem(&res, 0); |
794 | irq = acpi_res_irq(&res, 0); | | 795 | irq = acpi_res_irq(&res, 0); |
795 | if (mem == NULL || irq == NULL || mem->ar_length == 0) { | | 796 | if (mem == NULL || irq == NULL || mem->ar_length == 0) { |
796 | aprint_error(": incomplete crs resources\n"); | | 797 | aprint_error(": incomplete crs resources\n"); |
797 | goto done; | | 798 | goto done; |
798 | } | | 799 | } |
799 | if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, | | 800 | if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, |
800 | &bsh) != 0) { | | 801 | &bsh) != 0) { |
801 | aprint_error(": unable to map registers\n"); | | 802 | aprint_error(": unable to map registers\n"); |
802 | goto done; | | 803 | goto done; |
803 | } | | 804 | } |
804 | mem1 = acpi_res_mem(&res, 1); /* EEPROM for MAC address and ucode */ | | 805 | mem1 = acpi_res_mem(&res, 1); /* EEPROM for MAC address and ucode */ |
805 | if (mem1 == NULL || mem1->ar_length == 0) { | | 806 | if (mem1 == NULL || mem1->ar_length == 0) { |
806 | aprint_error(": incomplete eeprom resources\n"); | | 807 | aprint_error(": incomplete eeprom resources\n"); |
807 | goto fail_0; | | 808 | goto fail_0; |
808 | } | | 809 | } |
809 | if (bus_space_map(aa->aa_memt, mem1->ar_base, mem1->ar_length, 0, | | 810 | if (bus_space_map(aa->aa_memt, mem1->ar_base, mem1->ar_length, 0, |
810 | &eebsh)) { | | 811 | &eebsh)) { |
811 | aprint_error(": unable to map device eeprom\n"); | | 812 | aprint_error(": unable to map device eeprom\n"); |
812 | goto fail_0; | | 813 | goto fail_0; |
813 | } | | 814 | } |
814 | rv = acpi_dsd_integer(handle, "max-speed", &max_spd); | | 815 | rv = acpi_dsd_integer(handle, "max-speed", &max_spd); |
815 | if (ACPI_FAILURE(rv)) | | 816 | if (ACPI_FAILURE(rv)) |
816 | max_spd = 1000; | | 817 | max_spd = 1000; |
817 | rv = acpi_dsd_integer(handle, "max-frame-size", &max_frame); | | 818 | rv = acpi_dsd_integer(handle, "max-frame-size", &max_frame); |
818 | if (ACPI_FAILURE(rv)) | | 819 | if (ACPI_FAILURE(rv)) |
819 | max_frame = 2048; | | 820 | max_frame = 2048; |
820 | rv = acpi_dsd_integer(handle, "phy-channel", &phy_id); | | 821 | rv = acpi_dsd_integer(handle, "phy-channel", &phy_id); |
821 | if (ACPI_FAILURE(rv)) | | 822 | if (ACPI_FAILURE(rv)) |
822 | phy_id = MII_PHY_ANY; | | 823 | phy_id = MII_PHY_ANY; |
823 | rv = acpi_dsd_integer(handle, "socionext,phy-clock-frequency", | | 824 | rv = acpi_dsd_integer(handle, "socionext,phy-clock-frequency", |
824 | &phy_freq); | | 825 | &phy_freq); |
825 | if (ACPI_FAILURE(rv)) | | 826 | if (ACPI_FAILURE(rv)) |
826 | phy_freq = 250 * 1000 * 1000; | | 827 | phy_freq = 250 * 1000 * 1000; |
827 | | | 828 | |
828 | #if ATTACH_DEBUG == 1 | | 829 | #if ATTACH_DEBUG == 1 |
829 | aprint_normal_dev(self, | | 830 | aprint_normal_dev(self, |
830 | "[ACPI] max-speed %d, phy id %d, freq %ld\n", | | 831 | "[ACPI] max-speed %d, phy id %d, freq %ld\n", |
831 | (int)max_spd, (int)phy_id, phy_freq); | | 832 | (int)max_spd, (int)phy_id, phy_freq); |
832 | aprint_normal("%s", device_xname(self)); | | 833 | aprint_normal("%s", device_xname(self)); |
833 | #endif | | 834 | #endif |
834 | | | 835 | |
835 | intrh = acpi_intr_establish(self, (uint64_t)(uintptr_t)handle, | | 836 | intrh = acpi_intr_establish(self, (uint64_t)(uintptr_t)handle, |
836 | IPL_NET, NOT_MP_SAFE, scx_intr, sc, device_xname(self)); | | 837 | IPL_NET, NOT_MP_SAFE, scx_intr, sc, device_xname(self)); |
837 | if (intrh == NULL) { | | 838 | if (intrh == NULL) { |
838 | aprint_error(": couldn't establish interrupt\n"); | | 839 | aprint_error(": couldn't establish interrupt\n"); |
839 | goto fail_1; | | 840 | goto fail_1; |
840 | } | | 841 | } |
841 | | | 842 | |
842 | sc->sc_dev = self; | | 843 | sc->sc_dev = self; |
843 | sc->sc_st = aa->aa_memt; | | 844 | sc->sc_st = aa->aa_memt; |
844 | sc->sc_sh = bsh; | | 845 | sc->sc_sh = bsh; |
845 | sc->sc_sz = mem->ar_length; | | 846 | sc->sc_sz = mem->ar_length; |
846 | sc->sc_eesh = eebsh; | | 847 | sc->sc_eesh = eebsh; |
847 | sc->sc_eesz = mem1->ar_length; | | 848 | sc->sc_eesz = mem1->ar_length; |
848 | sc->sc_ih = intrh; | | 849 | sc->sc_ih = intrh; |
849 | sc->sc_dmat = | | 850 | sc->sc_dmat = |
850 | BUS_DMA_TAG_VALID(aa->aa_dmat64) ? aa->aa_dmat64 : aa->aa_dmat; | | 851 | BUS_DMA_TAG_VALID(aa->aa_dmat64) ? aa->aa_dmat64 : aa->aa_dmat; |
851 | sc->sc_phy_id = (int)phy_id; | | 852 | sc->sc_phy_id = (int)phy_id; |
852 | sc->sc_freq = phy_freq; | | 853 | sc->sc_freq = phy_freq; |
853 | sc->sc_maxsize = max_frame; | | 854 | sc->sc_maxsize = max_frame; |
854 | | | 855 | |
855 | scx_attach_i(sc); | | 856 | scx_attach_i(sc); |
856 | done: | | 857 | done: |
857 | acpi_resource_cleanup(&res); | | 858 | acpi_resource_cleanup(&res); |
858 | return; | | 859 | return; |
859 | fail_1: | | 860 | fail_1: |
860 | bus_space_unmap(sc->sc_st, sc->sc_eesh, sc->sc_eesz); | | 861 | bus_space_unmap(sc->sc_st, sc->sc_eesh, sc->sc_eesz); |
861 | fail_0: | | 862 | fail_0: |
862 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); | | 863 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); |
863 | acpi_resource_cleanup(&res); | | 864 | acpi_resource_cleanup(&res); |
864 | return; | | 865 | return; |
865 | } | | 866 | } |
866 | | | 867 | |
867 | static void | | 868 | static void |
868 | scx_attach_i(struct scx_softc *sc) | | 869 | scx_attach_i(struct scx_softc *sc) |
869 | { | | 870 | { |
870 | struct ifnet * const ifp = &sc->sc_ethercom.ec_if; | | 871 | struct ifnet * const ifp = &sc->sc_ethercom.ec_if; |
871 | struct mii_data * const mii = &sc->sc_mii; | | 872 | struct mii_data * const mii = &sc->sc_mii; |
872 | struct ifmedia * const ifm = &mii->mii_media; | | 873 | struct ifmedia * const ifm = &mii->mii_media; |
873 | uint32_t which, dwimp, dwfea; | | 874 | uint32_t which, dwimp, dwfea; |
874 | uint8_t enaddr[ETHER_ADDR_LEN]; | | 875 | uint8_t enaddr[ETHER_ADDR_LEN]; |
875 | bus_dma_segment_t seg; | | 876 | bus_dma_segment_t seg; |
876 | paddr_t paddr; | | 877 | paddr_t p, q; |
877 | uint32_t csr; | | 878 | uint32_t csr; |
878 | int i, nseg, error = 0; | | 879 | int i, nseg, error = 0; |
879 | | | 880 | |
880 | which = CSR_READ(sc, HWVER); /* Socionext version 5.xx */ | | 881 | which = CSR_READ(sc, HWVER); /* Socionext version 5.xx */ |
881 | dwimp = mac_read(sc, GMACIMPL); /* DWC implementation XX.YY */ | | 882 | dwimp = mac_read(sc, GMACIMPL); /* DWC implementation XX.YY */ |
882 | dwfea = mac_read(sc, HWFEA); /* DWC feature bits */ | | 883 | dwfea = mac_read(sc, HWFEA); /* DWC feature bits */ |
883 | | | 884 | |
884 | aprint_naive("\n"); | | 885 | aprint_naive("\n"); |
885 | aprint_normal(": Socionext NetSec Gigabit Ethernet controller " | | 886 | aprint_normal(": Socionext NetSec Gigabit Ethernet controller " |
886 | "%x.%x\n", which >> 16, which & 0xffff); | | 887 | "%x.%x\n", which >> 16, which & 0xffff); |
887 | | | 888 | |
888 | aprint_normal_dev(sc->sc_dev, | | 889 | aprint_normal_dev(sc->sc_dev, |
889 | "DesignWare EMAC ver 0x%x (0x%x) hw feature %08x\n", | | 890 | "DesignWare EMAC ver 0x%x (0x%x) hw feature %08x\n", |
890 | dwimp & 0xff, dwimp >> 8, dwfea); | | 891 | dwimp & 0xff, dwimp >> 8, dwfea); |
891 | dump_hwfeature(sc); | | 892 | dump_hwfeature(sc); |
892 | | | 893 | |
893 | /* detected PHY type */ | | 894 | /* detected PHY type */ |
894 | sc->sc_miigmii = ((dwfea & __BITS(30,28) >> 28) == 0); | | 895 | sc->sc_miigmii = ((dwfea & __BITS(30,28) >> 28) == 0); |
895 | | | 896 | |
896 | /* fetch MAC address in flash 0:7, stored in big endian order */ | | 897 | /* fetch MAC address in flash 0:7, stored in big endian order */ |
897 | csr = EE_READ(sc, 0x00); | | 898 | csr = EE_READ(sc, 0x00); |
898 | enaddr[0] = csr >> 24; | | 899 | enaddr[0] = csr >> 24; |
899 | enaddr[1] = csr >> 16; | | 900 | enaddr[1] = csr >> 16; |
900 | enaddr[2] = csr >> 8; | | 901 | enaddr[2] = csr >> 8; |
901 | enaddr[3] = csr; | | 902 | enaddr[3] = csr; |
902 | csr = EE_READ(sc, 0x04); | | 903 | csr = EE_READ(sc, 0x04); |
903 | enaddr[4] = csr >> 24; | | 904 | enaddr[4] = csr >> 24; |
904 | enaddr[5] = csr >> 16; | | 905 | enaddr[5] = csr >> 16; |
905 | aprint_normal_dev(sc->sc_dev, | | 906 | aprint_normal_dev(sc->sc_dev, |
906 | "Ethernet address %s\n", ether_sprintf(enaddr)); | | 907 | "Ethernet address %s\n", ether_sprintf(enaddr)); |
907 | | | 908 | |
908 | sc->sc_mdclk = get_mdioclk(sc->sc_freq) << GAR_CLK; /* 5:2 clk ratio */ | | 909 | sc->sc_mdclk = get_mdioclk(sc->sc_freq) << GAR_CLK; /* 5:2 clk ratio */ |
909 | | | 910 | |
910 | mii->mii_ifp = ifp; | | 911 | mii->mii_ifp = ifp; |
911 | mii->mii_readreg = mii_readreg; | | 912 | mii->mii_readreg = mii_readreg; |
912 | mii->mii_writereg = mii_writereg; | | 913 | mii->mii_writereg = mii_writereg; |
913 | mii->mii_statchg = mii_statchg; | | 914 | mii->mii_statchg = mii_statchg; |
914 | | | 915 | |
915 | sc->sc_ethercom.ec_mii = mii; | | 916 | sc->sc_ethercom.ec_mii = mii; |
916 | ifmedia_init(ifm, 0, ether_mediachange, scx_ifmedia_sts); | | 917 | ifmedia_init(ifm, 0, ether_mediachange, scx_ifmedia_sts); |
917 | mii_attach(sc->sc_dev, mii, 0xffffffff, sc->sc_phy_id, | | 918 | mii_attach(sc->sc_dev, mii, 0xffffffff, sc->sc_phy_id, |
918 | MII_OFFSET_ANY, MIIF_DOPAUSE); | | 919 | MII_OFFSET_ANY, MIIF_DOPAUSE); |
919 | if (LIST_FIRST(&mii->mii_phys) == NULL) { | | 920 | if (LIST_FIRST(&mii->mii_phys) == NULL) { |
920 | ifmedia_add(ifm, IFM_ETHER | IFM_NONE, 0, NULL); | | 921 | ifmedia_add(ifm, IFM_ETHER | IFM_NONE, 0, NULL); |
921 | ifmedia_set(ifm, IFM_ETHER | IFM_NONE); | | 922 | ifmedia_set(ifm, IFM_ETHER | IFM_NONE); |
922 | } else | | 923 | } else |
923 | ifmedia_set(ifm, IFM_ETHER | IFM_AUTO); | | 924 | ifmedia_set(ifm, IFM_ETHER | IFM_AUTO); |
924 | ifm->ifm_media = ifm->ifm_cur->ifm_media; /* as if user has requested */ | | 925 | ifm->ifm_media = ifm->ifm_cur->ifm_media; /* as if user has requested */ |
925 | | | 926 | |
926 | /* | | 927 | /* |
927 | * Allocate the control data structures, and create and load the | | 928 | * Allocate the control data structures, and create and load the |
928 | * DMA map for it. | | 929 | * DMA map for it. |
929 | */ | | 930 | */ |
930 | error = bus_dmamem_alloc(sc->sc_dmat, | | 931 | error = bus_dmamem_alloc(sc->sc_dmat, |
931 | sizeof(struct control_data), PAGE_SIZE, 0, &seg, 1, &nseg, 0); | | 932 | sizeof(struct control_data), PAGE_SIZE, 0, &seg, 1, &nseg, 0); |
932 | if (error != 0) { | | 933 | if (error != 0) { |
933 | aprint_error_dev(sc->sc_dev, | | 934 | aprint_error_dev(sc->sc_dev, |
934 | "unable to allocate control data, error = %d\n", error); | | 935 | "unable to allocate control data, error = %d\n", error); |
935 | goto fail_0; | | 936 | goto fail_0; |
936 | } | | 937 | } |
937 | error = bus_dmamem_map(sc->sc_dmat, &seg, nseg, | | 938 | error = bus_dmamem_map(sc->sc_dmat, &seg, nseg, |
938 | sizeof(struct control_data), (void **)&sc->sc_control_data, | | 939 | sizeof(struct control_data), (void **)&sc->sc_control_data, |
939 | BUS_DMA_COHERENT); | | 940 | BUS_DMA_COHERENT); |
940 | if (error != 0) { | | 941 | if (error != 0) { |
941 | aprint_error_dev(sc->sc_dev, | | 942 | aprint_error_dev(sc->sc_dev, |
942 | "unable to map control data, error = %d\n", error); | | 943 | "unable to map control data, error = %d\n", error); |
943 | goto fail_1; | | 944 | goto fail_1; |
944 | } | | 945 | } |
945 | error = bus_dmamap_create(sc->sc_dmat, | | 946 | error = bus_dmamap_create(sc->sc_dmat, |
946 | sizeof(struct control_data), 1, | | 947 | sizeof(struct control_data), 1, |
947 | sizeof(struct control_data), 0, 0, &sc->sc_cddmamap); | | 948 | sizeof(struct control_data), 0, 0, &sc->sc_cddmamap); |
948 | if (error != 0) { | | 949 | if (error != 0) { |
949 | aprint_error_dev(sc->sc_dev, | | 950 | aprint_error_dev(sc->sc_dev, |
950 | "unable to create control data DMA map, " | | 951 | "unable to create control data DMA map, " |
951 | "error = %d\n", error); | | 952 | "error = %d\n", error); |
952 | goto fail_2; | | 953 | goto fail_2; |
953 | } | | 954 | } |
954 | error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, | | 955 | error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, |
955 | sc->sc_control_data, sizeof(struct control_data), NULL, 0); | | 956 | sc->sc_control_data, sizeof(struct control_data), NULL, 0); |
956 | if (error != 0) { | | 957 | if (error != 0) { |
957 | aprint_error_dev(sc->sc_dev, | | 958 | aprint_error_dev(sc->sc_dev, |
958 | "unable to load control data DMA map, error = %d\n", | | 959 | "unable to load control data DMA map, error = %d\n", |
959 | error); | | 960 | error); |
960 | goto fail_3; | | 961 | goto fail_3; |
961 | } | | 962 | } |
962 | for (i = 0; i < MD_TXQUEUELEN; i++) { | | 963 | for (i = 0; i < MD_TXQUEUELEN; i++) { |
963 | if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, | | 964 | if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, |
964 | MD_NTXSEGS, MCLBYTES, 0, 0, | | 965 | MD_NTXSEGS, MCLBYTES, 0, 0, |
965 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { | | 966 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { |
966 | aprint_error_dev(sc->sc_dev, | | 967 | aprint_error_dev(sc->sc_dev, |
967 | "unable to create tx DMA map %d, error = %d\n", | | 968 | "unable to create tx DMA map %d, error = %d\n", |
968 | i, error); | | 969 | i, error); |
969 | goto fail_4; | | 970 | goto fail_4; |
970 | } | | 971 | } |
971 | } | | 972 | } |
972 | for (i = 0; i < MD_NRXDESC; i++) { | | 973 | for (i = 0; i < MD_NRXDESC; i++) { |
973 | if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, | | 974 | if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, |
974 | 1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { | | 975 | 1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { |
975 | aprint_error_dev(sc->sc_dev, | | 976 | aprint_error_dev(sc->sc_dev, |
976 | "unable to create rx DMA map %d, error = %d\n", | | 977 | "unable to create rx DMA map %d, error = %d\n", |
977 | i, error); | | 978 | i, error); |
978 | goto fail_5; | | 979 | goto fail_5; |
979 | } | | 980 | } |
980 | sc->sc_rxsoft[i].rxs_mbuf = NULL; | | 981 | sc->sc_rxsoft[i].rxs_mbuf = NULL; |
981 | } | | 982 | } |
982 | sc->sc_seg = seg; | | 983 | sc->sc_seg = seg; |
983 | sc->sc_nseg = nseg; | | 984 | sc->sc_nseg = nseg; |
984 | #if 0 | | 985 | #if 0 |
985 | aprint_normal_dev(sc->sc_dev, "descriptor ds_addr %lx, ds_len %lx, nseg %d\n", seg.ds_addr, seg.ds_len, nseg); | | 986 | aprint_normal_dev(sc->sc_dev, "descriptor ds_addr %lx, ds_len %lx, nseg %d\n", seg.ds_addr, seg.ds_len, nseg); |
986 | #endif | | 987 | #endif |
987 | strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); | | 988 | strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); |
988 | ifp->if_softc = sc; | | 989 | ifp->if_softc = sc; |
989 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | | 990 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; |
990 | ifp->if_ioctl = scx_ioctl; | | 991 | ifp->if_ioctl = scx_ioctl; |
991 | ifp->if_start = scx_start; | | 992 | ifp->if_start = scx_start; |
992 | ifp->if_watchdog = scx_watchdog; | | 993 | ifp->if_watchdog = scx_watchdog; |
993 | ifp->if_init = scx_init; | | 994 | ifp->if_init = scx_init; |
994 | ifp->if_stop = scx_stop; | | 995 | ifp->if_stop = scx_stop; |
995 | IFQ_SET_READY(&ifp->if_snd); | | 996 | IFQ_SET_READY(&ifp->if_snd); |
996 | | | 997 | |
997 | /* 802.1Q VLAN-sized frames, and 9000 jumbo frame are supported */ | | 998 | /* 802.1Q VLAN-sized frames, and 9000 jumbo frame are supported */ |
998 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; | | 999 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; |
999 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU; | | 1000 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU; |
1000 | | | 1001 | |
1001 | sc->sc_flowflags = 0; /* track PAUSE flow caps */ | | 1002 | sc->sc_flowflags = 0; /* track PAUSE flow caps */ |
1002 | | | 1003 | |
1003 | if_attach(ifp); | | 1004 | if_attach(ifp); |
1004 | if_deferred_start_init(ifp, NULL); | | 1005 | if_deferred_start_init(ifp, NULL); |
1005 | ether_ifattach(ifp, enaddr); | | 1006 | ether_ifattach(ifp, enaddr); |
1006 | | | 1007 | |
1007 | callout_init(&sc->sc_callout, 0); | | 1008 | callout_init(&sc->sc_callout, 0); |
1008 | callout_setfunc(&sc->sc_callout, phy_tick, sc); | | 1009 | callout_setfunc(&sc->sc_callout, phy_tick, sc); |
1009 | | | 1010 | |
1010 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | | 1011 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), |
1011 | RND_TYPE_NET, RND_FLAG_DEFAULT); | | 1012 | RND_TYPE_NET, RND_FLAG_DEFAULT); |
1012 | | | 1013 | |
1013 | stopuengine(sc); | | 1014 | resetuengine(sc); |
1014 | loaducode(sc); | | 1015 | loaducode(sc); |
1015 | | | 1016 | |
1016 | /* feed NetSec descriptor array base addresses and timer value */ | | 1017 | /* feed NetSec descriptor array base addresses and timer value */ |
1017 | paddr = SCX_CDTXADDR(sc, 0); /* tdes array (ring#0) */ | | 1018 | p = SCX_CDTXADDR(sc, 0); /* tdes array (ring#0) */ |
1018 | CSR_WRITE(sc, TDBA_HI, BUS_ADDR_HI32(paddr)); | | 1019 | q = SCX_CDRXADDR(sc, 0); /* rdes array (ring#1) */ |
1019 | CSR_WRITE(sc, TDBA_LO, BUS_ADDR_LO32(paddr)); | | 1020 | CSR_WRITE(sc, TDBA_LO, BUS_ADDR_LO32(p)); |
1020 | paddr = SCX_CDRXADDR(sc, 0); /* rdes array (ring#1) */ | | 1021 | CSR_WRITE(sc, TDBA_HI, BUS_ADDR_HI32(p)); |
1021 | CSR_WRITE(sc, RDBA_HI, BUS_ADDR_HI32(paddr)); | | 1022 | CSR_WRITE(sc, RDBA_LO, BUS_ADDR_LO32(q)); |
1022 | CSR_WRITE(sc, RDBA_LO, BUS_ADDR_LO32(paddr)); | | 1023 | CSR_WRITE(sc, RDBA_HI, BUS_ADDR_HI32(q)); |
1023 | CSR_WRITE(sc, TXCONF, DESCNF_LE); /* little endian */ | | 1024 | CSR_WRITE(sc, TXCONF, DESCNF_LE); /* little endian */ |
1024 | CSR_WRITE(sc, RXCONF, DESCNF_LE); /* little endian */ | | 1025 | CSR_WRITE(sc, RXCONF, DESCNF_LE); /* little endian */ |
1025 | CSR_WRITE(sc, DMACTL_TMR, sc->sc_freq / 1000000 - 1); | | 1026 | CSR_WRITE(sc, DMACTL_TMR, sc->sc_freq / 1000000 - 1); |
1026 | | | 1027 | |
1027 | startuengine(sc); | | 1028 | CSR_WRITE(sc, DMACTL_M2H, M2H_MODE_TRANS); |
| | | 1029 | CSR_WRITE(sc, PKTCTRL, MODENRM); /* change to use normal mode */ |
| | | 1030 | WAIT_FOR_SET(sc, MODE_TRANS, T2N_DONE); |
| | | 1031 | /* do { |
| | | 1032 | csr = CSR_READ(sc, MODE_TRANS); |
| | | 1033 | } while ((csr & T2N_DONE) == 0); */ |
| | | 1034 | |
| | | 1035 | CSR_WRITE(sc, TXISR, ~0); /* clear pending emtpry/error irq */ |
| | | 1036 | CSR_WRITE(sc, xINTAE_CLR, ~0); /* disable tx / rx interrupts */ |
1028 | | | 1037 | |
1029 | return; | | 1038 | return; |
1030 | | | 1039 | |
1031 | fail_5: | | 1040 | fail_5: |
1032 | for (i = 0; i < MD_NRXDESC; i++) { | | 1041 | for (i = 0; i < MD_NRXDESC; i++) { |
1033 | if (sc->sc_rxsoft[i].rxs_dmamap != NULL) | | 1042 | if (sc->sc_rxsoft[i].rxs_dmamap != NULL) |
1034 | bus_dmamap_destroy(sc->sc_dmat, | | 1043 | bus_dmamap_destroy(sc->sc_dmat, |
1035 | sc->sc_rxsoft[i].rxs_dmamap); | | 1044 | sc->sc_rxsoft[i].rxs_dmamap); |
1036 | } | | 1045 | } |
1037 | fail_4: | | 1046 | fail_4: |
1038 | for (i = 0; i < MD_TXQUEUELEN; i++) { | | 1047 | for (i = 0; i < MD_TXQUEUELEN; i++) { |
1039 | if (sc->sc_txsoft[i].txs_dmamap != NULL) | | 1048 | if (sc->sc_txsoft[i].txs_dmamap != NULL) |
1040 | bus_dmamap_destroy(sc->sc_dmat, | | 1049 | bus_dmamap_destroy(sc->sc_dmat, |
1041 | sc->sc_txsoft[i].txs_dmamap); | | 1050 | sc->sc_txsoft[i].txs_dmamap); |
1042 | } | | 1051 | } |
1043 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); | | 1052 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); |
1044 | fail_3: | | 1053 | fail_3: |
1045 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); | | 1054 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); |
1046 | fail_2: | | 1055 | fail_2: |
1047 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, | | 1056 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, |
1048 | sizeof(struct control_data)); | | 1057 | sizeof(struct control_data)); |
1049 | fail_1: | | 1058 | fail_1: |
1050 | bus_dmamem_free(sc->sc_dmat, &seg, nseg); | | 1059 | bus_dmamem_free(sc->sc_dmat, &seg, nseg); |
1051 | fail_0: | | 1060 | fail_0: |
1052 | if (sc->sc_phandle) | | 1061 | if (sc->sc_phandle) |
1053 | fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih); | | 1062 | fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_ih); |
1054 | else | | 1063 | else |
1055 | acpi_intr_disestablish(sc->sc_ih); | | 1064 | acpi_intr_disestablish(sc->sc_ih); |
1056 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); | | 1065 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); |
1057 | return; | | 1066 | return; |
1058 | } | | 1067 | } |
1059 | | | 1068 | |
1060 | static void | | 1069 | static void |
1061 | scx_reset(struct scx_softc *sc) | | 1070 | scx_reset(struct scx_softc *sc) |
1062 | { | | 1071 | { |
1063 | int loop = 0, busy; | | 1072 | int loop = 0, busy; |
1064 | | | 1073 | |
1065 | mac_write(sc, GMACOMR, 0); | | 1074 | mac_write(sc, GMACOMR, 0); |
1066 | mac_write(sc, GMACBMR, BMR_RST); | | 1075 | mac_write(sc, GMACBMR, BMR_RST); |
1067 | do { | | 1076 | do { |
1068 | DELAY(1); | | 1077 | DELAY(1); |
1069 | busy = mac_read(sc, GMACBMR) & BMR_RST; | | 1078 | busy = mac_read(sc, GMACBMR) & BMR_RST; |
1070 | } while (++loop < 3000 && busy); | | 1079 | } while (++loop < 3000 && busy); |
1071 | mac_write(sc, GMACBMR, _BMR); | | 1080 | mac_write(sc, GMACBMR, _BMR); |
1072 | mac_write(sc, GMACAFR, 0); | | 1081 | mac_write(sc, GMACAFR, 0); |
| | | 1082 | } |
1073 | | | 1083 | |
1074 | #if 0 | | 1084 | static void |
1075 | CSR_WRITE(sc, CLKEN, CLK_ALL); /* distribute clock sources */ | | 1085 | scx_stop(struct ifnet *ifp, int disable) |
1076 | CSR_WRITE(sc, SWRESET, 0); /* reset operation */ | | 1086 | { |
1077 | CSR_WRITE(sc, SWRESET, SRST_RUN); /* manifest run */ | | 1087 | struct scx_softc *sc = ifp->if_softc; |
1078 | CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS); | | 1088 | uint32_t csr; |
1079 | WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS), 0); | | | |
1080 | | | 1089 | |
1081 | CSR_WRITE(sc, TXISR, ~0); | | 1090 | /* Stop the one second clock. */ |
| | | 1091 | callout_stop(&sc->sc_callout); |
| | | 1092 | |
| | | 1093 | /* Down the MII. */ |
| | | 1094 | mii_down(&sc->sc_mii); |
| | | 1095 | |
| | | 1096 | /* Mark the interface down and cancel the watchdog timer. */ |
| | | 1097 | ifp->if_flags &= ~IFF_RUNNING; |
| | | 1098 | ifp->if_timer = 0; |
| | | 1099 | |
| | | 1100 | CSR_WRITE(sc, RXIE_CLR, ~0); |
| | | 1101 | CSR_WRITE(sc, TXIE_CLR, ~0); |
1082 | CSR_WRITE(sc, xINTAE_CLR, ~0); | | 1102 | CSR_WRITE(sc, xINTAE_CLR, ~0); |
1083 | #endif | | 1103 | CSR_WRITE(sc, TXISR, ~0); |
| | | 1104 | CSR_WRITE(sc, RXISR, ~0); |
| | | 1105 | |
| | | 1106 | csr = mac_read(sc, GMACOMR); |
| | | 1107 | mac_write(sc, GMACOMR, csr &~ (OMR_SR | OMR_ST)); |
1084 | } | | 1108 | } |
1085 | | | 1109 | |
1086 | static int | | 1110 | static int |
1087 | scx_init(struct ifnet *ifp) | | 1111 | scx_init(struct ifnet *ifp) |
1088 | { | | 1112 | { |
1089 | struct scx_softc *sc = ifp->if_softc; | | 1113 | struct scx_softc *sc = ifp->if_softc; |
1090 | const uint8_t *ea = CLLADDR(ifp->if_sadl); | | 1114 | const uint8_t *ea = CLLADDR(ifp->if_sadl); |
1091 | uint32_t csr; | | 1115 | uint32_t csr; |
1092 | int i, error; | | 1116 | int i, error; |
1093 | | | 1117 | |
1094 | /* Cancel pending I/O. */ | | 1118 | /* Cancel pending I/O. */ |
1095 | scx_stop(ifp, 0); | | 1119 | scx_stop(ifp, 0); |
1096 | | | 1120 | |
1097 | /* Reset the chip to a known state. */ | | 1121 | /* Reset the chip to a known state. */ |
1098 | scx_reset(sc); | | 1122 | scx_reset(sc); |
1099 | | | 1123 | |
1100 | /* build sane Tx */ | | 1124 | /* build sane Tx */ |
1101 | memset(sc->sc_txdescs, 0, sizeof(struct tdes) * MD_NTXDESC); | | 1125 | memset(sc->sc_txdescs, 0, sizeof(struct tdes) * MD_NTXDESC); |
1102 | sc->sc_txdescs[MD_NTXDESC - 1].t0 = T0_LD; /* tie off the ring */ | | 1126 | sc->sc_txdescs[MD_NTXDESC - 1].t0 = T0_LD; /* tie off the ring */ |
1103 | SCX_CDTXSYNC(sc, 0, MD_NTXDESC, | | 1127 | SCX_CDTXSYNC(sc, 0, MD_NTXDESC, |
1104 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | | 1128 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
1105 | sc->sc_txfree = MD_NTXDESC; | | 1129 | sc->sc_txfree = MD_NTXDESC; |
1106 | sc->sc_txnext = 0; | | 1130 | sc->sc_txnext = 0; |
1107 | for (i = 0; i < MD_TXQUEUELEN; i++) | | 1131 | for (i = 0; i < MD_TXQUEUELEN; i++) |
1108 | sc->sc_txsoft[i].txs_mbuf = NULL; | | 1132 | sc->sc_txsoft[i].txs_mbuf = NULL; |
1109 | sc->sc_txsfree = MD_TXQUEUELEN; | | 1133 | sc->sc_txsfree = MD_TXQUEUELEN; |
1110 | sc->sc_txsnext = 0; | | 1134 | sc->sc_txsnext = 0; |
1111 | sc->sc_txsdirty = 0; | | 1135 | sc->sc_txsdirty = 0; |
1112 | | | 1136 | |
1113 | /* load Rx descriptors with fresh mbuf */ | | 1137 | /* load Rx descriptors with fresh mbuf */ |
1114 | for (i = 0; i < MD_NRXDESC; i++) { | | 1138 | for (i = 0; i < MD_NRXDESC; i++) { |
1115 | if (sc->sc_rxsoft[i].rxs_mbuf == NULL) { | | 1139 | if (sc->sc_rxsoft[i].rxs_mbuf == NULL) { |
1116 | if ((error = add_rxbuf(sc, i)) != 0) { | | 1140 | if ((error = add_rxbuf(sc, i)) != 0) { |
1117 | aprint_error_dev(sc->sc_dev, | | 1141 | aprint_error_dev(sc->sc_dev, |
1118 | "unable to allocate or map rx " | | 1142 | "unable to allocate or map rx " |
1119 | "buffer %d, error = %d\n", | | 1143 | "buffer %d, error = %d\n", |
1120 | i, error); | | 1144 | i, error); |
1121 | rxdrain(sc); | | 1145 | rxdrain(sc); |
1122 | goto out; | | 1146 | goto out; |
1123 | } | | 1147 | } |
1124 | } | | 1148 | } |
1125 | else | | 1149 | else |
1126 | SCX_INIT_RXDESC(sc, i); | | 1150 | SCX_INIT_RXDESC(sc, i); |
1127 | } | | 1151 | } |
1128 | sc->sc_rxdescs[MD_NRXDESC - 1].r0 = R0_LD; /* tie off the ring */ | | 1152 | sc->sc_rxdescs[MD_NRXDESC - 1].r0 = R0_LD; /* tie off the ring */ |
1129 | sc->sc_rxptr = 0; | | 1153 | sc->sc_rxptr = 0; |
1130 | | | 1154 | |
1131 | /* set my address in perfect match slot 0. little endian order */ | | 1155 | /* set my address in perfect match slot 0. little endian order */ |
1132 | csr = (ea[3] << 24) | (ea[2] << 16) | (ea[1] << 8) | ea[0]; | | 1156 | csr = (ea[3] << 24) | (ea[2] << 16) | (ea[1] << 8) | ea[0]; |
1133 | mac_write(sc, GMACMAL0, csr); | | 1157 | mac_write(sc, GMACMAL0, csr); |
1134 | csr = (ea[5] << 8) | ea[4]; | | 1158 | csr = (ea[5] << 8) | ea[4]; |
1135 | mac_write(sc, GMACMAH0, csr); | | 1159 | mac_write(sc, GMACMAH0, csr); |
1136 | | | 1160 | |
1137 | /* accept multicast frame or run promisc mode */ | | 1161 | /* accept multicast frame or run promisc mode */ |
1138 | scx_set_rcvfilt(sc); | | 1162 | scx_set_rcvfilt(sc); |
1139 | | | 1163 | |
1140 | /* set current media */ | | 1164 | /* set current media */ |
1141 | if ((error = ether_mediachange(ifp)) != 0) | | 1165 | if ((error = ether_mediachange(ifp)) != 0) |
1142 | goto out; | | 1166 | goto out; |
1143 | | | 1167 | |
1144 | CSR_WRITE(sc, DESC_SRST, 01); | | 1168 | CSR_WRITE(sc, DESC_SRST, 01); |
1145 | WAIT_FOR_CLR(sc, DESC_SRST, 01, 0); | | 1169 | WAIT_FOR_CLR(sc, DESC_SRST, 01); |
1146 | | | 1170 | |
1147 | CSR_WRITE(sc, DESC_INIT, 01); | | 1171 | CSR_WRITE(sc, DESC_INIT, 01); |
1148 | WAIT_FOR_CLR(sc, DESC_INIT, 01, 0); | | 1172 | WAIT_FOR_CLR(sc, DESC_INIT, 01); |
1149 | | | 1173 | |
1150 | /* feed local memory descriptor array base addresses */ | | 1174 | /* feed local memory descriptor array base addresses */ |
1151 | mac_write(sc, GMACRDLA, _RDLA); /* GMAC rdes store */ | | 1175 | mac_write(sc, GMACRDLA, _RDLA); /* GMAC rdes store */ |
1152 | mac_write(sc, GMACTDLA, _TDLA); /* GMAC tdes store */ | | 1176 | mac_write(sc, GMACTDLA, _TDLA); /* GMAC tdes store */ |
1153 | | | 1177 | |
1154 | CSR_WRITE(sc, FLOWTHR, (48<<16) | 36); /* pause|resume threshold */ | | 1178 | CSR_WRITE(sc, FLOWTHR, (48<<16) | 36); /* pause|resume threshold */ |
1155 | mac_write(sc, GMACFCR, 256 << 16); /* 31:16 pause value */ | | 1179 | mac_write(sc, GMACFCR, 256 << 16); /* 31:16 pause value */ |
1156 | | | 1180 | |
1157 | CSR_WRITE(sc, RXIE_CLR, ~0); /* clear Rx interrupt enable */ | | 1181 | CSR_WRITE(sc, INTF_SEL, sc->sc_miigmii ? INTF_GMII : INTF_RGMII); |
1158 | CSR_WRITE(sc, TXIE_CLR, ~0); /* clear Tx interrupt enable */ | | | |
1159 | | | 1182 | |
1160 | CSR_WRITE(sc, RXCLSCMAX, 8); /* Rx coalesce upper bound */ | | 1183 | CSR_WRITE(sc, RXCOALESC, 8); /* Rx coalesce bound */ |
1161 | CSR_WRITE(sc, TXCLSCMAX, 8); /* Tx coalesce upper bound */ | | 1184 | CSR_WRITE(sc, TXCOALESC, 8); /* Tx coalesce bound */ |
1162 | CSR_WRITE(sc, RXITIMER, 500); /* Rx co. timer usec */ | | 1185 | CSR_WRITE(sc, RCLSCTIME, 500|(1U<<31)); /* Rx co. guard time usec */ |
1163 | CSR_WRITE(sc, TXITIMER, 500); /* Tx co. timer usec */ | | 1186 | CSR_WRITE(sc, TCLSCTIME, 500|(1U<<31)); /* Tx co. guard time usec */ |
1164 | | | 1187 | |
1165 | CSR_WRITE(sc, RXIE_SET, RXI_RC_ERR | RXI_PKTCNT | RXI_TMREXP); | | 1188 | CSR_WRITE(sc, RXIE_SET, RXI_RC_ERR | RXI_PKTCNT | RXI_TMREXP); |
1166 | CSR_WRITE(sc, TXIE_SET, TXI_TR_ERR | TXI_TXDONE | TXI_TMREXP); | | 1189 | CSR_WRITE(sc, TXIE_SET, TXI_TR_ERR | TXI_TXDONE | TXI_TMREXP); |
1167 | | | | |
1168 | CSR_WRITE(sc, xINTAE_SET, IRQ_RX | IRQ_TX); | | 1190 | CSR_WRITE(sc, xINTAE_SET, IRQ_RX | IRQ_TX); |
1169 | #if 1 | | 1191 | #if 1 |
1170 | /* clear event counters, auto-zero after every read */ | | 1192 | /* clear event counters, auto-zero after every read */ |
1171 | mac_write(sc, GMACEVCTL, EVC_CR /* | EVC_ROR */); | | 1193 | mac_write(sc, GMACEVCTL, EVC_CR | EVC_ROR); |
1172 | #endif | | 1194 | #endif |
1173 | /* kick to start GMAC engine */ | | 1195 | /* kick to start GMAC engine */ |
1174 | csr = mac_read(sc, GMACOMR); | | 1196 | csr = mac_read(sc, GMACOMR); |
1175 | mac_write(sc, GMACOMR, csr | OMR_SR | OMR_ST); | | 1197 | mac_write(sc, GMACOMR, csr | OMR_SR | OMR_ST); |
1176 | | | 1198 | |
1177 | ifp->if_flags |= IFF_RUNNING; | | 1199 | ifp->if_flags |= IFF_RUNNING; |
1178 | | | 1200 | |
1179 | /* start one second timer */ | | 1201 | /* start one second timer */ |
1180 | callout_schedule(&sc->sc_callout, hz); | | 1202 | callout_schedule(&sc->sc_callout, hz); |
1181 | out: | | 1203 | out: |
1182 | return error; | | 1204 | return error; |
1183 | } | | 1205 | } |
1184 | | | 1206 | |
1185 | static void | | | |
1186 | scx_stop(struct ifnet *ifp, int disable) | | | |
1187 | { | | | |
1188 | struct scx_softc *sc = ifp->if_softc; | | | |
1189 | | | | |
1190 | /* Stop the one second clock. */ | | | |
1191 | callout_stop(&sc->sc_callout); | | | |
1192 | | | | |
1193 | /* Down the MII. */ | | | |
1194 | mii_down(&sc->sc_mii); | | | |
1195 | | | | |
1196 | /* Mark the interface down and cancel the watchdog timer. */ | | | |
1197 | ifp->if_flags &= ~IFF_RUNNING; | | | |
1198 | ifp->if_timer = 0; | | | |
1199 | | | | |
1200 | CSR_WRITE(sc, xINTAE_CLR, ~0); | | | |
1201 | CSR_WRITE(sc, TXISR, ~0); | | | |
1202 | CSR_WRITE(sc, RXISR, ~0); | | | |
1203 | } | | | |
1204 | | | | |
1205 | static int | | 1207 | static int |
1206 | scx_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 1208 | scx_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1207 | { | | 1209 | { |
1208 | struct scx_softc *sc = ifp->if_softc; | | 1210 | struct scx_softc *sc = ifp->if_softc; |
1209 | struct ifreq *ifr = (struct ifreq *)data; | | 1211 | struct ifreq *ifr = (struct ifreq *)data; |
1210 | struct ifmedia *ifm = &sc->sc_mii.mii_media; | | 1212 | struct ifmedia *ifm = &sc->sc_mii.mii_media; |
1211 | int s, error; | | 1213 | int s, error; |
1212 | | | 1214 | |
1213 | s = splnet(); | | 1215 | s = splnet(); |
1214 | | | 1216 | |
1215 | switch (cmd) { | | 1217 | switch (cmd) { |
1216 | case SIOCSIFMEDIA: | | 1218 | case SIOCSIFMEDIA: |
1217 | /* Flow control requires full-duplex mode. */ | | 1219 | /* Flow control requires full-duplex mode. */ |
1218 | if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO || | | 1220 | if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO || |
1219 | (ifr->ifr_media & IFM_FDX) == 0) | | 1221 | (ifr->ifr_media & IFM_FDX) == 0) |
1220 | ifr->ifr_media &= ~IFM_ETH_FMASK; | | 1222 | ifr->ifr_media &= ~IFM_ETH_FMASK; |
1221 | if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) { | | 1223 | if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) { |
1222 | if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) { | | 1224 | if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) { |
1223 | /* We can do both TXPAUSE and RXPAUSE. */ | | 1225 | /* We can do both TXPAUSE and RXPAUSE. */ |
1224 | ifr->ifr_media |= | | 1226 | ifr->ifr_media |= |
1225 | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE; | | 1227 | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE; |
1226 | } | | 1228 | } |
1227 | sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK; | | 1229 | sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK; |
1228 | } | | 1230 | } |
1229 | error = ifmedia_ioctl(ifp, ifr, ifm, cmd); | | 1231 | error = ifmedia_ioctl(ifp, ifr, ifm, cmd); |
1230 | break; | | 1232 | break; |
1231 | default: | | 1233 | default: |
1232 | error = ether_ioctl(ifp, cmd, data); | | 1234 | error = ether_ioctl(ifp, cmd, data); |
1233 | if (error != ENETRESET) | | 1235 | if (error != ENETRESET) |
1234 | break; | | 1236 | break; |
1235 | error = 0; | | 1237 | error = 0; |
1236 | if (cmd == SIOCSIFCAP) | | 1238 | if (cmd == SIOCSIFCAP) |
1237 | error = if_init(ifp); | | 1239 | error = if_init(ifp); |
1238 | if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI) | | 1240 | if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI) |
1239 | ; | | 1241 | ; |
1240 | else if (ifp->if_flags & IFF_RUNNING) { | | 1242 | else if (ifp->if_flags & IFF_RUNNING) { |
1241 | /* | | 1243 | /* |
1242 | * Multicast list has changed; set the hardware filter | | 1244 | * Multicast list has changed; set the hardware filter |
1243 | * accordingly. | | 1245 | * accordingly. |
1244 | */ | | 1246 | */ |
1245 | scx_set_rcvfilt(sc); | | 1247 | scx_set_rcvfilt(sc); |
1246 | } | | 1248 | } |
1247 | break; | | 1249 | break; |
1248 | } | | 1250 | } |
1249 | | | 1251 | |
1250 | splx(s); | | 1252 | splx(s); |
1251 | return error; | | 1253 | return error; |
1252 | } | | 1254 | } |
1253 | | | 1255 | |
1254 | static uint32_t | | 1256 | static uint32_t |
1255 | bit_reverse_32(uint32_t x) | | 1257 | bit_reverse_32(uint32_t x) |
1256 | { | | 1258 | { |
1257 | x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); | | 1259 | x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); |
1258 | x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); | | 1260 | x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); |
1259 | x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); | | 1261 | x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); |
1260 | x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); | | 1262 | x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); |
1261 | return (x >> 16) | (x << 16); | | 1263 | return (x >> 16) | (x << 16); |
1262 | } | | 1264 | } |
1263 | | | 1265 | |
1264 | #define MCAST_DEBUG 0 | | 1266 | #define MCAST_DEBUG 0 |
1265 | | | 1267 | |
1266 | static void | | 1268 | static void |
1267 | scx_set_rcvfilt(struct scx_softc *sc) | | 1269 | scx_set_rcvfilt(struct scx_softc *sc) |
1268 | { | | 1270 | { |
1269 | struct ethercom * const ec = &sc->sc_ethercom; | | 1271 | struct ethercom * const ec = &sc->sc_ethercom; |
1270 | struct ifnet * const ifp = &ec->ec_if; | | 1272 | struct ifnet * const ifp = &ec->ec_if; |
1271 | struct ether_multistep step; | | 1273 | struct ether_multistep step; |
1272 | struct ether_multi *enm; | | 1274 | struct ether_multi *enm; |
1273 | uint32_t mchash[2]; /* 2x 32 = 64 bit */ | | 1275 | uint32_t mchash[2]; /* 2x 32 = 64 bit */ |
1274 | uint32_t csr, crc; | | 1276 | uint32_t csr, crc; |
1275 | int i; | | 1277 | int i; |
1276 | | | 1278 | |
1277 | csr = mac_read(sc, GMACAFR); | | 1279 | csr = mac_read(sc, GMACAFR); |
1278 | csr &= ~(AFR_PR | AFR_PM | AFR_MHTE | AFR_HPF); | | 1280 | csr &= ~(AFR_PR | AFR_PM | AFR_MHTE | AFR_HPF); |
1279 | mac_write(sc, GMACAFR, csr); | | 1281 | mac_write(sc, GMACAFR, csr); |
1280 | | | 1282 | |
1281 | /* clear 15 entry supplemental perfect match filter */ | | 1283 | /* clear 15 entry supplemental perfect match filter */ |
1282 | for (i = 1; i < 16; i++) | | 1284 | for (i = 1; i < 16; i++) |
1283 | mac_write(sc, GMACMAH(i), 0); | | 1285 | mac_write(sc, GMACMAH(i), 0); |
1284 | /* build 64 bit multicast hash filter */ | | 1286 | /* build 64 bit multicast hash filter */ |
1285 | crc = mchash[1] = mchash[0] = 0; | | 1287 | crc = mchash[1] = mchash[0] = 0; |
1286 | | | 1288 | |
1287 | ETHER_LOCK(ec); | | 1289 | ETHER_LOCK(ec); |
1288 | if (ifp->if_flags & IFF_PROMISC) { | | 1290 | if (ifp->if_flags & IFF_PROMISC) { |
1289 | ec->ec_flags |= ETHER_F_ALLMULTI; | | 1291 | ec->ec_flags |= ETHER_F_ALLMULTI; |
1290 | ETHER_UNLOCK(ec); | | 1292 | ETHER_UNLOCK(ec); |
1291 | /* run promisc. mode */ | | 1293 | /* run promisc. mode */ |
1292 | csr |= AFR_PR; | | 1294 | csr |= AFR_PR; |
1293 | goto update; | | 1295 | goto update; |
1294 | } | | 1296 | } |
1295 | ec->ec_flags &= ~ETHER_F_ALLMULTI; | | 1297 | ec->ec_flags &= ~ETHER_F_ALLMULTI; |
1296 | ETHER_FIRST_MULTI(step, ec, enm); | | 1298 | ETHER_FIRST_MULTI(step, ec, enm); |
1297 | i = 1; /* slot 0 is occupied */ | | 1299 | i = 1; /* slot 0 is occupied */ |
1298 | while (enm != NULL) { | | 1300 | while (enm != NULL) { |
1299 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { | | 1301 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { |
1300 | /* | | 1302 | /* |
1301 | * We must listen to a range of multicast addresses. | | 1303 | * We must listen to a range of multicast addresses. |
1302 | * For now, just accept all multicasts, rather than | | 1304 | * For now, just accept all multicasts, rather than |
1303 | * trying to set only those filter bits needed to match | | 1305 | * trying to set only those filter bits needed to match |
1304 | * the range. (At this time, the only use of address | | 1306 | * the range. (At this time, the only use of address |
1305 | * ranges is for IP multicast routing, for which the | | 1307 | * ranges is for IP multicast routing, for which the |
1306 | * range is big enough to require all bits set.) | | 1308 | * range is big enough to require all bits set.) |
1307 | */ | | 1309 | */ |
1308 | ec->ec_flags |= ETHER_F_ALLMULTI; | | 1310 | ec->ec_flags |= ETHER_F_ALLMULTI; |
1309 | ETHER_UNLOCK(ec); | | 1311 | ETHER_UNLOCK(ec); |
1310 | /* accept all multi */ | | 1312 | /* accept all multi */ |
1311 | csr |= AFR_PM; | | 1313 | csr |= AFR_PM; |
1312 | goto update; | | 1314 | goto update; |
1313 | } | | 1315 | } |
1314 | #if MCAST_DEBUG == 1 | | 1316 | #if MCAST_DEBUG == 1 |
1315 | aprint_normal_dev(sc->sc_dev, "[%d] %s\n", i, ether_sprintf(enm->enm_addrlo)); | | 1317 | aprint_normal_dev(sc->sc_dev, "[%d] %s\n", i, ether_sprintf(enm->enm_addrlo)); |
1316 | #endif | | 1318 | #endif |
1317 | if (i < 16) { | | 1319 | if (i < 16) { |
1318 | /* use 15 entry perfect match filter */ | | 1320 | /* use 15 entry perfect match filter */ |
1319 | uint32_t addr; | | 1321 | uint32_t addr; |
1320 | uint8_t *ep = enm->enm_addrlo; | | 1322 | uint8_t *ep = enm->enm_addrlo; |
1321 | addr = (ep[3] << 24) | (ep[2] << 16) | | 1323 | addr = (ep[3] << 24) | (ep[2] << 16) |
1322 | | (ep[1] << 8) | ep[0]; | | 1324 | | (ep[1] << 8) | ep[0]; |
1323 | mac_write(sc, GMACMAL(i), addr); | | 1325 | mac_write(sc, GMACMAL(i), addr); |
1324 | addr = (ep[5] << 8) | ep[4]; | | 1326 | addr = (ep[5] << 8) | ep[4]; |
1325 | mac_write(sc, GMACMAH(i), addr | 1U<<31); | | 1327 | mac_write(sc, GMACMAH(i), addr | 1U<<31); |
1326 | } else { | | 1328 | } else { |
1327 | /* use hash table when too many */ | | 1329 | /* use hash table when too many */ |
1328 | crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); | | 1330 | crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); |
1329 | crc = bit_reverse_32(~crc); | | 1331 | crc = bit_reverse_32(~crc); |
1330 | /* 1(31) 5(30:26) bit sampling */ | | 1332 | /* 1(31) 5(30:26) bit sampling */ |
1331 | mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); | | 1333 | mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); |
1332 | } | | 1334 | } |
1333 | ETHER_NEXT_MULTI(step, enm); | | 1335 | ETHER_NEXT_MULTI(step, enm); |
1334 | i++; | | 1336 | i++; |
1335 | } | | 1337 | } |
1336 | ETHER_UNLOCK(ec); | | 1338 | ETHER_UNLOCK(ec); |
1337 | if (crc) | | 1339 | if (crc) |
1338 | csr |= AFR_MHTE; | | 1340 | csr |= AFR_MHTE; /* use mchash[] */ |
1339 | csr |= AFR_HPF; /* use hash+perfect */ | | 1341 | csr |= AFR_HPF; /* use perfect match as well */ |
| | | 1342 | update: |
1340 | mac_write(sc, GMACMHTH, mchash[1]); | | 1343 | mac_write(sc, GMACMHTH, mchash[1]); |
1341 | mac_write(sc, GMACMHTL, mchash[0]); | | 1344 | mac_write(sc, GMACMHTL, mchash[0]); |
1342 | update: | | | |
1343 | /* With PR or PM, MHTE/MHTL/MHTH are never consulted. really? */ | | | |
1344 | mac_write(sc, GMACAFR, csr); | | 1345 | mac_write(sc, GMACAFR, csr); |
1345 | return; | | 1346 | return; |
1346 | } | | 1347 | } |
1347 | | | 1348 | |
1348 | static void | | 1349 | static void |
1349 | scx_start(struct ifnet *ifp) | | 1350 | scx_start(struct ifnet *ifp) |
1350 | { | | 1351 | { |
1351 | struct scx_softc *sc = ifp->if_softc; | | 1352 | struct scx_softc *sc = ifp->if_softc; |
1352 | struct mbuf *m0; | | 1353 | struct mbuf *m0; |
1353 | struct scx_txsoft *txs; | | 1354 | struct scx_txsoft *txs; |
1354 | bus_dmamap_t dmamap; | | 1355 | bus_dmamap_t dmamap; |
1355 | int error, nexttx, lasttx, ofree, seg; | | 1356 | int error, nexttx, lasttx, ofree, seg; |
1356 | uint32_t tdes0; | | 1357 | uint32_t tdes0; |
1357 | | | 1358 | |
1358 | if ((ifp->if_flags & IFF_RUNNING) == 0) | | 1359 | if ((ifp->if_flags & IFF_RUNNING) == 0) |
1359 | return; | | 1360 | return; |
1360 | | | 1361 | |
1361 | /* Remember the previous number of free descriptors. */ | | 1362 | /* Remember the previous number of free descriptors. */ |
1362 | ofree = sc->sc_txfree; | | 1363 | ofree = sc->sc_txfree; |
1363 | | | | |
1364 | /* | | 1364 | /* |
1365 | * Loop through the send queue, setting up transmit descriptors | | 1365 | * Loop through the send queue, setting up transmit descriptors |
1366 | * until we drain the queue, or use up all available transmit | | 1366 | * until we drain the queue, or use up all available transmit |
1367 | * descriptors. | | 1367 | * descriptors. |
1368 | */ | | 1368 | */ |
1369 | for (;;) { | | 1369 | for (;;) { |
1370 | IFQ_POLL(&ifp->if_snd, m0); | | 1370 | IFQ_POLL(&ifp->if_snd, m0); |
1371 | if (m0 == NULL) | | 1371 | if (m0 == NULL) |
1372 | break; | | 1372 | break; |
1373 | | | | |
1374 | if (sc->sc_txsfree < MD_TXQUEUE_GC) { | | 1373 | if (sc->sc_txsfree < MD_TXQUEUE_GC) { |
1375 | txreap(sc); | | 1374 | txreap(sc); |
1376 | if (sc->sc_txsfree == 0) | | 1375 | if (sc->sc_txsfree == 0) |
1377 | break; | | 1376 | break; |
1378 | } | | 1377 | } |
1379 | txs = &sc->sc_txsoft[sc->sc_txsnext]; | | 1378 | txs = &sc->sc_txsoft[sc->sc_txsnext]; |
1380 | dmamap = txs->txs_dmamap; | | 1379 | dmamap = txs->txs_dmamap; |
1381 | | | | |
1382 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, | | 1380 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, |
1383 | BUS_DMA_WRITE | BUS_DMA_NOWAIT); | | 1381 | BUS_DMA_WRITE | BUS_DMA_NOWAIT); |
1384 | if (error) { | | 1382 | if (error) { |
1385 | if (error == EFBIG) { | | 1383 | if (error == EFBIG) { |
1386 | aprint_error_dev(sc->sc_dev, | | 1384 | aprint_error_dev(sc->sc_dev, |
1387 | "Tx packet consumes too many " | | 1385 | "Tx packet consumes too many " |
1388 | "DMA segments, dropping...\n"); | | 1386 | "DMA segments, dropping...\n"); |
1389 | IFQ_DEQUEUE(&ifp->if_snd, m0); | | 1387 | IFQ_DEQUEUE(&ifp->if_snd, m0); |
1390 | m_freem(m0); | | 1388 | m_freem(m0); |
1391 | if_statinc_ref(ifp, if_oerrors); | | 1389 | if_statinc_ref(ifp, if_oerrors); |
1392 | continue; | | 1390 | continue; |
1393 | } | | 1391 | } |
1394 | /* Short on resources, just stop for now. */ | | 1392 | /* Short on resources, just stop for now. */ |
1395 | break; | | 1393 | break; |
1396 | } | | 1394 | } |
1397 | | | | |
1398 | if (dmamap->dm_nsegs > sc->sc_txfree) { | | 1395 | if (dmamap->dm_nsegs > sc->sc_txfree) { |
1399 | /* | | 1396 | /* |
1400 | * Not enough free descriptors to transmit this | | 1397 | * Not enough free descriptors to transmit this |
1401 | * packet. We haven't committed anything yet, | | 1398 | * packet. We haven't committed anything yet, |
1402 | * so just unload the DMA map, put the packet | | 1399 | * so just unload the DMA map, put the packet |
1403 | * back on the queue, and punt. | | 1400 | * back on the queue, and punt. |
1404 | */ | | 1401 | */ |
1405 | bus_dmamap_unload(sc->sc_dmat, dmamap); | | 1402 | bus_dmamap_unload(sc->sc_dmat, dmamap); |
1406 | break; | | 1403 | break; |
1407 | } | | 1404 | } |
1408 | | | 1405 | |
1409 | IFQ_DEQUEUE(&ifp->if_snd, m0); | | 1406 | IFQ_DEQUEUE(&ifp->if_snd, m0); |
1410 | | | | |
1411 | /* | | 1407 | /* |
1412 | * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. | | 1408 | * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. |
1413 | */ | | 1409 | */ |
1414 | | | | |
1415 | bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, | | 1410 | bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, |
1416 | BUS_DMASYNC_PREWRITE); | | 1411 | BUS_DMASYNC_PREWRITE); |
1417 | | | 1412 | |
1418 | tdes0 = 0; /* to postpone 1st segment T0_OWN write */ | | 1413 | tdes0 = 0; /* to postpone 1st segment T0_OWN write */ |
1419 | lasttx = -1; | | 1414 | lasttx = -1; |
1420 | for (nexttx = sc->sc_txnext, seg = 0; | | 1415 | for (nexttx = sc->sc_txnext, seg = 0; |
1421 | seg < dmamap->dm_nsegs; | | 1416 | seg < dmamap->dm_nsegs; |
1422 | seg++, nexttx = MD_NEXTTX(nexttx)) { | | 1417 | seg++, nexttx = MD_NEXTTX(nexttx)) { |
1423 | struct tdes *tdes = &sc->sc_txdescs[nexttx]; | | 1418 | struct tdes *tdes = &sc->sc_txdescs[nexttx]; |
1424 | bus_addr_t paddr = dmamap->dm_segs[seg].ds_addr; | | 1419 | bus_addr_t p = dmamap->dm_segs[seg].ds_addr; |
| | | 1420 | bus_size_t z = dmamap->dm_segs[seg].ds_len; |
1425 | /* | | 1421 | /* |
1426 | * If this is the first descriptor we're | | 1422 | * If this is the first descriptor we're |
1427 | * enqueueing, don't set the OWN bit just | | 1423 | * enqueueing, don't set the OWN bit just |
1428 | * yet. That could cause a race condition. | | 1424 | * yet. That could cause a race condition. |
1429 | * We'll do it below. | | 1425 | * We'll do it below. |
1430 | */ | | 1426 | */ |
1431 | tdes->t3 = htole32(dmamap->dm_segs[seg].ds_len); | | 1427 | tdes->t3 = htole32(z); |
1432 | tdes->t2 = htole32(BUS_ADDR_LO32(paddr)); | | 1428 | tdes->t2 = htole32(BUS_ADDR_LO32(p)); |
1433 | tdes->t1 = htole32(BUS_ADDR_HI32(paddr)); | | 1429 | tdes->t1 = htole32(BUS_ADDR_HI32(p)); |
1434 | tdes->t0 = htole32(tdes0 | (tdes->t0 & T0_LD) | | | 1430 | tdes->t0 &= htole32(T0_LD); |
| | | 1431 | tdes->t0 |= htole32(tdes0 | |
1435 | (15 << T0_TDRID) | T0_PT | | | 1432 | (15 << T0_TDRID) | T0_PT | |
1436 | sc->sc_t0cotso | T0_TRS); | | 1433 | sc->sc_t0cotso | T0_TRS); |
1437 | tdes0 = T0_OWN; /* 2nd and other segments */ | | 1434 | tdes0 = T0_OWN; /* 2nd and other segments */ |
1438 | /* NB; t0 DRID field contains zero */ | | 1435 | /* NB; t0 DRID field contains zero */ |
1439 | lasttx = nexttx; | | 1436 | lasttx = nexttx; |
1440 | } | | 1437 | } |
1441 | | | 1438 | |
| | | 1439 | /* HW lacks of per-frame xmit done interrupt control */ |
| | | 1440 | |
1442 | /* Write deferred 1st segment T0_OWN at the final stage */ | | 1441 | /* Write deferred 1st segment T0_OWN at the final stage */ |
1443 | sc->sc_txdescs[lasttx].t0 |= htole32(T0_LS); | | 1442 | sc->sc_txdescs[lasttx].t0 |= htole32(T0_LS); |
1444 | sc->sc_txdescs[sc->sc_txnext].t0 |= htole32(T0_FS | T0_OWN); | | 1443 | sc->sc_txdescs[sc->sc_txnext].t0 |= htole32(T0_FS | T0_OWN); |
1445 | SCX_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs, | | 1444 | SCX_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs, |
1446 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | | 1445 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
1447 | | | 1446 | |
1448 | /* submit one frame to xmit */ | | 1447 | /* submit one frame to xmit */ |
1449 | CSR_WRITE(sc, TXSUBMIT, 1); | | 1448 | CSR_WRITE(sc, TXSUBMIT, 1); |
1450 | | | 1449 | |
1451 | txs->txs_mbuf = m0; | | 1450 | txs->txs_mbuf = m0; |
1452 | txs->txs_firstdesc = sc->sc_txnext; | | 1451 | txs->txs_firstdesc = sc->sc_txnext; |
1453 | txs->txs_lastdesc = lasttx; | | 1452 | txs->txs_lastdesc = lasttx; |
1454 | txs->txs_ndesc = dmamap->dm_nsegs; | | 1453 | txs->txs_ndesc = dmamap->dm_nsegs; |
1455 | | | | |
1456 | sc->sc_txfree -= txs->txs_ndesc; | | 1454 | sc->sc_txfree -= txs->txs_ndesc; |
1457 | sc->sc_txnext = nexttx; | | 1455 | sc->sc_txnext = nexttx; |
1458 | sc->sc_txsfree--; | | 1456 | sc->sc_txsfree--; |
1459 | sc->sc_txsnext = MD_NEXTTXS(sc->sc_txsnext); | | 1457 | sc->sc_txsnext = MD_NEXTTXS(sc->sc_txsnext); |
1460 | /* | | 1458 | /* |
1461 | * Pass the packet to any BPF listeners. | | 1459 | * Pass the packet to any BPF listeners. |
1462 | */ | | 1460 | */ |
1463 | bpf_mtap(ifp, m0, BPF_D_OUT); | | 1461 | bpf_mtap(ifp, m0, BPF_D_OUT); |
1464 | } | | 1462 | } |
1465 | | | | |
1466 | if (sc->sc_txfree != ofree) { | | 1463 | if (sc->sc_txfree != ofree) { |
1467 | /* Set a watchdog timer in case the chip flakes out. */ | | 1464 | /* Set a watchdog timer in case the chip flakes out. */ |
1468 | ifp->if_timer = 5; | | 1465 | ifp->if_timer = 5; |
1469 | } | | 1466 | } |
1470 | } | | 1467 | } |
1471 | | | 1468 | |
1472 | #define EVENT_DEBUG 1 | | 1469 | #define EVENT_DEBUG 1 |
1473 | | | 1470 | |
1474 | static void | | 1471 | static void |
1475 | scx_watchdog(struct ifnet *ifp) | | 1472 | scx_watchdog(struct ifnet *ifp) |
1476 | { | | 1473 | { |
1477 | struct scx_softc *sc = ifp->if_softc; | | 1474 | struct scx_softc *sc = ifp->if_softc; |
1478 | | | 1475 | |
1479 | /* | | 1476 | /* |
1480 | * Since we're not interrupting every packet, sweep | | 1477 | * Since we're not interrupting every packet, sweep |
1481 | * up before we report an error. | | 1478 | * up before we report an error. |
1482 | */ | | 1479 | */ |
1483 | txreap(sc); | | 1480 | txreap(sc); |
1484 | | | 1481 | |
1485 | if (sc->sc_txfree != MD_NTXDESC) { | | 1482 | if (sc->sc_txfree != MD_NTXDESC) { |
1486 | aprint_error_dev(sc->sc_dev, | | 1483 | aprint_error_dev(sc->sc_dev, |
1487 | "device timeout (txfree %d txsfree %d txnext %d)\n", | | 1484 | "device timeout (txfree %d txsfree %d txnext %d)\n", |
1488 | sc->sc_txfree, sc->sc_txsfree, sc->sc_txnext); | | 1485 | sc->sc_txfree, sc->sc_txsfree, sc->sc_txnext); |
1489 | if_statinc(ifp, if_oerrors); | | 1486 | if_statinc(ifp, if_oerrors); |
1490 | #if EVENT_DEBUG == 1 | | 1487 | #if EVENT_DEBUG == 1 |
1491 | aprint_error_dev(sc->sc_dev, | | 1488 | aprint_error_dev(sc->sc_dev, |
1492 | "rx frames %d, octects %d, bcast %d, mcast %d\n", | | | |
1493 | mac_read(sc, GMACEVCNT(27)), | | | |
1494 | mac_read(sc, GMACEVCNT(28)), | | | |
1495 | mac_read(sc, GMACEVCNT(30)), | | | |
1496 | mac_read(sc, GMACEVCNT(31))); | | | |
1497 | aprint_error_dev(sc->sc_dev, | | | |
1498 | "tx frames %d, octects %d, bcast %d, mcast %d\n", | | 1489 | "tx frames %d, octects %d, bcast %d, mcast %d\n", |
1499 | mac_read(sc, GMACEVCNT(1)), | | 1490 | mac_read(sc, GMACEVCNT(1)), |
1500 | mac_read(sc, GMACEVCNT(0)), | | 1491 | mac_read(sc, GMACEVCNT(0)), |
1501 | mac_read(sc, GMACEVCNT(2)), | | 1492 | mac_read(sc, GMACEVCNT(2)), |
1502 | mac_read(sc, GMACEVCNT(3))); | | 1493 | mac_read(sc, GMACEVCNT(3))); |
1503 | aprint_error_dev(sc->sc_dev, | | 1494 | aprint_error_dev(sc->sc_dev, |
| | | 1495 | "rx frames %d, octects %d, bcast %d, mcast %d\n", |
| | | 1496 | mac_read(sc, GMACEVCNT(27)), |
| | | 1497 | mac_read(sc, GMACEVCNT(28)), |
| | | 1498 | mac_read(sc, GMACEVCNT(30)), |
| | | 1499 | mac_read(sc, GMACEVCNT(31))); |
| | | 1500 | aprint_error_dev(sc->sc_dev, |
1504 | "current tdes addr %x, buf addr %x\n", | | 1501 | "current tdes addr %x, buf addr %x\n", |
1505 | mac_read(sc, 0x1048), mac_read(sc, 0x1050)); | | 1502 | mac_read(sc, 0x1048), mac_read(sc, 0x1050)); |
1506 | aprint_error_dev(sc->sc_dev, | | 1503 | aprint_error_dev(sc->sc_dev, |
1507 | "current rdes addr %x, buf addr %x\n", | | 1504 | "current rdes addr %x, buf addr %x\n", |
1508 | mac_read(sc, 0x104c), mac_read(sc, 0x1054)); | | 1505 | mac_read(sc, 0x104c), mac_read(sc, 0x1054)); |
1509 | #endif | | 1506 | #endif |
1510 | /* Reset the interface. */ | | 1507 | /* Reset the interface. */ |
1511 | scx_init(ifp); | | 1508 | scx_init(ifp); |
1512 | } | | 1509 | } |
1513 | | | 1510 | |
1514 | scx_start(ifp); | | 1511 | scx_start(ifp); |
1515 | } | | 1512 | } |
1516 | | | 1513 | |
1517 | static int | | 1514 | static int |
1518 | scx_intr(void *arg) | | 1515 | scx_intr(void *arg) |
1519 | { | | 1516 | { |
1520 | struct scx_softc *sc = arg; | | 1517 | struct scx_softc *sc = arg; |
1521 | uint32_t enable, status; | | 1518 | uint32_t enable, status; |
1522 | | | 1519 | |
1523 | status = CSR_READ(sc, xINTSR); /* not W1C */ | | 1520 | status = CSR_READ(sc, xINTSR); /* not W1C */ |
1524 | enable = CSR_READ(sc, xINTAEN); | | 1521 | enable = CSR_READ(sc, xINTAEN); |
1525 | if ((status & enable) == 0) | | 1522 | if ((status & enable) == 0) |
1526 | return 0; | | 1523 | return 0; |
1527 | if (status & (IRQ_TX | IRQ_RX)) { | | 1524 | if (status & (IRQ_TX | IRQ_RX)) { |
1528 | CSR_WRITE(sc, xINTAE_CLR, (IRQ_TX | IRQ_RX)); | | 1525 | CSR_WRITE(sc, xINTAE_CLR, (IRQ_TX | IRQ_RX)); |
1529 | | | 1526 | |
1530 | status = CSR_READ(sc, RXISR); | | 1527 | status = CSR_READ(sc, RXISR); |
1531 | CSR_WRITE(sc, RXISR, status); | | 1528 | CSR_WRITE(sc, RXISR, status); |
1532 | if (status & RXI_RC_ERR) | | 1529 | if (status & RXI_RC_ERR) |
1533 | aprint_error_dev(sc->sc_dev, "Rx error\n"); | | 1530 | aprint_error_dev(sc->sc_dev, "Rx error\n"); |
1534 | if (status & (RXI_PKTCNT | RXI_TMREXP)) { | | 1531 | if (status & (RXI_PKTCNT | RXI_TMREXP)) { |
1535 | rxintr(sc); | | 1532 | rxfill(sc); |
1536 | (void)CSR_READ(sc, RXDONECNT); /* clear RXI_RXDONE */ | | 1533 | (void)CSR_READ(sc, RXAVAILCNT); /* clear RXI_PKTCNT */ |
1537 | } | | 1534 | } |
1538 | | | 1535 | |
1539 | status = CSR_READ(sc, TXISR); | | 1536 | status = CSR_READ(sc, TXISR); |
1540 | CSR_WRITE(sc, TXISR, status); | | 1537 | CSR_WRITE(sc, TXISR, status); |
1541 | if (status & TXI_TR_ERR) | | 1538 | if (status & TXI_TR_ERR) |
1542 | aprint_error_dev(sc->sc_dev, "Tx error\n"); | | 1539 | aprint_error_dev(sc->sc_dev, "Tx error\n"); |
1543 | if (status & (TXI_TXDONE | TXI_TMREXP)) { | | 1540 | if (status & (TXI_TXDONE | TXI_TMREXP)) { |
1544 | txreap(sc); | | 1541 | txreap(sc); |
1545 | (void)CSR_READ(sc, TXDONECNT); /* clear TXI_TXDONE */ | | 1542 | (void)CSR_READ(sc, TXDONECNT); /* clear TXI_TXDONE */ |
1546 | } | | 1543 | } |
1547 | | | 1544 | |
1548 | CSR_WRITE(sc, xINTAE_SET, (IRQ_TX | IRQ_RX)); | | 1545 | CSR_WRITE(sc, xINTAE_SET, (IRQ_TX | IRQ_RX)); |
1549 | } | | 1546 | } |
1550 | return 1; | | 1547 | return 1; |
1551 | } | | 1548 | } |
1552 | | | 1549 | |
1553 | static void | | 1550 | static void |
1554 | txreap(struct scx_softc *sc) | | 1551 | txreap(struct scx_softc *sc) |
1555 | { | | 1552 | { |
1556 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1553 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1557 | struct scx_txsoft *txs; | | 1554 | struct scx_txsoft *txs; |
1558 | uint32_t txstat; | | 1555 | uint32_t txstat; |
1559 | int i; | | 1556 | int i; |
1560 | | | 1557 | |
1561 | for (i = sc->sc_txsdirty; sc->sc_txsfree != MD_TXQUEUELEN; | | 1558 | for (i = sc->sc_txsdirty; sc->sc_txsfree != MD_TXQUEUELEN; |
1562 | i = MD_NEXTTXS(i), sc->sc_txsfree++) { | | 1559 | i = MD_NEXTTXS(i), sc->sc_txsfree++) { |
1563 | txs = &sc->sc_txsoft[i]; | | 1560 | txs = &sc->sc_txsoft[i]; |
1564 | | | 1561 | |
1565 | SCX_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_ndesc, | | 1562 | SCX_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_ndesc, |
1566 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | | 1563 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
1567 | | | 1564 | |
1568 | txstat = le32toh(sc->sc_txdescs[txs->txs_lastdesc].t0); | | 1565 | txstat = le32toh(sc->sc_txdescs[txs->txs_lastdesc].t0); |
1569 | if (txstat & T0_OWN) /* desc is still in use */ | | 1566 | if (txstat & T0_OWN) /* desc is still in use */ |
1570 | break; | | 1567 | break; |
1571 | | | 1568 | |
1572 | /* There is no way to tell transmission status per frame */ | | 1569 | /* There is no way to tell transmission status per frame */ |
1573 | | | 1570 | |
1574 | if_statinc(ifp, if_opackets); | | 1571 | if_statinc(ifp, if_opackets); |
1575 | | | 1572 | |
1576 | sc->sc_txfree += txs->txs_ndesc; | | 1573 | sc->sc_txfree += txs->txs_ndesc; |
1577 | bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, | | 1574 | bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, |
1578 | 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); | | 1575 | 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
1579 | bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); | | 1576 | bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); |
1580 | m_freem(txs->txs_mbuf); | | 1577 | m_freem(txs->txs_mbuf); |
1581 | txs->txs_mbuf = NULL; | | 1578 | txs->txs_mbuf = NULL; |
1582 | } | | 1579 | } |
1583 | sc->sc_txsdirty = i; | | 1580 | sc->sc_txsdirty = i; |
1584 | if (sc->sc_txsfree == MD_TXQUEUELEN) | | 1581 | if (sc->sc_txsfree == MD_TXQUEUELEN) |
1585 | ifp->if_timer = 0; | | 1582 | ifp->if_timer = 0; |
1586 | } | | 1583 | } |
1587 | | | 1584 | |
1588 | static void | | 1585 | static void |
1589 | rxintr(struct scx_softc *sc) | | 1586 | rxfill(struct scx_softc *sc) |
1590 | { | | 1587 | { |
1591 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1588 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1592 | struct scx_rxsoft *rxs; | | 1589 | struct scx_rxsoft *rxs; |
1593 | struct mbuf *m; | | 1590 | struct mbuf *m; |
1594 | uint32_t rxstat; | | 1591 | uint32_t rxstat, rlen; |
1595 | int i, len; | | 1592 | int i; |
1596 | | | 1593 | |
1597 | for (i = sc->sc_rxptr; /*CONSTCOND*/ 1; i = MD_NEXTRX(i)) { | | 1594 | for (i = sc->sc_rxptr; /*CONSTCOND*/ 1; i = MD_NEXTRX(i)) { |
1598 | rxs = &sc->sc_rxsoft[i]; | | | |
1599 | | | | |
1600 | SCX_CDRXSYNC(sc, i, | | 1595 | SCX_CDRXSYNC(sc, i, |
1601 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | | 1596 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
1602 | | | 1597 | |
1603 | rxstat = le32toh(sc->sc_rxdescs[i].r0); | | 1598 | rxstat = le32toh(sc->sc_rxdescs[i].r0); |
1604 | if (rxstat & R0_OWN) /* desc is left empty */ | | 1599 | if (rxstat & R0_OWN) /* desc is left empty */ |
1605 | break; | | 1600 | break; |
1606 | | | 1601 | |
1607 | /* R0_FS | R0_LS must have been marked for this desc */ | | 1602 | /* received frame length in R3 31:16 */ |
| | | 1603 | rlen = le32toh(sc->sc_rxdescs[i].r3) >> 16; |
1608 | | | 1604 | |
| | | 1605 | /* R0_FS | R0_LS must have been marked for this desc */ |
| | | 1606 | rxs = &sc->sc_rxsoft[i]; |
1609 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1607 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1610 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); | | 1608 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); |
1611 | | | 1609 | |
1612 | len = sc->sc_rxdescs[i].r3 >> 16; /* 31:16 received */ | | 1610 | /* dispense new storage to receive frame */ |
1613 | len -= ETHER_CRC_LEN; /* Trim CRC off */ | | | |
1614 | m = rxs->rxs_mbuf; | | 1611 | m = rxs->rxs_mbuf; |
1615 | | | | |
1616 | if (add_rxbuf(sc, i) != 0) { | | 1612 | if (add_rxbuf(sc, i) != 0) { |
1617 | if_statinc(ifp, if_ierrors); | | 1613 | if_statinc(ifp, if_ierrors); /* resource shortage */ |
1618 | SCX_INIT_RXDESC(sc, i); | | 1614 | SCX_INIT_RXDESC(sc, i); /* then reuse */ |
1619 | bus_dmamap_sync(sc->sc_dmat, | | 1615 | bus_dmamap_sync(sc->sc_dmat, |
1620 | rxs->rxs_dmamap, 0, | | 1616 | rxs->rxs_dmamap, 0, |
1621 | rxs->rxs_dmamap->dm_mapsize, | | 1617 | rxs->rxs_dmamap->dm_mapsize, |
1622 | BUS_DMASYNC_PREREAD); | | 1618 | BUS_DMASYNC_PREREAD); |
1623 | continue; | | 1619 | continue; |
1624 | } | | 1620 | } |
1625 | | | 1621 | /* complete mbuf */ |
1626 | m_set_rcvif(m, ifp); | | 1622 | m_set_rcvif(m, ifp); |
1627 | m->m_pkthdr.len = m->m_len = len; | | 1623 | m->m_pkthdr.len = m->m_len = rlen; |
1628 | | | 1624 | m->m_flags |= M_HASFCS; |
1629 | if (rxstat & R0_CSUM) { | | 1625 | if (rxstat & R0_CSUM) { |
1630 | uint32_t csum = M_CSUM_IPv4; | | 1626 | uint32_t csum = M_CSUM_IPv4; |
1631 | if (rxstat & R0_CERR) | | 1627 | if (rxstat & R0_CERR) |
1632 | csum |= M_CSUM_IPv4_BAD; | | 1628 | csum |= M_CSUM_IPv4_BAD; |
1633 | m->m_pkthdr.csum_flags |= csum; | | 1629 | m->m_pkthdr.csum_flags |= csum; |
1634 | } | | 1630 | } |
| | | 1631 | /* and pass to upper layer */ |
1635 | if_percpuq_enqueue(ifp->if_percpuq, m); | | 1632 | if_percpuq_enqueue(ifp->if_percpuq, m); |
1636 | } | | 1633 | } |
1637 | sc->sc_rxptr = i; | | 1634 | sc->sc_rxptr = i; |
1638 | } | | 1635 | } |
1639 | | | 1636 | |
1640 | static int | | 1637 | static int |
1641 | add_rxbuf(struct scx_softc *sc, int i) | | 1638 | add_rxbuf(struct scx_softc *sc, int i) |
1642 | { | | 1639 | { |
1643 | struct scx_rxsoft *rxs = &sc->sc_rxsoft[i]; | | 1640 | struct scx_rxsoft *rxs = &sc->sc_rxsoft[i]; |
1644 | struct mbuf *m; | | 1641 | struct mbuf *m; |
1645 | int error; | | 1642 | int error; |
1646 | | | 1643 | |
1647 | MGETHDR(m, M_DONTWAIT, MT_DATA); | | 1644 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
1648 | if (m == NULL) | | 1645 | if (m == NULL) |
1649 | return ENOBUFS; | | 1646 | return ENOBUFS; |
1650 | | | | |
1651 | MCLGET(m, M_DONTWAIT); | | 1647 | MCLGET(m, M_DONTWAIT); |
1652 | if ((m->m_flags & M_EXT) == 0) { | | 1648 | if ((m->m_flags & M_EXT) == 0) { |
1653 | m_freem(m); | | 1649 | m_freem(m); |
1654 | return ENOBUFS; | | 1650 | return ENOBUFS; |
1655 | } | | 1651 | } |
1656 | | | | |
1657 | if (rxs->rxs_mbuf != NULL) | | 1652 | if (rxs->rxs_mbuf != NULL) |
1658 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); | | 1653 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); |
1659 | | | | |
1660 | rxs->rxs_mbuf = m; | | 1654 | rxs->rxs_mbuf = m; |
1661 | | | | |
1662 | error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap, | | 1655 | error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap, |
1663 | m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT); | | 1656 | m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT); |
1664 | if (error) { | | 1657 | if (error) { |
1665 | aprint_error_dev(sc->sc_dev, | | 1658 | aprint_error_dev(sc->sc_dev, |
1666 | "can't load rx DMA map %d, error = %d\n", i, error); | | 1659 | "can't load rx DMA map %d, error = %d\n", i, error); |
1667 | panic("add_rxbuf"); | | 1660 | panic("add_rxbuf"); |
1668 | } | | 1661 | } |
1669 | | | | |
1670 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1662 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1671 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); | | 1663 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); |
1672 | SCX_INIT_RXDESC(sc, i); | | 1664 | SCX_INIT_RXDESC(sc, i); |
1673 | | | 1665 | |
1674 | return 0; | | 1666 | return 0; |
1675 | } | | 1667 | } |
1676 | | | 1668 | |
1677 | static void | | 1669 | static void |
1678 | rxdrain(struct scx_softc *sc) | | 1670 | rxdrain(struct scx_softc *sc) |
1679 | { | | 1671 | { |
1680 | struct scx_rxsoft *rxs; | | 1672 | struct scx_rxsoft *rxs; |
1681 | int i; | | 1673 | int i; |
1682 | | | 1674 | |
1683 | for (i = 0; i < MD_NRXDESC; i++) { | | 1675 | for (i = 0; i < MD_NRXDESC; i++) { |
1684 | rxs = &sc->sc_rxsoft[i]; | | 1676 | rxs = &sc->sc_rxsoft[i]; |
1685 | if (rxs->rxs_mbuf != NULL) { | | 1677 | if (rxs->rxs_mbuf != NULL) { |
1686 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); | | 1678 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); |
1687 | m_freem(rxs->rxs_mbuf); | | 1679 | m_freem(rxs->rxs_mbuf); |
1688 | rxs->rxs_mbuf = NULL; | | 1680 | rxs->rxs_mbuf = NULL; |
1689 | } | | 1681 | } |
1690 | } | | 1682 | } |
1691 | } | | 1683 | } |
1692 | | | 1684 | |
1693 | #define LINK_DEBUG 0 | | 1685 | #define LINK_DEBUG 0 |
1694 | | | 1686 | |
1695 | void | | 1687 | static void |
1696 | mii_statchg(struct ifnet *ifp) | | 1688 | mii_statchg(struct ifnet *ifp) |
1697 | { | | 1689 | { |
1698 | struct scx_softc *sc = ifp->if_softc; | | 1690 | struct scx_softc *sc = ifp->if_softc; |
1699 | struct mii_data *mii = &sc->sc_mii; | | 1691 | struct mii_data *mii = &sc->sc_mii; |
1700 | const int Mbps[4] = { 10, 100, 1000, 0 }; | | 1692 | const int Mbps[4] = { 10, 100, 1000, 0 }; |
1701 | uint32_t miisr, mcr, fcr; | | 1693 | uint32_t miisr, mcr, fcr; |
1702 | int spd; | | 1694 | int spd; |
1703 | | | 1695 | |
1704 | /* decode MIISR register value */ | | 1696 | /* decode MIISR register value */ |
1705 | miisr = mac_read(sc, GMACMIISR); | | 1697 | miisr = mac_read(sc, GMACMIISR); |
1706 | spd = Mbps[(miisr & MIISR_SPD) >> 1]; | | 1698 | spd = Mbps[(miisr & MIISR_SPD) >> 1]; |
1707 | #if LINK_DEBUG == 1 | | 1699 | #if LINK_DEBUG == 1 |
1708 | static uint32_t oldmiisr = 0; | | 1700 | static uint32_t oldmiisr = 0; |
1709 | if (miisr != oldmiisr) { | | 1701 | if (miisr != oldmiisr) { |
1710 | printf("MII link status (0x%x) %s", | | 1702 | printf("MII link status (0x%x) %s", |
1711 | miisr, (miisr & MIISR_LUP) ? "up" : "down"); | | 1703 | miisr, (miisr & MIISR_LUP) ? "up" : "down"); |
1712 | if (miisr & MIISR_LUP) { | | 1704 | if (miisr & MIISR_LUP) { |
1713 | printf(" spd%d", spd); | | 1705 | printf(" spd%d", spd); |
1714 | if (miisr & MIISR_FDX) | | 1706 | if (miisr & MIISR_FDX) |
1715 | printf(",full-duplex"); | | 1707 | printf(",full-duplex"); |
1716 | } | | 1708 | } |
1717 | printf("\n"); | | 1709 | printf("\n"); |
1718 | } | | 1710 | } |
1719 | #endif | | 1711 | #endif |
1720 | /* Get flow control negotiation result. */ | | 1712 | /* Get flow control negotiation result. */ |
1721 | if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO && | | 1713 | if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO && |
1722 | (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) | | 1714 | (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) |
1723 | sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK; | | 1715 | sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK; |
1724 | | | 1716 | |
1725 | /* Adjust speed 1000/100/10. */ | | 1717 | /* Adjust speed 1000/100/10. */ |
1726 | mcr = mac_read(sc, GMACMCR) &~ (MCR_PS | MCR_FES); | | 1718 | mcr = mac_read(sc, GMACMCR) &~ (MCR_PS | MCR_FES); |
1727 | if (sc->sc_miigmii) { | | 1719 | if (sc->sc_miigmii) { |
1728 | if (spd != 1000) | | 1720 | if (spd != 1000) |
1729 | mcr |= MCR_PS; | | 1721 | mcr |= MCR_PS; |
1730 | } else { | | 1722 | } else { |
1731 | if (spd == 100) | | 1723 | if (spd == 100) |
1732 | mcr |= MCR_FES; | | 1724 | mcr |= MCR_FES; |
1733 | } | | 1725 | } |
1734 | mcr |= MCR_CST | MCR_JE; | | 1726 | mcr |= MCR_CST | MCR_JE; |
1735 | if (sc->sc_miigmii == 0) | | 1727 | if (sc->sc_miigmii == 0) |
1736 | mcr |= MCR_IBN; | | 1728 | mcr |= MCR_IBN; |
1737 | | | 1729 | |
1738 | /* Adjust duplexity and PAUSE flow control. */ | | 1730 | /* Adjust duplexity and PAUSE flow control. */ |
1739 | mcr &= ~MCR_USEFDX; | | 1731 | mcr &= ~MCR_USEFDX; |
1740 | fcr = mac_read(sc, GMACFCR) & ~(FCR_TFE | FCR_RFE); | | 1732 | fcr = mac_read(sc, GMACFCR) & ~(FCR_TFE | FCR_RFE); |
1741 | if (miisr & MIISR_FDX) { | | 1733 | if (miisr & MIISR_FDX) { |
1742 | if (sc->sc_flowflags & IFM_ETH_TXPAUSE) | | 1734 | if (sc->sc_flowflags & IFM_ETH_TXPAUSE) |
1743 | fcr |= FCR_TFE; | | 1735 | fcr |= FCR_TFE; |
1744 | if (sc->sc_flowflags & IFM_ETH_RXPAUSE) | | 1736 | if (sc->sc_flowflags & IFM_ETH_RXPAUSE) |
1745 | fcr |= FCR_RFE; | | 1737 | fcr |= FCR_RFE; |
1746 | mcr |= MCR_USEFDX; | | 1738 | mcr |= MCR_USEFDX; |
1747 | } | | 1739 | } |
1748 | mac_write(sc, GMACMCR, mcr); | | 1740 | mac_write(sc, GMACMCR, mcr); |
1749 | mac_write(sc, GMACFCR, fcr); | | 1741 | mac_write(sc, GMACFCR, fcr); |
1750 | #if LINK_DEBUG == 1 | | 1742 | #if LINK_DEBUG == 1 |
1751 | if (miisr != oldmiisr) { | | 1743 | if (miisr != oldmiisr) { |
1752 | printf("%ctxfe, %crxfe\n", | | 1744 | printf("%ctxfe, %crxfe\n", |
1753 | (fcr & FCR_TFE) ? '+' : '-', | | 1745 | (fcr & FCR_TFE) ? '+' : '-', |
1754 | (fcr & FCR_RFE) ? '+' : '-'); | | 1746 | (fcr & FCR_RFE) ? '+' : '-'); |
1755 | } | | 1747 | } |
1756 | oldmiisr = miisr; | | 1748 | oldmiisr = miisr; |
1757 | #endif | | 1749 | #endif |
1758 | } | | 1750 | } |
1759 | | | 1751 | |
1760 | static void | | 1752 | static void |
1761 | scx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) | | 1753 | scx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) |
1762 | { | | 1754 | { |
1763 | struct scx_softc *sc = ifp->if_softc; | | 1755 | struct scx_softc *sc = ifp->if_softc; |
1764 | struct mii_data *mii = &sc->sc_mii; | | 1756 | struct mii_data *mii = &sc->sc_mii; |
1765 | | | 1757 | |
1766 | mii_pollstat(mii); | | 1758 | mii_pollstat(mii); |
1767 | ifmr->ifm_status = mii->mii_media_status; | | 1759 | ifmr->ifm_status = mii->mii_media_status; |
1768 | ifmr->ifm_active = sc->sc_flowflags | | | 1760 | ifmr->ifm_active = sc->sc_flowflags | |
1769 | (mii->mii_media_active & ~IFM_ETH_FMASK); | | 1761 | (mii->mii_media_active & ~IFM_ETH_FMASK); |
1770 | } | | 1762 | } |
1771 | | | 1763 | |
1772 | static int | | 1764 | static int |
1773 | mii_readreg(device_t self, int phy, int reg, uint16_t *val) | | 1765 | mii_readreg(device_t self, int phy, int reg, uint16_t *val) |
1774 | { | | 1766 | { |
1775 | struct scx_softc *sc = device_private(self); | | 1767 | struct scx_softc *sc = device_private(self); |
1776 | uint32_t miia; | | 1768 | uint32_t miia; |
1777 | int ntries; | | 1769 | int ntries; |
1778 | | | 1770 | |
1779 | miia = (phy << GAR_PHY) | (reg << GAR_REG) | sc->sc_mdclk; | | 1771 | miia = (phy << GAR_PHY) | (reg << GAR_REG) | sc->sc_mdclk; |
1780 | mac_write(sc, GMACGAR, miia | GAR_BUSY); | | 1772 | mac_write(sc, GMACGAR, miia | GAR_BUSY); |
1781 | for (ntries = 0; ntries < 1000; ntries++) { | | 1773 | for (ntries = 0; ntries < 1000; ntries++) { |
1782 | if ((mac_read(sc, GMACGAR) & GAR_BUSY) == 0) | | 1774 | if ((mac_read(sc, GMACGAR) & GAR_BUSY) == 0) |
1783 | goto unbusy; | | 1775 | goto unbusy; |
1784 | DELAY(1); | | 1776 | DELAY(1); |
1785 | } | | 1777 | } |
1786 | return ETIMEDOUT; | | 1778 | return ETIMEDOUT; |
1787 | unbusy: | | 1779 | unbusy: |
1788 | *val = mac_read(sc, GMACGDR); | | 1780 | *val = mac_read(sc, GMACGDR); |
1789 | return 0; | | 1781 | return 0; |
1790 | } | | 1782 | } |
1791 | | | 1783 | |
1792 | static int | | 1784 | static int |
1793 | mii_writereg(device_t self, int phy, int reg, uint16_t val) | | 1785 | mii_writereg(device_t self, int phy, int reg, uint16_t val) |
1794 | { | | 1786 | { |
1795 | struct scx_softc *sc = device_private(self); | | 1787 | struct scx_softc *sc = device_private(self); |
1796 | uint32_t miia; | | 1788 | uint32_t miia; |
1797 | uint16_t dummy; | | 1789 | uint16_t dummy; |
1798 | int ntries; | | 1790 | int ntries; |
1799 | | | 1791 | |
1800 | miia = (phy << GAR_PHY) | (reg << GAR_REG) | sc->sc_mdclk; | | 1792 | miia = (phy << GAR_PHY) | (reg << GAR_REG) | sc->sc_mdclk; |
1801 | mac_write(sc, GMACGDR, val); | | 1793 | mac_write(sc, GMACGDR, val); |
1802 | mac_write(sc, GMACGAR, miia | GAR_IOWR | GAR_BUSY); | | 1794 | mac_write(sc, GMACGAR, miia | GAR_IOWR | GAR_BUSY); |
1803 | for (ntries = 0; ntries < 1000; ntries++) { | | 1795 | for (ntries = 0; ntries < 1000; ntries++) { |
1804 | if ((mac_read(sc, GMACGAR) & GAR_BUSY) == 0) | | 1796 | if ((mac_read(sc, GMACGAR) & GAR_BUSY) == 0) |
1805 | goto unbusy; | | 1797 | goto unbusy; |
1806 | DELAY(1); | | 1798 | DELAY(1); |
1807 | } | | 1799 | } |
1808 | return ETIMEDOUT; | | 1800 | return ETIMEDOUT; |
1809 | unbusy: | | 1801 | unbusy: |
1810 | mii_readreg(self, phy, MII_PHYIDR1, &dummy); /* dummy read cycle */ | | 1802 | mii_readreg(self, phy, MII_PHYIDR1, &dummy); /* dummy read cycle */ |
1811 | return 0; | | 1803 | return 0; |
1812 | } | | 1804 | } |
1813 | | | 1805 | |
1814 | static void | | 1806 | static void |
1815 | phy_tick(void *arg) | | 1807 | phy_tick(void *arg) |
1816 | { | | 1808 | { |
1817 | struct scx_softc *sc = arg; | | 1809 | struct scx_softc *sc = arg; |
1818 | struct mii_data *mii = &sc->sc_mii; | | 1810 | struct mii_data *mii = &sc->sc_mii; |
1819 | int s; | | 1811 | int s; |
1820 | | | 1812 | |
1821 | s = splnet(); | | 1813 | s = splnet(); |
1822 | mii_tick(mii); | | 1814 | mii_tick(mii); |
1823 | splx(s); | | 1815 | splx(s); |
1824 | #ifdef GMAC_EVENT_COUNTERS | | 1816 | #ifdef GMAC_EVENT_COUNTERS |
1825 | /* 80 event counters exist */ | | 1817 | /* 80 event counters exist */ |
1826 | #endif | | 1818 | #endif |
1827 | callout_schedule(&sc->sc_callout, hz); | | 1819 | callout_schedule(&sc->sc_callout, hz); |
1828 | } | | 1820 | } |
1829 | | | 1821 | |
1830 | static void | | 1822 | static void |
1831 | stopuengine(struct scx_softc *sc) | | 1823 | resetuengine(struct scx_softc *sc) |
1832 | { | | 1824 | { |
1833 | | | 1825 | |
1834 | if (CSR_READ(sc, CORESTAT) != 0) { | | 1826 | if (CSR_READ(sc, CORESTAT) == 0) { |
| | | 1827 | /* make sure to stop */ |
1835 | CSR_WRITE(sc, DMACTL_H2M, DMACTL_STOP); | | 1828 | CSR_WRITE(sc, DMACTL_H2M, DMACTL_STOP); |
1836 | CSR_WRITE(sc, DMACTL_M2H, DMACTL_STOP); | | 1829 | CSR_WRITE(sc, DMACTL_M2H, DMACTL_STOP); |
1837 | WAIT_FOR_CLR(sc, DMACTL_H2M, DMACTL_STOP, 0); | | 1830 | WAIT_FOR_CLR(sc, DMACTL_H2M, DMACTL_STOP); |
1838 | WAIT_FOR_CLR(sc, DMACTL_M2H, DMACTL_STOP, 0); | | 1831 | WAIT_FOR_CLR(sc, DMACTL_M2H, DMACTL_STOP); |
1839 | } | | 1832 | } |
1840 | CSR_WRITE(sc, SWRESET, 0); /* reset operation */ | | 1833 | CSR_WRITE(sc, SWRESET, 0); /* reset operation */ |
1841 | CSR_WRITE(sc, SWRESET, SRST_RUN); /* manifest run */ | | 1834 | CSR_WRITE(sc, SWRESET, SRST_RUN); /* manifest run */ |
1842 | CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS); | | 1835 | CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS); |
1843 | WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS), 0); | | 1836 | WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS)); |
1844 | } | | 1837 | } |
1845 | | | 1838 | |
1846 | static void | | 1839 | #define UCODE_DEBUG 0 |
1847 | startuengine(struct scx_softc *sc) | | | |
1848 | { | | | |
1849 | int err; | | | |
1850 | | | | |
1851 | CSR_WRITE(sc, CORESTAT, 0); | | | |
1852 | err = WAIT_FOR_SET(sc, xINTSR, IRQ_UCODE, 0); | | | |
1853 | if (err) { | | | |
1854 | aprint_error_dev(sc->sc_dev, "uengine start failed\n"); | | | |
1855 | } | | | |
1856 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); | | | |
1857 | } | | | |
1858 | | | 1840 | |
1859 | /* | | 1841 | /* |
1860 | * 3 independent uengines exist to process host2media, media2host and | | 1842 | * 3 independent uengines exist to process host2media, media2host and |
1861 | * packet data flows. | | 1843 | * packet data flows. |
1862 | */ | | 1844 | */ |
1863 | static void | | 1845 | static void |
1864 | loaducode(struct scx_softc *sc) | | 1846 | loaducode(struct scx_softc *sc) |
1865 | { | | 1847 | { |
1866 | uint32_t up, lo, sz; | | 1848 | uint32_t up, lo, sz; |
1867 | uint64_t addr; | | 1849 | uint64_t addr; |
| | | 1850 | int err; |
1868 | | | 1851 | |
1869 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); | | 1852 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); |
1870 | | | 1853 | |
1871 | up = EE_READ(sc, 0x08); /* H->M ucode addr high */ | | 1854 | up = EE_READ(sc, 0x08); /* H->M ucode addr high */ |
1872 | lo = EE_READ(sc, 0x0c); /* H->M ucode addr low */ | | 1855 | lo = EE_READ(sc, 0x0c); /* H->M ucode addr low */ |
1873 | sz = EE_READ(sc, 0x10); /* H->M ucode size */ | | 1856 | sz = EE_READ(sc, 0x10); /* H->M ucode size */ |
1874 | sz *= 4; | | 1857 | sz *= 4; |
1875 | addr = ((uint64_t)up << 32) | lo; | | 1858 | addr = ((uint64_t)up << 32) | lo; |
1876 | aprint_normal_dev(sc->sc_dev, "0x%x H2M ucode %u\n", lo, sz); | | | |
1877 | injectucode(sc, UCODE_H2M, (bus_addr_t)addr, (bus_size_t)sz); | | 1859 | injectucode(sc, UCODE_H2M, (bus_addr_t)addr, (bus_size_t)sz); |
| | | 1860 | #if UCODE_DEBUG == 1 |
| | | 1861 | aprint_normal_dev(sc->sc_dev, "0x%x H2M ucode %u\n", lo, sz); |
| | | 1862 | #endif |
1878 | | | 1863 | |
1879 | up = EE_READ(sc, 0x14); /* M->H ucode addr high */ | | 1864 | up = EE_READ(sc, 0x14); /* M->H ucode addr high */ |
1880 | lo = EE_READ(sc, 0x18); /* M->H ucode addr low */ | | 1865 | lo = EE_READ(sc, 0x18); /* M->H ucode addr low */ |
1881 | sz = EE_READ(sc, 0x1c); /* M->H ucode size */ | | 1866 | sz = EE_READ(sc, 0x1c); /* M->H ucode size */ |
1882 | sz *= 4; | | 1867 | sz *= 4; |
1883 | addr = ((uint64_t)up << 32) | lo; | | 1868 | addr = ((uint64_t)up << 32) | lo; |
1884 | injectucode(sc, UCODE_M2H, (bus_addr_t)addr, (bus_size_t)sz); | | 1869 | injectucode(sc, UCODE_M2H, (bus_addr_t)addr, (bus_size_t)sz); |
| | | 1870 | #if UCODE_DEBUG == 1 |
1885 | aprint_normal_dev(sc->sc_dev, "0x%x M2H ucode %u\n", lo, sz); | | 1871 | aprint_normal_dev(sc->sc_dev, "0x%x M2H ucode %u\n", lo, sz); |
| | | 1872 | #endif |
1886 | | | 1873 | |
1887 | lo = EE_READ(sc, 0x20); /* PKT ucode addr */ | | 1874 | lo = EE_READ(sc, 0x20); /* PKT ucode addr */ |
1888 | sz = EE_READ(sc, 0x24); /* PKT ucode size */ | | 1875 | sz = EE_READ(sc, 0x24); /* PKT ucode size */ |
1889 | sz *= 4; | | 1876 | sz *= 4; |
1890 | injectucode(sc, UCODE_PKT, (bus_addr_t)lo, (bus_size_t)sz); | | 1877 | injectucode(sc, UCODE_PKT, (bus_addr_t)lo, (bus_size_t)sz); |
| | | 1878 | #if UCODE_DEBUG == 1 |
1891 | aprint_normal_dev(sc->sc_dev, "0x%x PKT ucode %u\n", lo, sz); | | 1879 | aprint_normal_dev(sc->sc_dev, "0x%x PKT ucode %u\n", lo, sz); |
| | | 1880 | #endif |
| | | 1881 | |
| | | 1882 | CSR_WRITE(sc, CORESTAT, 0); |
| | | 1883 | err = WAIT_FOR_SET(sc, xINTSR, IRQ_UCODE); |
| | | 1884 | if (err) { |
| | | 1885 | aprint_error_dev(sc->sc_dev, "uengine start failed\n"); |
| | | 1886 | } |
| | | 1887 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); |
1892 | } | | 1888 | } |
1893 | | | 1889 | |
1894 | static void | | 1890 | static void |
1895 | injectucode(struct scx_softc *sc, int port, | | 1891 | injectucode(struct scx_softc *sc, int port, |
1896 | bus_addr_t addr, bus_size_t size) | | 1892 | bus_addr_t addr, bus_size_t size) |
1897 | { | | 1893 | { |
1898 | bus_space_handle_t bsh; | | 1894 | bus_space_handle_t bsh; |
1899 | bus_size_t off; | | 1895 | bus_size_t off; |
1900 | uint32_t ucode; | | 1896 | uint32_t ucode; |
1901 | | | 1897 | |
1902 | if (bus_space_map(sc->sc_st, addr, size, 0, &bsh) != 0) { | | 1898 | if (bus_space_map(sc->sc_st, addr, size, 0, &bsh) != 0) { |
1903 | aprint_error_dev(sc->sc_dev, | | 1899 | aprint_error_dev(sc->sc_dev, |
1904 | "eeprom map failure for ucode port 0x%x\n", port); | | 1900 | "eeprom map failure for ucode port 0x%x\n", port); |
1905 | return; | | 1901 | return; |
1906 | } | | 1902 | } |
1907 | for (off = 0; off < size; off += 4) { | | 1903 | for (off = 0; off < size; off += 4) { |
1908 | ucode = bus_space_read_4(sc->sc_st, bsh, off); | | 1904 | ucode = bus_space_read_4(sc->sc_st, bsh, off); |
1909 | CSR_WRITE(sc, port, ucode); | | 1905 | CSR_WRITE(sc, port, ucode); |
1910 | } | | 1906 | } |
1911 | bus_space_unmap(sc->sc_st, bsh, size); | | 1907 | bus_space_unmap(sc->sc_st, bsh, size); |
1912 | } | | 1908 | } |
1913 | | | 1909 | |
1914 | /* GAR 5:2 MDIO frequency selection */ | | 1910 | /* GAR 5:2 MDIO frequency selection */ |
1915 | static int | | 1911 | static int |
1916 | get_mdioclk(uint32_t freq) | | 1912 | get_mdioclk(uint32_t freq) |
1917 | { | | 1913 | { |
1918 | | | 1914 | |
1919 | freq /= 1000 * 1000; | | 1915 | freq /= 1000 * 1000; |
1920 | if (freq < 35) | | 1916 | if (freq < 35) |
1921 | return GAR_MDIO_25_35MHZ; | | 1917 | return GAR_MDIO_25_35MHZ; |
1922 | if (freq < 60) | | 1918 | if (freq < 60) |
1923 | return GAR_MDIO_35_60MHZ; | | 1919 | return GAR_MDIO_35_60MHZ; |
1924 | if (freq < 100) | | 1920 | if (freq < 100) |
1925 | return GAR_MDIO_60_100MHZ; | | 1921 | return GAR_MDIO_60_100MHZ; |
1926 | if (freq < 150) | | 1922 | if (freq < 150) |
1927 | return GAR_MDIO_100_150MHZ; | | 1923 | return GAR_MDIO_100_150MHZ; |
1928 | if (freq < 250) | | 1924 | if (freq < 250) |
1929 | return GAR_MDIO_150_250MHZ; | | 1925 | return GAR_MDIO_150_250MHZ; |
1930 | return GAR_MDIO_250_300MHZ; | | 1926 | return GAR_MDIO_250_300MHZ; |
1931 | } | | 1927 | } |
1932 | | | 1928 | |
1933 | #define HWFEA_DEBUG 1 | | 1929 | #define HWFEA_DEBUG 1 |
1934 | | | 1930 | |
1935 | void | | 1931 | static void |
1936 | dump_hwfeature(struct scx_softc *sc) | | 1932 | dump_hwfeature(struct scx_softc *sc) |
1937 | { | | 1933 | { |
1938 | #if HWFEA_DEBUG == 1 | | 1934 | #if HWFEA_DEBUG == 1 |
1939 | struct { | | 1935 | struct { |
1940 | uint32_t bit; | | 1936 | uint32_t bit; |
1941 | const char *des; | | 1937 | const char *des; |
1942 | } field[] = { | | 1938 | } field[] = { |
1943 | { 27, "SA/VLAN insertion replacement enabled" }, | | 1939 | { 27, "SA/VLAN insertion replacement enabled" }, |
1944 | { 26, "flexible PPS enabled" }, | | 1940 | { 26, "flexible PPS enabled" }, |
1945 | { 25, "time stamping with internal system enabled" }, | | 1941 | { 25, "time stamping with internal system enabled" }, |
1946 | { 24, "alternate/enhanced descriptor enabled" }, | | 1942 | { 24, "alternate/enhanced descriptor enabled" }, |
1947 | { 19, "rx FIFO >2048 enabled" }, | | 1943 | { 19, "rx FIFO >2048 enabled" }, |
1948 | { 18, "type 2 IP checksum offload enabled" }, | | 1944 | { 18, "type 2 IP checksum offload enabled" }, |
1949 | { 17, "type 1 IP checksum offload enabled" }, | | 1945 | { 17, "type 1 IP checksum offload enabled" }, |
1950 | { 16, "Tx checksum offload enabled" }, | | 1946 | { 16, "Tx checksum offload enabled" }, |
1951 | { 15, "AV feature enabled" }, | | 1947 | { 15, "AV feature enabled" }, |
1952 | { 14, "EEE energy save feature enabled" }, | | 1948 | { 14, "EEE energy save feature enabled" }, |
1953 | { 13, "1588-2008 version 2 advanced feature enabled" }, | | 1949 | { 13, "1588-2008 version 2 advanced feature enabled" }, |
1954 | { 12, "only 1588-2002 version 1 feature enabled" }, | | 1950 | { 12, "only 1588-2002 version 1 feature enabled" }, |
1955 | { 11, "RMON event counter enabled" }, | | 1951 | { 11, "RMON event counter enabled" }, |
1956 | { 10, "PMT magic packet enabled" }, | | 1952 | { 10, "PMT magic packet enabled" }, |
1957 | { 9, "PMT remote wakeup enabled" }, | | 1953 | { 9, "PMT remote wakeup enabled" }, |
1958 | { 8, "MDIO enabled", }, | | 1954 | { 8, "MDIO enabled", }, |
1959 | { 7, "L3/L4 filter enabled" }, | | 1955 | { 7, "L3/L4 filter enabled" }, |
1960 | { 6, "TBI/SGMII/RTBI support enabled" }, | | 1956 | { 6, "TBI/SGMII/RTBI support enabled" }, |
1961 | { 5, "supplimental MAC address enabled" }, | | 1957 | { 5, "supplimental MAC address enabled" }, |
1962 | { 4, "receive hash filter enabled" }, | | 1958 | { 4, "receive hash filter enabled" }, |
1963 | { 3, "hash size is expanded" }, | | 1959 | { 3, "hash size is expanded" }, |
1964 | { 2, "Half Duplex enabled" }, | | 1960 | { 2, "Half Duplex enabled" }, |
1965 | { 1, "1000 Mbps enabled" }, | | 1961 | { 1, "1000 Mbps enabled" }, |
1966 | { 0, "10/100 Mbps enabled" }, | | 1962 | { 0, "10/100 Mbps enabled" }, |
1967 | }; | | 1963 | }; |
1968 | const char *nameofmii[] = { | | 1964 | const char *nameofmii[] = { |
1969 | "GMII or MII", | | 1965 | "GMII or MII", |
1970 | "RGMII", | | 1966 | "RGMII", |
1971 | "SGMII", | | 1967 | "SGMII", |
1972 | "TBI", | | 1968 | "TBI", |
1973 | "RMII", | | 1969 | "RMII", |
1974 | "RTBI", | | 1970 | "RTBI", |
1975 | "SMII", | | 1971 | "SMII", |
1976 | "RevMII" | | 1972 | "RevMII" |
1977 | }; | | 1973 | }; |
1978 | uint32_t hwfea, mtype, txchan, rxchan; | | 1974 | uint32_t hwfea, mtype, txchan, rxchan; |
1979 | | | 1975 | |
1980 | hwfea = CSR_READ(sc, HWFEA); | | 1976 | hwfea = CSR_READ(sc, HWFEA); |
1981 | mtype = (hwfea & __BITS(30,28)) >> 28; | | 1977 | mtype = (hwfea & __BITS(30,28)) >> 28; |
1982 | aprint_normal("HWFEA 0x%08x\n", hwfea); | | 1978 | aprint_normal("HWFEA 0x%08x\n", hwfea); |
1983 | aprint_normal("%s <30:28>\n", nameofmii[mtype]); | | 1979 | aprint_normal("%s <30:28>\n", nameofmii[mtype]); |
1984 | for (unsigned i = 0; i < __arraycount(field); i++) { | | 1980 | for (unsigned i = 0; i < __arraycount(field); i++) { |
1985 | if ((hwfea & (1U << field[i].bit)) == 0) | | 1981 | if ((hwfea & (1U << field[i].bit)) == 0) |
1986 | continue; | | 1982 | continue; |
1987 | aprint_normal("%s <%d>\n", field[i].des, field[i].bit); | | 1983 | aprint_normal("%s <%d>\n", field[i].des, field[i].bit); |
1988 | } | | 1984 | } |
1989 | if ((txchan = (hwfea & __BITS(23,22)) >> 22) != 0) | | 1985 | if ((txchan = (hwfea & __BITS(23,22)) >> 22) != 0) |
1990 | aprint_normal("+%d tx channel available <23,22>\n", txchan); | | 1986 | aprint_normal("+%d tx channel available <23,22>\n", txchan); |
1991 | if ((rxchan = (hwfea & __BITS(21,20)) >> 20) != 0) | | 1987 | if ((rxchan = (hwfea & __BITS(21,20)) >> 20) != 0) |
1992 | aprint_normal("+%d rx channel available <21:20>\n", rxchan); | | 1988 | aprint_normal("+%d rx channel available <21:20>\n", rxchan); |
1993 | return; | | 1989 | return; |
1994 | #endif | | 1990 | #endif |
1995 | } | | 1991 | } |