1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2019 Disruptive Technologies Research AS 4 * Sven Schwermer <sven.svenschwermer@disruptive-technologies.com> 5 */ 6 7#include <common.h> 8#include <dm.h> 9#include <log.h> 10#include <asm/gpio.h> 11#include <linux/delay.h> 12#include <power/regulator.h> 13#include "regulator_common.h" 14 15#include "regulator_common.h" 16 17int regulator_common_of_to_plat(struct udevice *dev, 18 struct regulator_common_plat *plat, 19 const char *enable_gpio_name) 20{ 21 struct gpio_desc *gpio; 22 int flags = GPIOD_IS_OUT; 23 int ret; 24 25 if (!dev_read_bool(dev, "enable-active-high")) 26 flags |= GPIOD_ACTIVE_LOW; 27 if (dev_read_bool(dev, "regulator-boot-on")) 28 flags |= GPIOD_IS_OUT_ACTIVE; 29 30 /* Get optional enable GPIO desc */ 31 gpio = &plat->gpio; 32 ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, flags); 33 if (ret) { 34 debug("Regulator '%s' optional enable GPIO - not found! Error: %d\n", 35 dev->name, ret); 36 if (ret != -ENOENT) 37 return ret; 38 } 39 40 /* Get optional ramp up delay */ 41 plat->startup_delay_us = dev_read_u32_default(dev, 42 "startup-delay-us", 0); 43 plat->off_on_delay_us = dev_read_u32_default(dev, "off-on-delay-us", 0); 44 if (!plat->off_on_delay_us) { 45 plat->off_on_delay_us = 46 dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0); 47 } 48 49 return 0; 50} 51 52int regulator_common_get_enable(const struct udevice *dev, 53 struct regulator_common_plat *plat) 54{ 55 /* Enable GPIO is optional */ 56 if (!plat->gpio.dev) 57 return true; 58 59 return dm_gpio_get_value(&plat->gpio); 60} 61 62int regulator_common_set_enable(const struct udevice *dev, 63 struct regulator_common_plat *plat, bool enable) 64{ 65 int ret; 66 67 debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__, 68 dev->name, enable, plat->startup_delay_us, 69 dm_gpio_is_valid(&plat->gpio)); 70 /* Enable GPIO is optional */ 71 if (!dm_gpio_is_valid(&plat->gpio)) { 72 if (!enable) 73 return -ENOSYS; 74 return 0; 75 } 76 77 /* If previously enabled, increase count */ 78 if (enable && plat->enable_count > 0) { 79 plat->enable_count++; 80 return -EALREADY; 81 } 82 83 if (!enable) { 84 if (plat->enable_count > 1) { 85 /* If enabled multiple times, decrease count */ 86 plat->enable_count--; 87 return -EBUSY; 88 } else if (!plat->enable_count) { 89 /* If already disabled, do nothing */ 90 return -EALREADY; 91 } 92 } 93 94 ret = dm_gpio_set_value(&plat->gpio, enable); 95 if (ret) { 96 pr_err("Can't set regulator : %s gpio to: %d\n", dev->name, 97 enable); 98 return ret; 99 } 100 101 if (enable && plat->startup_delay_us) 102 udelay(plat->startup_delay_us); 103 debug("%s: done\n", __func__); 104 105 if (!enable && plat->off_on_delay_us) 106 udelay(plat->off_on_delay_us); 107 108 if (enable) 109 plat->enable_count++; 110 else 111 plat->enable_count--; 112 113 return 0; 114} 115