diff options
author | Jose Abreu <Jose.Abreu@synopsys.com> | 2018-08-08 04:04:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-09 14:16:28 -0400 |
commit | 874dfb65a484cff9b95014ed66c7cc6d2d6c4436 (patch) | |
tree | 852c5312b6e11ad91e3526fdfd0b8ab11f7a816f | |
parent | d6ddfacd95c79d43465d4a85dffb1c9beca343a9 (diff) |
net: stmmac: Add descriptor related callbacks for XGMAC2
Add the descriptor related callbacks for the new IP block XGMAC2.
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | 280 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 |
5 files changed, 314 insertions, 2 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index da40d3bba037..99967a80a8c8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile | |||
@@ -5,7 +5,8 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ | |||
5 | dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ | 5 | dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ |
6 | mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ | 6 | mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ |
7 | dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ | 7 | dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ |
8 | stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o $(stmmac-y) | 8 | stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \ |
9 | $(stmmac-y) | ||
9 | 10 | ||
10 | # Ordering matters. Generic driver must be last. | 11 | # Ordering matters. Generic driver must be last. |
11 | obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o | 12 | obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index a6992332f801..0a80fa25afe3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | |||
@@ -195,4 +195,34 @@ | |||
195 | #define XGMAC_TPS BIT(1) | 195 | #define XGMAC_TPS BIT(1) |
196 | #define XGMAC_TI BIT(0) | 196 | #define XGMAC_TI BIT(0) |
197 | 197 | ||
198 | /* Descriptors */ | ||
199 | #define XGMAC_TDES2_IOC BIT(31) | ||
200 | #define XGMAC_TDES2_TTSE BIT(30) | ||
201 | #define XGMAC_TDES2_B2L GENMASK(29, 16) | ||
202 | #define XGMAC_TDES2_B2L_SHIFT 16 | ||
203 | #define XGMAC_TDES2_B1L GENMASK(13, 0) | ||
204 | #define XGMAC_TDES3_OWN BIT(31) | ||
205 | #define XGMAC_TDES3_CTXT BIT(30) | ||
206 | #define XGMAC_TDES3_FD BIT(29) | ||
207 | #define XGMAC_TDES3_LD BIT(28) | ||
208 | #define XGMAC_TDES3_CPC GENMASK(27, 26) | ||
209 | #define XGMAC_TDES3_CPC_SHIFT 26 | ||
210 | #define XGMAC_TDES3_TCMSSV BIT(26) | ||
211 | #define XGMAC_TDES3_THL GENMASK(22, 19) | ||
212 | #define XGMAC_TDES3_THL_SHIFT 19 | ||
213 | #define XGMAC_TDES3_TSE BIT(18) | ||
214 | #define XGMAC_TDES3_CIC GENMASK(17, 16) | ||
215 | #define XGMAC_TDES3_CIC_SHIFT 16 | ||
216 | #define XGMAC_TDES3_TPL GENMASK(17, 0) | ||
217 | #define XGMAC_TDES3_FL GENMASK(14, 0) | ||
218 | #define XGMAC_RDES3_OWN BIT(31) | ||
219 | #define XGMAC_RDES3_CTXT BIT(30) | ||
220 | #define XGMAC_RDES3_IOC BIT(30) | ||
221 | #define XGMAC_RDES3_LD BIT(28) | ||
222 | #define XGMAC_RDES3_CDA BIT(27) | ||
223 | #define XGMAC_RDES3_ES BIT(15) | ||
224 | #define XGMAC_RDES3_PL GENMASK(13, 0) | ||
225 | #define XGMAC_RDES3_TSD BIT(6) | ||
226 | #define XGMAC_RDES3_TSA BIT(4) | ||
227 | |||
198 | #endif /* __STMMAC_DWXGMAC2_H__ */ | 228 | #endif /* __STMMAC_DWXGMAC2_H__ */ |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c new file mode 100644 index 000000000000..1d858fdec997 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c | |||
@@ -0,0 +1,280 @@ | |||
1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) | ||
2 | /* | ||
3 | * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. | ||
4 | * stmmac XGMAC support. | ||
5 | */ | ||
6 | |||
7 | #include <linux/stmmac.h> | ||
8 | #include "common.h" | ||
9 | #include "dwxgmac2.h" | ||
10 | |||
11 | static int dwxgmac2_get_tx_status(void *data, struct stmmac_extra_stats *x, | ||
12 | struct dma_desc *p, void __iomem *ioaddr) | ||
13 | { | ||
14 | unsigned int tdes3 = le32_to_cpu(p->des3); | ||
15 | int ret = tx_done; | ||
16 | |||
17 | if (unlikely(tdes3 & XGMAC_TDES3_OWN)) | ||
18 | return tx_dma_own; | ||
19 | if (likely(!(tdes3 & XGMAC_TDES3_LD))) | ||
20 | return tx_not_ls; | ||
21 | |||
22 | return ret; | ||
23 | } | ||
24 | |||
25 | static int dwxgmac2_get_rx_status(void *data, struct stmmac_extra_stats *x, | ||
26 | struct dma_desc *p) | ||
27 | { | ||
28 | unsigned int rdes3 = le32_to_cpu(p->des3); | ||
29 | int ret = good_frame; | ||
30 | |||
31 | if (unlikely(rdes3 & XGMAC_RDES3_OWN)) | ||
32 | return dma_own; | ||
33 | if (likely(!(rdes3 & XGMAC_RDES3_LD))) | ||
34 | return discard_frame; | ||
35 | if (unlikely(rdes3 & XGMAC_RDES3_ES)) | ||
36 | ret = discard_frame; | ||
37 | |||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | static int dwxgmac2_get_tx_len(struct dma_desc *p) | ||
42 | { | ||
43 | return (le32_to_cpu(p->des2) & XGMAC_TDES2_B1L); | ||
44 | } | ||
45 | |||
46 | static int dwxgmac2_get_tx_owner(struct dma_desc *p) | ||
47 | { | ||
48 | return (le32_to_cpu(p->des3) & XGMAC_TDES3_OWN) > 0; | ||
49 | } | ||
50 | |||
51 | static void dwxgmac2_set_tx_owner(struct dma_desc *p) | ||
52 | { | ||
53 | p->des3 |= cpu_to_le32(XGMAC_TDES3_OWN); | ||
54 | } | ||
55 | |||
56 | static void dwxgmac2_set_rx_owner(struct dma_desc *p, int disable_rx_ic) | ||
57 | { | ||
58 | p->des3 = cpu_to_le32(XGMAC_RDES3_OWN); | ||
59 | |||
60 | if (!disable_rx_ic) | ||
61 | p->des3 |= cpu_to_le32(XGMAC_RDES3_IOC); | ||
62 | } | ||
63 | |||
64 | static int dwxgmac2_get_tx_ls(struct dma_desc *p) | ||
65 | { | ||
66 | return (le32_to_cpu(p->des3) & XGMAC_RDES3_LD) > 0; | ||
67 | } | ||
68 | |||
69 | static int dwxgmac2_get_rx_frame_len(struct dma_desc *p, int rx_coe) | ||
70 | { | ||
71 | return (le32_to_cpu(p->des3) & XGMAC_RDES3_PL); | ||
72 | } | ||
73 | |||
74 | static void dwxgmac2_enable_tx_timestamp(struct dma_desc *p) | ||
75 | { | ||
76 | p->des2 |= cpu_to_le32(XGMAC_TDES2_TTSE); | ||
77 | } | ||
78 | |||
79 | static int dwxgmac2_get_tx_timestamp_status(struct dma_desc *p) | ||
80 | { | ||
81 | return 0; /* Not supported */ | ||
82 | } | ||
83 | |||
84 | static inline void dwxgmac2_get_timestamp(void *desc, u32 ats, u64 *ts) | ||
85 | { | ||
86 | struct dma_desc *p = (struct dma_desc *)desc; | ||
87 | u64 ns = 0; | ||
88 | |||
89 | ns += le32_to_cpu(p->des1) * 1000000000ULL; | ||
90 | ns += le32_to_cpu(p->des0); | ||
91 | |||
92 | *ts = ns; | ||
93 | } | ||
94 | |||
95 | static int dwxgmac2_rx_check_timestamp(void *desc) | ||
96 | { | ||
97 | struct dma_desc *p = (struct dma_desc *)desc; | ||
98 | unsigned int rdes3 = le32_to_cpu(p->des3); | ||
99 | bool desc_valid, ts_valid; | ||
100 | |||
101 | desc_valid = !(rdes3 & XGMAC_RDES3_OWN) && (rdes3 & XGMAC_RDES3_CTXT); | ||
102 | ts_valid = !(rdes3 & XGMAC_RDES3_TSD) && (rdes3 & XGMAC_RDES3_TSA); | ||
103 | |||
104 | if (likely(desc_valid && ts_valid)) | ||
105 | return 0; | ||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | static int dwxgmac2_get_rx_timestamp_status(void *desc, void *next_desc, | ||
110 | u32 ats) | ||
111 | { | ||
112 | struct dma_desc *p = (struct dma_desc *)desc; | ||
113 | unsigned int rdes3 = le32_to_cpu(p->des3); | ||
114 | int ret = -EBUSY; | ||
115 | |||
116 | if (likely(rdes3 & XGMAC_RDES3_CDA)) { | ||
117 | ret = dwxgmac2_rx_check_timestamp(next_desc); | ||
118 | if (ret) | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic, | ||
126 | int mode, int end) | ||
127 | { | ||
128 | dwxgmac2_set_rx_owner(p, disable_rx_ic); | ||
129 | } | ||
130 | |||
131 | static void dwxgmac2_init_tx_desc(struct dma_desc *p, int mode, int end) | ||
132 | { | ||
133 | p->des0 = 0; | ||
134 | p->des1 = 0; | ||
135 | p->des2 = 0; | ||
136 | p->des3 = 0; | ||
137 | } | ||
138 | |||
139 | static void dwxgmac2_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, | ||
140 | bool csum_flag, int mode, bool tx_own, | ||
141 | bool ls, unsigned int tot_pkt_len) | ||
142 | { | ||
143 | unsigned int tdes3 = le32_to_cpu(p->des3); | ||
144 | |||
145 | p->des2 |= cpu_to_le32(len & XGMAC_TDES2_B1L); | ||
146 | |||
147 | tdes3 = tot_pkt_len & XGMAC_TDES3_FL; | ||
148 | if (is_fs) | ||
149 | tdes3 |= XGMAC_TDES3_FD; | ||
150 | else | ||
151 | tdes3 &= ~XGMAC_TDES3_FD; | ||
152 | |||
153 | if (csum_flag) | ||
154 | tdes3 |= 0x3 << XGMAC_TDES3_CIC_SHIFT; | ||
155 | else | ||
156 | tdes3 &= ~XGMAC_TDES3_CIC; | ||
157 | |||
158 | if (ls) | ||
159 | tdes3 |= XGMAC_TDES3_LD; | ||
160 | else | ||
161 | tdes3 &= ~XGMAC_TDES3_LD; | ||
162 | |||
163 | /* Finally set the OWN bit. Later the DMA will start! */ | ||
164 | if (tx_own) | ||
165 | tdes3 |= XGMAC_TDES3_OWN; | ||
166 | |||
167 | if (is_fs && tx_own) | ||
168 | /* When the own bit, for the first frame, has to be set, all | ||
169 | * descriptors for the same frame has to be set before, to | ||
170 | * avoid race condition. | ||
171 | */ | ||
172 | dma_wmb(); | ||
173 | |||
174 | p->des3 = cpu_to_le32(tdes3); | ||
175 | } | ||
176 | |||
177 | static void dwxgmac2_prepare_tso_tx_desc(struct dma_desc *p, int is_fs, | ||
178 | int len1, int len2, bool tx_own, | ||
179 | bool ls, unsigned int tcphdrlen, | ||
180 | unsigned int tcppayloadlen) | ||
181 | { | ||
182 | unsigned int tdes3 = le32_to_cpu(p->des3); | ||
183 | |||
184 | if (len1) | ||
185 | p->des2 |= cpu_to_le32(len1 & XGMAC_TDES2_B1L); | ||
186 | if (len2) | ||
187 | p->des2 |= cpu_to_le32((len2 << XGMAC_TDES2_B2L_SHIFT) & | ||
188 | XGMAC_TDES2_B2L); | ||
189 | if (is_fs) { | ||
190 | tdes3 |= XGMAC_TDES3_FD | XGMAC_TDES3_TSE; | ||
191 | tdes3 |= (tcphdrlen << XGMAC_TDES3_THL_SHIFT) & | ||
192 | XGMAC_TDES3_THL; | ||
193 | tdes3 |= tcppayloadlen & XGMAC_TDES3_TPL; | ||
194 | } else { | ||
195 | tdes3 &= ~XGMAC_TDES3_FD; | ||
196 | } | ||
197 | |||
198 | if (ls) | ||
199 | tdes3 |= XGMAC_TDES3_LD; | ||
200 | else | ||
201 | tdes3 &= ~XGMAC_TDES3_LD; | ||
202 | |||
203 | /* Finally set the OWN bit. Later the DMA will start! */ | ||
204 | if (tx_own) | ||
205 | tdes3 |= XGMAC_TDES3_OWN; | ||
206 | |||
207 | if (is_fs && tx_own) | ||
208 | /* When the own bit, for the first frame, has to be set, all | ||
209 | * descriptors for the same frame has to be set before, to | ||
210 | * avoid race condition. | ||
211 | */ | ||
212 | dma_wmb(); | ||
213 | |||
214 | p->des3 = cpu_to_le32(tdes3); | ||
215 | } | ||
216 | |||
217 | static void dwxgmac2_release_tx_desc(struct dma_desc *p, int mode) | ||
218 | { | ||
219 | p->des0 = 0; | ||
220 | p->des1 = 0; | ||
221 | p->des2 = 0; | ||
222 | p->des3 = 0; | ||
223 | } | ||
224 | |||
225 | static void dwxgmac2_set_tx_ic(struct dma_desc *p) | ||
226 | { | ||
227 | p->des2 |= cpu_to_le32(XGMAC_TDES2_IOC); | ||
228 | } | ||
229 | |||
230 | static void dwxgmac2_set_mss(struct dma_desc *p, unsigned int mss) | ||
231 | { | ||
232 | p->des0 = 0; | ||
233 | p->des1 = 0; | ||
234 | p->des2 = cpu_to_le32(mss); | ||
235 | p->des3 = cpu_to_le32(XGMAC_TDES3_CTXT | XGMAC_TDES3_TCMSSV); | ||
236 | } | ||
237 | |||
238 | static void dwxgmac2_get_addr(struct dma_desc *p, unsigned int *addr) | ||
239 | { | ||
240 | *addr = le32_to_cpu(p->des0); | ||
241 | } | ||
242 | |||
243 | static void dwxgmac2_set_addr(struct dma_desc *p, dma_addr_t addr) | ||
244 | { | ||
245 | p->des0 = cpu_to_le32(addr); | ||
246 | p->des1 = 0; | ||
247 | } | ||
248 | |||
249 | static void dwxgmac2_clear(struct dma_desc *p) | ||
250 | { | ||
251 | p->des0 = 0; | ||
252 | p->des1 = 0; | ||
253 | p->des2 = 0; | ||
254 | p->des3 = 0; | ||
255 | } | ||
256 | |||
257 | const struct stmmac_desc_ops dwxgmac210_desc_ops = { | ||
258 | .tx_status = dwxgmac2_get_tx_status, | ||
259 | .rx_status = dwxgmac2_get_rx_status, | ||
260 | .get_tx_len = dwxgmac2_get_tx_len, | ||
261 | .get_tx_owner = dwxgmac2_get_tx_owner, | ||
262 | .set_tx_owner = dwxgmac2_set_tx_owner, | ||
263 | .set_rx_owner = dwxgmac2_set_rx_owner, | ||
264 | .get_tx_ls = dwxgmac2_get_tx_ls, | ||
265 | .get_rx_frame_len = dwxgmac2_get_rx_frame_len, | ||
266 | .enable_tx_timestamp = dwxgmac2_enable_tx_timestamp, | ||
267 | .get_tx_timestamp_status = dwxgmac2_get_tx_timestamp_status, | ||
268 | .get_rx_timestamp_status = dwxgmac2_get_rx_timestamp_status, | ||
269 | .get_timestamp = dwxgmac2_get_timestamp, | ||
270 | .set_tx_ic = dwxgmac2_set_tx_ic, | ||
271 | .prepare_tx_desc = dwxgmac2_prepare_tx_desc, | ||
272 | .prepare_tso_tx_desc = dwxgmac2_prepare_tso_tx_desc, | ||
273 | .release_tx_desc = dwxgmac2_release_tx_desc, | ||
274 | .init_rx_desc = dwxgmac2_init_rx_desc, | ||
275 | .init_tx_desc = dwxgmac2_init_tx_desc, | ||
276 | .set_mss = dwxgmac2_set_mss, | ||
277 | .get_addr = dwxgmac2_get_addr, | ||
278 | .set_addr = dwxgmac2_set_addr, | ||
279 | .clear = dwxgmac2_clear, | ||
280 | }; | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 4030199aee7b..4b4ba1c8bad5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c | |||
@@ -196,7 +196,7 @@ static const struct stmmac_hwif_entry { | |||
196 | .ptp_off = 0, | 196 | .ptp_off = 0, |
197 | .mmc_off = 0, | 197 | .mmc_off = 0, |
198 | }, | 198 | }, |
199 | .desc = NULL, | 199 | .desc = &dwxgmac210_desc_ops, |
200 | .dma = &dwxgmac210_dma_ops, | 200 | .dma = &dwxgmac210_dma_ops, |
201 | .mac = &dwxgmac210_ops, | 201 | .mac = &dwxgmac210_ops, |
202 | .hwtimestamp = NULL, | 202 | .hwtimestamp = NULL, |
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 3106eaca60cd..92b8944f26e3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h | |||
@@ -481,6 +481,7 @@ extern const struct stmmac_ops dwmac510_ops; | |||
481 | extern const struct stmmac_tc_ops dwmac510_tc_ops; | 481 | extern const struct stmmac_tc_ops dwmac510_tc_ops; |
482 | extern const struct stmmac_ops dwxgmac210_ops; | 482 | extern const struct stmmac_ops dwxgmac210_ops; |
483 | extern const struct stmmac_dma_ops dwxgmac210_dma_ops; | 483 | extern const struct stmmac_dma_ops dwxgmac210_dma_ops; |
484 | extern const struct stmmac_desc_ops dwxgmac210_desc_ops; | ||
484 | 485 | ||
485 | #define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ | 486 | #define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ |
486 | #define GMAC4_VERSION 0x00000110 /* GMAC4+ CORE Version */ | 487 | #define GMAC4_VERSION 0x00000110 /* GMAC4+ CORE Version */ |