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