kernel: bump 4.14 to 4.14.125 (FS#2305 FS#2297)
[oweals/openwrt.git] / target / linux / layerscape / patches-4.14 / 704-dpaa2-mac-phy-support-layerscape.patch
1 From dd0cc8d0739a72ee5d85039a9ba7812383e8f555 Mon Sep 17 00:00:00 2001
2 From: Biwen Li <biwen.li@nxp.com>
3 Date: Wed, 17 Apr 2019 18:58:30 +0800
4 Subject: [PATCH] dpaa2-mac-phy: support layerscape
5
6 This is an integrated patch of dpaa2-mac-phy for layerscape
7
8 Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
9 Signed-off-by: Biwen Li <biwen.li@nxp.com>
10 Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
11 Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
12 Signed-off-by: Catalin Neacsu <valentin-catalin.neacsu@nxp.com>
13 Signed-off-by: Constantin Tudor <constantin.tudor@nxp.com>
14 Signed-off-by: Florin Chiculita <florinlaurentiu.chiculita@nxp.com>
15 Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
16 Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
17 Signed-off-by: Itai Katz <itai.katz@freescale.com>
18 Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
19 Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
20 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
21 Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
22 Signed-off-by: Valentin Catalin Neacsu <valentin-catalin.neacsu@nxp.com>
23 ---
24  drivers/staging/fsl-dpaa2/mac/Kconfig     |  23 +
25  drivers/staging/fsl-dpaa2/mac/Makefile    |  10 +
26  drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 196 ++++++
27  drivers/staging/fsl-dpaa2/mac/dpmac.c     | 689 ++++++++++++++++++
28  drivers/staging/fsl-dpaa2/mac/dpmac.h     | 374 ++++++++++
29  drivers/staging/fsl-dpaa2/mac/mac.c       | 817 ++++++++++++++++++++++
30  6 files changed, 2109 insertions(+)
31  create mode 100644 drivers/staging/fsl-dpaa2/mac/Kconfig
32  create mode 100644 drivers/staging/fsl-dpaa2/mac/Makefile
33  create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
34  create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.c
35  create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.h
36  create mode 100644 drivers/staging/fsl-dpaa2/mac/mac.c
37
38 --- /dev/null
39 +++ b/drivers/staging/fsl-dpaa2/mac/Kconfig
40 @@ -0,0 +1,23 @@
41 +config FSL_DPAA2_MAC
42 +       tristate "DPAA2 MAC / PHY interface"
43 +       depends on FSL_MC_BUS && FSL_DPAA2
44 +       select MDIO_BUS_MUX_MMIOREG
45 +       select FSL_XGMAC_MDIO
46 +       select FIXED_PHY
47 +       ---help---
48 +       Prototype driver for DPAA2 MAC / PHY interface object.
49 +       This driver works as a proxy between phylib including phy drivers and
50 +       the MC firmware.  It receives updates on link state changes from PHY
51 +       lib and forwards them to MC and receives interrupt from MC whenever
52 +       a request is made to change the link state.
53 +
54 +
55 +config FSL_DPAA2_MAC_NETDEVS
56 +       bool "Expose net interfaces for PHYs"
57 +       default n
58 +       depends on FSL_DPAA2_MAC
59 +       ---help---
60 +       Exposes macX net interfaces which allow direct control over MACs and
61 +       PHYs.
62 +       .
63 +       Leave disabled if unsure.
64 --- /dev/null
65 +++ b/drivers/staging/fsl-dpaa2/mac/Makefile
66 @@ -0,0 +1,10 @@
67 +
68 +obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o
69 +
70 +dpaa2-mac-objs := mac.o dpmac.o
71 +
72 +all:
73 +       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
74 +
75 +clean:
76 +       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
77 --- /dev/null
78 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
79 @@ -0,0 +1,196 @@
80 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
81 + *
82 + * Redistribution and use in source and binary forms, with or without
83 + * modification, are permitted provided that the following conditions are met:
84 + * * Redistributions of source code must retain the above copyright
85 + * notice, this list of conditions and the following disclaimer.
86 + * * Redistributions in binary form must reproduce the above copyright
87 + * notice, this list of conditions and the following disclaimer in the
88 + * documentation and/or other materials provided with the distribution.
89 + * * Neither the name of the above-listed copyright holders nor the
90 + * names of any contributors may be used to endorse or promote products
91 + * derived from this software without specific prior written permission.
92 + *
93 + *
94 + * ALTERNATIVELY, this software may be distributed under the terms of the
95 + * GNU General Public License ("GPL") as published by the Free Software
96 + * Foundation, either version 2 of that License or (at your option) any
97 + * later version.
98 + *
99 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
100 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
101 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
102 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
103 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
104 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
105 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
106 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
107 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
108 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
109 + * POSSIBILITY OF SUCH DAMAGE.
110 + */
111 +#ifndef _FSL_DPMAC_CMD_H
112 +#define _FSL_DPMAC_CMD_H
113 +
114 +/* DPMAC Version */
115 +#define DPMAC_VER_MAJOR                                4
116 +#define DPMAC_VER_MINOR                                2
117 +#define DPMAC_CMD_BASE_VERSION                 1
118 +#define DPMAC_CMD_2ND_VERSION                  2
119 +#define DPMAC_CMD_ID_OFFSET                    4
120 +
121 +#define DPMAC_CMD(id)  (((id) << DPMAC_CMD_ID_OFFSET) | DPMAC_CMD_BASE_VERSION)
122 +#define DPMAC_CMD_V2(id) (((id) << DPMAC_CMD_ID_OFFSET) | DPMAC_CMD_2ND_VERSION)
123 +
124 +/* Command IDs */
125 +#define DPMAC_CMDID_CLOSE              DPMAC_CMD(0x800)
126 +#define DPMAC_CMDID_OPEN               DPMAC_CMD(0x80c)
127 +#define DPMAC_CMDID_CREATE             DPMAC_CMD(0x90c)
128 +#define DPMAC_CMDID_DESTROY            DPMAC_CMD(0x98c)
129 +#define DPMAC_CMDID_GET_API_VERSION    DPMAC_CMD(0xa0c)
130 +
131 +#define DPMAC_CMDID_GET_ATTR           DPMAC_CMD(0x004)
132 +#define DPMAC_CMDID_RESET              DPMAC_CMD(0x005)
133 +
134 +#define DPMAC_CMDID_SET_IRQ_ENABLE     DPMAC_CMD(0x012)
135 +#define DPMAC_CMDID_GET_IRQ_ENABLE     DPMAC_CMD(0x013)
136 +#define DPMAC_CMDID_SET_IRQ_MASK       DPMAC_CMD(0x014)
137 +#define DPMAC_CMDID_GET_IRQ_MASK       DPMAC_CMD(0x015)
138 +#define DPMAC_CMDID_GET_IRQ_STATUS     DPMAC_CMD(0x016)
139 +#define DPMAC_CMDID_CLEAR_IRQ_STATUS   DPMAC_CMD(0x017)
140 +
141 +#define DPMAC_CMDID_GET_LINK_CFG       DPMAC_CMD(0x0c2)
142 +#define DPMAC_CMDID_GET_LINK_CFG_V2    DPMAC_CMD_V2(0x0c2)
143 +#define DPMAC_CMDID_SET_LINK_STATE     DPMAC_CMD(0x0c3)
144 +#define DPMAC_CMDID_SET_LINK_STATE_V2  DPMAC_CMD_V2(0x0c3)
145 +#define DPMAC_CMDID_GET_COUNTER                DPMAC_CMD(0x0c4)
146 +
147 +#define DPMAC_CMDID_SET_PORT_MAC_ADDR  DPMAC_CMD(0x0c5)
148 +
149 +/* Macros for accessing command fields smaller than 1byte */
150 +#define DPMAC_MASK(field)        \
151 +       GENMASK(DPMAC_##field##_SHIFT + DPMAC_##field##_SIZE - 1, \
152 +               DPMAC_##field##_SHIFT)
153 +#define dpmac_set_field(var, field, val) \
154 +       ((var) |= (((val) << DPMAC_##field##_SHIFT) & DPMAC_MASK(field)))
155 +#define dpmac_get_field(var, field)      \
156 +       (((var) & DPMAC_MASK(field)) >> DPMAC_##field##_SHIFT)
157 +
158 +struct dpmac_cmd_open {
159 +       u32 dpmac_id;
160 +};
161 +
162 +struct dpmac_cmd_create {
163 +       u32 mac_id;
164 +};
165 +
166 +struct dpmac_cmd_destroy {
167 +       u32 dpmac_id;
168 +};
169 +
170 +struct dpmac_cmd_set_irq_enable {
171 +       u8 enable;
172 +       u8 pad[3];
173 +       u8 irq_index;
174 +};
175 +
176 +struct dpmac_cmd_get_irq_enable {
177 +       u32 pad;
178 +       u8 irq_index;
179 +};
180 +
181 +struct dpmac_rsp_get_irq_enable {
182 +       u8 enabled;
183 +};
184 +
185 +struct dpmac_cmd_set_irq_mask {
186 +       u32 mask;
187 +       u8 irq_index;
188 +};
189 +
190 +struct dpmac_cmd_get_irq_mask {
191 +       u32 pad;
192 +       u8 irq_index;
193 +};
194 +
195 +struct dpmac_rsp_get_irq_mask {
196 +       u32 mask;
197 +};
198 +
199 +struct dpmac_cmd_get_irq_status {
200 +       u32 status;
201 +       u8 irq_index;
202 +};
203 +
204 +struct dpmac_rsp_get_irq_status {
205 +       u32 status;
206 +};
207 +
208 +struct dpmac_cmd_clear_irq_status {
209 +       u32 status;
210 +       u8 irq_index;
211 +};
212 +
213 +struct dpmac_rsp_get_attributes {
214 +       u8 eth_if;
215 +       u8 link_type;
216 +       u16 id;
217 +       u32 max_rate;
218 +};
219 +
220 +struct dpmac_rsp_get_link_cfg {
221 +       u64 options;
222 +       u32 rate;
223 +};
224 +
225 +struct dpmac_rsp_get_link_cfg_v2 {
226 +       u64 options;
227 +       u32 rate;
228 +       u32 pad;
229 +       u64 advertising;
230 +};
231 +
232 +#define DPMAC_STATE_SIZE       1
233 +#define DPMAC_STATE_SHIFT      0
234 +#define DPMAC_STATE_VALID_SIZE 1
235 +#define DPMAC_STATE_VALID_SHIFT        1
236 +
237 +struct dpmac_cmd_set_link_state {
238 +       u64 options;
239 +       u32 rate;
240 +       u32 pad;
241 +       /* only least significant bit is valid */
242 +       u8 up;
243 +};
244 +
245 +struct dpmac_cmd_set_link_state_v2 {
246 +       u64 options;
247 +       u32 rate;
248 +       u32 pad0;
249 +       /* from lsb: up:1, state_valid:1 */
250 +       u8 state;
251 +       u8 pad1[7];
252 +       u64 supported;
253 +       u64 advertising;
254 +};
255 +
256 +struct dpmac_cmd_get_counter {
257 +       u8 type;
258 +};
259 +
260 +struct dpmac_rsp_get_counter {
261 +       u64 pad;
262 +       u64 counter;
263 +};
264 +
265 +struct dpmac_rsp_get_api_version {
266 +       u16 major;
267 +       u16 minor;
268 +};
269 +
270 +struct dpmac_cmd_set_port_mac_addr {
271 +       u8 pad[2];
272 +       u8 addr[6];
273 +};
274 +
275 +#endif /* _FSL_DPMAC_CMD_H */
276 --- /dev/null
277 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c
278 @@ -0,0 +1,689 @@
279 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
280 + *
281 + * Redistribution and use in source and binary forms, with or without
282 + * modification, are permitted provided that the following conditions are met:
283 + * * Redistributions of source code must retain the above copyright
284 + * notice, this list of conditions and the following disclaimer.
285 + * * Redistributions in binary form must reproduce the above copyright
286 + * notice, this list of conditions and the following disclaimer in the
287 + * documentation and/or other materials provided with the distribution.
288 + * * Neither the name of the above-listed copyright holders nor the
289 + * names of any contributors may be used to endorse or promote products
290 + * derived from this software without specific prior written permission.
291 + *
292 + *
293 + * ALTERNATIVELY, this software may be distributed under the terms of the
294 + * GNU General Public License ("GPL") as published by the Free Software
295 + * Foundation, either version 2 of that License or (at your option) any
296 + * later version.
297 + *
298 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
299 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
300 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
301 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
302 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
303 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
304 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
305 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
306 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
307 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
308 + * POSSIBILITY OF SUCH DAMAGE.
309 + */
310 +#include <linux/fsl/mc.h>
311 +#include "dpmac.h"
312 +#include "dpmac-cmd.h"
313 +
314 +/**
315 + * dpmac_open() - Open a control session for the specified object.
316 + * @mc_io:     Pointer to MC portal's I/O object
317 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
318 + * @dpmac_id:  DPMAC unique ID
319 + * @token:     Returned token; use in subsequent API calls
320 + *
321 + * This function can be used to open a control session for an
322 + * already created object; an object may have been declared in
323 + * the DPL or by calling the dpmac_create function.
324 + * This function returns a unique authentication token,
325 + * associated with the specific object ID and the specific MC
326 + * portal; this token must be used in all subsequent commands for
327 + * this specific object
328 + *
329 + * Return:     '0' on Success; Error code otherwise.
330 + */
331 +int dpmac_open(struct fsl_mc_io *mc_io,
332 +              u32 cmd_flags,
333 +              int dpmac_id,
334 +              u16 *token)
335 +{
336 +       struct dpmac_cmd_open *cmd_params;
337 +       struct fsl_mc_command cmd = { 0 };
338 +       int err;
339 +
340 +       /* prepare command */
341 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
342 +                                         cmd_flags,
343 +                                         0);
344 +       cmd_params = (struct dpmac_cmd_open *)cmd.params;
345 +       cmd_params->dpmac_id = cpu_to_le32(dpmac_id);
346 +
347 +       /* send command to mc*/
348 +       err = mc_send_command(mc_io, &cmd);
349 +       if (err)
350 +               return err;
351 +
352 +       /* retrieve response parameters */
353 +       *token = mc_cmd_hdr_read_token(&cmd);
354 +
355 +       return err;
356 +}
357 +
358 +/**
359 + * dpmac_close() - Close the control session of the object
360 + * @mc_io:     Pointer to MC portal's I/O object
361 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
362 + * @token:     Token of DPMAC object
363 + *
364 + * After this function is called, no further operations are
365 + * allowed on the object without opening a new control session.
366 + *
367 + * Return:     '0' on Success; Error code otherwise.
368 + */
369 +int dpmac_close(struct fsl_mc_io *mc_io,
370 +               u32 cmd_flags,
371 +               u16 token)
372 +{
373 +       struct fsl_mc_command cmd = { 0 };
374 +
375 +       /* prepare command */
376 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
377 +                                         token);
378 +
379 +       /* send command to mc*/
380 +       return mc_send_command(mc_io, &cmd);
381 +}
382 +
383 +/**
384 + * dpmac_create() - Create the DPMAC object.
385 + * @mc_io:     Pointer to MC portal's I/O object
386 + * @dprc_token: Parent container token; '0' for default container
387 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
388 + * @cfg:       Configuration structure
389 + * @obj_id:    Returned object id
390 + *
391 + * Create the DPMAC object, allocate required resources and
392 + * perform required initialization.
393 + *
394 + * The function accepts an authentication token of a parent
395 + * container that this object should be assigned to. The token
396 + * can be '0' so the object will be assigned to the default container.
397 + * The newly created object can be opened with the returned
398 + * object id and using the container's associated tokens and MC portals.
399 + *
400 + * Return:     '0' on Success; Error code otherwise.
401 + */
402 +int dpmac_create(struct fsl_mc_io *mc_io,
403 +                u16 dprc_token,
404 +                u32 cmd_flags,
405 +                const struct dpmac_cfg *cfg,
406 +                u32 *obj_id)
407 +{
408 +       struct dpmac_cmd_create *cmd_params;
409 +       struct fsl_mc_command cmd = { 0 };
410 +       int err;
411 +
412 +       /* prepare command */
413 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
414 +                                         cmd_flags,
415 +                                         dprc_token);
416 +       cmd_params = (struct dpmac_cmd_create *)cmd.params;
417 +       cmd_params->mac_id = cpu_to_le32(cfg->mac_id);
418 +
419 +       /* send command to mc*/
420 +       err = mc_send_command(mc_io, &cmd);
421 +       if (err)
422 +               return err;
423 +
424 +       /* retrieve response parameters */
425 +       *obj_id = mc_cmd_read_object_id(&cmd);
426 +
427 +       return 0;
428 +}
429 +
430 +/**
431 + * dpmac_destroy() - Destroy the DPMAC object and release all its resources.
432 + * @mc_io:     Pointer to MC portal's I/O object
433 + * @dprc_token: Parent container token; '0' for default container
434 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
435 + * @object_id: The object id; it must be a valid id within the container that
436 + * created this object;
437 + *
438 + * The function accepts the authentication token of the parent container that
439 + * created the object (not the one that currently owns the object). The object
440 + * is searched within parent using the provided 'object_id'.
441 + * All tokens to the object must be closed before calling destroy.
442 + *
443 + * Return:     '0' on Success; error code otherwise.
444 + */
445 +int dpmac_destroy(struct fsl_mc_io *mc_io,
446 +                 u16 dprc_token,
447 +                 u32 cmd_flags,
448 +                 u32 object_id)
449 +{
450 +       struct dpmac_cmd_destroy *cmd_params;
451 +       struct fsl_mc_command cmd = { 0 };
452 +
453 +       /* prepare command */
454 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
455 +                                         cmd_flags,
456 +                                         dprc_token);
457 +       cmd_params = (struct dpmac_cmd_destroy *)cmd.params;
458 +       cmd_params->dpmac_id = cpu_to_le32(object_id);
459 +
460 +       /* send command to mc*/
461 +       return mc_send_command(mc_io, &cmd);
462 +}
463 +
464 +/**
465 + * dpmac_set_irq_enable() - Set overall interrupt state.
466 + * @mc_io:     Pointer to MC portal's I/O object
467 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
468 + * @token:     Token of DPMAC object
469 + * @irq_index: The interrupt index to configure
470 + * @en:                Interrupt state - enable = 1, disable = 0
471 + *
472 + * Allows GPP software to control when interrupts are generated.
473 + * Each interrupt can have up to 32 causes.  The enable/disable control's the
474 + * overall interrupt state. if the interrupt is disabled no causes will cause
475 + * an interrupt.
476 + *
477 + * Return:     '0' on Success; Error code otherwise.
478 + */
479 +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
480 +                        u32 cmd_flags,
481 +                        u16 token,
482 +                        u8 irq_index,
483 +                        u8 en)
484 +{
485 +       struct dpmac_cmd_set_irq_enable *cmd_params;
486 +       struct fsl_mc_command cmd = { 0 };
487 +
488 +       /* prepare command */
489 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
490 +                                         cmd_flags,
491 +                                         token);
492 +       cmd_params = (struct dpmac_cmd_set_irq_enable *)cmd.params;
493 +       cmd_params->irq_index = irq_index;
494 +       cmd_params->enable = en;
495 +
496 +       /* send command to mc*/
497 +       return mc_send_command(mc_io, &cmd);
498 +}
499 +
500 +/**
501 + * dpmac_get_irq_enable() - Get overall interrupt state
502 + * @mc_io:     Pointer to MC portal's I/O object
503 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
504 + * @token:     Token of DPMAC object
505 + * @irq_index: The interrupt index to configure
506 + * @en:                Returned interrupt state - enable = 1, disable = 0
507 + *
508 + * Return:     '0' on Success; Error code otherwise.
509 + */
510 +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
511 +                        u32 cmd_flags,
512 +                        u16 token,
513 +                        u8 irq_index,
514 +                        u8 *en)
515 +{
516 +       struct dpmac_cmd_get_irq_enable *cmd_params;
517 +       struct dpmac_rsp_get_irq_enable *rsp_params;
518 +       struct fsl_mc_command cmd = { 0 };
519 +       int err;
520 +
521 +       /* prepare command */
522 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
523 +                                         cmd_flags,
524 +                                         token);
525 +       cmd_params = (struct dpmac_cmd_get_irq_enable *)cmd.params;
526 +       cmd_params->irq_index = irq_index;
527 +
528 +       /* send command to mc*/
529 +       err = mc_send_command(mc_io, &cmd);
530 +       if (err)
531 +               return err;
532 +
533 +       /* retrieve response parameters */
534 +       rsp_params = (struct dpmac_rsp_get_irq_enable *)cmd.params;
535 +       *en = rsp_params->enabled;
536 +
537 +       return 0;
538 +}
539 +
540 +/**
541 + * dpmac_set_irq_mask() - Set interrupt mask.
542 + * @mc_io:     Pointer to MC portal's I/O object
543 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
544 + * @token:     Token of DPMAC object
545 + * @irq_index: The interrupt index to configure
546 + * @mask:      Event mask to trigger interrupt;
547 + *             each bit:
548 + *                     0 = ignore event
549 + *                     1 = consider event for asserting IRQ
550 + *
551 + * Every interrupt can have up to 32 causes and the interrupt model supports
552 + * masking/unmasking each cause independently
553 + *
554 + * Return:     '0' on Success; Error code otherwise.
555 + */
556 +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
557 +                      u32 cmd_flags,
558 +                      u16 token,
559 +                      u8 irq_index,
560 +                      u32 mask)
561 +{
562 +       struct dpmac_cmd_set_irq_mask *cmd_params;
563 +       struct fsl_mc_command cmd = { 0 };
564 +
565 +       /* prepare command */
566 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
567 +                                         cmd_flags,
568 +                                         token);
569 +       cmd_params = (struct dpmac_cmd_set_irq_mask *)cmd.params;
570 +       cmd_params->mask = cpu_to_le32(mask);
571 +       cmd_params->irq_index = irq_index;
572 +
573 +       /* send command to mc*/
574 +       return mc_send_command(mc_io, &cmd);
575 +}
576 +
577 +/**
578 + * dpmac_get_irq_mask() - Get interrupt mask.
579 + * @mc_io:     Pointer to MC portal's I/O object
580 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
581 + * @token:     Token of DPMAC object
582 + * @irq_index: The interrupt index to configure
583 + * @mask:      Returned event mask to trigger interrupt
584 + *
585 + * Every interrupt can have up to 32 causes and the interrupt model supports
586 + * masking/unmasking each cause independently
587 + *
588 + * Return:     '0' on Success; Error code otherwise.
589 + */
590 +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
591 +                      u32 cmd_flags,
592 +                      u16 token,
593 +                      u8 irq_index,
594 +                      u32 *mask)
595 +{
596 +       struct dpmac_cmd_get_irq_mask *cmd_params;
597 +       struct dpmac_rsp_get_irq_mask *rsp_params;
598 +       struct fsl_mc_command cmd = { 0 };
599 +       int err;
600 +
601 +       /* prepare command */
602 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
603 +                                         cmd_flags,
604 +                                         token);
605 +       cmd_params = (struct dpmac_cmd_get_irq_mask *)cmd.params;
606 +       cmd_params->irq_index = irq_index;
607 +
608 +       /* send command to mc*/
609 +       err = mc_send_command(mc_io, &cmd);
610 +       if (err)
611 +               return err;
612 +
613 +       /* retrieve response parameters */
614 +       rsp_params = (struct dpmac_rsp_get_irq_mask *)cmd.params;
615 +       *mask = le32_to_cpu(rsp_params->mask);
616 +
617 +       return 0;
618 +}
619 +
620 +/**
621 + * dpmac_get_irq_status() - Get the current status of any pending interrupts.
622 + *
623 + * @mc_io:     Pointer to MC portal's I/O object
624 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
625 + * @token:     Token of DPMAC object
626 + * @irq_index: The interrupt index to configure
627 + * @status:    Returned interrupts status - one bit per cause:
628 + *                     0 = no interrupt pending
629 + *                     1 = interrupt pending
630 + *
631 + * Return:     '0' on Success; Error code otherwise.
632 + */
633 +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
634 +                        u32 cmd_flags,
635 +                        u16 token,
636 +                        u8 irq_index,
637 +                        u32 *status)
638 +{
639 +       struct dpmac_cmd_get_irq_status *cmd_params;
640 +       struct dpmac_rsp_get_irq_status *rsp_params;
641 +       struct fsl_mc_command cmd = { 0 };
642 +       int err;
643 +
644 +       /* prepare command */
645 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
646 +                                         cmd_flags,
647 +                                         token);
648 +       cmd_params = (struct dpmac_cmd_get_irq_status *)cmd.params;
649 +       cmd_params->status = cpu_to_le32(*status);
650 +       cmd_params->irq_index = irq_index;
651 +
652 +       /* send command to mc*/
653 +       err = mc_send_command(mc_io, &cmd);
654 +       if (err)
655 +               return err;
656 +
657 +       /* retrieve response parameters */
658 +       rsp_params = (struct dpmac_rsp_get_irq_status *)cmd.params;
659 +       *status = le32_to_cpu(rsp_params->status);
660 +
661 +       return 0;
662 +}
663 +
664 +/**
665 + * dpmac_clear_irq_status() - Clear a pending interrupt's status
666 + *
667 + * @mc_io:     Pointer to MC portal's I/O object
668 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
669 + * @token:     Token of DPMAC object
670 + * @irq_index: The interrupt index to configure
671 + * @status:    Bits to clear (W1C) - one bit per cause:
672 + *                     0 = don't change
673 + *                     1 = clear status bit
674 + *
675 + * Return:     '0' on Success; Error code otherwise.
676 + */
677 +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
678 +                          u32 cmd_flags,
679 +                          u16 token,
680 +                          u8 irq_index,
681 +                          u32 status)
682 +{
683 +       struct dpmac_cmd_clear_irq_status *cmd_params;
684 +       struct fsl_mc_command cmd = { 0 };
685 +
686 +       /* prepare command */
687 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
688 +                                         cmd_flags,
689 +                                         token);
690 +       cmd_params = (struct dpmac_cmd_clear_irq_status *)cmd.params;
691 +       cmd_params->status = cpu_to_le32(status);
692 +       cmd_params->irq_index = irq_index;
693 +
694 +       /* send command to mc*/
695 +       return mc_send_command(mc_io, &cmd);
696 +}
697 +
698 +/**
699 + * dpmac_get_attributes - Retrieve DPMAC attributes.
700 + *
701 + * @mc_io:     Pointer to MC portal's I/O object
702 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
703 + * @token:     Token of DPMAC object
704 + * @attr:      Returned object's attributes
705 + *
706 + * Return:     '0' on Success; Error code otherwise.
707 + */
708 +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
709 +                        u32 cmd_flags,
710 +                        u16 token,
711 +                        struct dpmac_attr *attr)
712 +{
713 +       struct dpmac_rsp_get_attributes *rsp_params;
714 +       struct fsl_mc_command cmd = { 0 };
715 +       int err;
716 +
717 +       /* prepare command */
718 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
719 +                                         cmd_flags,
720 +                                         token);
721 +
722 +       /* send command to mc*/
723 +       err = mc_send_command(mc_io, &cmd);
724 +       if (err)
725 +               return err;
726 +
727 +       /* retrieve response parameters */
728 +       rsp_params = (struct dpmac_rsp_get_attributes *)cmd.params;
729 +       attr->eth_if = rsp_params->eth_if;
730 +       attr->link_type = rsp_params->link_type;
731 +       attr->id = le16_to_cpu(rsp_params->id);
732 +       attr->max_rate = le32_to_cpu(rsp_params->max_rate);
733 +
734 +       return 0;
735 +}
736 +
737 +/**
738 + * dpmac_get_link_cfg() - Get Ethernet link configuration
739 + * @mc_io:     Pointer to opaque I/O object
740 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
741 + * @token:     Token of DPMAC object
742 + * @cfg:       Returned structure with the link configuration
743 + *
744 + * Return:     '0' on Success; Error code otherwise.
745 + */
746 +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
747 +                      u32 cmd_flags,
748 +                      u16 token,
749 +                      struct dpmac_link_cfg *cfg)
750 +{
751 +       struct dpmac_rsp_get_link_cfg *rsp_params;
752 +       struct fsl_mc_command cmd = { 0 };
753 +       int err = 0;
754 +
755 +       /* prepare command */
756 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
757 +                                         cmd_flags,
758 +                                         token);
759 +
760 +       /* send command to mc*/
761 +       err = mc_send_command(mc_io, &cmd);
762 +       if (err)
763 +               return err;
764 +
765 +       rsp_params = (struct dpmac_rsp_get_link_cfg *)cmd.params;
766 +       cfg->options = le64_to_cpu(rsp_params->options);
767 +       cfg->rate = le32_to_cpu(rsp_params->rate);
768 +
769 +       return 0;
770 +}
771 +
772 +/**
773 + * dpmac_get_link_cfg_v2() - Get Ethernet link configuration
774 + * @mc_io:      Pointer to opaque I/O object
775 + * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
776 + * @token:      Token of DPMAC object
777 + * @cfg:        Returned structure with the link configuration
778 + *
779 + * Return:      '0' on Success; Error code otherwise.
780 + */
781 +int dpmac_get_link_cfg_v2(struct fsl_mc_io *mc_io,
782 +                         u32 cmd_flags,
783 +                         u16 token,
784 +                         struct dpmac_link_cfg *cfg)
785 +{
786 +       struct dpmac_rsp_get_link_cfg_v2 *rsp_params;
787 +       struct fsl_mc_command cmd = { 0 };
788 +       int err = 0;
789 +
790 +       /* prepare command */
791 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG_V2,
792 +                                         cmd_flags,
793 +                                         token);
794 +
795 +       /* send command to mc*/
796 +       err = mc_send_command(mc_io, &cmd);
797 +       if (err)
798 +               return err;
799 +
800 +       rsp_params = (struct dpmac_rsp_get_link_cfg_v2 *)cmd.params;
801 +       cfg->options = le64_to_cpu(rsp_params->options);
802 +       cfg->rate = le32_to_cpu(rsp_params->rate);
803 +       cfg->advertising = le64_to_cpu(rsp_params->advertising);
804 +
805 +       return 0;
806 +}
807 +
808 +/**
809 + * dpmac_set_link_state() - Set the Ethernet link status
810 + * @mc_io:     Pointer to opaque I/O object
811 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
812 + * @token:     Token of DPMAC object
813 + * @link_state:        Link state configuration
814 + *
815 + * Return:     '0' on Success; Error code otherwise.
816 + */
817 +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
818 +                        u32 cmd_flags,
819 +                        u16 token,
820 +                        struct dpmac_link_state *link_state)
821 +{
822 +       struct dpmac_cmd_set_link_state *cmd_params;
823 +       struct fsl_mc_command cmd = { 0 };
824 +
825 +       /* prepare command */
826 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
827 +                                         cmd_flags,
828 +                                         token);
829 +       cmd_params = (struct dpmac_cmd_set_link_state *)cmd.params;
830 +       cmd_params->options = cpu_to_le64(link_state->options);
831 +       cmd_params->rate = cpu_to_le32(link_state->rate);
832 +       dpmac_set_field(cmd_params->up, STATE, link_state->up);
833 +
834 +       /* send command to mc*/
835 +       return mc_send_command(mc_io, &cmd);
836 +}
837 +
838 +/**
839 + * dpmac_set_link_state_v2() - Set the Ethernet link status
840 + * @mc_io:      Pointer to opaque I/O object
841 + * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
842 + * @token:      Token of DPMAC object
843 + * @link_state: Link state configuration
844 + *
845 + * Return:      '0' on Success; Error code otherwise.
846 + */
847 +int dpmac_set_link_state_v2(struct fsl_mc_io *mc_io,
848 +                           u32 cmd_flags,
849 +                           u16 token,
850 +                           struct dpmac_link_state *link_state)
851 +{
852 +       struct dpmac_cmd_set_link_state_v2 *cmd_params;
853 +       struct fsl_mc_command cmd = { 0 };
854 +
855 +       /* prepare command */
856 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE_V2,
857 +                                         cmd_flags,
858 +                                         token);
859 +       cmd_params = (struct dpmac_cmd_set_link_state_v2 *)cmd.params;
860 +       cmd_params->options = cpu_to_le64(link_state->options);
861 +       cmd_params->rate = cpu_to_le32(link_state->rate);
862 +       dpmac_set_field(cmd_params->state, STATE, link_state->up);
863 +       dpmac_set_field(cmd_params->state, STATE_VALID,
864 +                       link_state->state_valid);
865 +       cmd_params->supported = cpu_to_le64(link_state->supported);
866 +       cmd_params->advertising = cpu_to_le64(link_state->advertising);
867 +
868 +       /* send command to mc*/
869 +       return mc_send_command(mc_io, &cmd);
870 +}
871 +
872 +/**
873 + * dpmac_get_counter() - Read a specific DPMAC counter
874 + * @mc_io:     Pointer to opaque I/O object
875 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
876 + * @token:     Token of DPMAC object
877 + * @type:      The requested counter
878 + * @counter:   Returned counter value
879 + *
880 + * Return:     The requested counter; '0' otherwise.
881 + */
882 +int dpmac_get_counter(struct fsl_mc_io *mc_io,
883 +                     u32 cmd_flags,
884 +                     u16 token,
885 +                     enum dpmac_counter type,
886 +                     u64 *counter)
887 +{
888 +       struct dpmac_cmd_get_counter *dpmac_cmd;
889 +       struct dpmac_rsp_get_counter *dpmac_rsp;
890 +       struct fsl_mc_command cmd = { 0 };
891 +       int err = 0;
892 +
893 +       /* prepare command */
894 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
895 +                                         cmd_flags,
896 +                                         token);
897 +       dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params;
898 +       dpmac_cmd->type = type;
899 +
900 +       /* send command to mc*/
901 +       err = mc_send_command(mc_io, &cmd);
902 +       if (err)
903 +               return err;
904 +
905 +       dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params;
906 +       *counter = le64_to_cpu(dpmac_rsp->counter);
907 +
908 +       return 0;
909 +}
910 +
911 +/* untested */
912 +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
913 +                           u32 cmd_flags,
914 +                           u16 token,
915 +                           const u8 addr[6])
916 +{
917 +       struct dpmac_cmd_set_port_mac_addr *dpmac_cmd;
918 +       struct fsl_mc_command cmd = { 0 };
919 +
920 +       /* prepare command */
921 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PORT_MAC_ADDR,
922 +                                         cmd_flags,
923 +                                         token);
924 +       dpmac_cmd = (struct dpmac_cmd_set_port_mac_addr *)cmd.params;
925 +       dpmac_cmd->addr[0] = addr[5];
926 +       dpmac_cmd->addr[1] = addr[4];
927 +       dpmac_cmd->addr[2] = addr[3];
928 +       dpmac_cmd->addr[3] = addr[2];
929 +       dpmac_cmd->addr[4] = addr[1];
930 +       dpmac_cmd->addr[5] = addr[0];
931 +
932 +       /* send command to mc*/
933 +       return mc_send_command(mc_io, &cmd);
934 +}
935 +
936 +/**
937 + * dpmac_get_api_version() - Get Data Path MAC version
938 + * @mc_io:     Pointer to MC portal's I/O object
939 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
940 + * @major_ver: Major version of data path mac API
941 + * @minor_ver: Minor version of data path mac API
942 + *
943 + * Return:  '0' on Success; Error code otherwise.
944 + */
945 +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
946 +                         u32 cmd_flags,
947 +                         u16 *major_ver,
948 +                         u16 *minor_ver)
949 +{
950 +       struct dpmac_rsp_get_api_version *rsp_params;
951 +       struct fsl_mc_command cmd = { 0 };
952 +       int err;
953 +
954 +       cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION,
955 +                                       cmd_flags,
956 +                                       0);
957 +
958 +       err = mc_send_command(mc_io, &cmd);
959 +       if (err)
960 +               return err;
961 +
962 +       rsp_params = (struct dpmac_rsp_get_api_version *)cmd.params;
963 +       *major_ver = le16_to_cpu(rsp_params->major);
964 +       *minor_ver = le16_to_cpu(rsp_params->minor);
965 +
966 +       return 0;
967 +}
968 --- /dev/null
969 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h
970 @@ -0,0 +1,374 @@
971 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
972 + *
973 + * Redistribution and use in source and binary forms, with or without
974 + * modification, are permitted provided that the following conditions are met:
975 + * * Redistributions of source code must retain the above copyright
976 + * notice, this list of conditions and the following disclaimer.
977 + * * Redistributions in binary form must reproduce the above copyright
978 + * notice, this list of conditions and the following disclaimer in the
979 + * documentation and/or other materials provided with the distribution.
980 + * * Neither the name of the above-listed copyright holders nor the
981 + * names of any contributors may be used to endorse or promote products
982 + * derived from this software without specific prior written permission.
983 + *
984 + *
985 + * ALTERNATIVELY, this software may be distributed under the terms of the
986 + * GNU General Public License ("GPL") as published by the Free Software
987 + * Foundation, either version 2 of that License or (at your option) any
988 + * later version.
989 + *
990 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
991 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
992 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
993 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
994 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
995 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
996 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
997 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
998 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
999 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1000 + * POSSIBILITY OF SUCH DAMAGE.
1001 + */
1002 +#ifndef __FSL_DPMAC_H
1003 +#define __FSL_DPMAC_H
1004 +
1005 +/* Data Path MAC API
1006 + * Contains initialization APIs and runtime control APIs for DPMAC
1007 + */
1008 +
1009 +struct fsl_mc_io;
1010 +
1011 +int dpmac_open(struct fsl_mc_io *mc_io,
1012 +              u32 cmd_flags,
1013 +              int dpmac_id,
1014 +              u16 *token);
1015 +
1016 +int dpmac_close(struct fsl_mc_io *mc_io,
1017 +               u32 cmd_flags,
1018 +               u16 token);
1019 +
1020 +/**
1021 + * enum dpmac_link_type -  DPMAC link type
1022 + * @DPMAC_LINK_TYPE_NONE: No link
1023 + * @DPMAC_LINK_TYPE_FIXED: Link is fixed type
1024 + * @DPMAC_LINK_TYPE_PHY: Link by PHY ID
1025 + * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type
1026 + */
1027 +enum dpmac_link_type {
1028 +       DPMAC_LINK_TYPE_NONE,
1029 +       DPMAC_LINK_TYPE_FIXED,
1030 +       DPMAC_LINK_TYPE_PHY,
1031 +       DPMAC_LINK_TYPE_BACKPLANE
1032 +};
1033 +
1034 +/**
1035 + * enum dpmac_eth_if - DPMAC Ethrnet interface
1036 + * @DPMAC_ETH_IF_MII: MII interface
1037 + * @DPMAC_ETH_IF_RMII: RMII interface
1038 + * @DPMAC_ETH_IF_SMII: SMII interface
1039 + * @DPMAC_ETH_IF_GMII: GMII interface
1040 + * @DPMAC_ETH_IF_RGMII: RGMII interface
1041 + * @DPMAC_ETH_IF_SGMII: SGMII interface
1042 + * @DPMAC_ETH_IF_QSGMII: QSGMII interface
1043 + * @DPMAC_ETH_IF_XAUI: XAUI interface
1044 + * @DPMAC_ETH_IF_XFI: XFI interface
1045 + */
1046 +enum dpmac_eth_if {
1047 +       DPMAC_ETH_IF_MII,
1048 +       DPMAC_ETH_IF_RMII,
1049 +       DPMAC_ETH_IF_SMII,
1050 +       DPMAC_ETH_IF_GMII,
1051 +       DPMAC_ETH_IF_RGMII,
1052 +       DPMAC_ETH_IF_SGMII,
1053 +       DPMAC_ETH_IF_QSGMII,
1054 +       DPMAC_ETH_IF_XAUI,
1055 +       DPMAC_ETH_IF_XFI
1056 +};
1057 +
1058 +/**
1059 + * struct dpmac_cfg - Structure representing DPMAC configuration
1060 + * @mac_id:    Represents the Hardware MAC ID; in case of multiple WRIOP,
1061 + *             the MAC IDs are continuous.
1062 + *             For example:  2 WRIOPs, 16 MACs in each:
1063 + *                             MAC IDs for the 1st WRIOP: 1-16,
1064 + *                             MAC IDs for the 2nd WRIOP: 17-32.
1065 + */
1066 +struct dpmac_cfg {
1067 +       u16 mac_id;
1068 +};
1069 +
1070 +int dpmac_create(struct fsl_mc_io *mc_io,
1071 +                u16 dprc_token,
1072 +                u32 cmd_flags,
1073 +                const struct dpmac_cfg *cfg,
1074 +                u32 *obj_id);
1075 +
1076 +int dpmac_destroy(struct fsl_mc_io *mc_io,
1077 +                 u16 dprc_token,
1078 +                 u32 cmd_flags,
1079 +                 u32 object_id);
1080 +
1081 +/**
1082 + * DPMAC IRQ Index and Events
1083 + */
1084 +
1085 +/**
1086 + * IRQ index
1087 + */
1088 +#define DPMAC_IRQ_INDEX                                0
1089 +/**
1090 + * IRQ event - indicates a change in link state
1091 + */
1092 +#define DPMAC_IRQ_EVENT_LINK_CFG_REQ           0x00000001
1093 +/**
1094 + * IRQ event - Indicates that the link state changed
1095 + */
1096 +#define DPMAC_IRQ_EVENT_LINK_CHANGED           0x00000002
1097 +
1098 +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
1099 +                        u32 cmd_flags,
1100 +                        u16 token,
1101 +                        u8 irq_index,
1102 +                        u8 en);
1103 +
1104 +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
1105 +                        u32 cmd_flags,
1106 +                        u16 token,
1107 +                        u8 irq_index,
1108 +                        u8 *en);
1109 +
1110 +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
1111 +                      u32 cmd_flags,
1112 +                      u16 token,
1113 +                      u8 irq_index,
1114 +                      u32 mask);
1115 +
1116 +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
1117 +                      u32 cmd_flags,
1118 +                      u16 token,
1119 +                      u8 irq_index,
1120 +                      u32 *mask);
1121 +
1122 +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
1123 +                        u32 cmd_flags,
1124 +                        u16 token,
1125 +                        u8 irq_index,
1126 +                        u32 *status);
1127 +
1128 +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
1129 +                          u32 cmd_flags,
1130 +                          u16 token,
1131 +                          u8 irq_index,
1132 +                          u32 status);
1133 +
1134 +/**
1135 + * struct dpmac_attr - Structure representing DPMAC attributes
1136 + * @id:                DPMAC object ID
1137 + * @max_rate:  Maximum supported rate - in Mbps
1138 + * @eth_if:    Ethernet interface
1139 + * @link_type: link type
1140 + */
1141 +struct dpmac_attr {
1142 +       u16 id;
1143 +       u32 max_rate;
1144 +       enum dpmac_eth_if eth_if;
1145 +       enum dpmac_link_type link_type;
1146 +};
1147 +
1148 +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
1149 +                        u32 cmd_flags,
1150 +                        u16 token,
1151 +                        struct dpmac_attr *attr);
1152 +
1153 +/**
1154 + * DPMAC link configuration/state options
1155 + */
1156 +
1157 +/**
1158 + * Enable auto-negotiation
1159 + */
1160 +#define DPMAC_LINK_OPT_AUTONEG         0x0000000000000001ULL
1161 +/**
1162 + * Enable half-duplex mode
1163 + */
1164 +#define DPMAC_LINK_OPT_HALF_DUPLEX     0x0000000000000002ULL
1165 +/**
1166 + * Enable pause frames
1167 + */
1168 +#define DPMAC_LINK_OPT_PAUSE           0x0000000000000004ULL
1169 +/**
1170 + * Enable a-symmetric pause frames
1171 + */
1172 +#define DPMAC_LINK_OPT_ASYM_PAUSE      0x0000000000000008ULL
1173 +
1174 +/**
1175 + * Advertised link speeds
1176 + */
1177 +#define DPMAC_ADVERTISED_10BASET_FULL          0x0000000000000001ULL
1178 +#define DPMAC_ADVERTISED_100BASET_FULL         0x0000000000000002ULL
1179 +#define DPMAC_ADVERTISED_1000BASET_FULL                0x0000000000000004ULL
1180 +#define DPMAC_ADVERTISED_10000BASET_FULL       0x0000000000000010ULL
1181 +#define DPMAC_ADVERTISED_2500BASEX_FULL                0x0000000000000020ULL
1182 +
1183 +/**
1184 + * Advertise auto-negotiation enable
1185 + */
1186 +#define DPMAC_ADVERTISED_AUTONEG               0x0000000000000008ULL
1187 +
1188 +/**
1189 + * struct dpmac_link_cfg - Structure representing DPMAC link configuration
1190 + * @rate: Link's rate - in Mbps
1191 + * @options: Enable/Disable DPMAC link cfg features (bitmap)
1192 + * @advertising: Speeds that are advertised for autoneg (bitmap)
1193 + */
1194 +struct dpmac_link_cfg {
1195 +       u32 rate;
1196 +       u64 options;
1197 +       u64 advertising;
1198 +};
1199 +
1200 +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
1201 +                      u32 cmd_flags,
1202 +                      u16 token,
1203 +                      struct dpmac_link_cfg *cfg);
1204 +
1205 +int dpmac_get_link_cfg_v2(struct fsl_mc_io *mc_io,
1206 +                         u32 cmd_flags,
1207 +                         u16 token,
1208 +                         struct dpmac_link_cfg *cfg);
1209 +
1210 +/**
1211 + * struct dpmac_link_state - DPMAC link configuration request
1212 + * @rate: Rate in Mbps
1213 + * @options: Enable/Disable DPMAC link cfg features (bitmap)
1214 + * @up: Link state
1215 + * @state_valid: Ignore/Update the state of the link
1216 + * @supported: Speeds capability of the phy (bitmap)
1217 + * @advertising: Speeds that are advertised for autoneg (bitmap)
1218 + */
1219 +struct dpmac_link_state {
1220 +       u32 rate;
1221 +       u64 options;
1222 +       int up;
1223 +       int state_valid;
1224 +       u64 supported;
1225 +       u64 advertising;
1226 +};
1227 +
1228 +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
1229 +                        u32 cmd_flags,
1230 +                        u16 token,
1231 +                        struct dpmac_link_state *link_state);
1232 +
1233 +int dpmac_set_link_state_v2(struct fsl_mc_io *mc_io,
1234 +                           u32 cmd_flags,
1235 +                           u16 token,
1236 +                           struct dpmac_link_state *link_state);
1237 +
1238 +/**
1239 + * enum dpmac_counter - DPMAC counter types
1240 + * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad.
1241 + * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad.
1242 + * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad.
1243 + * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad.
1244 + * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad.
1245 + * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad.
1246 + * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger
1247 + *                               (up to max frame length specified),
1248 + *                               good or bad.
1249 + * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received
1250 + *                     with a wrong CRC
1251 + * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length
1252 + *                       specified, with a bad frame check sequence.
1253 + * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors.
1254 + *                              Occurs when a receive FIFO overflows.
1255 + *                              Includes also frames truncated as a result of
1256 + *                              the receive FIFO overflow.
1257 + * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error
1258 + *                          (optional used for wrong SFD).
1259 + * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64
1260 + *                           bytes long with a good CRC.
1261 + * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length
1262 + *                          specified, with a good frame check sequence.
1263 + * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC)
1264 + * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted
1265 + *                                  (regular and PFC).
1266 + * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid
1267 + *                     frames and valid pause frames.
1268 + * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames.
1269 + * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames.
1270 + * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received.
1271 + * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames.
1272 + * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error
1273 + *                          (except for undersized/fragment frame).
1274 + * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid
1275 + *                     frames and valid pause frames transmitted.
1276 + * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames.
1277 + * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames.
1278 + * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames.
1279 + * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error.
1280 + * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including
1281 + *                           pause frames.
1282 + * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including
1283 + *                           pause frames.
1284 + */
1285 +enum dpmac_counter {
1286 +       DPMAC_CNT_ING_FRAME_64,
1287 +       DPMAC_CNT_ING_FRAME_127,
1288 +       DPMAC_CNT_ING_FRAME_255,
1289 +       DPMAC_CNT_ING_FRAME_511,
1290 +       DPMAC_CNT_ING_FRAME_1023,
1291 +       DPMAC_CNT_ING_FRAME_1518,
1292 +       DPMAC_CNT_ING_FRAME_1519_MAX,
1293 +       DPMAC_CNT_ING_FRAG,
1294 +       DPMAC_CNT_ING_JABBER,
1295 +       DPMAC_CNT_ING_FRAME_DISCARD,
1296 +       DPMAC_CNT_ING_ALIGN_ERR,
1297 +       DPMAC_CNT_EGR_UNDERSIZED,
1298 +       DPMAC_CNT_ING_OVERSIZED,
1299 +       DPMAC_CNT_ING_VALID_PAUSE_FRAME,
1300 +       DPMAC_CNT_EGR_VALID_PAUSE_FRAME,
1301 +       DPMAC_CNT_ING_BYTE,
1302 +       DPMAC_CNT_ING_MCAST_FRAME,
1303 +       DPMAC_CNT_ING_BCAST_FRAME,
1304 +       DPMAC_CNT_ING_ALL_FRAME,
1305 +       DPMAC_CNT_ING_UCAST_FRAME,
1306 +       DPMAC_CNT_ING_ERR_FRAME,
1307 +       DPMAC_CNT_EGR_BYTE,
1308 +       DPMAC_CNT_EGR_MCAST_FRAME,
1309 +       DPMAC_CNT_EGR_BCAST_FRAME,
1310 +       DPMAC_CNT_EGR_UCAST_FRAME,
1311 +       DPMAC_CNT_EGR_ERR_FRAME,
1312 +       DPMAC_CNT_ING_GOOD_FRAME,
1313 +       DPMAC_CNT_ENG_GOOD_FRAME
1314 +};
1315 +
1316 +int dpmac_get_counter(struct fsl_mc_io *mc_io,
1317 +                     u32 cmd_flags,
1318 +                     u16 token,
1319 +                     enum dpmac_counter type,
1320 +                     u64 *counter);
1321 +
1322 +/**
1323 + * dpmac_set_port_mac_addr() - Set a MAC address associated with the physical
1324 + *              port.  This is not used for filtering, MAC is always in
1325 + *              promiscuous mode, it is passed to DPNIs through DPNI API for
1326 + *              application used.
1327 + * @mc_io:     Pointer to opaque I/O object
1328 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1329 + * @token:     Token of DPMAC object
1330 + * @addr:      MAC address to set
1331 + *
1332 + * Return:     The requested counter; '0' otherwise.
1333 + */
1334 +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
1335 +                           u32 cmd_flags,
1336 +                           u16 token,
1337 +                           const u8 addr[6]);
1338 +
1339 +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
1340 +                         u32 cmd_flags,
1341 +                         u16 *major_ver,
1342 +                         u16 *minor_ver);
1343 +
1344 +#endif /* __FSL_DPMAC_H */
1345 --- /dev/null
1346 +++ b/drivers/staging/fsl-dpaa2/mac/mac.c
1347 @@ -0,0 +1,817 @@
1348 +/* Copyright 2015 Freescale Semiconductor Inc.
1349 + * Copyright 2018 NXP
1350 + *
1351 + * Redistribution and use in source and binary forms, with or without
1352 + * modification, are permitted provided that the following conditions are met:
1353 + *     * Redistributions of source code must retain the above copyright
1354 + *      notice, this list of conditions and the following disclaimer.
1355 + *     * Redistributions in binary form must reproduce the above copyright
1356 + *      notice, this list of conditions and the following disclaimer in the
1357 + *      documentation and/or other materials provided with the distribution.
1358 + *     * Neither the name of Freescale Semiconductor nor the
1359 + *      names of its contributors may be used to endorse or promote products
1360 + *      derived from this software without specific prior written permission.
1361 + *
1362 + *
1363 + * ALTERNATIVELY, this software may be distributed under the terms of the
1364 + * GNU General Public License ("GPL") as published by the Free Software
1365 + * Foundation, either version 2 of that License or (at your option) any
1366 + * later version.
1367 + *
1368 + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
1369 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1370 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1371 + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
1372 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1373 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1374 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1375 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1376 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1377 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1378 + */
1379 +
1380 +#include <linux/module.h>
1381 +
1382 +#include <linux/netdevice.h>
1383 +#include <linux/etherdevice.h>
1384 +#include <linux/msi.h>
1385 +#include <linux/rtnetlink.h>
1386 +#include <linux/if_vlan.h>
1387 +
1388 +#include <uapi/linux/if_bridge.h>
1389 +#include <net/netlink.h>
1390 +
1391 +#include <linux/of.h>
1392 +#include <linux/of_mdio.h>
1393 +#include <linux/of_net.h>
1394 +#include <linux/phy.h>
1395 +#include <linux/phy_fixed.h>
1396 +
1397 +#include <linux/fsl/mc.h>
1398 +
1399 +#include "dpmac.h"
1400 +#include "dpmac-cmd.h"
1401 +
1402 +struct dpaa2_mac_priv {
1403 +       struct net_device               *netdev;
1404 +       struct fsl_mc_device            *mc_dev;
1405 +       struct dpmac_attr               attr;
1406 +       struct dpmac_link_state         old_state;
1407 +       u16                             dpmac_ver_major;
1408 +       u16                             dpmac_ver_minor;
1409 +};
1410 +
1411 +/* TODO: fix the 10G modes, mapping can't be right:
1412 + *  XGMII is paralel
1413 + *  XAUI is serial, using 8b/10b encoding
1414 + *  XFI is also serial but using 64b/66b encoding
1415 + * they can't all map to XGMII...
1416 + *
1417 + * This must be kept in sync with enum dpmac_eth_if.
1418 + */
1419 +static phy_interface_t dpaa2_mac_iface_mode[] =  {
1420 +       PHY_INTERFACE_MODE_MII,         /* DPMAC_ETH_IF_MII */
1421 +       PHY_INTERFACE_MODE_RMII,        /* DPMAC_ETH_IF_RMII */
1422 +       PHY_INTERFACE_MODE_SMII,        /* DPMAC_ETH_IF_SMII */
1423 +       PHY_INTERFACE_MODE_GMII,        /* DPMAC_ETH_IF_GMII */
1424 +       PHY_INTERFACE_MODE_RGMII,       /* DPMAC_ETH_IF_RGMII */
1425 +       PHY_INTERFACE_MODE_SGMII,       /* DPMAC_ETH_IF_SGMII */
1426 +       PHY_INTERFACE_MODE_QSGMII,      /* DPMAC_ETH_IF_QSGMII */
1427 +       PHY_INTERFACE_MODE_XGMII,       /* DPMAC_ETH_IF_XAUI */
1428 +       PHY_INTERFACE_MODE_XGMII,       /* DPMAC_ETH_IF_XFI */
1429 +       PHY_INTERFACE_MODE_XGMII,        /* DPMAC_ETH_IF_CAUI */
1430 +       PHY_INTERFACE_MODE_XGMII,       /* DPMAC_ETH_IF_1000BASEX */
1431 +       PHY_INTERFACE_MODE_XGMII,       /* DPMAC_ETH_IF_USXGMII */
1432 +};
1433 +
1434 +static int cmp_dpmac_ver(struct dpaa2_mac_priv *priv,
1435 +                        u16 ver_major, u16 ver_minor)
1436 +{
1437 +       if (priv->dpmac_ver_major == ver_major)
1438 +               return priv->dpmac_ver_minor - ver_minor;
1439 +       return priv->dpmac_ver_major - ver_major;
1440 +}
1441 +
1442 +#define DPMAC_LINK_AUTONEG_VER_MAJOR           4
1443 +#define DPMAC_LINK_AUTONEG_VER_MINOR           3
1444 +
1445 +struct dpaa2_mac_link_mode_map {
1446 +       u64 dpmac_lm;
1447 +       u64 ethtool_lm;
1448 +};
1449 +
1450 +static const struct dpaa2_mac_link_mode_map dpaa2_mac_lm_map[] = {
1451 +       {DPMAC_ADVERTISED_10BASET_FULL, ETHTOOL_LINK_MODE_10baseT_Full_BIT},
1452 +       {DPMAC_ADVERTISED_100BASET_FULL, ETHTOOL_LINK_MODE_100baseT_Full_BIT},
1453 +       {DPMAC_ADVERTISED_1000BASET_FULL, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
1454 +       {DPMAC_ADVERTISED_10000BASET_FULL, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
1455 +       {DPMAC_ADVERTISED_2500BASEX_FULL, ETHTOOL_LINK_MODE_2500baseX_Full_BIT},
1456 +       {DPMAC_ADVERTISED_AUTONEG, ETHTOOL_LINK_MODE_Autoneg_BIT},
1457 +};
1458 +
1459 +static void link_mode_dpmac2phydev(u64 dpmac_lm, u32 *phydev_lm)
1460 +{
1461 +       __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
1462 +       int i;
1463 +
1464 +       for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
1465 +               if (dpmac_lm & dpaa2_mac_lm_map[i].dpmac_lm)
1466 +                       __set_bit(dpaa2_mac_lm_map[i].ethtool_lm, mask);
1467 +       }
1468 +
1469 +       ethtool_convert_link_mode_to_legacy_u32(phydev_lm, mask);
1470 +}
1471 +
1472 +static void link_mode_phydev2dpmac(u32 phydev_lm, u64 *dpni_lm)
1473 +{
1474 +       unsigned long lm;
1475 +       int i;
1476 +
1477 +       ethtool_convert_legacy_u32_to_link_mode(&lm, phydev_lm);
1478 +
1479 +       for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
1480 +               if (test_bit(dpaa2_mac_lm_map[i].ethtool_lm, &lm))
1481 +                       *dpni_lm |= dpaa2_mac_lm_map[i].dpmac_lm;
1482 +       }
1483 +}
1484 +
1485 +static void dpaa2_mac_link_changed(struct net_device *netdev)
1486 +{
1487 +       struct phy_device       *phydev;
1488 +       struct dpmac_link_state state = { 0 };
1489 +       struct dpaa2_mac_priv   *priv = netdev_priv(netdev);
1490 +       int                     err;
1491 +
1492 +       /* the PHY just notified us of link state change */
1493 +       phydev = netdev->phydev;
1494 +
1495 +       state.up = !!phydev->link;
1496 +       if (phydev->link) {
1497 +               state.rate = phydev->speed;
1498 +
1499 +               if (!phydev->duplex)
1500 +                       state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
1501 +               if (phydev->autoneg)
1502 +                       state.options |= DPMAC_LINK_OPT_AUTONEG;
1503 +
1504 +               if (phydev->pause && (phydev->advertising & ADVERTISED_Pause))
1505 +                       state.options |= DPMAC_LINK_OPT_PAUSE;
1506 +               if (phydev->pause &&
1507 +                   (phydev->advertising & ADVERTISED_Asym_Pause))
1508 +                       state.options |= DPMAC_LINK_OPT_ASYM_PAUSE;
1509 +
1510 +               netif_carrier_on(netdev);
1511 +       } else {
1512 +               netif_carrier_off(netdev);
1513 +       }
1514 +
1515 +       if (priv->old_state.up != state.up ||
1516 +           priv->old_state.rate != state.rate ||
1517 +           priv->old_state.options != state.options) {
1518 +               priv->old_state = state;
1519 +               phy_print_status(phydev);
1520 +       }
1521 +
1522 +       if (cmp_dpmac_ver(priv, DPMAC_LINK_AUTONEG_VER_MAJOR,
1523 +                         DPMAC_LINK_AUTONEG_VER_MINOR) < 0) {
1524 +               err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
1525 +                                          priv->mc_dev->mc_handle, &state);
1526 +       } else {
1527 +               link_mode_phydev2dpmac(phydev->supported, &state.supported);
1528 +               link_mode_phydev2dpmac(phydev->advertising, &state.advertising);
1529 +               state.state_valid = 1;
1530 +
1531 +               err = dpmac_set_link_state_v2(priv->mc_dev->mc_io, 0,
1532 +                                             priv->mc_dev->mc_handle, &state);
1533 +       }
1534 +       if (unlikely(err))
1535 +               dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
1536 +}
1537 +
1538 +static int dpaa2_mac_open(struct net_device *netdev)
1539 +{
1540 +       /* start PHY state machine */
1541 +       phy_start(netdev->phydev);
1542 +
1543 +       return 0;
1544 +}
1545 +
1546 +static int dpaa2_mac_stop(struct net_device *netdev)
1547 +{
1548 +       if (!netdev->phydev)
1549 +               goto done;
1550 +
1551 +       /* stop PHY state machine */
1552 +       phy_stop(netdev->phydev);
1553 +
1554 +       /* signal link down to firmware */
1555 +       netdev->phydev->link = 0;
1556 +       dpaa2_mac_link_changed(netdev);
1557 +
1558 +done:
1559 +       return 0;
1560 +}
1561 +
1562 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1563 +static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
1564 +                                       struct net_device *dev)
1565 +{
1566 +       /* we don't support I/O for now, drop the frame */
1567 +       dev_kfree_skb_any(skb);
1568 +       return NETDEV_TX_OK;
1569 +}
1570 +
1571 +static void dpaa2_mac_get_drvinfo(struct net_device *net_dev,
1572 +                                 struct ethtool_drvinfo *drvinfo)
1573 +{
1574 +       struct dpaa2_mac_priv *priv = netdev_priv(net_dev);
1575 +
1576 +       strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
1577 +       snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
1578 +                "%u.%u", priv->dpmac_ver_major, priv->dpmac_ver_minor);
1579 +       strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
1580 +               sizeof(drvinfo->bus_info));
1581 +}
1582 +
1583 +static int dpaa2_mac_get_link_ksettings(struct net_device *netdev,
1584 +                                       struct ethtool_link_ksettings *ks)
1585 +{
1586 +       phy_ethtool_ksettings_get(netdev->phydev, ks);
1587 +
1588 +       return 0;
1589 +}
1590 +
1591 +static int dpaa2_mac_set_link_ksettings(struct net_device *netdev,
1592 +                                       const struct ethtool_link_ksettings *ks)
1593 +{
1594 +       return phy_ethtool_ksettings_set(netdev->phydev, ks);
1595 +}
1596 +
1597 +static void dpaa2_mac_get_stats(struct net_device *netdev,
1598 +                               struct rtnl_link_stats64 *storage)
1599 +{
1600 +       struct dpaa2_mac_priv   *priv = netdev_priv(netdev);
1601 +       u64                     tmp;
1602 +       int                     err;
1603 +
1604 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1605 +                               DPMAC_CNT_EGR_MCAST_FRAME,
1606 +                               &storage->tx_packets);
1607 +       if (err)
1608 +               goto error;
1609 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1610 +                               DPMAC_CNT_EGR_BCAST_FRAME, &tmp);
1611 +       if (err)
1612 +               goto error;
1613 +       storage->tx_packets += tmp;
1614 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1615 +                               DPMAC_CNT_EGR_UCAST_FRAME, &tmp);
1616 +       if (err)
1617 +               goto error;
1618 +       storage->tx_packets += tmp;
1619 +
1620 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1621 +                               DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped);
1622 +       if (err)
1623 +               goto error;
1624 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1625 +                               DPMAC_CNT_EGR_BYTE, &storage->tx_bytes);
1626 +       if (err)
1627 +               goto error;
1628 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1629 +                               DPMAC_CNT_EGR_ERR_FRAME, &storage->tx_errors);
1630 +       if (err)
1631 +               goto error;
1632 +
1633 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1634 +                               DPMAC_CNT_ING_ALL_FRAME, &storage->rx_packets);
1635 +       if (err)
1636 +               goto error;
1637 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1638 +                               DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast);
1639 +       if (err)
1640 +               goto error;
1641 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1642 +                               DPMAC_CNT_ING_FRAME_DISCARD,
1643 +                               &storage->rx_dropped);
1644 +       if (err)
1645 +               goto error;
1646 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1647 +                               DPMAC_CNT_ING_ALIGN_ERR, &storage->rx_errors);
1648 +       if (err)
1649 +               goto error;
1650 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1651 +                               DPMAC_CNT_ING_OVERSIZED, &tmp);
1652 +       if (err)
1653 +               goto error;
1654 +       storage->rx_errors += tmp;
1655 +       err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1656 +                               DPMAC_CNT_ING_BYTE, &storage->rx_bytes);
1657 +       if (err)
1658 +               goto error;
1659 +
1660 +       return;
1661 +error:
1662 +       netdev_err(netdev, "dpmac_get_counter err %d\n", err);
1663 +}
1664 +
1665 +static struct {
1666 +       enum dpmac_counter id;
1667 +       char name[ETH_GSTRING_LEN];
1668 +} dpaa2_mac_counters[] =  {
1669 +       {DPMAC_CNT_ING_ALL_FRAME,               "rx all frames"},
1670 +       {DPMAC_CNT_ING_GOOD_FRAME,              "rx frames ok"},
1671 +       {DPMAC_CNT_ING_ERR_FRAME,               "rx frame errors"},
1672 +       {DPMAC_CNT_ING_FRAME_DISCARD,           "rx frame discards"},
1673 +       {DPMAC_CNT_ING_UCAST_FRAME,             "rx u-cast"},
1674 +       {DPMAC_CNT_ING_BCAST_FRAME,             "rx b-cast"},
1675 +       {DPMAC_CNT_ING_MCAST_FRAME,             "rx m-cast"},
1676 +       {DPMAC_CNT_ING_FRAME_64,                "rx 64 bytes"},
1677 +       {DPMAC_CNT_ING_FRAME_127,               "rx 65-127 bytes"},
1678 +       {DPMAC_CNT_ING_FRAME_255,               "rx 128-255 bytes"},
1679 +       {DPMAC_CNT_ING_FRAME_511,               "rx 256-511 bytes"},
1680 +       {DPMAC_CNT_ING_FRAME_1023,              "rx 512-1023 bytes"},
1681 +       {DPMAC_CNT_ING_FRAME_1518,              "rx 1024-1518 bytes"},
1682 +       {DPMAC_CNT_ING_FRAME_1519_MAX,          "rx 1519-max bytes"},
1683 +       {DPMAC_CNT_ING_FRAG,                    "rx frags"},
1684 +       {DPMAC_CNT_ING_JABBER,                  "rx jabber"},
1685 +       {DPMAC_CNT_ING_ALIGN_ERR,               "rx align errors"},
1686 +       {DPMAC_CNT_ING_OVERSIZED,               "rx oversized"},
1687 +       {DPMAC_CNT_ING_VALID_PAUSE_FRAME,       "rx pause"},
1688 +       {DPMAC_CNT_ING_BYTE,                    "rx bytes"},
1689 +       {DPMAC_CNT_ENG_GOOD_FRAME,              "tx frames ok"},
1690 +       {DPMAC_CNT_EGR_UCAST_FRAME,             "tx u-cast"},
1691 +       {DPMAC_CNT_EGR_MCAST_FRAME,             "tx m-cast"},
1692 +       {DPMAC_CNT_EGR_BCAST_FRAME,             "tx b-cast"},
1693 +       {DPMAC_CNT_EGR_ERR_FRAME,               "tx frame errors"},
1694 +       {DPMAC_CNT_EGR_UNDERSIZED,              "tx undersized"},
1695 +       {DPMAC_CNT_EGR_VALID_PAUSE_FRAME,       "tx b-pause"},
1696 +       {DPMAC_CNT_EGR_BYTE,                    "tx bytes"},
1697 +
1698 +};
1699 +
1700 +static void dpaa2_mac_get_strings(struct net_device *netdev,
1701 +                                 u32 stringset, u8 *data)
1702 +{
1703 +       int i;
1704 +
1705 +       switch (stringset) {
1706 +       case ETH_SS_STATS:
1707 +               for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++)
1708 +                       memcpy(data + i * ETH_GSTRING_LEN,
1709 +                              dpaa2_mac_counters[i].name,
1710 +                              ETH_GSTRING_LEN);
1711 +               break;
1712 +       }
1713 +}
1714 +
1715 +static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev,
1716 +                                       struct ethtool_stats *stats,
1717 +                                       u64 *data)
1718 +{
1719 +       struct dpaa2_mac_priv   *priv = netdev_priv(netdev);
1720 +       int                     i;
1721 +       int                     err;
1722 +
1723 +       for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) {
1724 +               err = dpmac_get_counter(priv->mc_dev->mc_io,
1725 +                                       0,
1726 +                                       priv->mc_dev->mc_handle,
1727 +                                       dpaa2_mac_counters[i].id, &data[i]);
1728 +               if (err)
1729 +                       netdev_err(netdev, "dpmac_get_counter[%s] err %d\n",
1730 +                                  dpaa2_mac_counters[i].name, err);
1731 +       }
1732 +}
1733 +
1734 +static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset)
1735 +{
1736 +       switch (sset) {
1737 +       case ETH_SS_STATS:
1738 +               return ARRAY_SIZE(dpaa2_mac_counters);
1739 +       default:
1740 +               return -EOPNOTSUPP;
1741 +       }
1742 +}
1743 +
1744 +static const struct net_device_ops dpaa2_mac_ndo_ops = {
1745 +       .ndo_open               = &dpaa2_mac_open,
1746 +       .ndo_stop               = &dpaa2_mac_stop,
1747 +       .ndo_start_xmit         = &dpaa2_mac_drop_frame,
1748 +       .ndo_get_stats64        = &dpaa2_mac_get_stats,
1749 +};
1750 +
1751 +static const struct ethtool_ops dpaa2_mac_ethtool_ops = {
1752 +       .get_drvinfo            = &dpaa2_mac_get_drvinfo,
1753 +       .get_link_ksettings     = &dpaa2_mac_get_link_ksettings,
1754 +       .set_link_ksettings     = &dpaa2_mac_set_link_ksettings,
1755 +       .get_strings            = &dpaa2_mac_get_strings,
1756 +       .get_ethtool_stats      = &dpaa2_mac_get_ethtool_stats,
1757 +       .get_sset_count         = &dpaa2_mac_get_sset_count,
1758 +};
1759 +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
1760 +
1761 +static void configure_link(struct dpaa2_mac_priv *priv,
1762 +                          struct dpmac_link_cfg *cfg)
1763 +{
1764 +       struct phy_device *phydev = priv->netdev->phydev;
1765 +
1766 +       if (unlikely(!phydev))
1767 +               return;
1768 +
1769 +       phydev->speed = cfg->rate;
1770 +       phydev->duplex  = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
1771 +
1772 +       if (cfg->advertising != 0) {
1773 +               phydev->advertising = 0;
1774 +               link_mode_dpmac2phydev(cfg->advertising, &phydev->advertising);
1775 +       }
1776 +
1777 +       if (phydev->supported & SUPPORTED_Pause) {
1778 +               if (cfg->options & DPMAC_LINK_OPT_PAUSE)
1779 +                       phydev->advertising |= ADVERTISED_Pause;
1780 +               else
1781 +                       phydev->advertising &= ~ADVERTISED_Pause;
1782 +       }
1783 +
1784 +       if (phydev->supported & SUPPORTED_Asym_Pause) {
1785 +               if (cfg->options & DPMAC_LINK_OPT_ASYM_PAUSE)
1786 +                       phydev->advertising |= ADVERTISED_Asym_Pause;
1787 +               else
1788 +                       phydev->advertising &= ~ADVERTISED_Asym_Pause;
1789 +       }
1790 +
1791 +       if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
1792 +               phydev->autoneg = AUTONEG_ENABLE;
1793 +               phydev->advertising |= ADVERTISED_Autoneg;
1794 +       } else {
1795 +               phydev->autoneg = AUTONEG_DISABLE;
1796 +               phydev->advertising &= ~ADVERTISED_Autoneg;
1797 +       }
1798 +
1799 +       phy_start_aneg(phydev);
1800 +}
1801 +
1802 +static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
1803 +{
1804 +       struct device *dev = (struct device *)arg;
1805 +       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1806 +       struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
1807 +       struct dpmac_link_cfg link_cfg = { 0 };
1808 +       u32 status;
1809 +       int err;
1810 +
1811 +       err = dpmac_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
1812 +                                  DPMAC_IRQ_INDEX, &status);
1813 +       if (unlikely(err || !status))
1814 +               return IRQ_NONE;
1815 +
1816 +       /* DPNI-initiated link configuration; 'ifconfig up' also calls this */
1817 +       if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) {
1818 +               if (cmp_dpmac_ver(priv, DPMAC_LINK_AUTONEG_VER_MAJOR,
1819 +                                 DPMAC_LINK_AUTONEG_VER_MINOR) < 0)
1820 +                       err = dpmac_get_link_cfg(mc_dev->mc_io, 0,
1821 +                                                mc_dev->mc_handle, &link_cfg);
1822 +               else
1823 +                       err = dpmac_get_link_cfg_v2(mc_dev->mc_io, 0,
1824 +                                                   mc_dev->mc_handle,
1825 +                                                   &link_cfg);
1826 +               if (unlikely(err))
1827 +                       goto out;
1828 +
1829 +               configure_link(priv, &link_cfg);
1830 +       }
1831 +
1832 +out:
1833 +       dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
1834 +                              DPMAC_IRQ_INDEX, status);
1835 +
1836 +       return IRQ_HANDLED;
1837 +}
1838 +
1839 +static int setup_irqs(struct fsl_mc_device *mc_dev)
1840 +{
1841 +       int err = 0;
1842 +       struct fsl_mc_device_irq *irq;
1843 +
1844 +       err = fsl_mc_allocate_irqs(mc_dev);
1845 +       if (err) {
1846 +               dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
1847 +               return err;
1848 +       }
1849 +
1850 +       irq = mc_dev->irqs[0];
1851 +       err = devm_request_threaded_irq(&mc_dev->dev, irq->msi_desc->irq,
1852 +                                       NULL, &dpaa2_mac_irq_handler,
1853 +                                       IRQF_NO_SUSPEND | IRQF_ONESHOT,
1854 +                                       dev_name(&mc_dev->dev), &mc_dev->dev);
1855 +       if (err) {
1856 +               dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
1857 +                       err);
1858 +               goto free_irq;
1859 +       }
1860 +
1861 +       err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
1862 +                                DPMAC_IRQ_INDEX, DPMAC_IRQ_EVENT_LINK_CFG_REQ);
1863 +       if (err) {
1864 +               dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
1865 +               goto free_irq;
1866 +       }
1867 +       err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
1868 +                                  DPMAC_IRQ_INDEX, 1);
1869 +       if (err) {
1870 +               dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
1871 +               goto free_irq;
1872 +       }
1873 +
1874 +       return 0;
1875 +
1876 +free_irq:
1877 +       fsl_mc_free_irqs(mc_dev);
1878 +
1879 +       return err;
1880 +}
1881 +
1882 +static void teardown_irqs(struct fsl_mc_device *mc_dev)
1883 +{
1884 +       int err;
1885 +
1886 +       err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
1887 +                                  DPMAC_IRQ_INDEX, 0);
1888 +       if (err)
1889 +               dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
1890 +
1891 +       fsl_mc_free_irqs(mc_dev);
1892 +}
1893 +
1894 +static struct device_node *find_dpmac_node(struct device *dev, u16 dpmac_id)
1895 +{
1896 +       struct device_node *dpmacs, *dpmac = NULL;
1897 +       struct device_node *mc_node = dev->of_node;
1898 +       u32 id;
1899 +       int err;
1900 +
1901 +       dpmacs = of_find_node_by_name(mc_node, "dpmacs");
1902 +       if (!dpmacs) {
1903 +               dev_err(dev, "No dpmacs subnode in device-tree\n");
1904 +               return NULL;
1905 +       }
1906 +
1907 +       while ((dpmac = of_get_next_child(dpmacs, dpmac))) {
1908 +               err = of_property_read_u32(dpmac, "reg", &id);
1909 +               if (err)
1910 +                       continue;
1911 +               if (id == dpmac_id)
1912 +                       return dpmac;
1913 +       }
1914 +
1915 +       return NULL;
1916 +}
1917 +
1918 +static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
1919 +{
1920 +       struct device           *dev;
1921 +       struct dpaa2_mac_priv   *priv = NULL;
1922 +       struct device_node      *phy_node, *dpmac_node;
1923 +       struct net_device       *netdev;
1924 +       int                     if_mode;
1925 +       int                     err = 0;
1926 +
1927 +       dev = &mc_dev->dev;
1928 +
1929 +       /* prepare a net_dev structure to make the phy lib API happy */
1930 +       netdev = alloc_etherdev(sizeof(*priv));
1931 +       if (!netdev) {
1932 +               dev_err(dev, "alloc_etherdev error\n");
1933 +               err = -ENOMEM;
1934 +               goto err_exit;
1935 +       }
1936 +       priv = netdev_priv(netdev);
1937 +       priv->mc_dev = mc_dev;
1938 +       priv->netdev = netdev;
1939 +
1940 +       SET_NETDEV_DEV(netdev, dev);
1941 +
1942 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1943 +       snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
1944 +#endif
1945 +
1946 +       dev_set_drvdata(dev, priv);
1947 +
1948 +       /* We may need to issue MC commands while in atomic context */
1949 +       err = fsl_mc_portal_allocate(mc_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
1950 +                                    &mc_dev->mc_io);
1951 +       if (err || !mc_dev->mc_io) {
1952 +               dev_dbg(dev, "fsl_mc_portal_allocate error: %d\n", err);
1953 +               err = -EPROBE_DEFER;
1954 +               goto err_free_netdev;
1955 +       }
1956 +
1957 +       err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
1958 +                        &mc_dev->mc_handle);
1959 +       if (err || !mc_dev->mc_handle) {
1960 +               dev_err(dev, "dpmac_open error: %d\n", err);
1961 +               err = -ENODEV;
1962 +               goto err_free_mcp;
1963 +       }
1964 +
1965 +       err = dpmac_get_api_version(mc_dev->mc_io, 0, &priv->dpmac_ver_major,
1966 +                                   &priv->dpmac_ver_minor);
1967 +       if (err) {
1968 +               dev_err(dev, "dpmac_get_api_version failed\n");
1969 +               goto err_version;
1970 +       }
1971 +
1972 +       if (cmp_dpmac_ver(priv, DPMAC_VER_MAJOR, DPMAC_VER_MINOR) < 0) {
1973 +               dev_err(dev, "DPMAC version %u.%u lower than supported %u.%u\n",
1974 +                       priv->dpmac_ver_major, priv->dpmac_ver_minor,
1975 +                       DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
1976 +               err = -ENOTSUPP;
1977 +               goto err_version;
1978 +       }
1979 +
1980 +       err = dpmac_get_attributes(mc_dev->mc_io, 0,
1981 +                                  mc_dev->mc_handle, &priv->attr);
1982 +       if (err) {
1983 +               dev_err(dev, "dpmac_get_attributes err %d\n", err);
1984 +               err = -EINVAL;
1985 +               goto err_close;
1986 +       }
1987 +
1988 +       /* Look up the DPMAC node in the device-tree. */
1989 +       dpmac_node = find_dpmac_node(dev, priv->attr.id);
1990 +       if (!dpmac_node) {
1991 +               dev_err(dev, "No dpmac@%d subnode found.\n", priv->attr.id);
1992 +               err = -ENODEV;
1993 +               goto err_close;
1994 +       }
1995 +
1996 +       err = setup_irqs(mc_dev);
1997 +       if (err) {
1998 +               err = -EFAULT;
1999 +               goto err_close;
2000 +       }
2001 +
2002 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
2003 +       /* OPTIONAL, register netdev just to make it visible to the user */
2004 +       netdev->netdev_ops = &dpaa2_mac_ndo_ops;
2005 +       netdev->ethtool_ops = &dpaa2_mac_ethtool_ops;
2006 +
2007 +       /* phy starts up enabled so netdev should be up too */
2008 +       netdev->flags |= IFF_UP;
2009 +
2010 +       err = register_netdev(priv->netdev);
2011 +       if (err < 0) {
2012 +               dev_err(dev, "register_netdev error %d\n", err);
2013 +               err = -ENODEV;
2014 +               goto err_free_irq;
2015 +       }
2016 +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
2017 +
2018 +       /* get the interface mode from the dpmac of node or from the MC attributes */
2019 +       if_mode = of_get_phy_mode(dpmac_node);
2020 +       if (if_mode >= 0) {
2021 +               dev_dbg(dev, "\tusing if mode %s for eth_if %d\n",
2022 +                       phy_modes(if_mode), priv->attr.eth_if);
2023 +               goto link_type;
2024 +       }
2025 +
2026 +       if (priv->attr.eth_if < ARRAY_SIZE(dpaa2_mac_iface_mode)) {
2027 +               if_mode = dpaa2_mac_iface_mode[priv->attr.eth_if];
2028 +               dev_dbg(dev, "\tusing if mode %s for eth_if %d\n",
2029 +                       phy_modes(if_mode), priv->attr.eth_if);
2030 +       } else {
2031 +               dev_err(dev, "Unexpected interface mode %d\n",
2032 +                       priv->attr.eth_if);
2033 +               err = -EINVAL;
2034 +               goto err_no_if_mode;
2035 +       }
2036 +
2037 +link_type:
2038 +       /* probe the PHY as fixed-link if the DPMAC attribute indicates so */
2039 +       if (priv->attr.link_type == DPMAC_LINK_TYPE_FIXED)
2040 +               goto probe_fixed_link;
2041 +
2042 +       /* or if there's no phy-handle defined in the device tree */
2043 +       phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
2044 +       if (!phy_node) {
2045 +               goto probe_fixed_link;
2046 +       }
2047 +
2048 +       /* try to connect to the PHY */
2049 +       netdev->phydev = of_phy_connect(netdev, phy_node,
2050 +                                       &dpaa2_mac_link_changed, 0, if_mode);
2051 +       if (!netdev->phydev) {
2052 +               /* No need for dev_err(); the kernel's loud enough as it is. */
2053 +               dev_dbg(dev, "Can't of_phy_connect() now.\n");
2054 +               /* We might be waiting for the MDIO MUX to probe, so defer
2055 +                * our own probing.
2056 +                */
2057 +               err = -EPROBE_DEFER;
2058 +               goto err_defer;
2059 +       }
2060 +       dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode));
2061 +
2062 +probe_fixed_link:
2063 +       if (!netdev->phydev) {
2064 +               struct fixed_phy_status status = {
2065 +                       .link = 1,
2066 +                       /* fixed-phys don't support 10Gbps speed for now */
2067 +                       .speed = 1000,
2068 +                       .duplex = 1,
2069 +               };
2070 +
2071 +               /* try to register a fixed link phy */
2072 +               netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1,
2073 +                                                   NULL);
2074 +               if (!netdev->phydev || IS_ERR(netdev->phydev)) {
2075 +                       dev_err(dev, "error trying to register fixed PHY\n");
2076 +                       /* So we don't crash unregister_netdev() later on */
2077 +                       netdev->phydev = NULL;
2078 +                       err = -EFAULT;
2079 +                       goto err_no_phy;
2080 +               }
2081 +
2082 +               err = phy_connect_direct(netdev, netdev->phydev,
2083 +                                        &dpaa2_mac_link_changed, if_mode);
2084 +               if (err) {
2085 +                       dev_err(dev, "error trying to connect to PHY\n");
2086 +                       goto err_no_phy;
2087 +               }
2088 +
2089 +               dev_info(dev, "Registered fixed PHY.\n");
2090 +       }
2091 +
2092 +       dpaa2_mac_open(netdev);
2093 +
2094 +       return 0;
2095 +
2096 +err_no_if_mode:
2097 +err_defer:
2098 +err_no_phy:
2099 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
2100 +       unregister_netdev(netdev);
2101 +err_free_irq:
2102 +#endif
2103 +       teardown_irqs(mc_dev);
2104 +err_version:
2105 +err_close:
2106 +       dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2107 +err_free_mcp:
2108 +       fsl_mc_portal_free(mc_dev->mc_io);
2109 +err_free_netdev:
2110 +       free_netdev(netdev);
2111 +err_exit:
2112 +       return err;
2113 +}
2114 +
2115 +static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
2116 +{
2117 +       struct device           *dev = &mc_dev->dev;
2118 +       struct dpaa2_mac_priv   *priv = dev_get_drvdata(dev);
2119 +       struct net_device       *netdev = priv->netdev;
2120 +
2121 +       dpaa2_mac_stop(netdev);
2122 +
2123 +       if (phy_is_pseudo_fixed_link(netdev->phydev))
2124 +               fixed_phy_unregister(netdev->phydev);
2125 +       else
2126 +               phy_disconnect(netdev->phydev);
2127 +       netdev->phydev = NULL;
2128 +
2129 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
2130 +       unregister_netdev(priv->netdev);
2131 +#endif
2132 +       teardown_irqs(priv->mc_dev);
2133 +       dpmac_close(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle);
2134 +       fsl_mc_portal_free(priv->mc_dev->mc_io);
2135 +       free_netdev(priv->netdev);
2136 +
2137 +       dev_set_drvdata(dev, NULL);
2138 +
2139 +       return 0;
2140 +}
2141 +
2142 +static const struct fsl_mc_device_id dpaa2_mac_match_id_table[] = {
2143 +       {
2144 +               .vendor = FSL_MC_VENDOR_FREESCALE,
2145 +               .obj_type = "dpmac",
2146 +       },
2147 +       { .vendor = 0x0 }
2148 +};
2149 +MODULE_DEVICE_TABLE(fslmc, dpaa2_mac_match_id_table);
2150 +
2151 +static struct fsl_mc_driver dpaa2_mac_drv = {
2152 +       .driver = {
2153 +               .name           = KBUILD_MODNAME,
2154 +               .owner          = THIS_MODULE,
2155 +       },
2156 +       .probe          = dpaa2_mac_probe,
2157 +       .remove         = dpaa2_mac_remove,
2158 +       .match_id_table = dpaa2_mac_match_id_table,
2159 +};
2160 +
2161 +module_fsl_mc_driver(dpaa2_mac_drv);
2162 +
2163 +MODULE_LICENSE("GPL");
2164 +MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver");