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 * DPAA2 MC command portal and helper routines. 33*ba7319e9SDmitry Salychev */ 34*ba7319e9SDmitry Salychev 35*ba7319e9SDmitry Salychev #include <sys/param.h> 36*ba7319e9SDmitry Salychev #include <sys/kernel.h> 37*ba7319e9SDmitry Salychev #include <sys/bus.h> 38*ba7319e9SDmitry Salychev #include <sys/rman.h> 39*ba7319e9SDmitry Salychev #include <sys/module.h> 40*ba7319e9SDmitry Salychev #include <sys/malloc.h> 41*ba7319e9SDmitry Salychev #include <sys/mutex.h> 42*ba7319e9SDmitry Salychev #include <sys/time.h> 43*ba7319e9SDmitry Salychev #include <sys/types.h> 44*ba7319e9SDmitry Salychev #include <sys/systm.h> 45*ba7319e9SDmitry Salychev #include <sys/condvar.h> 46*ba7319e9SDmitry Salychev #include <sys/lock.h> 47*ba7319e9SDmitry Salychev 48*ba7319e9SDmitry Salychev #include <machine/bus.h> 49*ba7319e9SDmitry Salychev #include <machine/resource.h> 50*ba7319e9SDmitry Salychev 51*ba7319e9SDmitry Salychev #include "pcib_if.h" 52*ba7319e9SDmitry Salychev #include "pci_if.h" 53*ba7319e9SDmitry Salychev 54*ba7319e9SDmitry Salychev #include "dpaa2_mcp.h" 55*ba7319e9SDmitry Salychev #include "dpaa2_mc.h" 56*ba7319e9SDmitry Salychev #include "dpaa2_cmd_if.h" 57*ba7319e9SDmitry Salychev 58*ba7319e9SDmitry Salychev MALLOC_DEFINE(M_DPAA2_MCP, "dpaa2_mcp", "DPAA2 Management Complex Portal"); 59*ba7319e9SDmitry Salychev 60*ba7319e9SDmitry Salychev static struct resource_spec dpaa2_mcp_spec[] = { 61*ba7319e9SDmitry Salychev { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_UNMAPPED }, 62*ba7319e9SDmitry Salychev RESOURCE_SPEC_END 63*ba7319e9SDmitry Salychev }; 64*ba7319e9SDmitry Salychev 65*ba7319e9SDmitry Salychev int 66*ba7319e9SDmitry Salychev dpaa2_mcp_init_portal(struct dpaa2_mcp **mcp, struct resource *res, 67*ba7319e9SDmitry Salychev struct resource_map *map, uint16_t flags) 68*ba7319e9SDmitry Salychev { 69*ba7319e9SDmitry Salychev const int mflags = flags & DPAA2_PORTAL_NOWAIT_ALLOC 70*ba7319e9SDmitry Salychev ? (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO); 71*ba7319e9SDmitry Salychev struct dpaa2_mcp *p; 72*ba7319e9SDmitry Salychev 73*ba7319e9SDmitry Salychev if (!mcp || !res || !map) 74*ba7319e9SDmitry Salychev return (DPAA2_CMD_STAT_EINVAL); 75*ba7319e9SDmitry Salychev 76*ba7319e9SDmitry Salychev p = malloc(sizeof(struct dpaa2_mcp), M_DPAA2_MCP, mflags); 77*ba7319e9SDmitry Salychev if (p == NULL) 78*ba7319e9SDmitry Salychev return (DPAA2_CMD_STAT_NO_MEMORY); 79*ba7319e9SDmitry Salychev 80*ba7319e9SDmitry Salychev mtx_init(&p->lock, "mcp_sleep_lock", NULL, MTX_DEF); 81*ba7319e9SDmitry Salychev 82*ba7319e9SDmitry Salychev p->res = res; 83*ba7319e9SDmitry Salychev p->map = map; 84*ba7319e9SDmitry Salychev p->flags = flags; 85*ba7319e9SDmitry Salychev p->rc_api_major = 0; /* DPRC API version to be cached later. */ 86*ba7319e9SDmitry Salychev p->rc_api_minor = 0; 87*ba7319e9SDmitry Salychev 88*ba7319e9SDmitry Salychev *mcp = p; 89*ba7319e9SDmitry Salychev 90*ba7319e9SDmitry Salychev return (0); 91*ba7319e9SDmitry Salychev } 92*ba7319e9SDmitry Salychev 93*ba7319e9SDmitry Salychev void 94*ba7319e9SDmitry Salychev dpaa2_mcp_free_portal(struct dpaa2_mcp *mcp) 95*ba7319e9SDmitry Salychev { 96*ba7319e9SDmitry Salychev uint16_t flags; 97*ba7319e9SDmitry Salychev 98*ba7319e9SDmitry Salychev KASSERT(mcp != NULL, ("%s: mcp is NULL", __func__)); 99*ba7319e9SDmitry Salychev 100*ba7319e9SDmitry Salychev DPAA2_MCP_LOCK(mcp, &flags); 101*ba7319e9SDmitry Salychev mcp->flags |= DPAA2_PORTAL_DESTROYED; 102*ba7319e9SDmitry Salychev DPAA2_MCP_UNLOCK(mcp); 103*ba7319e9SDmitry Salychev 104*ba7319e9SDmitry Salychev /* Let threads stop using this portal. */ 105*ba7319e9SDmitry Salychev DELAY(DPAA2_PORTAL_TIMEOUT); 106*ba7319e9SDmitry Salychev 107*ba7319e9SDmitry Salychev mtx_destroy(&mcp->lock); 108*ba7319e9SDmitry Salychev free(mcp, M_DPAA2_MCP); 109*ba7319e9SDmitry Salychev } 110*ba7319e9SDmitry Salychev 111*ba7319e9SDmitry Salychev int 112*ba7319e9SDmitry Salychev dpaa2_mcp_init_command(struct dpaa2_cmd **cmd, uint16_t flags) 113*ba7319e9SDmitry Salychev { 114*ba7319e9SDmitry Salychev const int mflags = flags & DPAA2_CMD_NOWAIT_ALLOC 115*ba7319e9SDmitry Salychev ? (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO); 116*ba7319e9SDmitry Salychev struct dpaa2_cmd *c; 117*ba7319e9SDmitry Salychev struct dpaa2_cmd_header *hdr; 118*ba7319e9SDmitry Salychev 119*ba7319e9SDmitry Salychev if (!cmd) 120*ba7319e9SDmitry Salychev return (DPAA2_CMD_STAT_EINVAL); 121*ba7319e9SDmitry Salychev 122*ba7319e9SDmitry Salychev c = malloc(sizeof(struct dpaa2_cmd), M_DPAA2_MCP, mflags); 123*ba7319e9SDmitry Salychev if (!c) 124*ba7319e9SDmitry Salychev return (DPAA2_CMD_STAT_NO_MEMORY); 125*ba7319e9SDmitry Salychev 126*ba7319e9SDmitry Salychev hdr = (struct dpaa2_cmd_header *) &c->header; 127*ba7319e9SDmitry Salychev hdr->srcid = 0; 128*ba7319e9SDmitry Salychev hdr->status = DPAA2_CMD_STAT_OK; 129*ba7319e9SDmitry Salychev hdr->token = 0; 130*ba7319e9SDmitry Salychev hdr->cmdid = 0; 131*ba7319e9SDmitry Salychev hdr->flags_hw = DPAA2_CMD_DEF; 132*ba7319e9SDmitry Salychev hdr->flags_sw = DPAA2_CMD_DEF; 133*ba7319e9SDmitry Salychev if (flags & DPAA2_CMD_HIGH_PRIO) 134*ba7319e9SDmitry Salychev hdr->flags_hw |= DPAA2_HW_FLAG_HIGH_PRIO; 135*ba7319e9SDmitry Salychev if (flags & DPAA2_CMD_INTR_DIS) 136*ba7319e9SDmitry Salychev hdr->flags_sw |= DPAA2_SW_FLAG_INTR_DIS; 137*ba7319e9SDmitry Salychev for (uint32_t i = 0; i < DPAA2_CMD_PARAMS_N; i++) 138*ba7319e9SDmitry Salychev c->params[i] = 0; 139*ba7319e9SDmitry Salychev *cmd = c; 140*ba7319e9SDmitry Salychev 141*ba7319e9SDmitry Salychev return (0); 142*ba7319e9SDmitry Salychev } 143*ba7319e9SDmitry Salychev 144*ba7319e9SDmitry Salychev void 145*ba7319e9SDmitry Salychev dpaa2_mcp_free_command(struct dpaa2_cmd *cmd) 146*ba7319e9SDmitry Salychev { 147*ba7319e9SDmitry Salychev if (cmd != NULL) 148*ba7319e9SDmitry Salychev free(cmd, M_DPAA2_MCP); 149*ba7319e9SDmitry Salychev } 150*ba7319e9SDmitry Salychev 151*ba7319e9SDmitry Salychev struct dpaa2_cmd * 152*ba7319e9SDmitry Salychev dpaa2_mcp_tk(struct dpaa2_cmd *cmd, uint16_t token) 153*ba7319e9SDmitry Salychev { 154*ba7319e9SDmitry Salychev struct dpaa2_cmd_header *hdr; 155*ba7319e9SDmitry Salychev if (cmd != NULL) { 156*ba7319e9SDmitry Salychev hdr = (struct dpaa2_cmd_header *) &cmd->header; 157*ba7319e9SDmitry Salychev hdr->token = token; 158*ba7319e9SDmitry Salychev } 159*ba7319e9SDmitry Salychev return (cmd); 160*ba7319e9SDmitry Salychev } 161*ba7319e9SDmitry Salychev 162*ba7319e9SDmitry Salychev struct dpaa2_cmd * 163*ba7319e9SDmitry Salychev dpaa2_mcp_f(struct dpaa2_cmd *cmd, uint16_t flags) 164*ba7319e9SDmitry Salychev { 165*ba7319e9SDmitry Salychev struct dpaa2_cmd_header *hdr; 166*ba7319e9SDmitry Salychev if (cmd) { 167*ba7319e9SDmitry Salychev hdr = (struct dpaa2_cmd_header *) &cmd->header; 168*ba7319e9SDmitry Salychev hdr->flags_hw = DPAA2_CMD_DEF; 169*ba7319e9SDmitry Salychev hdr->flags_sw = DPAA2_CMD_DEF; 170*ba7319e9SDmitry Salychev 171*ba7319e9SDmitry Salychev if (flags & DPAA2_CMD_HIGH_PRIO) 172*ba7319e9SDmitry Salychev hdr->flags_hw |= DPAA2_HW_FLAG_HIGH_PRIO; 173*ba7319e9SDmitry Salychev if (flags & DPAA2_CMD_INTR_DIS) 174*ba7319e9SDmitry Salychev hdr->flags_sw |= DPAA2_SW_FLAG_INTR_DIS; 175*ba7319e9SDmitry Salychev } 176*ba7319e9SDmitry Salychev return (cmd); 177*ba7319e9SDmitry Salychev } 178*ba7319e9SDmitry Salychev 179*ba7319e9SDmitry Salychev static int 180*ba7319e9SDmitry Salychev dpaa2_mcp_probe(device_t dev) 181*ba7319e9SDmitry Salychev { 182*ba7319e9SDmitry Salychev /* DPMCP device will be added by the parent resource container. */ 183*ba7319e9SDmitry Salychev device_set_desc(dev, "DPAA2 MC portal"); 184*ba7319e9SDmitry Salychev return (BUS_PROBE_DEFAULT); 185*ba7319e9SDmitry Salychev } 186*ba7319e9SDmitry Salychev 187*ba7319e9SDmitry Salychev static int 188*ba7319e9SDmitry Salychev dpaa2_mcp_detach(device_t dev) 189*ba7319e9SDmitry Salychev { 190*ba7319e9SDmitry Salychev return (0); 191*ba7319e9SDmitry Salychev } 192*ba7319e9SDmitry Salychev 193*ba7319e9SDmitry Salychev static int 194*ba7319e9SDmitry Salychev dpaa2_mcp_attach(device_t dev) 195*ba7319e9SDmitry Salychev { 196*ba7319e9SDmitry Salychev device_t pdev = device_get_parent(dev); 197*ba7319e9SDmitry Salychev device_t child = dev; 198*ba7319e9SDmitry Salychev struct dpaa2_mcp_softc *sc = device_get_softc(dev); 199*ba7319e9SDmitry Salychev struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); 200*ba7319e9SDmitry Salychev struct dpaa2_devinfo *dinfo = device_get_ivars(dev); 201*ba7319e9SDmitry Salychev struct dpaa2_cmd *cmd; 202*ba7319e9SDmitry Salychev struct dpaa2_mcp *portal; 203*ba7319e9SDmitry Salychev struct resource_map_request req; 204*ba7319e9SDmitry Salychev uint16_t rc_token, mcp_token; 205*ba7319e9SDmitry Salychev int error; 206*ba7319e9SDmitry Salychev 207*ba7319e9SDmitry Salychev sc->dev = dev; 208*ba7319e9SDmitry Salychev 209*ba7319e9SDmitry Salychev error = bus_alloc_resources(sc->dev, dpaa2_mcp_spec, sc->res); 210*ba7319e9SDmitry Salychev if (error) { 211*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to allocate resources\n", 212*ba7319e9SDmitry Salychev __func__); 213*ba7319e9SDmitry Salychev goto err_exit; 214*ba7319e9SDmitry Salychev } 215*ba7319e9SDmitry Salychev 216*ba7319e9SDmitry Salychev /* At least 64 bytes of the command portal should be available. */ 217*ba7319e9SDmitry Salychev if (rman_get_size(sc->res[0]) < DPAA2_MCP_MEM_WIDTH) { 218*ba7319e9SDmitry Salychev device_printf(dev, "%s: MC portal memory region too small: " 219*ba7319e9SDmitry Salychev "%jd\n", __func__, rman_get_size(sc->res[0])); 220*ba7319e9SDmitry Salychev goto err_exit; 221*ba7319e9SDmitry Salychev } 222*ba7319e9SDmitry Salychev 223*ba7319e9SDmitry Salychev /* Map MC portal memory resource. */ 224*ba7319e9SDmitry Salychev resource_init_map_request(&req); 225*ba7319e9SDmitry Salychev req.memattr = VM_MEMATTR_DEVICE; 226*ba7319e9SDmitry Salychev error = bus_map_resource(sc->dev, SYS_RES_MEMORY, sc->res[0], &req, 227*ba7319e9SDmitry Salychev &sc->map[0]); 228*ba7319e9SDmitry Salychev if (error) { 229*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to map MC portal memory\n", 230*ba7319e9SDmitry Salychev __func__); 231*ba7319e9SDmitry Salychev goto err_exit; 232*ba7319e9SDmitry Salychev } 233*ba7319e9SDmitry Salychev 234*ba7319e9SDmitry Salychev /* Initialize portal to send commands to MC. */ 235*ba7319e9SDmitry Salychev error = dpaa2_mcp_init_portal(&portal, sc->res[0], &sc->map[0], 236*ba7319e9SDmitry Salychev DPAA2_PORTAL_DEF); 237*ba7319e9SDmitry Salychev if (error) { 238*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to initialize dpaa2_mcp: " 239*ba7319e9SDmitry Salychev "error=%d\n", __func__, error); 240*ba7319e9SDmitry Salychev goto err_exit; 241*ba7319e9SDmitry Salychev } 242*ba7319e9SDmitry Salychev 243*ba7319e9SDmitry Salychev /* Allocate a command to send to MC hardware. */ 244*ba7319e9SDmitry Salychev error = dpaa2_mcp_init_command(&cmd, DPAA2_CMD_DEF); 245*ba7319e9SDmitry Salychev if (error) { 246*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to allocate dpaa2_cmd: " 247*ba7319e9SDmitry Salychev "error=%d\n", __func__, error); 248*ba7319e9SDmitry Salychev goto err_exit; 249*ba7319e9SDmitry Salychev } 250*ba7319e9SDmitry Salychev 251*ba7319e9SDmitry Salychev /* Open resource container and DPMCP object. */ 252*ba7319e9SDmitry Salychev error = DPAA2_CMD_RC_OPEN(dev, child, cmd, rcinfo->id, &rc_token); 253*ba7319e9SDmitry Salychev if (error) { 254*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to open DPRC: error=%d\n", 255*ba7319e9SDmitry Salychev __func__, error); 256*ba7319e9SDmitry Salychev goto err_free_cmd; 257*ba7319e9SDmitry Salychev } 258*ba7319e9SDmitry Salychev error = DPAA2_CMD_MCP_OPEN(dev, child, cmd, dinfo->id, &mcp_token); 259*ba7319e9SDmitry Salychev if (error) { 260*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to open DPMCP: id=%d, error=%d\n", 261*ba7319e9SDmitry Salychev __func__, dinfo->id, error); 262*ba7319e9SDmitry Salychev goto err_close_rc; 263*ba7319e9SDmitry Salychev } 264*ba7319e9SDmitry Salychev 265*ba7319e9SDmitry Salychev /* Prepare DPMCP object. */ 266*ba7319e9SDmitry Salychev error = DPAA2_CMD_MCP_RESET(dev, child, cmd); 267*ba7319e9SDmitry Salychev if (error) { 268*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to reset DPMCP: id=%d, " 269*ba7319e9SDmitry Salychev "error=%d\n", __func__, dinfo->id, error); 270*ba7319e9SDmitry Salychev goto err_close_mcp; 271*ba7319e9SDmitry Salychev } 272*ba7319e9SDmitry Salychev 273*ba7319e9SDmitry Salychev /* Close the DPMCP object and the resource container. */ 274*ba7319e9SDmitry Salychev error = DPAA2_CMD_MCP_CLOSE(dev, child, cmd); 275*ba7319e9SDmitry Salychev if (error) { 276*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to close DPMCP: id=%d, " 277*ba7319e9SDmitry Salychev "error=%d\n", __func__, dinfo->id, error); 278*ba7319e9SDmitry Salychev goto err_close_rc; 279*ba7319e9SDmitry Salychev } 280*ba7319e9SDmitry Salychev error = DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(cmd, rc_token)); 281*ba7319e9SDmitry Salychev if (error) { 282*ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to close DPRC: error=%d\n", 283*ba7319e9SDmitry Salychev __func__, error); 284*ba7319e9SDmitry Salychev goto err_free_cmd; 285*ba7319e9SDmitry Salychev } 286*ba7319e9SDmitry Salychev 287*ba7319e9SDmitry Salychev dpaa2_mcp_free_command(cmd); 288*ba7319e9SDmitry Salychev dinfo->portal = portal; 289*ba7319e9SDmitry Salychev 290*ba7319e9SDmitry Salychev return (0); 291*ba7319e9SDmitry Salychev 292*ba7319e9SDmitry Salychev err_close_mcp: 293*ba7319e9SDmitry Salychev DPAA2_CMD_MCP_CLOSE(dev, child, dpaa2_mcp_tk(cmd, mcp_token)); 294*ba7319e9SDmitry Salychev err_close_rc: 295*ba7319e9SDmitry Salychev DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(cmd, rc_token)); 296*ba7319e9SDmitry Salychev err_free_cmd: 297*ba7319e9SDmitry Salychev dpaa2_mcp_free_command(cmd); 298*ba7319e9SDmitry Salychev err_exit: 299*ba7319e9SDmitry Salychev dpaa2_mcp_detach(dev); 300*ba7319e9SDmitry Salychev return (ENXIO); 301*ba7319e9SDmitry Salychev } 302*ba7319e9SDmitry Salychev 303*ba7319e9SDmitry Salychev static device_method_t dpaa2_mcp_methods[] = { 304*ba7319e9SDmitry Salychev /* Device interface */ 305*ba7319e9SDmitry Salychev DEVMETHOD(device_probe, dpaa2_mcp_probe), 306*ba7319e9SDmitry Salychev DEVMETHOD(device_attach, dpaa2_mcp_attach), 307*ba7319e9SDmitry Salychev DEVMETHOD(device_detach, dpaa2_mcp_detach), 308*ba7319e9SDmitry Salychev 309*ba7319e9SDmitry Salychev DEVMETHOD_END 310*ba7319e9SDmitry Salychev }; 311*ba7319e9SDmitry Salychev 312*ba7319e9SDmitry Salychev static driver_t dpaa2_mcp_driver = { 313*ba7319e9SDmitry Salychev "dpaa2_mcp", 314*ba7319e9SDmitry Salychev dpaa2_mcp_methods, 315*ba7319e9SDmitry Salychev sizeof(struct dpaa2_mcp_softc), 316*ba7319e9SDmitry Salychev }; 317*ba7319e9SDmitry Salychev 318*ba7319e9SDmitry Salychev DRIVER_MODULE(dpaa2_mcp, dpaa2_rc, dpaa2_mcp_driver, 0, 0); 319