Merge commit 'f9a997e8c0ae83d037b416d2576ba6c372094927'

* commit 'f9a997e8c0ae83d037b416d2576ba6c372094927':
  ARM: configs: rk3502: use standalone recovery config
  drm/rockchip: gem: remove unused func rockchip_gem_mmap_buf()
  drm/rockchip: fbdev: replace rockchip_gem_mmap_buf() by drm_gem_mmap_obj() in .fb_mmp()
  ARM: configs: rk3506: Add rk801 regulator
  regulator: rk801: Add driver and fix voltage scale issue
  ARM: dts: rockchip: rk3506-rk801: Add pwrctrl-gpios and vcc_3v3 state mem

Change-Id: I371139ae0a8df6ecebf2c82977db6085e8e18644
This commit is contained in:
Tao Huang
2024-10-18 20:58:42 +08:00
12 changed files with 838 additions and 21 deletions

View File

@@ -18,6 +18,8 @@
reg = <0x27>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PC2 IRQ_TYPE_LEVEL_LOW>;
pwrctrl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>;
rockchip,system-power-controller;
@@ -111,6 +113,9 @@
regulator-name = "vcc_3v3";
regulator-boot-on;
regulator-always-on;
regulator-state-mem {
regulator-on-in-suspend;
};
};
};
};

View File

