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/arm/altera/socfpga/socfpga_a10_manager.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) 2017 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 /*
   32  * Intel Arria 10 FPGA Manager.
   33  * Chapter 4, Arria 10 Hard Processor System Technical Reference Manual.
   34  * Chapter A, FPGA Reconfiguration.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/bus.h>
   43 #include <sys/kernel.h>
   44 #include <sys/module.h>
   45 #include <sys/malloc.h>
   46 #include <sys/rman.h>
   47 #include <sys/timeet.h>
   48 #include <sys/timetc.h>
   49 #include <sys/conf.h>
   50 #include <sys/uio.h>
   51 
   52 #include <dev/ofw/openfirm.h>
   53 #include <dev/ofw/ofw_bus.h>
   54 #include <dev/ofw/ofw_bus_subr.h>
   55 
   56 #include <machine/bus.h>
   57 #include <machine/cpu.h>
   58 #include <machine/intr.h>
   59 
   60 #include <arm/altera/socfpga/socfpga_common.h>
   61 
   62 #define FPGAMGR_DCLKCNT                 0x8     /* DCLK Count Register */
   63 #define FPGAMGR_DCLKSTAT                0xC     /* DCLK Status Register */
   64 #define FPGAMGR_GPO                     0x10    /* General-Purpose Output Register */
   65 #define FPGAMGR_GPI                     0x14    /* General-Purpose Input Register */
   66 #define FPGAMGR_MISCI                   0x18    /* Miscellaneous Input Register */
   67 #define IMGCFG_CTRL_00                  0x70
   68 #define  S2F_CONDONE_OE                 (1 << 24)
   69 #define  S2F_NSTATUS_OE                 (1 << 16)
   70 #define  CTRL_00_NCONFIG                (1 << 8)
   71 #define  CTRL_00_NENABLE_CONDONE        (1 << 2)
   72 #define  CTRL_00_NENABLE_NSTATUS        (1 << 1)
   73 #define  CTRL_00_NENABLE_NCONFIG        (1 << 0)
   74 #define IMGCFG_CTRL_01                  0x74
   75 #define  CTRL_01_S2F_NCE                (1 << 24)
   76 #define  CTRL_01_S2F_PR_REQUEST         (1 << 16)
   77 #define  CTRL_01_S2F_NENABLE_CONFIG     (1 << 0)
   78 #define IMGCFG_CTRL_02                  0x78
   79 #define  CTRL_02_CDRATIO_S              16
   80 #define  CTRL_02_CDRATIO_M              (0x3 << CTRL_02_CDRATIO_S)
   81 #define  CTRL_02_CFGWIDTH_16            (0 << 24)
   82 #define  CTRL_02_CFGWIDTH_32            (1 << 24)
   83 #define  CTRL_02_EN_CFG_DATA            (1 << 8)
   84 #define  CTRL_02_EN_CFG_CTRL            (1 << 0)
   85 #define IMGCFG_STAT                     0x80
   86 #define  F2S_PR_ERROR                   (1 << 11)
   87 #define  F2S_PR_DONE                    (1 << 10)
   88 #define  F2S_PR_READY                   (1 << 9)
   89 #define  F2S_MSEL_S                     16
   90 #define  F2S_MSEL_M                     (0x7 << F2S_MSEL_S)
   91 #define  MSEL_PASSIVE_FAST              0
   92 #define  MSEL_PASSIVE_SLOW              1
   93 #define  F2S_NCONFIG_PIN                (1 << 12)
   94 #define  F2S_CONDONE_OE                 (1 << 7)
   95 #define  F2S_NSTATUS_PIN                (1 << 4)
   96 #define  F2S_CONDONE_PIN                (1 << 6)
   97 #define  F2S_USERMODE                   (1 << 2)
   98 
   99 struct fpgamgr_a10_softc {
  100         struct resource         *res[2];
  101         bus_space_tag_t         bst_data;
  102         bus_space_handle_t      bsh_data;
  103         struct cdev             *mgr_cdev;
  104         device_t                dev;
  105 };
  106 
  107 static struct resource_spec fpgamgr_a10_spec[] = {
  108         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  109         { SYS_RES_MEMORY,       1,      RF_ACTIVE },
  110         { -1, 0 }
  111 };
  112 
  113 static int
  114 fpga_wait_dclk_pulses(struct fpgamgr_a10_softc *sc, int npulses)
  115 {
  116         int tout;
  117 
  118         /* Clear done bit, if any */
  119         if (READ4(sc, FPGAMGR_DCLKSTAT) != 0)
  120                 WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
  121 
  122         /* Request DCLK pulses */
  123         WRITE4(sc, FPGAMGR_DCLKCNT, npulses);
  124 
  125         /* Wait finish */
  126         tout = 1000;
  127         while (tout > 0) {
  128                 if (READ4(sc, FPGAMGR_DCLKSTAT) == 1) {
  129                         WRITE4(sc, FPGAMGR_DCLKSTAT, 0x1);
  130                         break;
  131                 }
  132                 tout--;
  133                 DELAY(10);
  134         }
  135         if (tout == 0) {
  136                 device_printf(sc->dev,
  137                     "Error: dclkpulses wait timeout\n");
  138                 return (1);
  139         }
  140 
  141         return (0);
  142 }
  143 
  144 static int
  145 fpga_open(struct cdev *dev, int flags __unused,
  146     int fmt __unused, struct thread *td __unused)
  147 {
  148         struct fpgamgr_a10_softc *sc;
  149         int tout;
  150         int msel;
  151         int reg;
  152 
  153         sc = dev->si_drv1;
  154 
  155         /* Step 1 */
  156         reg = READ4(sc, IMGCFG_STAT);
  157         if ((reg & F2S_USERMODE) == 0) {
  158                 device_printf(sc->dev, "Error: invalid mode\n");
  159                 return (ENXIO);
  160         };
  161 
  162         /* Step 2 */
  163         reg = READ4(sc, IMGCFG_STAT);
  164         msel = (reg & F2S_MSEL_M) >> F2S_MSEL_S;
  165         if ((msel != MSEL_PASSIVE_FAST) && \
  166             (msel != MSEL_PASSIVE_SLOW)) {
  167                 device_printf(sc->dev,
  168                     "Error: invalid msel %d\n", msel);
  169                 return (ENXIO);
  170         };
  171 
  172         /*
  173          * Step 3.
  174          * TODO: add support for compressed, encrypted images.
  175          */
  176         reg = READ4(sc, IMGCFG_CTRL_02);
  177         reg &= ~(CTRL_02_CDRATIO_M);
  178         WRITE4(sc, IMGCFG_CTRL_02, reg);
  179 
  180         reg = READ4(sc, IMGCFG_CTRL_02);
  181         reg &= ~CTRL_02_CFGWIDTH_32;
  182         WRITE4(sc, IMGCFG_CTRL_02, reg);
  183 
  184         /* Step 4. a */
  185         reg = READ4(sc, IMGCFG_CTRL_01);
  186         reg &= ~CTRL_01_S2F_PR_REQUEST;
  187         WRITE4(sc, IMGCFG_CTRL_01, reg);
  188 
  189         reg = READ4(sc, IMGCFG_CTRL_00);
  190         reg |= CTRL_00_NCONFIG;
  191         WRITE4(sc, IMGCFG_CTRL_00, reg);
  192 
  193         /* b */
  194         reg = READ4(sc, IMGCFG_CTRL_01);
  195         reg &= ~CTRL_01_S2F_NCE;
  196         WRITE4(sc, IMGCFG_CTRL_01, reg);
  197 
  198         /* c */
  199         reg = READ4(sc, IMGCFG_CTRL_02);
  200         reg |= CTRL_02_EN_CFG_CTRL;
  201         WRITE4(sc, IMGCFG_CTRL_02, reg);
  202 
  203         /* d */
  204         reg = READ4(sc, IMGCFG_CTRL_00);
  205         reg &= ~S2F_CONDONE_OE;
  206         reg &= ~S2F_NSTATUS_OE;
  207         reg |= CTRL_00_NCONFIG;
  208         reg |= CTRL_00_NENABLE_NSTATUS;
  209         reg |= CTRL_00_NENABLE_CONDONE;
  210         reg &= ~CTRL_00_NENABLE_NCONFIG;
  211         WRITE4(sc, IMGCFG_CTRL_00, reg);
  212 
  213         /* Step 5 */
  214         reg = READ4(sc, IMGCFG_CTRL_01);
  215         reg &= ~CTRL_01_S2F_NENABLE_CONFIG;
  216         WRITE4(sc, IMGCFG_CTRL_01, reg);
  217 
  218         /* Step 6 */
  219         fpga_wait_dclk_pulses(sc, 0x100);
  220 
  221         /* Step 7. a */
  222         reg = READ4(sc, IMGCFG_CTRL_01);
  223         reg |= CTRL_01_S2F_PR_REQUEST;
  224         WRITE4(sc, IMGCFG_CTRL_01, reg);
  225 
  226         /* b, c */
  227         fpga_wait_dclk_pulses(sc, 0x7ff);
  228 
  229         /* Step 8 */
  230         tout = 10;
  231         while (tout--) {
  232                 reg = READ4(sc, IMGCFG_STAT);
  233                 if (reg & F2S_PR_ERROR) {
  234                         device_printf(sc->dev,
  235                             "Error: PR failed on open.\n");
  236                         return (ENXIO);
  237                 }
  238                 if (reg & F2S_PR_READY) {
  239                         break;
  240                 }
  241         }
  242         if (tout == 0) {
  243                 device_printf(sc->dev,
  244                     "Error: Timeout waiting PR ready bit.\n");
  245                 return (ENXIO);
  246         }
  247 
  248         return (0);
  249 }
  250 
  251 static int
  252 fpga_close(struct cdev *dev, int flags __unused,
  253     int fmt __unused, struct thread *td __unused)
  254 {
  255         struct fpgamgr_a10_softc *sc;
  256         int tout;
  257         int reg;
  258 
  259         sc = dev->si_drv1;
  260 
  261         /* Step 10 */
  262         tout = 10;
  263         while (tout--) {
  264                 reg = READ4(sc, IMGCFG_STAT);
  265                 if (reg & F2S_PR_ERROR) {
  266                         device_printf(sc->dev,
  267                             "Error: PR failed.\n");
  268                         return (ENXIO);
  269                 }
  270                 if (reg & F2S_PR_DONE) {
  271                         break;
  272                 }
  273         }
  274 
  275         /* Step 11 */
  276         reg = READ4(sc, IMGCFG_CTRL_01);
  277         reg &= ~CTRL_01_S2F_PR_REQUEST;
  278         WRITE4(sc, IMGCFG_CTRL_01, reg);
  279 
  280         /* Step 12, 13 */
  281         fpga_wait_dclk_pulses(sc, 0x100);
  282 
  283         /* Step 14 */
  284         reg = READ4(sc, IMGCFG_CTRL_02);
  285         reg &= ~CTRL_02_EN_CFG_CTRL;
  286         WRITE4(sc, IMGCFG_CTRL_02, reg);
  287 
  288         /* Step 15 */
  289         reg = READ4(sc, IMGCFG_CTRL_01);
  290         reg |= CTRL_01_S2F_NCE;
  291         WRITE4(sc, IMGCFG_CTRL_01, reg);
  292 
  293         /* Step 16 */
  294         reg = READ4(sc, IMGCFG_CTRL_01);
  295         reg |= CTRL_01_S2F_NENABLE_CONFIG;
  296         WRITE4(sc, IMGCFG_CTRL_01, reg);
  297 
  298         /* Step 17 */
  299         reg = READ4(sc, IMGCFG_STAT);
  300         if ((reg & F2S_USERMODE) == 0) {
  301                 device_printf(sc->dev,
  302                     "Error: invalid mode\n");
  303                 return (ENXIO);
  304         };
  305 
  306         if ((reg & F2S_CONDONE_PIN) == 0) {
  307                 device_printf(sc->dev,
  308                     "Error: configuration not done\n");
  309                 return (ENXIO);
  310         };
  311 
  312         if ((reg & F2S_NSTATUS_PIN) == 0) {
  313                 device_printf(sc->dev,
  314                     "Error: nstatus pin\n");
  315                 return (ENXIO);
  316         };
  317 
  318         return (0);
  319 }
  320 
  321 static int
  322 fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
  323 {
  324         struct fpgamgr_a10_softc *sc;
  325         uint32_t buffer;
  326 
  327         sc = dev->si_drv1;
  328 
  329         /*
  330          * Step 9.
  331          * Device supports 4-byte writes only.
  332          */
  333 
  334         while (uio->uio_resid >= 4) {
  335                 uiomove(&buffer, 4, uio);
  336                 bus_space_write_4(sc->bst_data, sc->bsh_data,
  337                     0x0, buffer);
  338         }
  339 
  340         switch (uio->uio_resid) {
  341         case 3:
  342                 uiomove(&buffer, 3, uio);
  343                 buffer &= 0xffffff;
  344                 bus_space_write_4(sc->bst_data, sc->bsh_data,
  345                     0x0, buffer);
  346                 break;
  347         case 2:
  348                 uiomove(&buffer, 2, uio);
  349                 buffer &= 0xffff;
  350                 bus_space_write_4(sc->bst_data, sc->bsh_data,
  351                     0x0, buffer);
  352                 break;
  353         case 1:
  354                 uiomove(&buffer, 1, uio);
  355                 buffer &= 0xff;
  356                 bus_space_write_4(sc->bst_data, sc->bsh_data,
  357                     0x0, buffer);
  358                 break;
  359         default:
  360                 break;
  361         };
  362 
  363         return (0);
  364 }
  365 
  366 static int
  367 fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
  368     struct thread *td)
  369 {
  370 
  371         return (0);
  372 }
  373 
  374 static struct cdevsw fpga_cdevsw = {
  375         .d_version =    D_VERSION,
  376         .d_open =       fpga_open,
  377         .d_close =      fpga_close,
  378         .d_write =      fpga_write,
  379         .d_ioctl =      fpga_ioctl,
  380         .d_name =       "FPGA Manager",
  381 };
  382 
  383 static int
  384 fpgamgr_a10_probe(device_t dev)
  385 {
  386 
  387         if (!ofw_bus_status_okay(dev))
  388                 return (ENXIO);
  389 
  390         if (!ofw_bus_is_compatible(dev, "altr,socfpga-a10-fpga-mgr"))
  391                 return (ENXIO);
  392 
  393         device_set_desc(dev, "Arria 10 FPGA Manager");
  394 
  395         return (BUS_PROBE_DEFAULT);
  396 }
  397 
  398 static int
  399 fpgamgr_a10_attach(device_t dev)
  400 {
  401         struct fpgamgr_a10_softc *sc;
  402 
  403         sc = device_get_softc(dev);
  404         sc->dev = dev;
  405 
  406         if (bus_alloc_resources(dev, fpgamgr_a10_spec, sc->res)) {
  407                 device_printf(dev, "Could not allocate resources.\n");
  408                 return (ENXIO);
  409         }
  410 
  411         /* Memory interface */
  412         sc->bst_data = rman_get_bustag(sc->res[1]);
  413         sc->bsh_data = rman_get_bushandle(sc->res[1]);
  414 
  415         sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
  416             0600, "fpga%d", device_get_unit(sc->dev));
  417 
  418         if (sc->mgr_cdev == NULL) {
  419                 device_printf(dev, "Failed to create character device.\n");
  420                 return (ENXIO);
  421         }
  422 
  423         sc->mgr_cdev->si_drv1 = sc;
  424 
  425         return (0);
  426 }
  427 
  428 static device_method_t fpgamgr_a10_methods[] = {
  429         DEVMETHOD(device_probe,         fpgamgr_a10_probe),
  430         DEVMETHOD(device_attach,        fpgamgr_a10_attach),
  431         { 0, 0 }
  432 };
  433 
  434 static driver_t fpgamgr_a10_driver = {
  435         "fpgamgr_a10",
  436         fpgamgr_a10_methods,
  437         sizeof(struct fpgamgr_a10_softc),
  438 };
  439 
  440 DRIVER_MODULE(fpgamgr_a10, simplebus, fpgamgr_a10_driver, 0, 0);

Cache object: fc3b4af003e11dd62a5cd44062c92fc4


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