xref: /rk3399_rockchip-uboot/drivers/power/regulator/pwm_regulator.c (revision 6aa65bb1ee0951865e27da81dde1de76c6d4687e)
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 		debug("Cannot find 'regulator-init-microvolt'\n");
109 
110 		/*
111 		 * 1. Compatible legacy pwm-regulator driver on rkdevelop;
112 		 * 2. Give pwm-regulator default init voltage 1.1v;
113 		 */
114 		priv->init_voltage = dev_read_u32_default(dev, "rockchip,pwm_voltage",
115 							  1100000);
116 	}
117 
118 	ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm);
119 	if (ret) {
120 		debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
121 		return ret;
122 	}
123 
124 	return 0;
125 }
126 
127 static int pwm_regulator_probe(struct udevice *dev)
128 {
129 	struct pwm_regulator_info *priv = dev_get_priv(dev);
130 	struct dm_regulator_uclass_platdata *uc_pdata;
131 
132 	uc_pdata = dev_get_uclass_platdata(dev);
133 
134 	uc_pdata->type = REGULATOR_TYPE_BUCK;
135 	uc_pdata->mode_count = 0;
136 	priv->max_voltage = uc_pdata->max_uV;
137 	priv->min_voltage = uc_pdata->min_uV;
138 
139 	if (priv->init_voltage > 0) {
140 		debug("pwm-regulator(%s): init %d uV\n",
141 		       dev->name, priv->init_voltage);
142 		pwm_regulator_set_voltage(dev, priv->init_voltage);
143 	}
144 
145 	return 0;
146 }
147 
148 static const struct dm_regulator_ops pwm_regulator_ops = {
149 	.get_value  = pwm_regulator_get_voltage,
150 	.set_value  = pwm_regulator_set_voltage,
151 	.set_enable = pwm_regulator_enable,
152 };
153 
154 static const struct udevice_id pwm_regulator_ids[] = {
155 	{ .compatible = "pwm-regulator" },
156 	{ }
157 };
158 
159 U_BOOT_DRIVER(pwm_regulator) = {
160 	.name = "pwm_regulator",
161 	.id = UCLASS_REGULATOR,
162 	.ops = &pwm_regulator_ops,
163 	.probe = pwm_regulator_probe,
164 	.of_match = pwm_regulator_ids,
165 	.ofdata_to_platdata	= pwm_regulator_ofdata_to_platdata,
166 	.priv_auto_alloc_size	= sizeof(struct pwm_regulator_info),
167 };
168