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/arm64/rockchip/rk_tsadc.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 /*
   32  * Thermometer and thermal zones driver for RockChip SoCs.
   33  * Calibration data are taken from Linux, because this part of SoC
   34  * is undocumented in TRM.
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/bus.h>
   40 #include <sys/gpio.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/malloc.h>
   44 #include <sys/rman.h>
   45 #include <sys/sysctl.h>
   46 
   47 #include <machine/bus.h>
   48 
   49 #include <dev/extres/clk/clk.h>
   50 #include <dev/extres/hwreset/hwreset.h>
   51 #include <dev/extres/syscon/syscon.h>
   52 #include <dev/ofw/ofw_bus.h>
   53 #include <dev/ofw/ofw_bus_subr.h>
   54 
   55 #include "syscon_if.h"
   56 #include "rk_tsadc_if.h"
   57 
   58 /* Version of HW */
   59 #define TSADC_V2                                1
   60 #define TSADC_V3                                2
   61 #define TSADC_V7                                3
   62 
   63 /* Global registers */
   64 #define TSADC_USER_CON                          0x000
   65 #define TSADC_AUTO_CON                          0x004
   66 #define  TSADC_AUTO_CON_POL_HI                          (1 << 8)
   67 #define  TSADC_AUTO_SRC_EN(x)                           (1 << (4 + (x)))
   68 #define  TSADC_AUTO_Q_SEL                               (1 << 1) /* V3 only */
   69 #define  TSADC_AUTO_CON_AUTO                            (1 << 0)
   70 
   71 #define TSADC_INT_EN                            0x008
   72 #define  TSADC_INT_EN_2CRU_EN_SRC(x)                    (1 << (8 + (x)))
   73 #define  TSADC_INT_EN_2GPIO_EN_SRC(x)                   (1 << (4 + (x)))
   74 #define TSADC_INT_PD                            0x00c
   75 #define TSADC_DATA(x)                           (0x20 + (x) * 0x04)
   76 #define TSADC_COMP_INT(x)                       (0x30 + (x) * 0x04)
   77 #define  TSADC_COMP_INT_SRC_EN(x)                       (1 << (0 + (x)))
   78 #define TSADC_COMP_SHUT(x)                      (0x40 + (x) * 0x04)
   79 #define TSADC_HIGHT_INT_DEBOUNCE                0x060
   80 #define TSADC_HIGHT_TSHUT_DEBOUNCE              0x064
   81 #define TSADC_AUTO_PERIOD                       0x068
   82 #define TSADC_AUTO_PERIOD_HT                    0x06c
   83 #define TSADC_COMP0_LOW_INT                     0x080   /* V3 only */
   84 #define TSADC_COMP1_LOW_INT                     0x084   /* V3 only */
   85 
   86 /* V3 GFR registers */
   87 #define GRF_SARADC_TESTBIT                      0x0e644
   88 #define  GRF_SARADC_TESTBIT_ON                          (0x10001 << 2)
   89 #define GRF_TSADC_TESTBIT_L                     0x0e648
   90 #define  GRF_TSADC_VCM_EN_L                             (0x10001 << 7)
   91 #define GRF_TSADC_TESTBIT_H                     0x0e64c
   92 #define  GRF_TSADC_VCM_EN_H                             (0x10001 << 7)
   93 #define  GRF_TSADC_TESTBIT_H_ON                         (0x10001 << 2)
   94 
   95 /* V7 GRF register */
   96 #define GRF_TSADC_CON                           0x0600
   97 #define  GRF_TSADC_ANA_REG0                     (0x10001 << 0)
   98 #define  GRF_TSADC_ANA_REG1                     (0x10001 << 1)
   99 #define  GRF_TSADC_ANA_REG2                     (0x10001 << 2)
  100 #define  GRF_TSADC_TSEN                         (0x10001 << 8)
  101 
  102 #define WR4(_sc, _r, _v)        bus_write_4((_sc)->mem_res, (_r), (_v))
  103 #define RD4(_sc, _r)            bus_read_4((_sc)->mem_res, (_r))
  104 
  105 static struct sysctl_ctx_list tsadc_sysctl_ctx;
  106 
  107 struct tsensor {
  108         char                    *name;
  109         int                     id;
  110         int                     channel;
  111 };
  112 
  113 struct rk_calib_entry {
  114         uint32_t        raw;
  115         int             temp;
  116 };
  117 
  118 struct tsadc_calib_info {
  119         struct rk_calib_entry   *table;
  120         int                     nentries;
  121 };
  122 
  123 struct tsadc_conf {
  124         int                     version;
  125         int                     q_sel_ntc;
  126         int                     shutdown_temp;
  127         int                     shutdown_mode;
  128         int                     shutdown_pol;
  129         struct tsensor          *tsensors;
  130         int                     ntsensors;
  131         struct tsadc_calib_info calib_info;
  132 };
  133 
  134 struct tsadc_softc {
  135         device_t                dev;
  136         struct resource         *mem_res;
  137         struct resource         *irq_res;
  138         void                    *irq_ih;
  139 
  140         clk_t                   tsadc_clk;
  141         clk_t                   apb_pclk_clk;
  142         hwreset_array_t         hwreset;
  143         struct syscon           *grf;
  144 
  145         struct tsadc_conf       *conf;
  146 
  147         int                     shutdown_temp;
  148         int                     shutdown_mode;
  149         int                     shutdown_pol;
  150 
  151         int                     alarm_temp;
  152 };
  153 
  154 static struct rk_calib_entry rk3288_calib_data[] = {
  155         {3800, -40000},
  156         {3792, -35000},
  157         {3783, -30000},
  158         {3774, -25000},
  159         {3765, -20000},
  160         {3756, -15000},
  161         {3747, -10000},
  162         {3737, -5000},
  163         {3728, 0},
  164         {3718, 5000},
  165         {3708, 10000},
  166         {3698, 15000},
  167         {3688, 20000},
  168         {3678, 25000},
  169         {3667, 30000},
  170         {3656, 35000},
  171         {3645, 40000},
  172         {3634, 45000},
  173         {3623, 50000},
  174         {3611, 55000},
  175         {3600, 60000},
  176         {3588, 65000},
  177         {3575, 70000},
  178         {3563, 75000},
  179         {3550, 80000},
  180         {3537, 85000},
  181         {3524, 90000},
  182         {3510, 95000},
  183         {3496, 100000},
  184         {3482, 105000},
  185         {3467, 110000},
  186         {3452, 115000},
  187         {3437, 120000},
  188         {3421, 125000},
  189 };
  190 
  191 struct tsensor rk3288_tsensors[] = {
  192         { .channel = 0, .id = 2, .name = "reserved"},
  193         { .channel = 1, .id = 0, .name = "CPU"},
  194         { .channel = 2, .id = 1, .name = "GPU"},
  195 };
  196 
  197 struct tsadc_conf rk3288_tsadc_conf = {
  198         .version =              TSADC_V2,
  199         .q_sel_ntc =            0,
  200         .shutdown_temp =        95000,
  201         .shutdown_mode =        1, /* GPIO */
  202         .shutdown_pol =         0, /* Low  */
  203         .tsensors =             rk3288_tsensors,
  204         .ntsensors =            nitems(rk3288_tsensors),
  205         .calib_info =   {
  206                         .table = rk3288_calib_data,
  207                         .nentries = nitems(rk3288_calib_data),
  208         }
  209 };
  210 
  211 static struct rk_calib_entry rk3328_calib_data[] = {
  212         {296, -40000},
  213         {304, -35000},
  214         {313, -30000},
  215         {331, -20000},
  216         {340, -15000},
  217         {349, -10000},
  218         {359, -5000},
  219         {368, 0},
  220         {378, 5000},
  221         {388, 10000},
  222         {398, 15000},
  223         {408, 20000},
  224         {418, 25000},
  225         {429, 30000},
  226         {440, 35000},
  227         {451, 40000},
  228         {462, 45000},
  229         {473, 50000},
  230         {485, 55000},
  231         {496, 60000},
  232         {508, 65000},
  233         {521, 70000},
  234         {533, 75000},
  235         {546, 80000},
  236         {559, 85000},
  237         {572, 90000},
  238         {586, 95000},
  239         {600, 100000},
  240         {614, 105000},
  241         {629, 110000},
  242         {644, 115000},
  243         {659, 120000},
  244         {675, 125000},
  245 };
  246 
  247 static struct tsensor rk3328_tsensors[] = {
  248         { .channel = 0, .id = 0, .name = "CPU"},
  249 };
  250 
  251 static struct tsadc_conf rk3328_tsadc_conf = {
  252         .version =              TSADC_V2,
  253         .q_sel_ntc =            1,
  254         .shutdown_temp =        95000,
  255         .shutdown_mode =        0, /* CRU */
  256         .shutdown_pol =         0, /* Low  */
  257         .tsensors =             rk3328_tsensors,
  258         .ntsensors =            nitems(rk3328_tsensors),
  259         .calib_info =   {
  260                         .table = rk3328_calib_data,
  261                         .nentries = nitems(rk3328_calib_data),
  262         }
  263 };
  264 
  265 static struct rk_calib_entry rk3399_calib_data[] = {
  266         {402, -40000},
  267         {410, -35000},
  268         {419, -30000},
  269         {427, -25000},
  270         {436, -20000},
  271         {444, -15000},
  272         {453, -10000},
  273         {461, -5000},
  274         {470, 0},
  275         {478, 5000},
  276         {487, 10000},
  277         {496, 15000},
  278         {504, 20000},
  279         {513, 25000},
  280         {521, 30000},
  281         {530, 35000},
  282         {538, 40000},
  283         {547, 45000},
  284         {555, 50000},
  285         {564, 55000},
  286         {573, 60000},
  287         {581, 65000},
  288         {590, 70000},
  289         {599, 75000},
  290         {607, 80000},
  291         {616, 85000},
  292         {624, 90000},
  293         {633, 95000},
  294         {642, 100000},
  295         {650, 105000},
  296         {659, 110000},
  297         {668, 115000},
  298         {677, 120000},
  299         {685, 125000},
  300 };
  301 
  302 static struct tsensor rk3399_tsensors[] = {
  303         { .channel = 0, .id = 0, .name = "CPU"},
  304         { .channel = 1, .id = 1, .name = "GPU"},
  305 };
  306 
  307 static struct tsadc_conf rk3399_tsadc_conf = {
  308         .version =              TSADC_V3,
  309         .q_sel_ntc =            1,
  310         .shutdown_temp =        95000,
  311         .shutdown_mode =        1, /* GPIO */
  312         .shutdown_pol =         0, /* Low  */
  313         .tsensors =             rk3399_tsensors,
  314         .ntsensors =            nitems(rk3399_tsensors),
  315         .calib_info =   {
  316                         .table = rk3399_calib_data,
  317                         .nentries = nitems(rk3399_calib_data),
  318         }
  319 };
  320 
  321 static struct rk_calib_entry rk3568_calib_data[] = {
  322         {0, -40000},
  323         {1584, -40000},
  324         {1620, -35000},
  325         {1652, -30000},
  326         {1688, -25000},
  327         {1720, -20000},
  328         {1756, -15000},
  329         {1788, -10000},
  330         {1824, -5000},
  331         {1856, 0},
  332         {1892, 5000},
  333         {1924, 10000},
  334         {1956, 15000},
  335         {1992, 20000},
  336         {2024, 25000},
  337         {2060, 30000},
  338         {2092, 35000},
  339         {2128, 40000},
  340         {2160, 45000},
  341         {2196, 50000},
  342         {2228, 55000},
  343         {2264, 60000},
  344         {2300, 65000},
  345         {2332, 70000},
  346         {2368, 75000},
  347         {2400, 80000},
  348         {2436, 85000},
  349         {2468, 90000},
  350         {2500, 95000},
  351         {2536, 100000},
  352         {2572, 105000},
  353         {2604, 110000},
  354         {2636, 115000},
  355         {2672, 120000},
  356         {2704, 125000},
  357 };
  358 
  359 static struct tsensor rk3568_tsensors[] = {
  360         { .channel = 0, .id = 0, .name = "CPU"},
  361         { .channel = 1, .id = 1, .name = "GPU"},
  362 };
  363 
  364 static struct tsadc_conf rk3568_tsadc_conf = {
  365         .version =              TSADC_V7,
  366         .q_sel_ntc =            1,
  367         .shutdown_temp =        95000,
  368         .shutdown_mode =        1, /* GPIO */
  369         .shutdown_pol =         0, /* Low  */
  370         .tsensors =             rk3568_tsensors,
  371         .ntsensors =            nitems(rk3568_tsensors),
  372         .calib_info =   {
  373                         .table = rk3568_calib_data,
  374                         .nentries = nitems(rk3568_calib_data),
  375         }
  376 };
  377 
  378 static struct ofw_compat_data compat_data[] = {
  379         {"rockchip,rk3288-tsadc",       (uintptr_t)&rk3288_tsadc_conf},
  380         {"rockchip,rk3328-tsadc",       (uintptr_t)&rk3328_tsadc_conf},
  381         {"rockchip,rk3399-tsadc",       (uintptr_t)&rk3399_tsadc_conf},
  382         {"rockchip,rk3568-tsadc",       (uintptr_t)&rk3568_tsadc_conf},
  383         {NULL,          0}
  384 };
  385 
  386 static uint32_t
  387 tsadc_temp_to_raw(struct tsadc_softc *sc, int temp)
  388 {
  389         struct rk_calib_entry *tbl;
  390         int denom, ntbl, raw, i;
  391 
  392         tbl = sc->conf->calib_info.table;
  393         ntbl = sc->conf->calib_info.nentries;
  394 
  395         if (temp <= tbl[0].temp)
  396                 return (tbl[0].raw);
  397 
  398         if (temp >= tbl[ntbl - 1].temp)
  399                 return (tbl[ntbl - 1].raw);
  400 
  401         for (i = 1; i < (ntbl - 1); i++) {
  402                 /* Exact match */
  403                 if (temp == tbl[i].temp)
  404                         return (tbl[i].raw);
  405                 if (temp < tbl[i].temp)
  406                         break;
  407         }
  408 
  409         /*
  410         * Translated value is between i and i - 1 table entries.
  411         * Do linear interpolation for it.
  412         */
  413         raw = (int)tbl[i - 1].raw - (int)tbl[i].raw;
  414         raw *= temp - tbl[i - 1].temp;
  415         denom = tbl[i - 1].temp - tbl[i].temp;
  416         raw = tbl[i - 1].raw + raw / denom;
  417         return (raw);
  418 }
  419 
  420 static int
  421 tsadc_raw_to_temp(struct tsadc_softc *sc, uint32_t raw)
  422 {
  423         struct rk_calib_entry *tbl;
  424         int denom, ntbl, temp, i;
  425         bool descending;
  426 
  427         tbl = sc->conf->calib_info.table;
  428         ntbl = sc->conf->calib_info.nentries;
  429         descending = tbl[0].raw > tbl[1].raw;
  430 
  431         if (descending) {
  432                 /* Raw column is in descending order. */
  433                 if (raw >= tbl[0].raw)
  434                         return (tbl[0].temp);
  435                 if (raw <= tbl[ntbl - 1].raw)
  436                         return (tbl[ntbl - 1].temp);
  437 
  438                 for (i = ntbl - 2; i > 0; i--) {
  439                         /* Exact match */
  440                         if (raw == tbl[i].raw)
  441                                 return (tbl[i].temp);
  442                         if (raw < tbl[i].raw)
  443                                 break;
  444                 }
  445         } else {
  446                 /* Raw column is in ascending order. */
  447                 if (raw <= tbl[0].raw)
  448                         return (tbl[0].temp);
  449                 if (raw >= tbl[ntbl - 1].raw)
  450                         return (tbl[ntbl - 1].temp);
  451                 for (i = 1; i < (ntbl - 1); i++) {
  452                         /* Exact match */
  453                         if (raw == tbl[i].raw)
  454                                 return (tbl[i].temp);
  455                         if (raw < tbl[i].raw)
  456                                 break;
  457                 }
  458         }
  459 
  460         /*
  461         * Translated value is between i and i - 1 table entries.
  462         * Do linear interpolation for it.
  463         */
  464         temp  = (int)tbl[i - 1].temp - (int)tbl[i].temp;
  465         temp *= raw - tbl[i - 1].raw;
  466         denom = tbl[i - 1].raw - tbl[i].raw;
  467         temp = tbl[i - 1].temp + temp / denom;
  468         return (temp);
  469 }
  470 
  471 static void
  472 tsadc_init_tsensor(struct tsadc_softc *sc, struct tsensor *sensor)
  473 {
  474         uint32_t val;
  475 
  476         /* Shutdown mode */
  477         val = RD4(sc, TSADC_INT_EN);
  478         if (sc->shutdown_mode != 0) {
  479                 /* Signal shutdown of GPIO pin */
  480                 val &= ~TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
  481                 val |= TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
  482         } else {
  483                 val |= TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
  484                 val &= ~TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
  485         }
  486         WR4(sc, TSADC_INT_EN, val);
  487 
  488         /* Shutdown temperature */
  489         val =  tsadc_raw_to_temp(sc, sc->shutdown_temp);
  490         WR4(sc, TSADC_COMP_SHUT(sensor->channel), val);
  491         val = RD4(sc, TSADC_AUTO_CON);
  492         val |= TSADC_AUTO_SRC_EN(sensor->channel);
  493         WR4(sc, TSADC_AUTO_CON, val);
  494 
  495         /* Alarm temperature */
  496         val =  tsadc_temp_to_raw(sc, sc->alarm_temp);
  497         WR4(sc, TSADC_COMP_INT(sensor->channel), val);
  498         val = RD4(sc, TSADC_INT_EN);
  499         val |= TSADC_COMP_INT_SRC_EN(sensor->channel);
  500         WR4(sc, TSADC_INT_EN, val);
  501 }
  502 
  503 static void
  504 tsadc_init(struct tsadc_softc *sc)
  505 {
  506         uint32_t val;
  507 
  508         /* Common part */
  509         val = 0;        /* XXX Is this right? */
  510         if (sc->shutdown_pol != 0)
  511                 val |= TSADC_AUTO_CON_POL_HI;
  512         else
  513                 val &= ~TSADC_AUTO_CON_POL_HI;
  514         if (sc->conf->q_sel_ntc)
  515                 val |= TSADC_AUTO_Q_SEL;
  516         WR4(sc, TSADC_AUTO_CON, val);
  517 
  518         switch (sc->conf->version) {
  519         case TSADC_V2:
  520                 /* V2 init */
  521                 WR4(sc, TSADC_AUTO_PERIOD, 250);        /* 250 ms */
  522                 WR4(sc, TSADC_AUTO_PERIOD_HT, 50);      /*  50 ms */
  523                 WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
  524                 WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
  525                 break;
  526         case TSADC_V3:
  527                 /* V3 init */
  528                 if (sc->grf == NULL) {
  529                         /* Errata: adjust interleave to working value */
  530                         WR4(sc, TSADC_USER_CON, 13 << 6);       /* 13 clks */
  531                 } else {
  532                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_L,
  533                             GRF_TSADC_VCM_EN_L);
  534                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
  535                             GRF_TSADC_VCM_EN_H);
  536                         DELAY(30);  /* 15 usec min */
  537 
  538                         SYSCON_WRITE_4(sc->grf, GRF_SARADC_TESTBIT,
  539                             GRF_SARADC_TESTBIT_ON);
  540                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
  541                             GRF_TSADC_TESTBIT_H_ON);
  542                         DELAY(180);  /* 90 usec min */
  543                 }
  544                 WR4(sc, TSADC_AUTO_PERIOD, 1875);       /* 2.5 ms */
  545                 WR4(sc, TSADC_AUTO_PERIOD_HT, 1875);    /* 2.5 ms */
  546                 WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
  547                 WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
  548                 break;
  549         case TSADC_V7:
  550                 /* V7 init */
  551                 WR4(sc, TSADC_USER_CON, 0xfc0);         /* 97us, at least 90us */
  552                 WR4(sc, TSADC_AUTO_PERIOD, 1622);       /* 2.5ms */
  553                 WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
  554                 WR4(sc, TSADC_AUTO_PERIOD_HT, 1622);    /* 2.5ms */
  555                 WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
  556                 if (sc->grf) {
  557                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON, GRF_TSADC_TSEN);
  558                         DELAY(15);                      /* 10 usec min */
  559                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
  560                             GRF_TSADC_ANA_REG0);
  561                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
  562                             GRF_TSADC_ANA_REG1);
  563                         SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
  564                             GRF_TSADC_ANA_REG2);
  565                         DELAY(100);                     /* 90 usec min */
  566                 }
  567                 break;
  568         }
  569 }
  570 
  571 static int
  572 tsadc_read_temp(struct tsadc_softc *sc, struct tsensor *sensor, int *temp)
  573 {
  574         uint32_t val;
  575 
  576         val = RD4(sc, TSADC_DATA(sensor->channel));
  577         *temp = tsadc_raw_to_temp(sc, val);
  578 
  579 #ifdef DEBUG
  580         device_printf(sc->dev, "%s: Sensor(id: %d, ch: %d), val: %d temp: %d\n",
  581             __func__, sensor->id, sensor->channel, val, *temp);
  582         device_printf(sc->dev, "%s: user_con=0x%08x auto_con=0x%08x "
  583             "comp_int=0x%08x comp_shut=0x%08x\n",
  584             __func__, RD4(sc, TSADC_USER_CON), RD4(sc, TSADC_AUTO_CON),
  585             RD4(sc, TSADC_COMP_INT(sensor->channel)),
  586             RD4(sc, TSADC_COMP_SHUT(sensor->channel)));
  587 #endif
  588         return (0);
  589 }
  590 
  591 static int
  592 tsadc_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
  593 {
  594         struct tsadc_softc *sc;
  595         int i, rv;
  596 
  597         sc = device_get_softc(dev);
  598 
  599         if (id >= sc->conf->ntsensors)
  600                 return (ERANGE);
  601 
  602         for (i = 0; i < sc->conf->ntsensors; i++) {
  603                 if (sc->conf->tsensors->id == id) {
  604                         rv =tsadc_read_temp(sc, sc->conf->tsensors + id, val);
  605                         return (rv);
  606                 }
  607         }
  608         return (ERANGE);
  609 }
  610 
  611 static int
  612 tsadc_sysctl_temperature(SYSCTL_HANDLER_ARGS)
  613 {
  614         struct tsadc_softc *sc;
  615         int val;
  616         int rv;
  617         int id;
  618 
  619         /* Write request */
  620         if (req->newptr != NULL)
  621                 return (EINVAL);
  622 
  623         sc = arg1;
  624         id = arg2;
  625 
  626         if (id >= sc->conf->ntsensors)
  627                 return (ERANGE);
  628         rv =  tsadc_read_temp(sc, sc->conf->tsensors + id, &val);
  629         if (rv != 0)
  630                 return (rv);
  631 
  632         val = val / 100;
  633         val +=  2731;
  634         rv = sysctl_handle_int(oidp, &val, 0, req);
  635         return (rv);
  636 }
  637 
  638 static int
  639 tsadc_init_sysctl(struct tsadc_softc *sc)
  640 {
  641         int i;
  642         struct sysctl_oid *oid, *tmp;
  643 
  644         sysctl_ctx_init(&tsadc_sysctl_ctx);
  645         /* create node for hw.temp */
  646         oid = SYSCTL_ADD_NODE(&tsadc_sysctl_ctx,
  647             SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "temperature",
  648             CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
  649         if (oid == NULL)
  650                 return (ENXIO);
  651 
  652         /* Add sensors */
  653         for (i = sc->conf->ntsensors  - 1; i >= 0; i--) {
  654                 tmp = SYSCTL_ADD_PROC(&tsadc_sysctl_ctx,
  655                     SYSCTL_CHILDREN(oid), OID_AUTO, sc->conf->tsensors[i].name,
  656                     CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, i,
  657                     tsadc_sysctl_temperature, "IK", "SoC Temperature");
  658                 if (tmp == NULL)
  659                         return (ENXIO);
  660         }
  661 
  662         return (0);
  663 }
  664 
  665 static int
  666 tsadc_intr(void *arg)
  667 {
  668         struct tsadc_softc *sc;
  669         uint32_t val;
  670 
  671         sc = (struct tsadc_softc *)arg;
  672 
  673         val = RD4(sc, TSADC_INT_PD);
  674         WR4(sc, TSADC_INT_PD, val);
  675 
  676         /* XXX Handle shutdown and alarm interrupts. */
  677         if (val & 0x00F0) {
  678                 device_printf(sc->dev, "Alarm: device temperature "
  679                     "is above of shutdown level.\n");
  680         } else if (val & 0x000F) {
  681                 device_printf(sc->dev, "Alarm: device temperature "
  682                     "is above of alarm level.\n");
  683         }
  684         return (FILTER_HANDLED);
  685 }
  686 
  687 static int
  688 tsadc_probe(device_t dev)
  689 {
  690 
  691         if (!ofw_bus_status_okay(dev))
  692                 return (ENXIO);
  693 
  694         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  695                 return (ENXIO);
  696 
  697         device_set_desc(dev, "RockChip temperature sensors");
  698         return (BUS_PROBE_DEFAULT);
  699 }
  700 
  701 static int
  702 tsadc_attach(device_t dev)
  703 {
  704         struct tsadc_softc *sc;
  705         phandle_t node;
  706         uint32_t val;
  707         int i, rid, rv;
  708 
  709         sc = device_get_softc(dev);
  710         sc->dev = dev;
  711         node = ofw_bus_get_node(sc->dev);
  712         sc->conf = (struct tsadc_conf *)
  713             ofw_bus_search_compatible(dev, compat_data)->ocd_data;
  714         sc->alarm_temp = 90000;
  715 
  716         rid = 0;
  717         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  718             RF_ACTIVE);
  719         if (sc->mem_res == NULL) {
  720                 device_printf(dev, "Cannot allocate memory resources\n");
  721                 goto fail;
  722         }
  723 
  724         rid = 0;
  725         sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
  726         if (sc->irq_res == NULL) {
  727                 device_printf(dev, "Cannot allocate IRQ resources\n");
  728                 goto fail;
  729         }
  730 
  731         if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  732             tsadc_intr, NULL, sc, &sc->irq_ih))) {
  733                 device_printf(dev,
  734                     "WARNING: unable to register interrupt handler\n");
  735                 goto fail;
  736         }
  737 
  738         /* FDT resources */
  739         rv = hwreset_array_get_ofw(dev, 0, &sc->hwreset);
  740         if (rv != 0) {
  741                 device_printf(dev, "Cannot get resets\n");
  742                 goto fail;
  743         }
  744         rv = clk_get_by_ofw_name(dev, 0, "tsadc", &sc->tsadc_clk);
  745         if (rv != 0) {
  746                 device_printf(dev, "Cannot get 'tsadc' clock: %d\n", rv);
  747                 goto fail;
  748         }
  749         rv = clk_get_by_ofw_name(dev, 0, "apb_pclk", &sc->apb_pclk_clk);
  750         if (rv != 0) {
  751                 device_printf(dev, "Cannot get 'apb_pclk' clock: %d\n", rv);
  752                 goto fail;
  753         }
  754 
  755         /* grf is optional */
  756         rv = syscon_get_by_ofw_property(dev, node, "rockchip,grf", &sc->grf);
  757         if (rv != 0 && rv != ENOENT) {
  758                 device_printf(dev, "Cannot get 'grf' syscon: %d\n", rv);
  759                 goto fail;
  760         }
  761 
  762         rv = OF_getencprop(node, "rockchip,hw-tshut-temp",
  763             &sc->shutdown_temp, sizeof(sc->shutdown_temp));
  764         if (rv <= 0)
  765                 sc->shutdown_temp = sc->conf->shutdown_temp;
  766 
  767         rv = OF_getencprop(node, "rockchip,hw-tshut-mode",
  768             &sc->shutdown_mode, sizeof(sc->shutdown_mode));
  769         if (rv <= 0)
  770                 sc->shutdown_mode = sc->conf->shutdown_mode;
  771 
  772         rv = OF_getencprop(node, "rockchip,hw-tshut-polarity",
  773             &sc->shutdown_pol, sizeof(sc->shutdown_pol));
  774         if (rv <= 0)
  775                 sc->shutdown_pol = sc->conf->shutdown_pol;
  776 
  777         /* Wakeup controller */
  778         rv = hwreset_array_assert(sc->hwreset);
  779         if (rv != 0) {
  780                 device_printf(dev, "Cannot assert reset\n");
  781                 goto fail;
  782         }
  783 
  784         /* Set the assigned clocks parent and freq */
  785         rv = clk_set_assigned(sc->dev, node);
  786         if (rv != 0 && rv != ENOENT) {
  787                 device_printf(dev, "clk_set_assigned failed\n");
  788                 goto fail;
  789         }
  790 
  791         rv = clk_enable(sc->tsadc_clk);
  792         if (rv != 0) {
  793                 device_printf(dev, "Cannot enable 'tsadc_clk' clock: %d\n", rv);
  794                 goto fail;
  795         }
  796         rv = clk_enable(sc->apb_pclk_clk);
  797         if (rv != 0) {
  798                 device_printf(dev, "Cannot enable 'apb_pclk' clock: %d\n", rv);
  799                 goto fail;
  800         }
  801         rv = hwreset_array_deassert(sc->hwreset);
  802         if (rv != 0) {
  803                 device_printf(dev, "Cannot deassert reset\n");
  804                 goto fail;
  805         }
  806 
  807         tsadc_init(sc);
  808         for (i = 0; i < sc->conf->ntsensors; i++)
  809                 tsadc_init_tsensor(sc, sc->conf->tsensors + i);
  810 
  811         /* Enable auto mode */
  812         val = RD4(sc, TSADC_AUTO_CON);
  813         val |= TSADC_AUTO_CON_AUTO;
  814         WR4(sc, TSADC_AUTO_CON, val);
  815 
  816         rv = tsadc_init_sysctl(sc);
  817         if (rv != 0) {
  818                 device_printf(sc->dev, "Cannot initialize sysctls\n");
  819                 goto fail_sysctl;
  820         }
  821 
  822         OF_device_register_xref(OF_xref_from_node(node), dev);
  823         return (bus_generic_attach(dev));
  824 
  825 fail_sysctl:
  826         sysctl_ctx_free(&tsadc_sysctl_ctx);
  827 fail:
  828         if (sc->irq_ih != NULL)
  829                 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
  830         if (sc->tsadc_clk != NULL)
  831                 clk_release(sc->tsadc_clk);
  832         if (sc->apb_pclk_clk != NULL)
  833                 clk_release(sc->apb_pclk_clk);
  834         if (sc->hwreset != NULL)
  835                 hwreset_array_release(sc->hwreset);
  836         if (sc->irq_res != NULL)
  837                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
  838         if (sc->mem_res != NULL)
  839                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  840 
  841         return (ENXIO);
  842 }
  843 
  844 static int
  845 tsadc_detach(device_t dev)
  846 {
  847         struct tsadc_softc *sc;
  848         sc = device_get_softc(dev);
  849 
  850         if (sc->irq_ih != NULL)
  851                 bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
  852         sysctl_ctx_free(&tsadc_sysctl_ctx);
  853         if (sc->tsadc_clk != NULL)
  854                 clk_release(sc->tsadc_clk);
  855         if (sc->apb_pclk_clk != NULL)
  856                 clk_release(sc->apb_pclk_clk);
  857         if (sc->hwreset != NULL)
  858                 hwreset_array_release(sc->hwreset);
  859         if (sc->irq_res != NULL)
  860                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
  861         if (sc->mem_res != NULL)
  862                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  863 
  864         return (ENXIO);
  865 }
  866 
  867 static device_method_t rk_tsadc_methods[] = {
  868         /* Device interface */
  869         DEVMETHOD(device_probe,                 tsadc_probe),
  870         DEVMETHOD(device_attach,                tsadc_attach),
  871         DEVMETHOD(device_detach,                tsadc_detach),
  872 
  873         /* TSADC interface */
  874         DEVMETHOD(rk_tsadc_get_temperature,     tsadc_get_temp),
  875 
  876         DEVMETHOD_END
  877 };
  878 
  879 static DEFINE_CLASS_0(rk_tsadc, rk_tsadc_driver, rk_tsadc_methods,
  880     sizeof(struct tsadc_softc));
  881 EARLY_DRIVER_MODULE(rk_tsadc, simplebus, rk_tsadc_driver, NULL, NULL,
  882     BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);

Cache object: e06ae9dd5e8896e9aa091c799f3157c0


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