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/tegra124/tegra124_cpufreq.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) 2016 Michal Meloun <mmel@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/cpu.h>
   34 #include <sys/kernel.h>
   35 #include <sys/lock.h>
   36 #include <sys/malloc.h>
   37 #include <sys/module.h>
   38 
   39 #include <machine/bus.h>
   40 #include <machine/cpu.h>
   41 
   42 #include <dev/extres/clk/clk.h>
   43 #include <dev/extres/regulator/regulator.h>
   44 #include <dev/ofw/ofw_bus_subr.h>
   45 
   46 #include <arm/nvidia/tegra_efuse.h>
   47 
   48 #include "cpufreq_if.h"
   49 
   50 #define XXX
   51 
   52 /* CPU voltage table entry */
   53 struct speedo_entry {
   54         uint64_t                freq;   /* Frequency point */
   55         int                     c0;     /* Coeeficient values for */
   56         int                     c1;     /* quadratic equation: */
   57         int                     c2;     /* c2 * speedo^2 + c1 * speedo + c0 */
   58 };
   59 
   60 struct cpu_volt_def {
   61         int                     min_uvolt;      /* Min allowed CPU voltage */
   62         int                     max_uvolt;      /* Max allowed CPU voltage */
   63         int                     step_uvolt;     /* Step of CPU voltage */
   64         int                     speedo_scale;   /* Scaling factor for cvt */
   65         int                     speedo_nitems;  /* Size of speedo table */
   66         struct speedo_entry     *speedo_tbl;    /* CPU voltage table */
   67 };
   68 
   69 struct cpu_speed_point {
   70         uint64_t                freq;           /* Frequecy */
   71         int                     uvolt;          /* Requested voltage */
   72 };
   73 
   74 static struct speedo_entry tegra124_speedo_dpll_tbl[] =
   75 {
   76         { 204000000ULL, 1112619, -29295, 402},
   77         { 306000000ULL, 1150460, -30585, 402},
   78         { 408000000ULL, 1190122, -31865, 402},
   79         { 510000000ULL, 1231606, -33155, 402},
   80         { 612000000ULL, 1274912, -34435, 402},
   81         { 714000000ULL, 1320040, -35725, 402},
   82         { 816000000ULL, 1366990, -37005, 402},
   83         { 918000000ULL, 1415762, -38295, 402},
   84         {1020000000ULL, 1466355, -39575, 402},
   85         {1122000000ULL, 1518771, -40865, 402},
   86         {1224000000ULL, 1573009, -42145, 402},
   87         {1326000000ULL, 1629068, -43435, 402},
   88         {1428000000ULL, 1686950, -44715, 402},
   89         {1530000000ULL, 1746653, -46005, 402},
   90         {1632000000ULL, 1808179, -47285, 402},
   91         {1734000000ULL, 1871526, -48575, 402},
   92         {1836000000ULL, 1936696, -49855, 402},
   93         {1938000000ULL, 2003687, -51145, 402},
   94         {2014500000ULL, 2054787, -52095, 402},
   95         {2116500000ULL, 2124957, -53385, 402},
   96         {2218500000ULL, 2196950, -54665, 402},
   97         {2320500000ULL, 2270765, -55955, 402},
   98         {2320500000ULL, 2270765, -55955, 402},
   99         {2422500000ULL, 2346401, -57235, 402},
  100         {2524500000ULL, 2437299, -58535, 402},
  101 };
  102 
  103 static struct cpu_volt_def tegra124_cpu_volt_dpll_def =
  104 {
  105         .min_uvolt =  900000,           /* 0.9 V */
  106         .max_uvolt = 1260000,           /* 1.26 */
  107         .step_uvolt =  10000,           /* 10 mV */
  108         .speedo_scale = 100,
  109         .speedo_nitems = nitems(tegra124_speedo_dpll_tbl),
  110         .speedo_tbl = tegra124_speedo_dpll_tbl,
  111 };
  112 
  113 static struct speedo_entry tegra124_speedo_pllx_tbl[] =
  114 {
  115         { 204000000ULL,  800000, 0, 0},
  116         { 306000000ULL,  800000, 0, 0},
  117         { 408000000ULL,  800000, 0, 0},
  118         { 510000000ULL,  800000, 0, 0},
  119         { 612000000ULL,  800000, 0, 0},
  120         { 714000000ULL,  800000, 0, 0},
  121         { 816000000ULL,  820000, 0, 0},
  122         { 918000000ULL,  840000, 0, 0},
  123         {1020000000ULL,  880000, 0, 0},
  124         {1122000000ULL,  900000, 0, 0},
  125         {1224000000ULL,  930000, 0, 0},
  126         {1326000000ULL,  960000, 0, 0},
  127         {1428000000ULL,  990000, 0, 0},
  128         {1530000000ULL, 1020000, 0, 0},
  129         {1632000000ULL, 1070000, 0, 0},
  130         {1734000000ULL, 1100000, 0, 0},
  131         {1836000000ULL, 1140000, 0, 0},
  132         {1938000000ULL, 1180000, 0, 0},
  133         {2014500000ULL, 1220000, 0, 0},
  134         {2116500000ULL, 1260000, 0, 0},
  135         {2218500000ULL, 1310000, 0, 0},
  136         {2320500000ULL, 1360000, 0, 0},
  137         {2397000000ULL, 1400000, 0, 0},
  138         {2499000000ULL, 1400000, 0, 0},
  139 };
  140 
  141 static struct cpu_volt_def tegra124_cpu_volt_pllx_def =
  142 {
  143         .min_uvolt = 1000000,           /* XXX 0.9 V doesn't work on all boards */
  144         .max_uvolt = 1260000,           /* 1.26 */
  145         .step_uvolt =  10000,           /* 10 mV */
  146         .speedo_scale = 100,
  147         .speedo_nitems = nitems(tegra124_speedo_pllx_tbl),
  148         .speedo_tbl = tegra124_speedo_pllx_tbl,
  149 };
  150 
  151 static uint64_t cpu_freq_tbl[] = {
  152          204000000ULL,
  153          306000000ULL,
  154          408000000ULL,
  155          510000000ULL,
  156          612000000ULL,
  157          714000000ULL,
  158          816000000ULL,
  159          918000000ULL,
  160         1020000000ULL,
  161         1122000000ULL,
  162         1224000000ULL,
  163         1326000000ULL,
  164         1428000000ULL,
  165         1530000000ULL,
  166         1632000000ULL,
  167         1734000000ULL,
  168         1836000000ULL,
  169         1938000000ULL,
  170         2014000000ULL,
  171         2116000000ULL,
  172         2218000000ULL,
  173         2320000000ULL,
  174         2422000000ULL,
  175         2524000000ULL,
  176 };
  177 
  178 static uint64_t cpu_max_freq[] = {
  179         2014500000ULL,
  180         2320500000ULL,
  181         2116500000ULL,
  182         2524500000ULL,
  183 };
  184 
  185 struct tegra124_cpufreq_softc {
  186         device_t                dev;
  187         phandle_t               node;
  188 
  189         regulator_t             supply_vdd_cpu;
  190         clk_t                   clk_cpu_g;
  191         clk_t                   clk_cpu_lp;
  192         clk_t                   clk_pll_x;
  193         clk_t                   clk_pll_p;
  194         clk_t                   clk_dfll;
  195 
  196         int                     process_id;
  197         int                     speedo_id;
  198         int                     speedo_value;
  199 
  200         uint64_t                cpu_max_freq;
  201         struct cpu_volt_def     *cpu_def;
  202         struct cpu_speed_point  *speed_points;
  203         int                     nspeed_points;
  204 
  205         struct cpu_speed_point  *act_speed_point;
  206 
  207         int                     latency;
  208 };
  209 
  210 static int cpufreq_lowest_freq = 1;
  211 TUNABLE_INT("hw.tegra124.cpufreq.lowest_freq", &cpufreq_lowest_freq);
  212 
  213 #define DIV_ROUND_CLOSEST(val, div)     (((val) + ((div) / 2)) / (div))
  214 
  215 #define ROUND_UP(val, div)      roundup(val, div)
  216 #define ROUND_DOWN(val, div)    rounddown(val, div)
  217 
  218 /*
  219  * Compute requesetd voltage for given frequency and SoC process variations,
  220  * - compute base voltage from speedo value using speedo table
  221  * - round up voltage to next regulator step
  222  * - clamp it to regulator limits
  223  */
  224 static int
  225 freq_to_voltage(struct tegra124_cpufreq_softc *sc, uint64_t freq)
  226 {
  227         int uv, scale, min_uvolt, max_uvolt, step_uvolt;
  228         struct speedo_entry *ent;
  229         int i;
  230 
  231         /* Get speedo entry with higher frequency */
  232         ent = NULL;
  233         for (i = 0; i < sc->cpu_def->speedo_nitems; i++) {
  234                 if (sc->cpu_def->speedo_tbl[i].freq >= freq) {
  235                         ent = &sc->cpu_def->speedo_tbl[i];
  236                         break;
  237                 }
  238         }
  239         if (ent == NULL)
  240                 ent = &sc->cpu_def->speedo_tbl[sc->cpu_def->speedo_nitems - 1];
  241         scale = sc->cpu_def->speedo_scale;
  242 
  243         /* uV = (c2 * speedo / scale + c1) * speedo / scale + c0) */
  244         uv = DIV_ROUND_CLOSEST(ent->c2 * sc->speedo_value, scale);
  245         uv = DIV_ROUND_CLOSEST((uv + ent->c1) * sc->speedo_value, scale) +
  246             ent->c0;
  247         step_uvolt = sc->cpu_def->step_uvolt;
  248         /* Round up it to next regulator step */
  249         uv = ROUND_UP(uv, step_uvolt);
  250 
  251         /* Clamp result */
  252         min_uvolt = ROUND_UP(sc->cpu_def->min_uvolt, step_uvolt);
  253         max_uvolt = ROUND_DOWN(sc->cpu_def->max_uvolt, step_uvolt);
  254         if (uv < min_uvolt)
  255                 uv =  min_uvolt;
  256         if (uv > max_uvolt)
  257                 uv =  max_uvolt;
  258         return (uv);
  259 
  260 }
  261 
  262 static void
  263 build_speed_points(struct tegra124_cpufreq_softc *sc) {
  264         int i;
  265 
  266         sc->nspeed_points = nitems(cpu_freq_tbl);
  267         sc->speed_points = malloc(sizeof(struct cpu_speed_point) *
  268             sc->nspeed_points, M_DEVBUF, M_NOWAIT);
  269         for (i = 0; i < sc->nspeed_points; i++) {
  270                 sc->speed_points[i].freq = cpu_freq_tbl[i];
  271                 sc->speed_points[i].uvolt = freq_to_voltage(sc,
  272                     cpu_freq_tbl[i]);
  273         }
  274 }
  275 
  276 static struct cpu_speed_point *
  277 get_speed_point(struct tegra124_cpufreq_softc *sc, uint64_t freq)
  278 {
  279         int i;
  280 
  281         if (sc->speed_points[0].freq >= freq)
  282                 return (sc->speed_points + 0);
  283 
  284         for (i = 0; i < sc->nspeed_points - 1; i++) {
  285                 if (sc->speed_points[i + 1].freq > freq)
  286                         return (sc->speed_points + i);
  287         }
  288 
  289         return (sc->speed_points + sc->nspeed_points - 1);
  290 }
  291 
  292 static int
  293 tegra124_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
  294 {
  295         struct tegra124_cpufreq_softc *sc;
  296         int i, j;
  297 
  298         if (sets == NULL || count == NULL)
  299                 return (EINVAL);
  300 
  301         sc = device_get_softc(dev);
  302         memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
  303 
  304         for (i = 0, j = sc->nspeed_points - 1; j >= 0; j--) {
  305                 if (sc->cpu_max_freq < sc->speed_points[j].freq)
  306                         continue;
  307                 sets[i].freq = sc->speed_points[j].freq / 1000000;
  308                 sets[i].volts = sc->speed_points[j].uvolt / 1000;
  309                 sets[i].lat = sc->latency;
  310                 sets[i].dev = dev;
  311                 i++;
  312         }
  313         *count = i;
  314 
  315         return (0);
  316 }
  317 
  318 static int
  319 set_cpu_freq(struct tegra124_cpufreq_softc *sc, uint64_t freq)
  320 {
  321         struct cpu_speed_point *point;
  322         int rv;
  323 
  324         point = get_speed_point(sc, freq);
  325 
  326         if (sc->act_speed_point->uvolt < point->uvolt) {
  327                 /* set cpu voltage */
  328                 rv = regulator_set_voltage(sc->supply_vdd_cpu,
  329                     point->uvolt, point->uvolt);
  330                 DELAY(10000);
  331                 if (rv != 0)
  332                         return (rv);
  333         }
  334 
  335         /* Switch supermux to PLLP first */
  336         rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_p);
  337         if (rv != 0) {
  338                 device_printf(sc->dev, "Can't set parent to PLLP\n");
  339                 return (rv);
  340         }
  341 
  342         /* Set PLLX frequency */
  343         rv = clk_set_freq(sc->clk_pll_x, point->freq, CLK_SET_ROUND_DOWN);
  344         if (rv != 0) {
  345                 device_printf(sc->dev, "Can't set CPU clock frequency\n");
  346                 return (rv);
  347         }
  348 
  349         rv = clk_set_parent_by_clk(sc->clk_cpu_g, sc->clk_pll_x);
  350         if (rv != 0) {
  351                 device_printf(sc->dev, "Can't set parent to PLLX\n");
  352                 return (rv);
  353         }
  354 
  355         if (sc->act_speed_point->uvolt > point->uvolt) {
  356                 /* set cpu voltage */
  357                 rv = regulator_set_voltage(sc->supply_vdd_cpu,
  358                     point->uvolt, point->uvolt);
  359                 if (rv != 0)
  360                         return (rv);
  361         }
  362 
  363         sc->act_speed_point = point;
  364 
  365         return (0);
  366 }
  367 
  368 static int
  369 tegra124_cpufreq_set(device_t dev, const struct cf_setting *cf)
  370 {
  371         struct tegra124_cpufreq_softc *sc;
  372         uint64_t freq;
  373         int rv;
  374 
  375         if (cf == NULL || cf->freq < 0)
  376                 return (EINVAL);
  377 
  378         sc = device_get_softc(dev);
  379 
  380         freq = cf->freq;
  381         if (freq < cpufreq_lowest_freq)
  382                 freq = cpufreq_lowest_freq;
  383         freq *= 1000000;
  384         if (freq >= sc->cpu_max_freq)
  385                 freq = sc->cpu_max_freq;
  386         rv = set_cpu_freq(sc, freq);
  387 
  388         return (rv);
  389 }
  390 
  391 static int
  392 tegra124_cpufreq_get(device_t dev, struct cf_setting *cf)
  393 {
  394         struct tegra124_cpufreq_softc *sc;
  395 
  396         if (cf == NULL)
  397                 return (EINVAL);
  398 
  399         sc = device_get_softc(dev);
  400         memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
  401         cf->dev = NULL;
  402         cf->freq = sc->act_speed_point->freq / 1000000;
  403         cf->volts = sc->act_speed_point->uvolt / 1000;
  404         /* Transition latency in us. */
  405         cf->lat = sc->latency;
  406         /* Driver providing this setting. */
  407         cf->dev = dev;
  408 
  409         return (0);
  410 }
  411 
  412 static int
  413 tegra124_cpufreq_type(device_t dev, int *type)
  414 {
  415 
  416         if (type == NULL)
  417                 return (EINVAL);
  418         *type = CPUFREQ_TYPE_ABSOLUTE;
  419 
  420         return (0);
  421 }
  422 
  423 static int
  424 get_fdt_resources(struct tegra124_cpufreq_softc *sc, phandle_t node)
  425 {
  426         int rv;
  427         device_t parent_dev;
  428 
  429         parent_dev =  device_get_parent(sc->dev);
  430         rv = regulator_get_by_ofw_property(parent_dev, 0, "vdd-cpu-supply",
  431             &sc->supply_vdd_cpu);
  432         if (rv != 0) {
  433                 device_printf(sc->dev, "Cannot get 'vdd-cpu' regulator\n");
  434                 return (rv);
  435         }
  436 
  437         rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_g", &sc->clk_cpu_g);
  438         if (rv != 0) {
  439                 device_printf(sc->dev, "Cannot get 'cpu_g' clock: %d\n", rv);
  440                 return (ENXIO);
  441         }
  442 
  443         rv = clk_get_by_ofw_name(parent_dev, 0, "cpu_lp", &sc->clk_cpu_lp);
  444         if (rv != 0) {
  445                 device_printf(sc->dev, "Cannot get 'cpu_lp' clock\n");
  446                 return (ENXIO);
  447         }
  448 
  449         rv = clk_get_by_ofw_name(parent_dev, 0, "pll_x", &sc->clk_pll_x);
  450         if (rv != 0) {
  451                 device_printf(sc->dev, "Cannot get 'pll_x' clock\n");
  452                 return (ENXIO);
  453         }
  454         rv = clk_get_by_ofw_name(parent_dev, 0, "pll_p", &sc->clk_pll_p);
  455         if (rv != 0) {
  456                 device_printf(parent_dev, "Cannot get 'pll_p' clock\n");
  457                 return (ENXIO);
  458         }
  459         rv = clk_get_by_ofw_name(parent_dev, 0, "dfll", &sc->clk_dfll);
  460         if (rv != 0) {
  461                 /* XXX DPLL is not implemented yet */
  462 /*
  463                 device_printf(sc->dev, "Cannot get 'dfll' clock\n");
  464                 return (ENXIO);
  465 */
  466         }
  467         return (0);
  468 }
  469 
  470 static void
  471 tegra124_cpufreq_identify(driver_t *driver, device_t parent)
  472 {
  473         phandle_t root;
  474 
  475         root = OF_finddevice("/");
  476         if (!ofw_bus_node_is_compatible(root, "nvidia,tegra124"))
  477                 return;
  478 
  479         if (device_get_unit(parent) != 0)
  480                 return;
  481         if (device_find_child(parent, "tegra124_cpufreq", -1) != NULL)
  482                 return;
  483         if (BUS_ADD_CHILD(parent, 0, "tegra124_cpufreq", -1) == NULL)
  484                 device_printf(parent, "add child failed\n");
  485 }
  486 
  487 static int
  488 tegra124_cpufreq_probe(device_t dev)
  489 {
  490 
  491         device_set_desc(dev, "CPU Frequency Control");
  492 
  493         return (0);
  494 }
  495 
  496 static int
  497 tegra124_cpufreq_attach(device_t dev)
  498 {
  499         struct tegra124_cpufreq_softc *sc;
  500         uint64_t freq;
  501         int rv;
  502 
  503         sc = device_get_softc(dev);
  504         sc->dev = dev;
  505         sc->node = ofw_bus_get_node(device_get_parent(dev));
  506 
  507         sc->process_id = tegra_sku_info.cpu_process_id;
  508         sc->speedo_id = tegra_sku_info.cpu_speedo_id;
  509         sc->speedo_value = tegra_sku_info.cpu_speedo_value;
  510 
  511         /* Tegra 124 */
  512         /* XXX DPLL is not implemented yet */
  513         if (1)
  514                 sc->cpu_def = &tegra124_cpu_volt_pllx_def;
  515         else
  516                 sc->cpu_def = &tegra124_cpu_volt_dpll_def;
  517 
  518         rv = get_fdt_resources(sc, sc->node);
  519         if (rv !=  0) {
  520                 return (rv);
  521         }
  522 
  523         build_speed_points(sc);
  524 
  525         rv = clk_get_freq(sc->clk_cpu_g, &freq);
  526         if (rv != 0) {
  527                 device_printf(dev, "Can't get CPU clock frequency\n");
  528                 return (rv);
  529         }
  530         if (sc->speedo_id < nitems(cpu_max_freq))
  531                 sc->cpu_max_freq = cpu_max_freq[sc->speedo_id];
  532         else
  533                 sc->cpu_max_freq = cpu_max_freq[0];
  534         sc->act_speed_point = get_speed_point(sc, freq);
  535 
  536         /* Set safe startup CPU frequency. */
  537         rv = set_cpu_freq(sc, 1632000000);
  538         if (rv != 0) {
  539                 device_printf(dev, "Can't set initial CPU clock frequency\n");
  540                 return (rv);
  541         }
  542 
  543         /* This device is controlled by cpufreq(4). */
  544         cpufreq_register(dev);
  545 
  546         return (0);
  547 }
  548 
  549 static int
  550 tegra124_cpufreq_detach(device_t dev)
  551 {
  552         struct tegra124_cpufreq_softc *sc;
  553 
  554         sc = device_get_softc(dev);
  555         cpufreq_unregister(dev);
  556 
  557         if (sc->supply_vdd_cpu != NULL)
  558                 regulator_release(sc->supply_vdd_cpu);
  559 
  560         if (sc->clk_cpu_g != NULL)
  561                 clk_release(sc->clk_cpu_g);
  562         if (sc->clk_cpu_lp != NULL)
  563                 clk_release(sc->clk_cpu_lp);
  564         if (sc->clk_pll_x != NULL)
  565                 clk_release(sc->clk_pll_x);
  566         if (sc->clk_pll_p != NULL)
  567                 clk_release(sc->clk_pll_p);
  568         if (sc->clk_dfll != NULL)
  569                 clk_release(sc->clk_dfll);
  570         return (0);
  571 }
  572 
  573 static device_method_t tegra124_cpufreq_methods[] = {
  574         /* Device interface */
  575         DEVMETHOD(device_identify,      tegra124_cpufreq_identify),
  576         DEVMETHOD(device_probe,         tegra124_cpufreq_probe),
  577         DEVMETHOD(device_attach,        tegra124_cpufreq_attach),
  578         DEVMETHOD(device_detach,        tegra124_cpufreq_detach),
  579 
  580         /* cpufreq interface */
  581         DEVMETHOD(cpufreq_drv_set,      tegra124_cpufreq_set),
  582         DEVMETHOD(cpufreq_drv_get,      tegra124_cpufreq_get),
  583         DEVMETHOD(cpufreq_drv_settings, tegra124_cpufreq_settings),
  584         DEVMETHOD(cpufreq_drv_type,     tegra124_cpufreq_type),
  585 
  586         DEVMETHOD_END
  587 };
  588 
  589 static DEFINE_CLASS_0(tegra124_cpufreq, tegra124_cpufreq_driver,
  590     tegra124_cpufreq_methods, sizeof(struct tegra124_cpufreq_softc));
  591 DRIVER_MODULE(tegra124_cpufreq, cpu, tegra124_cpufreq_driver, NULL, NULL);

Cache object: d3d6b0b15f96803f63e1a6336ffd9b65


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