1 From 92cf25fe454dd42136e717ba679a9dba740db0e7 Mon Sep 17 00:00:00 2001
2 From: Biwen Li <biwen.li@nxp.com>
3 Date: Tue, 30 Oct 2018 18:26:18 +0800
4 Subject: [PATCH 10/40] dpaa2-mac-phy: support layerscape
5 This is an integrated patch of dpaa2-mac-phy for
8 Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
9 Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
10 Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
11 Signed-off-by: Constantin Tudor <constantin.tudor@nxp.com>
12 Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
13 Signed-off-by: Itai Katz <itai.katz@freescale.com>
14 Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
15 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
16 Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
17 Signed-off-by: Biwen Li <biwen.li@nxp.com>
19 drivers/staging/fsl-dpaa2/mac/Kconfig | 23 +
20 drivers/staging/fsl-dpaa2/mac/Makefile | 10 +
21 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 ++++++
22 drivers/staging/fsl-dpaa2/mac/dpmac.c | 619 ++++++++++++++++++++
23 drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 +++++++++++
24 drivers/staging/fsl-dpaa2/mac/mac.c | 672 ++++++++++++++++++++++
25 6 files changed, 1838 insertions(+)
26 create mode 100644 drivers/staging/fsl-dpaa2/mac/Kconfig
27 create mode 100644 drivers/staging/fsl-dpaa2/mac/Makefile
28 create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
29 create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.c
30 create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.h
31 create mode 100644 drivers/staging/fsl-dpaa2/mac/mac.c
34 +++ b/drivers/staging/fsl-dpaa2/mac/Kconfig
37 + tristate "DPAA2 MAC / PHY interface"
38 + depends on FSL_MC_BUS && FSL_DPAA2
39 + select MDIO_BUS_MUX_MMIOREG
40 + select FSL_XGMAC_MDIO
43 + Prototype driver for DPAA2 MAC / PHY interface object.
44 + This driver works as a proxy between phylib including phy drivers and
45 + the MC firmware. It receives updates on link state changes from PHY
46 + lib and forwards them to MC and receives interrupt from MC whenever
47 + a request is made to change the link state.
50 +config FSL_DPAA2_MAC_NETDEVS
51 + bool "Expose net interfaces for PHYs"
53 + depends on FSL_DPAA2_MAC
55 + Exposes macX net interfaces which allow direct control over MACs and
58 + Leave disabled if unsure.
60 +++ b/drivers/staging/fsl-dpaa2/mac/Makefile
63 +obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o
65 +dpaa2-mac-objs := mac.o dpmac.o
68 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
71 + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
73 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
75 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
77 + * Redistribution and use in source and binary forms, with or without
78 + * modification, are permitted provided that the following conditions are met:
79 + * * Redistributions of source code must retain the above copyright
80 + * notice, this list of conditions and the following disclaimer.
81 + * * Redistributions in binary form must reproduce the above copyright
82 + * notice, this list of conditions and the following disclaimer in the
83 + * documentation and/or other materials provided with the distribution.
84 + * * Neither the name of the above-listed copyright holders nor the
85 + * names of any contributors may be used to endorse or promote products
86 + * derived from this software without specific prior written permission.
89 + * ALTERNATIVELY, this software may be distributed under the terms of the
90 + * GNU General Public License ("GPL") as published by the Free Software
91 + * Foundation, either version 2 of that License or (at your option) any
94 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
95 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
96 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
97 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
98 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
99 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
100 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
101 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
102 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
103 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
104 + * POSSIBILITY OF SUCH DAMAGE.
106 +#ifndef _FSL_DPMAC_CMD_H
107 +#define _FSL_DPMAC_CMD_H
110 +#define DPMAC_VER_MAJOR 4
111 +#define DPMAC_VER_MINOR 2
112 +#define DPMAC_CMD_BASE_VERSION 1
113 +#define DPMAC_CMD_ID_OFFSET 4
115 +#define DPMAC_CMD(id) (((id) << DPMAC_CMD_ID_OFFSET) | DPMAC_CMD_BASE_VERSION)
118 +#define DPMAC_CMDID_CLOSE DPMAC_CMD(0x800)
119 +#define DPMAC_CMDID_OPEN DPMAC_CMD(0x80c)
120 +#define DPMAC_CMDID_CREATE DPMAC_CMD(0x90c)
121 +#define DPMAC_CMDID_DESTROY DPMAC_CMD(0x98c)
122 +#define DPMAC_CMDID_GET_API_VERSION DPMAC_CMD(0xa0c)
124 +#define DPMAC_CMDID_GET_ATTR DPMAC_CMD(0x004)
125 +#define DPMAC_CMDID_RESET DPMAC_CMD(0x005)
127 +#define DPMAC_CMDID_SET_IRQ_ENABLE DPMAC_CMD(0x012)
128 +#define DPMAC_CMDID_GET_IRQ_ENABLE DPMAC_CMD(0x013)
129 +#define DPMAC_CMDID_SET_IRQ_MASK DPMAC_CMD(0x014)
130 +#define DPMAC_CMDID_GET_IRQ_MASK DPMAC_CMD(0x015)
131 +#define DPMAC_CMDID_GET_IRQ_STATUS DPMAC_CMD(0x016)
132 +#define DPMAC_CMDID_CLEAR_IRQ_STATUS DPMAC_CMD(0x017)
134 +#define DPMAC_CMDID_GET_LINK_CFG DPMAC_CMD(0x0c2)
135 +#define DPMAC_CMDID_SET_LINK_STATE DPMAC_CMD(0x0c3)
136 +#define DPMAC_CMDID_GET_COUNTER DPMAC_CMD(0x0c4)
138 +#define DPMAC_CMDID_SET_PORT_MAC_ADDR DPMAC_CMD(0x0c5)
140 +/* Macros for accessing command fields smaller than 1byte */
141 +#define DPMAC_MASK(field) \
142 + GENMASK(DPMAC_##field##_SHIFT + DPMAC_##field##_SIZE - 1, \
143 + DPMAC_##field##_SHIFT)
144 +#define dpmac_set_field(var, field, val) \
145 + ((var) |= (((val) << DPMAC_##field##_SHIFT) & DPMAC_MASK(field)))
146 +#define dpmac_get_field(var, field) \
147 + (((var) & DPMAC_MASK(field)) >> DPMAC_##field##_SHIFT)
149 +struct dpmac_cmd_open {
153 +struct dpmac_cmd_create {
157 +struct dpmac_cmd_destroy {
161 +struct dpmac_cmd_set_irq_enable {
167 +struct dpmac_cmd_get_irq_enable {
172 +struct dpmac_rsp_get_irq_enable {
176 +struct dpmac_cmd_set_irq_mask {
181 +struct dpmac_cmd_get_irq_mask {
186 +struct dpmac_rsp_get_irq_mask {
190 +struct dpmac_cmd_get_irq_status {
195 +struct dpmac_rsp_get_irq_status {
199 +struct dpmac_cmd_clear_irq_status {
204 +struct dpmac_rsp_get_attributes {
211 +struct dpmac_rsp_get_link_cfg {
216 +#define DPMAC_STATE_SIZE 1
217 +#define DPMAC_STATE_SHIFT 0
219 +struct dpmac_cmd_set_link_state {
223 + /* only least significant bit is valid */
227 +struct dpmac_cmd_get_counter {
231 +struct dpmac_rsp_get_counter {
236 +struct dpmac_rsp_get_api_version {
241 +struct dpmac_cmd_set_port_mac_addr {
246 +#endif /* _FSL_DPMAC_CMD_H */
248 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c
250 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
252 + * Redistribution and use in source and binary forms, with or without
253 + * modification, are permitted provided that the following conditions are met:
254 + * * Redistributions of source code must retain the above copyright
255 + * notice, this list of conditions and the following disclaimer.
256 + * * Redistributions in binary form must reproduce the above copyright
257 + * notice, this list of conditions and the following disclaimer in the
258 + * documentation and/or other materials provided with the distribution.
259 + * * Neither the name of the above-listed copyright holders nor the
260 + * names of any contributors may be used to endorse or promote products
261 + * derived from this software without specific prior written permission.
264 + * ALTERNATIVELY, this software may be distributed under the terms of the
265 + * GNU General Public License ("GPL") as published by the Free Software
266 + * Foundation, either version 2 of that License or (at your option) any
269 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
270 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
272 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
273 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
274 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
275 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
276 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
277 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
278 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
279 + * POSSIBILITY OF SUCH DAMAGE.
281 +#include <linux/fsl/mc.h>
283 +#include "dpmac-cmd.h"
286 + * dpmac_open() - Open a control session for the specified object.
287 + * @mc_io: Pointer to MC portal's I/O object
288 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
289 + * @dpmac_id: DPMAC unique ID
290 + * @token: Returned token; use in subsequent API calls
292 + * This function can be used to open a control session for an
293 + * already created object; an object may have been declared in
294 + * the DPL or by calling the dpmac_create function.
295 + * This function returns a unique authentication token,
296 + * associated with the specific object ID and the specific MC
297 + * portal; this token must be used in all subsequent commands for
298 + * this specific object
300 + * Return: '0' on Success; Error code otherwise.
302 +int dpmac_open(struct fsl_mc_io *mc_io,
307 + struct dpmac_cmd_open *cmd_params;
308 + struct fsl_mc_command cmd = { 0 };
311 + /* prepare command */
312 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
315 + cmd_params = (struct dpmac_cmd_open *)cmd.params;
316 + cmd_params->dpmac_id = cpu_to_le32(dpmac_id);
318 + /* send command to mc*/
319 + err = mc_send_command(mc_io, &cmd);
323 + /* retrieve response parameters */
324 + *token = mc_cmd_hdr_read_token(&cmd);
330 + * dpmac_close() - Close the control session of the object
331 + * @mc_io: Pointer to MC portal's I/O object
332 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
333 + * @token: Token of DPMAC object
335 + * After this function is called, no further operations are
336 + * allowed on the object without opening a new control session.
338 + * Return: '0' on Success; Error code otherwise.
340 +int dpmac_close(struct fsl_mc_io *mc_io,
344 + struct fsl_mc_command cmd = { 0 };
346 + /* prepare command */
347 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
350 + /* send command to mc*/
351 + return mc_send_command(mc_io, &cmd);
355 + * dpmac_create() - Create the DPMAC object.
356 + * @mc_io: Pointer to MC portal's I/O object
357 + * @dprc_token: Parent container token; '0' for default container
358 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
359 + * @cfg: Configuration structure
360 + * @obj_id: Returned object id
362 + * Create the DPMAC object, allocate required resources and
363 + * perform required initialization.
365 + * The function accepts an authentication token of a parent
366 + * container that this object should be assigned to. The token
367 + * can be '0' so the object will be assigned to the default container.
368 + * The newly created object can be opened with the returned
369 + * object id and using the container's associated tokens and MC portals.
371 + * Return: '0' on Success; Error code otherwise.
373 +int dpmac_create(struct fsl_mc_io *mc_io,
376 + const struct dpmac_cfg *cfg,
379 + struct dpmac_cmd_create *cmd_params;
380 + struct fsl_mc_command cmd = { 0 };
383 + /* prepare command */
384 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
387 + cmd_params = (struct dpmac_cmd_create *)cmd.params;
388 + cmd_params->mac_id = cpu_to_le32(cfg->mac_id);
390 + /* send command to mc*/
391 + err = mc_send_command(mc_io, &cmd);
395 + /* retrieve response parameters */
396 + *obj_id = mc_cmd_read_object_id(&cmd);
402 + * dpmac_destroy() - Destroy the DPMAC object and release all its resources.
403 + * @mc_io: Pointer to MC portal's I/O object
404 + * @dprc_token: Parent container token; '0' for default container
405 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
406 + * @object_id: The object id; it must be a valid id within the container that
407 + * created this object;
409 + * The function accepts the authentication token of the parent container that
410 + * created the object (not the one that currently owns the object). The object
411 + * is searched within parent using the provided 'object_id'.
412 + * All tokens to the object must be closed before calling destroy.
414 + * Return: '0' on Success; error code otherwise.
416 +int dpmac_destroy(struct fsl_mc_io *mc_io,
421 + struct dpmac_cmd_destroy *cmd_params;
422 + struct fsl_mc_command cmd = { 0 };
424 + /* prepare command */
425 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
428 + cmd_params = (struct dpmac_cmd_destroy *)cmd.params;
429 + cmd_params->dpmac_id = cpu_to_le32(object_id);
431 + /* send command to mc*/
432 + return mc_send_command(mc_io, &cmd);
436 + * dpmac_set_irq_enable() - Set overall interrupt state.
437 + * @mc_io: Pointer to MC portal's I/O object
438 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
439 + * @token: Token of DPMAC object
440 + * @irq_index: The interrupt index to configure
441 + * @en: Interrupt state - enable = 1, disable = 0
443 + * Allows GPP software to control when interrupts are generated.
444 + * Each interrupt can have up to 32 causes. The enable/disable control's the
445 + * overall interrupt state. if the interrupt is disabled no causes will cause
448 + * Return: '0' on Success; Error code otherwise.
450 +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
456 + struct dpmac_cmd_set_irq_enable *cmd_params;
457 + struct fsl_mc_command cmd = { 0 };
459 + /* prepare command */
460 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
463 + cmd_params = (struct dpmac_cmd_set_irq_enable *)cmd.params;
464 + cmd_params->irq_index = irq_index;
465 + cmd_params->enable = en;
467 + /* send command to mc*/
468 + return mc_send_command(mc_io, &cmd);
472 + * dpmac_get_irq_enable() - Get overall interrupt state
473 + * @mc_io: Pointer to MC portal's I/O object
474 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
475 + * @token: Token of DPMAC object
476 + * @irq_index: The interrupt index to configure
477 + * @en: Returned interrupt state - enable = 1, disable = 0
479 + * Return: '0' on Success; Error code otherwise.
481 +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
487 + struct dpmac_cmd_get_irq_enable *cmd_params;
488 + struct dpmac_rsp_get_irq_enable *rsp_params;
489 + struct fsl_mc_command cmd = { 0 };
492 + /* prepare command */
493 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
496 + cmd_params = (struct dpmac_cmd_get_irq_enable *)cmd.params;
497 + cmd_params->irq_index = irq_index;
499 + /* send command to mc*/
500 + err = mc_send_command(mc_io, &cmd);
504 + /* retrieve response parameters */
505 + rsp_params = (struct dpmac_rsp_get_irq_enable *)cmd.params;
506 + *en = rsp_params->enabled;
512 + * dpmac_set_irq_mask() - Set interrupt mask.
513 + * @mc_io: Pointer to MC portal's I/O object
514 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
515 + * @token: Token of DPMAC object
516 + * @irq_index: The interrupt index to configure
517 + * @mask: Event mask to trigger interrupt;
520 + * 1 = consider event for asserting IRQ
522 + * Every interrupt can have up to 32 causes and the interrupt model supports
523 + * masking/unmasking each cause independently
525 + * Return: '0' on Success; Error code otherwise.
527 +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
533 + struct dpmac_cmd_set_irq_mask *cmd_params;
534 + struct fsl_mc_command cmd = { 0 };
536 + /* prepare command */
537 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
540 + cmd_params = (struct dpmac_cmd_set_irq_mask *)cmd.params;
541 + cmd_params->mask = cpu_to_le32(mask);
542 + cmd_params->irq_index = irq_index;
544 + /* send command to mc*/
545 + return mc_send_command(mc_io, &cmd);
549 + * dpmac_get_irq_mask() - Get interrupt mask.
550 + * @mc_io: Pointer to MC portal's I/O object
551 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
552 + * @token: Token of DPMAC object
553 + * @irq_index: The interrupt index to configure
554 + * @mask: Returned event mask to trigger interrupt
556 + * Every interrupt can have up to 32 causes and the interrupt model supports
557 + * masking/unmasking each cause independently
559 + * Return: '0' on Success; Error code otherwise.
561 +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
567 + struct dpmac_cmd_get_irq_mask *cmd_params;
568 + struct dpmac_rsp_get_irq_mask *rsp_params;
569 + struct fsl_mc_command cmd = { 0 };
572 + /* prepare command */
573 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
576 + cmd_params = (struct dpmac_cmd_get_irq_mask *)cmd.params;
577 + cmd_params->irq_index = irq_index;
579 + /* send command to mc*/
580 + err = mc_send_command(mc_io, &cmd);
584 + /* retrieve response parameters */
585 + rsp_params = (struct dpmac_rsp_get_irq_mask *)cmd.params;
586 + *mask = le32_to_cpu(rsp_params->mask);
592 + * dpmac_get_irq_status() - Get the current status of any pending interrupts.
594 + * @mc_io: Pointer to MC portal's I/O object
595 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
596 + * @token: Token of DPMAC object
597 + * @irq_index: The interrupt index to configure
598 + * @status: Returned interrupts status - one bit per cause:
599 + * 0 = no interrupt pending
600 + * 1 = interrupt pending
602 + * Return: '0' on Success; Error code otherwise.
604 +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
610 + struct dpmac_cmd_get_irq_status *cmd_params;
611 + struct dpmac_rsp_get_irq_status *rsp_params;
612 + struct fsl_mc_command cmd = { 0 };
615 + /* prepare command */
616 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
619 + cmd_params = (struct dpmac_cmd_get_irq_status *)cmd.params;
620 + cmd_params->status = cpu_to_le32(*status);
621 + cmd_params->irq_index = irq_index;
623 + /* send command to mc*/
624 + err = mc_send_command(mc_io, &cmd);
628 + /* retrieve response parameters */
629 + rsp_params = (struct dpmac_rsp_get_irq_status *)cmd.params;
630 + *status = le32_to_cpu(rsp_params->status);
636 + * dpmac_clear_irq_status() - Clear a pending interrupt's status
638 + * @mc_io: Pointer to MC portal's I/O object
639 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
640 + * @token: Token of DPMAC object
641 + * @irq_index: The interrupt index to configure
642 + * @status: Bits to clear (W1C) - one bit per cause:
644 + * 1 = clear status bit
646 + * Return: '0' on Success; Error code otherwise.
648 +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
654 + struct dpmac_cmd_clear_irq_status *cmd_params;
655 + struct fsl_mc_command cmd = { 0 };
657 + /* prepare command */
658 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
661 + cmd_params = (struct dpmac_cmd_clear_irq_status *)cmd.params;
662 + cmd_params->status = cpu_to_le32(status);
663 + cmd_params->irq_index = irq_index;
665 + /* send command to mc*/
666 + return mc_send_command(mc_io, &cmd);
670 + * dpmac_get_attributes - Retrieve DPMAC attributes.
672 + * @mc_io: Pointer to MC portal's I/O object
673 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
674 + * @token: Token of DPMAC object
675 + * @attr: Returned object's attributes
677 + * Return: '0' on Success; Error code otherwise.
679 +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
682 + struct dpmac_attr *attr)
684 + struct dpmac_rsp_get_attributes *rsp_params;
685 + struct fsl_mc_command cmd = { 0 };
688 + /* prepare command */
689 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
693 + /* send command to mc*/
694 + err = mc_send_command(mc_io, &cmd);
698 + /* retrieve response parameters */
699 + rsp_params = (struct dpmac_rsp_get_attributes *)cmd.params;
700 + attr->eth_if = rsp_params->eth_if;
701 + attr->link_type = rsp_params->link_type;
702 + attr->id = le16_to_cpu(rsp_params->id);
703 + attr->max_rate = le32_to_cpu(rsp_params->max_rate);
709 + * dpmac_get_link_cfg() - Get Ethernet link configuration
710 + * @mc_io: Pointer to opaque I/O object
711 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
712 + * @token: Token of DPMAC object
713 + * @cfg: Returned structure with the link configuration
715 + * Return: '0' on Success; Error code otherwise.
717 +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
720 + struct dpmac_link_cfg *cfg)
722 + struct dpmac_rsp_get_link_cfg *rsp_params;
723 + struct fsl_mc_command cmd = { 0 };
726 + /* prepare command */
727 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
731 + /* send command to mc*/
732 + err = mc_send_command(mc_io, &cmd);
736 + rsp_params = (struct dpmac_rsp_get_link_cfg *)cmd.params;
737 + cfg->options = le64_to_cpu(rsp_params->options);
738 + cfg->rate = le32_to_cpu(rsp_params->rate);
744 + * dpmac_set_link_state() - Set the Ethernet link status
745 + * @mc_io: Pointer to opaque I/O object
746 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
747 + * @token: Token of DPMAC object
748 + * @link_state: Link state configuration
750 + * Return: '0' on Success; Error code otherwise.
752 +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
755 + struct dpmac_link_state *link_state)
757 + struct dpmac_cmd_set_link_state *cmd_params;
758 + struct fsl_mc_command cmd = { 0 };
760 + /* prepare command */
761 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
764 + cmd_params = (struct dpmac_cmd_set_link_state *)cmd.params;
765 + cmd_params->options = cpu_to_le64(link_state->options);
766 + cmd_params->rate = cpu_to_le32(link_state->rate);
767 + cmd_params->up = dpmac_get_field(link_state->up, STATE);
769 + /* send command to mc*/
770 + return mc_send_command(mc_io, &cmd);
774 + * dpmac_get_counter() - Read a specific DPMAC counter
775 + * @mc_io: Pointer to opaque I/O object
776 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
777 + * @token: Token of DPMAC object
778 + * @type: The requested counter
779 + * @counter: Returned counter value
781 + * Return: The requested counter; '0' otherwise.
783 +int dpmac_get_counter(struct fsl_mc_io *mc_io,
786 + enum dpmac_counter type,
789 + struct dpmac_cmd_get_counter *dpmac_cmd;
790 + struct dpmac_rsp_get_counter *dpmac_rsp;
791 + struct fsl_mc_command cmd = { 0 };
794 + /* prepare command */
795 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
798 + dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params;
799 + dpmac_cmd->type = type;
801 + /* send command to mc*/
802 + err = mc_send_command(mc_io, &cmd);
806 + dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params;
807 + *counter = le64_to_cpu(dpmac_rsp->counter);
813 +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
818 + struct dpmac_cmd_set_port_mac_addr *dpmac_cmd;
819 + struct fsl_mc_command cmd = { 0 };
821 + /* prepare command */
822 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PORT_MAC_ADDR,
825 + dpmac_cmd = (struct dpmac_cmd_set_port_mac_addr *)cmd.params;
826 + dpmac_cmd->addr[0] = addr[5];
827 + dpmac_cmd->addr[1] = addr[4];
828 + dpmac_cmd->addr[2] = addr[3];
829 + dpmac_cmd->addr[3] = addr[2];
830 + dpmac_cmd->addr[4] = addr[1];
831 + dpmac_cmd->addr[5] = addr[0];
833 + /* send command to mc*/
834 + return mc_send_command(mc_io, &cmd);
838 + * dpmac_get_api_version() - Get Data Path MAC version
839 + * @mc_io: Pointer to MC portal's I/O object
840 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
841 + * @major_ver: Major version of data path mac API
842 + * @minor_ver: Minor version of data path mac API
844 + * Return: '0' on Success; Error code otherwise.
846 +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
851 + struct dpmac_rsp_get_api_version *rsp_params;
852 + struct fsl_mc_command cmd = { 0 };
855 + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION,
859 + err = mc_send_command(mc_io, &cmd);
863 + rsp_params = (struct dpmac_rsp_get_api_version *)cmd.params;
864 + *major_ver = le16_to_cpu(rsp_params->major);
865 + *minor_ver = le16_to_cpu(rsp_params->minor);
870 +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h
872 +/* Copyright 2013-2016 Freescale Semiconductor Inc.
874 + * Redistribution and use in source and binary forms, with or without
875 + * modification, are permitted provided that the following conditions are met:
876 + * * Redistributions of source code must retain the above copyright
877 + * notice, this list of conditions and the following disclaimer.
878 + * * Redistributions in binary form must reproduce the above copyright
879 + * notice, this list of conditions and the following disclaimer in the
880 + * documentation and/or other materials provided with the distribution.
881 + * * Neither the name of the above-listed copyright holders nor the
882 + * names of any contributors may be used to endorse or promote products
883 + * derived from this software without specific prior written permission.
886 + * ALTERNATIVELY, this software may be distributed under the terms of the
887 + * GNU General Public License ("GPL") as published by the Free Software
888 + * Foundation, either version 2 of that License or (at your option) any
891 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
892 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
893 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
894 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
895 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
896 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
897 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
898 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
899 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
900 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
901 + * POSSIBILITY OF SUCH DAMAGE.
903 +#ifndef __FSL_DPMAC_H
904 +#define __FSL_DPMAC_H
906 +/* Data Path MAC API
907 + * Contains initialization APIs and runtime control APIs for DPMAC
912 +int dpmac_open(struct fsl_mc_io *mc_io,
917 +int dpmac_close(struct fsl_mc_io *mc_io,
922 + * enum dpmac_link_type - DPMAC link type
923 + * @DPMAC_LINK_TYPE_NONE: No link
924 + * @DPMAC_LINK_TYPE_FIXED: Link is fixed type
925 + * @DPMAC_LINK_TYPE_PHY: Link by PHY ID
926 + * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type
928 +enum dpmac_link_type {
929 + DPMAC_LINK_TYPE_NONE,
930 + DPMAC_LINK_TYPE_FIXED,
931 + DPMAC_LINK_TYPE_PHY,
932 + DPMAC_LINK_TYPE_BACKPLANE
936 + * enum dpmac_eth_if - DPMAC Ethrnet interface
937 + * @DPMAC_ETH_IF_MII: MII interface
938 + * @DPMAC_ETH_IF_RMII: RMII interface
939 + * @DPMAC_ETH_IF_SMII: SMII interface
940 + * @DPMAC_ETH_IF_GMII: GMII interface
941 + * @DPMAC_ETH_IF_RGMII: RGMII interface
942 + * @DPMAC_ETH_IF_SGMII: SGMII interface
943 + * @DPMAC_ETH_IF_QSGMII: QSGMII interface
944 + * @DPMAC_ETH_IF_XAUI: XAUI interface
945 + * @DPMAC_ETH_IF_XFI: XFI interface
952 + DPMAC_ETH_IF_RGMII,
953 + DPMAC_ETH_IF_SGMII,
954 + DPMAC_ETH_IF_QSGMII,
960 + * struct dpmac_cfg - Structure representing DPMAC configuration
961 + * @mac_id: Represents the Hardware MAC ID; in case of multiple WRIOP,
962 + * the MAC IDs are continuous.
963 + * For example: 2 WRIOPs, 16 MACs in each:
964 + * MAC IDs for the 1st WRIOP: 1-16,
965 + * MAC IDs for the 2nd WRIOP: 17-32.
971 +int dpmac_create(struct fsl_mc_io *mc_io,
974 + const struct dpmac_cfg *cfg,
977 +int dpmac_destroy(struct fsl_mc_io *mc_io,
983 + * DPMAC IRQ Index and Events
989 +#define DPMAC_IRQ_INDEX 0
991 + * IRQ event - indicates a change in link state
993 +#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001
995 + * IRQ event - Indicates that the link state changed
997 +#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002
999 +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
1005 +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
1011 +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
1017 +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
1023 +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
1029 +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
1036 + * struct dpmac_attr - Structure representing DPMAC attributes
1037 + * @id: DPMAC object ID
1038 + * @max_rate: Maximum supported rate - in Mbps
1039 + * @eth_if: Ethernet interface
1040 + * @link_type: link type
1042 +struct dpmac_attr {
1045 + enum dpmac_eth_if eth_if;
1046 + enum dpmac_link_type link_type;
1049 +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
1052 + struct dpmac_attr *attr);
1055 + * DPMAC link configuration/state options
1059 + * Enable auto-negotiation
1061 +#define DPMAC_LINK_OPT_AUTONEG 0x0000000000000001ULL
1063 + * Enable half-duplex mode
1065 +#define DPMAC_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
1067 + * Enable pause frames
1069 +#define DPMAC_LINK_OPT_PAUSE 0x0000000000000004ULL
1071 + * Enable a-symmetric pause frames
1073 +#define DPMAC_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
1076 + * struct dpmac_link_cfg - Structure representing DPMAC link configuration
1077 + * @rate: Link's rate - in Mbps
1078 + * @options: Enable/Disable DPMAC link cfg features (bitmap)
1080 +struct dpmac_link_cfg {
1085 +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
1088 + struct dpmac_link_cfg *cfg);
1091 + * struct dpmac_link_state - DPMAC link configuration request
1092 + * @rate: Rate in Mbps
1093 + * @options: Enable/Disable DPMAC link cfg features (bitmap)
1096 +struct dpmac_link_state {
1102 +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
1105 + struct dpmac_link_state *link_state);
1108 + * enum dpmac_counter - DPMAC counter types
1109 + * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad.
1110 + * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad.
1111 + * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad.
1112 + * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad.
1113 + * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad.
1114 + * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad.
1115 + * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger
1116 + * (up to max frame length specified),
1118 + * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received
1119 + * with a wrong CRC
1120 + * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length
1121 + * specified, with a bad frame check sequence.
1122 + * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors.
1123 + * Occurs when a receive FIFO overflows.
1124 + * Includes also frames truncated as a result of
1125 + * the receive FIFO overflow.
1126 + * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error
1127 + * (optional used for wrong SFD).
1128 + * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64
1129 + * bytes long with a good CRC.
1130 + * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length
1131 + * specified, with a good frame check sequence.
1132 + * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC)
1133 + * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted
1134 + * (regular and PFC).
1135 + * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid
1136 + * frames and valid pause frames.
1137 + * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames.
1138 + * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames.
1139 + * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received.
1140 + * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames.
1141 + * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error
1142 + * (except for undersized/fragment frame).
1143 + * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid
1144 + * frames and valid pause frames transmitted.
1145 + * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames.
1146 + * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames.
1147 + * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames.
1148 + * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error.
1149 + * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including
1151 + * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including
1154 +enum dpmac_counter {
1155 + DPMAC_CNT_ING_FRAME_64,
1156 + DPMAC_CNT_ING_FRAME_127,
1157 + DPMAC_CNT_ING_FRAME_255,
1158 + DPMAC_CNT_ING_FRAME_511,
1159 + DPMAC_CNT_ING_FRAME_1023,
1160 + DPMAC_CNT_ING_FRAME_1518,
1161 + DPMAC_CNT_ING_FRAME_1519_MAX,
1162 + DPMAC_CNT_ING_FRAG,
1163 + DPMAC_CNT_ING_JABBER,
1164 + DPMAC_CNT_ING_FRAME_DISCARD,
1165 + DPMAC_CNT_ING_ALIGN_ERR,
1166 + DPMAC_CNT_EGR_UNDERSIZED,
1167 + DPMAC_CNT_ING_OVERSIZED,
1168 + DPMAC_CNT_ING_VALID_PAUSE_FRAME,
1169 + DPMAC_CNT_EGR_VALID_PAUSE_FRAME,
1170 + DPMAC_CNT_ING_BYTE,
1171 + DPMAC_CNT_ING_MCAST_FRAME,
1172 + DPMAC_CNT_ING_BCAST_FRAME,
1173 + DPMAC_CNT_ING_ALL_FRAME,
1174 + DPMAC_CNT_ING_UCAST_FRAME,
1175 + DPMAC_CNT_ING_ERR_FRAME,
1176 + DPMAC_CNT_EGR_BYTE,
1177 + DPMAC_CNT_EGR_MCAST_FRAME,
1178 + DPMAC_CNT_EGR_BCAST_FRAME,
1179 + DPMAC_CNT_EGR_UCAST_FRAME,
1180 + DPMAC_CNT_EGR_ERR_FRAME,
1181 + DPMAC_CNT_ING_GOOD_FRAME,
1182 + DPMAC_CNT_ENG_GOOD_FRAME
1185 +int dpmac_get_counter(struct fsl_mc_io *mc_io,
1188 + enum dpmac_counter type,
1192 + * dpmac_set_port_mac_addr() - Set a MAC address associated with the physical
1193 + * port. This is not used for filtering, MAC is always in
1194 + * promiscuous mode, it is passed to DPNIs through DPNI API for
1195 + * application used.
1196 + * @mc_io: Pointer to opaque I/O object
1197 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1198 + * @token: Token of DPMAC object
1199 + * @addr: MAC address to set
1201 + * Return: The requested counter; '0' otherwise.
1203 +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
1206 + const u8 addr[6]);
1208 +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
1213 +#endif /* __FSL_DPMAC_H */
1215 +++ b/drivers/staging/fsl-dpaa2/mac/mac.c
1217 +/* Copyright 2015 Freescale Semiconductor Inc.
1219 + * Redistribution and use in source and binary forms, with or without
1220 + * modification, are permitted provided that the following conditions are met:
1221 + * * Redistributions of source code must retain the above copyright
1222 + * notice, this list of conditions and the following disclaimer.
1223 + * * Redistributions in binary form must reproduce the above copyright
1224 + * notice, this list of conditions and the following disclaimer in the
1225 + * documentation and/or other materials provided with the distribution.
1226 + * * Neither the name of Freescale Semiconductor nor the
1227 + * names of its contributors may be used to endorse or promote products
1228 + * derived from this software without specific prior written permission.
1231 + * ALTERNATIVELY, this software may be distributed under the terms of the
1232 + * GNU General Public License ("GPL") as published by the Free Software
1233 + * Foundation, either version 2 of that License or (at your option) any
1236 + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
1237 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1238 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1239 + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
1240 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1241 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1242 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1243 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1244 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1245 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1248 +#include <linux/module.h>
1250 +#include <linux/netdevice.h>
1251 +#include <linux/etherdevice.h>
1252 +#include <linux/msi.h>
1253 +#include <linux/rtnetlink.h>
1254 +#include <linux/if_vlan.h>
1256 +#include <uapi/linux/if_bridge.h>
1257 +#include <net/netlink.h>
1259 +#include <linux/of.h>
1260 +#include <linux/of_mdio.h>
1261 +#include <linux/of_net.h>
1262 +#include <linux/phy.h>
1263 +#include <linux/phy_fixed.h>
1265 +#include <linux/fsl/mc.h>
1268 +#include "dpmac-cmd.h"
1270 +struct dpaa2_mac_priv {
1271 + struct net_device *netdev;
1272 + struct fsl_mc_device *mc_dev;
1273 + struct dpmac_attr attr;
1274 + struct dpmac_link_state old_state;
1277 +/* TODO: fix the 10G modes, mapping can't be right:
1278 + * XGMII is paralel
1279 + * XAUI is serial, using 8b/10b encoding
1280 + * XFI is also serial but using 64b/66b encoding
1281 + * they can't all map to XGMII...
1283 + * This must be kept in sync with enum dpmac_eth_if.
1285 +static phy_interface_t dpaa2_mac_iface_mode[] = {
1286 + PHY_INTERFACE_MODE_MII, /* DPMAC_ETH_IF_MII */
1287 + PHY_INTERFACE_MODE_RMII, /* DPMAC_ETH_IF_RMII */
1288 + PHY_INTERFACE_MODE_SMII, /* DPMAC_ETH_IF_SMII */
1289 + PHY_INTERFACE_MODE_GMII, /* DPMAC_ETH_IF_GMII */
1290 + PHY_INTERFACE_MODE_RGMII, /* DPMAC_ETH_IF_RGMII */
1291 + PHY_INTERFACE_MODE_SGMII, /* DPMAC_ETH_IF_SGMII */
1292 + PHY_INTERFACE_MODE_QSGMII, /* DPMAC_ETH_IF_QSGMII */
1293 + PHY_INTERFACE_MODE_XGMII, /* DPMAC_ETH_IF_XAUI */
1294 + PHY_INTERFACE_MODE_XGMII, /* DPMAC_ETH_IF_XFI */
1297 +static void dpaa2_mac_link_changed(struct net_device *netdev)
1299 + struct phy_device *phydev;
1300 + struct dpmac_link_state state = { 0 };
1301 + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
1304 + /* the PHY just notified us of link state change */
1305 + phydev = netdev->phydev;
1307 + state.up = !!phydev->link;
1308 + if (phydev->link) {
1309 + state.rate = phydev->speed;
1311 + if (!phydev->duplex)
1312 + state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
1313 + if (phydev->autoneg)
1314 + state.options |= DPMAC_LINK_OPT_AUTONEG;
1316 + netif_carrier_on(netdev);
1318 + netif_carrier_off(netdev);
1321 + if (priv->old_state.up != state.up ||
1322 + priv->old_state.rate != state.rate ||
1323 + priv->old_state.options != state.options) {
1324 + priv->old_state = state;
1325 + phy_print_status(phydev);
1328 + /* We must interrogate MC at all times, because we don't know
1329 + * when and whether a potential DPNI may have read the link state.
1331 + err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
1332 + priv->mc_dev->mc_handle, &state);
1333 + if (unlikely(err))
1334 + dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
1337 +static int dpaa2_mac_open(struct net_device *netdev)
1339 + /* start PHY state machine */
1340 + phy_start(netdev->phydev);
1345 +static int dpaa2_mac_stop(struct net_device *netdev)
1347 + if (!netdev->phydev)
1350 + /* stop PHY state machine */
1351 + phy_stop(netdev->phydev);
1353 + /* signal link down to firmware */
1354 + netdev->phydev->link = 0;
1355 + dpaa2_mac_link_changed(netdev);
1361 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1362 +static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
1363 + struct net_device *dev)
1365 + /* we don't support I/O for now, drop the frame */
1366 + dev_kfree_skb_any(skb);
1367 + return NETDEV_TX_OK;
1370 +static int dpaa2_mac_get_link_ksettings(struct net_device *netdev,
1371 + struct ethtool_link_ksettings *ks)
1373 + phy_ethtool_ksettings_get(netdev->phydev, ks);
1378 +static int dpaa2_mac_set_link_ksettings(struct net_device *netdev,
1379 + const struct ethtool_link_ksettings *ks)
1381 + return phy_ethtool_ksettings_set(netdev->phydev, ks);
1384 +static void dpaa2_mac_get_stats(struct net_device *netdev,
1385 + struct rtnl_link_stats64 *storage)
1387 + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
1391 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1392 + DPMAC_CNT_EGR_MCAST_FRAME,
1393 + &storage->tx_packets);
1396 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1397 + DPMAC_CNT_EGR_BCAST_FRAME, &tmp);
1400 + storage->tx_packets += tmp;
1401 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1402 + DPMAC_CNT_EGR_UCAST_FRAME, &tmp);
1405 + storage->tx_packets += tmp;
1407 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1408 + DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped);
1411 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1412 + DPMAC_CNT_EGR_BYTE, &storage->tx_bytes);
1415 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1416 + DPMAC_CNT_EGR_ERR_FRAME, &storage->tx_errors);
1420 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1421 + DPMAC_CNT_ING_ALL_FRAME, &storage->rx_packets);
1424 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1425 + DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast);
1428 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1429 + DPMAC_CNT_ING_FRAME_DISCARD,
1430 + &storage->rx_dropped);
1433 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1434 + DPMAC_CNT_ING_ALIGN_ERR, &storage->rx_errors);
1437 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1438 + DPMAC_CNT_ING_OVERSIZED, &tmp);
1441 + storage->rx_errors += tmp;
1442 + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
1443 + DPMAC_CNT_ING_BYTE, &storage->rx_bytes);
1449 + netdev_err(netdev, "dpmac_get_counter err %d\n", err);
1453 + enum dpmac_counter id;
1454 + char name[ETH_GSTRING_LEN];
1455 +} dpaa2_mac_counters[] = {
1456 + {DPMAC_CNT_ING_ALL_FRAME, "rx all frames"},
1457 + {DPMAC_CNT_ING_GOOD_FRAME, "rx frames ok"},
1458 + {DPMAC_CNT_ING_ERR_FRAME, "rx frame errors"},
1459 + {DPMAC_CNT_ING_FRAME_DISCARD, "rx frame discards"},
1460 + {DPMAC_CNT_ING_UCAST_FRAME, "rx u-cast"},
1461 + {DPMAC_CNT_ING_BCAST_FRAME, "rx b-cast"},
1462 + {DPMAC_CNT_ING_MCAST_FRAME, "rx m-cast"},
1463 + {DPMAC_CNT_ING_FRAME_64, "rx 64 bytes"},
1464 + {DPMAC_CNT_ING_FRAME_127, "rx 65-127 bytes"},
1465 + {DPMAC_CNT_ING_FRAME_255, "rx 128-255 bytes"},
1466 + {DPMAC_CNT_ING_FRAME_511, "rx 256-511 bytes"},
1467 + {DPMAC_CNT_ING_FRAME_1023, "rx 512-1023 bytes"},
1468 + {DPMAC_CNT_ING_FRAME_1518, "rx 1024-1518 bytes"},
1469 + {DPMAC_CNT_ING_FRAME_1519_MAX, "rx 1519-max bytes"},
1470 + {DPMAC_CNT_ING_FRAG, "rx frags"},
1471 + {DPMAC_CNT_ING_JABBER, "rx jabber"},
1472 + {DPMAC_CNT_ING_ALIGN_ERR, "rx align errors"},
1473 + {DPMAC_CNT_ING_OVERSIZED, "rx oversized"},
1474 + {DPMAC_CNT_ING_VALID_PAUSE_FRAME, "rx pause"},
1475 + {DPMAC_CNT_ING_BYTE, "rx bytes"},
1476 + {DPMAC_CNT_ENG_GOOD_FRAME, "tx frames ok"},
1477 + {DPMAC_CNT_EGR_UCAST_FRAME, "tx u-cast"},
1478 + {DPMAC_CNT_EGR_MCAST_FRAME, "tx m-cast"},
1479 + {DPMAC_CNT_EGR_BCAST_FRAME, "tx b-cast"},
1480 + {DPMAC_CNT_EGR_ERR_FRAME, "tx frame errors"},
1481 + {DPMAC_CNT_EGR_UNDERSIZED, "tx undersized"},
1482 + {DPMAC_CNT_EGR_VALID_PAUSE_FRAME, "tx b-pause"},
1483 + {DPMAC_CNT_EGR_BYTE, "tx bytes"},
1487 +static void dpaa2_mac_get_strings(struct net_device *netdev,
1488 + u32 stringset, u8 *data)
1492 + switch (stringset) {
1493 + case ETH_SS_STATS:
1494 + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++)
1495 + memcpy(data + i * ETH_GSTRING_LEN,
1496 + dpaa2_mac_counters[i].name,
1502 +static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev,
1503 + struct ethtool_stats *stats,
1506 + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
1510 + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) {
1511 + err = dpmac_get_counter(priv->mc_dev->mc_io,
1513 + priv->mc_dev->mc_handle,
1514 + dpaa2_mac_counters[i].id, &data[i]);
1516 + netdev_err(netdev, "dpmac_get_counter[%s] err %d\n",
1517 + dpaa2_mac_counters[i].name, err);
1521 +static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset)
1524 + case ETH_SS_STATS:
1525 + return ARRAY_SIZE(dpaa2_mac_counters);
1527 + return -EOPNOTSUPP;
1531 +static const struct net_device_ops dpaa2_mac_ndo_ops = {
1532 + .ndo_open = &dpaa2_mac_open,
1533 + .ndo_stop = &dpaa2_mac_stop,
1534 + .ndo_start_xmit = &dpaa2_mac_drop_frame,
1535 + .ndo_get_stats64 = &dpaa2_mac_get_stats,
1538 +static const struct ethtool_ops dpaa2_mac_ethtool_ops = {
1539 + .get_link_ksettings = &dpaa2_mac_get_link_ksettings,
1540 + .set_link_ksettings = &dpaa2_mac_set_link_ksettings,
1541 + .get_strings = &dpaa2_mac_get_strings,
1542 + .get_ethtool_stats = &dpaa2_mac_get_ethtool_stats,
1543 + .get_sset_count = &dpaa2_mac_get_sset_count,
1545 +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
1547 +static void configure_link(struct dpaa2_mac_priv *priv,
1548 + struct dpmac_link_cfg *cfg)
1550 + struct phy_device *phydev = priv->netdev->phydev;
1552 + if (unlikely(!phydev))
1555 + phydev->speed = cfg->rate;
1556 + phydev->duplex = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
1558 + if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
1559 + phydev->autoneg = 1;
1560 + phydev->advertising |= ADVERTISED_Autoneg;
1562 + phydev->autoneg = 0;
1563 + phydev->advertising &= ~ADVERTISED_Autoneg;
1566 + phy_start_aneg(phydev);
1569 +static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
1571 + struct device *dev = (struct device *)arg;
1572 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1573 + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
1574 + struct dpmac_link_cfg link_cfg;
1578 + err = dpmac_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
1579 + DPMAC_IRQ_INDEX, &status);
1580 + if (unlikely(err || !status))
1583 + /* DPNI-initiated link configuration; 'ifconfig up' also calls this */
1584 + if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) {
1585 + err = dpmac_get_link_cfg(mc_dev->mc_io, 0, mc_dev->mc_handle,
1587 + if (unlikely(err))
1590 + configure_link(priv, &link_cfg);
1594 + dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
1595 + DPMAC_IRQ_INDEX, status);
1597 + return IRQ_HANDLED;
1600 +static int setup_irqs(struct fsl_mc_device *mc_dev)
1603 + struct fsl_mc_device_irq *irq;
1605 + err = fsl_mc_allocate_irqs(mc_dev);
1607 + dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
1611 + irq = mc_dev->irqs[0];
1612 + err = devm_request_threaded_irq(&mc_dev->dev, irq->msi_desc->irq,
1613 + NULL, &dpaa2_mac_irq_handler,
1614 + IRQF_NO_SUSPEND | IRQF_ONESHOT,
1615 + dev_name(&mc_dev->dev), &mc_dev->dev);
1617 + dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
1622 + err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
1623 + DPMAC_IRQ_INDEX, DPMAC_IRQ_EVENT_LINK_CFG_REQ);
1625 + dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
1628 + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
1629 + DPMAC_IRQ_INDEX, 1);
1631 + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
1638 + fsl_mc_free_irqs(mc_dev);
1643 +static void teardown_irqs(struct fsl_mc_device *mc_dev)
1647 + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
1648 + DPMAC_IRQ_INDEX, 0);
1650 + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
1652 + fsl_mc_free_irqs(mc_dev);
1655 +static struct device_node *find_dpmac_node(struct device *dev, u16 dpmac_id)
1657 + struct device_node *dpmacs, *dpmac = NULL;
1658 + struct device_node *mc_node = dev->of_node;
1662 + dpmacs = of_find_node_by_name(mc_node, "dpmacs");
1664 + dev_err(dev, "No dpmacs subnode in device-tree\n");
1668 + while ((dpmac = of_get_next_child(dpmacs, dpmac))) {
1669 + err = of_property_read_u32(dpmac, "reg", &id);
1672 + if (id == dpmac_id)
1679 +static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
1681 + struct device *dev;
1682 + struct dpaa2_mac_priv *priv = NULL;
1683 + struct device_node *phy_node, *dpmac_node;
1684 + struct net_device *netdev;
1685 + phy_interface_t if_mode;
1688 + dev = &mc_dev->dev;
1690 + /* prepare a net_dev structure to make the phy lib API happy */
1691 + netdev = alloc_etherdev(sizeof(*priv));
1693 + dev_err(dev, "alloc_etherdev error\n");
1697 + priv = netdev_priv(netdev);
1698 + priv->mc_dev = mc_dev;
1699 + priv->netdev = netdev;
1701 + SET_NETDEV_DEV(netdev, dev);
1703 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1704 + snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
1707 + dev_set_drvdata(dev, priv);
1709 + /* We may need to issue MC commands while in atomic context */
1710 + err = fsl_mc_portal_allocate(mc_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
1712 + if (err || !mc_dev->mc_io) {
1713 + dev_dbg(dev, "fsl_mc_portal_allocate error: %d\n", err);
1714 + err = -EPROBE_DEFER;
1715 + goto err_free_netdev;
1718 + err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
1719 + &mc_dev->mc_handle);
1720 + if (err || !mc_dev->mc_handle) {
1721 + dev_err(dev, "dpmac_open error: %d\n", err);
1723 + goto err_free_mcp;
1726 + err = dpmac_get_attributes(mc_dev->mc_io, 0,
1727 + mc_dev->mc_handle, &priv->attr);
1729 + dev_err(dev, "dpmac_get_attributes err %d\n", err);
1734 + /* Look up the DPMAC node in the device-tree. */
1735 + dpmac_node = find_dpmac_node(dev, priv->attr.id);
1736 + if (!dpmac_node) {
1737 + dev_err(dev, "No dpmac@%d subnode found.\n", priv->attr.id);
1742 + err = setup_irqs(mc_dev);
1748 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1749 + /* OPTIONAL, register netdev just to make it visible to the user */
1750 + netdev->netdev_ops = &dpaa2_mac_ndo_ops;
1751 + netdev->ethtool_ops = &dpaa2_mac_ethtool_ops;
1753 + /* phy starts up enabled so netdev should be up too */
1754 + netdev->flags |= IFF_UP;
1756 + err = register_netdev(priv->netdev);
1758 + dev_err(dev, "register_netdev error %d\n", err);
1760 + goto err_free_irq;
1762 +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
1764 + /* probe the PHY as a fixed-link if there's a phy-handle defined
1765 + * in the device tree
1767 + phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
1769 + goto probe_fixed_link;
1772 + if (priv->attr.eth_if < ARRAY_SIZE(dpaa2_mac_iface_mode)) {
1773 + if_mode = dpaa2_mac_iface_mode[priv->attr.eth_if];
1774 + dev_dbg(dev, "\tusing if mode %s for eth_if %d\n",
1775 + phy_modes(if_mode), priv->attr.eth_if);
1777 + dev_warn(dev, "Unexpected interface mode %d, will probe as fixed link\n",
1778 + priv->attr.eth_if);
1779 + goto probe_fixed_link;
1782 + /* try to connect to the PHY */
1783 + netdev->phydev = of_phy_connect(netdev, phy_node,
1784 + &dpaa2_mac_link_changed, 0, if_mode);
1785 + if (!netdev->phydev) {
1786 + /* No need for dev_err(); the kernel's loud enough as it is. */
1787 + dev_dbg(dev, "Can't of_phy_connect() now.\n");
1788 + /* We might be waiting for the MDIO MUX to probe, so defer
1789 + * our own probing.
1791 + err = -EPROBE_DEFER;
1794 + dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode));
1797 + if (!netdev->phydev) {
1798 + struct fixed_phy_status status = {
1800 + /* fixed-phys don't support 10Gbps speed for now */
1805 + /* try to register a fixed link phy */
1806 + netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1,
1808 + if (!netdev->phydev || IS_ERR(netdev->phydev)) {
1809 + dev_err(dev, "error trying to register fixed PHY\n");
1810 + /* So we don't crash unregister_netdev() later on */
1811 + netdev->phydev = NULL;
1815 + dev_info(dev, "Registered fixed PHY.\n");
1818 + dpaa2_mac_open(netdev);
1824 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1825 + unregister_netdev(netdev);
1828 + teardown_irqs(mc_dev);
1830 + dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
1832 + fsl_mc_portal_free(mc_dev->mc_io);
1834 + free_netdev(netdev);
1839 +static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
1841 + struct device *dev = &mc_dev->dev;
1842 + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
1843 + struct net_device *netdev = priv->netdev;
1845 + dpaa2_mac_stop(netdev);
1847 + if (phy_is_pseudo_fixed_link(netdev->phydev))
1848 + fixed_phy_unregister(netdev->phydev);
1850 + phy_disconnect(netdev->phydev);
1851 + netdev->phydev = NULL;
1853 +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
1854 + unregister_netdev(priv->netdev);
1856 + teardown_irqs(priv->mc_dev);
1857 + dpmac_close(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle);
1858 + fsl_mc_portal_free(priv->mc_dev->mc_io);
1859 + free_netdev(priv->netdev);
1861 + dev_set_drvdata(dev, NULL);
1866 +static const struct fsl_mc_device_id dpaa2_mac_match_id_table[] = {
1868 + .vendor = FSL_MC_VENDOR_FREESCALE,
1869 + .obj_type = "dpmac",
1873 +MODULE_DEVICE_TABLE(fslmc, dpaa2_mac_match_id_table);
1875 +static struct fsl_mc_driver dpaa2_mac_drv = {
1877 + .name = KBUILD_MODNAME,
1878 + .owner = THIS_MODULE,
1880 + .probe = dpaa2_mac_probe,
1881 + .remove = dpaa2_mac_remove,
1882 + .match_id_table = dpaa2_mac_match_id_table,
1885 +module_fsl_mc_driver(dpaa2_mac_drv);
1887 +MODULE_LICENSE("GPL");
1888 +MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver");