1*af41e8dbSPrzemyslaw Marczak /* 2*af41e8dbSPrzemyslaw Marczak * Copyright (C) 2014-2015 Samsung Electronics 3*af41e8dbSPrzemyslaw Marczak * Przemyslaw Marczak <p.marczak@samsung.com> 4*af41e8dbSPrzemyslaw Marczak * 5*af41e8dbSPrzemyslaw Marczak * SPDX-License-Identifier: GPL-2.0+ 6*af41e8dbSPrzemyslaw Marczak */ 7*af41e8dbSPrzemyslaw Marczak #include <common.h> 8*af41e8dbSPrzemyslaw Marczak #include <fdtdec.h> 9*af41e8dbSPrzemyslaw Marczak #include <errno.h> 10*af41e8dbSPrzemyslaw Marczak #include <dm.h> 11*af41e8dbSPrzemyslaw Marczak #include <dm/uclass-internal.h> 12*af41e8dbSPrzemyslaw Marczak #include <power/pmic.h> 13*af41e8dbSPrzemyslaw Marczak #include <power/regulator.h> 14*af41e8dbSPrzemyslaw Marczak 15*af41e8dbSPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR; 16*af41e8dbSPrzemyslaw Marczak 17*af41e8dbSPrzemyslaw Marczak int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep) 18*af41e8dbSPrzemyslaw Marczak { 19*af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 20*af41e8dbSPrzemyslaw Marczak 21*af41e8dbSPrzemyslaw Marczak *modep = NULL; 22*af41e8dbSPrzemyslaw Marczak 23*af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 24*af41e8dbSPrzemyslaw Marczak if (!uc_pdata) 25*af41e8dbSPrzemyslaw Marczak return -ENXIO; 26*af41e8dbSPrzemyslaw Marczak 27*af41e8dbSPrzemyslaw Marczak *modep = uc_pdata->mode; 28*af41e8dbSPrzemyslaw Marczak return uc_pdata->mode_count; 29*af41e8dbSPrzemyslaw Marczak } 30*af41e8dbSPrzemyslaw Marczak 31*af41e8dbSPrzemyslaw Marczak int regulator_get_value(struct udevice *dev) 32*af41e8dbSPrzemyslaw Marczak { 33*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 34*af41e8dbSPrzemyslaw Marczak 35*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_value) 36*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 37*af41e8dbSPrzemyslaw Marczak 38*af41e8dbSPrzemyslaw Marczak return ops->get_value(dev); 39*af41e8dbSPrzemyslaw Marczak } 40*af41e8dbSPrzemyslaw Marczak 41*af41e8dbSPrzemyslaw Marczak int regulator_set_value(struct udevice *dev, int uV) 42*af41e8dbSPrzemyslaw Marczak { 43*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 44*af41e8dbSPrzemyslaw Marczak 45*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_value) 46*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 47*af41e8dbSPrzemyslaw Marczak 48*af41e8dbSPrzemyslaw Marczak return ops->set_value(dev, uV); 49*af41e8dbSPrzemyslaw Marczak } 50*af41e8dbSPrzemyslaw Marczak 51*af41e8dbSPrzemyslaw Marczak int regulator_get_current(struct udevice *dev) 52*af41e8dbSPrzemyslaw Marczak { 53*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 54*af41e8dbSPrzemyslaw Marczak 55*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_current) 56*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 57*af41e8dbSPrzemyslaw Marczak 58*af41e8dbSPrzemyslaw Marczak return ops->get_current(dev); 59*af41e8dbSPrzemyslaw Marczak } 60*af41e8dbSPrzemyslaw Marczak 61*af41e8dbSPrzemyslaw Marczak int regulator_set_current(struct udevice *dev, int uA) 62*af41e8dbSPrzemyslaw Marczak { 63*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 64*af41e8dbSPrzemyslaw Marczak 65*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_current) 66*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 67*af41e8dbSPrzemyslaw Marczak 68*af41e8dbSPrzemyslaw Marczak return ops->set_current(dev, uA); 69*af41e8dbSPrzemyslaw Marczak } 70*af41e8dbSPrzemyslaw Marczak 71*af41e8dbSPrzemyslaw Marczak bool regulator_get_enable(struct udevice *dev) 72*af41e8dbSPrzemyslaw Marczak { 73*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 74*af41e8dbSPrzemyslaw Marczak 75*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_enable) 76*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 77*af41e8dbSPrzemyslaw Marczak 78*af41e8dbSPrzemyslaw Marczak return ops->get_enable(dev); 79*af41e8dbSPrzemyslaw Marczak } 80*af41e8dbSPrzemyslaw Marczak 81*af41e8dbSPrzemyslaw Marczak int regulator_set_enable(struct udevice *dev, bool enable) 82*af41e8dbSPrzemyslaw Marczak { 83*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 84*af41e8dbSPrzemyslaw Marczak 85*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_enable) 86*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 87*af41e8dbSPrzemyslaw Marczak 88*af41e8dbSPrzemyslaw Marczak return ops->set_enable(dev, enable); 89*af41e8dbSPrzemyslaw Marczak } 90*af41e8dbSPrzemyslaw Marczak 91*af41e8dbSPrzemyslaw Marczak int regulator_get_mode(struct udevice *dev) 92*af41e8dbSPrzemyslaw Marczak { 93*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 94*af41e8dbSPrzemyslaw Marczak 95*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->get_mode) 96*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 97*af41e8dbSPrzemyslaw Marczak 98*af41e8dbSPrzemyslaw Marczak return ops->get_mode(dev); 99*af41e8dbSPrzemyslaw Marczak } 100*af41e8dbSPrzemyslaw Marczak 101*af41e8dbSPrzemyslaw Marczak int regulator_set_mode(struct udevice *dev, int mode) 102*af41e8dbSPrzemyslaw Marczak { 103*af41e8dbSPrzemyslaw Marczak const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); 104*af41e8dbSPrzemyslaw Marczak 105*af41e8dbSPrzemyslaw Marczak if (!ops || !ops->set_mode) 106*af41e8dbSPrzemyslaw Marczak return -ENOSYS; 107*af41e8dbSPrzemyslaw Marczak 108*af41e8dbSPrzemyslaw Marczak return ops->set_mode(dev, mode); 109*af41e8dbSPrzemyslaw Marczak } 110*af41e8dbSPrzemyslaw Marczak 111*af41e8dbSPrzemyslaw Marczak int regulator_by_platname(const char *plat_name, struct udevice **devp) 112*af41e8dbSPrzemyslaw Marczak { 113*af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 114*af41e8dbSPrzemyslaw Marczak struct udevice *dev; 115*af41e8dbSPrzemyslaw Marczak 116*af41e8dbSPrzemyslaw Marczak *devp = NULL; 117*af41e8dbSPrzemyslaw Marczak 118*af41e8dbSPrzemyslaw Marczak for (uclass_find_first_device(UCLASS_REGULATOR, &dev); 119*af41e8dbSPrzemyslaw Marczak dev; 120*af41e8dbSPrzemyslaw Marczak uclass_find_next_device(&dev)) { 121*af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 122*af41e8dbSPrzemyslaw Marczak if (!uc_pdata || strcmp(plat_name, uc_pdata->name)) 123*af41e8dbSPrzemyslaw Marczak continue; 124*af41e8dbSPrzemyslaw Marczak 125*af41e8dbSPrzemyslaw Marczak return uclass_get_device_tail(dev, 0, devp); 126*af41e8dbSPrzemyslaw Marczak } 127*af41e8dbSPrzemyslaw Marczak 128*af41e8dbSPrzemyslaw Marczak debug("%s: can't find: %s\n", __func__, plat_name); 129*af41e8dbSPrzemyslaw Marczak 130*af41e8dbSPrzemyslaw Marczak return -ENODEV; 131*af41e8dbSPrzemyslaw Marczak } 132*af41e8dbSPrzemyslaw Marczak 133*af41e8dbSPrzemyslaw Marczak int regulator_by_devname(const char *devname, struct udevice **devp) 134*af41e8dbSPrzemyslaw Marczak { 135*af41e8dbSPrzemyslaw Marczak return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp); 136*af41e8dbSPrzemyslaw Marczak } 137*af41e8dbSPrzemyslaw Marczak 138*af41e8dbSPrzemyslaw Marczak static int setting_failed(int ret, bool verbose, const char *fmt, ...) 139*af41e8dbSPrzemyslaw Marczak { 140*af41e8dbSPrzemyslaw Marczak va_list args; 141*af41e8dbSPrzemyslaw Marczak char buf[64]; 142*af41e8dbSPrzemyslaw Marczak 143*af41e8dbSPrzemyslaw Marczak if (verbose == false) 144*af41e8dbSPrzemyslaw Marczak return ret; 145*af41e8dbSPrzemyslaw Marczak 146*af41e8dbSPrzemyslaw Marczak va_start(args, fmt); 147*af41e8dbSPrzemyslaw Marczak vscnprintf(buf, sizeof(buf), fmt, args); 148*af41e8dbSPrzemyslaw Marczak va_end(args); 149*af41e8dbSPrzemyslaw Marczak 150*af41e8dbSPrzemyslaw Marczak printf(buf); 151*af41e8dbSPrzemyslaw Marczak 152*af41e8dbSPrzemyslaw Marczak if (!ret) 153*af41e8dbSPrzemyslaw Marczak return 0; 154*af41e8dbSPrzemyslaw Marczak 155*af41e8dbSPrzemyslaw Marczak printf(" (ret: %d)", ret); 156*af41e8dbSPrzemyslaw Marczak 157*af41e8dbSPrzemyslaw Marczak return ret; 158*af41e8dbSPrzemyslaw Marczak } 159*af41e8dbSPrzemyslaw Marczak 160*af41e8dbSPrzemyslaw Marczak int regulator_by_platname_autoset_and_enable(const char *platname, 161*af41e8dbSPrzemyslaw Marczak struct udevice **devp, 162*af41e8dbSPrzemyslaw Marczak bool verbose) 163*af41e8dbSPrzemyslaw Marczak { 164*af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 165*af41e8dbSPrzemyslaw Marczak struct udevice *dev; 166*af41e8dbSPrzemyslaw Marczak bool v = verbose; 167*af41e8dbSPrzemyslaw Marczak int ret; 168*af41e8dbSPrzemyslaw Marczak 169*af41e8dbSPrzemyslaw Marczak if (devp) 170*af41e8dbSPrzemyslaw Marczak *devp = NULL; 171*af41e8dbSPrzemyslaw Marczak 172*af41e8dbSPrzemyslaw Marczak ret = regulator_by_platname(platname, &dev); 173*af41e8dbSPrzemyslaw Marczak if (ret) { 174*af41e8dbSPrzemyslaw Marczak error("Can get the regulator: %s!", platname); 175*af41e8dbSPrzemyslaw Marczak return ret; 176*af41e8dbSPrzemyslaw Marczak } 177*af41e8dbSPrzemyslaw Marczak 178*af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 179*af41e8dbSPrzemyslaw Marczak if (!uc_pdata) { 180*af41e8dbSPrzemyslaw Marczak error("Can get the regulator %s uclass platdata!", platname); 181*af41e8dbSPrzemyslaw Marczak return -ENXIO; 182*af41e8dbSPrzemyslaw Marczak } 183*af41e8dbSPrzemyslaw Marczak 184*af41e8dbSPrzemyslaw Marczak if (v) 185*af41e8dbSPrzemyslaw Marczak printf("%s@%s: ", dev->name, uc_pdata->name); 186*af41e8dbSPrzemyslaw Marczak 187*af41e8dbSPrzemyslaw Marczak /* Those values are optional (-ENODATA if unset) */ 188*af41e8dbSPrzemyslaw Marczak if ((uc_pdata->min_uV != -ENODATA) && 189*af41e8dbSPrzemyslaw Marczak (uc_pdata->max_uV != -ENODATA) && 190*af41e8dbSPrzemyslaw Marczak (uc_pdata->min_uV == uc_pdata->max_uV)) { 191*af41e8dbSPrzemyslaw Marczak ret = regulator_set_value(dev, uc_pdata->min_uV); 192*af41e8dbSPrzemyslaw Marczak if (setting_failed(ret, v, "set %d uV", uc_pdata->min_uV)) 193*af41e8dbSPrzemyslaw Marczak goto exit; 194*af41e8dbSPrzemyslaw Marczak } 195*af41e8dbSPrzemyslaw Marczak 196*af41e8dbSPrzemyslaw Marczak /* Those values are optional (-ENODATA if unset) */ 197*af41e8dbSPrzemyslaw Marczak if ((uc_pdata->min_uA != -ENODATA) && 198*af41e8dbSPrzemyslaw Marczak (uc_pdata->max_uA != -ENODATA) && 199*af41e8dbSPrzemyslaw Marczak (uc_pdata->min_uA == uc_pdata->max_uA)) { 200*af41e8dbSPrzemyslaw Marczak ret = regulator_set_current(dev, uc_pdata->min_uA); 201*af41e8dbSPrzemyslaw Marczak if (setting_failed(ret, v, "; set %d uA", uc_pdata->min_uA)) 202*af41e8dbSPrzemyslaw Marczak goto exit; 203*af41e8dbSPrzemyslaw Marczak } 204*af41e8dbSPrzemyslaw Marczak 205*af41e8dbSPrzemyslaw Marczak if (!uc_pdata->always_on && !uc_pdata->boot_on) 206*af41e8dbSPrzemyslaw Marczak goto retdev; 207*af41e8dbSPrzemyslaw Marczak 208*af41e8dbSPrzemyslaw Marczak ret = regulator_set_enable(dev, true); 209*af41e8dbSPrzemyslaw Marczak if (setting_failed(ret, v, "; enabling", uc_pdata->min_uA)) 210*af41e8dbSPrzemyslaw Marczak goto exit; 211*af41e8dbSPrzemyslaw Marczak 212*af41e8dbSPrzemyslaw Marczak retdev: 213*af41e8dbSPrzemyslaw Marczak if (devp) 214*af41e8dbSPrzemyslaw Marczak *devp = dev; 215*af41e8dbSPrzemyslaw Marczak exit: 216*af41e8dbSPrzemyslaw Marczak if (v) 217*af41e8dbSPrzemyslaw Marczak printf("\n"); 218*af41e8dbSPrzemyslaw Marczak return ret; 219*af41e8dbSPrzemyslaw Marczak } 220*af41e8dbSPrzemyslaw Marczak 221*af41e8dbSPrzemyslaw Marczak int regulator_by_platname_list_autoset_and_enable(const char *list_platname[], 222*af41e8dbSPrzemyslaw Marczak int list_entries, 223*af41e8dbSPrzemyslaw Marczak struct udevice *list_devp[], 224*af41e8dbSPrzemyslaw Marczak bool verbose) 225*af41e8dbSPrzemyslaw Marczak { 226*af41e8dbSPrzemyslaw Marczak struct udevice *dev; 227*af41e8dbSPrzemyslaw Marczak int i, ret, success = 0; 228*af41e8dbSPrzemyslaw Marczak 229*af41e8dbSPrzemyslaw Marczak for (i = 0; i < list_entries; i++) { 230*af41e8dbSPrzemyslaw Marczak ret = regulator_autoset(list_platname[i], &dev, verbose); 231*af41e8dbSPrzemyslaw Marczak if (!ret) 232*af41e8dbSPrzemyslaw Marczak success++; 233*af41e8dbSPrzemyslaw Marczak 234*af41e8dbSPrzemyslaw Marczak if (!list_devp) 235*af41e8dbSPrzemyslaw Marczak continue; 236*af41e8dbSPrzemyslaw Marczak 237*af41e8dbSPrzemyslaw Marczak if (ret) 238*af41e8dbSPrzemyslaw Marczak list_devp[i] = NULL; 239*af41e8dbSPrzemyslaw Marczak else 240*af41e8dbSPrzemyslaw Marczak list_devp[i] = dev; 241*af41e8dbSPrzemyslaw Marczak } 242*af41e8dbSPrzemyslaw Marczak 243*af41e8dbSPrzemyslaw Marczak return (success != list_entries); 244*af41e8dbSPrzemyslaw Marczak } 245*af41e8dbSPrzemyslaw Marczak 246*af41e8dbSPrzemyslaw Marczak static int regulator_post_bind(struct udevice *dev) 247*af41e8dbSPrzemyslaw Marczak { 248*af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 249*af41e8dbSPrzemyslaw Marczak int offset = dev->of_offset; 250*af41e8dbSPrzemyslaw Marczak const void *blob = gd->fdt_blob; 251*af41e8dbSPrzemyslaw Marczak 252*af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 253*af41e8dbSPrzemyslaw Marczak if (!uc_pdata) 254*af41e8dbSPrzemyslaw Marczak return -ENXIO; 255*af41e8dbSPrzemyslaw Marczak 256*af41e8dbSPrzemyslaw Marczak /* Regulator's mandatory constraint */ 257*af41e8dbSPrzemyslaw Marczak uc_pdata->name = fdt_getprop(blob, offset, "regulator-name", NULL); 258*af41e8dbSPrzemyslaw Marczak if (!uc_pdata->name) { 259*af41e8dbSPrzemyslaw Marczak debug("%s: dev: %s has no property 'regulator-name'\n", 260*af41e8dbSPrzemyslaw Marczak __func__, dev->name); 261*af41e8dbSPrzemyslaw Marczak return -ENXIO; 262*af41e8dbSPrzemyslaw Marczak } 263*af41e8dbSPrzemyslaw Marczak 264*af41e8dbSPrzemyslaw Marczak return 0; 265*af41e8dbSPrzemyslaw Marczak } 266*af41e8dbSPrzemyslaw Marczak 267*af41e8dbSPrzemyslaw Marczak static int regulator_pre_probe(struct udevice *dev) 268*af41e8dbSPrzemyslaw Marczak { 269*af41e8dbSPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 270*af41e8dbSPrzemyslaw Marczak int offset = dev->of_offset; 271*af41e8dbSPrzemyslaw Marczak 272*af41e8dbSPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 273*af41e8dbSPrzemyslaw Marczak if (!uc_pdata) 274*af41e8dbSPrzemyslaw Marczak return -ENXIO; 275*af41e8dbSPrzemyslaw Marczak 276*af41e8dbSPrzemyslaw Marczak /* Regulator's optional constraints */ 277*af41e8dbSPrzemyslaw Marczak uc_pdata->min_uV = fdtdec_get_int(gd->fdt_blob, offset, 278*af41e8dbSPrzemyslaw Marczak "regulator-min-microvolt", -ENODATA); 279*af41e8dbSPrzemyslaw Marczak uc_pdata->max_uV = fdtdec_get_int(gd->fdt_blob, offset, 280*af41e8dbSPrzemyslaw Marczak "regulator-max-microvolt", -ENODATA); 281*af41e8dbSPrzemyslaw Marczak uc_pdata->min_uA = fdtdec_get_int(gd->fdt_blob, offset, 282*af41e8dbSPrzemyslaw Marczak "regulator-min-microamp", -ENODATA); 283*af41e8dbSPrzemyslaw Marczak uc_pdata->max_uA = fdtdec_get_int(gd->fdt_blob, offset, 284*af41e8dbSPrzemyslaw Marczak "regulator-max-microamp", -ENODATA); 285*af41e8dbSPrzemyslaw Marczak uc_pdata->always_on = fdtdec_get_bool(gd->fdt_blob, offset, 286*af41e8dbSPrzemyslaw Marczak "regulator-always-on"); 287*af41e8dbSPrzemyslaw Marczak uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset, 288*af41e8dbSPrzemyslaw Marczak "regulator-boot-on"); 289*af41e8dbSPrzemyslaw Marczak 290*af41e8dbSPrzemyslaw Marczak return 0; 291*af41e8dbSPrzemyslaw Marczak } 292*af41e8dbSPrzemyslaw Marczak 293*af41e8dbSPrzemyslaw Marczak UCLASS_DRIVER(regulator) = { 294*af41e8dbSPrzemyslaw Marczak .id = UCLASS_REGULATOR, 295*af41e8dbSPrzemyslaw Marczak .name = "regulator", 296*af41e8dbSPrzemyslaw Marczak .post_bind = regulator_post_bind, 297*af41e8dbSPrzemyslaw Marczak .pre_probe = regulator_pre_probe, 298*af41e8dbSPrzemyslaw Marczak .per_device_platdata_auto_alloc_size = 299*af41e8dbSPrzemyslaw Marczak sizeof(struct dm_regulator_uclass_platdata), 300*af41e8dbSPrzemyslaw Marczak }; 301