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/nvidia/tegra_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 Michal Meloun
    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 #include <sys/rman.h>
   41 
   42 #include <machine/bus.h>
   43 #include <machine/resource.h>
   44 
   45 #include <dev/extres/clk/clk.h>
   46 #include <dev/extres/hwreset/hwreset.h>
   47 #include <dev/ofw/ofw_bus.h>
   48 #include <dev/ofw/ofw_bus_subr.h>
   49 
   50 #include <arm/nvidia/tegra_efuse.h>
   51 
   52 #define FUSES_START     0x100
   53 #define RD4(_sc, _r)    bus_read_4((_sc)->mem_res, (FUSES_START + (_r)))
   54 
   55 struct efuse_soc;
   56 struct tegra_efuse_softc {
   57         device_t                dev;
   58         struct resource         *mem_res;
   59 
   60         struct efuse_soc        *soc;
   61         clk_t                   clk;
   62         hwreset_t               reset;
   63 };
   64 
   65 struct tegra_efuse_softc *dev_sc;
   66 struct tegra_sku_info tegra_sku_info;
   67 static char *tegra_rev_name[] = {
   68         [TEGRA_REVISION_UNKNOWN] = "unknown",
   69         [TEGRA_REVISION_A01]     = "A01",
   70         [TEGRA_REVISION_A02]     = "A02",
   71         [TEGRA_REVISION_A03]     = "A03",
   72         [TEGRA_REVISION_A03p]    = "A03 prime",
   73         [TEGRA_REVISION_A04]     = "A04",
   74 };
   75 
   76 struct efuse_soc {
   77         void    (*init)(struct tegra_efuse_softc *sc,
   78                     struct tegra_sku_info *sku);
   79 };
   80 
   81 static void tegra124_init(struct tegra_efuse_softc *sc,
   82     struct tegra_sku_info *sku);
   83 struct efuse_soc tegra124_efuse_soc = {
   84         .init = tegra124_init,
   85 };
   86 
   87 static void tegra210_init(struct tegra_efuse_softc *sc,
   88     struct tegra_sku_info *sku);
   89 struct efuse_soc tegra210_efuse_soc = {
   90         .init = tegra210_init,
   91 };
   92 
   93 static struct ofw_compat_data compat_data[] = {
   94         {"nvidia,tegra124-efuse", (intptr_t)&tegra124_efuse_soc},
   95         {"nvidia,tegra210-efuse", (intptr_t)&tegra210_efuse_soc},
   96         {NULL,                  0}
   97 };
   98 
   99 /* ---------------------- Tegra 124 specific code & data --------------- */
  100 #define TEGRA124_CPU_PROCESS_CORNERS    2
  101 #define TEGRA124_GPU_PROCESS_CORNERS    2
  102 #define TEGRA124_SOC_PROCESS_CORNERS    2
  103 
  104 #define TEGRA124_FUSE_SKU_INFO          0x10
  105 #define TEGRA124_FUSE_CPU_SPEEDO_0      0x14
  106 #define TEGRA124_FUSE_CPU_IDDQ          0x18
  107 #define TEGRA124_FUSE_FT_REV            0x28
  108 #define TEGRA124_FUSE_CPU_SPEEDO_1      0x2c
  109 #define TEGRA124_FUSE_CPU_SPEEDO_2      0x30
  110 #define TEGRA124_FUSE_SOC_SPEEDO_0      0x34
  111 #define TEGRA124_FUSE_SOC_SPEEDO_1      0x38
  112 #define TEGRA124_FUSE_SOC_SPEEDO_2      0x3c
  113 #define TEGRA124_FUSE_SOC_IDDQ          0x40
  114 #define TEGRA124_FUSE_GPU_IDDQ          0x128
  115 
  116 enum {
  117         TEGRA124_THRESHOLD_INDEX_0,
  118         TEGRA124_THRESHOLD_INDEX_1,
  119         TEGRA124_THRESHOLD_INDEX_COUNT,
  120 };
  121 
  122 static uint32_t tegra124_cpu_process_speedos[][TEGRA124_CPU_PROCESS_CORNERS] =
  123 {
  124         {2190,  UINT_MAX},
  125         {0,     UINT_MAX},
  126 };
  127 
  128 static uint32_t tegra124_gpu_process_speedos[][TEGRA124_GPU_PROCESS_CORNERS] =
  129 {
  130         {1965,  UINT_MAX},
  131         {0,     UINT_MAX},
  132 };
  133 
  134 static uint32_t tegra124_soc_process_speedos[][TEGRA124_SOC_PROCESS_CORNERS] =
  135 {
  136         {2101,  UINT_MAX},
  137         {0,     UINT_MAX},
  138 };
  139 
  140 
  141 static void
  142 tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
  143     struct tegra_sku_info *sku, int *threshold)
  144 {
  145 
  146         /* Set default */
  147         sku->cpu_speedo_id = 0;
  148         sku->soc_speedo_id = 0;
  149         sku->gpu_speedo_id = 0;
  150         *threshold = TEGRA124_THRESHOLD_INDEX_0;
  151 
  152         switch (sku->sku_id) {
  153         case 0x00: /* Eng sku */
  154         case 0x0F:
  155         case 0x23:
  156                 /* Using the default */
  157                 break;
  158         case 0x83:
  159                 sku->cpu_speedo_id = 2;
  160                 break;
  161 
  162         case 0x1F:
  163         case 0x87:
  164         case 0x27:
  165                 sku->cpu_speedo_id = 2;
  166                 sku->soc_speedo_id = 0;
  167                 sku->gpu_speedo_id = 1;
  168                 *threshold = TEGRA124_THRESHOLD_INDEX_0;
  169                 break;
  170         case 0x81:
  171         case 0x21:
  172         case 0x07:
  173                 sku->cpu_speedo_id = 1;
  174                 sku->soc_speedo_id = 1;
  175                 sku->gpu_speedo_id = 1;
  176                 *threshold = TEGRA124_THRESHOLD_INDEX_1;
  177                 break;
  178         case 0x49:
  179         case 0x4A:
  180         case 0x48:
  181                 sku->cpu_speedo_id = 4;
  182                 sku->soc_speedo_id = 2;
  183                 sku->gpu_speedo_id = 3;
  184                 *threshold = TEGRA124_THRESHOLD_INDEX_1;
  185                 break;
  186         default:
  187                 device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id);
  188                 break;
  189         }
  190 }
  191 
  192 static void
  193 tegra124_init(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
  194 {
  195         int i, threshold;
  196 
  197         sku->sku_id = RD4(sc, TEGRA124_FUSE_SKU_INFO);
  198         sku->soc_iddq_value = RD4(sc, TEGRA124_FUSE_SOC_IDDQ);
  199         sku->cpu_iddq_value = RD4(sc, TEGRA124_FUSE_CPU_IDDQ);
  200         sku->gpu_iddq_value = RD4(sc, TEGRA124_FUSE_GPU_IDDQ);
  201         sku->soc_speedo_value = RD4(sc, TEGRA124_FUSE_SOC_SPEEDO_0);
  202         sku->cpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_0);
  203         sku->gpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_2);
  204 
  205         if (sku->cpu_speedo_value == 0) {
  206                 device_printf(sc->dev, "CPU Speedo value is not fused.\n");
  207                 return;
  208         }
  209 
  210         tegra124_rev_sku_to_speedo_ids(sc, sku, &threshold);
  211 
  212         for (i = 0; i < TEGRA124_SOC_PROCESS_CORNERS; i++) {
  213                 if (sku->soc_speedo_value <
  214                         tegra124_soc_process_speedos[threshold][i])
  215                         break;
  216         }
  217         sku->soc_process_id = i;
  218 
  219         for (i = 0; i < TEGRA124_CPU_PROCESS_CORNERS; i++) {
  220                 if (sku->cpu_speedo_value <
  221                         tegra124_cpu_process_speedos[threshold][i])
  222                                 break;
  223         }
  224         sku->cpu_process_id = i;
  225 
  226         for (i = 0; i < TEGRA124_GPU_PROCESS_CORNERS; i++) {
  227                 if (sku->gpu_speedo_value <
  228                         tegra124_gpu_process_speedos[threshold][i])
  229                         break;
  230         }
  231         sku->gpu_process_id = i;
  232 
  233 }
  234 /* ----------------- End of Tegra 124 specific code & data --------------- */
  235 
  236 /* -------------------- Tegra 201 specific code & data ------------------- */
  237 #define TEGRA210_CPU_PROCESS_CORNERS    2
  238 #define TEGRA210_GPU_PROCESS_CORNERS    2
  239 #define TEGRA210_SOC_PROCESS_CORNERS    3
  240 
  241 #define TEGRA210_FUSE_SKU_INFO          0x010
  242 #define TEGRA210_FUSE_CPU_SPEEDO_0      0x014
  243 #define TEGRA210_FUSE_CPU_IDDQ          0x018
  244 #define TEGRA210_FUSE_FT_REV            0x028
  245 #define TEGRA210_FUSE_CPU_SPEEDO_1      0x02c
  246 #define TEGRA210_FUSE_CPU_SPEEDO_2      0x030
  247 #define TEGRA210_FUSE_SOC_SPEEDO_0      0x034
  248 #define TEGRA210_FUSE_SOC_SPEEDO_1      0x038
  249 #define TEGRA210_FUSE_SOC_SPEEDO_2      0x03c
  250 #define TEGRA210_FUSE_SOC_IDDQ          0x040
  251 #define TEGRA210_FUSE_GPU_IDDQ          0x128
  252 #define TEGRA210_FUSE_SPARE             0x270
  253 
  254 enum {
  255         TEGRA210_THRESHOLD_INDEX_0,
  256         TEGRA210_THRESHOLD_INDEX_1,
  257         TEGRA210_THRESHOLD_INDEX_COUNT,
  258 };
  259 
  260 static uint32_t tegra210_cpu_process_speedos[][TEGRA210_CPU_PROCESS_CORNERS] =
  261 {
  262         {2119, UINT_MAX},
  263         {2119, UINT_MAX},
  264 };
  265 
  266 static uint32_t tegra210_gpu_process_speedos[][TEGRA210_GPU_PROCESS_CORNERS] =
  267 {
  268         {UINT_MAX, UINT_MAX},
  269         {UINT_MAX, UINT_MAX},
  270 };
  271 
  272 static uint32_t tegra210_soc_process_speedos[][TEGRA210_SOC_PROCESS_CORNERS] =
  273 {
  274         {1950, 2100, UINT_MAX},
  275         {1950, 2100, UINT_MAX},
  276 };
  277 
  278 static uint32_t
  279 tegra210_get_speedo_revision(struct tegra_efuse_softc *sc)
  280 {
  281         uint32_t reg;
  282         uint32_t val;
  283 
  284         val = 0;
  285 
  286         /* Revision i encoded in spare fields */
  287         reg = RD4(sc, TEGRA210_FUSE_SPARE + 2 * 4);
  288         val |=  (reg & 1) << 0;
  289         reg = RD4(sc, TEGRA210_FUSE_SPARE + 3 * 4);
  290         val |=  (reg & 1) << 1;
  291         reg = RD4(sc, TEGRA210_FUSE_SPARE + 4 * 4);
  292         val |=  (reg & 1) << 2;
  293 
  294         return (val);
  295 }
  296 
  297 
  298 static void
  299 tegra210_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
  300     struct tegra_sku_info *sku, int speedo_rev, int *threshold)
  301 {
  302 
  303         /* Set defaults */
  304         sku->cpu_speedo_id = 0;
  305         sku->soc_speedo_id = 0;
  306         sku->gpu_speedo_id = 0;
  307         *threshold = TEGRA210_THRESHOLD_INDEX_0;
  308 
  309         switch (sku->sku_id) {
  310         case 0x00: /* Eng sku */
  311         case 0x01: /* Eng sku */
  312         case 0x07:
  313         case 0x17:
  314         case 0x27:
  315                 /* Use defaults */
  316                 if (speedo_rev >= 2)
  317                         sku->gpu_speedo_id = 1;
  318                 break;
  319         case 0x13:
  320                 if (speedo_rev >= 2)
  321                         sku->gpu_speedo_id = 1;
  322                 sku->cpu_speedo_id = 1;
  323                 break;
  324 
  325         default:
  326                 device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id);
  327                 break;
  328         }
  329 }
  330 
  331 
  332 static void
  333 tegra210_init(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
  334 {
  335         int i, threshold, speedo_rev;
  336         uint32_t cpu_speedo[3], soc_speedo[3];
  337         uint32_t cpu_iddq, soc_iddq, gpu_iddq;
  338 
  339         cpu_speedo[0] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_0);
  340         cpu_speedo[1] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_1);
  341         cpu_speedo[2] = RD4(sc, TEGRA210_FUSE_CPU_SPEEDO_2);
  342         soc_speedo[0] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_0);
  343         soc_speedo[1] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_1);
  344         soc_speedo[2] = RD4(sc, TEGRA210_FUSE_SOC_SPEEDO_2);
  345 
  346 
  347         sku->cpu_iddq_value = RD4(sc, TEGRA210_FUSE_CPU_IDDQ);
  348         sku->soc_iddq_value = RD4(sc, TEGRA210_FUSE_SOC_IDDQ);
  349         sku->gpu_iddq_value = RD4(sc, TEGRA210_FUSE_GPU_IDDQ);
  350 
  351         cpu_iddq = RD4(sc, TEGRA210_FUSE_CPU_IDDQ) * 4;
  352         soc_iddq = RD4(sc, TEGRA210_FUSE_SOC_IDDQ) * 4;
  353         gpu_iddq = RD4(sc, TEGRA210_FUSE_GPU_IDDQ) * 5;
  354 
  355         speedo_rev = tegra210_get_speedo_revision(sc);
  356 device_printf(sc->dev, " Speedo revision: %u\n", speedo_rev);
  357 
  358         if (speedo_rev >= 3) {
  359                 sku->cpu_speedo_value = cpu_speedo[0];
  360                 sku->gpu_speedo_value = cpu_speedo[2];
  361                 sku->soc_speedo_value = soc_speedo[0];
  362         } else if (speedo_rev == 2) {
  363                 sku->cpu_speedo_value =
  364                     (-1938 + (1095 * cpu_speedo[0] / 100)) / 10;
  365                 sku->gpu_speedo_value =
  366                     (-1662 + (1082 * cpu_speedo[2] / 100)) / 10;
  367                 sku->soc_speedo_value =
  368                     ( -705 + (1037 * soc_speedo[0] / 100)) / 10;
  369         } else {
  370                 sku->cpu_speedo_value = 2100;
  371                 sku->gpu_speedo_value = cpu_speedo[2] - 75;
  372                 sku->soc_speedo_value = 1900;
  373         }
  374 
  375         tegra210_rev_sku_to_speedo_ids(sc, sku, speedo_rev, &threshold);
  376 
  377         for (i = 0; i < TEGRA210_SOC_PROCESS_CORNERS; i++) {
  378                 if (sku->soc_speedo_value <
  379                         tegra210_soc_process_speedos[threshold][i])
  380                         break;
  381         }
  382         sku->soc_process_id = i;
  383 
  384         for (i = 0; i < TEGRA210_CPU_PROCESS_CORNERS; i++) {
  385                 if (sku->cpu_speedo_value <
  386                         tegra210_cpu_process_speedos[threshold][i])
  387                                 break;
  388         }
  389         sku->cpu_process_id = i;
  390 
  391         for (i = 0; i < TEGRA210_GPU_PROCESS_CORNERS; i++) {
  392                 if (sku->gpu_speedo_value <
  393                         tegra210_gpu_process_speedos[threshold][i])
  394                         break;
  395         }
  396         sku->gpu_process_id = i;
  397 
  398 }
  399 
  400 /* ----------------- End of Tegra 210 specific code & data --------------- */
  401 
  402 
  403 uint32_t
  404 tegra_fuse_read_4(int addr) {
  405         if (dev_sc == NULL)
  406                 panic("tegra_fuse_read_4 called too early");
  407         return (RD4(dev_sc, addr));
  408 }
  409 
  410 static void
  411 tegra_efuse_dump_sku(void)
  412 {
  413         printf(" TEGRA SKU Info:\n");
  414         printf("  chip_id: %u\n", tegra_sku_info.chip_id);
  415         printf("  sku_id: %u\n", tegra_sku_info.sku_id);
  416         printf("  cpu_process_id: %u\n", tegra_sku_info.cpu_process_id);
  417         printf("  cpu_speedo_id: %u\n", tegra_sku_info.cpu_speedo_id);
  418         printf("  cpu_speedo_value: %u\n", tegra_sku_info.cpu_speedo_value);
  419         printf("  cpu_iddq_value: %u\n", tegra_sku_info.cpu_iddq_value);
  420         printf("  soc_process_id: %u\n", tegra_sku_info.soc_process_id);
  421         printf("  soc_speedo_id: %u\n", tegra_sku_info.soc_speedo_id);
  422         printf("  soc_speedo_value: %u\n", tegra_sku_info.soc_speedo_value);
  423         printf("  soc_iddq_value: %u\n", tegra_sku_info.soc_iddq_value);
  424         printf("  gpu_process_id: %u\n", tegra_sku_info.gpu_process_id);
  425         printf("  gpu_speedo_id: %u\n", tegra_sku_info.gpu_speedo_id);
  426         printf("  gpu_speedo_value: %u\n", tegra_sku_info.gpu_speedo_value);
  427         printf("  gpu_iddq_value: %u\n", tegra_sku_info.gpu_iddq_value);
  428         printf("  revision: %s\n", tegra_rev_name[tegra_sku_info.revision]);
  429 }
  430 
  431 static int
  432 tegra_efuse_probe(device_t dev)
  433 {
  434         if (!ofw_bus_status_okay(dev))
  435                 return (ENXIO);
  436 
  437         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  438                 return (ENXIO);
  439 
  440         return (BUS_PROBE_DEFAULT);
  441 }
  442 
  443 static int
  444 tegra_efuse_attach(device_t dev)
  445 {
  446         int rv, rid;
  447         phandle_t node;
  448         struct tegra_efuse_softc *sc;
  449 
  450         sc = device_get_softc(dev);
  451         sc->dev = dev;
  452         node = ofw_bus_get_node(dev);
  453         sc->soc = (struct efuse_soc *)ofw_bus_search_compatible(dev,
  454             compat_data)->ocd_data;
  455 
  456         /* Get the memory resource for the register mapping. */
  457         rid = 0;
  458         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  459             RF_ACTIVE);
  460         if (sc->mem_res == NULL) {
  461                 device_printf(dev, "Cannot map registers.\n");
  462                 rv = ENXIO;
  463                 goto fail;
  464         }
  465 
  466         /* OFW resources. */
  467         rv = clk_get_by_ofw_name(dev, 0, "fuse", &sc->clk);
  468         if (rv != 0) {
  469                 device_printf(dev, "Cannot get fuse clock: %d\n", rv);
  470                 goto fail;
  471         }
  472         rv = clk_enable(sc->clk);
  473         if (rv != 0) {
  474                 device_printf(dev, "Cannot enable clock: %d\n", rv);
  475                 goto fail;
  476         }
  477         rv = hwreset_get_by_ofw_name(sc->dev, 0, "fuse", &sc->reset);
  478         if (rv != 0) {
  479                 device_printf(dev, "Cannot get fuse reset\n");
  480                 goto fail;
  481         }
  482         rv = hwreset_deassert(sc->reset);
  483         if (rv != 0) {
  484                 device_printf(sc->dev, "Cannot clear reset\n");
  485                 goto fail;
  486         }
  487 
  488         sc->soc->init(sc, &tegra_sku_info);
  489 
  490         dev_sc = sc;
  491 
  492         if (bootverbose)
  493                 tegra_efuse_dump_sku();
  494         return (bus_generic_attach(dev));
  495 
  496 fail:
  497         dev_sc = NULL;
  498         if (sc->clk != NULL)
  499                 clk_release(sc->clk);
  500         if (sc->reset != NULL)
  501                 hwreset_release(sc->reset);
  502         if (sc->mem_res != NULL)
  503                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  504 
  505         return (rv);
  506 }
  507 
  508 static int
  509 tegra_efuse_detach(device_t dev)
  510 {
  511         struct tegra_efuse_softc *sc;
  512 
  513         sc = device_get_softc(dev);
  514         dev_sc = NULL;
  515         if (sc->clk != NULL)
  516                 clk_release(sc->clk);
  517         if (sc->reset != NULL)
  518                 hwreset_release(sc->reset);
  519         if (sc->mem_res != NULL)
  520                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  521 
  522         return (bus_generic_detach(dev));
  523 }
  524 
  525 static device_method_t tegra_efuse_methods[] = {
  526         /* Device interface */
  527         DEVMETHOD(device_probe,         tegra_efuse_probe),
  528         DEVMETHOD(device_attach,        tegra_efuse_attach),
  529         DEVMETHOD(device_detach,        tegra_efuse_detach),
  530 
  531         DEVMETHOD_END
  532 };
  533 
  534 static devclass_t tegra_efuse_devclass;
  535 static DEFINE_CLASS_0(efuse, tegra_efuse_driver, tegra_efuse_methods,
  536     sizeof(struct tegra_efuse_softc));
  537 EARLY_DRIVER_MODULE(tegra_efuse, simplebus, tegra_efuse_driver,
  538     tegra_efuse_devclass, NULL, NULL, BUS_PASS_TIMER);

Cache object: a6e4aa89372aed75d7534f378476dd28


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