xref: /rk3399_rockchip-uboot/drivers/power/regulator/fp9931_regulator.c (revision 6cef3c7b7cc45a9c882fc64e5496a416c99313b8)
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 
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) */
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 
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 
82 static int fp9931_vpos_vneg_set_enable(struct udevice *dev, bool enable)
83 {
84 	return 0;
85 }
86 
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