1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2015 Samsung Electronics
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Przemyslaw Marczak <p.marczak@samsung.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <i2c.h>
13*4882a593Smuzhiyun #include <asm/gpio.h>
14*4882a593Smuzhiyun #include <power/pmic.h>
15*4882a593Smuzhiyun #include <power/regulator.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun struct fixed_regulator_platdata {
20*4882a593Smuzhiyun struct gpio_desc gpio; /* GPIO for regulator enable control */
21*4882a593Smuzhiyun unsigned int startup_delay_us;
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun
fixed_regulator_ofdata_to_platdata(struct udevice * dev)24*4882a593Smuzhiyun static int fixed_regulator_ofdata_to_platdata(struct udevice *dev)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun struct dm_regulator_uclass_platdata *uc_pdata;
27*4882a593Smuzhiyun struct fixed_regulator_platdata *dev_pdata;
28*4882a593Smuzhiyun struct gpio_desc *gpio;
29*4882a593Smuzhiyun int flags = GPIOD_IS_OUT;
30*4882a593Smuzhiyun int ret;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun dev_pdata = dev_get_platdata(dev);
33*4882a593Smuzhiyun uc_pdata = dev_get_uclass_platdata(dev);
34*4882a593Smuzhiyun if (!uc_pdata)
35*4882a593Smuzhiyun return -ENXIO;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /* Set type to fixed */
38*4882a593Smuzhiyun uc_pdata->type = REGULATOR_TYPE_FIXED;
39*4882a593Smuzhiyun if (!dev_read_bool(dev, "enable-active-high"))
40*4882a593Smuzhiyun flags |= GPIOD_ACTIVE_LOW;
41*4882a593Smuzhiyun if (dev_read_bool(dev, "regulator-boot-on"))
42*4882a593Smuzhiyun flags |= GPIOD_IS_OUT_ACTIVE;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* Get fixed regulator optional enable GPIO desc */
45*4882a593Smuzhiyun gpio = &dev_pdata->gpio;
46*4882a593Smuzhiyun ret = gpio_request_by_name(dev, "gpio", 0, gpio, flags);
47*4882a593Smuzhiyun if (ret) {
48*4882a593Smuzhiyun ret = gpio_request_by_name(dev, "gpios", 0, gpio, flags);
49*4882a593Smuzhiyun if (ret) {
50*4882a593Smuzhiyun debug("Fixed regulator optional enable GPIO - not found! Error: %d\n", ret);
51*4882a593Smuzhiyun if (ret != -ENOENT)
52*4882a593Smuzhiyun return ret;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Get optional ramp up delay */
57*4882a593Smuzhiyun dev_pdata->startup_delay_us = dev_read_u32_default(dev,
58*4882a593Smuzhiyun "startup-delay-us", 0);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun return 0;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
fixed_regulator_get_value(struct udevice * dev)63*4882a593Smuzhiyun static int fixed_regulator_get_value(struct udevice *dev)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun struct dm_regulator_uclass_platdata *uc_pdata;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun uc_pdata = dev_get_uclass_platdata(dev);
68*4882a593Smuzhiyun if (!uc_pdata)
69*4882a593Smuzhiyun return -ENXIO;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if (uc_pdata->min_uV != uc_pdata->max_uV) {
72*4882a593Smuzhiyun debug("Invalid constraints for: %s\n", uc_pdata->name);
73*4882a593Smuzhiyun return -EINVAL;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return uc_pdata->min_uV;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
fixed_regulator_get_current(struct udevice * dev)79*4882a593Smuzhiyun static int fixed_regulator_get_current(struct udevice *dev)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct dm_regulator_uclass_platdata *uc_pdata;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun uc_pdata = dev_get_uclass_platdata(dev);
84*4882a593Smuzhiyun if (!uc_pdata)
85*4882a593Smuzhiyun return -ENXIO;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if (uc_pdata->min_uA != uc_pdata->max_uA) {
88*4882a593Smuzhiyun debug("Invalid constraints for: %s\n", uc_pdata->name);
89*4882a593Smuzhiyun return -EINVAL;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun return uc_pdata->min_uA;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
fixed_regulator_get_enable(struct udevice * dev)95*4882a593Smuzhiyun static int fixed_regulator_get_enable(struct udevice *dev)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* Enable GPIO is optional */
100*4882a593Smuzhiyun if (!dev_pdata->gpio.dev)
101*4882a593Smuzhiyun return true;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return dm_gpio_get_value(&dev_pdata->gpio);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
fixed_regulator_set_enable(struct udevice * dev,bool enable)106*4882a593Smuzhiyun static int fixed_regulator_set_enable(struct udevice *dev, bool enable)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev);
109*4882a593Smuzhiyun int ret;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
112*4882a593Smuzhiyun dev->name, enable, dev_pdata->startup_delay_us,
113*4882a593Smuzhiyun dm_gpio_is_valid(&dev_pdata->gpio));
114*4882a593Smuzhiyun /* Enable GPIO is optional */
115*4882a593Smuzhiyun if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
116*4882a593Smuzhiyun if (!enable)
117*4882a593Smuzhiyun return -ENOSYS;
118*4882a593Smuzhiyun return 0;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
122*4882a593Smuzhiyun if (ret) {
123*4882a593Smuzhiyun pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
124*4882a593Smuzhiyun enable);
125*4882a593Smuzhiyun return ret;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun if (enable && dev_pdata->startup_delay_us)
129*4882a593Smuzhiyun udelay(dev_pdata->startup_delay_us);
130*4882a593Smuzhiyun debug("%s: done\n", __func__);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun static const struct dm_regulator_ops fixed_regulator_ops = {
136*4882a593Smuzhiyun .get_value = fixed_regulator_get_value,
137*4882a593Smuzhiyun .get_current = fixed_regulator_get_current,
138*4882a593Smuzhiyun .get_enable = fixed_regulator_get_enable,
139*4882a593Smuzhiyun .set_enable = fixed_regulator_set_enable,
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun static const struct udevice_id fixed_regulator_ids[] = {
143*4882a593Smuzhiyun { .compatible = "regulator-fixed" },
144*4882a593Smuzhiyun { },
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun U_BOOT_DRIVER(fixed_regulator) = {
148*4882a593Smuzhiyun .name = "fixed regulator",
149*4882a593Smuzhiyun .id = UCLASS_REGULATOR,
150*4882a593Smuzhiyun .ops = &fixed_regulator_ops,
151*4882a593Smuzhiyun .of_match = fixed_regulator_ids,
152*4882a593Smuzhiyun .ofdata_to_platdata = fixed_regulator_ofdata_to_platdata,
153*4882a593Smuzhiyun .platdata_auto_alloc_size = sizeof(struct fixed_regulator_platdata),
154*4882a593Smuzhiyun };
155