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 Concentrator (DPCON) driver. 33ba7319e9SDmitry Salychev * 34ba7319e9SDmitry Salychev * Supports configuration of QBMan channels for advanced scheduling of ingress 35ba7319e9SDmitry Salychev * packets from one or more network interfaces. 36ba7319e9SDmitry Salychev * 37ba7319e9SDmitry Salychev * DPCONs are used to distribute Rx or Tx Confirmation traffic to different 38ba7319e9SDmitry Salychev * cores, via affine DPIO objects. The implication is that one DPCON must be 39ba7319e9SDmitry Salychev * available for each core where Rx or Tx Confirmation traffic should be 40ba7319e9SDmitry Salychev * distributed to. 41ba7319e9SDmitry Salychev * 42ba7319e9SDmitry Salychev * QBMan channel contains several work queues. The WQs within a channel have a 43ba7319e9SDmitry Salychev * priority relative to each other. Each channel consists of either eight or two 44ba7319e9SDmitry Salychev * WQs, and thus, there are either eight or two possible priorities in a channel. 45ba7319e9SDmitry Salychev */ 46ba7319e9SDmitry Salychev 47ba7319e9SDmitry Salychev #include <sys/param.h> 48ba7319e9SDmitry Salychev #include <sys/kernel.h> 49ba7319e9SDmitry Salychev #include <sys/bus.h> 50ba7319e9SDmitry Salychev #include <sys/rman.h> 51ba7319e9SDmitry Salychev #include <sys/module.h> 52ba7319e9SDmitry Salychev #include <sys/malloc.h> 53ba7319e9SDmitry Salychev #include <sys/mutex.h> 54ba7319e9SDmitry Salychev 55ba7319e9SDmitry Salychev #include <vm/vm.h> 56ba7319e9SDmitry Salychev 57ba7319e9SDmitry Salychev #include <machine/bus.h> 58ba7319e9SDmitry Salychev #include <machine/resource.h> 59ba7319e9SDmitry Salychev 60ba7319e9SDmitry Salychev #include <dev/pci/pcivar.h> 61ba7319e9SDmitry Salychev 62ba7319e9SDmitry Salychev #include "pcib_if.h" 63ba7319e9SDmitry Salychev #include "pci_if.h" 64ba7319e9SDmitry Salychev 65ba7319e9SDmitry Salychev #include "dpaa2_mcp.h" 66ba7319e9SDmitry Salychev #include "dpaa2_swp.h" 67ba7319e9SDmitry Salychev #include "dpaa2_mc.h" 68ba7319e9SDmitry Salychev #include "dpaa2_cmd_if.h" 69ba7319e9SDmitry Salychev 70ba7319e9SDmitry Salychev /* DPAA2 Concentrator resource specification. */ 71ba7319e9SDmitry Salychev struct resource_spec dpaa2_con_spec[] = { 72ba7319e9SDmitry Salychev /* 73ba7319e9SDmitry Salychev * DPMCP resources. 74ba7319e9SDmitry Salychev * 75ba7319e9SDmitry Salychev * NOTE: MC command portals (MCPs) are used to send commands to, and 76ba7319e9SDmitry Salychev * receive responses from, the MC firmware. One portal per DPCON. 77ba7319e9SDmitry Salychev */ 78ba7319e9SDmitry Salychev #define MCP_RES_NUM (1u) 79ba7319e9SDmitry Salychev #define MCP_RID_OFF (0u) 80ba7319e9SDmitry Salychev #define MCP_RID(rid) ((rid) + MCP_RID_OFF) 81ba7319e9SDmitry Salychev /* --- */ 82ba7319e9SDmitry Salychev { DPAA2_DEV_MCP, MCP_RID(0), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL }, 83ba7319e9SDmitry Salychev /* --- */ 84ba7319e9SDmitry Salychev RESOURCE_SPEC_END 85ba7319e9SDmitry Salychev }; 86ba7319e9SDmitry Salychev 87ba7319e9SDmitry Salychev static int dpaa2_con_detach(device_t dev); 88ba7319e9SDmitry Salychev 89ba7319e9SDmitry Salychev /* 90ba7319e9SDmitry Salychev * Device interface. 91ba7319e9SDmitry Salychev */ 92ba7319e9SDmitry Salychev 93ba7319e9SDmitry Salychev static int 94ba7319e9SDmitry Salychev dpaa2_con_probe(device_t dev) 95ba7319e9SDmitry Salychev { 96ba7319e9SDmitry Salychev /* DPCON device will be added by a parent resource container itself. */ 97ba7319e9SDmitry Salychev device_set_desc(dev, "DPAA2 Concentrator"); 98ba7319e9SDmitry Salychev return (BUS_PROBE_DEFAULT); 99ba7319e9SDmitry Salychev } 100ba7319e9SDmitry Salychev 101ba7319e9SDmitry Salychev static int 102ba7319e9SDmitry Salychev dpaa2_con_detach(device_t dev) 103ba7319e9SDmitry Salychev { 104*4cd96614SDmitry Salychev /* TBD */ 105ba7319e9SDmitry Salychev return (0); 106ba7319e9SDmitry Salychev } 107ba7319e9SDmitry Salychev 108ba7319e9SDmitry Salychev static int 109ba7319e9SDmitry Salychev dpaa2_con_attach(device_t dev) 110ba7319e9SDmitry Salychev { 111ba7319e9SDmitry Salychev device_t pdev = device_get_parent(dev); 112ba7319e9SDmitry Salychev device_t child = dev; 113ba7319e9SDmitry Salychev device_t mcp_dev; 114ba7319e9SDmitry Salychev struct dpaa2_con_softc *sc = device_get_softc(dev); 115ba7319e9SDmitry Salychev struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); 116ba7319e9SDmitry Salychev struct dpaa2_devinfo *dinfo = device_get_ivars(dev); 117ba7319e9SDmitry Salychev struct dpaa2_devinfo *mcp_dinfo; 118*4cd96614SDmitry Salychev struct dpaa2_cmd cmd; 119*4cd96614SDmitry Salychev uint16_t rc_token, con_token; 120ba7319e9SDmitry Salychev int error; 121ba7319e9SDmitry Salychev 122ba7319e9SDmitry Salychev sc->dev = dev; 123ba7319e9SDmitry Salychev 124ba7319e9SDmitry Salychev error = bus_alloc_resources(sc->dev, dpaa2_con_spec, sc->res); 125ba7319e9SDmitry Salychev if (error) { 126ba7319e9SDmitry Salychev device_printf(dev, "%s: failed to allocate resources: " 127ba7319e9SDmitry Salychev "error=%d\n", __func__, error); 128*4cd96614SDmitry Salychev goto err_exit; 129ba7319e9SDmitry Salychev } 130ba7319e9SDmitry Salychev 131ba7319e9SDmitry Salychev /* Obtain MC portal. */ 132ba7319e9SDmitry Salychev mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); 133ba7319e9SDmitry Salychev mcp_dinfo = device_get_ivars(mcp_dev); 134ba7319e9SDmitry Salychev dinfo->portal = mcp_dinfo->portal; 135ba7319e9SDmitry Salychev 136*4cd96614SDmitry Salychev DPAA2_CMD_INIT(&cmd); 137*4cd96614SDmitry Salychev 138*4cd96614SDmitry Salychev error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); 139ba7319e9SDmitry Salychev if (error) { 140*4cd96614SDmitry Salychev device_printf(dev, "%s: failed to open DPRC: error=%d\n", 141*4cd96614SDmitry Salychev __func__, error); 142ba7319e9SDmitry Salychev goto err_exit; 143ba7319e9SDmitry Salychev } 144*4cd96614SDmitry Salychev error = DPAA2_CMD_CON_OPEN(dev, child, &cmd, dinfo->id, &con_token); 145ba7319e9SDmitry Salychev if (error) { 146*4cd96614SDmitry Salychev device_printf(dev, "%s: failed to open DPCON: id=%d, error=%d\n", 147*4cd96614SDmitry Salychev __func__, dinfo->id, error); 148*4cd96614SDmitry Salychev goto close_rc; 149ba7319e9SDmitry Salychev } 150ba7319e9SDmitry Salychev 151*4cd96614SDmitry Salychev error = DPAA2_CMD_CON_RESET(dev, child, &cmd); 152ba7319e9SDmitry Salychev if (error) { 153*4cd96614SDmitry Salychev device_printf(dev, "%s: failed to reset DPCON: id=%d, " 154*4cd96614SDmitry Salychev "error=%d\n", __func__, dinfo->id, error); 155*4cd96614SDmitry Salychev goto close_con; 156ba7319e9SDmitry Salychev } 157*4cd96614SDmitry Salychev error = DPAA2_CMD_CON_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); 158ba7319e9SDmitry Salychev if (error) { 159*4cd96614SDmitry Salychev device_printf(dev, "%s: failed to get DPCON attributes: id=%d, " 160*4cd96614SDmitry Salychev "error=%d\n", __func__, dinfo->id, error); 161*4cd96614SDmitry Salychev goto close_con; 162ba7319e9SDmitry Salychev } 163ba7319e9SDmitry Salychev 164*4cd96614SDmitry Salychev if (bootverbose) { 165ba7319e9SDmitry Salychev device_printf(dev, "chan_id=%d, priorities=%d\n", 166ba7319e9SDmitry Salychev sc->attr.chan_id, sc->attr.prior_num); 167*4cd96614SDmitry Salychev } 168ba7319e9SDmitry Salychev 169*4cd96614SDmitry Salychev (void)DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); 170*4cd96614SDmitry Salychev (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); 171ba7319e9SDmitry Salychev return (0); 172ba7319e9SDmitry Salychev 173*4cd96614SDmitry Salychev close_con: 174*4cd96614SDmitry Salychev DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); 175*4cd96614SDmitry Salychev close_rc: 176*4cd96614SDmitry Salychev DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); 177ba7319e9SDmitry Salychev err_exit: 178ba7319e9SDmitry Salychev return (ENXIO); 179ba7319e9SDmitry Salychev } 180ba7319e9SDmitry Salychev 181ba7319e9SDmitry Salychev static device_method_t dpaa2_con_methods[] = { 182ba7319e9SDmitry Salychev /* Device interface */ 183ba7319e9SDmitry Salychev DEVMETHOD(device_probe, dpaa2_con_probe), 184ba7319e9SDmitry Salychev DEVMETHOD(device_attach, dpaa2_con_attach), 185ba7319e9SDmitry Salychev DEVMETHOD(device_detach, dpaa2_con_detach), 186ba7319e9SDmitry Salychev 187ba7319e9SDmitry Salychev DEVMETHOD_END 188ba7319e9SDmitry Salychev }; 189ba7319e9SDmitry Salychev 190ba7319e9SDmitry Salychev static driver_t dpaa2_con_driver = { 191ba7319e9SDmitry Salychev "dpaa2_con", 192ba7319e9SDmitry Salychev dpaa2_con_methods, 193ba7319e9SDmitry Salychev sizeof(struct dpaa2_con_softc), 194ba7319e9SDmitry Salychev }; 195ba7319e9SDmitry Salychev 196ba7319e9SDmitry Salychev DRIVER_MODULE(dpaa2_con, dpaa2_rc, dpaa2_con_driver, 0, 0); 197