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/fp9931.h>
11
12 DECLARE_GLOBAL_DATA_PTR;
13
14 /* in uV */
15 const static int fp9931_vpos_vneg_voltages[] = {
16 7040000, 7040000, 7040000, 7040000, 7040000,
17 7260000, 7490000, 7710000, 7930000, 8150000,
18 8380000, 8600000, 8820000, 9040000, 9270000,
19 9490000, 9710000, 9940000, 10160000, 10380000,
20 10600000, 10830000, 11050000, 11270000, 11490000,
21 11720000, 11940000, 12160000, 12380000, 12610000,
22 12830000, 13050000, 13280000, 13500000, 13720000,
23 13940000, 14170000, 14390000, 14610000, 14830000,
24 15060000
25 };
26
fp9931_vcom_set_enable(struct udevice * dev,bool enable)27 static int fp9931_vcom_set_enable(struct udevice *dev, bool enable)
28 {
29 struct udevice *pmic = dev_get_parent(dev);
30 struct fp9931_plat_data *data = dev_get_platdata(pmic);
31 int ret;
32
33 if (enable) {
34 ret = pmic_clrsetbits(pmic, FP9931_CONTROL_REG1, 0, CONTROL_REG1_V3P3_EN);
35 if (ret)
36 return ret;
37 }
38
39 /* V3P3 is auto off when EN pin disable */
40 ret = dm_gpio_set_value(&data->enable_gpio, enable);
41
42 /* It takes about 55 ms at most for i2c to become available again. */
43 if (enable)
44 mdelay(55);
45
46 return ret;
47 }
48
49 /* VCOM = 0V + [(-5 / 255) * N]V, N = 1~255 (0 is meaningless) */
fp9931_vcom_set_value(struct udevice * dev,int uV)50 static int fp9931_vcom_set_value(struct udevice *dev, int uV)
51 {
52 struct udevice *pmic = dev_get_parent(dev);
53 u32 val;
54 int ret;
55
56 val = 255ul * uV;
57 val /= 5000000;
58
59 if (val == 0)
60 val = 1;
61 else if (val > 255)
62 val = 255;
63
64 ret = pmic_reg_write(pmic, FP9931_VCOM_SETTING, val);
65
66 return ret;
67 }
68
fp9931_regulator_get_enable(struct udevice * dev)69 static int fp9931_regulator_get_enable(struct udevice *dev)
70 {
71 struct udevice *pmic = dev_get_parent(dev);
72 struct fp9931_plat_data *data = dev_get_platdata(pmic);
73 int ret;
74
75 ret = dm_gpio_get_value(&data->enable_gpio);
76 if (ret < 0)
77 return ret;
78
79 return !!ret;
80 }
81
fp9931_vpos_vneg_set_enable(struct udevice * dev,bool enable)82 static int fp9931_vpos_vneg_set_enable(struct udevice *dev, bool enable)
83 {
84 return 0;
85 }
86
fp9931_vpos_vneg_set_value(struct udevice * dev,int uV)87 static int fp9931_vpos_vneg_set_value(struct udevice *dev, int uV)
88 {
89 struct udevice *pmic = dev_get_parent(dev);
90 int i, ret, val;
91
92 for (i = 0; i < ARRAY_SIZE(fp9931_vpos_vneg_voltages); i++) {
93 if (fp9931_vpos_vneg_voltages[i] > uV)
94 break;
95 }
96
97 if (--i < 0)
98 i = 0;
99
100 ret = pmic_reg_read(pmic, FP9931_VPOS_VNEG_SETTING);
101 if (ret < 0)
102 return ret;
103
104 val = (ret & 0xFF) & (~VPOS_VNEG_SETTING);
105 val |= i;
106
107 ret = pmic_reg_write(pmic, FP9931_VPOS_VNEG_SETTING, val);
108 if (ret < 0)
109 return ret;
110
111 return 0;
112 }
113
114 static const struct dm_regulator_ops fp9931_vcom_ops = {
115 .get_enable = fp9931_regulator_get_enable,
116 .set_enable = fp9931_vcom_set_enable,
117 .set_value = fp9931_vcom_set_value,
118 };
119
120 U_BOOT_DRIVER(fp9931_vcom) = {
121 .name = FP9931_VCOM_DRIVER_NAME,
122 .id = UCLASS_REGULATOR,
123 .ops = &fp9931_vcom_ops,
124 };
125
126 static const struct dm_regulator_ops fp9931_vpos_vneg_ops = {
127 .get_enable = fp9931_regulator_get_enable,
128 .set_enable = fp9931_vpos_vneg_set_enable,
129 .set_value = fp9931_vpos_vneg_set_value,
130 };
131
132 U_BOOT_DRIVER(fp9931_vpos_vneg) = {
133 .name = FP9931_VPOS_VNEG_DRIVER_NAME,
134 .id = UCLASS_REGULATOR,
135 .ops = &fp9931_vpos_vneg_ops,
136 };
137