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/spibus/spibus.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 #include <sys/cdefs.h>
    2 __FBSDID("$FreeBSD: releng/10.3/sys/dev/spibus/spibus.c 260489 2014-01-09 18:28:58Z loos $");
    3 
    4 #include <sys/param.h>
    5 #include <sys/systm.h>
    6 #include <sys/malloc.h>
    7 #include <sys/module.h>
    8 #include <sys/kernel.h>
    9 #include <sys/queue.h>
   10 #include <sys/sysctl.h>
   11 #include <sys/types.h>
   12 
   13 #include <sys/bus.h>
   14 #include <machine/bus.h>
   15 #include <sys/rman.h>
   16 #include <machine/resource.h>
   17 
   18 #include <dev/spibus/spibusvar.h>
   19 #include <dev/spibus/spi.h>
   20 #include "spibus_if.h"
   21 
   22 static int
   23 spibus_probe(device_t dev)
   24 {
   25         device_set_desc(dev, "spibus bus");
   26         return (BUS_PROBE_GENERIC);
   27 }
   28 
   29 static int
   30 spibus_attach(device_t dev)
   31 {
   32         struct spibus_softc *sc = SPIBUS_SOFTC(dev);
   33 
   34         sc->dev = dev;
   35         bus_enumerate_hinted_children(dev);
   36         return (bus_generic_attach(dev));
   37 }
   38 
   39 /*
   40  * Since this is not a self-enumerating bus, and since we always add
   41  * children in attach, we have to always delete children here.
   42  */
   43 static int
   44 spibus_detach(device_t dev)
   45 {
   46         int err, ndevs, i;
   47         device_t *devlist;
   48 
   49         if ((err = bus_generic_detach(dev)) != 0)
   50                 return (err);
   51         if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
   52                 return (err);
   53         for (i = 0; i < ndevs; i++)
   54                 device_delete_child(dev, devlist[i]);
   55         free(devlist, M_TEMP);
   56 
   57         return (0);
   58 }
   59 
   60 static int
   61 spibus_suspend(device_t dev)
   62 {
   63         return (bus_generic_suspend(dev));
   64 }
   65 
   66 static
   67 int
   68 spibus_resume(device_t dev)
   69 {
   70         return (bus_generic_resume(dev));
   71 }
   72 
   73 static int
   74 spibus_print_child(device_t dev, device_t child)
   75 {
   76         struct spibus_ivar *devi = SPIBUS_IVAR(child);
   77         int retval = 0;
   78 
   79         retval += bus_print_child_header(dev, child);
   80         retval += printf(" at cs %d", devi->cs);
   81         retval += bus_print_child_footer(dev, child);
   82 
   83         return (retval);
   84 }
   85 
   86 static void
   87 spibus_probe_nomatch(device_t bus, device_t child)
   88 {
   89         struct spibus_ivar *devi = SPIBUS_IVAR(child);
   90 
   91         device_printf(bus, "<unknown card>");
   92         printf(" at cs %d\n", devi->cs);
   93         return;
   94 }
   95 
   96 static int
   97 spibus_child_location_str(device_t bus, device_t child, char *buf,
   98     size_t buflen)
   99 {
  100         struct spibus_ivar *devi = SPIBUS_IVAR(child);
  101 
  102         snprintf(buf, buflen, "cs=%d", devi->cs);
  103         return (0);
  104 }
  105 
  106 static int
  107 spibus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
  108     size_t buflen)
  109 {
  110         *buf = '\0';
  111         return (0);
  112 }
  113 
  114 static int
  115 spibus_read_ivar(device_t bus, device_t child, int which, u_int *result)
  116 {
  117         struct spibus_ivar *devi = SPIBUS_IVAR(child);
  118 
  119         switch (which) {
  120         default:
  121                 return (EINVAL);
  122         case SPIBUS_IVAR_CS:
  123                 *(uint32_t *)result = devi->cs;
  124                 break;
  125         }
  126         return (0);
  127 }
  128 
  129 static device_t
  130 spibus_add_child(device_t dev, u_int order, const char *name, int unit)
  131 {
  132         device_t child;
  133         struct spibus_ivar *devi;
  134 
  135         child = device_add_child_ordered(dev, order, name, unit);
  136         if (child == NULL) 
  137                 return (child);
  138         devi = malloc(sizeof(struct spibus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
  139         if (devi == NULL) {
  140                 device_delete_child(dev, child);
  141                 return (0);
  142         }
  143         device_set_ivars(child, devi);
  144         return (child);
  145 }
  146 
  147 static void
  148 spibus_hinted_child(device_t bus, const char *dname, int dunit)
  149 {
  150         device_t child;
  151         struct spibus_ivar *devi;
  152 
  153         child = BUS_ADD_CHILD(bus, 0, dname, dunit);
  154         devi = SPIBUS_IVAR(child);
  155         resource_int_value(dname, dunit, "cs", &devi->cs);
  156 }
  157 
  158 static int
  159 spibus_transfer_impl(device_t dev, device_t child, struct spi_command *cmd)
  160 {
  161         return (SPIBUS_TRANSFER(device_get_parent(dev), child, cmd));
  162 }
  163 
  164 static device_method_t spibus_methods[] = {
  165         /* Device interface */
  166         DEVMETHOD(device_probe,         spibus_probe),
  167         DEVMETHOD(device_attach,        spibus_attach),
  168         DEVMETHOD(device_detach,        spibus_detach),
  169         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  170         DEVMETHOD(device_suspend,       spibus_suspend),
  171         DEVMETHOD(device_resume,        spibus_resume),
  172 
  173         /* Bus interface */
  174         DEVMETHOD(bus_add_child,        spibus_add_child),
  175         DEVMETHOD(bus_print_child,      spibus_print_child),
  176         DEVMETHOD(bus_probe_nomatch,    spibus_probe_nomatch),
  177         DEVMETHOD(bus_read_ivar,        spibus_read_ivar),
  178         DEVMETHOD(bus_child_pnpinfo_str, spibus_child_pnpinfo_str),
  179         DEVMETHOD(bus_child_location_str, spibus_child_location_str),
  180         DEVMETHOD(bus_hinted_child,     spibus_hinted_child),
  181 
  182         /* spibus interface */
  183         DEVMETHOD(spibus_transfer,      spibus_transfer_impl),
  184 
  185         DEVMETHOD_END
  186 };
  187 
  188 driver_t spibus_driver = {
  189         "spibus",
  190         spibus_methods,
  191         sizeof(struct spibus_softc)
  192 };
  193 
  194 devclass_t      spibus_devclass;
  195 
  196 DRIVER_MODULE(spibus, spi, spibus_driver, spibus_devclass, 0, 0);
  197 MODULE_VERSION(spibus, 1);

Cache object: 121162bbc26b63d5ca4a218f5772710c


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