2 * Copyright (C) 2016 Rockchip Electronics Co., Ltd
4 * Based on kernel drivers/regulator/pwm-regulator.c
5 * Copyright (C) 2014 - STMicroelectronics Inc.
6 * Author: Lee Jones <lee.jones@linaro.org>
8 * SPDX-License-Identifier: GPL-2.0+
15 #include <power/regulator.h>
17 #include <fdt_support.h>
20 DECLARE_GLOBAL_DATA_PTR
;
22 struct pwm_regulator_info
{
23 /* pwm id corresponding to the PWM driver */
25 /* the period of one PWM cycle */
28 * the polarity of one PWM
30 * 1: inverted polarity
34 /* initialize voltage of regulator */
36 /* the maximum voltage of regulator */
38 /* the minimum voltage of regulator */
40 /* the current voltage of regulator */
44 static int pwm_regulator_enable(struct udevice
*dev
, bool enable
)
46 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
48 return pwm_set_enable(priv
->pwm
, priv
->pwm_id
, enable
);
51 static int pwm_voltage_to_duty_cycle_percentage(struct udevice
*dev
, int req_uV
)
53 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
54 int min_uV
= priv
->min_voltage
;
55 int max_uV
= priv
->max_voltage
;
56 int diff
= max_uV
- min_uV
;
58 return ((req_uV
* 100) - (min_uV
* 100)) / diff
;
61 static int pwm_regulator_get_voltage(struct udevice
*dev
)
63 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
68 static int pwm_regulator_set_voltage(struct udevice
*dev
, int uvolt
)
70 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
74 duty_cycle
= pwm_voltage_to_duty_cycle_percentage(dev
, uvolt
);
76 ret
= pwm_set_invert(priv
->pwm
, priv
->pwm_id
, priv
->polarity
);
78 dev_err(dev
, "Failed to init PWM\n");
82 ret
= pwm_set_config(priv
->pwm
, priv
->pwm_id
,
83 priv
->period_ns
, (priv
->period_ns
/ 100) * duty_cycle
);
85 dev_err(dev
, "Failed to configure PWM\n");
89 priv
->volt_uV
= uvolt
;
94 static int pwm_regulator_ofdata_to_platdata(struct udevice
*dev
)
96 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
97 struct fdtdec_phandle_args args
;
98 const void *blob
= gd
->fdt_blob
;
99 int node
= dev_of_offset(dev
);
102 ret
= fdtdec_parse_phandle_with_args(blob
, node
, "pwms", "#pwm-cells",
105 debug("%s: Cannot get PWM phandle: ret=%d\n", __func__
, ret
);
109 priv
->period_ns
= args
.args
[1];
110 priv
->polarity
= args
.args
[2];
112 priv
->init_voltage
= fdtdec_get_int(blob
, node
,
113 "regulator-init-microvolt", -1);
114 if (priv
->init_voltage
< 0) {
115 printf("Cannot find regulator pwm init_voltage\n");
119 ret
= uclass_get_device_by_of_offset(UCLASS_PWM
, args
.node
, &priv
->pwm
);
121 debug("%s: Cannot get PWM: ret=%d\n", __func__
, ret
);
128 static int pwm_regulator_probe(struct udevice
*dev
)
130 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
131 struct dm_regulator_uclass_platdata
*uc_pdata
;
133 uc_pdata
= dev_get_uclass_platdata(dev
);
135 uc_pdata
->type
= REGULATOR_TYPE_BUCK
;
136 uc_pdata
->mode_count
= 0;
137 priv
->max_voltage
= uc_pdata
->max_uV
;
138 priv
->min_voltage
= uc_pdata
->min_uV
;
140 if (priv
->init_voltage
)
141 pwm_regulator_set_voltage(dev
, priv
->init_voltage
);
146 static const struct dm_regulator_ops pwm_regulator_ops
= {
147 .get_value
= pwm_regulator_get_voltage
,
148 .set_value
= pwm_regulator_set_voltage
,
149 .set_enable
= pwm_regulator_enable
,
152 static const struct udevice_id pwm_regulator_ids
[] = {
153 { .compatible
= "pwm-regulator" },
157 U_BOOT_DRIVER(pwm_regulator
) = {
158 .name
= "pwm_regulator",
159 .id
= UCLASS_REGULATOR
,
160 .ops
= &pwm_regulator_ops
,
161 .probe
= pwm_regulator_probe
,
162 .of_match
= pwm_regulator_ids
,
163 .ofdata_to_platdata
= pwm_regulator_ofdata_to_platdata
,
164 .priv_auto_alloc_size
= sizeof(struct pwm_regulator_info
),