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 /* initialize voltage of regulator */
29 unsigned int init_voltage
;
30 /* the maximum voltage of regulator */
31 unsigned int max_voltage
;
32 /* the minimum voltage of regulator */
33 unsigned int min_voltage
;
34 /* the current voltage of regulator */
38 static int pwm_regulator_enable(struct udevice
*dev
, bool enable
)
40 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
42 return pwm_set_enable(priv
->pwm
, priv
->pwm_id
, enable
);
45 static int pwm_voltage_to_duty_cycle_percentage(struct udevice
*dev
, int req_uV
)
47 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
48 int min_uV
= priv
->min_voltage
;
49 int max_uV
= priv
->max_voltage
;
50 int diff
= max_uV
- min_uV
;
52 return 100 - (((req_uV
* 100) - (min_uV
* 100)) / diff
);
55 static int pwm_regulator_get_voltage(struct udevice
*dev
)
57 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
62 static int pwm_regulator_set_voltage(struct udevice
*dev
, int uvolt
)
64 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
68 duty_cycle
= pwm_voltage_to_duty_cycle_percentage(dev
, uvolt
);
70 ret
= pwm_set_config(priv
->pwm
, priv
->pwm_id
,
71 (priv
->period_ns
/ 100) * duty_cycle
, priv
->period_ns
);
73 dev_err(dev
, "Failed to configure PWM\n");
77 ret
= pwm_set_enable(priv
->pwm
, priv
->pwm_id
, true);
79 dev_err(dev
, "Failed to enable PWM\n");
82 priv
->volt_uV
= uvolt
;
86 static int pwm_regulator_ofdata_to_platdata(struct udevice
*dev
)
88 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
89 struct fdtdec_phandle_args args
;
90 const void *blob
= gd
->fdt_blob
;
91 int node
= dev_of_offset(dev
);
94 ret
= fdtdec_parse_phandle_with_args(blob
, node
, "pwms", "#pwm-cells",
97 debug("%s: Cannot get PWM phandle: ret=%d\n", __func__
, ret
);
100 /* TODO: pwm_id here from device tree if needed */
102 priv
->period_ns
= args
.args
[1];
104 priv
->init_voltage
= fdtdec_get_int(blob
, node
,
105 "regulator-init-microvolt", -1);
106 if (priv
->init_voltage
< 0) {
107 printf("Cannot find regulator pwm init_voltage\n");
111 ret
= uclass_get_device_by_of_offset(UCLASS_PWM
, args
.node
, &priv
->pwm
);
113 debug("%s: Cannot get PWM: ret=%d\n", __func__
, ret
);
120 static int pwm_regulator_probe(struct udevice
*dev
)
122 struct pwm_regulator_info
*priv
= dev_get_priv(dev
);
123 struct dm_regulator_uclass_platdata
*uc_pdata
;
125 uc_pdata
= dev_get_uclass_platdata(dev
);
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
;
132 if (priv
->init_voltage
)
133 pwm_regulator_set_voltage(dev
, priv
->init_voltage
);
135 pwm_regulator_enable(dev
, 1);
140 static const struct dm_regulator_ops pwm_regulator_ops
= {
141 .get_value
= pwm_regulator_get_voltage
,
142 .set_value
= pwm_regulator_set_voltage
,
143 .set_enable
= pwm_regulator_enable
,
146 static const struct udevice_id pwm_regulator_ids
[] = {
147 { .compatible
= "pwm-regulator" },
151 U_BOOT_DRIVER(pwm_regulator
) = {
152 .name
= "pwm_regulator",
153 .id
= UCLASS_REGULATOR
,
154 .ops
= &pwm_regulator_ops
,
155 .probe
= pwm_regulator_probe
,
156 .of_match
= pwm_regulator_ids
,
157 .ofdata_to_platdata
= pwm_regulator_ofdata_to_platdata
,
158 .priv_auto_alloc_size
= sizeof(struct pwm_regulator_info
),