@@ -0,0 +1,143 @@
# CONFIG_ADVISE_SYSCALLS is not set
# CONFIG_ARCH_MULTIPLATFORM is not set
# CONFIG_ASYMMETRIC_KEY_TYPE is not set
# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
# CONFIG_CMA is not set
CONFIG_CONFIGFS_FS=y
# CONFIG_COREDUMP is not set
# CONFIG_CPU_ISOLATION is not set
# CONFIG_CROSS_MEMORY_ATTACH is not set
# CONFIG_CRYPTO_AES is not set
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_CMAC is not set
CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_DRBG_MENU is not set
# CONFIG_CRYPTO_ECB is not set
# CONFIG_CRYPTO_ECDH is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_GHASH is not set
# CONFIG_CRYPTO_HMAC is not set
# CONFIG_CRYPTO_HW is not set
# CONFIG_CRYPTO_JITTERENTROPY is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_RSA is not set
# CONFIG_CRYPTO_SHA256 is not set
CONFIG_CRYPTO_SHA512=y
# CONFIG_CRYPTO_ZSTD is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_USER is not set
# CONFIG_DMABUF_CACHE is not set
# CONFIG_DMABUF_HEAPS is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_EXFAT_FS is not set
# CONFIG_EXT4_FS is not set
# CONFIG_FHANDLE is not set
# CONFIG_FILE_LOCKING is not set
# CONFIG_FUTEX is not set
CONFIG_GPIOLIB_FASTPATH_LIMIT=160
# CONFIG_GPIO_CDEV_V1 is not set
CONFIG_HZ=250
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MUX=y
# CONFIG_IIO is not set
# CONFIG_INITRAMFS_PRESERVE_MTIME is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MISC is not set
# CONFIG_IOSCHED_BFQ is not set
# CONFIG_JUMP_LABEL is not set
# CONFIG_KALLSYMS is not set
# CONFIG_KCMP is not set
CONFIG_LOG_CPU_MAX_BUF_SHIFT=15
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_MEMORY is not set
# CONFIG_MFD_RK808 is not set
# CONFIG_MMC is not set
# CONFIG_MODULES is not set
# CONFIG_MQ_IOSCHED_DEADLINE is not set
# CONFIG_MQ_IOSCHED_KYBER is not set
# CONFIG_MSDOS_PARTITION is not set
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_RAW_NAND=y
# CONFIG_MULTIUSER is not set
# CONFIG_NET is not set
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NTFS3_FS is not set
# CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_PPS is not set
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
# CONFIG_PSTORE is not set
# CONFIG_RCU_TRACE is not set
CONFIG_RD_XZ=y
CONFIG_ROCKCHIP_DISABLE_UNUSED=y
# CONFIG_ROCKCHIP_MULTI_RGA is not set
# CONFIG_ROCKCHIP_SUSPEND_MODE is not set
# CONFIG_RSEQ is not set
# CONFIG_SCSI is not set
CONFIG_SCSI_MOD=y
# CONFIG_SENSOR_DEVICE is not set
# CONFIG_SHMEM is not set
# CONFIG_SLUB_CPU_PARTIAL is not set
# CONFIG_SLUB_SYSFS is not set
# CONFIG_SOUND is not set
# CONFIG_SQUASHFS is not set
# CONFIG_STAGING is not set
# CONFIG_SUSPEND is not set
# CONFIG_SYSFS_SYSCALL is not set
# CONFIG_THERMAL_GOV_USER_SPACE is not set
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
# CONFIG_UBIFS_FS_XATTR is not set
# CONFIG_UBIFS_FS_ZLIB is not set
# CONFIG_UBIFS_FS_ZSTD is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_VDSO=y
# CONFIG_VFAT_FS is not set
CONFIG_XZ_DEC=y
# CONFIG_ARM_ERRATA_458693 is not set
# CONFIG_ARM_ERRATA_460075 is not set
# CONFIG_ARM_ERRATA_742230 is not set
# CONFIG_ARM_ERRATA_742231 is not set
# CONFIG_ARM_ERRATA_743622 is not set
# CONFIG_ARM_ERRATA_751472 is not set
CONFIG_DECOMPRESS_XZ=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_VDSO_32=y
CONFIG_HAVE_GENERIC_VDSO=y
# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
# CONFIG_I2C_DEMUX_PINCTRL is not set
# CONFIG_I2C_MUX_GPIO is not set
# CONFIG_I2C_MUX_GPMUX is not set
# CONFIG_I2C_MUX_LTC4306 is not set
# CONFIG_I2C_MUX_MLXCPLD is not set
# CONFIG_I2C_MUX_PCA9541 is not set
# CONFIG_I2C_MUX_PCA954x is not set
# CONFIG_I2C_MUX_PINCTRL is not set
# CONFIG_I2C_MUX_REG is not set
# CONFIG_MTD_NAND_ARASAN is not set
# CONFIG_MTD_NAND_BRCMNAND is not set
# CONFIG_MTD_NAND_CADENCE is not set
# CONFIG_MTD_NAND_DENALI_DT is not set
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set
# CONFIG_MTD_NAND_GPIO is not set
# CONFIG_MTD_NAND_INTEL_LGM is not set
# CONFIG_MTD_NAND_MXIC is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
CONFIG_MTD_NAND_ROCKCHIP=y
# CONFIG_ROCKCHIP_RGA2 is not set
# CONFIG_XZ_DEC_ARM is not set
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_BCJ=y
# CONFIG_XZ_DEC_IA64 is not set
# CONFIG_XZ_DEC_MICROLZMA is not set
# CONFIG_XZ_DEC_POWERPC is not set
# CONFIG_XZ_DEC_SPARC is not set
# CONFIG_XZ_DEC_TEST is not set
# CONFIG_XZ_DEC_X86 is not set

View File

@@ -1,5 +1,6 @@
# CONFIG_ADVISE_SYSCALLS is not set
# CONFIG_ARCH_MULTIPLATFORM is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
CONFIG_BT_BNEP=m
CONFIG_BT_HIDP=m
@@ -66,7 +67,6 @@ CONFIG_NLS=m
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
# CONFIG_PTP_1588_CLOCK is not set
# CONFIG_RCU_TRACE is not set
CONFIG_RD_GZIP=y
CONFIG_RFKILL=y
CONFIG_RFKILL_RK=y
CONFIG_ROCKCHIP_DISABLE_UNUSED=y
@@ -108,7 +108,6 @@ CONFIG_ZRAM=y
# CONFIG_ARM_ERRATA_751472 is not set
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_TIME_VSYSCALL=y

View File

