bcm63xx: ar-5315u: expose LEDs through controller
[openwrt/staging/mkresin.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");