Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
[linux-2.6-microblaze.git] / drivers / net / ethernet / freescale / dpaa2 / dpaa2-mac.c
1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2019 NXP */
3
4 #include "dpaa2-eth.h"
5 #include "dpaa2-mac.h"
6
7 #define phylink_to_dpaa2_mac(config) \
8         container_of((config), struct dpaa2_mac, phylink_config)
9
10 static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
11 {
12         *if_mode = PHY_INTERFACE_MODE_NA;
13
14         switch (eth_if) {
15         case DPMAC_ETH_IF_RGMII:
16                 *if_mode = PHY_INTERFACE_MODE_RGMII;
17                 break;
18         default:
19                 return -EINVAL;
20         }
21
22         return 0;
23 }
24
25 /* Caller must call of_node_put on the returned value */
26 static struct device_node *dpaa2_mac_get_node(u16 dpmac_id)
27 {
28         struct device_node *dpmacs, *dpmac = NULL;
29         u32 id;
30         int err;
31
32         dpmacs = of_find_node_by_name(NULL, "dpmacs");
33         if (!dpmacs)
34                 return NULL;
35
36         while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) {
37                 err = of_property_read_u32(dpmac, "reg", &id);
38                 if (err)
39                         continue;
40                 if (id == dpmac_id)
41                         break;
42         }
43
44         of_node_put(dpmacs);
45
46         return dpmac;
47 }
48
49 static int dpaa2_mac_get_if_mode(struct device_node *node,
50                                  struct dpmac_attr attr)
51 {
52         phy_interface_t if_mode;
53         int err;
54
55         err = of_get_phy_mode(node, &if_mode);
56         if (!err)
57                 return if_mode;
58
59         err = phy_mode(attr.eth_if, &if_mode);
60         if (!err)
61                 return if_mode;
62
63         return err;
64 }
65
66 static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac,
67                                         phy_interface_t interface)
68 {
69         switch (interface) {
70         case PHY_INTERFACE_MODE_RGMII:
71         case PHY_INTERFACE_MODE_RGMII_ID:
72         case PHY_INTERFACE_MODE_RGMII_RXID:
73         case PHY_INTERFACE_MODE_RGMII_TXID:
74                 return (interface != mac->if_mode);
75         default:
76                 return true;
77         }
78 }
79
80 static void dpaa2_mac_validate(struct phylink_config *config,
81                                unsigned long *supported,
82                                struct phylink_link_state *state)
83 {
84         struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
85         __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
86
87         if (state->interface != PHY_INTERFACE_MODE_NA &&
88             dpaa2_mac_phy_mode_mismatch(mac, state->interface)) {
89                 goto empty_set;
90         }
91
92         phylink_set_port_modes(mask);
93         phylink_set(mask, Autoneg);
94         phylink_set(mask, Pause);
95         phylink_set(mask, Asym_Pause);
96
97         switch (state->interface) {
98         case PHY_INTERFACE_MODE_RGMII:
99         case PHY_INTERFACE_MODE_RGMII_ID:
100         case PHY_INTERFACE_MODE_RGMII_RXID:
101         case PHY_INTERFACE_MODE_RGMII_TXID:
102                 phylink_set(mask, 10baseT_Full);
103                 phylink_set(mask, 100baseT_Full);
104                 phylink_set(mask, 1000baseT_Full);
105                 break;
106         default:
107                 goto empty_set;
108         }
109
110         linkmode_and(supported, supported, mask);
111         linkmode_and(state->advertising, state->advertising, mask);
112
113         return;
114
115 empty_set:
116         linkmode_zero(supported);
117 }
118
119 static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
120                              const struct phylink_link_state *state)
121 {
122         struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
123         struct dpmac_link_state *dpmac_state = &mac->state;
124         int err;
125
126         if (state->an_enabled)
127                 dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG;
128         else
129                 dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG;
130
131         err = dpmac_set_link_state(mac->mc_io, 0,
132                                    mac->mc_dev->mc_handle, dpmac_state);
133         if (err)
134                 netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
135                            __func__, err);
136 }
137
138 static void dpaa2_mac_link_up(struct phylink_config *config,
139                               struct phy_device *phy,
140                               unsigned int mode, phy_interface_t interface,
141                               int speed, int duplex,
142                               bool tx_pause, bool rx_pause)
143 {
144         struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
145         struct dpmac_link_state *dpmac_state = &mac->state;
146         int err;
147
148         dpmac_state->up = 1;
149
150         if (mac->if_link_type == DPMAC_LINK_TYPE_PHY) {
151                 /* If the DPMAC is configured for PHY mode, we need
152                  * to pass the link parameters to the MC firmware.
153                  */
154                 dpmac_state->rate = speed;
155
156                 if (duplex == DUPLEX_HALF)
157                         dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
158                 else if (duplex == DUPLEX_FULL)
159                         dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX;
160
161                 /* This is lossy; the firmware really should take the pause
162                  * enablement status rather than pause/asym pause status.
163                  */
164                 if (rx_pause)
165                         dpmac_state->options |= DPMAC_LINK_OPT_PAUSE;
166                 else
167                         dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE;
168
169                 if (rx_pause ^ tx_pause)
170                         dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE;
171                 else
172                         dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE;
173         }
174
175         err = dpmac_set_link_state(mac->mc_io, 0,
176                                    mac->mc_dev->mc_handle, dpmac_state);
177         if (err)
178                 netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
179                            __func__, err);
180 }
181
182 static void dpaa2_mac_link_down(struct phylink_config *config,
183                                 unsigned int mode,
184                                 phy_interface_t interface)
185 {
186         struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
187         struct dpmac_link_state *dpmac_state = &mac->state;
188         int err;
189
190         dpmac_state->up = 0;
191         err = dpmac_set_link_state(mac->mc_io, 0,
192                                    mac->mc_dev->mc_handle, dpmac_state);
193         if (err)
194                 netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err);
195 }
196
197 static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
198         .validate = dpaa2_mac_validate,
199         .mac_config = dpaa2_mac_config,
200         .mac_link_up = dpaa2_mac_link_up,
201         .mac_link_down = dpaa2_mac_link_down,
202 };
203
204 bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
205                              struct fsl_mc_io *mc_io)
206 {
207         struct dpmac_attr attr;
208         bool fixed = false;
209         u16 mc_handle = 0;
210         int err;
211
212         err = dpmac_open(mc_io, 0, dpmac_dev->obj_desc.id,
213                          &mc_handle);
214         if (err || !mc_handle)
215                 return false;
216
217         err = dpmac_get_attributes(mc_io, 0, mc_handle, &attr);
218         if (err)
219                 goto out;
220
221         if (attr.link_type == DPMAC_LINK_TYPE_FIXED)
222                 fixed = true;
223
224 out:
225         dpmac_close(mc_io, 0, mc_handle);
226
227         return fixed;
228 }
229
230 int dpaa2_mac_connect(struct dpaa2_mac *mac)
231 {
232         struct fsl_mc_device *dpmac_dev = mac->mc_dev;
233         struct net_device *net_dev = mac->net_dev;
234         struct device_node *dpmac_node;
235         struct phylink *phylink;
236         struct dpmac_attr attr;
237         int err;
238
239         err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id,
240                          &dpmac_dev->mc_handle);
241         if (err || !dpmac_dev->mc_handle) {
242                 netdev_err(net_dev, "dpmac_open() = %d\n", err);
243                 return -ENODEV;
244         }
245
246         err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle, &attr);
247         if (err) {
248                 netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err);
249                 goto err_close_dpmac;
250         }
251
252         mac->if_link_type = attr.link_type;
253
254         dpmac_node = dpaa2_mac_get_node(attr.id);
255         if (!dpmac_node) {
256                 netdev_err(net_dev, "No dpmac@%d node found.\n", attr.id);
257                 err = -ENODEV;
258                 goto err_close_dpmac;
259         }
260
261         err = dpaa2_mac_get_if_mode(dpmac_node, attr);
262         if (err < 0) {
263                 err = -EINVAL;
264                 goto err_put_node;
265         }
266         mac->if_mode = err;
267
268         /* The MAC does not have the capability to add RGMII delays so
269          * error out if the interface mode requests them and there is no PHY
270          * to act upon them
271          */
272         if (of_phy_is_fixed_link(dpmac_node) &&
273             (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID ||
274              mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
275              mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) {
276                 netdev_err(net_dev, "RGMII delay not supported\n");
277                 err = -EINVAL;
278                 goto err_put_node;
279         }
280
281         mac->phylink_config.dev = &net_dev->dev;
282         mac->phylink_config.type = PHYLINK_NETDEV;
283
284         phylink = phylink_create(&mac->phylink_config,
285                                  of_fwnode_handle(dpmac_node), mac->if_mode,
286                                  &dpaa2_mac_phylink_ops);
287         if (IS_ERR(phylink)) {
288                 err = PTR_ERR(phylink);
289                 goto err_put_node;
290         }
291         mac->phylink = phylink;
292
293         err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
294         if (err) {
295                 netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err);
296                 goto err_phylink_destroy;
297         }
298
299         of_node_put(dpmac_node);
300
301         return 0;
302
303 err_phylink_destroy:
304         phylink_destroy(mac->phylink);
305 err_put_node:
306         of_node_put(dpmac_node);
307 err_close_dpmac:
308         dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
309         return err;
310 }
311
312 void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
313 {
314         if (!mac->phylink)
315                 return;
316
317         phylink_disconnect_phy(mac->phylink);
318         phylink_destroy(mac->phylink);
319         dpmac_close(mac->mc_io, 0, mac->mc_dev->mc_handle);
320 }
321
322 static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
323         [DPMAC_CNT_ING_ALL_FRAME]               = "[mac] rx all frames",
324         [DPMAC_CNT_ING_GOOD_FRAME]              = "[mac] rx frames ok",
325         [DPMAC_CNT_ING_ERR_FRAME]               = "[mac] rx frame errors",
326         [DPMAC_CNT_ING_FRAME_DISCARD]           = "[mac] rx frame discards",
327         [DPMAC_CNT_ING_UCAST_FRAME]             = "[mac] rx u-cast",
328         [DPMAC_CNT_ING_BCAST_FRAME]             = "[mac] rx b-cast",
329         [DPMAC_CNT_ING_MCAST_FRAME]             = "[mac] rx m-cast",
330         [DPMAC_CNT_ING_FRAME_64]                = "[mac] rx 64 bytes",
331         [DPMAC_CNT_ING_FRAME_127]               = "[mac] rx 65-127 bytes",
332         [DPMAC_CNT_ING_FRAME_255]               = "[mac] rx 128-255 bytes",
333         [DPMAC_CNT_ING_FRAME_511]               = "[mac] rx 256-511 bytes",
334         [DPMAC_CNT_ING_FRAME_1023]              = "[mac] rx 512-1023 bytes",
335         [DPMAC_CNT_ING_FRAME_1518]              = "[mac] rx 1024-1518 bytes",
336         [DPMAC_CNT_ING_FRAME_1519_MAX]          = "[mac] rx 1519-max bytes",
337         [DPMAC_CNT_ING_FRAG]                    = "[mac] rx frags",
338         [DPMAC_CNT_ING_JABBER]                  = "[mac] rx jabber",
339         [DPMAC_CNT_ING_ALIGN_ERR]               = "[mac] rx align errors",
340         [DPMAC_CNT_ING_OVERSIZED]               = "[mac] rx oversized",
341         [DPMAC_CNT_ING_VALID_PAUSE_FRAME]       = "[mac] rx pause",
342         [DPMAC_CNT_ING_BYTE]                    = "[mac] rx bytes",
343         [DPMAC_CNT_EGR_GOOD_FRAME]              = "[mac] tx frames ok",
344         [DPMAC_CNT_EGR_UCAST_FRAME]             = "[mac] tx u-cast",
345         [DPMAC_CNT_EGR_MCAST_FRAME]             = "[mac] tx m-cast",
346         [DPMAC_CNT_EGR_BCAST_FRAME]             = "[mac] tx b-cast",
347         [DPMAC_CNT_EGR_ERR_FRAME]               = "[mac] tx frame errors",
348         [DPMAC_CNT_EGR_UNDERSIZED]              = "[mac] tx undersized",
349         [DPMAC_CNT_EGR_VALID_PAUSE_FRAME]       = "[mac] tx b-pause",
350         [DPMAC_CNT_EGR_BYTE]                    = "[mac] tx bytes",
351 };
352
353 #define DPAA2_MAC_NUM_STATS     ARRAY_SIZE(dpaa2_mac_ethtool_stats)
354
355 int dpaa2_mac_get_sset_count(void)
356 {
357         return DPAA2_MAC_NUM_STATS;
358 }
359
360 void dpaa2_mac_get_strings(u8 *data)
361 {
362         u8 *p = data;
363         int i;
364
365         for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
366                 strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
367                 p += ETH_GSTRING_LEN;
368         }
369 }
370
371 void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data)
372 {
373         struct fsl_mc_device *dpmac_dev = mac->mc_dev;
374         int i, err;
375         u64 value;
376
377         for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
378                 err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle,
379                                         i, &value);
380                 if (err) {
381                         netdev_err_once(mac->net_dev,
382                                         "dpmac_get_counter error %d\n", err);
383                         *(data + i) = U64_MAX;
384                         continue;
385                 }
386                 *(data + i) = value;
387         }
388 }