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/mips/ingenic/jz4780_efuse.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 Alexander Kabaev <kan@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 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/clock.h>
   34 #include <sys/kernel.h>
   35 #include <sys/limits.h>
   36 #include <sys/lock.h>
   37 #include <sys/mutex.h>
   38 #include <sys/module.h>
   39 #include <sys/resource.h>
   40 
   41 #include <machine/bus.h>
   42 #include <machine/resource.h>
   43 
   44 #include <dev/fdt/fdt_common.h>
   45 #include <dev/ofw/ofw_bus.h>
   46 #include <dev/ofw/ofw_bus_subr.h>
   47 
   48 #include <mips/ingenic/jz4780_regs.h>
   49 
   50 static struct ofw_compat_data compat_data[] = {
   51         {"ingenic,jz4780-efuse",        1},
   52         {NULL,                          0}
   53 };
   54 
   55 struct jz4780_efuse_data {
   56         uint32_t serial_num;
   57         uint32_t date;
   58         uint8_t  nanufacturer[2];
   59         uint8_t  macaddr[6];
   60 } __packed;
   61 
   62 static struct resource_spec jz4780_efuse_spec[] = {
   63         { SYS_RES_MEMORY, 0, RF_ACTIVE },
   64         { -1, 0 }
   65 };
   66 
   67 struct jz4780_efuse_softc {
   68         device_t                dev;
   69         struct resource         *res[1];
   70         struct jz4780_efuse_data data;
   71 };
   72 
   73 #define CSR_WRITE_4(sc, reg, val) \
   74     bus_write_4((sc)->res[0], (reg), (val))
   75 #define CSR_READ_4(sc, reg) \
   76     bus_read_4((sc)->res[0], (reg))
   77 
   78 #define JZ_EFUSE_BANK_SIZE      (4096 / 8) /* Bank size is 4096 bits */
   79 
   80 static int
   81 jz4780_efuse_probe(device_t dev)
   82 {
   83         if (!ofw_bus_status_okay(dev))
   84                 return (ENXIO);
   85 
   86         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
   87                 return (ENXIO);
   88 
   89         return (BUS_PROBE_DEFAULT);
   90 }
   91 
   92 static void
   93 jz4780_efuse_read_chunk(struct jz4780_efuse_softc *sc, int addr, uint8_t *buf, int len)
   94 {
   95         uint32_t abuf;
   96         int i, count;
   97 
   98         /* Setup to read proper bank */
   99         CSR_WRITE_4(sc, JZ_EFUCTRL, JZ_EFUSE_READ |
  100             (addr < JZ_EFUSE_BANK_SIZE ? 0: JZ_EFUSE_BANK) |
  101             (addr << JZ_EFUSE_ADDR_SHIFT) |
  102             ((len - 1) << JZ_EFUSE_SIZE_SHIFT));
  103         /* Wait for read to complete */
  104         while ((CSR_READ_4(sc, JZ_EFUSTATE) & JZ_EFUSE_RD_DONE) == 0)
  105                 DELAY(1000);
  106 
  107         /* Round to 4 bytes for the simple loop below */
  108         count = len & ~3;
  109 
  110         for (i = 0; i < count; i += 4) {
  111                 abuf = CSR_READ_4(sc, JZ_EFUDATA0 + i);
  112                 memcpy(buf, &abuf, 4);
  113                 buf += 4;
  114         }
  115 
  116         /* Read partial word and assign it byte-by-byte */
  117         if (i < len) {
  118                 abuf = CSR_READ_4(sc, JZ_EFUDATA0 + i);
  119                 for (/* none */; i < len; i++) {
  120                         buf[i] = abuf & 0xff;
  121                         abuf >>= 8;
  122                 }
  123         }
  124 }
  125 
  126 static void
  127 jz4780_efuse_read(struct jz4780_efuse_softc *sc, int addr, void *buf, int len)
  128 {
  129         int chunk;
  130 
  131         while (len > 0) {
  132                 chunk = (len > 32) ? 32 : len;
  133                 jz4780_efuse_read_chunk(sc, addr, buf, chunk);
  134                 len -= chunk;
  135                 buf = (void *)((uintptr_t)buf + chunk);
  136                 addr += chunk;
  137         }
  138 }
  139 
  140 static void
  141 jz4780_efuse_update_kenv(struct jz4780_efuse_softc *sc)
  142 {
  143         char macstr[sizeof("xx:xx:xx:xx:xx:xx")];
  144 
  145         /*
  146          * Update hint in kernel env only if none is available yet.
  147          * It is quite possible one was set by command line already.
  148          */
  149         if (kern_getenv("hint.dme.0.macaddr") == NULL) {
  150                 snprintf(macstr, sizeof(macstr), "%6D",
  151                     sc->data.macaddr, ":");
  152                 kern_setenv("hint.dme.0.macaddr", macstr);
  153         }
  154 }
  155 
  156 static int
  157 jz4780_efuse_attach(device_t dev)
  158 {
  159         struct jz4780_efuse_softc *sc;
  160 
  161         sc = device_get_softc(dev);
  162         sc->dev = dev;
  163 
  164         if (bus_alloc_resources(dev, jz4780_efuse_spec, sc->res)) {
  165                 device_printf(dev, "could not allocate resources for device\n");
  166                 return (ENXIO);
  167         }
  168 
  169         /*
  170          * Default RD_STROBE to 4 h2clk cycles, should already be set to 4 by  reset
  171          * but configure it anyway.
  172          */
  173         CSR_WRITE_4(sc, JZ_EFUCFG, 0x00040000);
  174 
  175         /* Read user-id segment */
  176         jz4780_efuse_read(sc, 0x18, &sc->data, sizeof(sc->data));
  177 
  178         /*
  179          * Set resource hints for the dme device to discover its
  180          * MAC address, if not set already.
  181          */
  182         jz4780_efuse_update_kenv(sc);
  183 
  184         /* Resource conflicts with NEMC, release early */
  185         bus_release_resources(dev, jz4780_efuse_spec, sc->res);
  186         return (0);
  187 }
  188 
  189 static int
  190 jz4780_efuse_detach(device_t dev)
  191 {
  192 
  193         return (0);
  194 }
  195 
  196 static device_method_t jz4780_efuse_methods[] = {
  197         /* Device interface */
  198         DEVMETHOD(device_probe,         jz4780_efuse_probe),
  199         DEVMETHOD(device_attach,        jz4780_efuse_attach),
  200         DEVMETHOD(device_detach,        jz4780_efuse_detach),
  201 
  202         DEVMETHOD_END
  203 };
  204 
  205 static driver_t jz4780_efuse_driver = {
  206         "efuse",
  207         jz4780_efuse_methods,
  208         sizeof(struct jz4780_efuse_softc),
  209 };
  210 
  211 static devclass_t jz4780_efuse_devclass;
  212 EARLY_DRIVER_MODULE(jz4780_efuse, simplebus, jz4780_efuse_driver,
  213     jz4780_efuse_devclass, 0, 0, BUS_PASS_TIMER);

Cache object: 8a9558118569ed7ed81bebd4f6afccef


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