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