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