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/arm64/coresight/coresight_tmc.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  * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * This software was developed by SRI International and the University of
    6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
    7  * ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/rman.h>
   38 #include <sys/kernel.h>
   39 #include <sys/module.h>
   40 #include <machine/bus.h>
   41 
   42 #include <arm64/coresight/coresight.h>
   43 #include <arm64/coresight/coresight_tmc.h>
   44 
   45 #include "coresight_if.h"
   46 
   47 #define TMC_DEBUG
   48 #undef TMC_DEBUG
   49         
   50 #ifdef TMC_DEBUG
   51 #define dprintf(fmt, ...)       printf(fmt, ##__VA_ARGS__)
   52 #else
   53 #define dprintf(fmt, ...)
   54 #endif
   55 
   56 static struct resource_spec tmc_spec[] = {
   57         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
   58         { -1, 0 }
   59 };
   60 
   61 static int
   62 tmc_start(device_t dev)
   63 {
   64         struct tmc_softc *sc;
   65         uint32_t reg;
   66 
   67         sc = device_get_softc(dev);
   68 
   69         if (bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN)
   70                 return (-1);
   71 
   72         /* Enable TMC */
   73         bus_write_4(sc->res, TMC_CTL, CTL_TRACECAPTEN);
   74         if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
   75                 panic("Not enabled\n");
   76 
   77         do {
   78                 reg = bus_read_4(sc->res, TMC_STS);
   79         } while ((reg & STS_TMCREADY) == 1);
   80 
   81         if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
   82                 panic("Not enabled\n");
   83 
   84         return (0);
   85 }
   86 
   87 static int
   88 tmc_stop(device_t dev)
   89 {
   90         struct tmc_softc *sc;
   91         uint32_t reg;
   92 
   93         sc = device_get_softc(dev);
   94 
   95         reg = bus_read_4(sc->res, TMC_CTL);
   96         reg &= ~CTL_TRACECAPTEN;
   97         bus_write_4(sc->res, TMC_CTL, reg);
   98 
   99         do {
  100                 reg = bus_read_4(sc->res, TMC_STS);
  101         } while ((reg & STS_TMCREADY) == 1);
  102 
  103         return (0);
  104 }
  105 
  106 static int
  107 tmc_configure_etf(device_t dev)
  108 {
  109         struct tmc_softc *sc;
  110         uint32_t reg;
  111 
  112         sc = device_get_softc(dev);
  113 
  114         do {
  115                 reg = bus_read_4(sc->res, TMC_STS);
  116         } while ((reg & STS_TMCREADY) == 0);
  117 
  118         bus_write_4(sc->res, TMC_MODE, MODE_HW_FIFO);
  119         bus_write_4(sc->res, TMC_FFCR, FFCR_EN_FMT | FFCR_EN_TI);
  120 
  121         tmc_start(dev);
  122 
  123         dprintf("%s: STS %x, CTL %x, RSZ %x, RRP %x, RWP %x, "
  124             "LBUFLEVEL %x, CBUFLEVEL %x\n", __func__,
  125             bus_read_4(sc->res, TMC_STS),
  126             bus_read_4(sc->res, TMC_CTL),
  127             bus_read_4(sc->res, TMC_RSZ),
  128             bus_read_4(sc->res, TMC_RRP),
  129             bus_read_4(sc->res, TMC_RWP),
  130             bus_read_4(sc->res, TMC_CBUFLEVEL),
  131             bus_read_4(sc->res, TMC_LBUFLEVEL));
  132 
  133         return (0);
  134 }
  135 
  136 static int
  137 tmc_configure_etr(device_t dev, struct endpoint *endp,
  138     struct coresight_event *event)
  139 {
  140         struct tmc_softc *sc;
  141         uint32_t reg;
  142 
  143         sc = device_get_softc(dev);
  144 
  145         tmc_stop(dev);
  146 
  147         do {
  148                 reg = bus_read_4(sc->res, TMC_STS);
  149         } while ((reg & STS_TMCREADY) == 0);
  150 
  151         /* Configure TMC */
  152         bus_write_4(sc->res, TMC_MODE, MODE_CIRCULAR_BUFFER);
  153 
  154         reg = AXICTL_PROT_CTRL_BIT1;
  155         reg |= AXICTL_WRBURSTLEN_16;
  156 
  157         /*
  158          * SG operation is broken on DragonBoard 410c
  159          * reg |= AXICTL_SG_MODE;
  160          */
  161 
  162         reg |= AXICTL_AXCACHE_OS;
  163         bus_write_4(sc->res, TMC_AXICTL, reg);
  164 
  165         reg = FFCR_EN_FMT | FFCR_EN_TI | FFCR_FON_FLIN |
  166             FFCR_FON_TRIG_EVT | FFCR_TRIGON_TRIGIN;
  167         bus_write_4(sc->res, TMC_FFCR, reg);
  168 
  169         bus_write_4(sc->res, TMC_TRG, 8);
  170 
  171         bus_write_4(sc->res, TMC_DBALO, event->etr.low);
  172         bus_write_4(sc->res, TMC_DBAHI, event->etr.high);
  173         bus_write_4(sc->res, TMC_RSZ, event->etr.bufsize / 4);
  174 
  175         bus_write_4(sc->res, TMC_RRP, event->etr.low);
  176         bus_write_4(sc->res, TMC_RWP, event->etr.low);
  177 
  178         reg = bus_read_4(sc->res, TMC_STS);
  179         reg &= ~STS_FULL;
  180         bus_write_4(sc->res, TMC_STS, reg);
  181 
  182         tmc_start(dev);
  183 
  184         return (0);
  185 }
  186 
  187 static int
  188 tmc_init(device_t dev)
  189 {
  190         struct tmc_softc *sc;
  191         uint32_t reg;
  192 
  193         sc = device_get_softc(dev);
  194 
  195         /* Unlock Coresight */
  196         bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK);
  197 
  198         /* Unlock TMC */
  199         bus_write_4(sc->res, TMC_LAR, CORESIGHT_UNLOCK);
  200 
  201         reg = bus_read_4(sc->res, TMC_DEVID);
  202         reg &= DEVID_CONFIGTYPE_M;
  203         switch (reg) {
  204         case DEVID_CONFIGTYPE_ETR:
  205                 sc->dev_type = CORESIGHT_ETR;
  206                 dprintf(dev, "ETR configuration found\n");
  207                 break;
  208         case DEVID_CONFIGTYPE_ETF:
  209                 sc->dev_type = CORESIGHT_ETF;
  210                 dprintf(dev, "ETF configuration found\n");
  211                 if (sc->etf_configured == false) {
  212                         tmc_configure_etf(dev);
  213                         sc->etf_configured = true;
  214                 }
  215                 break;
  216         default:
  217                 sc->dev_type = CORESIGHT_UNKNOWN;
  218                 break;
  219         }
  220 
  221         return (0);
  222 }
  223 
  224 static int
  225 tmc_enable(device_t dev, struct endpoint *endp,
  226     struct coresight_event *event)
  227 {
  228         struct tmc_softc *sc;
  229         uint32_t nev;
  230 
  231         sc = device_get_softc(dev);
  232 
  233         if (sc->dev_type == CORESIGHT_ETF)
  234                 return (0);
  235 
  236         KASSERT(sc->dev_type == CORESIGHT_ETR,
  237             ("Wrong dev_type"));
  238 
  239         /*
  240          * Multiple CPUs can call this same time.
  241          * We allow only one running configuration.
  242          */
  243 
  244         if (event->etr.flags & ETR_FLAG_ALLOCATE) {
  245                 event->etr.flags &= ~ETR_FLAG_ALLOCATE;
  246                 nev = atomic_fetchadd_int(&sc->nev, 1);
  247                 if (nev == 0) {
  248                         sc->event = event;
  249                         tmc_stop(dev);
  250                         tmc_configure_etr(dev, endp, event);
  251                         tmc_start(dev);
  252                 }
  253         }
  254 
  255         return (0);
  256 }
  257 
  258 static void
  259 tmc_disable(device_t dev, struct endpoint *endp,
  260     struct coresight_event *event)
  261 {
  262         struct tmc_softc *sc;
  263         uint32_t nev;
  264 
  265         sc = device_get_softc(dev);
  266 
  267         /* ETF configuration is static */
  268         if (sc->dev_type == CORESIGHT_ETF)
  269                 return;
  270 
  271         KASSERT(sc->dev_type == CORESIGHT_ETR, ("Wrong dev_type"));
  272 
  273         if (event->etr.flags & ETR_FLAG_RELEASE) {
  274                 event->etr.flags &= ~ETR_FLAG_RELEASE;
  275                 nev = atomic_fetchadd_int(&sc->nev, -1);
  276                 if (nev == 1) {
  277                         tmc_stop(dev);
  278                         sc->event = NULL;
  279                 }
  280         }
  281 }
  282 
  283 static int
  284 tmc_read(device_t dev, struct endpoint *endp,
  285     struct coresight_event *event)
  286 {
  287         struct tmc_softc *sc;
  288         uint32_t cur_ptr;
  289 
  290         sc = device_get_softc(dev);
  291 
  292         if (sc->dev_type == CORESIGHT_ETF)
  293                 return (0);
  294 
  295         /*
  296          * Ensure the event we are reading information for
  297          * is currently configured one.
  298          */
  299         if (sc->event != event)
  300                 return (0);
  301 
  302         if (bus_read_4(sc->res, TMC_STS) & STS_FULL) {
  303                 event->etr.offset = 0;
  304                 event->etr.cycle++;
  305                 tmc_stop(dev);
  306                 tmc_start(dev);
  307         } else {
  308                 cur_ptr = bus_read_4(sc->res, TMC_RWP);
  309                 event->etr.offset = (cur_ptr - event->etr.low);
  310         }
  311 
  312         return (0);
  313 }
  314 
  315 int
  316 tmc_attach(device_t dev)
  317 {
  318         struct coresight_desc desc;
  319         struct tmc_softc *sc;
  320 
  321         sc = device_get_softc(dev);
  322         sc->dev = dev;
  323 
  324         if (bus_alloc_resources(dev, tmc_spec, &sc->res) != 0) {
  325                 device_printf(dev, "cannot allocate resources for device\n");
  326                 return (ENXIO);
  327         }
  328 
  329         desc.pdata = sc->pdata;
  330         desc.dev = dev;
  331         desc.dev_type = CORESIGHT_TMC;
  332         coresight_register(&desc);
  333 
  334         return (0);
  335 }
  336 
  337 static device_method_t tmc_methods[] = {
  338         /* Device interface */
  339         DEVMETHOD(device_attach,        tmc_attach),
  340 
  341         /* Coresight interface */
  342         DEVMETHOD(coresight_init,       tmc_init),
  343         DEVMETHOD(coresight_enable,     tmc_enable),
  344         DEVMETHOD(coresight_disable,    tmc_disable),
  345         DEVMETHOD(coresight_read,       tmc_read),
  346         DEVMETHOD_END
  347 };
  348 
  349 DEFINE_CLASS_0(tmc, tmc_driver, tmc_methods, sizeof(struct tmc_softc));

Cache object: 6a8c27ddef4d2851855d87edde75e6c8


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