blob: f7ddba8b45e4bdaa6725f2331c613f13a9db465c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Przemyslaw Marczak3753f282015-04-20 20:07:48 +02002/*
3 * Copyright (C) 2015 Samsung Electronics
4 *
5 * Przemyslaw Marczak <p.marczak@samsung.com>
Przemyslaw Marczak3753f282015-04-20 20:07:48 +02006 */
7
8#include <common.h>
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +02009#include <clk.h>
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020010#include <errno.h>
11#include <dm.h>
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +020012#include <linux/delay.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020014#include <power/pmic.h>
15#include <power/regulator.h>
16
Simon Glass1c1ddf62020-07-19 10:15:44 -060017#include "regulator_common.h"
18
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +020019struct fixed_clock_regulator_plat {
20 struct clk *enable_clock;
21 unsigned int clk_enable_counter;
22};
23
Simon Glassaad29ae2020-12-03 16:55:21 -070024static int fixed_regulator_of_to_plat(struct udevice *dev)
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020025{
Simon Glass71fa5b42020-12-03 16:55:18 -070026 struct dm_regulator_uclass_plat *uc_pdata;
Eugen Hristev81aa1922023-04-19 16:45:25 +030027 struct regulator_common_plat *plat;
Jonas Karlman7257f092023-07-22 13:30:21 +000028 bool gpios;
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020029
Eugen Hristev81aa1922023-04-19 16:45:25 +030030 plat = dev_get_plat(dev);
Simon Glass71fa5b42020-12-03 16:55:18 -070031 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020032 if (!uc_pdata)
33 return -ENXIO;
34
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020035 uc_pdata->type = REGULATOR_TYPE_FIXED;
36
Jonas Karlman7257f092023-07-22 13:30:21 +000037 gpios = dev_read_bool(dev, "gpios");
38 return regulator_common_of_to_plat(dev, plat, gpios ? "gpios" : "gpio");
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020039}
40
41static int fixed_regulator_get_value(struct udevice *dev)
42{
Simon Glass71fa5b42020-12-03 16:55:18 -070043 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020044
Simon Glass71fa5b42020-12-03 16:55:18 -070045 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020046 if (!uc_pdata)
47 return -ENXIO;
48
49 if (uc_pdata->min_uV != uc_pdata->max_uV) {
50 debug("Invalid constraints for: %s\n", uc_pdata->name);
51 return -EINVAL;
52 }
53
54 return uc_pdata->min_uV;
55}
56
57static int fixed_regulator_get_current(struct udevice *dev)
58{
Simon Glass71fa5b42020-12-03 16:55:18 -070059 struct dm_regulator_uclass_plat *uc_pdata;
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020060
Simon Glass71fa5b42020-12-03 16:55:18 -070061 uc_pdata = dev_get_uclass_plat(dev);
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020062 if (!uc_pdata)
63 return -ENXIO;
64
65 if (uc_pdata->min_uA != uc_pdata->max_uA) {
66 debug("Invalid constraints for: %s\n", uc_pdata->name);
67 return -EINVAL;
68 }
69
70 return uc_pdata->min_uA;
71}
72
Keerthy8690d6a2017-06-13 09:53:46 +053073static int fixed_regulator_get_enable(struct udevice *dev)
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020074{
Simon Glassfa20e932020-12-03 16:55:20 -070075 return regulator_common_get_enable(dev, dev_get_plat(dev));
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020076}
77
78static int fixed_regulator_set_enable(struct udevice *dev, bool enable)
79{
Simon Glassfa20e932020-12-03 16:55:20 -070080 return regulator_common_set_enable(dev, dev_get_plat(dev), enable);
Przemyslaw Marczak3753f282015-04-20 20:07:48 +020081}
82
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +020083static int fixed_clock_regulator_get_enable(struct udevice *dev)
84{
85 struct fixed_clock_regulator_plat *priv = dev_get_priv(dev);
86
87 return priv->clk_enable_counter > 0;
88}
89
90static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
91{
92 struct fixed_clock_regulator_plat *priv = dev_get_priv(dev);
Eugen Hristev81aa1922023-04-19 16:45:25 +030093 struct regulator_common_plat *plat = dev_get_plat(dev);
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +020094 int ret = 0;
95
96 if (enable) {
97 ret = clk_enable(priv->enable_clock);
98 priv->clk_enable_counter++;
99 } else {
100 ret = clk_disable(priv->enable_clock);
101 priv->clk_enable_counter--;
102 }
103 if (ret)
104 return ret;
105
Eugen Hristev81aa1922023-04-19 16:45:25 +0300106 if (enable && plat->startup_delay_us)
107 udelay(plat->startup_delay_us);
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +0200108
Eugen Hristev81aa1922023-04-19 16:45:25 +0300109 if (!enable && plat->off_on_delay_us)
110 udelay(plat->off_on_delay_us);
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +0200111
112 return ret;
113}
114
Przemyslaw Marczak3753f282015-04-20 20:07:48 +0200115static const struct dm_regulator_ops fixed_regulator_ops = {
116 .get_value = fixed_regulator_get_value,
117 .get_current = fixed_regulator_get_current,
118 .get_enable = fixed_regulator_get_enable,
119 .set_enable = fixed_regulator_set_enable,
120};
121
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +0200122static const struct dm_regulator_ops fixed_clock_regulator_ops = {
123 .get_enable = fixed_clock_regulator_get_enable,
124 .set_enable = fixed_clock_regulator_set_enable,
125};
126
Przemyslaw Marczak3753f282015-04-20 20:07:48 +0200127static const struct udevice_id fixed_regulator_ids[] = {
128 { .compatible = "regulator-fixed" },
129 { },
130};
131
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +0200132static const struct udevice_id fixed_clock_regulator_ids[] = {
133 { .compatible = "regulator-fixed-clock" },
134 { },
135};
136
Walter Lozano2901ac62020-06-25 01:10:04 -0300137U_BOOT_DRIVER(regulator_fixed) = {
138 .name = "regulator_fixed",
Przemyslaw Marczak3753f282015-04-20 20:07:48 +0200139 .id = UCLASS_REGULATOR,
140 .ops = &fixed_regulator_ops,
141 .of_match = fixed_regulator_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700142 .of_to_plat = fixed_regulator_of_to_plat,
Philippe Schenkercdd4bfe2022-04-08 10:07:10 +0200143 .plat_auto = sizeof(struct regulator_common_plat),
144};
145
146U_BOOT_DRIVER(regulator_fixed_clock) = {
147 .name = "regulator_fixed_clk",
148 .id = UCLASS_REGULATOR,
149 .ops = &fixed_clock_regulator_ops,
150 .of_match = fixed_clock_regulator_ids,
151 .of_to_plat = fixed_regulator_of_to_plat,
152 .plat_auto = sizeof(struct fixed_clock_regulator_plat),
Przemyslaw Marczak3753f282015-04-20 20:07:48 +0200153};