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
6 This is an integrated patch of dpaa2-mac-phy for layerscape
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>
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
39 +++ b/drivers/staging/fsl-dpaa2/mac/Kconfig
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
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.
55 +config FSL_DPAA2_MAC_NETDEVS
56 + bool "Expose net interfaces for PHYs"
58 + depends on FSL_DPAA2_MAC
60 + Exposes macX net interfaces which allow direct control over MACs and
63 + Leave disabled if unsure.
65 +++ b/drivers/staging/fsl-dpaa2/mac/Makefile
68 +obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o
70 +dpaa2-mac-objs := mac.o dpmac.o
73 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
76 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
78 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
80 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
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.
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
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.
111 +#ifndef _FSL_DPMAC_CMD_H
112 +#define _FSL_DPMAC_CMD_H
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
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)
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)
131 +#define DPMAC_CMDID_GET_ATTR DPMAC_CMD(0x004)
132 +#define DPMAC_CMDID_RESET DPMAC_CMD(0x005)
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)
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)
147 +#define DPMAC_CMDID_SET_PORT_MAC_ADDR DPMAC_CMD(0x0c5)
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)
158 +struct dpmac_cmd_open {
162 +struct dpmac_cmd_create {
166 +struct dpmac_cmd_destroy {
170 +struct dpmac_cmd_set_irq_enable {
176 +struct dpmac_cmd_get_irq_enable {
181 +struct dpmac_rsp_get_irq_enable {
185 +struct dpmac_cmd_set_irq_mask {
190 +struct dpmac_cmd_get_irq_mask {
195 +struct dpmac_rsp_get_irq_mask {
199 +struct dpmac_cmd_get_irq_status {
204 +struct dpmac_rsp_get_irq_status {
208 +struct dpmac_cmd_clear_irq_status {
213 +struct dpmac_rsp_get_attributes {
220 +struct dpmac_rsp_get_link_cfg {
225 +struct dpmac_rsp_get_link_cfg_v2 {
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
237 +struct dpmac_cmd_set_link_state {
241 + /* only least significant bit is valid */
245 +struct dpmac_cmd_set_link_state_v2 {
249 + /* from lsb: up:1, state_valid:1 */
256 +struct dpmac_cmd_get_counter {
260 +struct dpmac_rsp_get_counter {
265 +struct dpmac_rsp_get_api_version {
270 +struct dpmac_cmd_set_port_mac_addr {
275 +#endif /* _FSL_DPMAC_CMD_H */
277 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c
279 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
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.
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
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.
310 +#include <linux/fsl/mc.h>
312 +#include "dpmac-cmd.h"
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
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
329 + * Return: '0' on Success; Error code otherwise.
331 +int dpmac_open(struct fsl_mc_io *mc_io,
336 + struct dpmac_cmd_open *cmd_params;
337 + struct fsl_mc_command cmd = { 0 };
340 + /* prepare command */
341 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
344 + cmd_params = (struct dpmac_cmd_open *)cmd.params;
345 + cmd_params->dpmac_id = cpu_to_le32(dpmac_id);
347 + /* send command to mc*/
348 + err = mc_send_command(mc_io, &cmd);
352 + /* retrieve response parameters */
353 + *token = mc_cmd_hdr_read_token(&cmd);
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
364 + * After this function is called, no further operations are
365 + * allowed on the object without opening a new control session.
367 + * Return: '0' on Success; Error code otherwise.
369 +int dpmac_close(struct fsl_mc_io *mc_io,
373 + struct fsl_mc_command cmd = { 0 };
375 + /* prepare command */
376 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
379 + /* send command to mc*/
380 + return mc_send_command(mc_io, &cmd);
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
391 + * Create the DPMAC object, allocate required resources and
392 + * perform required initialization.
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.
400 + * Return: '0' on Success; Error code otherwise.
402 +int dpmac_create(struct fsl_mc_io *mc_io,
405 + const struct dpmac_cfg *cfg,
408 + struct dpmac_cmd_create *cmd_params;
409 + struct fsl_mc_command cmd = { 0 };
412 + /* prepare command */
413 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
416 + cmd_params = (struct dpmac_cmd_create *)cmd.params;
417 + cmd_params->mac_id = cpu_to_le32(cfg->mac_id);
419 + /* send command to mc*/
420 + err = mc_send_command(mc_io, &cmd);
424 + /* retrieve response parameters */
425 + *obj_id = mc_cmd_read_object_id(&cmd);
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;
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.
443 + * Return: '0' on Success; error code otherwise.
445 +int dpmac_destroy(struct fsl_mc_io *mc_io,
450 + struct dpmac_cmd_destroy *cmd_params;
451 + struct fsl_mc_command cmd = { 0 };
453 + /* prepare command */
454 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
457 + cmd_params = (struct dpmac_cmd_destroy *)cmd.params;
458 + cmd_params->dpmac_id = cpu_to_le32(object_id);
460 + /* send command to mc*/
461 + return mc_send_command(mc_io, &cmd);
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
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
477 + * Return: '0' on Success; Error code otherwise.
479 +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
485 + struct dpmac_cmd_set_irq_enable *cmd_params;
486 + struct fsl_mc_command cmd = { 0 };
488 + /* prepare command */
489 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
492 + cmd_params = (struct dpmac_cmd_set_irq_enable *)cmd.params;
493 + cmd_params->irq_index = irq_index;
494 + cmd_params->enable = en;
496 + /* send command to mc*/
497 + return mc_send_command(mc_io, &cmd);
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
508 + * Return: '0' on Success; Error code otherwise.
510 +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
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 };
521 + /* prepare command */
522 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
525 + cmd_params = (struct dpmac_cmd_get_irq_enable *)cmd.params;
526 + cmd_params->irq_index = irq_index;
528 + /* send command to mc*/
529 + err = mc_send_command(mc_io, &cmd);
533 + /* retrieve response parameters */
534 + rsp_params = (struct dpmac_rsp_get_irq_enable *)cmd.params;
535 + *en = rsp_params->enabled;
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;
549 + * 1 = consider event for asserting IRQ
551 + * Every interrupt can have up to 32 causes and the interrupt model supports
552 + * masking/unmasking each cause independently
554 + * Return: '0' on Success; Error code otherwise.
556 +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
562 + struct dpmac_cmd_set_irq_mask *cmd_params;
563 + struct fsl_mc_command cmd = { 0 };
565 + /* prepare command */
566 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
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;
573 + /* send command to mc*/
574 + return mc_send_command(mc_io, &cmd);
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
585 + * Every interrupt can have up to 32 causes and the interrupt model supports
586 + * masking/unmasking each cause independently
588 + * Return: '0' on Success; Error code otherwise.
590 +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
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 };
601 + /* prepare command */
602 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
605 + cmd_params = (struct dpmac_cmd_get_irq_mask *)cmd.params;
606 + cmd_params->irq_index = irq_index;
608 + /* send command to mc*/
609 + err = mc_send_command(mc_io, &cmd);
613 + /* retrieve response parameters */
614 + rsp_params = (struct dpmac_rsp_get_irq_mask *)cmd.params;
615 + *mask = le32_to_cpu(rsp_params->mask);
621 + * dpmac_get_irq_status() - Get the current status of any pending interrupts.
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
631 + * Return: '0' on Success; Error code otherwise.
633 +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
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 };
644 + /* prepare command */
645 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
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;
652 + /* send command to mc*/
653 + err = mc_send_command(mc_io, &cmd);
657 + /* retrieve response parameters */
658 + rsp_params = (struct dpmac_rsp_get_irq_status *)cmd.params;
659 + *status = le32_to_cpu(rsp_params->status);
665 + * dpmac_clear_irq_status() - Clear a pending interrupt's status
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:
673 + * 1 = clear status bit
675 + * Return: '0' on Success; Error code otherwise.
677 +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
683 + struct dpmac_cmd_clear_irq_status *cmd_params;
684 + struct fsl_mc_command cmd = { 0 };
686 + /* prepare command */
687 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
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;
694 + /* send command to mc*/
695 + return mc_send_command(mc_io, &cmd);
699 + * dpmac_get_attributes - Retrieve DPMAC attributes.
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
706 + * Return: '0' on Success; Error code otherwise.
708 +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
711 + struct dpmac_attr *attr)
713 + struct dpmac_rsp_get_attributes *rsp_params;
714 + struct fsl_mc_command cmd = { 0 };
717 + /* prepare command */
718 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
722 + /* send command to mc*/
723 + err = mc_send_command(mc_io, &cmd);
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);
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
744 + * Return: '0' on Success; Error code otherwise.
746 +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
749 + struct dpmac_link_cfg *cfg)
751 + struct dpmac_rsp_get_link_cfg *rsp_params;
752 + struct fsl_mc_command cmd = { 0 };
755 + /* prepare command */
756 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
760 + /* send command to mc*/
761 + err = mc_send_command(mc_io, &cmd);
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);
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
779 + * Return: '0' on Success; Error code otherwise.
781 +int dpmac_get_link_cfg_v2(struct fsl_mc_io *mc_io,
784 + struct dpmac_link_cfg *cfg)
786 + struct dpmac_rsp_get_link_cfg_v2 *rsp_params;
787 + struct fsl_mc_command cmd = { 0 };
790 + /* prepare command */
791 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG_V2,
795 + /* send command to mc*/
796 + err = mc_send_command(mc_io, &cmd);
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);
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
815 + * Return: '0' on Success; Error code otherwise.
817 +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
820 + struct dpmac_link_state *link_state)
822 + struct dpmac_cmd_set_link_state *cmd_params;
823 + struct fsl_mc_command cmd = { 0 };
825 + /* prepare command */
826 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
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);
834 + /* send command to mc*/
835 + return mc_send_command(mc_io, &cmd);
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
845 + * Return: '0' on Success; Error code otherwise.
847 +int dpmac_set_link_state_v2(struct fsl_mc_io *mc_io,
850 + struct dpmac_link_state *link_state)
852 + struct dpmac_cmd_set_link_state_v2 *cmd_params;
853 + struct fsl_mc_command cmd = { 0 };
855 + /* prepare command */
856 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE_V2,
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);
868 + /* send command to mc*/
869 + return mc_send_command(mc_io, &cmd);
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
880 + * Return: The requested counter; '0' otherwise.
882 +int dpmac_get_counter(struct fsl_mc_io *mc_io,
885 + enum dpmac_counter type,
888 + struct dpmac_cmd_get_counter *dpmac_cmd;
889 + struct dpmac_rsp_get_counter *dpmac_rsp;
890 + struct fsl_mc_command cmd = { 0 };
893 + /* prepare command */
894 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
897 + dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params;
898 + dpmac_cmd->type = type;
900 + /* send command to mc*/
901 + err = mc_send_command(mc_io, &cmd);
905 + dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params;
906 + *counter = le64_to_cpu(dpmac_rsp->counter);
912 +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
917 + struct dpmac_cmd_set_port_mac_addr *dpmac_cmd;
918 + struct fsl_mc_command cmd = { 0 };
920 + /* prepare command */
921 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PORT_MAC_ADDR,
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];
932 + /* send command to mc*/
933 + return mc_send_command(mc_io, &cmd);
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
943 + * Return: '0' on Success; Error code otherwise.
945 +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
950 + struct dpmac_rsp_get_api_version *rsp_params;
951 + struct fsl_mc_command cmd = { 0 };
954 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION,
958 + err = mc_send_command(mc_io, &cmd);
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);
969 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h
971 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
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.
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
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.
1002 +#ifndef __FSL_DPMAC_H
1003 +#define __FSL_DPMAC_H
1005 +/* Data Path MAC API
1006 + * Contains initialization APIs and runtime control APIs for DPMAC
1011 +int dpmac_open(struct fsl_mc_io *mc_io,
1016 +int dpmac_close(struct fsl_mc_io *mc_io,
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
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
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
1046 +enum dpmac_eth_if {
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,
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.
1070 +int dpmac_create(struct fsl_mc_io *mc_io,
1073 + const struct dpmac_cfg *cfg,
1076 +int dpmac_destroy(struct fsl_mc_io *mc_io,
1082 + * DPMAC IRQ Index and Events
1088 +#define DPMAC_IRQ_INDEX 0
1090 + * IRQ event - indicates a change in link state
1092 +#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001
1094 + * IRQ event - Indicates that the link state changed
1096 +#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002
1098 +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
1104 +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
1110 +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
1116 +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
1122 +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
1128 +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
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
1141 +struct dpmac_attr {
1144 + enum dpmac_eth_if eth_if;
1145 + enum dpmac_link_type link_type;
1148 +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
1151 + struct dpmac_attr *attr);
1154 + * DPMAC link configuration/state options
1158 + * Enable auto-negotiation
1160 +#define DPMAC_LINK_OPT_AUTONEG 0x0000000000000001ULL
1162 + * Enable half-duplex mode
1164 +#define DPMAC_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
1166 + * Enable pause frames
1168 +#define DPMAC_LINK_OPT_PAUSE 0x0000000000000004ULL
1170 + * Enable a-symmetric pause frames
1172 +#define DPMAC_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
1175 + * Advertised link speeds
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
1184 + * Advertise auto-negotiation enable
1186 +#define DPMAC_ADVERTISED_AUTONEG 0x0000000000000008ULL
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)
1194 +struct dpmac_link_cfg {
1200 +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
1203 + struct dpmac_link_cfg *cfg);
1205 +int dpmac_get_link_cfg_v2(struct fsl_mc_io *mc_io,
1208 + struct dpmac_link_cfg *cfg);
1211 + * struct dpmac_link_state - DPMAC link configuration request
1212 + * @rate: Rate in Mbps
1213 + * @options: Enable/Disable DPMAC link cfg features (bitmap)
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)
1219 +struct dpmac_link_state {
1228 +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
1231 + struct dpmac_link_state *link_state);
1233 +int dpmac_set_link_state_v2(struct fsl_mc_io *mc_io,
1236 + struct dpmac_link_state *link_state);
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),
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
1282 + * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including
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
1316 +int dpmac_get_counter(struct fsl_mc_io *mc_io,
1319 + enum dpmac_counter type,
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
1332 + * Return: The requested counter; '0' otherwise.
1334 +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
1337 + const u8 addr[6]);
1339 +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
1344 +#endif /* __FSL_DPMAC_H */
1346 +++ b/drivers/staging/fsl-dpaa2/mac/mac.c
1348 +/* Copyright 2015 Freescale Semiconductor Inc.
1349 + * Copyright 2018 NXP
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.
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
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.
1380 +#include <linux/module.h>
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>
1388 +#include <uapi/linux/if_bridge.h>
1389 +#include <net/netlink.h>
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>
1397 +#include <linux/fsl/mc.h>
1400 +#include "dpmac-cmd.h"
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;
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...
1417 + * This must be kept in sync with enum dpmac_eth_if.
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 */
1434 +static int cmp_dpmac_ver(struct dpaa2_mac_priv *priv,
1435 + u16 ver_major, u16 ver_minor)
1437 + if (priv->dpmac_ver_major == ver_major)
1438 + return priv->dpmac_ver_minor - ver_minor;
1439 + return priv->dpmac_ver_major - ver_major;
1442 +#define DPMAC_LINK_AUTONEG_VER_MAJOR 4
1443 +#define DPMAC_LINK_AUTONEG_VER_MINOR 3
1445 +struct dpaa2_mac_link_mode_map {
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},
1459 +static void link_mode_dpmac2phydev(u64 dpmac_lm, u32 *phydev_lm)
1461 + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
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);
1469 + ethtool_convert_link_mode_to_legacy_u32(phydev_lm, mask);
1472 +static void link_mode_phydev2dpmac(u32 phydev_lm, u64 *dpni_lm)
1477 + ethtool_convert_legacy_u32_to_link_mode(&lm, phydev_lm);
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;
1485 +static void dpaa2_mac_link_changed(struct net_device *netdev)
1487 + struct phy_device *phydev;
1488 + struct dpmac_link_state state = { 0 };
1489 + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
1492 + /* the PHY just notified us of link state change */
1493 + phydev = netdev->phydev;
1495 + state.up = !!phydev->link;
1496 + if (phydev->link) {
1497 + state.rate = phydev->speed;
1499 + if (!phydev->duplex)
1500 + state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
1501 + if (phydev->autoneg)
1502 + state.options |= DPMAC_LINK_OPT_AUTONEG;
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;
1510 + netif_carrier_on(netdev);
1512 + netif_carrier_off(netdev);
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);
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);
1527 + link_mode_phydev2dpmac(phydev->supported, &state.supported);
1528 + link_mode_phydev2dpmac(phydev->advertising, &state.advertising);
1529 + state.state_valid = 1;
1531 + err = dpmac_set_link_state_v2(priv->mc_dev->mc_io, 0,
1532 + priv->mc_dev->mc_handle, &state);
1534 + if (unlikely(err))
1535 + dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
1538 +static int dpaa2_mac_open(struct net_device *netdev)
1540 + /* start PHY state machine */
1541 + phy_start(netdev->phydev);
1546 +static int dpaa2_mac_stop(struct net_device *netdev)
1548 + if (!netdev->phydev)
1551 + /* stop PHY state machine */
1552 + phy_stop(netdev->phydev);
1554 + /* signal link down to firmware */
1555 + netdev->phydev->link = 0;
1556 + dpaa2_mac_link_changed(netdev);
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)
1566 + /* we don't support I/O for now, drop the frame */
1567 + dev_kfree_skb_any(skb);
1568 + return NETDEV_TX_OK;
1571 +static void dpaa2_mac_get_drvinfo(struct net_device *net_dev,
1572 + struct ethtool_drvinfo *drvinfo)
1574 + struct dpaa2_mac_priv *priv = netdev_priv(net_dev);
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));
1583 +static int dpaa2_mac_get_link_ksettings(struct net_device *netdev,
1584 + struct ethtool_link_ksettings *ks)
1586 + phy_ethtool_ksettings_get(netdev->phydev, ks);
1591 +static int dpaa2_mac_set_link_ksettings(struct net_device *netdev,
1592 + const struct ethtool_link_ksettings *ks)
1594 + return phy_ethtool_ksettings_set(netdev->phydev, ks);
1597 +static void dpaa2_mac_get_stats(struct net_device *netdev,
1598 + struct rtnl_link_stats64 *storage)
1600 + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
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);
1609 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1610 + DPMAC_CNT_EGR_BCAST_FRAME, &tmp);
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);
1618 + storage->tx_packets += tmp;
1620 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1621 + DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped);
1624 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1625 + DPMAC_CNT_EGR_BYTE, &storage->tx_bytes);
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);
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);
1637 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1638 + DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast);
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);
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);
1650 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1651 + DPMAC_CNT_ING_OVERSIZED, &tmp);
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);
1662 + netdev_err(netdev, "dpmac_get_counter err %d\n", err);
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"},
1700 +static void dpaa2_mac_get_strings(struct net_device *netdev,
1701 + u32 stringset, u8 *data)
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,
1715 +static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev,
1716 + struct ethtool_stats *stats,
1719 + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
1723 + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) {
1724 + err = dpmac_get_counter(priv->mc_dev->mc_io,
1726 + priv->mc_dev->mc_handle,
1727 + dpaa2_mac_counters[i].id, &data[i]);
1729 + netdev_err(netdev, "dpmac_get_counter[%s] err %d\n",
1730 + dpaa2_mac_counters[i].name, err);
1734 +static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset)
1737 + case ETH_SS_STATS:
1738 + return ARRAY_SIZE(dpaa2_mac_counters);
1740 + return -EOPNOTSUPP;
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,
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,
1759 +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
1761 +static void configure_link(struct dpaa2_mac_priv *priv,
1762 + struct dpmac_link_cfg *cfg)
1764 + struct phy_device *phydev = priv->netdev->phydev;
1766 + if (unlikely(!phydev))
1769 + phydev->speed = cfg->rate;
1770 + phydev->duplex = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
1772 + if (cfg->advertising != 0) {
1773 + phydev->advertising = 0;
1774 + link_mode_dpmac2phydev(cfg->advertising, &phydev->advertising);
1777 + if (phydev->supported & SUPPORTED_Pause) {
1778 + if (cfg->options & DPMAC_LINK_OPT_PAUSE)
1779 + phydev->advertising |= ADVERTISED_Pause;
1781 + phydev->advertising &= ~ADVERTISED_Pause;
1784 + if (phydev->supported & SUPPORTED_Asym_Pause) {
1785 + if (cfg->options & DPMAC_LINK_OPT_ASYM_PAUSE)
1786 + phydev->advertising |= ADVERTISED_Asym_Pause;
1788 + phydev->advertising &= ~ADVERTISED_Asym_Pause;
1791 + if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
1792 + phydev->autoneg = AUTONEG_ENABLE;
1793 + phydev->advertising |= ADVERTISED_Autoneg;
1795 + phydev->autoneg = AUTONEG_DISABLE;
1796 + phydev->advertising &= ~ADVERTISED_Autoneg;
1799 + phy_start_aneg(phydev);
1802 +static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
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 };
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))
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);
1823 + err = dpmac_get_link_cfg_v2(mc_dev->mc_io, 0,
1824 + mc_dev->mc_handle,
1826 + if (unlikely(err))
1829 + configure_link(priv, &link_cfg);
1833 + dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
1834 + DPMAC_IRQ_INDEX, status);
1836 + return IRQ_HANDLED;
1839 +static int setup_irqs(struct fsl_mc_device *mc_dev)
1842 + struct fsl_mc_device_irq *irq;
1844 + err = fsl_mc_allocate_irqs(mc_dev);
1846 + dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
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);
1856 + dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
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);
1864 + dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
1867 + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
1868 + DPMAC_IRQ_INDEX, 1);
1870 + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
1877 + fsl_mc_free_irqs(mc_dev);
1882 +static void teardown_irqs(struct fsl_mc_device *mc_dev)
1886 + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
1887 + DPMAC_IRQ_INDEX, 0);
1889 + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
1891 + fsl_mc_free_irqs(mc_dev);
1894 +static struct device_node *find_dpmac_node(struct device *dev, u16 dpmac_id)
1896 + struct device_node *dpmacs, *dpmac = NULL;
1897 + struct device_node *mc_node = dev->of_node;
1901 + dpmacs = of_find_node_by_name(mc_node, "dpmacs");
1903 + dev_err(dev, "No dpmacs subnode in device-tree\n");
1907 + while ((dpmac = of_get_next_child(dpmacs, dpmac))) {
1908 + err = of_property_read_u32(dpmac, "reg", &id);
1911 + if (id == dpmac_id)
1918 +static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
1920 + struct device *dev;
1921 + struct dpaa2_mac_priv *priv = NULL;
1922 + struct device_node *phy_node, *dpmac_node;
1923 + struct net_device *netdev;
1927 + dev = &mc_dev->dev;
1929 + /* prepare a net_dev structure to make the phy lib API happy */
1930 + netdev = alloc_etherdev(sizeof(*priv));
1932 + dev_err(dev, "alloc_etherdev error\n");
1936 + priv = netdev_priv(netdev);
1937 + priv->mc_dev = mc_dev;
1938 + priv->netdev = netdev;
1940 + SET_NETDEV_DEV(netdev, dev);
1942 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1943 + snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
1946 + dev_set_drvdata(dev, priv);
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,
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;
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);
1962 + goto err_free_mcp;
1965 + err = dpmac_get_api_version(mc_dev->mc_io, 0, &priv->dpmac_ver_major,
1966 + &priv->dpmac_ver_minor);
1968 + dev_err(dev, "dpmac_get_api_version failed\n");
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);
1980 + err = dpmac_get_attributes(mc_dev->mc_io, 0,
1981 + mc_dev->mc_handle, &priv->attr);
1983 + dev_err(dev, "dpmac_get_attributes err %d\n", err);
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);
1996 + err = setup_irqs(mc_dev);
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;
2007 + /* phy starts up enabled so netdev should be up too */
2008 + netdev->flags |= IFF_UP;
2010 + err = register_netdev(priv->netdev);
2012 + dev_err(dev, "register_netdev error %d\n", err);
2014 + goto err_free_irq;
2016 +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
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);
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);
2031 + dev_err(dev, "Unexpected interface mode %d\n",
2032 + priv->attr.eth_if);
2034 + goto err_no_if_mode;
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;
2042 + /* or if there's no phy-handle defined in the device tree */
2043 + phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
2045 + goto probe_fixed_link;
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.
2057 + err = -EPROBE_DEFER;
2060 + dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode));
2063 + if (!netdev->phydev) {
2064 + struct fixed_phy_status status = {
2066 + /* fixed-phys don't support 10Gbps speed for now */
2071 + /* try to register a fixed link phy */
2072 + netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1,
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;
2082 + err = phy_connect_direct(netdev, netdev->phydev,
2083 + &dpaa2_mac_link_changed, if_mode);
2085 + dev_err(dev, "error trying to connect to PHY\n");
2089 + dev_info(dev, "Registered fixed PHY.\n");
2092 + dpaa2_mac_open(netdev);
2099 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
2100 + unregister_netdev(netdev);
2103 + teardown_irqs(mc_dev);
2106 + dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2108 + fsl_mc_portal_free(mc_dev->mc_io);
2110 + free_netdev(netdev);
2115 +static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
2117 + struct device *dev = &mc_dev->dev;
2118 + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
2119 + struct net_device *netdev = priv->netdev;
2121 + dpaa2_mac_stop(netdev);
2123 + if (phy_is_pseudo_fixed_link(netdev->phydev))
2124 + fixed_phy_unregister(netdev->phydev);
2126 + phy_disconnect(netdev->phydev);
2127 + netdev->phydev = NULL;
2129 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
2130 + unregister_netdev(priv->netdev);
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);
2137 + dev_set_drvdata(dev, NULL);
2142 +static const struct fsl_mc_device_id dpaa2_mac_match_id_table[] = {
2144 + .vendor = FSL_MC_VENDOR_FREESCALE,
2145 + .obj_type = "dpmac",
2149 +MODULE_DEVICE_TABLE(fslmc, dpaa2_mac_match_id_table);
2151 +static struct fsl_mc_driver dpaa2_mac_drv = {
2153 + .name = KBUILD_MODNAME,
2154 + .owner = THIS_MODULE,
2156 + .probe = dpaa2_mac_probe,
2157 + .remove = dpaa2_mac_remove,
2158 + .match_id_table = dpaa2_mac_match_id_table,
2161 +module_fsl_mc_driver(dpaa2_mac_drv);
2163 +MODULE_LICENSE("GPL");
2164 +MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver");