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 872f5d532fSKeerthy /* 882f5d532fSKeerthy * To be called with at most caution as there is no check 892f5d532fSKeerthy * before setting the actual voltage value. 902f5d532fSKeerthy */ 912f5d532fSKeerthy int regulator_set_value_force(struct udevice *dev, int uV) 922f5d532fSKeerthy { 932f5d532fSKeerthy const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 942f5d532fSKeerthy 952f5d532fSKeerthy if (!ops || !ops->set_value) 962f5d532fSKeerthy return -ENOSYS; 972f5d532fSKeerthy 982f5d532fSKeerthy return ops->set_value(dev, uV); 992f5d532fSKeerthy } 1002f5d532fSKeerthy 101af41e8dbSPrzemyslaw Marczak int regulator_get_current(struct udevice *dev) 102af41e8dbSPrzemyslaw Marczak { 103af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 104af41e8dbSPrzemyslaw Marczak 105af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_current) 106af41e8dbSPrzemyslaw Marczak return -ENOSYS; 107af41e8dbSPrzemyslaw Marczak 108af41e8dbSPrzemyslaw Marczak return ops->get_current(dev); 109af41e8dbSPrzemyslaw Marczak } 110af41e8dbSPrzemyslaw Marczak 111af41e8dbSPrzemyslaw Marczak int regulator_set_current(struct udevice *dev, int uA) 112af41e8dbSPrzemyslaw Marczak { 113af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 1145483456eSKeerthy struct dm_regulator_uclass_platdata *uc_pdata; 1155483456eSKeerthy 1165483456eSKeerthy uc_pdata = dev_get_uclass_platdata(dev); 1175483456eSKeerthy if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA) 1185483456eSKeerthy return -EINVAL; 1195483456eSKeerthy if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA) 1205483456eSKeerthy return -EINVAL; 121af41e8dbSPrzemyslaw Marczak 122af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_current) 123af41e8dbSPrzemyslaw Marczak return -ENOSYS; 124af41e8dbSPrzemyslaw Marczak 125af41e8dbSPrzemyslaw Marczak return ops->set_current(dev, uA); 126af41e8dbSPrzemyslaw Marczak } 127af41e8dbSPrzemyslaw Marczak 12806bdf600SKeerthy int regulator_get_enable(struct udevice *dev) 129af41e8dbSPrzemyslaw Marczak { 130af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 131af41e8dbSPrzemyslaw Marczak 132af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_enable) 133af41e8dbSPrzemyslaw Marczak return -ENOSYS; 134af41e8dbSPrzemyslaw Marczak 135af41e8dbSPrzemyslaw Marczak return ops->get_enable(dev); 136af41e8dbSPrzemyslaw Marczak } 137af41e8dbSPrzemyslaw Marczak 138af41e8dbSPrzemyslaw Marczak int regulator_set_enable(struct udevice *dev, bool enable) 139af41e8dbSPrzemyslaw Marczak { 140af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 141af41e8dbSPrzemyslaw Marczak 142af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_enable) 143af41e8dbSPrzemyslaw Marczak return -ENOSYS; 144af41e8dbSPrzemyslaw Marczak 145af41e8dbSPrzemyslaw Marczak return ops->set_enable(dev, enable); 146af41e8dbSPrzemyslaw Marczak } 147af41e8dbSPrzemyslaw Marczak 148fbc6dab9SJoseph Chen int regulator_set_suspend_enable(struct udevice *dev, bool enable) 149fbc6dab9SJoseph Chen { 150fbc6dab9SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 151fbc6dab9SJoseph Chen 152fbc6dab9SJoseph Chen if (!ops || !ops->set_suspend_enable) 153fbc6dab9SJoseph Chen return -ENOSYS; 154fbc6dab9SJoseph Chen 155fbc6dab9SJoseph Chen return ops->set_suspend_enable(dev, enable); 156fbc6dab9SJoseph Chen } 157fbc6dab9SJoseph Chen 158b29e2b63SJoseph Chen int regulator_set_ramp_delay(struct udevice *dev, u32 ramp_delay) 159b29e2b63SJoseph Chen { 160b29e2b63SJoseph Chen const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 161b29e2b63SJoseph Chen 162b29e2b63SJoseph Chen if (!ops || !ops->set_ramp_delay) 163b29e2b63SJoseph Chen return -ENOSYS; 164b29e2b63SJoseph Chen 165b29e2b63SJoseph Chen return ops->set_ramp_delay(dev, ramp_delay); 166b29e2b63SJoseph Chen } 167b29e2b63SJoseph Chen 168af41e8dbSPrzemyslaw Marczak int regulator_get_mode(struct udevice *dev) 169af41e8dbSPrzemyslaw Marczak { 170af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 171af41e8dbSPrzemyslaw Marczak 172af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_mode) 173af41e8dbSPrzemyslaw Marczak return -ENOSYS; 174af41e8dbSPrzemyslaw Marczak 175af41e8dbSPrzemyslaw Marczak return ops->get_mode(dev); 176af41e8dbSPrzemyslaw Marczak } 177af41e8dbSPrzemyslaw Marczak 178af41e8dbSPrzemyslaw Marczak int regulator_set_mode(struct udevice *dev, int mode) 179af41e8dbSPrzemyslaw Marczak { 180af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 181af41e8dbSPrzemyslaw Marczak 182af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_mode) 183af41e8dbSPrzemyslaw Marczak return -ENOSYS; 184af41e8dbSPrzemyslaw Marczak 185af41e8dbSPrzemyslaw Marczak return ops->set_mode(dev, mode); 186af41e8dbSPrzemyslaw Marczak } 187af41e8dbSPrzemyslaw Marczak 1883b880757SPrzemyslaw Marczak int regulator_get_by_platname(const char *plat_name, struct udevice **devp) 189af41e8dbSPrzemyslaw Marczak { 190af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 191af41e8dbSPrzemyslaw Marczak struct udevice *dev; 1923b880757SPrzemyslaw Marczak int ret; 193af41e8dbSPrzemyslaw Marczak 194af41e8dbSPrzemyslaw Marczak *devp = NULL; 195af41e8dbSPrzemyslaw Marczak 1963b880757SPrzemyslaw Marczak for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; 1973b880757SPrzemyslaw Marczak ret = uclass_find_next_device(&dev)) { 198422f04b6SSimon Glass if (ret) { 199422f04b6SSimon Glass debug("regulator %s, ret=%d\n", dev->name, ret); 2003b880757SPrzemyslaw Marczak continue; 201422f04b6SSimon Glass } 2023b880757SPrzemyslaw Marczak 203af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 204af41e8dbSPrzemyslaw Marczak if (!uc_pdata || strcmp(plat_name, uc_pdata->name)) 205af41e8dbSPrzemyslaw Marczak continue; 206af41e8dbSPrzemyslaw Marczak 207af41e8dbSPrzemyslaw Marczak return uclass_get_device_tail(dev, 0, devp); 208af41e8dbSPrzemyslaw Marczak } 209af41e8dbSPrzemyslaw Marczak 210422f04b6SSimon Glass debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret); 211af41e8dbSPrzemyslaw Marczak 212af41e8dbSPrzemyslaw Marczak return -ENODEV; 213af41e8dbSPrzemyslaw Marczak } 214af41e8dbSPrzemyslaw Marczak 2153b880757SPrzemyslaw Marczak int regulator_get_by_devname(const char *devname, struct udevice **devp) 216af41e8dbSPrzemyslaw Marczak { 217af41e8dbSPrzemyslaw Marczak return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp); 218af41e8dbSPrzemyslaw Marczak } 219af41e8dbSPrzemyslaw Marczak 2207c816e24SPrzemyslaw Marczak int device_get_supply_regulator(struct udevice *dev, const char *supply_name, 2217c816e24SPrzemyslaw Marczak struct udevice **devp) 2227c816e24SPrzemyslaw Marczak { 2237c816e24SPrzemyslaw Marczak return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 2247c816e24SPrzemyslaw Marczak supply_name, devp); 2257c816e24SPrzemyslaw Marczak } 2267c816e24SPrzemyslaw Marczak 2273b55d30fSSimon Glass int regulator_autoset(struct udevice *dev) 228af41e8dbSPrzemyslaw Marczak { 2293b55d30fSSimon Glass struct dm_regulator_uclass_platdata *uc_pdata; 2303b55d30fSSimon Glass int ret = 0; 231af41e8dbSPrzemyslaw Marczak 2323b55d30fSSimon Glass uc_pdata = dev_get_uclass_platdata(dev); 233fbc6dab9SJoseph Chen 234b29e2b63SJoseph Chen if (uc_pdata->ramp_delay != -ENODATA) 235b29e2b63SJoseph Chen regulator_set_ramp_delay(dev, uc_pdata->ramp_delay); 236b29e2b63SJoseph Chen 237*34483cf7SJoseph Chen /* 238*34483cf7SJoseph Chen * Suspend configure is not necessary and should not influence normal 239*34483cf7SJoseph Chen * configure, so that we set "ret=0" even failed here. 240*34483cf7SJoseph Chen */ 241fbc6dab9SJoseph Chen ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on); 242fbc6dab9SJoseph Chen if (!ret && uc_pdata->suspend_on) 243*34483cf7SJoseph Chen regulator_set_suspend_value(dev, uc_pdata->suspend_uV); 244*34483cf7SJoseph Chen else 245*34483cf7SJoseph Chen ret = 0; 246fbc6dab9SJoseph Chen 2473b55d30fSSimon Glass if (!uc_pdata->always_on && !uc_pdata->boot_on) 2483b55d30fSSimon Glass return -EMEDIUMTYPE; 249af41e8dbSPrzemyslaw Marczak 2503b55d30fSSimon Glass if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV) 2513b55d30fSSimon Glass ret = regulator_set_value(dev, uc_pdata->min_uV); 2520e1b20c5SJoseph Chen if (uc_pdata->init_uV > 0) 2530e1b20c5SJoseph Chen ret = regulator_set_value(dev, uc_pdata->init_uV); 2543b55d30fSSimon Glass if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)) 2553b55d30fSSimon Glass ret = regulator_set_current(dev, uc_pdata->min_uA); 256af41e8dbSPrzemyslaw Marczak 257af41e8dbSPrzemyslaw Marczak if (!ret) 2583b55d30fSSimon Glass ret = regulator_set_enable(dev, true); 259af41e8dbSPrzemyslaw Marczak 260af41e8dbSPrzemyslaw Marczak return ret; 261af41e8dbSPrzemyslaw Marczak } 262af41e8dbSPrzemyslaw Marczak 2633b55d30fSSimon Glass static void regulator_show(struct udevice *dev, int ret) 264af41e8dbSPrzemyslaw Marczak { 265af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 2663b55d30fSSimon Glass 2673b55d30fSSimon Glass uc_pdata = dev_get_uclass_platdata(dev); 2683b55d30fSSimon Glass 2693b55d30fSSimon Glass printf("%s@%s: ", dev->name, uc_pdata->name); 2703b55d30fSSimon Glass if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV) 2713b55d30fSSimon Glass printf("set %d uV", uc_pdata->min_uV); 2723b55d30fSSimon Glass if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA) 2733b55d30fSSimon Glass printf("; set %d uA", uc_pdata->min_uA); 2743b55d30fSSimon Glass printf("; enabling"); 2753b55d30fSSimon Glass if (ret) 2767d577999SSimon Glass printf(" (ret: %d)", ret); 2773b55d30fSSimon Glass printf("\n"); 2783b55d30fSSimon Glass } 2793b55d30fSSimon Glass 2803b55d30fSSimon Glass int regulator_autoset_by_name(const char *platname, struct udevice **devp) 2813b55d30fSSimon Glass { 282af41e8dbSPrzemyslaw Marczak struct udevice *dev; 283af41e8dbSPrzemyslaw Marczak int ret; 284af41e8dbSPrzemyslaw Marczak 2853b880757SPrzemyslaw Marczak ret = regulator_get_by_platname(platname, &dev); 286af41e8dbSPrzemyslaw Marczak if (devp) 287af41e8dbSPrzemyslaw Marczak *devp = dev; 2883b55d30fSSimon Glass if (ret) { 289422f04b6SSimon Glass debug("Can get the regulator: %s (err=%d)\n", platname, ret); 290af41e8dbSPrzemyslaw Marczak return ret; 291af41e8dbSPrzemyslaw Marczak } 292af41e8dbSPrzemyslaw Marczak 2933b55d30fSSimon Glass return regulator_autoset(dev); 2943b55d30fSSimon Glass } 2953b55d30fSSimon Glass 2963b880757SPrzemyslaw Marczak int regulator_list_autoset(const char *list_platname[], 297af41e8dbSPrzemyslaw Marczak struct udevice *list_devp[], 298af41e8dbSPrzemyslaw Marczak bool verbose) 299af41e8dbSPrzemyslaw Marczak { 300af41e8dbSPrzemyslaw Marczak struct udevice *dev; 3013b880757SPrzemyslaw Marczak int error = 0, i = 0, ret; 302af41e8dbSPrzemyslaw Marczak 3033b880757SPrzemyslaw Marczak while (list_platname[i]) { 3043b55d30fSSimon Glass ret = regulator_autoset_by_name(list_platname[i], &dev); 3053b55d30fSSimon Glass if (ret != -EMEDIUMTYPE && verbose) 3063b55d30fSSimon Glass regulator_show(dev, ret); 3073b880757SPrzemyslaw Marczak if (ret & !error) 3083b880757SPrzemyslaw Marczak error = ret; 309af41e8dbSPrzemyslaw Marczak 3103b880757SPrzemyslaw Marczak if (list_devp) 311af41e8dbSPrzemyslaw Marczak list_devp[i] = dev; 3123b880757SPrzemyslaw Marczak 3133b880757SPrzemyslaw Marczak i++; 314af41e8dbSPrzemyslaw Marczak } 315af41e8dbSPrzemyslaw Marczak 3163b880757SPrzemyslaw Marczak return error; 3173b880757SPrzemyslaw Marczak } 3183b880757SPrzemyslaw Marczak 3193b880757SPrzemyslaw Marczak static bool regulator_name_is_unique(struct udevice *check_dev, 3203b880757SPrzemyslaw Marczak const char *check_name) 3213b880757SPrzemyslaw Marczak { 3223b880757SPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 3233b880757SPrzemyslaw Marczak struct udevice *dev; 3243b880757SPrzemyslaw Marczak int check_len = strlen(check_name); 3253b880757SPrzemyslaw Marczak int ret; 3263b880757SPrzemyslaw Marczak int len; 3273b880757SPrzemyslaw Marczak 3283b880757SPrzemyslaw Marczak for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; 3293b880757SPrzemyslaw Marczak ret = uclass_find_next_device(&dev)) { 3303b880757SPrzemyslaw Marczak if (ret || dev == check_dev) 3313b880757SPrzemyslaw Marczak continue; 3323b880757SPrzemyslaw Marczak 3333b880757SPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 3343b880757SPrzemyslaw Marczak len = strlen(uc_pdata->name); 3353b880757SPrzemyslaw Marczak if (len != check_len) 3363b880757SPrzemyslaw Marczak continue; 3373b880757SPrzemyslaw Marczak 3383b880757SPrzemyslaw Marczak if (!strcmp(uc_pdata->name, check_name)) 3393b880757SPrzemyslaw Marczak return false; 3403b880757SPrzemyslaw Marczak } 3413b880757SPrzemyslaw Marczak 3423b880757SPrzemyslaw Marczak return true; 343af41e8dbSPrzemyslaw Marczak } 344af41e8dbSPrzemyslaw Marczak 345af41e8dbSPrzemyslaw Marczak static int regulator_post_bind(struct udevice *dev) 346af41e8dbSPrzemyslaw Marczak { 347af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 3483b880757SPrzemyslaw Marczak const char *property = "regulator-name"; 349af41e8dbSPrzemyslaw Marczak 350af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 351af41e8dbSPrzemyslaw Marczak 352af41e8dbSPrzemyslaw Marczak /* Regulator's mandatory constraint */ 353f15cd4f1SSimon Glass uc_pdata->name = dev_read_string(dev, property); 354af41e8dbSPrzemyslaw Marczak if (!uc_pdata->name) { 355f15cd4f1SSimon Glass debug("%s: dev '%s' has no property '%s'\n", 356f15cd4f1SSimon Glass __func__, dev->name, property); 357f15cd4f1SSimon Glass uc_pdata->name = dev_read_name(dev); 358cf260011SPeng Fan if (!uc_pdata->name) 3593b880757SPrzemyslaw Marczak return -EINVAL; 360af41e8dbSPrzemyslaw Marczak } 361af41e8dbSPrzemyslaw Marczak 3623b880757SPrzemyslaw Marczak if (regulator_name_is_unique(dev, uc_pdata->name)) 363af41e8dbSPrzemyslaw Marczak return 0; 3643b880757SPrzemyslaw Marczak 365f15cd4f1SSimon Glass debug("'%s' of dev: '%s', has nonunique value: '%s\n", 3663b880757SPrzemyslaw Marczak property, dev->name, uc_pdata->name); 3673b880757SPrzemyslaw Marczak 3683b880757SPrzemyslaw Marczak return -EINVAL; 369af41e8dbSPrzemyslaw Marczak } 370af41e8dbSPrzemyslaw Marczak 371af41e8dbSPrzemyslaw Marczak static int regulator_pre_probe(struct udevice *dev) 372af41e8dbSPrzemyslaw Marczak { 373af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 374fbc6dab9SJoseph Chen ofnode node; 375af41e8dbSPrzemyslaw Marczak 376af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 377af41e8dbSPrzemyslaw Marczak if (!uc_pdata) 378af41e8dbSPrzemyslaw Marczak return -ENXIO; 379af41e8dbSPrzemyslaw Marczak 380af41e8dbSPrzemyslaw Marczak /* Regulator's optional constraints */ 381f15cd4f1SSimon Glass uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt", 382f15cd4f1SSimon Glass -ENODATA); 383f15cd4f1SSimon Glass uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt", 384f15cd4f1SSimon Glass -ENODATA); 3850e1b20c5SJoseph Chen uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt", 3860e1b20c5SJoseph Chen -ENODATA); 387f15cd4f1SSimon Glass uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp", 388f15cd4f1SSimon Glass -ENODATA); 389f15cd4f1SSimon Glass uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp", 390f15cd4f1SSimon Glass -ENODATA); 391f15cd4f1SSimon Glass uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on"); 392f15cd4f1SSimon Glass uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on"); 393b29e2b63SJoseph Chen uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay", 394b29e2b63SJoseph Chen -ENODATA); 395fbc6dab9SJoseph Chen node = dev_read_subnode(dev, "regulator-state-mem"); 396fbc6dab9SJoseph Chen if (ofnode_valid(node)) { 397fbc6dab9SJoseph Chen uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend"); 398fbc6dab9SJoseph Chen if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV)) 399fbc6dab9SJoseph Chen uc_pdata->suspend_uV = uc_pdata->max_uA; 400fbc6dab9SJoseph Chen } else { 401fbc6dab9SJoseph Chen uc_pdata->suspend_on = true; 402fbc6dab9SJoseph Chen uc_pdata->suspend_uV = uc_pdata->max_uA; 403fbc6dab9SJoseph Chen } 404fbc6dab9SJoseph Chen 4057837ceabSSimon Glass /* Those values are optional (-ENODATA if unset) */ 4067837ceabSSimon Glass if ((uc_pdata->min_uV != -ENODATA) && 4077837ceabSSimon Glass (uc_pdata->max_uV != -ENODATA) && 4087837ceabSSimon Glass (uc_pdata->min_uV == uc_pdata->max_uV)) 4097837ceabSSimon Glass uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV; 4107837ceabSSimon Glass 4117837ceabSSimon Glass /* Those values are optional (-ENODATA if unset) */ 4127837ceabSSimon Glass if ((uc_pdata->min_uA != -ENODATA) && 4137837ceabSSimon Glass (uc_pdata->max_uA != -ENODATA) && 4147837ceabSSimon Glass (uc_pdata->min_uA == uc_pdata->max_uA)) 4157837ceabSSimon Glass uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA; 4167837ceabSSimon Glass 4172f22a22fSJoseph Chen debug("dev.name=%s: min_uV=%d, max_uV=%d, boot-on=%d, always-on=%d, " 4182f22a22fSJoseph Chen "off-in-suspend=%d, suspend_volt=%d\n", 4192f22a22fSJoseph Chen dev->name, uc_pdata->min_uV, uc_pdata->max_uV, uc_pdata->boot_on, 4202f22a22fSJoseph Chen uc_pdata->always_on, !uc_pdata->suspend_on, uc_pdata->suspend_uV); 4212f22a22fSJoseph Chen 422af41e8dbSPrzemyslaw Marczak return 0; 423af41e8dbSPrzemyslaw Marczak } 424af41e8dbSPrzemyslaw Marczak 425083fc83aSSimon Glass int regulators_enable_boot_on(bool verbose) 426083fc83aSSimon Glass { 427083fc83aSSimon Glass struct udevice *dev; 428083fc83aSSimon Glass struct uclass *uc; 429083fc83aSSimon Glass int ret; 430083fc83aSSimon Glass 431083fc83aSSimon Glass ret = uclass_get(UCLASS_REGULATOR, &uc); 432083fc83aSSimon Glass if (ret) 433083fc83aSSimon Glass return ret; 434083fc83aSSimon Glass for (uclass_first_device(UCLASS_REGULATOR, &dev); 4353f603cbbSSimon Glass dev; 436083fc83aSSimon Glass uclass_next_device(&dev)) { 437083fc83aSSimon Glass ret = regulator_autoset(dev); 438d08504d1SSimon Glass if (ret == -EMEDIUMTYPE) { 439d08504d1SSimon Glass ret = 0; 440083fc83aSSimon Glass continue; 441d08504d1SSimon Glass } 442083fc83aSSimon Glass if (verbose) 443083fc83aSSimon Glass regulator_show(dev, ret); 444364809deSSimon Glass if (ret == -ENOSYS) 445364809deSSimon Glass ret = 0; 446083fc83aSSimon Glass } 447083fc83aSSimon Glass 448083fc83aSSimon Glass return ret; 449083fc83aSSimon Glass } 450083fc83aSSimon Glass 451af41e8dbSPrzemyslaw Marczak UCLASS_DRIVER(regulator) = { 452af41e8dbSPrzemyslaw Marczak .id = UCLASS_REGULATOR, 453af41e8dbSPrzemyslaw Marczak .name = "regulator", 454af41e8dbSPrzemyslaw Marczak .post_bind = regulator_post_bind, 455af41e8dbSPrzemyslaw Marczak .pre_probe = regulator_pre_probe, 456af41e8dbSPrzemyslaw Marczak .per_device_platdata_auto_alloc_size = 457af41e8dbSPrzemyslaw Marczak sizeof(struct dm_regulator_uclass_platdata), 458af41e8dbSPrzemyslaw Marczak }; 459