xref: /freebsd/sys/dev/dpaa2/dpaa2_mac.c (revision ba7319e9091b4f6ef15a9c4be3d3d076f3047f72)
1*ba7319e9SDmitry Salychev /*-
2*ba7319e9SDmitry Salychev  * SPDX-License-Identifier: BSD-2-Clause
3*ba7319e9SDmitry Salychev  *
4*ba7319e9SDmitry Salychev  * Copyright © 2021-2022 Dmitry Salychev
5*ba7319e9SDmitry Salychev  *
6*ba7319e9SDmitry Salychev  * Redistribution and use in source and binary forms, with or without
7*ba7319e9SDmitry Salychev  * modification, are permitted provided that the following conditions
8*ba7319e9SDmitry Salychev  * are met:
9*ba7319e9SDmitry Salychev  * 1. Redistributions of source code must retain the above copyright
10*ba7319e9SDmitry Salychev  *    notice, this list of conditions and the following disclaimer.
11*ba7319e9SDmitry Salychev  * 2. Redistributions in binary form must reproduce the above copyright
12*ba7319e9SDmitry Salychev  *    notice, this list of conditions and the following disclaimer in the
13*ba7319e9SDmitry Salychev  *    documentation and/or other materials provided with the distribution.
14*ba7319e9SDmitry Salychev  *
15*ba7319e9SDmitry Salychev  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*ba7319e9SDmitry Salychev  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*ba7319e9SDmitry Salychev  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*ba7319e9SDmitry Salychev  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*ba7319e9SDmitry Salychev  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*ba7319e9SDmitry Salychev  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*ba7319e9SDmitry Salychev  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*ba7319e9SDmitry Salychev  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*ba7319e9SDmitry Salychev  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*ba7319e9SDmitry Salychev  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*ba7319e9SDmitry Salychev  * SUCH DAMAGE.
26*ba7319e9SDmitry Salychev  */
27*ba7319e9SDmitry Salychev 
28*ba7319e9SDmitry Salychev #include <sys/cdefs.h>
29*ba7319e9SDmitry Salychev __FBSDID("$FreeBSD$");
30*ba7319e9SDmitry Salychev 
31*ba7319e9SDmitry Salychev /*
32*ba7319e9SDmitry Salychev  * The DPAA2 MAC driver.
33*ba7319e9SDmitry Salychev  *
34*ba7319e9SDmitry Salychev  * For every DPAA2 MAC, there is an MC object named DPMAC, for MDIO and link
35*ba7319e9SDmitry Salychev  * state updates. The DPMAC virtualizes the MDIO interface, so each PHY driver
36*ba7319e9SDmitry Salychev  * may see a private interface (removing the need for synchronization in GPP on
37*ba7319e9SDmitry Salychev  * the multiplexed MDIO hardware).
38*ba7319e9SDmitry Salychev  */
39*ba7319e9SDmitry Salychev 
40*ba7319e9SDmitry Salychev #include <sys/param.h>
41*ba7319e9SDmitry Salychev #include <sys/kernel.h>
42*ba7319e9SDmitry Salychev #include <sys/bus.h>
43*ba7319e9SDmitry Salychev #include <sys/rman.h>
44*ba7319e9SDmitry Salychev #include <sys/module.h>
45*ba7319e9SDmitry Salychev #include <sys/malloc.h>
46*ba7319e9SDmitry Salychev #include <sys/mutex.h>
47*ba7319e9SDmitry Salychev 
48*ba7319e9SDmitry Salychev #include <vm/vm.h>
49*ba7319e9SDmitry Salychev 
50*ba7319e9SDmitry Salychev #include <machine/bus.h>
51*ba7319e9SDmitry Salychev #include <machine/resource.h>
52*ba7319e9SDmitry Salychev 
53*ba7319e9SDmitry Salychev #include <dev/pci/pcivar.h>
54*ba7319e9SDmitry Salychev 
55*ba7319e9SDmitry Salychev #include "pcib_if.h"
56*ba7319e9SDmitry Salychev #include "pci_if.h"
57*ba7319e9SDmitry Salychev 
58*ba7319e9SDmitry Salychev #include "dpaa2_mc.h"
59*ba7319e9SDmitry Salychev #include "dpaa2_ni.h"
60*ba7319e9SDmitry Salychev #include "dpaa2_mcp.h"
61*ba7319e9SDmitry Salychev #include "dpaa2_swp.h"
62*ba7319e9SDmitry Salychev #include "dpaa2_swp_if.h"
63*ba7319e9SDmitry Salychev #include "dpaa2_cmd_if.h"
64*ba7319e9SDmitry Salychev 
65*ba7319e9SDmitry Salychev /* Index of the only DPMAC IRQ. */
66*ba7319e9SDmitry Salychev #define DPMAC_IRQ_INDEX		0
67*ba7319e9SDmitry Salychev 
68*ba7319e9SDmitry Salychev /* DPMAC IRQ statuses. */
69*ba7319e9SDmitry Salychev #define DPMAC_IRQ_LINK_CFG_REQ	0x00000001 /* change in requested link config. */
70*ba7319e9SDmitry Salychev #define DPMAC_IRQ_LINK_CHANGED	0x00000002 /* link state changed */
71*ba7319e9SDmitry Salychev #define DPMAC_IRQ_LINK_UP_REQ	0x00000004 /* link up request */
72*ba7319e9SDmitry Salychev #define DPMAC_IRQ_LINK_DOWN_REQ	0x00000008 /* link down request */
73*ba7319e9SDmitry Salychev #define DPMAC_IRQ_EP_CHANGED	0x00000010 /* DPAA2 endpoint dis/connected */
74*ba7319e9SDmitry Salychev 
75*ba7319e9SDmitry Salychev /* DPAA2 MAC resource specification. */
76*ba7319e9SDmitry Salychev struct resource_spec dpaa2_mac_spec[] = {
77*ba7319e9SDmitry Salychev 	/*
78*ba7319e9SDmitry Salychev 	 * DPMCP resources.
79*ba7319e9SDmitry Salychev 	 *
80*ba7319e9SDmitry Salychev 	 * NOTE: MC command portals (MCPs) are used to send commands to, and
81*ba7319e9SDmitry Salychev 	 *	 receive responses from, the MC firmware. One portal per DPMAC.
82*ba7319e9SDmitry Salychev 	 */
83*ba7319e9SDmitry Salychev #define MCP_RES_NUM	(1u)
84*ba7319e9SDmitry Salychev #define MCP_RID_OFF	(0u)
85*ba7319e9SDmitry Salychev #define MCP_RID(rid)	((rid) + MCP_RID_OFF)
86*ba7319e9SDmitry Salychev 	/* --- */
87*ba7319e9SDmitry Salychev 	{ DPAA2_DEV_MCP, MCP_RID(0), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL },
88*ba7319e9SDmitry Salychev 	/* --- */
89*ba7319e9SDmitry Salychev 	RESOURCE_SPEC_END
90*ba7319e9SDmitry Salychev };
91*ba7319e9SDmitry Salychev 
92*ba7319e9SDmitry Salychev /* Interrupt configuration routines. */
93*ba7319e9SDmitry Salychev static int dpaa2_mac_setup_irq(device_t);
94*ba7319e9SDmitry Salychev static int dpaa2_mac_setup_msi(struct dpaa2_mac_softc *);
95*ba7319e9SDmitry Salychev 
96*ba7319e9SDmitry Salychev /* Subroutines to get text representation. */
97*ba7319e9SDmitry Salychev static const char *dpaa2_mac_ethif_to_str(enum dpaa2_mac_eth_if);
98*ba7319e9SDmitry Salychev static const char *dpaa2_mac_link_type_to_str(enum dpaa2_mac_link_type);
99*ba7319e9SDmitry Salychev 
100*ba7319e9SDmitry Salychev /* Interrupt handlers */
101*ba7319e9SDmitry Salychev static void dpaa2_mac_intr(void *arg);
102*ba7319e9SDmitry Salychev 
103*ba7319e9SDmitry Salychev static int
104*ba7319e9SDmitry Salychev dpaa2_mac_probe(device_t dev)
105*ba7319e9SDmitry Salychev {
106*ba7319e9SDmitry Salychev 	/* DPIO device will be added by a parent resource container itself. */
107*ba7319e9SDmitry Salychev 	device_set_desc(dev, "DPAA2 MAC");
108*ba7319e9SDmitry Salychev 	return (BUS_PROBE_DEFAULT);
109*ba7319e9SDmitry Salychev }
110*ba7319e9SDmitry Salychev 
111*ba7319e9SDmitry Salychev static int
112*ba7319e9SDmitry Salychev dpaa2_mac_attach(device_t dev)
113*ba7319e9SDmitry Salychev {
114*ba7319e9SDmitry Salychev 	device_t pdev = device_get_parent(dev);
115*ba7319e9SDmitry Salychev 	device_t child = dev;
116*ba7319e9SDmitry Salychev 	device_t mcp_dev;
117*ba7319e9SDmitry Salychev 	struct dpaa2_mac_softc *sc = device_get_softc(dev);
118*ba7319e9SDmitry Salychev 	struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
119*ba7319e9SDmitry Salychev 	struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
120*ba7319e9SDmitry Salychev 	struct dpaa2_devinfo *mcp_dinfo;
121*ba7319e9SDmitry Salychev 	int error;
122*ba7319e9SDmitry Salychev 
123*ba7319e9SDmitry Salychev 	sc->dev = dev;
124*ba7319e9SDmitry Salychev 
125*ba7319e9SDmitry Salychev 	memset(sc->addr, 0, ETHER_ADDR_LEN);
126*ba7319e9SDmitry Salychev 
127*ba7319e9SDmitry Salychev 	error = bus_alloc_resources(sc->dev, dpaa2_mac_spec, sc->res);
128*ba7319e9SDmitry Salychev 	if (error) {
129*ba7319e9SDmitry Salychev 		device_printf(dev, "%s: failed to allocate resources: "
130*ba7319e9SDmitry Salychev 		    "error=%d\n", __func__, error);
131*ba7319e9SDmitry Salychev 		return (ENXIO);
132*ba7319e9SDmitry Salychev 	}
133*ba7319e9SDmitry Salychev 
134*ba7319e9SDmitry Salychev 	/* Obtain MC portal. */
135*ba7319e9SDmitry Salychev 	mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]);
136*ba7319e9SDmitry Salychev 	mcp_dinfo = device_get_ivars(mcp_dev);
137*ba7319e9SDmitry Salychev 	dinfo->portal = mcp_dinfo->portal;
138*ba7319e9SDmitry Salychev 
139*ba7319e9SDmitry Salychev 	/* Allocate a command to send to MC hardware. */
140*ba7319e9SDmitry Salychev 	error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF);
141*ba7319e9SDmitry Salychev 	if (error) {
142*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to allocate dpaa2_cmd: error=%d\n",
143*ba7319e9SDmitry Salychev 		    error);
144*ba7319e9SDmitry Salychev 		goto err_exit;
145*ba7319e9SDmitry Salychev 	}
146*ba7319e9SDmitry Salychev 
147*ba7319e9SDmitry Salychev 	/* Open resource container and DPMAC object. */
148*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id,
149*ba7319e9SDmitry Salychev 	    &sc->rc_token);
150*ba7319e9SDmitry Salychev 	if (error) {
151*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to open DPRC: error=%d\n", error);
152*ba7319e9SDmitry Salychev 		goto err_free_cmd;
153*ba7319e9SDmitry Salychev 	}
154*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_MAC_OPEN(dev, child, sc->cmd, dinfo->id,
155*ba7319e9SDmitry Salychev 	    &sc->mac_token);
156*ba7319e9SDmitry Salychev 	if (error) {
157*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to open DPMAC: id=%d, error=%d\n",
158*ba7319e9SDmitry Salychev 		    dinfo->id, error);
159*ba7319e9SDmitry Salychev 		goto err_close_rc;
160*ba7319e9SDmitry Salychev 	}
161*ba7319e9SDmitry Salychev 
162*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_MAC_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr);
163*ba7319e9SDmitry Salychev 	if (error) {
164*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to get DPMAC attributes: id=%d, "
165*ba7319e9SDmitry Salychev 		    "error=%d\n", dinfo->id, error);
166*ba7319e9SDmitry Salychev 		goto err_close_mac;
167*ba7319e9SDmitry Salychev 	}
168*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_MAC_GET_ADDR(dev, child, sc->cmd, sc->addr);
169*ba7319e9SDmitry Salychev 	if (error)
170*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to get physical address: error=%d\n",
171*ba7319e9SDmitry Salychev 		    error);
172*ba7319e9SDmitry Salychev 	/*
173*ba7319e9SDmitry Salychev 	 * TODO: Enable debug output via sysctl.
174*ba7319e9SDmitry Salychev 	 */
175*ba7319e9SDmitry Salychev 	if (bootverbose) {
176*ba7319e9SDmitry Salychev 		device_printf(dev, "ether %6D\n", sc->addr, ":");
177*ba7319e9SDmitry Salychev 		device_printf(dev, "max_rate=%d, eth_if=%s, link_type=%s\n",
178*ba7319e9SDmitry Salychev 		    sc->attr.max_rate,
179*ba7319e9SDmitry Salychev 		    dpaa2_mac_ethif_to_str(sc->attr.eth_if),
180*ba7319e9SDmitry Salychev 		    dpaa2_mac_link_type_to_str(sc->attr.link_type));
181*ba7319e9SDmitry Salychev 	}
182*ba7319e9SDmitry Salychev 
183*ba7319e9SDmitry Salychev 	error = dpaa2_mac_setup_irq(dev);
184*ba7319e9SDmitry Salychev 	if (error) {
185*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to setup IRQs: error=%d\n", error);
186*ba7319e9SDmitry Salychev 		goto err_close_mac;
187*ba7319e9SDmitry Salychev 	}
188*ba7319e9SDmitry Salychev 
189*ba7319e9SDmitry Salychev 	return (0);
190*ba7319e9SDmitry Salychev 
191*ba7319e9SDmitry Salychev err_close_mac:
192*ba7319e9SDmitry Salychev 	DPAA2_CMD_MAC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->mac_token));
193*ba7319e9SDmitry Salychev err_close_rc:
194*ba7319e9SDmitry Salychev 	DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token));
195*ba7319e9SDmitry Salychev err_free_cmd:
196*ba7319e9SDmitry Salychev 	dpaa2_mcp_free_command(sc->cmd);
197*ba7319e9SDmitry Salychev err_exit:
198*ba7319e9SDmitry Salychev 	return (ENXIO);
199*ba7319e9SDmitry Salychev }
200*ba7319e9SDmitry Salychev 
201*ba7319e9SDmitry Salychev static int
202*ba7319e9SDmitry Salychev dpaa2_mac_detach(device_t dev)
203*ba7319e9SDmitry Salychev {
204*ba7319e9SDmitry Salychev 	device_t child = dev;
205*ba7319e9SDmitry Salychev 	struct dpaa2_mac_softc *sc = device_get_softc(dev);
206*ba7319e9SDmitry Salychev 
207*ba7319e9SDmitry Salychev 	DPAA2_CMD_MAC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->mac_token));
208*ba7319e9SDmitry Salychev 	DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token));
209*ba7319e9SDmitry Salychev 	dpaa2_mcp_free_command(sc->cmd);
210*ba7319e9SDmitry Salychev 
211*ba7319e9SDmitry Salychev 	sc->cmd = NULL;
212*ba7319e9SDmitry Salychev 	sc->rc_token = 0;
213*ba7319e9SDmitry Salychev 	sc->mac_token = 0;
214*ba7319e9SDmitry Salychev 
215*ba7319e9SDmitry Salychev 	return (0);
216*ba7319e9SDmitry Salychev }
217*ba7319e9SDmitry Salychev 
218*ba7319e9SDmitry Salychev /**
219*ba7319e9SDmitry Salychev  * @brief Configure DPMAC object to generate interrupts.
220*ba7319e9SDmitry Salychev  */
221*ba7319e9SDmitry Salychev static int
222*ba7319e9SDmitry Salychev dpaa2_mac_setup_irq(device_t dev)
223*ba7319e9SDmitry Salychev {
224*ba7319e9SDmitry Salychev 	device_t child = dev;
225*ba7319e9SDmitry Salychev 	struct dpaa2_mac_softc *sc = device_get_softc(dev);
226*ba7319e9SDmitry Salychev 	struct dpaa2_cmd *cmd = sc->cmd;
227*ba7319e9SDmitry Salychev 	uint16_t mac_token = sc->mac_token;
228*ba7319e9SDmitry Salychev 	uint32_t irq_mask;
229*ba7319e9SDmitry Salychev 	int error;
230*ba7319e9SDmitry Salychev 
231*ba7319e9SDmitry Salychev 	/* Configure IRQs. */
232*ba7319e9SDmitry Salychev 	error = dpaa2_mac_setup_msi(sc);
233*ba7319e9SDmitry Salychev 	if (error) {
234*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to allocate MSI\n");
235*ba7319e9SDmitry Salychev 		return (error);
236*ba7319e9SDmitry Salychev 	}
237*ba7319e9SDmitry Salychev 	if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
238*ba7319e9SDmitry Salychev 	    &sc->irq_rid[0], RF_ACTIVE | RF_SHAREABLE)) == NULL) {
239*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to allocate IRQ resource\n");
240*ba7319e9SDmitry Salychev 		return (ENXIO);
241*ba7319e9SDmitry Salychev 	}
242*ba7319e9SDmitry Salychev 	if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
243*ba7319e9SDmitry Salychev 	    NULL, dpaa2_mac_intr, sc, &sc->intr)) {
244*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to setup IRQ resource\n");
245*ba7319e9SDmitry Salychev 		return (ENXIO);
246*ba7319e9SDmitry Salychev 	}
247*ba7319e9SDmitry Salychev 
248*ba7319e9SDmitry Salychev 	/* Configure DPNI to generate interrupts. */
249*ba7319e9SDmitry Salychev 	irq_mask =
250*ba7319e9SDmitry Salychev 	    DPMAC_IRQ_LINK_CFG_REQ |
251*ba7319e9SDmitry Salychev 	    DPMAC_IRQ_LINK_CHANGED |
252*ba7319e9SDmitry Salychev 	    DPMAC_IRQ_LINK_UP_REQ |
253*ba7319e9SDmitry Salychev 	    DPMAC_IRQ_LINK_DOWN_REQ |
254*ba7319e9SDmitry Salychev 	    DPMAC_IRQ_EP_CHANGED;
255*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_MAC_SET_IRQ_MASK(dev, child, dpaa2_mcp_tk(cmd,
256*ba7319e9SDmitry Salychev 	    mac_token), DPMAC_IRQ_INDEX, irq_mask);
257*ba7319e9SDmitry Salychev 	if (error) {
258*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to set IRQ mask\n");
259*ba7319e9SDmitry Salychev 		return (error);
260*ba7319e9SDmitry Salychev 	}
261*ba7319e9SDmitry Salychev 
262*ba7319e9SDmitry Salychev 	/* Enable IRQ. */
263*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_MAC_SET_IRQ_ENABLE(dev, child, cmd, DPMAC_IRQ_INDEX,
264*ba7319e9SDmitry Salychev 	    true);
265*ba7319e9SDmitry Salychev 	if (error) {
266*ba7319e9SDmitry Salychev 		device_printf(dev, "Failed to enable IRQ\n");
267*ba7319e9SDmitry Salychev 		return (error);
268*ba7319e9SDmitry Salychev 	}
269*ba7319e9SDmitry Salychev 
270*ba7319e9SDmitry Salychev 	return (0);
271*ba7319e9SDmitry Salychev }
272*ba7319e9SDmitry Salychev 
273*ba7319e9SDmitry Salychev /**
274*ba7319e9SDmitry Salychev  * @brief Allocate MSI interrupts for DPMAC.
275*ba7319e9SDmitry Salychev  */
276*ba7319e9SDmitry Salychev static int
277*ba7319e9SDmitry Salychev dpaa2_mac_setup_msi(struct dpaa2_mac_softc *sc)
278*ba7319e9SDmitry Salychev {
279*ba7319e9SDmitry Salychev 	int val;
280*ba7319e9SDmitry Salychev 
281*ba7319e9SDmitry Salychev 	val = pci_msi_count(sc->dev);
282*ba7319e9SDmitry Salychev 	if (val < DPAA2_MAC_MSI_COUNT)
283*ba7319e9SDmitry Salychev 		device_printf(sc->dev, "MSI: actual=%d, expected=%d\n", val,
284*ba7319e9SDmitry Salychev 		    DPAA2_MAC_MSI_COUNT);
285*ba7319e9SDmitry Salychev 	val = MIN(val, DPAA2_MAC_MSI_COUNT);
286*ba7319e9SDmitry Salychev 
287*ba7319e9SDmitry Salychev 	if (pci_alloc_msi(sc->dev, &val) != 0)
288*ba7319e9SDmitry Salychev 		return (EINVAL);
289*ba7319e9SDmitry Salychev 
290*ba7319e9SDmitry Salychev 	for (int i = 0; i < val; i++)
291*ba7319e9SDmitry Salychev 		sc->irq_rid[i] = i + 1;
292*ba7319e9SDmitry Salychev 
293*ba7319e9SDmitry Salychev 	return (0);
294*ba7319e9SDmitry Salychev }
295*ba7319e9SDmitry Salychev 
296*ba7319e9SDmitry Salychev static void
297*ba7319e9SDmitry Salychev dpaa2_mac_intr(void *arg)
298*ba7319e9SDmitry Salychev {
299*ba7319e9SDmitry Salychev 	struct dpaa2_mac_softc *sc = (struct dpaa2_mac_softc *) arg;
300*ba7319e9SDmitry Salychev 	device_t child = sc->dev;
301*ba7319e9SDmitry Salychev 	uint32_t status = ~0u; /* clear all IRQ status bits */
302*ba7319e9SDmitry Salychev 	int error;
303*ba7319e9SDmitry Salychev 
304*ba7319e9SDmitry Salychev 	error = DPAA2_CMD_MAC_GET_IRQ_STATUS(sc->dev, child,
305*ba7319e9SDmitry Salychev 	    dpaa2_mcp_tk(sc->cmd, sc->mac_token), DPMAC_IRQ_INDEX, &status);
306*ba7319e9SDmitry Salychev 	if (error)
307*ba7319e9SDmitry Salychev 		device_printf(sc->dev, "%s: failed to obtain IRQ status: "
308*ba7319e9SDmitry Salychev 		    "error=%d\n", __func__, error);
309*ba7319e9SDmitry Salychev }
310*ba7319e9SDmitry Salychev 
311*ba7319e9SDmitry Salychev static const char *
312*ba7319e9SDmitry Salychev dpaa2_mac_ethif_to_str(enum dpaa2_mac_eth_if eth_if)
313*ba7319e9SDmitry Salychev {
314*ba7319e9SDmitry Salychev 	switch (eth_if) {
315*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_MII:
316*ba7319e9SDmitry Salychev 		return ("MII");
317*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_RMII:
318*ba7319e9SDmitry Salychev 		return ("RMII");
319*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_SMII:
320*ba7319e9SDmitry Salychev 		return ("SMII");
321*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_GMII:
322*ba7319e9SDmitry Salychev 		return ("GMII");
323*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_RGMII:
324*ba7319e9SDmitry Salychev 		return ("RGMII");
325*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_SGMII:
326*ba7319e9SDmitry Salychev 		return ("SGMII");
327*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_QSGMII:
328*ba7319e9SDmitry Salychev 		return ("QSGMII");
329*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_XAUI:
330*ba7319e9SDmitry Salychev 		return ("XAUI");
331*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_XFI:
332*ba7319e9SDmitry Salychev 		return ("XFI");
333*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_CAUI:
334*ba7319e9SDmitry Salychev 		return ("CAUI");
335*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_1000BASEX:
336*ba7319e9SDmitry Salychev 		return ("1000BASE-X");
337*ba7319e9SDmitry Salychev 	case DPAA2_MAC_ETH_IF_USXGMII:
338*ba7319e9SDmitry Salychev 		return ("USXGMII");
339*ba7319e9SDmitry Salychev 	default:
340*ba7319e9SDmitry Salychev 		return ("unknown");
341*ba7319e9SDmitry Salychev 	}
342*ba7319e9SDmitry Salychev }
343*ba7319e9SDmitry Salychev 
344*ba7319e9SDmitry Salychev static const char *
345*ba7319e9SDmitry Salychev dpaa2_mac_link_type_to_str(enum dpaa2_mac_link_type link_type)
346*ba7319e9SDmitry Salychev {
347*ba7319e9SDmitry Salychev 	switch (link_type) {
348*ba7319e9SDmitry Salychev 	case DPAA2_MAC_LINK_TYPE_NONE:
349*ba7319e9SDmitry Salychev 		return ("NONE");
350*ba7319e9SDmitry Salychev 	case DPAA2_MAC_LINK_TYPE_FIXED:
351*ba7319e9SDmitry Salychev 		return ("FIXED");
352*ba7319e9SDmitry Salychev 	case DPAA2_MAC_LINK_TYPE_PHY:
353*ba7319e9SDmitry Salychev 		return ("PHY");
354*ba7319e9SDmitry Salychev 	case DPAA2_MAC_LINK_TYPE_BACKPLANE:
355*ba7319e9SDmitry Salychev 		return ("BACKPLANE");
356*ba7319e9SDmitry Salychev 	default:
357*ba7319e9SDmitry Salychev 		return ("unknown");
358*ba7319e9SDmitry Salychev 	}
359*ba7319e9SDmitry Salychev }
360*ba7319e9SDmitry Salychev 
361*ba7319e9SDmitry Salychev static device_method_t dpaa2_mac_methods[] = {
362*ba7319e9SDmitry Salychev 	/* Device interface */
363*ba7319e9SDmitry Salychev 	DEVMETHOD(device_probe,		dpaa2_mac_probe),
364*ba7319e9SDmitry Salychev 	DEVMETHOD(device_attach,	dpaa2_mac_attach),
365*ba7319e9SDmitry Salychev 	DEVMETHOD(device_detach,	dpaa2_mac_detach),
366*ba7319e9SDmitry Salychev 
367*ba7319e9SDmitry Salychev 	DEVMETHOD_END
368*ba7319e9SDmitry Salychev };
369*ba7319e9SDmitry Salychev 
370*ba7319e9SDmitry Salychev static driver_t dpaa2_mac_driver = {
371*ba7319e9SDmitry Salychev 	"dpaa2_mac",
372*ba7319e9SDmitry Salychev 	dpaa2_mac_methods,
373*ba7319e9SDmitry Salychev 	sizeof(struct dpaa2_mac_softc),
374*ba7319e9SDmitry Salychev };
375*ba7319e9SDmitry Salychev 
376*ba7319e9SDmitry Salychev DRIVER_MODULE(dpaa2_mac, dpaa2_rc, dpaa2_mac_driver, 0, 0);
377