@@ -220,7 +220,7 @@ CONFIG_MFD_RK808=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_RK801=y
CONFIG_ROCKCHIP_MULTI_RGA=y
CONFIG_SOUND=y
CONFIG_SND=y

View File

@@ -22,7 +22,7 @@ static int rockchip_fbdev_mmap(struct fb_info *info,
struct drm_fb_helper *helper = info->par;
struct rockchip_drm_private *private = helper->dev->dev_private;
return rockchip_gem_mmap_buf(private->fbdev_bo, vma);
return drm_gem_mmap_obj(private->fbdev_bo, private->fbdev_bo->size, vma);
}
static const struct fb_ops rockchip_drm_fbdev_ops = {

View File

@@ -593,18 +593,6 @@ const struct drm_gem_object_funcs rockchip_gem_object_funcs = {
.vm_ops = &drm_gem_dma_vm_ops,
};
int rockchip_gem_mmap_buf(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
int ret;
ret = drm_gem_mmap_obj(obj, obj->size, vma);
if (ret)
return ret;
return rockchip_drm_gem_object_mmap(obj, vma);
}
static struct rockchip_gem_object *
rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size,
unsigned int flags)

View File

@@ -54,9 +54,6 @@ void rockchip_gem_free_object(struct drm_gem_object *obj);
int rockchip_gem_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
struct drm_mode_create_dumb *args);
/* mmap a gem object to userspace. */
int rockchip_gem_mmap_buf(struct drm_gem_object *obj,
struct vm_area_struct *vma);
/*
* request gem object creation and buffer allocation as the size

View File

@@ -217,7 +217,7 @@ static const struct resource rk817_pwrkey_resources[] = {
};
static const struct mfd_cell rk801s[] = {
{ .name = "rk808-regulator", },
{ .name = "rk801-regulator", },
{
.name = "rk805-pwrkey",
.num_resources = ARRAY_SIZE(rk801_key_resources),

View File

@@ -1053,6 +1053,15 @@ config REGULATOR_RC5T583
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
config REGULATOR_RK801
tristate "Rockchip RK801 Power regulators"
depends on MFD_RK808
help
Select this option to enable the power regulator of ROCKCHIP
PMIC RK801. This driver supports the control of different power rails
of device through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
config REGULATOR_RK806
tristate "Rockchip RK806 Power regulator"
depends on MFD_RK806

View File

@@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_RK801) += rk801-regulator.o
obj-$(CONFIG_REGULATOR_RK806) += rk806-regulator.o
obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
obj-$(CONFIG_REGULATOR_RK860X) += rk860x-regulator.o

View File

@@ -0,0 +1,669 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Regulator driver for Rockchip RK801
*
* Copyright (c) 2024, Rockchip Electronics Co., Ltd
*/
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/mfd/rk808.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/syscore_ops.h>
#include <linux/gpio/consumer.h>
/* Field Definitions */
#define RK801_BUCK_VSEL_MASK 0x7f
#define RK801_LDO_VSEL_MASK 0x3f
#define ENABLE_MASK(id) (BIT(4 + (id)) | BIT(id))
#define ENABLE_VAL(id) (BIT(4 + (id)) | BIT(id))
#define DISABLE_VAL(id) (BIT(4 + (id)) | 0)
#define RK801_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enval, _disval, _etime) \
{ \
.name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = (_id), \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
.uV_step = (_step) * 1000, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.enable_val = (_enval), \
.disable_val = (_disval), \
.enable_time = (_etime), \
.ops = &rk801_reg_ops, \
}
#define RK801_DESC_SWITCH(_id, _match, _supply, _ereg, _emask, _enval, \
_disval, _etime) \
{ \
.name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = (_id), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.enable_val = (_enval), \
.disable_val = (_disval), \
.enable_time = (_etime), \
.owner = THIS_MODULE, \
.ops = &rk801_switch_ops \
}
struct suspend_device {
struct regulator_dev *rdev;
int enable;
int uv;
};
struct runtime_device {
int reg_src;
int reg_dst;
};
struct rk801_regulator_data {
struct gpio_desc *pwrctrl_gpio;
struct suspend_device sdev[RK801_ID_MAX];
bool pwrctrl_dvs;
};
static const struct linear_range rk801_buck1_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 80, 12500), /* 0.5v - 1.5v */
REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
REGULATOR_LINEAR_RANGE(3300000, 83, 83, 0), /* 3.3v */
REGULATOR_LINEAR_RANGE(5000000, 84, 84, 0), /* 5.0v */
REGULATOR_LINEAR_RANGE(5250000, 85, 85, 0), /* 5.25v */
};
static const struct linear_range rk801_buck2_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 2, 50000), /* 0.8v - 0.9v */
REGULATOR_LINEAR_RANGE(1800000, 3, 4, 400000), /* 1.8v - 2.2v */
REGULATOR_LINEAR_RANGE(3300000, 5, 5, 0), /* 3.3v */
REGULATOR_LINEAR_RANGE(5000000, 6, 6, 0), /* 5.0v */
REGULATOR_LINEAR_RANGE(5250000, 7, 7, 0), /* 5.25v */
};
static const struct linear_range rk801_buck4_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 80, 12500), /* 0.5v - 1.5v */
REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
REGULATOR_LINEAR_RANGE(2500000, 83, 83, 0), /* 2.5v */
REGULATOR_LINEAR_RANGE(2800000, 84, 84, 0), /* 2.8v */
REGULATOR_LINEAR_RANGE(3000000, 85, 85, 0), /* 3.0v */
REGULATOR_LINEAR_RANGE(3300000, 86, 86, 0), /* 3.3v */
};
static unsigned int rk801_regulator_of_map_mode(unsigned int mode)
{
switch (mode) {
case 1:
return REGULATOR_MODE_FAST;
case 2:
return REGULATOR_MODE_NORMAL;
default:
return REGULATOR_MODE_INVALID;
}
}
static unsigned int rk801_get_mode(struct regulator_dev *rdev)
{
unsigned int pmw_mode_msk;
unsigned int val;
int err;
pmw_mode_msk = BIT(rdev->desc->id);
err = regmap_read(rdev->regmap, RK801_POWER_FPWM_EN_REG, &val);
if (err)
return err;
if ((val & pmw_mode_msk) == RK801_FPWM_MODE)
return REGULATOR_MODE_FAST;
else
return REGULATOR_MODE_NORMAL;
}
static int rk801_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
unsigned int offset = rdev->desc->id;
switch (mode) {
case REGULATOR_MODE_FAST:
return regmap_update_bits(rdev->regmap, RK801_POWER_FPWM_EN_REG,
BIT(offset), RK801_FPWM_MODE << offset);
case REGULATOR_MODE_NORMAL:
return regmap_update_bits(rdev->regmap, RK801_POWER_FPWM_EN_REG,
BIT(offset), RK801_AUTO_PWM_MODE << offset);
default:
dev_err(&rdev->dev, "do not support this mode\n");
return -EINVAL;
}
return 0;
}
static int rk801_set_suspend_voltage(struct regulator_dev *rdev, int uv)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
unsigned int reg;
int sel;
if (pdata->pwrctrl_dvs) {
pdata->sdev[rdev->desc->id].rdev = rdev;
pdata->sdev[rdev->desc->id].uv = uv;
} else {
if (rdev->desc->id < RK801_ID_LDO1)
sel = regulator_map_voltage_linear_range(rdev, uv, uv);
else
sel = regulator_map_voltage_linear(rdev, uv, uv);
if (sel < 0)
return -EINVAL;
reg = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET;
return regmap_update_bits(rdev->regmap, reg,
rdev->desc->vsel_mask, sel);
}
return 0;
}
static int rk801_set_suspend_enable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
if (pdata->pwrctrl_dvs) {
pdata->sdev[rdev->desc->id].rdev = rdev;
pdata->sdev[rdev->desc->id].enable = 1;
} else {
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), BIT(rdev->desc->id));
}
return 0;
}
static int rk801_set_suspend_disable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
if (pdata->pwrctrl_dvs) {
pdata->sdev[rdev->desc->id].rdev = rdev;
pdata->sdev[rdev->desc->id].enable = 0;
} else {
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), 0);
}
return 0;
}
static int rk801_set_enable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
int ret;
ret = regulator_enable_regmap(rdev);
if (ret)
return ret;
if (pdata->pwrctrl_dvs)
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), BIT(rdev->desc->id));
return 0;
}
static int rk801_set_disable(struct regulator_dev *rdev)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
int ret;
ret = regulator_disable_regmap(rdev);
if (ret)
return ret;
if (pdata->pwrctrl_dvs)
return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
BIT(rdev->desc->id), 0);
return 0;
}
static int rk801_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_selector,
unsigned int new_selector)
{
return regulator_set_voltage_time_sel(rdev, old_selector, new_selector) + 32;
}
static int rk801_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
{
struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev);
struct gpio_desc *gpio = pdata->pwrctrl_gpio;
unsigned int reg0 = rdev->desc->vsel_reg;
unsigned int reg1 = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET;
unsigned int reg;
int ret, gpio_level;
if (pdata->pwrctrl_dvs) {
gpio_level = gpiod_get_value(gpio);
reg = (gpio_level == 1) ? reg0 : reg1;
sel <<= ffs(rdev->desc->vsel_mask) - 1;
ret = regmap_update_bits(rdev->regmap, reg, rdev->desc->vsel_mask, sel);
if (ret)
return ret;
udelay(40); /* hw sync */
gpiod_set_value(gpio, !gpio_level);
if (reg == reg0)
ret = regmap_update_bits(rdev->regmap, reg1,
rdev->desc->vsel_mask, sel);
else
ret = regmap_update_bits(rdev->regmap, reg0,
rdev->desc->vsel_mask, sel);
} else {
ret = regulator_set_voltage_sel_regmap(rdev, sel);
}
return ret;
}
static const struct regulator_ops rk801_buck_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = rk801_set_voltage_sel,
.set_voltage_time_sel = rk801_set_voltage_time_sel,
.enable = rk801_set_enable,
.disable = rk801_set_disable,
.is_enabled = regulator_is_enabled_regmap,
.set_mode = rk801_set_mode,
.get_mode = rk801_get_mode,
.set_suspend_voltage = rk801_set_suspend_voltage,
.set_suspend_enable = rk801_set_suspend_enable,
.set_suspend_disable = rk801_set_suspend_disable,
};
static const struct regulator_ops rk801_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = rk801_set_voltage_sel,
.enable = rk801_set_enable,
.disable = rk801_set_disable,
.is_enabled = regulator_is_enabled_regmap,
.set_suspend_voltage = rk801_set_suspend_voltage,
.set_suspend_enable = rk801_set_suspend_enable,
.set_suspend_disable = rk801_set_suspend_disable,
};
static const struct regulator_ops rk801_switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_suspend_enable = rk801_set_suspend_enable,
.set_suspend_disable = rk801_set_suspend_disable,
};
static const struct regulator_desc rk801_reg[] = {
{
.name = "DCDC_REG1",
.supply_name = "vcc1",
.of_match = of_match_ptr("DCDC_REG1"),
.regulators_node = of_match_ptr("regulators"),
.id = RK801_ID_DCDC1,
.ops = &rk801_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 86,
.linear_ranges = rk801_buck1_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk801_buck1_voltage_ranges),
.vsel_reg = RK801_BUCK1_ON_VSEL_REG,
.vsel_mask = RK801_BUCK_VSEL_MASK,
.enable_reg = RK801_POWER_EN0_REG,
.enable_mask = ENABLE_MASK(RK801_ID_DCDC1),
.enable_val = ENABLE_VAL(RK801_ID_DCDC1),
.disable_val = DISABLE_VAL(RK801_ID_DCDC1),
.ramp_delay = 1,
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG2",
.supply_name = "vcc2",
.of_match = of_match_ptr("DCDC_REG2"),
.regulators_node = of_match_ptr("regulators"),
.id = RK801_ID_DCDC2,
.ops = &rk801_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 8,
.linear_ranges = rk801_buck2_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk801_buck2_voltage_ranges),
.vsel_reg = RK801_BUCK2_ON_VSEL_REG,
.vsel_mask = RK801_BUCK_VSEL_MASK,
.enable_reg = RK801_POWER_EN0_REG,
.enable_mask = ENABLE_MASK(RK801_ID_DCDC2),
.enable_val = ENABLE_VAL(RK801_ID_DCDC2),
.disable_val = DISABLE_VAL(RK801_ID_DCDC2),
.ramp_delay = 1,
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG3",
.supply_name = "vcc3",
.of_match = of_match_ptr("DCDC_REG3"),
.regulators_node = of_match_ptr("regulators"),
.id = RK801_ID_DCDC3,
.ops = &rk801_switch_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 1,
.enable_reg = RK801_POWER_EN0_REG,
.enable_mask = ENABLE_MASK(RK801_ID_DCDC3),
.enable_val = ENABLE_VAL(RK801_ID_DCDC3),
.disable_val = DISABLE_VAL(RK801_ID_DCDC3),
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG4",
.supply_name = "vcc4",
.of_match = of_match_ptr("DCDC_REG4"),
.regulators_node = of_match_ptr("regulators"),
.id = RK801_ID_DCDC4,
.ops = &rk801_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 87,
.linear_ranges = rk801_buck4_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk801_buck4_voltage_ranges),
.vsel_reg = RK801_BUCK4_ON_VSEL_REG,
.vsel_mask = RK801_BUCK_VSEL_MASK,
.enable_reg = RK801_POWER_EN0_REG,
.enable_mask = ENABLE_MASK(RK801_ID_DCDC4),
.enable_val = ENABLE_VAL(RK801_ID_DCDC4),
.disable_val = DISABLE_VAL(RK801_ID_DCDC4),
.ramp_delay = 1,
.of_map_mode = rk801_regulator_of_map_mode,
.enable_time = 400,
.owner = THIS_MODULE,
},
RK801_DESC(RK801_ID_LDO1, "LDO_REG1", "vcc5", 500, 3400, 50,
RK801_LDO1_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
ENABLE_MASK(0), ENABLE_VAL(0), DISABLE_VAL(0), 400),
RK801_DESC(RK801_ID_LDO2, "LDO_REG2", "vcc6", 500, 3400, 50,
RK801_LDO2_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
ENABLE_MASK(1), ENABLE_VAL(1), DISABLE_VAL(1), 400),
RK801_DESC_SWITCH(RK801_ID_SWITCH, "SWITCH_REG", "vcc7", RK801_POWER_EN1_REG,
ENABLE_MASK(2), ENABLE_VAL(2), DISABLE_VAL(2), 400),
};
static int rk801_regulator_dt_parse_pdata(struct device *dev,
struct device *client_dev,
struct regmap *map,
struct rk801_regulator_data *pdata)
{
struct device_node *np;
int ret = 0;
np = of_get_child_by_name(client_dev->of_node, "regulators");
if (!np)
return -ENXIO;
if (pdata->pwrctrl_dvs) {
pdata->pwrctrl_gpio = devm_gpiod_get_optional(client_dev,
"pwrctrl", GPIOD_OUT_LOW);
if (IS_ERR(pdata->pwrctrl_gpio)) {
ret = PTR_ERR(pdata->pwrctrl_gpio);
dev_err(dev, "failed to get pwrctrl gpio! ret=%d\n", ret);
goto dt_parse_end;
}
if (!pdata->pwrctrl_gpio) {
dev_err(dev, "there is no pwrctrl gpio!\n");
ret = -EINVAL;
}
}
dt_parse_end:
of_node_put(np);
return ret;
}
static int rk801_regulator_init(struct device *dev)
{
struct rk808 *rk808 = dev_get_drvdata(dev->parent);
struct rk801_regulator_data *pdata = dev_get_drvdata(dev);
struct runtime_device rdev[] = {
{ RK801_BUCK1_ON_VSEL_REG, RK801_BUCK1_SLP_VSEL_REG },
{ RK801_BUCK2_ON_VSEL_REG, RK801_BUCK2_SLP_VSEL_REG },
{ RK801_BUCK4_ON_VSEL_REG, RK801_BUCK4_SLP_VSEL_REG },
{ RK801_LDO1_ON_VSEL_REG, RK801_LDO1_SLP_VSEL_REG },
{ RK801_LDO2_ON_VSEL_REG, RK801_LDO2_SLP_VSEL_REG },
};
uint val, en0, en1;
int i, ret;
/* pwrctrl gpio active high and use sleep function */
ret = regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG,
RK801_SLEEP_POL_MSK, RK801_SLEEP_ACT_H);
if (ret)
return ret;
ret = regmap_update_bits(rk808->regmap, RK801_SLEEP_CFG_REG,
RK801_SLEEP_FUN_MSK, RK801_SLEEP_FUN);
if (ret)
return ret;
/* disable buck/pldo slp lp */
ret = regmap_update_bits(rk808->regmap, RK801_SLP_LP_CONFIG_REG,
RK801_SLP_LP_MASK, 0);
if (ret)
return ret;
/* copy en/slp_en */
ret = regmap_read(rk808->regmap, RK801_POWER_EN0_REG, &en0);
if (ret)
return ret;
ret = regmap_read(rk808->regmap, RK801_POWER_EN1_REG, &en1);
if (ret)
return ret;
val = (en0 & 0x0f) | ((en1 & 0x0f) << 4);
ret = regmap_write(rk808->regmap, RK801_POWER_SLP_EN_REG, val);
if (ret)
return ret;
/* copy on_vsel/slp_vsel */
for (i = 0; i < ARRAY_SIZE(rdev); i++) {
ret = regmap_read(rk808->regmap, rdev[i].reg_src, &val);
if (ret)
return ret;
ret = regmap_write(rk808->regmap, rdev[i].reg_dst, val);
if (ret)
return ret;
}
/* init */
for (i = 0; i < ARRAY_SIZE(pdata->sdev); i++) {
pdata->sdev[i].rdev = NULL;
pdata->sdev[i].uv = -EINVAL;
pdata->sdev[i].enable = -EINVAL;
}
return 0;
}
static int rk801_set_suspend_dev(struct suspend_device sdev)
{
struct regulator_dev *rdev = sdev.rdev;
int enable = sdev.enable;
int uv = sdev.uv;
int val, sel, reg;
int ret, mask;
if (!rdev)
return 0;
if (uv != -EINVAL) {
if (rdev->desc->id < RK801_ID_LDO1)
sel = regulator_map_voltage_linear_range(rdev, uv, uv);
else
sel = regulator_map_voltage_linear(rdev, uv, uv);
if (sel < 0)
return -EINVAL;
reg = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET;
ret = regmap_update_bits(rdev->regmap, reg,
rdev->desc->vsel_mask, sel);
if (ret)
return ret;
}
if (enable != -EINVAL) {
mask = BIT(rdev->desc->id);
val = enable ? mask : 0;
ret = regmap_update_bits(rdev->regmap,
RK801_POWER_SLP_EN_REG, mask, val);
if (ret)
return ret;
}
return 0;
}
static int rk801_regulator_suspend_late(struct device *dev)
{
struct rk808 *rk808 = dev_get_drvdata(dev->parent);
struct rk801_regulator_data *pdata = dev_get_drvdata(dev);
struct gpio_desc *gpio = pdata->pwrctrl_gpio;
int i, ret;
if (!pdata->pwrctrl_dvs)
return 0;
/* set pwrctrl pin low */
gpiod_set_value(gpio, 0);
udelay(40);
/* set buck/ldo/switch suspend */
for (i = 0; i < ARRAY_SIZE(pdata->sdev); i++) {
ret = rk801_set_suspend_dev(pdata->sdev[i]);
if (ret)
return ret;
}
/* enable buck/pldo lp enable */
return regmap_update_bits(rk808->regmap, RK801_SLP_LP_CONFIG_REG,
RK801_SLP_LP_MASK, RK801_SLP_LP_MASK);
}
static int rk801_regulator_resume_early(struct device *dev)
{
struct rk801_regulator_data *pdata = dev_get_drvdata(dev);
if (!pdata->pwrctrl_dvs)
return 0;
return rk801_regulator_init(dev);
}
static int rk801_regulator_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct i2c_client *client = rk808->i2c;
struct regulator_config config = {};
struct regulator_dev *rk801_rdev;
struct rk801_regulator_data *pdata;
int id_lsb, i, ret;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
ret = regmap_read(rk808->regmap, RK801_ID_LSB, &id_lsb);
if (ret)
return ret;
pdata->pwrctrl_dvs = (id_lsb & 0x0f) < 4;
dev_info(&pdev->dev, "pwrctrl dvs: %d\n", pdata->pwrctrl_dvs);
ret = rk801_regulator_dt_parse_pdata(&pdev->dev, &client->dev,
rk808->regmap, pdata);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, pdata);
config.dev = &client->dev;
config.driver_data = pdata;
config.regmap = rk808->regmap;
ret = rk801_regulator_init(&pdev->dev);
if (ret)
return ret;
for (i = 0; i < RK801_NUM_REGULATORS; i++) {
rk801_rdev = devm_regulator_register(&pdev->dev,
&rk801_reg[i], &config);
if (IS_ERR(rk801_rdev)) {
dev_err(&client->dev,
"failed to register %d regulator\n", i);
return PTR_ERR(rk801_rdev);
}
}
return 0;
}
static const struct dev_pm_ops rk801_pm_ops = {
.suspend_late = pm_sleep_ptr(rk801_regulator_suspend_late),
.resume_early = pm_sleep_ptr(rk801_regulator_resume_early),
};
static struct platform_driver rk801_regulator_driver = {
.probe = rk801_regulator_probe,
.driver = {
.name = "rk801-regulator",
.pm = pm_sleep_ptr(&rk801_pm_ops),
},
};
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
static int __init rk801_regulator_driver_init(void)
{
return platform_driver_register(&rk801_regulator_driver);
}
subsys_initcall(rk801_regulator_driver_init);
static void __exit rk801_regulator_driver_exit(void)
{
platform_driver_unregister(&rk801_regulator_driver);
}
module_exit(rk801_regulator_driver_exit);
#else
module_platform_driver(rk801_regulator_driver);
#endif
MODULE_DESCRIPTION("regulator driver for the RK801 PMIC");
MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
MODULE_LICENSE("GPL");

View File

@@ -22,11 +22,12 @@
enum rk801_reg {
RK801_ID_DCDC1,
RK801_ID_DCDC2,
RK801_ID_DCDC3,
RK801_ID_DCDC4,
RK801_ID_DCDC3,
RK801_ID_LDO1,
RK801_ID_LDO2,
RK801_ID_SWITCH,
RK801_ID_MAX,
};
#define RK801_SLP_REG_OFFSET 5
@@ -107,6 +108,11 @@ enum rk801_reg {
#define RK801_IRQ_VDC_RISE_MSK BIT(5)
#define RK801_IRQ_VDC_FALL_MSK BIT(6)
/* RK801_SLP_LP_CONFIG_REG */
#define RK801_BUCK_SLP_LP_EN BIT(3)
#define RK801_PLDO_SLP_LP_EN BIT(1)
#define RK801_SLP_LP_MASK (RK801_PLDO_SLP_LP_EN | RK801_BUCK_SLP_LP_EN)
/* RK801_SLEEP_CFG_REG */
#define RK801_SLEEP_FUN_MSK 0x3
#define RK801_NONE_FUN 0x0