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/iicbus/iicbus.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) 1998, 2001 Nicolas Souchu
    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 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 /*
   31  * Autoconfiguration and support routines for the Philips serial I2C bus
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/lock.h>
   38 #include <sys/malloc.h>
   39 #include <sys/module.h>
   40 #include <sys/mutex.h>
   41 #include <sys/bus.h> 
   42 
   43 #include <dev/iicbus/iiconf.h>
   44 #include <dev/iicbus/iicbus.h>
   45 
   46 #include "iicbus_if.h"
   47 
   48 /* See comments below for why auto-scanning is a bad idea. */
   49 #define SCAN_IICBUS 0
   50 
   51 static int
   52 iicbus_probe(device_t dev)
   53 {
   54 
   55         device_set_desc(dev, "Philips I2C bus");
   56 
   57         /* Allow other subclasses to override this driver. */
   58         return (BUS_PROBE_GENERIC);
   59 }
   60 
   61 #if SCAN_IICBUS
   62 static int 
   63 iic_probe_device(device_t dev, u_char addr)
   64 {
   65         int count;
   66         char byte;
   67 
   68         if ((addr & 1) == 0) {
   69                 /* is device writable? */
   70                 if (!iicbus_start(dev, (u_char)addr, 0)) {
   71                         iicbus_stop(dev);
   72                         return (1);
   73                 }
   74         } else {
   75                 /* is device readable? */
   76                 if (!iicbus_block_read(dev, (u_char)addr, &byte, 1, &count))
   77                         return (1);
   78         }
   79 
   80         return (0);
   81 }
   82 #endif
   83 
   84 /*
   85  * We add all the devices which we know about.
   86  * The generic attach routine will attach them if they are alive.
   87  */
   88 static int
   89 iicbus_attach(device_t dev)
   90 {
   91 #if SCAN_IICBUS
   92         unsigned char addr;
   93 #endif
   94         struct iicbus_softc *sc = IICBUS_SOFTC(dev);
   95 
   96         sc->dev = dev;
   97         mtx_init(&sc->lock, "iicbus", NULL, MTX_DEF);
   98         iicbus_reset(dev, IIC_FASTEST, 0, NULL);
   99 
  100         /* device probing is meaningless since the bus is supposed to be
  101          * hot-plug. Moreover, some I2C chips do not appreciate random
  102          * accesses like stop after start to fast, reads for less than
  103          * x bytes...
  104          */
  105 #if SCAN_IICBUS
  106         printf("Probing for devices on iicbus%d:", device_get_unit(dev));
  107 
  108         /* probe any devices */
  109         for (addr = 16; addr < 240; addr++) {
  110                 if (iic_probe_device(dev, (u_char)addr)) {
  111                         printf(" <%x>", addr);
  112                 }
  113         }
  114         printf("\n");
  115 #endif
  116         bus_generic_probe(dev);
  117         bus_enumerate_hinted_children(dev);
  118         bus_generic_attach(dev);
  119         return (0);
  120 }
  121   
  122 static int
  123 iicbus_detach(device_t dev)
  124 {
  125         struct iicbus_softc *sc = IICBUS_SOFTC(dev);
  126 
  127         iicbus_reset(dev, IIC_FASTEST, 0, NULL);
  128         bus_generic_detach(dev);
  129         mtx_destroy(&sc->lock);
  130         return (0);
  131 }
  132   
  133 static int
  134 iicbus_print_child(device_t dev, device_t child)
  135 {
  136         struct iicbus_ivar *devi = IICBUS_IVAR(child);
  137         int retval = 0;
  138 
  139         retval += bus_print_child_header(dev, child);
  140         if (devi->addr != 0)
  141                 retval += printf(" at addr %#x", devi->addr);
  142         retval += bus_print_child_footer(dev, child);
  143 
  144         return (retval);
  145 }
  146 
  147 static void
  148 iicbus_probe_nomatch(device_t bus, device_t child)
  149 {
  150         struct iicbus_ivar *devi = IICBUS_IVAR(child);
  151 
  152         device_printf(bus, "<unknown card>");
  153         printf(" at addr %#x\n", devi->addr);
  154         return;
  155 }
  156 
  157 static int
  158 iicbus_child_location_str(device_t bus, device_t child, char *buf,
  159     size_t buflen)
  160 {
  161         struct iicbus_ivar *devi = IICBUS_IVAR(child);
  162 
  163         snprintf(buf, buflen, "addr=%#x", devi->addr);
  164         return (0);
  165 }
  166 
  167 static int
  168 iicbus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
  169     size_t buflen)
  170 {
  171         *buf = '\0';
  172         return (0);
  173 }
  174 
  175 static int
  176 iicbus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
  177 {
  178         struct iicbus_ivar *devi = IICBUS_IVAR(child);
  179 
  180         switch (which) {
  181         default:
  182                 return (EINVAL);
  183         case IICBUS_IVAR_ADDR:
  184                 *result = devi->addr;
  185                 break;
  186         }
  187         return (0);
  188 }
  189 
  190 static device_t
  191 iicbus_add_child(device_t dev, u_int order, const char *name, int unit)
  192 {
  193         device_t child;
  194         struct iicbus_ivar *devi;
  195 
  196         child = device_add_child_ordered(dev, order, name, unit);
  197         if (child == NULL)
  198                 return (child);
  199         devi = malloc(sizeof(struct iicbus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
  200         if (devi == NULL) {
  201                 device_delete_child(dev, child);
  202                 return (0);
  203         }
  204         device_set_ivars(child, devi);
  205         return (child);
  206 }
  207 
  208 static void
  209 iicbus_hinted_child(device_t bus, const char *dname, int dunit)
  210 {
  211         device_t child;
  212         struct iicbus_ivar *devi;
  213 
  214         child = BUS_ADD_CHILD(bus, 0, dname, dunit);
  215         devi = IICBUS_IVAR(child);
  216         resource_int_value(dname, dunit, "addr", &devi->addr);
  217 }
  218 
  219 int
  220 iicbus_generic_intr(device_t dev, int event, char *buf)
  221 {
  222 
  223         return (0);
  224 }
  225 
  226 int
  227 iicbus_null_callback(device_t dev, int index, caddr_t data)
  228 {
  229 
  230         return (0);
  231 }
  232 
  233 int
  234 iicbus_null_repeated_start(device_t dev, u_char addr)
  235 {
  236 
  237         return (IIC_ENOTSUPP);
  238 }
  239 
  240 static device_method_t iicbus_methods[] = {
  241         /* device interface */
  242         DEVMETHOD(device_probe,         iicbus_probe),
  243         DEVMETHOD(device_attach,        iicbus_attach),
  244         DEVMETHOD(device_detach,        iicbus_detach),
  245 
  246         /* bus interface */
  247         DEVMETHOD(bus_add_child,        iicbus_add_child),
  248         DEVMETHOD(bus_print_child,      iicbus_print_child),
  249         DEVMETHOD(bus_probe_nomatch,    iicbus_probe_nomatch),
  250         DEVMETHOD(bus_read_ivar,        iicbus_read_ivar),
  251         DEVMETHOD(bus_child_pnpinfo_str, iicbus_child_pnpinfo_str),
  252         DEVMETHOD(bus_child_location_str, iicbus_child_location_str),
  253         DEVMETHOD(bus_hinted_child,     iicbus_hinted_child),
  254 
  255         /* iicbus interface */
  256         DEVMETHOD(iicbus_transfer,      iicbus_transfer),
  257 
  258         DEVMETHOD_END
  259 };
  260 
  261 driver_t iicbus_driver = {
  262         "iicbus",
  263         iicbus_methods,
  264         sizeof(struct iicbus_softc),
  265 };
  266 
  267 devclass_t iicbus_devclass;
  268 
  269 MODULE_VERSION(iicbus, IICBUS_MODVER);
  270 DRIVER_MODULE(iicbus, iichb, iicbus_driver, iicbus_devclass, 0, 0);
  271 

Cache object: c915e4efe366a878f59389890b16d874


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