The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/dpaa2/dpaa2_mc_fdt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause
    3  *
    4  * Copyright © 2021-2022 Dmitry Salychev
    5  * Copyright © 2022 Bjoern A. Zeeb
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 /*
   33  * The DPAA2 Management Complex (MC) Bus Driver (FDT-based).
   34  *
   35  * MC is a hardware resource manager which can be found in several NXP
   36  * SoCs (LX2160A, for example) and provides an access to the specialized
   37  * hardware objects used in network-oriented packet processing applications.
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/bus.h>
   43 #include <sys/rman.h>
   44 #include <sys/module.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mutex.h>
   47 
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 
   51 #include <dev/ofw/ofw_bus.h>
   52 #include <dev/ofw/ofw_bus_subr.h>
   53 #include <dev/fdt/simplebus.h>
   54 
   55 #include "pcib_if.h"
   56 #include "pci_if.h"
   57 #include "ofw_bus_if.h"
   58 
   59 #include "dpaa2_mcp.h"
   60 #include "dpaa2_mc.h"
   61 #include "dpaa2_mc_if.h"
   62 
   63 struct dpaa2_mac_fdt_softc {
   64         uint32_t                        reg;
   65         phandle_t                       sfp;
   66         phandle_t                       pcs_handle;
   67         phandle_t                       phy_handle;
   68         char                            managed[64];
   69         char                            phy_conn_type[64];
   70 };
   71 
   72 #if 0
   73         ethernet@1 {
   74 
   75                 compatible = "fsl,qoriq-mc-dpmac";
   76                 reg = <0x1>;
   77                 sfp = <0x14>;
   78                 pcs-handle = <0x15>;
   79                 phy-connection-type = "10gbase-r";
   80                 managed = "in-band-status";
   81         };
   82         ethernet@3 {
   83 
   84                 compatible = "fsl,qoriq-mc-dpmac";
   85                 reg = <0x3>;
   86                 phy-handle = <0x18>;
   87                 phy-connection-type = "qsgmii";
   88                 managed = "in-band-status";
   89                 pcs-handle = <0x19>;
   90         };
   91 #endif
   92 
   93 static int
   94 dpaa2_mac_dev_probe(device_t dev)
   95 {
   96         phandle_t node;
   97         uint64_t reg;
   98         ssize_t s;
   99 
  100         node = ofw_bus_get_node(dev);
  101         if (!ofw_bus_node_is_compatible(node, "fsl,qoriq-mc-dpmac")) {
  102                 device_printf(dev, "'%s' not fsl,qoriq-mc-dpmac compatible\n",
  103                     ofw_bus_get_name(dev));
  104                 return (ENXIO);
  105         }
  106 
  107         s = device_get_property(dev, "reg", &reg, sizeof(reg),
  108             DEVICE_PROP_UINT32);
  109         if (s == -1) {
  110                 device_printf(dev, "%s: '%s' has no 'reg' property, s %zd\n",
  111                     __func__, ofw_bus_get_name(dev), s);
  112                 return (ENXIO);
  113         }
  114 
  115         device_set_desc(dev, "DPAA2 MAC DEV");
  116         return (BUS_PROBE_DEFAULT);
  117 }
  118 
  119 static int
  120 dpaa2_mac_fdt_attach(device_t dev)
  121 {
  122         struct dpaa2_mac_fdt_softc *sc;
  123         phandle_t node;
  124         ssize_t s;
  125 
  126         sc = device_get_softc(dev);
  127         node = ofw_bus_get_node(dev);
  128 
  129         s = device_get_property(dev, "reg", &sc->reg, sizeof(sc->reg),
  130             DEVICE_PROP_UINT32);
  131         if (s == -1) {
  132                 device_printf(dev, "Cannot find 'reg' property: %zd\n", s);
  133                 return (ENXIO);
  134         }
  135 
  136         s = device_get_property(dev, "managed", sc->managed,
  137             sizeof(sc->managed), DEVICE_PROP_ANY);
  138         s = device_get_property(dev, "phy-connection-type", sc->phy_conn_type,
  139             sizeof(sc->phy_conn_type), DEVICE_PROP_ANY);
  140         s = device_get_property(dev, "pcs-handle", &sc->pcs_handle,
  141             sizeof(sc->pcs_handle), DEVICE_PROP_HANDLE);
  142 
  143         /* 'sfp' and 'phy-handle' are optional but we need one or the other. */
  144         s = device_get_property(dev, "sfp", &sc->sfp, sizeof(sc->sfp),
  145             DEVICE_PROP_HANDLE);
  146         s = device_get_property(dev, "phy-handle", &sc->phy_handle,
  147             sizeof(sc->phy_handle), DEVICE_PROP_HANDLE);
  148 
  149         if (bootverbose)
  150                 device_printf(dev, "node %#x '%s': reg %#x sfp %#x pcs-handle "
  151                     "%#x phy-handle %#x managed '%s' phy-conn-type '%s'\n",
  152                     node, ofw_bus_get_name(dev),
  153                     sc->reg, sc->sfp, sc->pcs_handle, sc->phy_handle,
  154                     sc->managed, sc->phy_conn_type);
  155 
  156         return (0);
  157 }
  158 
  159 static bool
  160 dpaa2_mac_fdt_match_id(device_t dev, uint32_t id)
  161 {
  162         struct dpaa2_mac_fdt_softc *sc;
  163 
  164         if (dev == NULL)
  165                 return (false);
  166 
  167         sc = device_get_softc(dev);
  168         if (sc->reg == id)
  169                 return (true);
  170 
  171         return (false);
  172 }
  173 
  174 static device_t
  175 dpaa2_mac_fdt_get_phy_dev(device_t dev)
  176 {
  177         struct dpaa2_mac_fdt_softc *sc;
  178 
  179         if (dev == NULL)
  180                 return (NULL);
  181 
  182         sc = device_get_softc(dev);
  183         if (sc->phy_handle == 0 && sc->sfp == 0)
  184                 return (NULL);
  185 
  186 #ifdef __not_yet__      /* No sff,sfp support yet. */
  187         if (sc->sfp != 0) {
  188                 device_t xdev;
  189 
  190                 xdev = OF_device_from_xref(OF_xref_from_node(sc->sfp));
  191                 if (xdev != NULL)
  192                         return (xdev);
  193         }
  194 #endif
  195         return (OF_device_from_xref(OF_xref_from_node(sc->phy_handle)));
  196 }
  197 
  198 static device_method_t dpaa2_mac_fdt_methods[] = {
  199         /* Device interface */
  200         DEVMETHOD(device_probe,         dpaa2_mac_dev_probe),
  201         DEVMETHOD(device_attach,        dpaa2_mac_fdt_attach),
  202         DEVMETHOD(device_detach,        bus_generic_detach),
  203 
  204         DEVMETHOD_END
  205 };
  206 
  207 DEFINE_CLASS_0(dpaa2_mac_fdt, dpaa2_mac_fdt_driver, dpaa2_mac_fdt_methods,
  208     sizeof(struct dpaa2_mac_fdt_softc));
  209 DRIVER_MODULE(dpaa2_mac_fdt, dpaa2_mc, dpaa2_mac_fdt_driver, 0, 0);
  210 MODULE_DEPEND(dpaa2_mac_fdt, memac_mdio_fdt, 1, 1, 1);
  211 
  212 /*
  213  * Device interface.
  214  */
  215 
  216 static int
  217 dpaa2_mc_fdt_probe(device_t dev)
  218 {
  219         if (!ofw_bus_status_okay(dev))
  220                 return (ENXIO);
  221 
  222         if (!ofw_bus_is_compatible(dev, "fsl,qoriq-mc"))
  223                 return (ENXIO);
  224 
  225         device_set_desc(dev, "DPAA2 Management Complex");
  226         return (BUS_PROBE_DEFAULT);
  227 }
  228 
  229 static int
  230 dpaa2_mc_fdt_probe_child(device_t bus, phandle_t child)
  231 {
  232         device_t childdev;
  233 
  234         /* make sure we do not aliready have a device. */
  235         childdev = ofw_bus_find_child_device_by_phandle(bus, child);
  236         if (childdev != NULL)
  237                 return (0);
  238 
  239         childdev = simplebus_add_device(bus, child, 0, "dpaa2_mac_fdt", -1,
  240             NULL);
  241         if (childdev == NULL)
  242                 return (ENXIO);
  243 
  244         return (device_probe_and_attach(childdev));
  245 }
  246 
  247 static int
  248 dpaa2_mc_fdt_attach(device_t dev)
  249 {
  250         struct dpaa2_mc_softc *sc;
  251         phandle_t node;
  252         phandle_t child;
  253 
  254         sc = device_get_softc(dev);
  255         sc->acpi_based = false;
  256         sc->ofw_node = ofw_bus_get_node(dev);
  257 
  258         bus_generic_probe(dev);
  259         bus_enumerate_hinted_children(dev);
  260 
  261         bus_generic_probe(dev);
  262         bus_enumerate_hinted_children(dev);
  263         /*
  264          * Attach the children represented in the device tree.
  265          */
  266         /* fsl-mc -> dpamcs */
  267         node = OF_child(sc->ofw_node);
  268         simplebus_init(dev, node);
  269 
  270         /* Attach the dpmac children represented in the device tree. */
  271         child = ofw_bus_find_compatible(node, "fsl,qoriq-mc-dpmac");
  272         for (; child > 0; child = OF_peer(child)) {
  273                 if (!ofw_bus_node_is_compatible(child, "fsl,qoriq-mc-dpmac"))
  274                         continue;
  275                 if (!OF_hasprop(child, "reg"))
  276                         continue;
  277                 if (!OF_hasprop(child, "pcs-handle"))
  278                         continue;
  279                 if (dpaa2_mc_fdt_probe_child(dev, child) != 0)
  280                         continue;
  281         }
  282 
  283         return (dpaa2_mc_attach(dev));
  284 }
  285 
  286 /*
  287  * FDT compat layer.
  288  */
  289 static device_t
  290 dpaa2_mc_fdt_find_dpaa2_mac_dev(device_t dev, uint32_t id)
  291 {
  292         int devcount, error, i, len;
  293         device_t *devlist, mdev;
  294         const char *mdevname;
  295 
  296         error = device_get_children(dev, &devlist, &devcount);
  297         if (error != 0)
  298                 return (NULL);
  299 
  300         for (i = 0; i < devcount; i++) {
  301                 mdev = devlist[i];
  302                 mdevname = device_get_name(mdev);
  303                 if (mdevname == NULL)
  304                         continue;
  305                 len = strlen(mdevname);
  306                 if (strncmp("dpaa2_mac_fdt", mdevname, len) != 0)
  307                         continue;
  308                 if (!device_is_attached(mdev))
  309                         continue;
  310 
  311                 if (dpaa2_mac_fdt_match_id(mdev, id))
  312                         return (mdev);
  313         }
  314 
  315         return (NULL);
  316 }
  317 
  318 static int
  319 dpaa2_mc_fdt_get_phy_dev(device_t dev, device_t *phy_dev, uint32_t id)
  320 {
  321         device_t mdev, pdev;
  322 
  323         mdev = dpaa2_mc_fdt_find_dpaa2_mac_dev(dev, id);
  324         if (mdev == NULL) {
  325                 device_printf(dev, "%s: error finding dpmac device with id=%u\n",
  326                     __func__, id);
  327                 return (ENXIO);
  328         }
  329 
  330         pdev = dpaa2_mac_fdt_get_phy_dev(mdev);
  331         if (pdev == NULL) {
  332                 device_printf(dev, "%s: error getting MDIO device for dpamc %s "
  333                     "(id=%u)\n", __func__, device_get_nameunit(mdev), id);
  334                 return (ENXIO);
  335         }
  336 
  337         if (phy_dev != NULL)
  338                 *phy_dev = pdev;
  339 
  340         if (bootverbose)
  341                 device_printf(dev, "dpmac_id %u mdev %p (%s) pdev %p (%s)\n",
  342                     id, mdev, device_get_nameunit(mdev),
  343                     pdev, device_get_nameunit(pdev));
  344 
  345         return (0);
  346 }
  347 
  348 static const struct ofw_bus_devinfo *
  349 dpaa2_mc_simplebus_get_devinfo(device_t bus, device_t child)
  350 {
  351 
  352         return (OFW_BUS_GET_DEVINFO(device_get_parent(bus), child));
  353 }
  354 
  355 static device_method_t dpaa2_mc_fdt_methods[] = {
  356         /* Device interface */
  357         DEVMETHOD(device_probe,         dpaa2_mc_fdt_probe),
  358         DEVMETHOD(device_attach,        dpaa2_mc_fdt_attach),
  359         DEVMETHOD(device_detach,        dpaa2_mc_detach),
  360 
  361         /* Bus interface */
  362         DEVMETHOD(bus_alloc_resource,   dpaa2_mc_alloc_resource),
  363         DEVMETHOD(bus_adjust_resource,  dpaa2_mc_adjust_resource),
  364         DEVMETHOD(bus_release_resource, dpaa2_mc_release_resource),
  365         DEVMETHOD(bus_activate_resource, dpaa2_mc_activate_resource),
  366         DEVMETHOD(bus_deactivate_resource, dpaa2_mc_deactivate_resource),
  367         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  368         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  369 
  370         /* Pseudo-PCIB interface */
  371         DEVMETHOD(pcib_alloc_msi,       dpaa2_mc_alloc_msi),
  372         DEVMETHOD(pcib_release_msi,     dpaa2_mc_release_msi),
  373         DEVMETHOD(pcib_map_msi,         dpaa2_mc_map_msi),
  374         DEVMETHOD(pcib_get_id,          dpaa2_mc_get_id),
  375 
  376         /* DPAA2 MC bus interface */
  377         DEVMETHOD(dpaa2_mc_manage_dev,  dpaa2_mc_manage_dev),
  378         DEVMETHOD(dpaa2_mc_get_free_dev,dpaa2_mc_get_free_dev),
  379         DEVMETHOD(dpaa2_mc_get_dev,     dpaa2_mc_get_dev),
  380         DEVMETHOD(dpaa2_mc_get_shared_dev, dpaa2_mc_get_shared_dev),
  381         DEVMETHOD(dpaa2_mc_reserve_dev, dpaa2_mc_reserve_dev),
  382         DEVMETHOD(dpaa2_mc_release_dev, dpaa2_mc_release_dev),
  383         DEVMETHOD(dpaa2_mc_get_phy_dev, dpaa2_mc_fdt_get_phy_dev),
  384 
  385         /* OFW/simplebus */
  386         DEVMETHOD(ofw_bus_get_devinfo,  dpaa2_mc_simplebus_get_devinfo),
  387         DEVMETHOD(ofw_bus_get_compat,   ofw_bus_gen_get_compat),
  388         DEVMETHOD(ofw_bus_get_model,    ofw_bus_gen_get_model),
  389         DEVMETHOD(ofw_bus_get_name,     ofw_bus_gen_get_name),
  390         DEVMETHOD(ofw_bus_get_node,     ofw_bus_gen_get_node),
  391         DEVMETHOD(ofw_bus_get_type,     ofw_bus_gen_get_type),
  392 
  393         DEVMETHOD_END
  394 };
  395 
  396 DEFINE_CLASS_1(dpaa2_mc, dpaa2_mc_fdt_driver, dpaa2_mc_fdt_methods,
  397     sizeof(struct dpaa2_mc_softc), dpaa2_mc_driver);
  398 
  399 DRIVER_MODULE(dpaa2_mc, simplebus, dpaa2_mc_fdt_driver, 0, 0);

Cache object: 6acf0746012897118ae7cb3bbc9bb5c3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.