1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <limits.h> 10*91f16700Schasinglulu #include <stdint.h> 11*91f16700Schasinglulu #include <string.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <common/debug.h> 14*91f16700Schasinglulu #include <drivers/delay_timer.h> 15*91f16700Schasinglulu #include <drivers/st/regulator.h> 16*91f16700Schasinglulu #include <libfdt.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #define MAX_PROPERTY_LEN 64 19*91f16700Schasinglulu 20*91f16700Schasinglulu CASSERT(PLAT_NB_RDEVS >= 1U, plat_nb_rdevs_must_be_higher); 21*91f16700Schasinglulu 22*91f16700Schasinglulu static struct rdev rdev_array[PLAT_NB_RDEVS]; 23*91f16700Schasinglulu 24*91f16700Schasinglulu #define for_each_rdev(rdev) \ 25*91f16700Schasinglulu for ((rdev) = rdev_array; (rdev) <= &rdev_array[PLAT_NB_RDEVS - 1U]; (rdev)++) 26*91f16700Schasinglulu 27*91f16700Schasinglulu #define for_each_registered_rdev(rdev) \ 28*91f16700Schasinglulu for ((rdev) = rdev_array; \ 29*91f16700Schasinglulu ((rdev) <= &rdev_array[PLAT_NB_RDEVS - 1U]) && ((rdev)->desc != NULL); (rdev)++) 30*91f16700Schasinglulu 31*91f16700Schasinglulu static void lock_driver(const struct rdev *rdev) 32*91f16700Schasinglulu { 33*91f16700Schasinglulu if (rdev->desc->ops->lock != NULL) { 34*91f16700Schasinglulu rdev->desc->ops->lock(rdev->desc); 35*91f16700Schasinglulu } 36*91f16700Schasinglulu } 37*91f16700Schasinglulu 38*91f16700Schasinglulu static void unlock_driver(const struct rdev *rdev) 39*91f16700Schasinglulu { 40*91f16700Schasinglulu if (rdev->desc->ops->unlock != NULL) { 41*91f16700Schasinglulu rdev->desc->ops->unlock(rdev->desc); 42*91f16700Schasinglulu } 43*91f16700Schasinglulu } 44*91f16700Schasinglulu 45*91f16700Schasinglulu static struct rdev *regulator_get_by_phandle(int32_t phandle) 46*91f16700Schasinglulu { 47*91f16700Schasinglulu struct rdev *rdev; 48*91f16700Schasinglulu 49*91f16700Schasinglulu for_each_registered_rdev(rdev) { 50*91f16700Schasinglulu if (rdev->phandle == phandle) { 51*91f16700Schasinglulu return rdev; 52*91f16700Schasinglulu } 53*91f16700Schasinglulu } 54*91f16700Schasinglulu 55*91f16700Schasinglulu WARN("%s: phandle %d not found\n", __func__, phandle); 56*91f16700Schasinglulu return NULL; 57*91f16700Schasinglulu } 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* 60*91f16700Schasinglulu * Get a regulator from its node name 61*91f16700Schasinglulu * 62*91f16700Schasinglulu * @fdt - pointer to device tree memory 63*91f16700Schasinglulu * @node_name - name of the node "ldo1" 64*91f16700Schasinglulu * Return pointer to rdev if succeed, NULL else. 65*91f16700Schasinglulu */ 66*91f16700Schasinglulu struct rdev *regulator_get_by_name(const char *node_name) 67*91f16700Schasinglulu { 68*91f16700Schasinglulu struct rdev *rdev; 69*91f16700Schasinglulu 70*91f16700Schasinglulu assert(node_name != NULL); 71*91f16700Schasinglulu VERBOSE("get %s\n", node_name); 72*91f16700Schasinglulu 73*91f16700Schasinglulu for_each_registered_rdev(rdev) { 74*91f16700Schasinglulu if (strcmp(rdev->desc->node_name, node_name) == 0) { 75*91f16700Schasinglulu return rdev; 76*91f16700Schasinglulu } 77*91f16700Schasinglulu } 78*91f16700Schasinglulu 79*91f16700Schasinglulu WARN("%s: %s not found\n", __func__, node_name); 80*91f16700Schasinglulu return NULL; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu static int32_t get_supply_phandle(const void *fdt, int node, const char *name) 84*91f16700Schasinglulu { 85*91f16700Schasinglulu const fdt32_t *cuint; 86*91f16700Schasinglulu int len __unused; 87*91f16700Schasinglulu int supply_phandle = -FDT_ERR_NOTFOUND; 88*91f16700Schasinglulu char prop_name[MAX_PROPERTY_LEN]; 89*91f16700Schasinglulu 90*91f16700Schasinglulu len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name); 91*91f16700Schasinglulu assert((len >= 0) && (len < (MAX_PROPERTY_LEN - 1))); 92*91f16700Schasinglulu 93*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, prop_name, NULL); 94*91f16700Schasinglulu if (cuint != NULL) { 95*91f16700Schasinglulu supply_phandle = fdt32_to_cpu(*cuint); 96*91f16700Schasinglulu VERBOSE("%s: supplied by %d\n", name, supply_phandle); 97*91f16700Schasinglulu } 98*91f16700Schasinglulu 99*91f16700Schasinglulu return supply_phandle; 100*91f16700Schasinglulu } 101*91f16700Schasinglulu 102*91f16700Schasinglulu /* 103*91f16700Schasinglulu * Get a regulator from a supply name 104*91f16700Schasinglulu * 105*91f16700Schasinglulu * @fdt - pointer to device tree memory 106*91f16700Schasinglulu * @node - offset of the node that contains the supply description 107*91f16700Schasinglulu * @name - name of the supply "vdd" for "vdd-supply' 108*91f16700Schasinglulu * Return pointer to rdev if succeed, NULL else. 109*91f16700Schasinglulu */ 110*91f16700Schasinglulu struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name) 111*91f16700Schasinglulu { 112*91f16700Schasinglulu const int p = get_supply_phandle(fdt, node, name); 113*91f16700Schasinglulu 114*91f16700Schasinglulu if (p < 0) { 115*91f16700Schasinglulu return NULL; 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu return regulator_get_by_phandle(p); 119*91f16700Schasinglulu } 120*91f16700Schasinglulu 121*91f16700Schasinglulu static int __regulator_set_state(struct rdev *rdev, bool state) 122*91f16700Schasinglulu { 123*91f16700Schasinglulu if (rdev->desc->ops->set_state == NULL) { 124*91f16700Schasinglulu return -ENODEV; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu 127*91f16700Schasinglulu return rdev->desc->ops->set_state(rdev->desc, state); 128*91f16700Schasinglulu } 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* 131*91f16700Schasinglulu * Enable regulator 132*91f16700Schasinglulu * 133*91f16700Schasinglulu * @rdev - pointer to rdev struct 134*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 135*91f16700Schasinglulu */ 136*91f16700Schasinglulu int regulator_enable(struct rdev *rdev) 137*91f16700Schasinglulu { 138*91f16700Schasinglulu int ret; 139*91f16700Schasinglulu 140*91f16700Schasinglulu assert(rdev != NULL); 141*91f16700Schasinglulu 142*91f16700Schasinglulu ret = __regulator_set_state(rdev, STATE_ENABLE); 143*91f16700Schasinglulu 144*91f16700Schasinglulu udelay(rdev->enable_ramp_delay); 145*91f16700Schasinglulu 146*91f16700Schasinglulu return ret; 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu /* 150*91f16700Schasinglulu * Disable regulator 151*91f16700Schasinglulu * 152*91f16700Schasinglulu * @rdev - pointer to rdev struct 153*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 154*91f16700Schasinglulu */ 155*91f16700Schasinglulu int regulator_disable(struct rdev *rdev) 156*91f16700Schasinglulu { 157*91f16700Schasinglulu int ret; 158*91f16700Schasinglulu 159*91f16700Schasinglulu assert(rdev != NULL); 160*91f16700Schasinglulu 161*91f16700Schasinglulu if ((rdev->flags & REGUL_ALWAYS_ON) != 0U) { 162*91f16700Schasinglulu return 0; 163*91f16700Schasinglulu } 164*91f16700Schasinglulu 165*91f16700Schasinglulu ret = __regulator_set_state(rdev, STATE_DISABLE); 166*91f16700Schasinglulu 167*91f16700Schasinglulu udelay(rdev->enable_ramp_delay); 168*91f16700Schasinglulu 169*91f16700Schasinglulu return ret; 170*91f16700Schasinglulu } 171*91f16700Schasinglulu 172*91f16700Schasinglulu /* 173*91f16700Schasinglulu * Regulator enabled query 174*91f16700Schasinglulu * 175*91f16700Schasinglulu * @rdev - pointer to rdev struct 176*91f16700Schasinglulu * Return 0 if disabled, 1 if enabled, <0 else. 177*91f16700Schasinglulu */ 178*91f16700Schasinglulu int regulator_is_enabled(const struct rdev *rdev) 179*91f16700Schasinglulu { 180*91f16700Schasinglulu int ret; 181*91f16700Schasinglulu 182*91f16700Schasinglulu assert(rdev != NULL); 183*91f16700Schasinglulu 184*91f16700Schasinglulu VERBOSE("%s: is en\n", rdev->desc->node_name); 185*91f16700Schasinglulu 186*91f16700Schasinglulu if (rdev->desc->ops->get_state == NULL) { 187*91f16700Schasinglulu return -ENODEV; 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu lock_driver(rdev); 191*91f16700Schasinglulu 192*91f16700Schasinglulu ret = rdev->desc->ops->get_state(rdev->desc); 193*91f16700Schasinglulu if (ret < 0) { 194*91f16700Schasinglulu ERROR("regul %s get state failed: err:%d\n", 195*91f16700Schasinglulu rdev->desc->node_name, ret); 196*91f16700Schasinglulu } 197*91f16700Schasinglulu 198*91f16700Schasinglulu unlock_driver(rdev); 199*91f16700Schasinglulu 200*91f16700Schasinglulu return ret; 201*91f16700Schasinglulu } 202*91f16700Schasinglulu 203*91f16700Schasinglulu /* 204*91f16700Schasinglulu * Set regulator voltage 205*91f16700Schasinglulu * 206*91f16700Schasinglulu * @rdev - pointer to rdev struct 207*91f16700Schasinglulu * @mvolt - Target voltage level in millivolt 208*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 209*91f16700Schasinglulu */ 210*91f16700Schasinglulu int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt) 211*91f16700Schasinglulu { 212*91f16700Schasinglulu int ret; 213*91f16700Schasinglulu 214*91f16700Schasinglulu assert(rdev != NULL); 215*91f16700Schasinglulu 216*91f16700Schasinglulu VERBOSE("%s: set mvolt\n", rdev->desc->node_name); 217*91f16700Schasinglulu 218*91f16700Schasinglulu if (rdev->desc->ops->set_voltage == NULL) { 219*91f16700Schasinglulu return -ENODEV; 220*91f16700Schasinglulu } 221*91f16700Schasinglulu 222*91f16700Schasinglulu if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) { 223*91f16700Schasinglulu return -EPERM; 224*91f16700Schasinglulu } 225*91f16700Schasinglulu 226*91f16700Schasinglulu lock_driver(rdev); 227*91f16700Schasinglulu 228*91f16700Schasinglulu ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt); 229*91f16700Schasinglulu if (ret < 0) { 230*91f16700Schasinglulu ERROR("regul %s set volt failed: err:%d\n", 231*91f16700Schasinglulu rdev->desc->node_name, ret); 232*91f16700Schasinglulu } 233*91f16700Schasinglulu 234*91f16700Schasinglulu unlock_driver(rdev); 235*91f16700Schasinglulu 236*91f16700Schasinglulu return ret; 237*91f16700Schasinglulu } 238*91f16700Schasinglulu 239*91f16700Schasinglulu /* 240*91f16700Schasinglulu * Set regulator min voltage 241*91f16700Schasinglulu * 242*91f16700Schasinglulu * @rdev - pointer to rdev struct 243*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 244*91f16700Schasinglulu */ 245*91f16700Schasinglulu int regulator_set_min_voltage(struct rdev *rdev) 246*91f16700Schasinglulu { 247*91f16700Schasinglulu return regulator_set_voltage(rdev, rdev->min_mv); 248*91f16700Schasinglulu } 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* 251*91f16700Schasinglulu * Get regulator voltage 252*91f16700Schasinglulu * 253*91f16700Schasinglulu * @rdev - pointer to rdev struct 254*91f16700Schasinglulu * Return milli volts if succeed, <0 else. 255*91f16700Schasinglulu */ 256*91f16700Schasinglulu int regulator_get_voltage(const struct rdev *rdev) 257*91f16700Schasinglulu { 258*91f16700Schasinglulu int ret; 259*91f16700Schasinglulu 260*91f16700Schasinglulu assert(rdev != NULL); 261*91f16700Schasinglulu 262*91f16700Schasinglulu VERBOSE("%s: get volt\n", rdev->desc->node_name); 263*91f16700Schasinglulu 264*91f16700Schasinglulu if (rdev->desc->ops->get_voltage == NULL) { 265*91f16700Schasinglulu return rdev->min_mv; 266*91f16700Schasinglulu } 267*91f16700Schasinglulu 268*91f16700Schasinglulu lock_driver(rdev); 269*91f16700Schasinglulu 270*91f16700Schasinglulu ret = rdev->desc->ops->get_voltage(rdev->desc); 271*91f16700Schasinglulu if (ret < 0) { 272*91f16700Schasinglulu ERROR("regul %s get voltage failed: err:%d\n", 273*91f16700Schasinglulu rdev->desc->node_name, ret); 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu unlock_driver(rdev); 277*91f16700Schasinglulu 278*91f16700Schasinglulu return ret; 279*91f16700Schasinglulu } 280*91f16700Schasinglulu 281*91f16700Schasinglulu /* 282*91f16700Schasinglulu * List regulator voltages 283*91f16700Schasinglulu * 284*91f16700Schasinglulu * @rdev - pointer to rdev struct 285*91f16700Schasinglulu * @levels - out: array of supported millitvolt levels from min to max value 286*91f16700Schasinglulu * @count - out: number of possible millivolt values 287*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 288*91f16700Schasinglulu */ 289*91f16700Schasinglulu int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count) 290*91f16700Schasinglulu { 291*91f16700Schasinglulu int ret; 292*91f16700Schasinglulu size_t n; 293*91f16700Schasinglulu 294*91f16700Schasinglulu assert(rdev != NULL); 295*91f16700Schasinglulu assert(levels != NULL); 296*91f16700Schasinglulu assert(count != NULL); 297*91f16700Schasinglulu 298*91f16700Schasinglulu VERBOSE("%s: list volt\n", rdev->desc->node_name); 299*91f16700Schasinglulu 300*91f16700Schasinglulu if (rdev->desc->ops->list_voltages == NULL) { 301*91f16700Schasinglulu return -ENODEV; 302*91f16700Schasinglulu } 303*91f16700Schasinglulu 304*91f16700Schasinglulu lock_driver(rdev); 305*91f16700Schasinglulu 306*91f16700Schasinglulu ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count); 307*91f16700Schasinglulu 308*91f16700Schasinglulu unlock_driver(rdev); 309*91f16700Schasinglulu 310*91f16700Schasinglulu if (ret < 0) { 311*91f16700Schasinglulu ERROR("regul %s list_voltages failed: err: %d\n", 312*91f16700Schasinglulu rdev->desc->node_name, ret); 313*91f16700Schasinglulu return ret; 314*91f16700Schasinglulu } 315*91f16700Schasinglulu 316*91f16700Schasinglulu /* 317*91f16700Schasinglulu * Reduce the possible values depending on min and max from device-tree 318*91f16700Schasinglulu */ 319*91f16700Schasinglulu n = *count; 320*91f16700Schasinglulu while ((n > 1U) && ((*levels)[n - 1U] > rdev->max_mv)) { 321*91f16700Schasinglulu n--; 322*91f16700Schasinglulu } 323*91f16700Schasinglulu 324*91f16700Schasinglulu /* Verify that max val is a valid value */ 325*91f16700Schasinglulu if (rdev->max_mv != (*levels)[n - 1]) { 326*91f16700Schasinglulu ERROR("regul %s: max value %u is invalid\n", 327*91f16700Schasinglulu rdev->desc->node_name, rdev->max_mv); 328*91f16700Schasinglulu return -EINVAL; 329*91f16700Schasinglulu } 330*91f16700Schasinglulu 331*91f16700Schasinglulu while ((n > 1U) && ((*levels[0U]) < rdev->min_mv)) { 332*91f16700Schasinglulu (*levels)++; 333*91f16700Schasinglulu n--; 334*91f16700Schasinglulu } 335*91f16700Schasinglulu 336*91f16700Schasinglulu /* Verify that min is not too high */ 337*91f16700Schasinglulu if (n == 0U) { 338*91f16700Schasinglulu ERROR("regul %s set min voltage is too high\n", 339*91f16700Schasinglulu rdev->desc->node_name); 340*91f16700Schasinglulu return -EINVAL; 341*91f16700Schasinglulu } 342*91f16700Schasinglulu 343*91f16700Schasinglulu /* Verify that min val is a valid vlue */ 344*91f16700Schasinglulu if (rdev->min_mv != (*levels)[0U]) { 345*91f16700Schasinglulu ERROR("regul %s: min value %u is invalid\n", 346*91f16700Schasinglulu rdev->desc->node_name, rdev->min_mv); 347*91f16700Schasinglulu return -EINVAL; 348*91f16700Schasinglulu } 349*91f16700Schasinglulu 350*91f16700Schasinglulu *count = n; 351*91f16700Schasinglulu 352*91f16700Schasinglulu VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv); 353*91f16700Schasinglulu 354*91f16700Schasinglulu return 0; 355*91f16700Schasinglulu } 356*91f16700Schasinglulu 357*91f16700Schasinglulu /* 358*91f16700Schasinglulu * Get regulator voltages range 359*91f16700Schasinglulu * 360*91f16700Schasinglulu * @rdev - pointer to rdev struct 361*91f16700Schasinglulu * @min_mv - out: min possible millivolt value 362*91f16700Schasinglulu * @max_mv - out: max possible millivolt value 363*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 364*91f16700Schasinglulu */ 365*91f16700Schasinglulu void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv) 366*91f16700Schasinglulu { 367*91f16700Schasinglulu assert(rdev != NULL); 368*91f16700Schasinglulu 369*91f16700Schasinglulu if (min_mv != NULL) { 370*91f16700Schasinglulu *min_mv = rdev->min_mv; 371*91f16700Schasinglulu } 372*91f16700Schasinglulu if (max_mv != NULL) { 373*91f16700Schasinglulu *max_mv = rdev->max_mv; 374*91f16700Schasinglulu } 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu /* 378*91f16700Schasinglulu * Set regulator flag 379*91f16700Schasinglulu * 380*91f16700Schasinglulu * @rdev - pointer to rdev struct 381*91f16700Schasinglulu * @flag - flag value to set (eg: REGUL_OCP) 382*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 383*91f16700Schasinglulu */ 384*91f16700Schasinglulu int regulator_set_flag(struct rdev *rdev, uint16_t flag) 385*91f16700Schasinglulu { 386*91f16700Schasinglulu int ret; 387*91f16700Schasinglulu 388*91f16700Schasinglulu /* check that only one bit is set on flag */ 389*91f16700Schasinglulu if (__builtin_popcount(flag) != 1) { 390*91f16700Schasinglulu return -EINVAL; 391*91f16700Schasinglulu } 392*91f16700Schasinglulu 393*91f16700Schasinglulu /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */ 394*91f16700Schasinglulu if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) { 395*91f16700Schasinglulu rdev->flags |= flag; 396*91f16700Schasinglulu return 0; 397*91f16700Schasinglulu } 398*91f16700Schasinglulu 399*91f16700Schasinglulu if (rdev->desc->ops->set_flag == NULL) { 400*91f16700Schasinglulu ERROR("%s can not set any flag\n", rdev->desc->node_name); 401*91f16700Schasinglulu return -ENODEV; 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu lock_driver(rdev); 405*91f16700Schasinglulu 406*91f16700Schasinglulu ret = rdev->desc->ops->set_flag(rdev->desc, flag); 407*91f16700Schasinglulu 408*91f16700Schasinglulu unlock_driver(rdev); 409*91f16700Schasinglulu 410*91f16700Schasinglulu if (ret != 0) { 411*91f16700Schasinglulu ERROR("%s: could not set flag %d ret=%d\n", 412*91f16700Schasinglulu rdev->desc->node_name, flag, ret); 413*91f16700Schasinglulu return ret; 414*91f16700Schasinglulu } 415*91f16700Schasinglulu 416*91f16700Schasinglulu rdev->flags |= flag; 417*91f16700Schasinglulu 418*91f16700Schasinglulu return 0; 419*91f16700Schasinglulu } 420*91f16700Schasinglulu 421*91f16700Schasinglulu static int parse_properties(const void *fdt, struct rdev *rdev, int node) 422*91f16700Schasinglulu { 423*91f16700Schasinglulu int ret; 424*91f16700Schasinglulu 425*91f16700Schasinglulu if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { 426*91f16700Schasinglulu VERBOSE("%s: set regulator-always-on\n", rdev->desc->node_name); 427*91f16700Schasinglulu ret = regulator_set_flag(rdev, REGUL_ALWAYS_ON); 428*91f16700Schasinglulu if (ret != 0) { 429*91f16700Schasinglulu return ret; 430*91f16700Schasinglulu } 431*91f16700Schasinglulu } 432*91f16700Schasinglulu 433*91f16700Schasinglulu return 0; 434*91f16700Schasinglulu } 435*91f16700Schasinglulu 436*91f16700Schasinglulu /* 437*91f16700Schasinglulu * Parse the device-tree for a regulator 438*91f16700Schasinglulu * 439*91f16700Schasinglulu * Read min/max voltage from dt and check its validity 440*91f16700Schasinglulu * Read the properties, and call the driver to set flags 441*91f16700Schasinglulu * Read power supply phandle 442*91f16700Schasinglulu * Read and store low power mode states 443*91f16700Schasinglulu * 444*91f16700Schasinglulu * @rdev - pointer to rdev struct 445*91f16700Schasinglulu * @node - device-tree node offset of the regulator 446*91f16700Schasinglulu * Return 0 if disabled, 1 if enabled, <0 else. 447*91f16700Schasinglulu */ 448*91f16700Schasinglulu static int parse_dt(struct rdev *rdev, int node) 449*91f16700Schasinglulu { 450*91f16700Schasinglulu void *fdt; 451*91f16700Schasinglulu const fdt32_t *cuint; 452*91f16700Schasinglulu const uint16_t *levels; 453*91f16700Schasinglulu size_t size; 454*91f16700Schasinglulu int ret; 455*91f16700Schasinglulu 456*91f16700Schasinglulu VERBOSE("%s: parse dt\n", rdev->desc->node_name); 457*91f16700Schasinglulu 458*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 459*91f16700Schasinglulu return -ENOENT; 460*91f16700Schasinglulu } 461*91f16700Schasinglulu 462*91f16700Schasinglulu rdev->phandle = fdt_get_phandle(fdt, node); 463*91f16700Schasinglulu 464*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); 465*91f16700Schasinglulu if (cuint != NULL) { 466*91f16700Schasinglulu uint16_t min_mv; 467*91f16700Schasinglulu 468*91f16700Schasinglulu min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); 469*91f16700Schasinglulu VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv); 470*91f16700Schasinglulu if (min_mv <= rdev->max_mv) { 471*91f16700Schasinglulu rdev->min_mv = min_mv; 472*91f16700Schasinglulu } else { 473*91f16700Schasinglulu ERROR("%s: min_mv=%d is too high\n", 474*91f16700Schasinglulu rdev->desc->node_name, (int)min_mv); 475*91f16700Schasinglulu return -EINVAL; 476*91f16700Schasinglulu } 477*91f16700Schasinglulu } 478*91f16700Schasinglulu 479*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); 480*91f16700Schasinglulu if (cuint != NULL) { 481*91f16700Schasinglulu uint16_t max_mv; 482*91f16700Schasinglulu 483*91f16700Schasinglulu max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); 484*91f16700Schasinglulu VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv); 485*91f16700Schasinglulu if (max_mv >= rdev->min_mv) { 486*91f16700Schasinglulu rdev->max_mv = max_mv; 487*91f16700Schasinglulu } else { 488*91f16700Schasinglulu ERROR("%s: max_mv=%d is too low\n", 489*91f16700Schasinglulu rdev->desc->node_name, (int)max_mv); 490*91f16700Schasinglulu return -EINVAL; 491*91f16700Schasinglulu } 492*91f16700Schasinglulu } 493*91f16700Schasinglulu 494*91f16700Schasinglulu /* validate that min and max values can be used */ 495*91f16700Schasinglulu ret = regulator_list_voltages(rdev, &levels, &size); 496*91f16700Schasinglulu if ((ret != 0) && (ret != -ENODEV)) { 497*91f16700Schasinglulu return ret; 498*91f16700Schasinglulu } 499*91f16700Schasinglulu 500*91f16700Schasinglulu ret = parse_properties(fdt, rdev, node); 501*91f16700Schasinglulu if (ret != 0) { 502*91f16700Schasinglulu return ret; 503*91f16700Schasinglulu } 504*91f16700Schasinglulu 505*91f16700Schasinglulu return 0; 506*91f16700Schasinglulu } 507*91f16700Schasinglulu 508*91f16700Schasinglulu /* 509*91f16700Schasinglulu * Register a regulator driver in regulator framework. 510*91f16700Schasinglulu * Initialize voltage range from driver description 511*91f16700Schasinglulu * 512*91f16700Schasinglulu * @desc - pointer to the regulator description 513*91f16700Schasinglulu * @node - device-tree node offset of the regulator 514*91f16700Schasinglulu * Return 0 if succeed, non 0 else. 515*91f16700Schasinglulu */ 516*91f16700Schasinglulu int regulator_register(const struct regul_description *desc, int node) 517*91f16700Schasinglulu { 518*91f16700Schasinglulu struct rdev *rdev; 519*91f16700Schasinglulu 520*91f16700Schasinglulu assert(desc != NULL); 521*91f16700Schasinglulu 522*91f16700Schasinglulu VERBOSE("register %s\n", desc->node_name); 523*91f16700Schasinglulu 524*91f16700Schasinglulu for_each_rdev(rdev) { 525*91f16700Schasinglulu if (rdev->desc == NULL) { 526*91f16700Schasinglulu break; 527*91f16700Schasinglulu } 528*91f16700Schasinglulu } 529*91f16700Schasinglulu 530*91f16700Schasinglulu if (rdev > &rdev_array[PLAT_NB_RDEVS - 1U]) { 531*91f16700Schasinglulu WARN("Not enough place for regulators, PLAT_NB_RDEVS should be increased.\n"); 532*91f16700Schasinglulu return -ENOMEM; 533*91f16700Schasinglulu } 534*91f16700Schasinglulu 535*91f16700Schasinglulu rdev->desc = desc; 536*91f16700Schasinglulu rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay; 537*91f16700Schasinglulu 538*91f16700Schasinglulu if (rdev->desc->ops->list_voltages != NULL) { 539*91f16700Schasinglulu int ret; 540*91f16700Schasinglulu const uint16_t *levels; 541*91f16700Schasinglulu size_t count; 542*91f16700Schasinglulu 543*91f16700Schasinglulu lock_driver(rdev); 544*91f16700Schasinglulu 545*91f16700Schasinglulu ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count); 546*91f16700Schasinglulu 547*91f16700Schasinglulu unlock_driver(rdev); 548*91f16700Schasinglulu 549*91f16700Schasinglulu if (ret < 0) { 550*91f16700Schasinglulu ERROR("regul %s set state failed: err:%d\n", 551*91f16700Schasinglulu rdev->desc->node_name, ret); 552*91f16700Schasinglulu return ret; 553*91f16700Schasinglulu } 554*91f16700Schasinglulu 555*91f16700Schasinglulu rdev->min_mv = levels[0]; 556*91f16700Schasinglulu rdev->max_mv = levels[count - 1U]; 557*91f16700Schasinglulu } else { 558*91f16700Schasinglulu rdev->max_mv = UINT16_MAX; 559*91f16700Schasinglulu } 560*91f16700Schasinglulu 561*91f16700Schasinglulu return parse_dt(rdev, node); 562*91f16700Schasinglulu } 563