xref: /rk3399_rockchip-uboot/drivers/power/regulator/sy7636a_regulator.c (revision 12e25d6dabb5a12529baaa09009184622210b9bb)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <power/pmic.h>
9 #include <power/regulator.h>
10 #include <power/sy7636a.h>
11 
12 DECLARE_GLOBAL_DATA_PTR;
13 
sy7636a_get_enable(struct udevice * dev)14 static int sy7636a_get_enable(struct udevice *dev)
15 {
16         struct udevice *pmic = dev_get_parent(dev);
17         int ret;
18 
19         ret = pmic_reg_read(pmic, SY7636A_REG_OPERATION_MODE_CRL);
20         if (ret < 0)
21                 return ret;
22 
23         return !!(ret & SY7636A_OPERATION_MODE_CRL_VCOMCTL);
24 }
25 
sy7636a_set_enable(struct udevice * dev,bool enable)26 static int sy7636a_set_enable(struct udevice *dev, bool enable)
27 {
28         struct udevice *pmic = dev_get_parent(dev);
29         int ret;
30 
31         if (enable)
32                 ret = pmic_clrsetbits(pmic, SY7636A_REG_OPERATION_MODE_CRL,
33                                       0, SY7636A_OPERATION_MODE_CRL_ONOFF);
34         else
35                 ret = pmic_clrsetbits(pmic, SY7636A_REG_OPERATION_MODE_CRL,
36                                       SY7636A_OPERATION_MODE_CRL_ONOFF, 0);
37 
38         return ret;
39 }
40 
sy7636a_set_value(struct udevice * dev,int uV)41 static int sy7636a_set_value(struct udevice *dev, int uV)
42 {
43         struct udevice *pmic = dev_get_parent(dev);
44         int mV;
45         u32 val, origin_val;
46         int ret;
47 
48         mV = uV / 1000;
49 	val = mV / 10;
50 
51         /* VCOM[7:0] */
52         ret = pmic_reg_read(pmic, SY7636A_REG_VCOM_ADJUST_CTRL_L);
53         if (ret < 0)
54                 return ret;
55 
56         origin_val = ret & 0xFF;
57 
58         /* VCOM[8] */
59         ret = pmic_reg_read(pmic, SY7636A_REG_VCOM_ADJUST_CTRL_H);
60         if (ret < 0)
61                 return ret;
62 
63         origin_val |= (ret & VCOM_ADJUST_BIT_8) << 1;
64         if (val == origin_val)
65                 return 0;
66 
67         /* turn off power rails */
68         ret = pmic_clrsetbits(pmic, SY7636A_REG_OPERATION_MODE_CRL,
69                               SY7636A_OPERATION_MODE_CRL_ONOFF, 0);
70         if (ret < 0)
71                 return ret;
72 
73 	ret = pmic_reg_write(pmic, SY7636A_REG_VCOM_ADJUST_CTRL_L, val & 0xFF);
74 	if (ret < 0)
75 		return ret;
76 
77 	ret = pmic_reg_write(pmic, SY7636A_REG_VCOM_ADJUST_CTRL_H, (val >> 1) & 0x80);
78 	if (ret < 0)
79 		return ret;
80 
81         /* SY7636A has 50ms protection mask for power rails */
82         udelay(50 * 1000);
83 
84         /* turn on power rails */
85         ret = pmic_clrsetbits(pmic, SY7636A_REG_OPERATION_MODE_CRL, 0,
86                               SY7636A_OPERATION_MODE_CRL_ONOFF);
87 
88         return ret;
89 }
90 
sy7636a_regulator_probe(struct udevice * dev)91 static int sy7636a_regulator_probe(struct udevice *dev)
92 {
93         struct udevice *pmic = dev_get_parent(dev);
94         int ret;
95 
96         ret = pmic_reg_write(pmic, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);
97 	if (ret) {
98 		dev_err(dev, "Failed to initialize regulator: %d\n", ret);
99 		return ret;
100 	}
101 
102         return 0;
103 }
104 
105 static const struct dm_regulator_ops sy7636a_ops = {
106         .get_enable = sy7636a_get_enable,
107         .set_enable = sy7636a_set_enable,
108         .set_value  = sy7636a_set_value,
109 };
110 
111 U_BOOT_DRIVER(sy7636a_regulator) = {
112 	.name = SY7636A_REGULATOR_DRIVER_NAME,
113 	.id = UCLASS_REGULATOR,
114 	.ops = &sy7636a_ops,
115 	.probe = sy7636a_regulator_probe,
116 };
117