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