xref: /rk3399_rockchip-uboot/drivers/power/regulator/pwm_regulator.c (revision 83ab7b4937c098a3febc8f361a6be16f28ae16aa)
1 /*
2  * Copyright (C) 2016 Rockchip Electronics Co., Ltd
3  *
4  * Based on kernel drivers/regulator/pwm-regulator.c
5  * Copyright (C) 2014 - STMicroelectronics Inc.
6  * Author: Lee Jones <lee.jones@linaro.org>
7  *
8  * SPDX-License-Identifier:	GPL-2.0+
9  */
10 
11 #include <common.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <pwm.h>
15 #include <power/regulator.h>
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 struct pwm_regulator_info {
20 	/* pwm id corresponding to the PWM driver */
21 	int pwm_id;
22 	/* the period of one PWM cycle */
23 	int period_ns;
24 	/*
25 	 * the polarity of one PWM
26 	 * 0: normal polarity
27 	 * 1: inverted polarity
28 	 */
29 	bool polarity;
30 	struct udevice *pwm;
31 	/* initialize voltage of regulator */
32 	int init_voltage;
33 	/* the maximum voltage of regulator */
34 	int max_voltage;
35 	/* the minimum voltage of regulator */
36 	int min_voltage;
37 	/* the current voltage of regulator */
38 	int volt_uV;
39 };
40 
41 static int pwm_regulator_enable(struct udevice *dev, bool enable)
42 {
43 	struct pwm_regulator_info *priv = dev_get_priv(dev);
44 
45 	return pwm_set_enable(priv->pwm, priv->pwm_id, enable);
46 }
47 
48 static int pwm_voltage_to_duty_cycle_percentage(struct udevice *dev, int req_uV)
49 {
50 	struct pwm_regulator_info *priv = dev_get_priv(dev);
51 	int min_uV = priv->min_voltage;
52 	int max_uV = priv->max_voltage;
53 	int diff = max_uV - min_uV;
54 
55 	return ((req_uV * 100) - (min_uV * 100)) / diff;
56 }
57 
58 static int pwm_regulator_get_voltage(struct udevice *dev)
59 {
60 	struct pwm_regulator_info *priv = dev_get_priv(dev);
61 
62 	return priv->volt_uV;
63 }
64 
65 static int pwm_regulator_set_voltage(struct udevice *dev, int uvolt)
66 {
67 	struct pwm_regulator_info *priv = dev_get_priv(dev);
68 	int duty_cycle;
69 	int ret = 0;
70 
71 	duty_cycle = pwm_voltage_to_duty_cycle_percentage(dev, uvolt);
72 
73 	ret = pwm_set_invert(priv->pwm, priv->pwm_id, priv->polarity);
74 	if (ret) {
75 		dev_err(dev, "Failed to init PWM\n");
76 		return ret;
77 	}
78 
79 	ret = pwm_set_config(priv->pwm, priv->pwm_id,
80 			priv->period_ns, (priv->period_ns / 100) * duty_cycle);
81 	if (ret) {
82 		dev_err(dev, "Failed to configure PWM\n");
83 		return ret;
84 	}
85 
86 	priv->volt_uV = uvolt;
87 
88 	return ret;
89 }
90 
91 static int pwm_regulator_ofdata_to_platdata(struct udevice *dev)
92 {
93 	struct pwm_regulator_info *priv = dev_get_priv(dev);
94 	struct ofnode_phandle_args args;
95 	int ret;
96 
97 	ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0, &args);
98 	if (ret) {
99 		debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret);
100 		return ret;
101 	}
102 
103 	priv->period_ns = args.args[1];
104 	priv->polarity = args.args[2];
105 
106 	priv->init_voltage = dev_read_u32_default(dev, "regulator-init-microvolt", -1);
107 	if (priv->init_voltage < 0) {
108 		printf("Cannot find regulator pwm init_voltage\n");
109 	}
110 
111 	ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm);
112 	if (ret) {
113 		debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
114 		return ret;
115 	}
116 
117 	return 0;
118 }
119 
120 static int pwm_regulator_probe(struct udevice *dev)
121 {
122 	struct pwm_regulator_info *priv = dev_get_priv(dev);
123 	struct dm_regulator_uclass_platdata *uc_pdata;
124 
125 	uc_pdata = dev_get_uclass_platdata(dev);
126 
127 	uc_pdata->type = REGULATOR_TYPE_BUCK;
128 	uc_pdata->mode_count = 0;
129 	priv->max_voltage = uc_pdata->max_uV;
130 	priv->min_voltage = uc_pdata->min_uV;
131 
132 	if (priv->init_voltage)
133 		pwm_regulator_set_voltage(dev, priv->init_voltage);
134 
135 	return 0;
136 }
137 
138 static const struct dm_regulator_ops pwm_regulator_ops = {
139 	.get_value  = pwm_regulator_get_voltage,
140 	.set_value  = pwm_regulator_set_voltage,
141 	.set_enable = pwm_regulator_enable,
142 };
143 
144 static const struct udevice_id pwm_regulator_ids[] = {
145 	{ .compatible = "pwm-regulator" },
146 	{ }
147 };
148 
149 U_BOOT_DRIVER(pwm_regulator) = {
150 	.name = "pwm_regulator",
151 	.id = UCLASS_REGULATOR,
152 	.ops = &pwm_regulator_ops,
153 	.probe = pwm_regulator_probe,
154 	.of_match = pwm_regulator_ids,
155 	.ofdata_to_platdata	= pwm_regulator_ofdata_to_platdata,
156 	.priv_auto_alloc_size	= sizeof(struct pwm_regulator_info),
157 };
158