1af41e8dbSPrzemyslaw Marczak /* 2af41e8dbSPrzemyslaw Marczak * Copyright (C) 2014-2015 Samsung Electronics 3af41e8dbSPrzemyslaw Marczak * Przemyslaw Marczak <p.marczak@samsung.com> 4af41e8dbSPrzemyslaw Marczak * 5af41e8dbSPrzemyslaw Marczak * SPDX-License-Identifier: GPL-2.0+ 6af41e8dbSPrzemyslaw Marczak */ 7f15cd4f1SSimon Glass 8af41e8dbSPrzemyslaw Marczak #include <common.h> 9af41e8dbSPrzemyslaw Marczak #include <errno.h> 10af41e8dbSPrzemyslaw Marczak #include <dm.h> 11af41e8dbSPrzemyslaw Marczak #include <dm/uclass-internal.h> 12af41e8dbSPrzemyslaw Marczak #include <power/pmic.h> 13af41e8dbSPrzemyslaw Marczak #include <power/regulator.h> 14af41e8dbSPrzemyslaw Marczak 15af41e8dbSPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR; 16af41e8dbSPrzemyslaw Marczak 17af41e8dbSPrzemyslaw Marczak int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep) 18af41e8dbSPrzemyslaw Marczak { 19af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 20af41e8dbSPrzemyslaw Marczak 21af41e8dbSPrzemyslaw Marczak *modep = NULL; 22af41e8dbSPrzemyslaw Marczak 23af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 24af41e8dbSPrzemyslaw Marczak if (!uc_pdata) 25af41e8dbSPrzemyslaw Marczak return -ENXIO; 26af41e8dbSPrzemyslaw Marczak 27af41e8dbSPrzemyslaw Marczak *modep = uc_pdata->mode; 28af41e8dbSPrzemyslaw Marczak return uc_pdata->mode_count; 29af41e8dbSPrzemyslaw Marczak } 30af41e8dbSPrzemyslaw Marczak 31af41e8dbSPrzemyslaw Marczak int regulator_get_value(struct udevice *dev) 32af41e8dbSPrzemyslaw Marczak { 33af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 34af41e8dbSPrzemyslaw Marczak 35af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_value) 36af41e8dbSPrzemyslaw Marczak return -ENOSYS; 37af41e8dbSPrzemyslaw Marczak 38af41e8dbSPrzemyslaw Marczak return ops->get_value(dev); 39af41e8dbSPrzemyslaw Marczak } 40af41e8dbSPrzemyslaw Marczak 41af41e8dbSPrzemyslaw Marczak int regulator_set_value(struct udevice *dev, int uV) 42af41e8dbSPrzemyslaw Marczak { 43af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 44eaadcf38SKeerthy struct dm_regulator_uclass_platdata *uc_pdata; 45b29e2b63SJoseph Chen u32 old_uV = -ENODATA, us; 46b29e2b63SJoseph Chen int ret; 47eaadcf38SKeerthy 48eaadcf38SKeerthy uc_pdata = dev_get_uclass_platdata(dev); 49eaadcf38SKeerthy if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV) 50eaadcf38SKeerthy return -EINVAL; 51eaadcf38SKeerthy if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV) 52eaadcf38SKeerthy return -EINVAL; 53af41e8dbSPrzemyslaw Marczak 54af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_value) 55af41e8dbSPrzemyslaw Marczak return -ENOSYS; 56af41e8dbSPrzemyslaw Marczak 57b29e2b63SJoseph Chen if (uc_pdata->ramp_delay != -ENODATA) { 58b29e2b63SJoseph Chen if (!ops->get_value) 59b29e2b63SJoseph Chen return -ENOSYS; 60b29e2b63SJoseph Chen old_uV = ops->get_value(dev); 61b29e2b63SJoseph Chen if (old_uV < 0) 62b29e2b63SJoseph Chen return -EINVAL; 63b29e2b63SJoseph Chen } 64b29e2b63SJoseph Chen 65b29e2b63SJoseph Chen ret = ops->set_value(dev, uV); 66b29e2b63SJoseph Chen 67b29e2b63SJoseph Chen if (!ret && (old_uV != -ENODATA) && (old_uV != uV)) { 68b29e2b63SJoseph Chen us = DIV_ROUND_UP(abs(uV - old_uV), uc_pdata->ramp_delay); 69b29e2b63SJoseph Chen udelay(us); 70b29e2b63SJoseph Chen debug("%s: ramp=%d, old_uV=%d, uV=%d, us=%d\n", 71b29e2b63SJoseph Chen uc_pdata->name, uc_pdata->ramp_delay, old_uV, uV, us); 72b29e2b63SJoseph Chen } 73b29e2b63SJoseph Chen 74b29e2b63SJoseph Chen return ret; 75af41e8dbSPrzemyslaw Marczak } 76af41e8dbSPrzemyslaw Marczak 77fbc6dab9SJoseph Chen int regulator_set_suspend_value(struct udevice *dev, int uV) 78fbc6dab9SJoseph Chen { 79fbc6dab9SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 80fbc6dab9SJoseph Chen 81fbc6dab9SJoseph Chen if (!ops || !ops->set_suspend_value) 82fbc6dab9SJoseph Chen return -ENOSYS; 83fbc6dab9SJoseph Chen 84fbc6dab9SJoseph Chen return ops->set_suspend_value(dev, uV); 85fbc6dab9SJoseph Chen } 86fbc6dab9SJoseph Chen 8771aebe78SJoseph Chen int regulator_get_suspend_value(struct udevice *dev) 8871aebe78SJoseph Chen { 8971aebe78SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 9071aebe78SJoseph Chen 9171aebe78SJoseph Chen if (!ops || !ops->get_suspend_value) 9271aebe78SJoseph Chen return -ENOSYS; 9371aebe78SJoseph Chen 9471aebe78SJoseph Chen return ops->get_suspend_value(dev); 9571aebe78SJoseph Chen } 9671aebe78SJoseph Chen 972f5d532fSKeerthy /* 982f5d532fSKeerthy * To be called with at most caution as there is no check 992f5d532fSKeerthy * before setting the actual voltage value. 1002f5d532fSKeerthy */ 1012f5d532fSKeerthy int regulator_set_value_force(struct udevice *dev, int uV) 1022f5d532fSKeerthy { 1032f5d532fSKeerthy const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 1042f5d532fSKeerthy 1052f5d532fSKeerthy if (!ops || !ops->set_value) 1062f5d532fSKeerthy return -ENOSYS; 1072f5d532fSKeerthy 1082f5d532fSKeerthy return ops->set_value(dev, uV); 1092f5d532fSKeerthy } 1102f5d532fSKeerthy 111af41e8dbSPrzemyslaw Marczak int regulator_get_current(struct udevice *dev) 112af41e8dbSPrzemyslaw Marczak { 113af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 114af41e8dbSPrzemyslaw Marczak 115af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_current) 116af41e8dbSPrzemyslaw Marczak return -ENOSYS; 117af41e8dbSPrzemyslaw Marczak 118af41e8dbSPrzemyslaw Marczak return ops->get_current(dev); 119af41e8dbSPrzemyslaw Marczak } 120af41e8dbSPrzemyslaw Marczak 121af41e8dbSPrzemyslaw Marczak int regulator_set_current(struct udevice *dev, int uA) 122af41e8dbSPrzemyslaw Marczak { 123af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 1245483456eSKeerthy struct dm_regulator_uclass_platdata *uc_pdata; 1255483456eSKeerthy 1265483456eSKeerthy uc_pdata = dev_get_uclass_platdata(dev); 1275483456eSKeerthy if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA) 1285483456eSKeerthy return -EINVAL; 1295483456eSKeerthy if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA) 1305483456eSKeerthy return -EINVAL; 131af41e8dbSPrzemyslaw Marczak 132af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_current) 133af41e8dbSPrzemyslaw Marczak return -ENOSYS; 134af41e8dbSPrzemyslaw Marczak 135af41e8dbSPrzemyslaw Marczak return ops->set_current(dev, uA); 136af41e8dbSPrzemyslaw Marczak } 137af41e8dbSPrzemyslaw Marczak 13806bdf600SKeerthy int regulator_get_enable(struct udevice *dev) 139af41e8dbSPrzemyslaw Marczak { 140af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 141af41e8dbSPrzemyslaw Marczak 142af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_enable) 143af41e8dbSPrzemyslaw Marczak return -ENOSYS; 144af41e8dbSPrzemyslaw Marczak 145af41e8dbSPrzemyslaw Marczak return ops->get_enable(dev); 146af41e8dbSPrzemyslaw Marczak } 147af41e8dbSPrzemyslaw Marczak 148af41e8dbSPrzemyslaw Marczak int regulator_set_enable(struct udevice *dev, bool enable) 149af41e8dbSPrzemyslaw Marczak { 150af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 151af41e8dbSPrzemyslaw Marczak 152af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_enable) 153af41e8dbSPrzemyslaw Marczak return -ENOSYS; 154af41e8dbSPrzemyslaw Marczak 155af41e8dbSPrzemyslaw Marczak return ops->set_enable(dev, enable); 156af41e8dbSPrzemyslaw Marczak } 157af41e8dbSPrzemyslaw Marczak 158fbc6dab9SJoseph Chen int regulator_set_suspend_enable(struct udevice *dev, bool enable) 159fbc6dab9SJoseph Chen { 160fbc6dab9SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 161fbc6dab9SJoseph Chen 162fbc6dab9SJoseph Chen if (!ops || !ops->set_suspend_enable) 163fbc6dab9SJoseph Chen return -ENOSYS; 164fbc6dab9SJoseph Chen 165fbc6dab9SJoseph Chen return ops->set_suspend_enable(dev, enable); 166fbc6dab9SJoseph Chen } 167fbc6dab9SJoseph Chen 16871aebe78SJoseph Chen int regulator_get_suspend_enable(struct udevice *dev) 16971aebe78SJoseph Chen { 17071aebe78SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 17171aebe78SJoseph Chen 17271aebe78SJoseph Chen if (!ops || !ops->get_suspend_enable) 17371aebe78SJoseph Chen return -ENOSYS; 17471aebe78SJoseph Chen 17571aebe78SJoseph Chen return ops->get_suspend_enable(dev); 17671aebe78SJoseph Chen } 17771aebe78SJoseph Chen 178b29e2b63SJoseph Chen int regulator_set_ramp_delay(struct udevice *dev, u32 ramp_delay) 179b29e2b63SJoseph Chen { 180b29e2b63SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 181b29e2b63SJoseph Chen 182b29e2b63SJoseph Chen if (!ops || !ops->set_ramp_delay) 183b29e2b63SJoseph Chen return -ENOSYS; 184b29e2b63SJoseph Chen 185b29e2b63SJoseph Chen return ops->set_ramp_delay(dev, ramp_delay); 186b29e2b63SJoseph Chen } 187b29e2b63SJoseph Chen 188af41e8dbSPrzemyslaw Marczak int regulator_get_mode(struct udevice *dev) 189af41e8dbSPrzemyslaw Marczak { 190af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 191af41e8dbSPrzemyslaw Marczak 192af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_mode) 193af41e8dbSPrzemyslaw Marczak return -ENOSYS; 194af41e8dbSPrzemyslaw Marczak 195af41e8dbSPrzemyslaw Marczak return ops->get_mode(dev); 196af41e8dbSPrzemyslaw Marczak } 197af41e8dbSPrzemyslaw Marczak 198af41e8dbSPrzemyslaw Marczak int regulator_set_mode(struct udevice *dev, int mode) 199af41e8dbSPrzemyslaw Marczak { 200af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 201af41e8dbSPrzemyslaw Marczak 202af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_mode) 203af41e8dbSPrzemyslaw Marczak return -ENOSYS; 204af41e8dbSPrzemyslaw Marczak 205af41e8dbSPrzemyslaw Marczak return ops->set_mode(dev, mode); 206af41e8dbSPrzemyslaw Marczak } 207af41e8dbSPrzemyslaw Marczak 2083b880757SPrzemyslaw Marczak int regulator_get_by_platname(const char *plat_name, struct udevice **devp) 209af41e8dbSPrzemyslaw Marczak { 210af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 211af41e8dbSPrzemyslaw Marczak struct udevice *dev; 2123b880757SPrzemyslaw Marczak int ret; 213af41e8dbSPrzemyslaw Marczak 214af41e8dbSPrzemyslaw Marczak *devp = NULL; 215af41e8dbSPrzemyslaw Marczak 2163b880757SPrzemyslaw Marczak for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; 2173b880757SPrzemyslaw Marczak ret = uclass_find_next_device(&dev)) { 218422f04b6SSimon Glass if (ret) { 219422f04b6SSimon Glass debug("regulator %s, ret=%d\n", dev->name, ret); 2203b880757SPrzemyslaw Marczak continue; 221422f04b6SSimon Glass } 2223b880757SPrzemyslaw Marczak 223af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 224af41e8dbSPrzemyslaw Marczak if (!uc_pdata || strcmp(plat_name, uc_pdata->name)) 225af41e8dbSPrzemyslaw Marczak continue; 226af41e8dbSPrzemyslaw Marczak 227af41e8dbSPrzemyslaw Marczak return uclass_get_device_tail(dev, 0, devp); 228af41e8dbSPrzemyslaw Marczak } 229af41e8dbSPrzemyslaw Marczak 230422f04b6SSimon Glass debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret); 231af41e8dbSPrzemyslaw Marczak 232af41e8dbSPrzemyslaw Marczak return -ENODEV; 233af41e8dbSPrzemyslaw Marczak } 234af41e8dbSPrzemyslaw Marczak 2353b880757SPrzemyslaw Marczak int regulator_get_by_devname(const char *devname, struct udevice **devp) 236af41e8dbSPrzemyslaw Marczak { 237af41e8dbSPrzemyslaw Marczak return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp); 238af41e8dbSPrzemyslaw Marczak } 239af41e8dbSPrzemyslaw Marczak 2407c816e24SPrzemyslaw Marczak int device_get_supply_regulator(struct udevice *dev, const char *supply_name, 2417c816e24SPrzemyslaw Marczak struct udevice **devp) 2427c816e24SPrzemyslaw Marczak { 2437c816e24SPrzemyslaw Marczak return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 2447c816e24SPrzemyslaw Marczak supply_name, devp); 2457c816e24SPrzemyslaw Marczak } 2467c816e24SPrzemyslaw Marczak 2470ae9790cSJoseph Chen static int regulator_init_suspend(struct udevice *dev) 2480ae9790cSJoseph Chen { 2490ae9790cSJoseph Chen struct dm_regulator_uclass_platdata *uc_pdata; 2500ae9790cSJoseph Chen int ret; 2510ae9790cSJoseph Chen 2520ae9790cSJoseph Chen uc_pdata = dev_get_uclass_platdata(dev); 2530ae9790cSJoseph Chen 2540ae9790cSJoseph Chen ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on); 2550ae9790cSJoseph Chen if (!ret && uc_pdata->suspend_on) 2560ae9790cSJoseph Chen return regulator_set_suspend_value(dev, uc_pdata->suspend_uV); 2570ae9790cSJoseph Chen 2580ae9790cSJoseph Chen return 0; 2590ae9790cSJoseph Chen } 2600ae9790cSJoseph Chen 2613b55d30fSSimon Glass int regulator_autoset(struct udevice *dev) 262af41e8dbSPrzemyslaw Marczak { 2633b55d30fSSimon Glass struct dm_regulator_uclass_platdata *uc_pdata; 2643b55d30fSSimon Glass int ret = 0; 265af41e8dbSPrzemyslaw Marczak 2663b55d30fSSimon Glass uc_pdata = dev_get_uclass_platdata(dev); 267fbc6dab9SJoseph Chen 2686999767bSJoseph Chen if (uc_pdata->ignore) 2696999767bSJoseph Chen return ret; 2706999767bSJoseph Chen 271b29e2b63SJoseph Chen if (uc_pdata->ramp_delay != -ENODATA) 272b29e2b63SJoseph Chen regulator_set_ramp_delay(dev, uc_pdata->ramp_delay); 273b29e2b63SJoseph Chen 2743b55d30fSSimon Glass if (!uc_pdata->always_on && !uc_pdata->boot_on) 2753b55d30fSSimon Glass return -EMEDIUMTYPE; 276af41e8dbSPrzemyslaw Marczak 277*219e0f93SJoseph Chen /* 278*219e0f93SJoseph Chen * To compatible the old possible failure before adding this code, 279*219e0f93SJoseph Chen * ignore the result. 280*219e0f93SJoseph Chen */ 281*219e0f93SJoseph Chen if (uc_pdata->type == REGULATOR_TYPE_FIXED) { 282*219e0f93SJoseph Chen regulator_set_enable(dev, true); 283*219e0f93SJoseph Chen return 0; 284*219e0f93SJoseph Chen } 285*219e0f93SJoseph Chen 28632db71f8SJoseph Chen if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV) { 2873b55d30fSSimon Glass ret = regulator_set_value(dev, uc_pdata->min_uV); 28832db71f8SJoseph Chen } else { 28932db71f8SJoseph Chen if ((uc_pdata->type == REGULATOR_TYPE_BUCK) && 29032db71f8SJoseph Chen (uc_pdata->min_uV != -ENODATA) && 29145ec5783SJoseph Chen (uc_pdata->max_uV != -ENODATA) && 29245ec5783SJoseph Chen (uc_pdata->init_uV <= 0)) 29332db71f8SJoseph Chen printf("%s %d uV\n", 29432db71f8SJoseph Chen uc_pdata->name, regulator_get_value(dev)); 29532db71f8SJoseph Chen } 29632db71f8SJoseph Chen 297a538876eSJoseph Chen if (uc_pdata->init_uV > 0) { 2980e1b20c5SJoseph Chen ret = regulator_set_value(dev, uc_pdata->init_uV); 299a538876eSJoseph Chen if (!ret) 30071ebef54SJoseph Chen printf("%s init %d uV\n", 30154c0dba4SJoseph Chen uc_pdata->name, uc_pdata->init_uV); 302a538876eSJoseph Chen } 303a538876eSJoseph Chen 3043b55d30fSSimon Glass if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)) 3053b55d30fSSimon Glass ret = regulator_set_current(dev, uc_pdata->min_uA); 306af41e8dbSPrzemyslaw Marczak 307af41e8dbSPrzemyslaw Marczak if (!ret) 3083b55d30fSSimon Glass ret = regulator_set_enable(dev, true); 309af41e8dbSPrzemyslaw Marczak 310af41e8dbSPrzemyslaw Marczak return ret; 311af41e8dbSPrzemyslaw Marczak } 312af41e8dbSPrzemyslaw Marczak 3133b55d30fSSimon Glass static void regulator_show(struct udevice *dev, int ret) 314af41e8dbSPrzemyslaw Marczak { 315af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 3168152d3f6SJoseph Chen int uV = 0; 3173b55d30fSSimon Glass 3183b55d30fSSimon Glass uc_pdata = dev_get_uclass_platdata(dev); 3198152d3f6SJoseph Chen uV = regulator_get_value(dev); 3203b55d30fSSimon Glass 3218152d3f6SJoseph Chen printf("%25s@%15s: ", dev->name, uc_pdata->name); 3228152d3f6SJoseph Chen printf("%7duV <-> %7duV, set %7duV, %s", 3238152d3f6SJoseph Chen uc_pdata->min_uV, uc_pdata->max_uV, uV, 324f98160cbSJoseph Chen (uc_pdata->always_on || uc_pdata->boot_on) ? 3258152d3f6SJoseph Chen "enabling" : "disabled"); 3268152d3f6SJoseph Chen 3278152d3f6SJoseph Chen printf(" | supsend %7duV, %s", 3288152d3f6SJoseph Chen uc_pdata->suspend_uV, 3298152d3f6SJoseph Chen uc_pdata->suspend_on ? "enabling" : "disabled"); 3308152d3f6SJoseph Chen if (uc_pdata->init_uV != -ENODATA) 3318152d3f6SJoseph Chen printf(" ; init %7duV", uc_pdata->init_uV); 3328152d3f6SJoseph Chen 3333b55d30fSSimon Glass if (ret) 3347d577999SSimon Glass printf(" (ret: %d)", ret); 335f98160cbSJoseph Chen 3363b55d30fSSimon Glass printf("\n"); 3373b55d30fSSimon Glass } 3383b55d30fSSimon Glass 3393b55d30fSSimon Glass int regulator_autoset_by_name(const char *platname, struct udevice **devp) 3403b55d30fSSimon Glass { 341af41e8dbSPrzemyslaw Marczak struct udevice *dev; 342af41e8dbSPrzemyslaw Marczak int ret; 343af41e8dbSPrzemyslaw Marczak 3443b880757SPrzemyslaw Marczak ret = regulator_get_by_platname(platname, &dev); 345af41e8dbSPrzemyslaw Marczak if (devp) 346af41e8dbSPrzemyslaw Marczak *devp = dev; 3473b55d30fSSimon Glass if (ret) { 348422f04b6SSimon Glass debug("Can get the regulator: %s (err=%d)\n", platname, ret); 349af41e8dbSPrzemyslaw Marczak return ret; 350af41e8dbSPrzemyslaw Marczak } 351af41e8dbSPrzemyslaw Marczak 3523b55d30fSSimon Glass return regulator_autoset(dev); 3533b55d30fSSimon Glass } 3543b55d30fSSimon Glass 3553b880757SPrzemyslaw Marczak int regulator_list_autoset(const char *list_platname[], 356af41e8dbSPrzemyslaw Marczak struct udevice *list_devp[], 357af41e8dbSPrzemyslaw Marczak bool verbose) 358af41e8dbSPrzemyslaw Marczak { 359af41e8dbSPrzemyslaw Marczak struct udevice *dev; 3603b880757SPrzemyslaw Marczak int error = 0, i = 0, ret; 361af41e8dbSPrzemyslaw Marczak 3623b880757SPrzemyslaw Marczak while (list_platname[i]) { 3633b55d30fSSimon Glass ret = regulator_autoset_by_name(list_platname[i], &dev); 3643b55d30fSSimon Glass if (ret != -EMEDIUMTYPE && verbose) 3653b55d30fSSimon Glass regulator_show(dev, ret); 3663b880757SPrzemyslaw Marczak if (ret & !error) 3673b880757SPrzemyslaw Marczak error = ret; 368af41e8dbSPrzemyslaw Marczak 3693b880757SPrzemyslaw Marczak if (list_devp) 370af41e8dbSPrzemyslaw Marczak list_devp[i] = dev; 3713b880757SPrzemyslaw Marczak 3723b880757SPrzemyslaw Marczak i++; 373af41e8dbSPrzemyslaw Marczak } 374af41e8dbSPrzemyslaw Marczak 3753b880757SPrzemyslaw Marczak return error; 3763b880757SPrzemyslaw Marczak } 3773b880757SPrzemyslaw Marczak 3783b880757SPrzemyslaw Marczak static bool regulator_name_is_unique(struct udevice *check_dev, 3793b880757SPrzemyslaw Marczak const char *check_name) 3803b880757SPrzemyslaw Marczak { 3813b880757SPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 3823b880757SPrzemyslaw Marczak struct udevice *dev; 3833b880757SPrzemyslaw Marczak int check_len = strlen(check_name); 3843b880757SPrzemyslaw Marczak int ret; 3853b880757SPrzemyslaw Marczak int len; 3863b880757SPrzemyslaw Marczak 3873b880757SPrzemyslaw Marczak for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; 3883b880757SPrzemyslaw Marczak ret = uclass_find_next_device(&dev)) { 3893b880757SPrzemyslaw Marczak if (ret || dev == check_dev) 3903b880757SPrzemyslaw Marczak continue; 3913b880757SPrzemyslaw Marczak 3923b880757SPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 3933b880757SPrzemyslaw Marczak len = strlen(uc_pdata->name); 3943b880757SPrzemyslaw Marczak if (len != check_len) 3953b880757SPrzemyslaw Marczak continue; 3963b880757SPrzemyslaw Marczak 3973b880757SPrzemyslaw Marczak if (!strcmp(uc_pdata->name, check_name)) 3983b880757SPrzemyslaw Marczak return false; 3993b880757SPrzemyslaw Marczak } 4003b880757SPrzemyslaw Marczak 4013b880757SPrzemyslaw Marczak return true; 402af41e8dbSPrzemyslaw Marczak } 403af41e8dbSPrzemyslaw Marczak 404af41e8dbSPrzemyslaw Marczak static int regulator_post_bind(struct udevice *dev) 405af41e8dbSPrzemyslaw Marczak { 406af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 4073b880757SPrzemyslaw Marczak const char *property = "regulator-name"; 408af41e8dbSPrzemyslaw Marczak 409af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 410af41e8dbSPrzemyslaw Marczak 411af41e8dbSPrzemyslaw Marczak /* Regulator's mandatory constraint */ 412f15cd4f1SSimon Glass uc_pdata->name = dev_read_string(dev, property); 413af41e8dbSPrzemyslaw Marczak if (!uc_pdata->name) { 414f15cd4f1SSimon Glass debug("%s: dev '%s' has no property '%s'\n", 415f15cd4f1SSimon Glass __func__, dev->name, property); 416f15cd4f1SSimon Glass uc_pdata->name = dev_read_name(dev); 417cf260011SPeng Fan if (!uc_pdata->name) 4183b880757SPrzemyslaw Marczak return -EINVAL; 419af41e8dbSPrzemyslaw Marczak } 420af41e8dbSPrzemyslaw Marczak 4213b880757SPrzemyslaw Marczak if (regulator_name_is_unique(dev, uc_pdata->name)) 422af41e8dbSPrzemyslaw Marczak return 0; 4233b880757SPrzemyslaw Marczak 424f15cd4f1SSimon Glass debug("'%s' of dev: '%s', has nonunique value: '%s\n", 4253b880757SPrzemyslaw Marczak property, dev->name, uc_pdata->name); 4263b880757SPrzemyslaw Marczak 4273b880757SPrzemyslaw Marczak return -EINVAL; 428af41e8dbSPrzemyslaw Marczak } 429af41e8dbSPrzemyslaw Marczak 430af41e8dbSPrzemyslaw Marczak static int regulator_pre_probe(struct udevice *dev) 431af41e8dbSPrzemyslaw Marczak { 432af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 433fbc6dab9SJoseph Chen ofnode node; 434af41e8dbSPrzemyslaw Marczak 435af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 436af41e8dbSPrzemyslaw Marczak if (!uc_pdata) 437af41e8dbSPrzemyslaw Marczak return -ENXIO; 438af41e8dbSPrzemyslaw Marczak 439af41e8dbSPrzemyslaw Marczak /* Regulator's optional constraints */ 440f15cd4f1SSimon Glass uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt", 441f15cd4f1SSimon Glass -ENODATA); 442f15cd4f1SSimon Glass uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt", 443f15cd4f1SSimon Glass -ENODATA); 4440e1b20c5SJoseph Chen uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt", 4450e1b20c5SJoseph Chen -ENODATA); 446f15cd4f1SSimon Glass uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp", 447f15cd4f1SSimon Glass -ENODATA); 448f15cd4f1SSimon Glass uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp", 449f15cd4f1SSimon Glass -ENODATA); 450f15cd4f1SSimon Glass uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on"); 451f15cd4f1SSimon Glass uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on"); 4526999767bSJoseph Chen uc_pdata->ignore = dev_read_bool(dev, "regulator-loader-ignore"); 453b29e2b63SJoseph Chen uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay", 454b29e2b63SJoseph Chen -ENODATA); 455fbc6dab9SJoseph Chen node = dev_read_subnode(dev, "regulator-state-mem"); 456fbc6dab9SJoseph Chen if (ofnode_valid(node)) { 457fbc6dab9SJoseph Chen uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend"); 458fbc6dab9SJoseph Chen if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV)) 459fbc6dab9SJoseph Chen uc_pdata->suspend_uV = uc_pdata->max_uA; 460fbc6dab9SJoseph Chen } else { 461fbc6dab9SJoseph Chen uc_pdata->suspend_on = true; 462fbc6dab9SJoseph Chen uc_pdata->suspend_uV = uc_pdata->max_uA; 463fbc6dab9SJoseph Chen } 464fbc6dab9SJoseph Chen 4657837ceabSSimon Glass /* Those values are optional (-ENODATA if unset) */ 4667837ceabSSimon Glass if ((uc_pdata->min_uV != -ENODATA) && 4677837ceabSSimon Glass (uc_pdata->max_uV != -ENODATA) && 4687837ceabSSimon Glass (uc_pdata->min_uV == uc_pdata->max_uV)) 4697837ceabSSimon Glass uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV; 4707837ceabSSimon Glass 4717837ceabSSimon Glass /* Those values are optional (-ENODATA if unset) */ 4727837ceabSSimon Glass if ((uc_pdata->min_uA != -ENODATA) && 4737837ceabSSimon Glass (uc_pdata->max_uA != -ENODATA) && 4747837ceabSSimon Glass (uc_pdata->min_uA == uc_pdata->max_uA)) 4757837ceabSSimon Glass uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA; 4767837ceabSSimon Glass 4772f22a22fSJoseph Chen debug("dev.name=%s: min_uV=%d, max_uV=%d, boot-on=%d, always-on=%d, " 4782f22a22fSJoseph Chen "off-in-suspend=%d, suspend_volt=%d\n", 4792f22a22fSJoseph Chen dev->name, uc_pdata->min_uV, uc_pdata->max_uV, uc_pdata->boot_on, 4802f22a22fSJoseph Chen uc_pdata->always_on, !uc_pdata->suspend_on, uc_pdata->suspend_uV); 4812f22a22fSJoseph Chen 482af41e8dbSPrzemyslaw Marczak return 0; 483af41e8dbSPrzemyslaw Marczak } 484af41e8dbSPrzemyslaw Marczak 4850ae9790cSJoseph Chen int regulators_enable_state_mem(bool verbose) 4860ae9790cSJoseph Chen { 4870ae9790cSJoseph Chen struct udevice *dev; 4880ae9790cSJoseph Chen struct uclass *uc; 4890ae9790cSJoseph Chen int ret; 4900ae9790cSJoseph Chen 4910ae9790cSJoseph Chen ret = uclass_get(UCLASS_REGULATOR, &uc); 4920ae9790cSJoseph Chen if (ret) 4930ae9790cSJoseph Chen return ret; 4940ae9790cSJoseph Chen for (uclass_first_device(UCLASS_REGULATOR, &dev); 4950ae9790cSJoseph Chen dev; 4960ae9790cSJoseph Chen uclass_next_device(&dev)) { 4970ae9790cSJoseph Chen ret = regulator_init_suspend(dev); 4980ae9790cSJoseph Chen 4990ae9790cSJoseph Chen if (ret == -EMEDIUMTYPE) 5000ae9790cSJoseph Chen ret = 0; 5010ae9790cSJoseph Chen if (verbose) 5020ae9790cSJoseph Chen regulator_show(dev, ret); 5030ae9790cSJoseph Chen if (ret == -ENOSYS) 5040ae9790cSJoseph Chen ret = 0; 5050ae9790cSJoseph Chen } 5060ae9790cSJoseph Chen 5070ae9790cSJoseph Chen return ret; 5080ae9790cSJoseph Chen } 5090ae9790cSJoseph Chen 510083fc83aSSimon Glass int regulators_enable_boot_on(bool verbose) 511083fc83aSSimon Glass { 512083fc83aSSimon Glass struct udevice *dev; 513083fc83aSSimon Glass struct uclass *uc; 514083fc83aSSimon Glass int ret; 515083fc83aSSimon Glass 516083fc83aSSimon Glass ret = uclass_get(UCLASS_REGULATOR, &uc); 517083fc83aSSimon Glass if (ret) 518083fc83aSSimon Glass return ret; 519083fc83aSSimon Glass for (uclass_first_device(UCLASS_REGULATOR, &dev); 5203f603cbbSSimon Glass dev; 521083fc83aSSimon Glass uclass_next_device(&dev)) { 522083fc83aSSimon Glass ret = regulator_autoset(dev); 5230ae9790cSJoseph Chen 524f98160cbSJoseph Chen if (ret == -EMEDIUMTYPE) 525d08504d1SSimon Glass ret = 0; 526083fc83aSSimon Glass if (verbose) 527083fc83aSSimon Glass regulator_show(dev, ret); 528364809deSSimon Glass if (ret == -ENOSYS) 529364809deSSimon Glass ret = 0; 530083fc83aSSimon Glass } 531083fc83aSSimon Glass 532083fc83aSSimon Glass return ret; 533083fc83aSSimon Glass } 534083fc83aSSimon Glass 535af41e8dbSPrzemyslaw Marczak UCLASS_DRIVER(regulator) = { 536af41e8dbSPrzemyslaw Marczak .id = UCLASS_REGULATOR, 537af41e8dbSPrzemyslaw Marczak .name = "regulator", 538af41e8dbSPrzemyslaw Marczak .post_bind = regulator_post_bind, 539af41e8dbSPrzemyslaw Marczak .pre_probe = regulator_pre_probe, 540af41e8dbSPrzemyslaw Marczak .per_device_platdata_auto_alloc_size = 541af41e8dbSPrzemyslaw Marczak sizeof(struct dm_regulator_uclass_platdata), 542af41e8dbSPrzemyslaw Marczak }; 543