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/ti/am335x/am335x_dmtpps.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) 2015 Ian lepore <ian@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * AM335x PPS driver using DMTimer capture.
   29  *
   30  * Note that this PPS driver does not use an interrupt.  Instead it uses the
   31  * hardware's ability to latch the timer's count register in response to a
   32  * signal on an IO pin.  Each of timers 4-7 have an associated pin, and this
   33  * code allows any one of those to be used.
   34  *
   35  * The timecounter routines in kern_tc.c call the pps poll routine periodically
   36  * to see if a new counter value has been latched.  When a new value has been
   37  * latched, the only processing done in the poll routine is to capture the
   38  * current set of timecounter timehands (done with pps_capture()) and the
   39  * latched value from the timer.  The remaining work (done by pps_event() while
   40  * holding a mutex) is scheduled to be done later in a non-interrupt context.
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __FBSDID("$FreeBSD$");
   45 
   46 #include "opt_platform.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/bus.h>
   51 #include <sys/conf.h>
   52 #include <sys/kernel.h>
   53 #include <sys/lock.h>
   54 #include <sys/module.h>
   55 #include <sys/malloc.h>
   56 #include <sys/mutex.h>
   57 #include <sys/rman.h>
   58 #include <sys/timepps.h>
   59 #include <sys/timetc.h>
   60 #include <machine/bus.h>
   61 
   62 #include <dev/ofw/openfirm.h>
   63 #include <dev/ofw/ofw_bus.h>
   64 #include <dev/ofw/ofw_bus_subr.h>
   65 #include <dev/extres/clk/clk.h>
   66 
   67 #include <arm/ti/ti_sysc.h>
   68 #include <arm/ti/ti_pinmux.h>
   69 #include <arm/ti/am335x/am335x_scm_padconf.h>
   70 
   71 #include "am335x_dmtreg.h"
   72 
   73 #define PPS_CDEV_NAME   "dmtpps"
   74 
   75 struct dmtpps_softc {
   76         device_t                dev;
   77         int                     mem_rid;
   78         struct resource *       mem_res;
   79         int                     tmr_num;        /* N from hwmod str "timerN" */
   80         char                    tmr_name[12];   /* "DMTimerN" */
   81         uint32_t                tclr;           /* Cached TCLR register. */
   82         struct timecounter      tc;
   83         int                     pps_curmode;    /* Edge mode now set in hw. */
   84         struct cdev *           pps_cdev;
   85         struct pps_state        pps_state;
   86         struct mtx              pps_mtx;
   87         clk_t                   clk_fck;
   88         uint64_t                sysclk_freq;
   89 };
   90 
   91 static int dmtpps_tmr_num;      /* Set by probe() */
   92 
   93 /* List of compatible strings for FDT tree */
   94 static struct ofw_compat_data compat_data[] = {
   95         {"ti,am335x-timer",     1},
   96         {"ti,am335x-timer-1ms", 1},
   97         {NULL,                  0},
   98 };
   99 SIMPLEBUS_PNP_INFO(compat_data);
  100 
  101 /*
  102  * A table relating pad names to the hardware timer number they can be mux'd to.
  103  */
  104 struct padinfo {
  105         char *  ballname;
  106         int     tmr_num;
  107 };
  108 static struct padinfo dmtpps_padinfo[] = {
  109         {"GPMC_ADVn_ALE",    4},
  110         {"I2C0_SDA",         4},
  111         {"MII1_TX_EN",       4},
  112         {"XDMA_EVENT_INTR0", 4},
  113         {"GPMC_BEn0_CLE",    5},
  114         {"MDC",              5},
  115         {"MMC0_DAT3",        5},
  116         {"UART1_RTSn",       5},
  117         {"GPMC_WEn",         6},
  118         {"MDIO",             6},
  119         {"MMC0_DAT2",        6},
  120         {"UART1_CTSn",       6},
  121         {"GPMC_OEn_REn",     7},
  122         {"I2C0_SCL",         7},
  123         {"UART0_CTSn",       7},
  124         {"XDMA_EVENT_INTR1", 7},
  125         {NULL, 0}
  126 };
  127 
  128 /*
  129  * This is either brilliantly user-friendly, or utterly lame...
  130  *
  131  * The am335x chip is used on the popular Beaglebone boards.  Those boards have
  132  * pins for all four capture-capable timers available on the P8 header. Allow
  133  * users to configure the input pin by giving the name of the header pin.
  134  */
  135 struct nicknames {
  136         const char * nick;
  137         const char * name;
  138 };
  139 static struct nicknames dmtpps_pin_nicks[] = {
  140         {"P8-7",  "GPMC_ADVn_ALE"},
  141         {"P8-9",  "GPMC_BEn0_CLE"},
  142         {"P8-10", "GPMC_WEn"},
  143         {"P8-8",  "GPMC_OEn_REn",},
  144         {NULL, NULL}
  145 };
  146 
  147 #define DMTIMER_READ4(sc, reg)          bus_read_4((sc)->mem_res, (reg))
  148 #define DMTIMER_WRITE4(sc, reg, val)    bus_write_4((sc)->mem_res, (reg), (val))
  149 
  150 /*
  151  * Translate a short friendly case-insensitive name to its canonical name.
  152  */
  153 static const char *
  154 dmtpps_translate_nickname(const char *nick)
  155 {
  156         struct nicknames *nn;
  157 
  158         for (nn = dmtpps_pin_nicks; nn->nick != NULL; nn++)
  159                 if (strcasecmp(nick, nn->nick) == 0)
  160                         return nn->name;
  161         return (nick);
  162 }
  163 
  164 /*
  165  * See if our tunable is set to the name of the input pin.  If not, that's NOT
  166  * an error, return 0.  If so, try to configure that pin as a timer capture
  167  * input pin, and if that works, then we have our timer unit number and if it
  168  * fails that IS an error, return -1.
  169  */
  170 static int
  171 dmtpps_find_tmr_num_by_tunable(void)
  172 {
  173         struct padinfo *pi;
  174         char iname[20];
  175         char muxmode[12];
  176         const char * ballname;
  177         int err;
  178 
  179         if (!TUNABLE_STR_FETCH("hw.am335x_dmtpps.input", iname, sizeof(iname)))
  180                 return (0);
  181         ballname = dmtpps_translate_nickname(iname);
  182         for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {
  183                 if (strcmp(ballname, pi->ballname) != 0)
  184                         continue;
  185                 snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);
  186                 err = ti_pinmux_padconf_set(pi->ballname, muxmode,
  187                     PADCONF_INPUT);
  188                 if (err != 0) {
  189                         printf("am335x_dmtpps: unable to configure capture pin "
  190                             "for %s to input mode\n", muxmode);
  191                         return (-1);
  192                 } else if (bootverbose) {
  193                         printf("am335x_dmtpps: configured pin %s as input "
  194                             "for %s\n", iname, muxmode);
  195                 }
  196                 return (pi->tmr_num);
  197         }
  198 
  199         /* Invalid name in the tunable, that's an error. */
  200         printf("am335x_dmtpps: unknown pin name '%s'\n", iname);
  201         return (-1);
  202 }
  203 
  204 /*
  205  * Ask the pinmux driver whether any pin has been configured as a TIMER4..TIMER7
  206  * input pin.  If so, return the timer number, if not return 0.
  207  */
  208 static int
  209 dmtpps_find_tmr_num_by_padconf(void)
  210 {
  211         int err;
  212         unsigned int padstate;
  213         const char * padmux;
  214         struct padinfo *pi;
  215         char muxmode[12];
  216 
  217         for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {
  218                 err = ti_pinmux_padconf_get(pi->ballname, &padmux, &padstate);
  219                 snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);
  220                 if (err == 0 && (padstate & RXACTIVE) != 0 &&
  221                     strcmp(muxmode, padmux) == 0)
  222                         return (pi->tmr_num);
  223         }
  224         /* Nothing found, not an error. */
  225         return (0);
  226 }
  227 
  228 /*
  229  * Figure out which hardware timer number to use based on input pin
  230  * configuration.  This is done just once, the first time probe() runs.
  231  */
  232 static int
  233 dmtpps_find_tmr_num(void)
  234 {
  235         int tmr_num;
  236 
  237         if ((tmr_num = dmtpps_find_tmr_num_by_tunable()) == 0)
  238                 tmr_num = dmtpps_find_tmr_num_by_padconf();
  239 
  240         if (tmr_num <= 0) {
  241                 printf("am335x_dmtpps: PPS driver not enabled: unable to find "
  242                     "or configure a capture input pin\n");
  243                 tmr_num = -1; /* Must return non-zero to prevent re-probing. */
  244         }
  245         return (tmr_num);
  246 }
  247 
  248 static void
  249 dmtpps_set_hw_capture(struct dmtpps_softc *sc, bool force_off)
  250 {
  251         int newmode;
  252 
  253         if (force_off)
  254                 newmode = 0;
  255         else
  256                 newmode = sc->pps_state.ppsparam.mode & PPS_CAPTUREASSERT;
  257 
  258         if (newmode == sc->pps_curmode)
  259                 return;
  260         sc->pps_curmode = newmode;
  261 
  262         if (newmode == PPS_CAPTUREASSERT)
  263                 sc->tclr |= DMT_TCLR_CAPTRAN_LOHI;
  264         else
  265                 sc->tclr &= ~DMT_TCLR_CAPTRAN_MASK;
  266         DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
  267 }
  268 
  269 static unsigned
  270 dmtpps_get_timecount(struct timecounter *tc)
  271 {
  272         struct dmtpps_softc *sc;
  273 
  274         sc = tc->tc_priv;
  275 
  276         return (DMTIMER_READ4(sc, DMT_TCRR));
  277 }
  278 
  279 static void
  280 dmtpps_poll(struct timecounter *tc)
  281 {
  282         struct dmtpps_softc *sc;
  283 
  284         sc = tc->tc_priv;
  285 
  286         /*
  287          * If a new value has been latched we've got a PPS event.  Capture the
  288          * timecounter data, then override the capcount field (pps_capture()
  289          * populates it from the current DMT_TCRR register) with the latched
  290          * value from the TCAR1 register.
  291          *
  292          * Note that we don't have the TCAR interrupt enabled, but the hardware
  293          * still provides the status bits in the "RAW" status register even when
  294          * they're masked from generating an irq.  However, when clearing the
  295          * TCAR status to re-arm the capture for the next second, we have to
  296          * write to the IRQ status register, not the RAW register.  Quirky.
  297          *
  298          * We do not need to hold a lock while capturing the pps data, because
  299          * it is captured into an area of the pps_state struct which is read
  300          * only by pps_event().  We do need to hold a lock while calling
  301          * pps_event(), because it manipulates data which is also accessed from
  302          * the ioctl(2) context by userland processes.
  303          */
  304         if (DMTIMER_READ4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) {
  305                 pps_capture(&sc->pps_state);
  306                 sc->pps_state.capcount = DMTIMER_READ4(sc, DMT_TCAR1);
  307                 DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR);
  308 
  309                 mtx_lock_spin(&sc->pps_mtx);
  310                 pps_event(&sc->pps_state, PPS_CAPTUREASSERT);
  311                 mtx_unlock_spin(&sc->pps_mtx);
  312         }
  313 }
  314 
  315 static int
  316 dmtpps_open(struct cdev *dev, int flags, int fmt, 
  317     struct thread *td)
  318 {
  319         struct dmtpps_softc *sc;
  320 
  321         sc = dev->si_drv1;
  322 
  323         /*
  324          * Begin polling for pps and enable capture in the hardware whenever the
  325          * device is open.  Doing this stuff again is harmless if this isn't the
  326          * first open.
  327          */
  328         sc->tc.tc_poll_pps = dmtpps_poll;
  329         dmtpps_set_hw_capture(sc, false);
  330 
  331         return 0;
  332 }
  333 
  334 static  int
  335 dmtpps_close(struct cdev *dev, int flags, int fmt, 
  336     struct thread *td)
  337 {
  338         struct dmtpps_softc *sc;
  339 
  340         sc = dev->si_drv1;
  341 
  342         /*
  343          * Stop polling and disable capture on last close.  Use the force-off
  344          * flag to override the configured mode and turn off the hardware.
  345          */
  346         sc->tc.tc_poll_pps = NULL;
  347         dmtpps_set_hw_capture(sc, true);
  348 
  349         return 0;
  350 }
  351 
  352 static int
  353 dmtpps_ioctl(struct cdev *dev, u_long cmd, caddr_t data, 
  354     int flags, struct thread *td)
  355 {
  356         struct dmtpps_softc *sc;
  357         int err;
  358 
  359         sc = dev->si_drv1;
  360 
  361         /* Let the kernel do the heavy lifting for ioctl. */
  362         mtx_lock_spin(&sc->pps_mtx);
  363         err = pps_ioctl(cmd, data, &sc->pps_state);
  364         mtx_unlock_spin(&sc->pps_mtx);
  365         if (err != 0)
  366                 return (err);
  367 
  368         /*
  369          * The capture mode could have changed, set the hardware to whatever
  370          * mode is now current.  Effectively a no-op if nothing changed.
  371          */
  372         dmtpps_set_hw_capture(sc, false);
  373 
  374         return (err);
  375 }
  376 
  377 static struct cdevsw dmtpps_cdevsw = {
  378         .d_version =    D_VERSION,
  379         .d_open =       dmtpps_open,
  380         .d_close =      dmtpps_close,
  381         .d_ioctl =      dmtpps_ioctl,
  382         .d_name =       PPS_CDEV_NAME,
  383 };
  384 
  385 static int
  386 dmtpps_probe(device_t dev)
  387 {
  388         char strbuf[64];
  389         int tmr_num;
  390         uint64_t rev_address;
  391 
  392         if (!ofw_bus_status_okay(dev))
  393                 return (ENXIO);
  394 
  395         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  396                 return (ENXIO);
  397 
  398         /*
  399          * If we haven't chosen which hardware timer to use yet, go do that now.
  400          * We need to know that to decide whether to return success for this
  401          * hardware timer instance or not.
  402          */
  403         if (dmtpps_tmr_num == 0)
  404                 dmtpps_tmr_num = dmtpps_find_tmr_num();
  405 
  406         /*
  407          * Figure out which hardware timer is being probed and see if it matches
  408          * the configured timer number determined earlier.
  409          */
  410         rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
  411         switch (rev_address) {
  412                 case DMTIMER1_1MS_REV:
  413                         tmr_num = 1;
  414                         break;
  415                 case DMTIMER2_REV:
  416                         tmr_num = 2;
  417                         break;
  418                 case DMTIMER3_REV:
  419                         tmr_num = 3;
  420                         break;
  421                 case DMTIMER4_REV:
  422                         tmr_num = 4;
  423                         break;
  424                 case DMTIMER5_REV:
  425                         tmr_num = 5;
  426                         break;
  427                 case DMTIMER6_REV:
  428                         tmr_num = 6;
  429                         break;
  430                 case DMTIMER7_REV:
  431                         tmr_num = 7;
  432                         break;
  433                 default:
  434                         return (ENXIO);
  435         }
  436 
  437         if (dmtpps_tmr_num != tmr_num)
  438                 return (ENXIO);
  439 
  440         snprintf(strbuf, sizeof(strbuf), "AM335x PPS-Capture DMTimer%d",
  441             tmr_num);
  442         device_set_desc_copy(dev, strbuf);
  443 
  444         return(BUS_PROBE_DEFAULT);
  445 }
  446 
  447 static int
  448 dmtpps_attach(device_t dev)
  449 {
  450         struct dmtpps_softc *sc;
  451         struct make_dev_args mda;
  452         int err;
  453         clk_t sys_clkin;
  454         uint64_t rev_address;
  455 
  456         sc = device_get_softc(dev);
  457         sc->dev = dev;
  458 
  459         /* Figure out which hardware timer this is and set the name string. */
  460         rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
  461         switch (rev_address) {
  462                 case DMTIMER1_1MS_REV:
  463                         sc->tmr_num = 1;
  464                         break;
  465                 case DMTIMER2_REV:
  466                         sc->tmr_num = 2;
  467                         break;
  468                 case DMTIMER3_REV:
  469                         sc->tmr_num = 3;
  470                         break;
  471                 case DMTIMER4_REV:
  472                         sc->tmr_num = 4;
  473                         break;
  474                 case DMTIMER5_REV:
  475                         sc->tmr_num = 5;
  476                         break;
  477                 case DMTIMER6_REV:
  478                         sc->tmr_num = 6;
  479                         break;
  480                 case DMTIMER7_REV:
  481                         sc->tmr_num = 7;
  482                         break;
  483         }
  484         snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
  485 
  486         /* expect one clock */
  487         err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck);
  488         if (err != 0) {
  489                 device_printf(dev, "Cant find clock index 0. err: %d\n", err);
  490                 return (ENXIO);
  491         }
  492 
  493         err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin);
  494         if (err != 0) {
  495                 device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err);
  496                 return (ENXIO);
  497         }
  498 
  499         /* Select M_OSC as DPLL parent */
  500         err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin);
  501         if (err != 0) {
  502                 device_printf(dev, "Cant set mux to CLK_M_OSC\n");
  503                 return (ENXIO);
  504         }
  505 
  506         /* Enable clocks and power on the device. */
  507         err = ti_sysc_clock_enable(device_get_parent(dev));
  508         if (err != 0) {
  509                 device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err);
  510                 return (ENXIO);
  511         }
  512 
  513         /* Get the base clock frequency. */
  514         err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq);
  515         if (err != 0) {
  516                 device_printf(dev, "Cant get sysclk frequency, err %d\n", err);
  517                 return (ENXIO);
  518         }
  519         /* Request the memory resources. */
  520         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  521             &sc->mem_rid, RF_ACTIVE);
  522         if (sc->mem_res == NULL) {
  523                 return (ENXIO);
  524         }
  525 
  526         /*
  527          * Configure the timer pulse/capture pin to input/capture mode.  This is
  528          * required in addition to configuring the pin as input with the pinmux
  529          * controller (which was done via fdt data or tunable at probe time).
  530          */
  531         sc->tclr = DMT_TCLR_GPO_CFG;
  532         DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
  533 
  534         /* Set up timecounter hardware, start it. */
  535         DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);
  536         while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
  537                 continue;
  538 
  539         sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;
  540         DMTIMER_WRITE4(sc, DMT_TLDR, 0);
  541         DMTIMER_WRITE4(sc, DMT_TCRR, 0);
  542         DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
  543 
  544         /* Register the timecounter. */
  545         sc->tc.tc_name           = sc->tmr_name;
  546         sc->tc.tc_get_timecount  = dmtpps_get_timecount;
  547         sc->tc.tc_counter_mask   = ~0u;
  548         sc->tc.tc_frequency      = sc->sysclk_freq;
  549         sc->tc.tc_quality        = 1000;
  550         sc->tc.tc_priv           = sc;
  551 
  552         tc_init(&sc->tc);
  553 
  554         /*
  555          * Indicate our PPS capabilities.  Have the kernel init its part of the
  556          * pps_state struct and add its capabilities.
  557          *
  558          * While the hardware has a mode to capture each edge, it's not clear we
  559          * can use it that way, because there's only a single interrupt/status
  560          * bit to say something was captured, but not which edge it was.  For
  561          * now, just say we can only capture assert events (the positive-going
  562          * edge of the pulse).
  563          */
  564         mtx_init(&sc->pps_mtx, "dmtpps", NULL, MTX_SPIN);
  565         sc->pps_state.flags = PPSFLAG_MTX_SPIN;
  566         sc->pps_state.ppscap = PPS_CAPTUREASSERT;
  567         sc->pps_state.driver_abi = PPS_ABI_VERSION;
  568         sc->pps_state.driver_mtx = &sc->pps_mtx;
  569         pps_init_abi(&sc->pps_state);
  570 
  571         /* Create the PPS cdev. */
  572         make_dev_args_init(&mda);
  573         mda.mda_flags = MAKEDEV_WAITOK;
  574         mda.mda_devsw = &dmtpps_cdevsw;
  575         mda.mda_cr = NULL;
  576         mda.mda_uid = UID_ROOT;
  577         mda.mda_gid = GID_WHEEL;
  578         mda.mda_mode = 0600;
  579         mda.mda_unit = device_get_unit(dev);
  580         mda.mda_si_drv1 = sc;
  581         if ((err = make_dev_s(&mda, &sc->pps_cdev, PPS_CDEV_NAME)) != 0) {
  582                 device_printf(dev, "Failed to create cdev %s\n", PPS_CDEV_NAME);
  583                 return (err);
  584         }
  585 
  586         if (bootverbose)
  587                 device_printf(sc->dev, "Using %s for PPS device /dev/%s\n",
  588                     sc->tmr_name, PPS_CDEV_NAME);
  589 
  590         return (0);
  591 }
  592 
  593 static int
  594 dmtpps_detach(device_t dev)
  595 {
  596 
  597         /*
  598          * There is no way to remove a timecounter once it has been registered,
  599          * even if it's not in use, so we can never detach.  If we were
  600          * dynamically loaded as a module this will prevent unloading.
  601          */
  602         return (EBUSY);
  603 }
  604 
  605 static device_method_t dmtpps_methods[] = {
  606         DEVMETHOD(device_probe,         dmtpps_probe),
  607         DEVMETHOD(device_attach,        dmtpps_attach),
  608         DEVMETHOD(device_detach,        dmtpps_detach),
  609         { 0, 0 }
  610 };
  611 
  612 static driver_t dmtpps_driver = {
  613         "am335x_dmtpps",
  614         dmtpps_methods,
  615         sizeof(struct dmtpps_softc),
  616 };
  617 
  618 DRIVER_MODULE(am335x_dmtpps, simplebus, dmtpps_driver, 0, 0);
  619 MODULE_DEPEND(am335x_dmtpps, ti_sysc, 1, 1, 1);

Cache object: 5388671f3da57a075c5140d832da008d


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