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/pwm/pwmc.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-FreeBSD
    3  *
    4  * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
    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 "opt_platform.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/bus.h>
   36 #include <sys/conf.h>
   37 #include <sys/kernel.h>
   38 #include <sys/module.h>
   39 #include <sys/time.h>
   40 
   41 #include <dev/pwm/pwmbus.h>
   42 #include <dev/pwm/pwmc.h>
   43 
   44 #include "pwmbus_if.h"
   45 
   46 #ifdef FDT
   47 #include <dev/ofw/openfirm.h>
   48 #include <dev/ofw/ofw_bus.h>
   49 #include <dev/ofw/ofw_bus_subr.h>
   50 
   51 static struct ofw_compat_data compat_data[] = {
   52         {"freebsd,pwmc", true},
   53         {NULL,           false},
   54 };
   55 
   56 PWMBUS_FDT_PNP_INFO(compat_data);
   57 
   58 #endif
   59 
   60 struct pwmc_softc {
   61         device_t        dev;
   62         struct cdev     *cdev;
   63         u_int           chan;
   64 };
   65 
   66 static int
   67 pwm_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
   68     int fflag, struct thread *td)
   69 {
   70         struct pwmc_softc *sc;
   71         struct pwm_state state;
   72         device_t bus;
   73         int rv = 0;
   74 
   75         sc = dev->si_drv1;
   76         bus = device_get_parent(sc->dev);
   77 
   78         switch (cmd) {
   79         case PWMSETSTATE:
   80                 bcopy(data, &state, sizeof(state));
   81                 rv = PWMBUS_CHANNEL_CONFIG(bus, sc->chan,
   82                     state.period, state.duty);
   83                 if (rv != 0)
   84                         return (rv);
   85 
   86                 rv = PWMBUS_CHANNEL_SET_FLAGS(bus,
   87                     sc->chan, state.flags);
   88                 if (rv != 0 && rv != EOPNOTSUPP)
   89                         return (rv);
   90 
   91                 rv = PWMBUS_CHANNEL_ENABLE(bus, sc->chan,
   92                     state.enable);
   93                 break;
   94         case PWMGETSTATE:
   95                 bcopy(data, &state, sizeof(state));
   96                 rv = PWMBUS_CHANNEL_GET_CONFIG(bus, sc->chan,
   97                     &state.period, &state.duty);
   98                 if (rv != 0)
   99                         return (rv);
  100 
  101                 rv = PWMBUS_CHANNEL_GET_FLAGS(bus, sc->chan,
  102                     &state.flags);
  103                 if (rv != 0)
  104                         return (rv);
  105 
  106                 rv = PWMBUS_CHANNEL_IS_ENABLED(bus, sc->chan,
  107                     &state.enable);
  108                 if (rv != 0)
  109                         return (rv);
  110                 bcopy(&state, data, sizeof(state));
  111                 break;
  112         }
  113 
  114         return (rv);
  115 }
  116 
  117 static struct cdevsw pwm_cdevsw = {
  118         .d_version      = D_VERSION,
  119         .d_name         = "pwmc",
  120         .d_ioctl        = pwm_ioctl
  121 };
  122 
  123 static void
  124 pwmc_setup_label(struct pwmc_softc *sc)
  125 {
  126         const char *hintlabel;
  127 #ifdef FDT
  128         void *label;
  129 
  130         if (OF_getprop_alloc(ofw_bus_get_node(sc->dev), "label", &label) > 0) {
  131                 make_dev_alias(sc->cdev, "pwm/%s", (char *)label);
  132                 OF_prop_free(label);
  133         }
  134 #endif
  135 
  136         if (resource_string_value(device_get_name(sc->dev),
  137             device_get_unit(sc->dev), "label", &hintlabel) == 0) {
  138                 make_dev_alias(sc->cdev, "pwm/%s", hintlabel);
  139         }
  140 }
  141 
  142 static int
  143 pwmc_probe(device_t dev)
  144 {
  145         int rv;
  146 
  147         rv = BUS_PROBE_NOWILDCARD;
  148 
  149 #ifdef FDT
  150         if (!ofw_bus_status_okay(dev))
  151                 return (ENXIO);
  152 
  153         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
  154                 rv = BUS_PROBE_DEFAULT;
  155         }
  156 #endif
  157 
  158         device_set_desc(dev, "PWM Control");
  159         return (rv);
  160 }
  161 
  162 static int
  163 pwmc_attach(device_t dev)
  164 {
  165         struct pwmc_softc *sc;
  166         struct make_dev_args args;
  167         int error;
  168 
  169         sc = device_get_softc(dev);
  170         sc->dev = dev;
  171 
  172         if ((error = pwmbus_get_channel(dev, &sc->chan)) != 0)
  173                 return (error);
  174 
  175         make_dev_args_init(&args);
  176         args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
  177         args.mda_devsw = &pwm_cdevsw;
  178         args.mda_uid = UID_ROOT;
  179         args.mda_gid = GID_OPERATOR;
  180         args.mda_mode = 0660;
  181         args.mda_si_drv1 = sc;
  182         error = make_dev_s(&args, &sc->cdev, "pwm/pwmc%d.%d",
  183             device_get_unit(device_get_parent(dev)), sc->chan);
  184         if (error != 0) {
  185                 device_printf(dev, "Failed to make PWM device\n");
  186                 return (error);
  187         }
  188 
  189         pwmc_setup_label(sc);
  190 
  191         return (0);
  192 }
  193 
  194 static int
  195 pwmc_detach(device_t dev)
  196 {
  197         struct pwmc_softc *sc;
  198 
  199         sc = device_get_softc(dev);
  200         destroy_dev(sc->cdev);
  201 
  202         return (0);
  203 }
  204 
  205 static device_method_t pwmc_methods[] = {
  206         /* device_if */
  207         DEVMETHOD(device_probe, pwmc_probe),
  208         DEVMETHOD(device_attach, pwmc_attach),
  209         DEVMETHOD(device_detach, pwmc_detach),
  210 
  211         DEVMETHOD_END
  212 };
  213 
  214 static driver_t pwmc_driver = {
  215         "pwmc",
  216         pwmc_methods,
  217         sizeof(struct pwmc_softc),
  218 };
  219 
  220 DRIVER_MODULE(pwmc, pwmbus, pwmc_driver, 0, 0);
  221 MODULE_DEPEND(pwmc, pwmbus, 1, 1, 1);
  222 MODULE_VERSION(pwmc, 1);

Cache object: 6a6752d100b4662b64c37b2f118a49ec


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