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/nvidia/tegra210/max77620_regulators.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 2020 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 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/gpio.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/malloc.h>
   38 #include <sys/rman.h>
   39 #include <sys/sx.h>
   40 
   41 #include <machine/bus.h>
   42 
   43 #include <dev/extres/regulator/regulator.h>
   44 #include <dev/gpio/gpiobusvar.h>
   45 
   46 #include <dt-bindings/mfd/max77620.h>
   47 
   48 #include "max77620.h"
   49 
   50 MALLOC_DEFINE(M_MAX77620_REG, "MAX77620 regulator", "MAX77620 power regulator");
   51 
   52 #define DIV_ROUND_UP(n,d) howmany(n, d)
   53 
   54 enum max77620_reg_id {
   55         MAX77620_REG_ID_SD0,
   56         MAX77620_REG_ID_SD1,
   57         MAX77620_REG_ID_SD2,
   58         MAX77620_REG_ID_SD3,
   59         MAX77620_REG_ID_LDO0,
   60         MAX77620_REG_ID_LDO1,
   61         MAX77620_REG_ID_LDO2,
   62         MAX77620_REG_ID_LDO3,
   63         MAX77620_REG_ID_LDO4,
   64         MAX77620_REG_ID_LDO5,
   65         MAX77620_REG_ID_LDO6,
   66         MAX77620_REG_ID_LDO7,
   67         MAX77620_REG_ID_LDO8,
   68 };
   69 
   70 /* Initial configuration. */
   71 struct max77620_regnode_init_def {
   72         struct regnode_init_def reg_init_def;
   73         int active_fps_src;
   74         int active_fps_pu_slot;
   75         int active_fps_pd_slot;
   76         int suspend_fps_src;
   77         int suspend_fps_pu_slot;
   78         int suspend_fps_pd_slot;
   79         int ramp_rate_setting;
   80 };
   81 
   82 /* Regulator HW definition. */
   83 struct reg_def {
   84         intptr_t                id;             /* ID */
   85         char                    *name;          /* Regulator name */
   86         char                    *supply_name;   /* Source property name */
   87         bool                    is_sd_reg;      /* SD or LDO regulator? */
   88         uint8_t                 volt_reg;
   89         uint8_t                 volt_vsel_mask;
   90         uint8_t                 cfg_reg;
   91         uint8_t                 fps_reg;
   92         uint8_t                 pwr_mode_reg;
   93         uint8_t                 pwr_mode_mask;
   94         uint8_t                 pwr_mode_shift;
   95         struct regulator_range  *ranges;
   96         int                     nranges;
   97 };
   98 
   99 struct max77620_reg_sc {
  100         struct regnode          *regnode;
  101         struct max77620_softc   *base_sc;
  102         struct reg_def          *def;
  103         phandle_t               xref;
  104 
  105         struct regnode_std_param *param;
  106         /* Configured values */
  107         int                     active_fps_src;
  108         int                     active_fps_pu_slot;
  109         int                     active_fps_pd_slot;
  110         int                     suspend_fps_src;
  111         int                     suspend_fps_pu_slot;
  112         int                     suspend_fps_pd_slot;
  113         int                     ramp_rate_setting;
  114         int                     enable_usec;
  115         uint8_t                 enable_pwr_mode;
  116 
  117         /* Cached values */
  118         uint8_t                 fps_src;
  119         uint8_t                 pwr_mode;
  120         int                     pwr_ramp_delay;
  121 };
  122 
  123 static struct regulator_range max77620_sd0_ranges[] = {
  124         REG_RANGE_INIT(0, 64, 600000, 12500),  /* 0.6V - 1.4V / 12.5mV */
  125 };
  126 
  127 static struct regulator_range max77620_sd1_ranges[] = {
  128         REG_RANGE_INIT(0, 76, 600000, 12500),  /* 0.6V - 1.55V / 12.5mV */
  129 };
  130 
  131 static struct regulator_range max77620_sdx_ranges[] = {
  132         REG_RANGE_INIT(0, 255, 600000, 12500),  /* 0.6V - 3.7875V / 12.5mV */
  133 };
  134 
  135 static struct regulator_range max77620_ldo0_1_ranges[] = {
  136         REG_RANGE_INIT(0, 63, 800000, 25000),  /* 0.8V - 2.375V / 25mV */
  137 };
  138 
  139 static struct regulator_range max77620_ldo4_ranges[] = {
  140         REG_RANGE_INIT(0, 63, 800000, 12500),  /* 0.8V - 1.5875V / 12.5mV */
  141 };
  142 
  143 static struct regulator_range max77620_ldox_ranges[] = {
  144         REG_RANGE_INIT(0, 63, 800000, 50000),  /* 0.8V - 3.95V / 50mV */
  145 };
  146 
  147 static struct reg_def max77620s_def[] = {
  148         {
  149                 .id = MAX77620_REG_ID_SD0,
  150                 .name = "sd0",
  151                 .supply_name = "in-sd0",
  152                 .is_sd_reg = true,
  153                 .volt_reg = MAX77620_REG_SD0,
  154                 .volt_vsel_mask = MAX77620_SD0_VSEL_MASK,
  155                 .cfg_reg = MAX77620_REG_CFG_SD0,
  156                 .fps_reg = MAX77620_REG_FPS_SD0,
  157                 .pwr_mode_reg = MAX77620_REG_CFG_SD0,
  158                 .pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
  159                 .pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
  160                 .ranges = max77620_sd0_ranges,
  161                 .nranges = nitems(max77620_sd0_ranges),
  162         },
  163         {
  164                 .id = MAX77620_REG_ID_SD1,
  165                 .name = "sd1",
  166                 .supply_name = "in-sd1",
  167                 .is_sd_reg = true,
  168                 .volt_reg = MAX77620_REG_SD1,
  169                 .volt_vsel_mask = MAX77620_SD1_VSEL_MASK,
  170                 .cfg_reg = MAX77620_REG_CFG_SD1,
  171                 .fps_reg = MAX77620_REG_FPS_SD1,
  172                 .pwr_mode_reg = MAX77620_REG_CFG_SD1,
  173                 .pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
  174                 .pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
  175                 .ranges = max77620_sd1_ranges,
  176                 .nranges = nitems(max77620_sd1_ranges),
  177         },
  178         {
  179                 .id = MAX77620_REG_ID_SD2,
  180                 .name = "sd2",
  181                 .supply_name = "in-sd2",
  182                 .is_sd_reg = true,
  183                 .volt_reg = MAX77620_REG_SD2,
  184                 .volt_vsel_mask = MAX77620_SDX_VSEL_MASK,
  185                 .cfg_reg = MAX77620_REG_CFG_SD2,
  186                 .fps_reg = MAX77620_REG_FPS_SD2,
  187                 .pwr_mode_reg = MAX77620_REG_CFG_SD2,
  188                 .pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
  189                 .pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
  190                 .ranges = max77620_sdx_ranges,
  191                 .nranges = nitems(max77620_sdx_ranges),
  192         },
  193         {
  194                 .id = MAX77620_REG_ID_SD3,
  195                 .name = "sd3",
  196                 .supply_name = "in-sd3",
  197                 .is_sd_reg = true,
  198                 .volt_reg = MAX77620_REG_SD3,
  199                 .volt_vsel_mask = MAX77620_SDX_VSEL_MASK,
  200                 .cfg_reg = MAX77620_REG_CFG_SD3,
  201                 .fps_reg = MAX77620_REG_FPS_SD3,
  202                 .pwr_mode_reg = MAX77620_REG_CFG_SD3,
  203                 .pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
  204                 .pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
  205                 .ranges = max77620_sdx_ranges,
  206                 .nranges = nitems(max77620_sdx_ranges),
  207         },
  208         {
  209                 .id = MAX77620_REG_ID_LDO0,
  210                 .name = "ldo0",
  211                 .supply_name = "vin-ldo0-1",
  212                 .volt_reg = MAX77620_REG_CFG_LDO0,
  213                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  214                 .is_sd_reg = false,
  215                 .cfg_reg = MAX77620_REG_CFG2_LDO0,
  216                 .fps_reg = MAX77620_REG_FPS_LDO0,
  217                 .pwr_mode_reg = MAX77620_REG_CFG_LDO0,
  218                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  219                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  220                 .ranges = max77620_ldo0_1_ranges,
  221                 .nranges = nitems(max77620_ldo0_1_ranges),
  222         },
  223         {
  224                 .id = MAX77620_REG_ID_LDO1,
  225                 .name = "ldo1",
  226                 .supply_name = "in-ldo0-1",
  227                 .is_sd_reg = false,
  228                 .volt_reg = MAX77620_REG_CFG_LDO1,
  229                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  230                 .cfg_reg = MAX77620_REG_CFG2_LDO1,
  231                 .fps_reg = MAX77620_REG_FPS_LDO1,
  232                 .pwr_mode_reg = MAX77620_REG_CFG_LDO1,
  233                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  234                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  235                 .ranges = max77620_ldo0_1_ranges,
  236                 .nranges = nitems(max77620_ldo0_1_ranges),
  237         },
  238         {
  239                 .id = MAX77620_REG_ID_LDO2,
  240                 .name = "ldo2",
  241                 .supply_name = "in-ldo2",
  242                 .is_sd_reg = false,
  243                 .volt_reg = MAX77620_REG_CFG_LDO2,
  244                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  245                 .cfg_reg = MAX77620_REG_CFG2_LDO2,
  246                 .fps_reg = MAX77620_REG_FPS_LDO2,
  247                 .pwr_mode_reg = MAX77620_REG_CFG_LDO2,
  248                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  249                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  250                 .ranges = max77620_ldox_ranges,
  251                 .nranges = nitems(max77620_ldox_ranges),
  252         },
  253         {
  254                 .id = MAX77620_REG_ID_LDO3,
  255                 .name = "ldo3",
  256                 .supply_name = "in-ldo3-5",
  257                 .is_sd_reg = false,
  258                 .volt_reg = MAX77620_REG_CFG_LDO3,
  259                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  260                 .cfg_reg = MAX77620_REG_CFG2_LDO3,
  261                 .fps_reg = MAX77620_REG_FPS_LDO3,
  262                 .pwr_mode_reg = MAX77620_REG_CFG_LDO3,
  263                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  264                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  265                 .ranges = max77620_ldox_ranges,
  266                 .nranges = nitems(max77620_ldox_ranges),
  267         },
  268         {
  269                 .id = MAX77620_REG_ID_LDO4,
  270                 .name = "ldo4",
  271                 .supply_name = "in-ldo4-6",
  272                 .is_sd_reg = false,
  273                 .volt_reg = MAX77620_REG_CFG_LDO4,
  274                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  275                 .cfg_reg = MAX77620_REG_CFG2_LDO4,
  276                 .fps_reg = MAX77620_REG_FPS_LDO4,
  277                 .pwr_mode_reg = MAX77620_REG_CFG_LDO4,
  278                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  279                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  280                 .ranges = max77620_ldo4_ranges,
  281                 .nranges = nitems(max77620_ldo4_ranges),
  282         },
  283         {
  284                 .id = MAX77620_REG_ID_LDO5,
  285                 .name = "ldo5",
  286                 .supply_name = "in-ldo3-5",
  287                 .is_sd_reg = false,
  288                 .volt_reg = MAX77620_REG_CFG_LDO5,
  289                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  290                 .cfg_reg = MAX77620_REG_CFG2_LDO5,
  291                 .fps_reg = MAX77620_REG_FPS_LDO5,
  292                 .pwr_mode_reg = MAX77620_REG_CFG_LDO5,
  293                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  294                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  295                 .ranges = max77620_ldox_ranges,
  296                 .nranges = nitems(max77620_ldox_ranges),
  297         },
  298         {
  299                 .id = MAX77620_REG_ID_LDO6,
  300                 .name = "ldo6",
  301                 .supply_name = "in-ldo4-6",
  302                 .is_sd_reg = false,
  303                 .volt_reg = MAX77620_REG_CFG_LDO6,
  304                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  305                 .cfg_reg = MAX77620_REG_CFG2_LDO6,
  306                 .fps_reg = MAX77620_REG_FPS_LDO6,
  307                 .pwr_mode_reg = MAX77620_REG_CFG_LDO6,
  308                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  309                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  310                 .ranges = max77620_ldox_ranges,
  311                 .nranges = nitems(max77620_ldox_ranges),
  312         },
  313         {
  314                 .id = MAX77620_REG_ID_LDO7,
  315                 .name = "ldo7",
  316                 .supply_name = "in-ldo7-8",
  317                 .is_sd_reg = false,
  318                 .volt_reg = MAX77620_REG_CFG_LDO7,
  319                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  320                 .cfg_reg = MAX77620_REG_CFG2_LDO7,
  321                 .fps_reg = MAX77620_REG_FPS_LDO7,
  322                 .pwr_mode_reg = MAX77620_REG_CFG_LDO7,
  323                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  324                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  325                 .ranges = max77620_ldox_ranges,
  326                 .nranges = nitems(max77620_ldox_ranges),
  327         },
  328         {
  329                 .id = MAX77620_REG_ID_LDO8,
  330                 .name = "ldo8",
  331                 .supply_name = "in-ldo7-8",
  332                 .is_sd_reg = false,
  333                 .volt_reg = MAX77620_REG_CFG_LDO8,
  334                 .volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
  335                 .cfg_reg = MAX77620_REG_CFG2_LDO8,
  336                 .fps_reg = MAX77620_REG_FPS_LDO8,
  337                 .pwr_mode_reg = MAX77620_REG_CFG_LDO8,
  338                 .pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
  339                 .pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
  340                 .ranges = max77620_ldox_ranges,
  341                 .nranges = nitems(max77620_ldox_ranges),
  342         },
  343 };
  344 
  345 
  346 static int max77620_regnode_init(struct regnode *regnode);
  347 static int max77620_regnode_enable(struct regnode *regnode, bool enable,
  348     int *udelay);
  349 static int max77620_regnode_set_volt(struct regnode *regnode, int min_uvolt,
  350     int max_uvolt, int *udelay);
  351 static int max77620_regnode_get_volt(struct regnode *regnode, int *uvolt);
  352 static regnode_method_t max77620_regnode_methods[] = {
  353         /* Regulator interface */
  354         REGNODEMETHOD(regnode_init,             max77620_regnode_init),
  355         REGNODEMETHOD(regnode_enable,           max77620_regnode_enable),
  356         REGNODEMETHOD(regnode_set_voltage,      max77620_regnode_set_volt),
  357         REGNODEMETHOD(regnode_get_voltage,      max77620_regnode_get_volt),
  358         REGNODEMETHOD_END
  359 };
  360 DEFINE_CLASS_1(max77620_regnode, max77620_regnode_class, max77620_regnode_methods,
  361    sizeof(struct max77620_reg_sc), regnode_class);
  362 
  363 static int
  364 max77620_get_sel(struct max77620_reg_sc *sc, uint8_t *sel)
  365 {
  366         int rv;
  367 
  368         rv = RD1(sc->base_sc, sc->def->volt_reg, sel);
  369         if (rv != 0) {
  370                 printf("%s: cannot read volatge selector: %d\n",
  371                     regnode_get_name(sc->regnode), rv);
  372                 return (rv);
  373         }
  374         *sel &= sc->def->volt_vsel_mask;
  375         *sel >>= ffs(sc->def->volt_vsel_mask) - 1;
  376         return (0);
  377 }
  378 
  379 static int
  380 max77620_set_sel(struct max77620_reg_sc *sc, uint8_t sel)
  381 {
  382         int rv;
  383 
  384         sel <<= ffs(sc->def->volt_vsel_mask) - 1;
  385         sel &= sc->def->volt_vsel_mask;
  386 
  387         rv = RM1(sc->base_sc, sc->def->volt_reg,
  388             sc->def->volt_vsel_mask, sel);
  389         if (rv != 0) {
  390                 printf("%s: cannot set volatge selector: %d\n",
  391                     regnode_get_name(sc->regnode), rv);
  392                 return (rv);
  393         }
  394         return (rv);
  395 }
  396 
  397 static int
  398 max77620_get_fps_src(struct max77620_reg_sc *sc, uint8_t *fps_src)
  399 {
  400         uint8_t val;
  401         int rv;
  402 
  403         rv = RD1(sc->base_sc, sc->def->fps_reg, &val);
  404         if (rv != 0)
  405                 return (rv);
  406 
  407         *fps_src  = (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
  408         return (0);
  409 }
  410 
  411 static int
  412 max77620_set_fps_src(struct max77620_reg_sc *sc, uint8_t fps_src)
  413 {
  414         int rv;
  415 
  416         rv = RM1(sc->base_sc, sc->def->fps_reg, MAX77620_FPS_SRC_MASK,
  417             fps_src << MAX77620_FPS_SRC_SHIFT);
  418         if (rv != 0)
  419                 return (rv);
  420         sc->fps_src = fps_src;
  421         return (0);
  422 }
  423 
  424 static int
  425 max77620_set_fps_slots(struct max77620_reg_sc *sc, bool suspend)
  426 {
  427         uint8_t mask, val;
  428         int pu_slot, pd_slot, rv;
  429 
  430         if (suspend) {
  431                 pu_slot = sc->suspend_fps_pu_slot;
  432                 pd_slot = sc->suspend_fps_pd_slot;
  433         } else {
  434                 pu_slot = sc->active_fps_pu_slot;
  435                 pd_slot = sc->active_fps_pd_slot;
  436         }
  437 
  438         mask = 0;
  439         val = 0;
  440         if (pu_slot >= 0) {
  441                 mask |= MAX77620_FPS_PU_PERIOD_MASK;
  442                 val |= ((uint8_t)pu_slot << MAX77620_FPS_PU_PERIOD_SHIFT) &
  443                     MAX77620_FPS_PU_PERIOD_MASK;
  444         }
  445         if (pd_slot >= 0) {
  446                 mask |= MAX77620_FPS_PD_PERIOD_MASK;
  447                 val |= ((uint8_t)pd_slot << MAX77620_FPS_PD_PERIOD_SHIFT) &
  448                     MAX77620_FPS_PD_PERIOD_MASK;
  449         }
  450 
  451         rv = RM1(sc->base_sc, sc->def->fps_reg, mask, val);
  452         if (rv != 0)
  453                 return (rv);
  454         return (0);
  455 }
  456 
  457 static int
  458 max77620_get_pwr_mode(struct max77620_reg_sc *sc, uint8_t *pwr_mode)
  459 {
  460         uint8_t val;
  461         int rv;
  462 
  463         rv = RD1(sc->base_sc, sc->def->pwr_mode_reg, &val);
  464         if (rv != 0)
  465                 return (rv);
  466 
  467         *pwr_mode  = (val & sc->def->pwr_mode_mask) >> sc->def->pwr_mode_shift;
  468         return (0);
  469 }
  470 
  471 static int
  472 max77620_set_pwr_mode(struct max77620_reg_sc *sc, uint8_t pwr_mode)
  473 {
  474         int rv;
  475 
  476         rv = RM1(sc->base_sc, sc->def->pwr_mode_reg, sc->def->pwr_mode_shift,
  477             pwr_mode << sc->def->pwr_mode_shift);
  478         if (rv != 0)
  479                 return (rv);
  480         sc->pwr_mode = pwr_mode;
  481         return (0);
  482 }
  483 
  484 static int
  485 max77620_get_pwr_ramp_delay(struct max77620_reg_sc *sc, int *rate)
  486 {
  487         uint8_t val;
  488         int rv;
  489 
  490         rv = RD1(sc->base_sc, sc->def->cfg_reg, &val);
  491         if (rv != 0)
  492                 return (rv);
  493 
  494         if (sc->def->is_sd_reg) {
  495                 val = (val & MAX77620_SD_SR_MASK) >> MAX77620_SD_SR_SHIFT;
  496                 if (val == 0)
  497                         *rate = 13750;
  498                 else if (val == 1)
  499                         *rate = 27500;
  500                 else if (val == 2)
  501                         *rate = 55000;
  502                 else
  503                         *rate = 100000;
  504         } else {
  505                 val = (val & MAX77620_LDO_SLEW_RATE_MASK) >>
  506                     MAX77620_LDO_SLEW_RATE_SHIFT;
  507                 if (val == 0)
  508                         *rate = 100000;
  509                 else
  510                         *rate = 5000;
  511         }
  512         sc->pwr_ramp_delay = *rate;
  513         return (0);
  514 }
  515 
  516 static int
  517 max77620_set_pwr_ramp_delay(struct max77620_reg_sc *sc, int rate)
  518 {
  519         uint8_t val, mask;
  520         int rv;
  521 
  522         if (sc->def->is_sd_reg) {
  523                 if (rate <= 13750)
  524                         val = 0;
  525                 else if (rate <= 27500)
  526                         val = 1;
  527                 else if (rate <= 55000)
  528                         val = 2;
  529                 else
  530                         val = 3;
  531                 val <<= MAX77620_SD_SR_SHIFT;
  532                 mask = MAX77620_SD_SR_MASK;
  533         } else {
  534                 if (rate <= 5000)
  535                         val = 1;
  536                 else
  537                         val = 0;
  538                 val <<= MAX77620_LDO_SLEW_RATE_SHIFT;
  539                 mask = MAX77620_LDO_SLEW_RATE_MASK;
  540         }
  541         rv = RM1(sc->base_sc, sc->def->cfg_reg, mask, val);
  542         if (rv != 0)
  543                 return (rv);
  544         return (0);
  545 }
  546 
  547 static int
  548 max77620_regnode_init(struct regnode *regnode)
  549 {
  550         struct max77620_reg_sc *sc;
  551         uint8_t val;
  552         int intval, rv;
  553 
  554         sc = regnode_get_softc(regnode);
  555         sc->enable_usec = 500;
  556         sc->enable_pwr_mode = MAX77620_POWER_MODE_NORMAL;
  557 #if 0
  558 {
  559 uint8_t val1, val2, val3;
  560 RD1(sc->base_sc, sc->def->volt_reg, &val1);
  561 RD1(sc->base_sc, sc->def->cfg_reg, &val2);
  562 RD1(sc->base_sc, sc->def->fps_reg, &val3);
  563 printf("%s: Volt: 0x%02X, CFG: 0x%02X, FPS: 0x%02X\n", regnode_get_name(sc->regnode), val1, val2, val3);
  564 }
  565 #endif
  566         /* Get current power mode */
  567         rv = max77620_get_pwr_mode(sc, &val);
  568         if (rv != 0) {
  569                 printf("%s: cannot read current power mode: %d\n",
  570                     regnode_get_name(sc->regnode), rv);
  571                 return (rv);
  572         }
  573         sc->pwr_mode = val;
  574 
  575         /* Get current power ramp delay */
  576         rv = max77620_get_pwr_ramp_delay(sc, &intval);
  577         if (rv != 0) {
  578                 printf("%s: cannot read current power mode: %d\n",
  579                     regnode_get_name(sc->regnode), rv);
  580                 return (rv);
  581         }
  582         sc->pwr_ramp_delay = intval;
  583 
  584         /* Get FPS source if is not specified. */
  585         if (sc->active_fps_src == -1) {
  586                 rv = max77620_get_fps_src(sc, &val);
  587                 if (rv != 0) {
  588                         printf("%s: cannot read current FPS source: %d\n",
  589                             regnode_get_name(sc->regnode), rv);
  590                         return (rv);
  591                 }
  592                 sc->active_fps_src = val;
  593         }
  594 
  595         /* Configure power mode non-FPS controlled regulators. */
  596         if (sc->active_fps_src != MAX77620_FPS_SRC_NONE ||
  597             (sc->pwr_mode != MAX77620_POWER_MODE_DISABLE &&
  598             sc->pwr_mode != sc->enable_pwr_mode)) {
  599                 rv = max77620_set_pwr_mode(sc, (uint8_t)sc->enable_pwr_mode);
  600                 if (rv != 0) {
  601                         printf("%s: cannot set power mode: %d\n",
  602                             regnode_get_name(sc->regnode), rv);
  603                         return (rv);
  604                 }
  605         }
  606 
  607         /* Set FPS source. */
  608         rv = max77620_set_fps_src(sc, sc->active_fps_src);
  609         if (rv != 0) {
  610                 printf("%s: cannot setup FPS source: %d\n",
  611                     regnode_get_name(sc->regnode), rv);
  612                 return (rv);
  613         }
  614         /* Set FPS slots. */
  615         rv = max77620_set_fps_slots(sc, false);
  616         if (rv != 0) {
  617                 printf("%s: cannot setup power slots: %d\n",
  618                     regnode_get_name(sc->regnode), rv);
  619                 return (rv);
  620         }
  621         /* Setup power ramp . */
  622         if (sc->ramp_rate_setting != -1) {
  623                 rv = max77620_set_pwr_ramp_delay(sc, sc->pwr_ramp_delay);
  624                 if (rv != 0) {
  625                         printf("%s: cannot set power ramp delay: %d\n",
  626                             regnode_get_name(sc->regnode), rv);
  627                         return (rv);
  628                 }
  629         }
  630 
  631         return (0);
  632 }
  633 
  634 static void
  635 max77620_fdt_parse(struct max77620_softc *sc, phandle_t node, struct reg_def *def,
  636 struct max77620_regnode_init_def *init_def)
  637 {
  638         int rv;
  639         phandle_t parent, supply_node;
  640         char prop_name[64]; /* Maximum OFW property name length. */
  641 
  642         rv = regulator_parse_ofw_stdparam(sc->dev, node,
  643             &init_def->reg_init_def);
  644 
  645         rv = OF_getencprop(node, "maxim,active-fps-source",
  646             &init_def->active_fps_src, sizeof(init_def->active_fps_src));
  647         if (rv <= 0)
  648                 init_def->active_fps_src = MAX77620_FPS_SRC_DEF;
  649 
  650         rv = OF_getencprop(node, "maxim,active-fps-power-up-slot",
  651             &init_def->active_fps_pu_slot, sizeof(init_def->active_fps_pu_slot));
  652         if (rv <= 0)
  653                 init_def->active_fps_pu_slot = -1;
  654 
  655         rv = OF_getencprop(node, "maxim,active-fps-power-down-slot",
  656             &init_def->active_fps_pd_slot, sizeof(init_def->active_fps_pd_slot));
  657         if (rv <= 0)
  658                 init_def->active_fps_pd_slot = -1;
  659 
  660         rv = OF_getencprop(node, "maxim,suspend-fps-source",
  661             &init_def->suspend_fps_src, sizeof(init_def->suspend_fps_src));
  662         if (rv <= 0)
  663                 init_def->suspend_fps_src = -1;
  664 
  665         rv = OF_getencprop(node, "maxim,suspend-fps-power-up-slot",
  666             &init_def->suspend_fps_pu_slot, sizeof(init_def->suspend_fps_pu_slot));
  667         if (rv <= 0)
  668                 init_def->suspend_fps_pu_slot = -1;
  669 
  670         rv = OF_getencprop(node, "maxim,suspend-fps-power-down-slot",
  671             &init_def->suspend_fps_pd_slot, sizeof(init_def->suspend_fps_pd_slot));
  672         if (rv <= 0)
  673                 init_def->suspend_fps_pd_slot = -1;
  674 
  675         rv = OF_getencprop(node, "maxim,ramp-rate-setting",
  676             &init_def->ramp_rate_setting, sizeof(init_def->ramp_rate_setting));
  677         if (rv <= 0)
  678                 init_def->ramp_rate_setting = -1;
  679 
  680         /* Get parent supply. */
  681         if (def->supply_name == NULL)
  682                  return;
  683 
  684         parent = OF_parent(node);
  685         snprintf(prop_name, sizeof(prop_name), "%s-supply",
  686             def->supply_name);
  687         rv = OF_getencprop(parent, prop_name, &supply_node,
  688             sizeof(supply_node));
  689         if (rv <= 0)
  690                 return;
  691         supply_node = OF_node_from_xref(supply_node);
  692         rv = OF_getprop_alloc(supply_node, "regulator-name",
  693             (void **)&init_def->reg_init_def.parent_name);
  694         if (rv <= 0)
  695                 init_def->reg_init_def.parent_name = NULL;
  696 }
  697 
  698 static struct max77620_reg_sc *
  699 max77620_attach(struct max77620_softc *sc, phandle_t node, struct reg_def *def)
  700 {
  701         struct max77620_reg_sc *reg_sc;
  702         struct max77620_regnode_init_def init_def;
  703         struct regnode *regnode;
  704 
  705         bzero(&init_def, sizeof(init_def));
  706 
  707         max77620_fdt_parse(sc, node, def, &init_def);
  708         init_def.reg_init_def.id = def->id;
  709         init_def.reg_init_def.ofw_node = node;
  710         regnode = regnode_create(sc->dev, &max77620_regnode_class,
  711             &init_def.reg_init_def);
  712         if (regnode == NULL) {
  713                 device_printf(sc->dev, "Cannot create regulator.\n");
  714                 return (NULL);
  715         }
  716         reg_sc = regnode_get_softc(regnode);
  717 
  718         /* Init regulator softc. */
  719         reg_sc->regnode = regnode;
  720         reg_sc->base_sc = sc;
  721         reg_sc->def = def;
  722         reg_sc->xref = OF_xref_from_node(node);
  723         reg_sc->param = regnode_get_stdparam(regnode);
  724         reg_sc->active_fps_src = init_def.active_fps_src;
  725         reg_sc->active_fps_pu_slot = init_def.active_fps_pu_slot;
  726         reg_sc->active_fps_pd_slot = init_def.active_fps_pd_slot;
  727         reg_sc->suspend_fps_src = init_def.suspend_fps_src;
  728         reg_sc->suspend_fps_pu_slot = init_def.suspend_fps_pu_slot;
  729         reg_sc->suspend_fps_pd_slot = init_def.suspend_fps_pd_slot;
  730         reg_sc->ramp_rate_setting = init_def.ramp_rate_setting;
  731 
  732         regnode_register(regnode);
  733         if (bootverbose) {
  734                 int volt, rv;
  735                 regnode_topo_slock();
  736                 rv = regnode_get_voltage(regnode, &volt);
  737                 if (rv == ENODEV) {
  738                         device_printf(sc->dev,
  739                            " Regulator %s: parent doesn't exist yet.\n",
  740                            regnode_get_name(regnode));
  741                 } else if (rv != 0) {
  742                         device_printf(sc->dev,
  743                            " Regulator %s: voltage: INVALID!!!\n",
  744                            regnode_get_name(regnode));
  745                 } else {
  746                         device_printf(sc->dev,
  747                             " Regulator %s: voltage: %d uV\n",
  748                             regnode_get_name(regnode), volt);
  749                         device_printf(sc->dev,
  750                             "  FPS source: %d, mode: %d, ramp delay: %d\n",
  751                             reg_sc->fps_src, reg_sc->pwr_mode,
  752                             reg_sc->pwr_ramp_delay);
  753                 }
  754                 regnode_topo_unlock();
  755         }
  756 
  757         return (reg_sc);
  758 }
  759 
  760 int
  761 max77620_regulator_attach(struct max77620_softc *sc, phandle_t node)
  762 {
  763         struct max77620_reg_sc *reg;
  764         phandle_t child, rnode;
  765         int i;
  766 
  767         rnode = ofw_bus_find_child(node, "regulators");
  768         if (rnode <= 0) {
  769                 device_printf(sc->dev, " Cannot find regulators subnode\n");
  770                 return (ENXIO);
  771         }
  772 
  773         sc->nregs = nitems(max77620s_def);
  774         sc->regs = malloc(sizeof(struct max77620_reg_sc *) * sc->nregs,
  775             M_MAX77620_REG, M_WAITOK | M_ZERO);
  776 
  777 
  778         /* Attach all known regulators if exist in DT. */
  779         for (i = 0; i < sc->nregs; i++) {
  780                 child = ofw_bus_find_child(rnode, max77620s_def[i].name);
  781                 if (child == 0) {
  782                         if (bootverbose)
  783                                 device_printf(sc->dev,
  784                                     "Regulator %s missing in DT\n",
  785                                     max77620s_def[i].name);
  786                         continue;
  787                 }
  788                 if (ofw_bus_node_status_okay(child) == 0)
  789                         continue;
  790                 reg = max77620_attach(sc, child, max77620s_def + i);
  791                 if (reg == NULL) {
  792                         device_printf(sc->dev, "Cannot attach regulator: %s\n",
  793                             max77620s_def[i].name);
  794                         return (ENXIO);
  795                 }
  796                 sc->regs[i] = reg;
  797         }
  798         return (0);
  799 }
  800 
  801 int
  802 max77620_regulator_map(device_t dev, phandle_t xref, int ncells,
  803     pcell_t *cells, intptr_t *num)
  804 {
  805         struct max77620_softc *sc;
  806         int i;
  807 
  808         sc = device_get_softc(dev);
  809         for (i = 0; i < sc->nregs; i++) {
  810                 if (sc->regs[i] == NULL)
  811                         continue;
  812                 if (sc->regs[i]->xref == xref) {
  813                         *num = sc->regs[i]->def->id;
  814                         return (0);
  815                 }
  816         }
  817 
  818         return (ENXIO);
  819 }
  820 
  821 static int
  822 max77620_regnode_enable(struct regnode *regnode, bool val, int *udelay)
  823 {
  824 
  825         struct max77620_reg_sc *sc;
  826         uint8_t mode;
  827         int rv;
  828 
  829         sc = regnode_get_softc(regnode);
  830 
  831         if (sc->active_fps_src != MAX77620_FPS_SRC_NONE) {
  832                 *udelay = 0;
  833                 return (0);
  834         }
  835 
  836         if (val)
  837                 mode = sc->enable_pwr_mode;
  838         else
  839                 mode = MAX77620_POWER_MODE_DISABLE;
  840 
  841         rv = max77620_set_pwr_mode(sc, mode);
  842         if (rv != 0) {
  843                 printf("%s: cannot set power mode: %d\n",
  844                     regnode_get_name(sc->regnode), rv);
  845                 return (rv);
  846         }
  847 
  848         *udelay = sc->enable_usec;
  849         return (0);
  850 }
  851 
  852 static int
  853 max77620_regnode_set_volt(struct regnode *regnode, int min_uvolt, int max_uvolt,
  854     int *udelay)
  855 {
  856         struct max77620_reg_sc *sc;
  857         uint8_t sel;
  858         int rv;
  859 
  860         sc = regnode_get_softc(regnode);
  861 
  862         *udelay = 0;
  863         rv = regulator_range_volt_to_sel8(sc->def->ranges, sc->def->nranges,
  864             min_uvolt, max_uvolt, &sel);
  865         if (rv != 0)
  866                 return (rv);
  867         rv = max77620_set_sel(sc, sel);
  868         return (rv);
  869 }
  870 
  871 static int
  872 max77620_regnode_get_volt(struct regnode *regnode, int *uvolt)
  873 {
  874 
  875         struct max77620_reg_sc *sc;
  876         uint8_t sel;
  877         int rv;
  878 
  879         sc = regnode_get_softc(regnode);
  880         rv = max77620_get_sel(sc, &sel);
  881         if (rv != 0)
  882                 return (rv);
  883 
  884         rv = regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges,
  885             sel, uvolt);
  886         return (rv);
  887         return(0);
  888 }

Cache object: 689633f137c52ef9247c64e414551dbf


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