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/memac_mdio_acpi.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 Bjoern A. Zeeb
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bus.h>
   34 #include <sys/rman.h>
   35 #include <sys/malloc.h>
   36 #include <sys/module.h>
   37 #include <sys/endian.h>
   38 #include <sys/socket.h>
   39 
   40 #include <machine/bus.h>
   41 #include <machine/resource.h>
   42 
   43 #include <contrib/dev/acpica/include/acpi.h>
   44 #include <dev/acpica/acpivar.h>
   45 
   46 #include <net/if.h>
   47 #include <net/if_var.h>
   48 #include <net/if_media.h>
   49 
   50 #include <dev/mii/mii.h>
   51 #include <dev/mii/miivar.h>
   52 
   53 #include "memac_mdio.h"
   54 #include "memac_mdio_if.h"
   55 #include "acpi_bus_if.h"
   56 #include "miibus_if.h"
   57 
   58 /* -------------------------------------------------------------------------- */
   59 
   60 struct memacphy_softc_acpi {
   61         struct memacphy_softc_common    scc;
   62         int                             uid;
   63         uint64_t                        phy_channel;
   64         char                            compatible[64];
   65 };
   66 
   67 static void
   68 memacphy_acpi_miibus_statchg(device_t dev)
   69 {
   70         struct memacphy_softc_acpi *sc;
   71 
   72         sc = device_get_softc(dev);
   73         memacphy_miibus_statchg(&sc->scc);
   74 }
   75 
   76 static int
   77 memacphy_acpi_set_ni_dev(device_t dev, device_t nidev)
   78 {
   79         struct memacphy_softc_acpi *sc;
   80 
   81         sc = device_get_softc(dev);
   82         return (memacphy_set_ni_dev(&sc->scc, nidev));
   83 }
   84 
   85 static int
   86 memacphy_acpi_get_phy_loc(device_t dev, int *phy_loc)
   87 {
   88         struct memacphy_softc_acpi *sc;
   89 
   90         sc = device_get_softc(dev);
   91         return (memacphy_get_phy_loc(&sc->scc, phy_loc));
   92 }
   93 
   94 static int
   95 memacphy_acpi_probe(device_t dev)
   96 {
   97 
   98         device_set_desc(dev, "MEMAC PHY (acpi)");
   99         return (BUS_PROBE_DEFAULT);
  100 }
  101 
  102 static int
  103 memacphy_acpi_attach(device_t dev)
  104 {
  105         struct memacphy_softc_acpi *sc;
  106         ACPI_HANDLE h;
  107         ssize_t s;
  108 
  109         sc = device_get_softc(dev);
  110         sc->scc.dev = dev;
  111         h = acpi_get_handle(dev);
  112 
  113         s = acpi_GetInteger(h, "_UID", &sc->uid);
  114         if (ACPI_FAILURE(s)) {
  115                 device_printf(dev, "Cannot get '_UID' property: %zd\n", s);
  116                 return (ENXIO);
  117         }
  118 
  119         s = device_get_property(dev, "phy-channel",
  120             &sc->phy_channel, sizeof(sc->phy_channel), DEVICE_PROP_UINT64);
  121         if (s != -1)
  122                 sc->scc.phy = sc->phy_channel;
  123         else
  124                 sc->scc.phy = -1;
  125         s = device_get_property(dev, "compatible",
  126             sc->compatible, sizeof(sc->compatible), DEVICE_PROP_ANY);
  127 
  128         if (bootverbose)
  129                 device_printf(dev, "UID %#04x phy-channel %ju compatible '%s' phy %u\n",
  130                     sc->uid, sc->phy_channel,
  131                     sc->compatible[0] != '\0' ? sc->compatible : "", sc->scc.phy);
  132 
  133         if (sc->scc.phy == -1)
  134                 return (ENXIO);
  135         return (0);
  136 }
  137 
  138 static device_method_t memacphy_acpi_methods[] = {
  139         /* Device interface */
  140         DEVMETHOD(device_probe,         memacphy_acpi_probe),
  141         DEVMETHOD(device_attach,        memacphy_acpi_attach),
  142         DEVMETHOD(device_detach,        bus_generic_detach),
  143 
  144         /* MII interface */
  145         DEVMETHOD(miibus_readreg,       memacphy_miibus_readreg),
  146         DEVMETHOD(miibus_writereg,      memacphy_miibus_writereg),
  147         DEVMETHOD(miibus_statchg,       memacphy_acpi_miibus_statchg),
  148 
  149         /* memac */
  150         DEVMETHOD(memac_mdio_set_ni_dev, memacphy_acpi_set_ni_dev),
  151         DEVMETHOD(memac_mdio_get_phy_loc, memacphy_acpi_get_phy_loc),
  152 
  153         DEVMETHOD_END
  154 };
  155 
  156 DEFINE_CLASS_0(memacphy_acpi, memacphy_acpi_driver, memacphy_acpi_methods,
  157     sizeof(struct memacphy_softc_acpi));
  158 
  159 EARLY_DRIVER_MODULE(memacphy_acpi, memac_mdio_acpi, memacphy_acpi_driver, 0, 0,
  160     BUS_PASS_SUPPORTDEV);
  161 DRIVER_MODULE(miibus, memacphy_acpi, miibus_driver, 0, 0);
  162 MODULE_DEPEND(memacphy_acpi, miibus, 1, 1, 1);
  163 
  164 /* -------------------------------------------------------------------------- */
  165 
  166 struct memac_mdio_softc_acpi {
  167         struct memac_mdio_softc_common  scc;
  168 };
  169 
  170 static int
  171 memac_acpi_miibus_readreg(device_t dev, int phy, int reg)
  172 {
  173         struct memac_mdio_softc_acpi *sc;
  174 
  175         sc = device_get_softc(dev);
  176         return (memac_miibus_readreg(&sc->scc, phy, reg));
  177 }
  178 
  179 static int
  180 memac_acpi_miibus_writereg(device_t dev, int phy, int reg, int data)
  181 {
  182         struct memac_mdio_softc_acpi *sc;
  183 
  184         sc = device_get_softc(dev);
  185         return (memac_miibus_writereg(&sc->scc, phy, reg, data));
  186 }
  187 
  188 /* Context for walking PHY child devices. */
  189 struct memac_mdio_walk_ctx {
  190         device_t        dev;
  191         int             count;
  192         int             countok;
  193 };
  194 
  195 static char *memac_mdio_ids[] = {
  196         "NXP0006",
  197         NULL
  198 };
  199 
  200 static int
  201 memac_mdio_acpi_probe(device_t dev)
  202 {
  203         int rc;
  204 
  205         if (acpi_disabled("fsl_memac_mdio"))
  206                 return (ENXIO);
  207 
  208         rc = ACPI_ID_PROBE(device_get_parent(dev), dev, memac_mdio_ids, NULL);
  209         if (rc <= 0)
  210                 device_set_desc(dev, "Freescale XGMAC MDIO Bus");
  211 
  212         return (rc);
  213 }
  214 
  215 static ACPI_STATUS
  216 memac_mdio_acpi_probe_child(ACPI_HANDLE h, device_t *dev, int level, void *arg)
  217 {
  218         struct memac_mdio_walk_ctx *ctx;
  219         struct acpi_device *ad;
  220         device_t child;
  221         uint32_t adr;
  222 
  223         ctx = (struct memac_mdio_walk_ctx *)arg;
  224         ctx->count++;
  225 
  226         if (ACPI_FAILURE(acpi_GetInteger(h, "_ADR", &adr)))
  227                 return (AE_OK);
  228 
  229         /* Technically M_ACPIDEV */
  230         if ((ad = malloc(sizeof(*ad), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL)
  231                 return (AE_OK);
  232 
  233         child = device_add_child(ctx->dev, "memacphy_acpi", -1);
  234         if (child == NULL) {
  235                 free(ad, M_DEVBUF);
  236                 return (AE_OK);
  237         }
  238         ad->ad_handle = h;
  239         ad->ad_cls_class = 0xffffff;
  240         resource_list_init(&ad->ad_rl);
  241         device_set_ivars(child, ad);
  242         *dev = child;
  243 
  244         ctx->countok++;
  245         return (AE_OK);
  246 }
  247 
  248 static int
  249 memac_mdio_acpi_attach(device_t dev)
  250 {
  251         struct memac_mdio_softc_acpi *sc;
  252         struct memac_mdio_walk_ctx ctx;
  253         int error;
  254 
  255         sc = device_get_softc(dev);
  256         sc->scc.dev = dev;
  257 
  258         error = memac_mdio_generic_attach(&sc->scc);
  259         if (error != 0)
  260                 return (error);
  261 
  262         ctx.dev = dev;
  263         ctx.count = 0;
  264         ctx.countok = 0;
  265         ACPI_SCAN_CHILDREN(device_get_parent(dev), dev, 1,
  266             memac_mdio_acpi_probe_child, &ctx);
  267         if (ctx.countok > 0) {
  268                 bus_generic_probe(dev);
  269                 bus_generic_attach(dev);
  270         }
  271 
  272         return (0);
  273 }
  274 
  275 static int
  276 memac_mdio_acpi_detach(device_t dev)
  277 {
  278         struct memac_mdio_softc_acpi *sc;
  279 
  280         sc = device_get_softc(dev);
  281         return (memac_mdio_generic_detach(&sc->scc));
  282 }
  283 
  284 static device_method_t memac_mdio_acpi_methods[] = {
  285         /* Device interface */
  286         DEVMETHOD(device_probe,         memac_mdio_acpi_probe),
  287         DEVMETHOD(device_attach,        memac_mdio_acpi_attach),
  288         DEVMETHOD(device_detach,        memac_mdio_acpi_detach),
  289 
  290         /* MII interface */
  291         DEVMETHOD(miibus_readreg,       memac_acpi_miibus_readreg),
  292         DEVMETHOD(miibus_writereg,      memac_acpi_miibus_writereg),
  293 
  294         /* .. */
  295         DEVMETHOD(bus_add_child,        bus_generic_add_child),
  296         DEVMETHOD(bus_read_ivar,        memac_mdio_read_ivar),
  297         DEVMETHOD(bus_get_property,     memac_mdio_get_property),
  298 
  299         DEVMETHOD_END
  300 };
  301 
  302 DEFINE_CLASS_0(memac_mdio_acpi, memac_mdio_acpi_driver, memac_mdio_acpi_methods,
  303     sizeof(struct memac_mdio_softc_acpi));
  304 
  305 EARLY_DRIVER_MODULE(memac_mdio_acpi, acpi, memac_mdio_acpi_driver, 0, 0,
  306     BUS_PASS_SUPPORTDEV);
  307 
  308 DRIVER_MODULE(miibus, memac_mdio_acpi, miibus_driver, 0, 0);
  309 MODULE_DEPEND(memac_mdio_acpi, miibus, 1, 1, 1);
  310 MODULE_VERSION(memac_mdio_acpi, 1);

Cache object: ea4255e4a25b4fe094d3fcb23ed1fd07


[ 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.