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