137 lines
3.0 KiB
C
137 lines
3.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2024 Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <power/pmic.h>
|
|
#include <power/regulator.h>
|
|
#include <power/fp9931.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
/* in uV */
|
|
const static int fp9931_vpos_vneg_voltages[] = {
|
|
7040000, 7040000, 7040000, 7040000, 7040000,
|
|
7260000, 7490000, 7710000, 7930000, 8150000,
|
|
8380000, 8600000, 8820000, 9040000, 9270000,
|
|
9490000, 9710000, 9940000, 10160000, 10380000,
|
|
10600000, 10830000, 11050000, 11270000, 11490000,
|
|
11720000, 11940000, 12160000, 12380000, 12610000,
|
|
12830000, 13050000, 13280000, 13500000, 13720000,
|
|
13940000, 14170000, 14390000, 14610000, 14830000,
|
|
15060000
|
|
};
|
|
|
|
static int fp9931_vcom_set_enable(struct udevice *dev, bool enable)
|
|
{
|
|
struct udevice *pmic = dev_get_parent(dev);
|
|
struct fp9931_plat_data *data = dev_get_platdata(pmic);
|
|
int ret;
|
|
|
|
if (enable) {
|
|
ret = pmic_clrsetbits(pmic, FP9931_CONTROL_REG1, 0, CONTROL_REG1_V3P3_EN);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
/* V3P3 is auto off when EN pin disable */
|
|
ret = dm_gpio_set_value(&data->enable_gpio, enable);
|
|
|
|
/* It takes about 55 ms at most for i2c to become available again. */
|
|
if (enable)
|
|
mdelay(55);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* VCOM = 0V + [(-5 / 255) * N]V, N = 1~255 (0 is meaningless) */
|
|
static int fp9931_vcom_set_value(struct udevice *dev, int uV)
|
|
{
|
|
struct udevice *pmic = dev_get_parent(dev);
|
|
u32 val;
|
|
int ret;
|
|
|
|
val = 255ul * uV;
|
|
val /= 5000000;
|
|
|
|
if (val == 0)
|
|
val = 1;
|
|
else if (val > 255)
|
|
val = 255;
|
|
|
|
ret = pmic_reg_write(pmic, FP9931_VCOM_SETTING, val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int fp9931_regulator_get_enable(struct udevice *dev)
|
|
{
|
|
struct udevice *pmic = dev_get_parent(dev);
|
|
struct fp9931_plat_data *data = dev_get_platdata(pmic);
|
|
int ret;
|
|
|
|
ret = dm_gpio_get_value(&data->enable_gpio);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
return !!ret;
|
|
}
|
|
|
|
static int fp9931_vpos_vneg_set_enable(struct udevice *dev, bool enable)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int fp9931_vpos_vneg_set_value(struct udevice *dev, int uV)
|
|
{
|
|
struct udevice *pmic = dev_get_parent(dev);
|
|
int i, ret, val;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(fp9931_vpos_vneg_voltages); i++) {
|
|
if (fp9931_vpos_vneg_voltages[i] > uV)
|
|
break;
|
|
}
|
|
|
|
if (--i < 0)
|
|
i = 0;
|
|
|
|
ret = pmic_reg_read(pmic, FP9931_VPOS_VNEG_SETTING);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
val = (ret & 0xFF) & (~VPOS_VNEG_SETTING);
|
|
val |= i;
|
|
|
|
ret = pmic_reg_write(pmic, FP9931_VPOS_VNEG_SETTING, val);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct dm_regulator_ops fp9931_vcom_ops = {
|
|
.get_enable = fp9931_regulator_get_enable,
|
|
.set_enable = fp9931_vcom_set_enable,
|
|
.set_value = fp9931_vcom_set_value,
|
|
};
|
|
|
|
U_BOOT_DRIVER(fp9931_vcom) = {
|
|
.name = FP9931_VCOM_DRIVER_NAME,
|
|
.id = UCLASS_REGULATOR,
|
|
.ops = &fp9931_vcom_ops,
|
|
};
|
|
|
|
static const struct dm_regulator_ops fp9931_vpos_vneg_ops = {
|
|
.get_enable = fp9931_regulator_get_enable,
|
|
.set_enable = fp9931_vpos_vneg_set_enable,
|
|
.set_value = fp9931_vpos_vneg_set_value,
|
|
};
|
|
|
|
U_BOOT_DRIVER(fp9931_vpos_vneg) = {
|
|
.name = FP9931_VPOS_VNEG_DRIVER_NAME,
|
|
.id = UCLASS_REGULATOR,
|
|
.ops = &fp9931_vpos_vneg_ops,
|
|
};
|