19923a8b4SPrzemyslaw Marczak /* 29923a8b4SPrzemyslaw Marczak * Copyright (C) 2015 Samsung Electronics 39923a8b4SPrzemyslaw Marczak * 49923a8b4SPrzemyslaw Marczak * Przemyslaw Marczak <p.marczak@samsung.com> 59923a8b4SPrzemyslaw Marczak * 69923a8b4SPrzemyslaw Marczak * SPDX-License-Identifier: GPL-2.0+ 79923a8b4SPrzemyslaw Marczak */ 89923a8b4SPrzemyslaw Marczak 99923a8b4SPrzemyslaw Marczak #include <common.h> 109923a8b4SPrzemyslaw Marczak #include <errno.h> 119923a8b4SPrzemyslaw Marczak #include <dm.h> 129923a8b4SPrzemyslaw Marczak #include <i2c.h> 139923a8b4SPrzemyslaw Marczak #include <asm/gpio.h> 149923a8b4SPrzemyslaw Marczak #include <power/pmic.h> 159923a8b4SPrzemyslaw Marczak #include <power/regulator.h> 169923a8b4SPrzemyslaw Marczak 179923a8b4SPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR; 189923a8b4SPrzemyslaw Marczak 199923a8b4SPrzemyslaw Marczak struct fixed_regulator_platdata { 209923a8b4SPrzemyslaw Marczak struct gpio_desc gpio; /* GPIO for regulator enable control */ 217302fbb3SJohn Keeping unsigned int startup_delay_us; 229923a8b4SPrzemyslaw Marczak }; 239923a8b4SPrzemyslaw Marczak 249923a8b4SPrzemyslaw Marczak static int fixed_regulator_ofdata_to_platdata(struct udevice *dev) 259923a8b4SPrzemyslaw Marczak { 269923a8b4SPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 279923a8b4SPrzemyslaw Marczak struct fixed_regulator_platdata *dev_pdata; 289923a8b4SPrzemyslaw Marczak struct gpio_desc *gpio; 29a5493f82SSimon Glass int flags = GPIOD_IS_OUT; 309923a8b4SPrzemyslaw Marczak int ret; 319923a8b4SPrzemyslaw Marczak 329923a8b4SPrzemyslaw Marczak dev_pdata = dev_get_platdata(dev); 339923a8b4SPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 349923a8b4SPrzemyslaw Marczak if (!uc_pdata) 359923a8b4SPrzemyslaw Marczak return -ENXIO; 369923a8b4SPrzemyslaw Marczak 379923a8b4SPrzemyslaw Marczak /* Set type to fixed */ 389923a8b4SPrzemyslaw Marczak uc_pdata->type = REGULATOR_TYPE_FIXED; 39*3c74eaaaSJoseph Chen if (!dev_read_bool(dev, "enable-active-high")) 40*3c74eaaaSJoseph Chen flags |= GPIOD_ACTIVE_LOW; 41*3c74eaaaSJoseph Chen if (dev_read_bool(dev, "regulator-boot-on")) 42bd2e9714SVignesh R flags |= GPIOD_IS_OUT_ACTIVE; 43bd2e9714SVignesh R 44dc06f63fSMarcel Ziswiler /* Get fixed regulator optional enable GPIO desc */ 459923a8b4SPrzemyslaw Marczak gpio = &dev_pdata->gpio; 46bd2e9714SVignesh R ret = gpio_request_by_name(dev, "gpio", 0, gpio, flags); 47dc06f63fSMarcel Ziswiler if (ret) { 485d3e5a0aSJoseph Chen debug("Fixed regulator optional enable GPIO - not found! Error: %d\n", 49dc06f63fSMarcel Ziswiler ret); 50dc06f63fSMarcel Ziswiler if (ret != -ENOENT) 51dc06f63fSMarcel Ziswiler return ret; 52dc06f63fSMarcel Ziswiler } 539923a8b4SPrzemyslaw Marczak 547302fbb3SJohn Keeping /* Get optional ramp up delay */ 55a5493f82SSimon Glass dev_pdata->startup_delay_us = dev_read_u32_default(dev, 567302fbb3SJohn Keeping "startup-delay-us", 0); 577302fbb3SJohn Keeping 589923a8b4SPrzemyslaw Marczak return 0; 599923a8b4SPrzemyslaw Marczak } 609923a8b4SPrzemyslaw Marczak 619923a8b4SPrzemyslaw Marczak static int fixed_regulator_get_value(struct udevice *dev) 629923a8b4SPrzemyslaw Marczak { 639923a8b4SPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 649923a8b4SPrzemyslaw Marczak 659923a8b4SPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 669923a8b4SPrzemyslaw Marczak if (!uc_pdata) 679923a8b4SPrzemyslaw Marczak return -ENXIO; 689923a8b4SPrzemyslaw Marczak 699923a8b4SPrzemyslaw Marczak if (uc_pdata->min_uV != uc_pdata->max_uV) { 709923a8b4SPrzemyslaw Marczak debug("Invalid constraints for: %s\n", uc_pdata->name); 719923a8b4SPrzemyslaw Marczak return -EINVAL; 729923a8b4SPrzemyslaw Marczak } 739923a8b4SPrzemyslaw Marczak 749923a8b4SPrzemyslaw Marczak return uc_pdata->min_uV; 759923a8b4SPrzemyslaw Marczak } 769923a8b4SPrzemyslaw Marczak 779923a8b4SPrzemyslaw Marczak static int fixed_regulator_get_current(struct udevice *dev) 789923a8b4SPrzemyslaw Marczak { 799923a8b4SPrzemyslaw Marczak struct dm_regulator_uclass_platdata *uc_pdata; 809923a8b4SPrzemyslaw Marczak 819923a8b4SPrzemyslaw Marczak uc_pdata = dev_get_uclass_platdata(dev); 829923a8b4SPrzemyslaw Marczak if (!uc_pdata) 839923a8b4SPrzemyslaw Marczak return -ENXIO; 849923a8b4SPrzemyslaw Marczak 859923a8b4SPrzemyslaw Marczak if (uc_pdata->min_uA != uc_pdata->max_uA) { 869923a8b4SPrzemyslaw Marczak debug("Invalid constraints for: %s\n", uc_pdata->name); 879923a8b4SPrzemyslaw Marczak return -EINVAL; 889923a8b4SPrzemyslaw Marczak } 899923a8b4SPrzemyslaw Marczak 909923a8b4SPrzemyslaw Marczak return uc_pdata->min_uA; 919923a8b4SPrzemyslaw Marczak } 929923a8b4SPrzemyslaw Marczak 930f2194d8SKeerthy static int fixed_regulator_get_enable(struct udevice *dev) 949923a8b4SPrzemyslaw Marczak { 959923a8b4SPrzemyslaw Marczak struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev); 969923a8b4SPrzemyslaw Marczak 97dc06f63fSMarcel Ziswiler /* Enable GPIO is optional */ 989923a8b4SPrzemyslaw Marczak if (!dev_pdata->gpio.dev) 99dc06f63fSMarcel Ziswiler return true; 1009923a8b4SPrzemyslaw Marczak 1019923a8b4SPrzemyslaw Marczak return dm_gpio_get_value(&dev_pdata->gpio); 1029923a8b4SPrzemyslaw Marczak } 1039923a8b4SPrzemyslaw Marczak 1049923a8b4SPrzemyslaw Marczak static int fixed_regulator_set_enable(struct udevice *dev, bool enable) 1059923a8b4SPrzemyslaw Marczak { 1069923a8b4SPrzemyslaw Marczak struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev); 1079923a8b4SPrzemyslaw Marczak int ret; 1089923a8b4SPrzemyslaw Marczak 109a5493f82SSimon Glass debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__, 110a5493f82SSimon Glass dev->name, enable, dev_pdata->startup_delay_us, 111a5493f82SSimon Glass dm_gpio_is_valid(&dev_pdata->gpio)); 112dc06f63fSMarcel Ziswiler /* Enable GPIO is optional */ 113a5493f82SSimon Glass if (!dm_gpio_is_valid(&dev_pdata->gpio)) { 114dc06f63fSMarcel Ziswiler if (!enable) 1159923a8b4SPrzemyslaw Marczak return -ENOSYS; 116dc06f63fSMarcel Ziswiler return 0; 117dc06f63fSMarcel Ziswiler } 1189923a8b4SPrzemyslaw Marczak 1199923a8b4SPrzemyslaw Marczak ret = dm_gpio_set_value(&dev_pdata->gpio, enable); 1209923a8b4SPrzemyslaw Marczak if (ret) { 12190aa625cSMasahiro Yamada pr_err("Can't set regulator : %s gpio to: %d\n", dev->name, 1229923a8b4SPrzemyslaw Marczak enable); 1239923a8b4SPrzemyslaw Marczak return ret; 1249923a8b4SPrzemyslaw Marczak } 1257302fbb3SJohn Keeping 1267302fbb3SJohn Keeping if (enable && dev_pdata->startup_delay_us) 1277302fbb3SJohn Keeping udelay(dev_pdata->startup_delay_us); 128a5493f82SSimon Glass debug("%s: done\n", __func__); 1297302fbb3SJohn Keeping 1309923a8b4SPrzemyslaw Marczak return 0; 1319923a8b4SPrzemyslaw Marczak } 1329923a8b4SPrzemyslaw Marczak 1339923a8b4SPrzemyslaw Marczak static const struct dm_regulator_ops fixed_regulator_ops = { 1349923a8b4SPrzemyslaw Marczak .get_value = fixed_regulator_get_value, 1359923a8b4SPrzemyslaw Marczak .get_current = fixed_regulator_get_current, 1369923a8b4SPrzemyslaw Marczak .get_enable = fixed_regulator_get_enable, 1379923a8b4SPrzemyslaw Marczak .set_enable = fixed_regulator_set_enable, 1389923a8b4SPrzemyslaw Marczak }; 1399923a8b4SPrzemyslaw Marczak 1409923a8b4SPrzemyslaw Marczak static const struct udevice_id fixed_regulator_ids[] = { 1419923a8b4SPrzemyslaw Marczak { .compatible = "regulator-fixed" }, 1429923a8b4SPrzemyslaw Marczak { }, 1439923a8b4SPrzemyslaw Marczak }; 1449923a8b4SPrzemyslaw Marczak 1459923a8b4SPrzemyslaw Marczak U_BOOT_DRIVER(fixed_regulator) = { 1469923a8b4SPrzemyslaw Marczak .name = "fixed regulator", 1479923a8b4SPrzemyslaw Marczak .id = UCLASS_REGULATOR, 1489923a8b4SPrzemyslaw Marczak .ops = &fixed_regulator_ops, 1499923a8b4SPrzemyslaw Marczak .of_match = fixed_regulator_ids, 1509923a8b4SPrzemyslaw Marczak .ofdata_to_platdata = fixed_regulator_ofdata_to_platdata, 1519923a8b4SPrzemyslaw Marczak .platdata_auto_alloc_size = sizeof(struct fixed_regulator_platdata), 1529923a8b4SPrzemyslaw Marczak }; 153