blob: ad3b4b98d6671996cb1e09af63d111fa606fca46 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +02002/*
3 * Copyright (C) 2015 Samsung Electronics
4 *
5 * Przemyslaw Marczak <p.marczak@samsung.com>
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +02006 */
7
8#include <common.h>
Philippe Schenkerf3b51002022-04-08 10:07:10 +02009#include <clk.h>
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020010#include <errno.h>
11#include <dm.h>
Philippe Schenkerf3b51002022-04-08 10:07:10 +020012#include <linux/delay.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060013#include <log.h>
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020014#include <power/pmic.h>
15#include <power/regulator.h>
16
Simon Glassad2f4ac2020-07-19 10:15:44 -060017#include "regulator_common.h"
18
Philippe Schenkerf3b51002022-04-08 10:07:10 +020019struct fixed_clock_regulator_plat {
20 struct clk *enable_clock;
21 unsigned int clk_enable_counter;
22};
23
Simon Glassd1998a92020-12-03 16:55:21 -070024static int fixed_regulator_of_to_plat(struct udevice *dev)
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020025{
Simon Glasscaa4daa2020-12-03 16:55:18 -070026 struct dm_regulator_uclass_plat *uc_pdata;
Eugen Hristev29fca9f2023-04-19 16:45:25 +030027 struct regulator_common_plat *plat;
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020028
Eugen Hristev29fca9f2023-04-19 16:45:25 +030029 plat = dev_get_plat(dev);
Simon Glasscaa4daa2020-12-03 16:55:18 -070030 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020031 if (!uc_pdata)
32 return -ENXIO;
33
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020034 uc_pdata->type = REGULATOR_TYPE_FIXED;
35
Eugen Hristev29fca9f2023-04-19 16:45:25 +030036 return regulator_common_of_to_plat(dev, plat, "gpio");
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020037}
38
39static int fixed_regulator_get_value(struct udevice *dev)
40{
Simon Glasscaa4daa2020-12-03 16:55:18 -070041 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020042
Simon Glasscaa4daa2020-12-03 16:55:18 -070043 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020044 if (!uc_pdata)
45 return -ENXIO;
46
47 if (uc_pdata->min_uV != uc_pdata->max_uV) {
48 debug("Invalid constraints for: %s\n", uc_pdata->name);
49 return -EINVAL;
50 }
51
52 return uc_pdata->min_uV;
53}
54
55static int fixed_regulator_get_current(struct udevice *dev)
56{
Simon Glasscaa4daa2020-12-03 16:55:18 -070057 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020058
Simon Glasscaa4daa2020-12-03 16:55:18 -070059 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020060 if (!uc_pdata)
61 return -ENXIO;
62
63 if (uc_pdata->min_uA != uc_pdata->max_uA) {
64 debug("Invalid constraints for: %s\n", uc_pdata->name);
65 return -EINVAL;
66 }
67
68 return uc_pdata->min_uA;
69}
70
Keerthy0f2194d2017-06-13 09:53:46 +053071static int fixed_regulator_get_enable(struct udevice *dev)
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020072{
Simon Glassc69cda22020-12-03 16:55:20 -070073 return regulator_common_get_enable(dev, dev_get_plat(dev));
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020074}
75
76static int fixed_regulator_set_enable(struct udevice *dev, bool enable)
77{
Simon Glassc69cda22020-12-03 16:55:20 -070078 return regulator_common_set_enable(dev, dev_get_plat(dev), enable);
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +020079}
80
Philippe Schenkerf3b51002022-04-08 10:07:10 +020081static int fixed_clock_regulator_get_enable(struct udevice *dev)
82{
83 struct fixed_clock_regulator_plat *priv = dev_get_priv(dev);
84
85 return priv->clk_enable_counter > 0;
86}
87
88static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
89{
90 struct fixed_clock_regulator_plat *priv = dev_get_priv(dev);
Eugen Hristev29fca9f2023-04-19 16:45:25 +030091 struct regulator_common_plat *plat = dev_get_plat(dev);
Philippe Schenkerf3b51002022-04-08 10:07:10 +020092 int ret = 0;
93
94 if (enable) {
95 ret = clk_enable(priv->enable_clock);
96 priv->clk_enable_counter++;
97 } else {
98 ret = clk_disable(priv->enable_clock);
99 priv->clk_enable_counter--;
100 }
101 if (ret)
102 return ret;
103
Eugen Hristev29fca9f2023-04-19 16:45:25 +0300104 if (enable && plat->startup_delay_us)
105 udelay(plat->startup_delay_us);
Philippe Schenkerf3b51002022-04-08 10:07:10 +0200106
Eugen Hristev29fca9f2023-04-19 16:45:25 +0300107 if (!enable && plat->off_on_delay_us)
108 udelay(plat->off_on_delay_us);
Philippe Schenkerf3b51002022-04-08 10:07:10 +0200109
110 return ret;
111}
112
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +0200113static const struct dm_regulator_ops fixed_regulator_ops = {
114 .get_value = fixed_regulator_get_value,
115 .get_current = fixed_regulator_get_current,
116 .get_enable = fixed_regulator_get_enable,
117 .set_enable = fixed_regulator_set_enable,
118};
119
Philippe Schenkerf3b51002022-04-08 10:07:10 +0200120static const struct dm_regulator_ops fixed_clock_regulator_ops = {
121 .get_enable = fixed_clock_regulator_get_enable,
122 .set_enable = fixed_clock_regulator_set_enable,
123};
124
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +0200125static const struct udevice_id fixed_regulator_ids[] = {
126 { .compatible = "regulator-fixed" },
127 { },
128};
129
Philippe Schenkerf3b51002022-04-08 10:07:10 +0200130static const struct udevice_id fixed_clock_regulator_ids[] = {
131 { .compatible = "regulator-fixed-clock" },
132 { },
133};
134
Walter Lozanoe3e24702020-06-25 01:10:04 -0300135U_BOOT_DRIVER(regulator_fixed) = {
136 .name = "regulator_fixed",
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +0200137 .id = UCLASS_REGULATOR,
138 .ops = &fixed_regulator_ops,
139 .of_match = fixed_regulator_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700140 .of_to_plat = fixed_regulator_of_to_plat,
Philippe Schenkerf3b51002022-04-08 10:07:10 +0200141 .plat_auto = sizeof(struct regulator_common_plat),
142};
143
144U_BOOT_DRIVER(regulator_fixed_clock) = {
145 .name = "regulator_fixed_clk",
146 .id = UCLASS_REGULATOR,
147 .ops = &fixed_clock_regulator_ops,
148 .of_match = fixed_clock_regulator_ids,
149 .of_to_plat = fixed_regulator_of_to_plat,
150 .plat_auto = sizeof(struct fixed_clock_regulator_plat),
Przemyslaw Marczak9923a8b2015-04-20 20:07:48 +0200151};