Skip to main content

Rockchip FreeRTOS Regulator Developer Guide

ID: RK-KF-YF-060

Release Version: V1.0.1

Date: 2021-04-29

Security Level: □Top-Secret □Secret □Internal ■Public

DISCLAIMER

This document is provided "as is". Rockchip Electronics Co., Ltd. ("the Company") makes no express or implied representations or warranties regarding the accuracy, reliability, completeness, merchantability, fitness for a particular purpose, or non-infringement of any statements, information, or content in this document. This document is for reference as a usage guide only.

Due to product version upgrades or other reasons, this document may be updated or modified from time to time without any notice.

Trademark Statement

"Rockchip", "Rockchip", and "Rockchip" are registered trademarks of the Company and belong to the Company.

All other registered trademarks or trademarks mentioned in this document are owned by their respective owners.

Copyright © 2021 Rockchip Electronics Co., Ltd.

Without the Company's written permission, no individual or entity may extract or copy part or all of the content of this document, or distribute it in any form, beyond the scope of fair use.

Rockchip Electronics Co., Ltd.

Address: No. 18, Area A, Software Park, Tongpan Road, Fuzhou, Fujian Province

Website: www.rock-chips.com

Customer Service Phone: +86-4007-700-590

Customer Service Fax: +86-591-83951833

Customer Service Email: fae@rock-chips.com


Preface

Overview

This document mainly describes the basic introduction and usage of RK2206 PMIC, Charger, Power key and other drivers.

Product Versions

Chip NameKernel Version
RK2206FreeRTOS V10.0.1

Intended Audience

This document (guide) is mainly applicable to the following engineers:

Technical Support Engineers Software Development Engineers

Revision History

VersionAuthorDateRevision Description
V1.0.0Huang Xiaodong2019-12-02Initial version
V1.0.1Huang Ying2021-04-29Modified copyright info and format

Table of Contents

[TOC]


Regulator​

Overview​

Regulator refers to a "stabilizer", including voltage regulator or current regulator, referring to a device that can automatically maintain a constant voltage (or current). Voltage regulators are more commonly used compared to current regulators. From a driver perspective, regulator control mainly involves output enable/disable and control of output voltage or current magnitude.

Configuration​

Configuration in menuconfig:

Enable regulator driver:

BSP Driver --->
[*] Enable REGULATOR

The regulator driver is a core driver that provides interfaces for other related drivers. Simply enabling the regulator driver alone has no practical effect; other drivers need to be enabled based on the specific regulator type, as follows:

BSP Driver --->
[*] Enable REGULATOR
[*] Enable PMIC REGULATOR

For a specific hardware system, the struct regulator_desc needs to be populated to configure specific information for all regulators in that system. The global variable const struct regulator_init regulator_inits[] also needs to be initialized to set the initial voltage for all regulators, as follows:

union U_PWR_REG_DESC
{
struct PWR_INTREG_DESC intreg_desc; /* If the regulator is controlled by internal registers, use this structure */
struct pwr_i2cbus_desc i2c_desc; /* If the regulator is controlled by I2C bus, use this structure */
};

struct regulator_desc
{
uint8 flag;
union U_PWR_REG_DESC desc; /* Hardware parameter information */
regulator_mutex_t lock; /* lock */
uint16 setup_fixed; /* Fixed boost delay uS */
uint16 setup_step; /* Boost rate, mV/uS */
uint32 currentVolt; /* Current voltage value uV */
};

struct regulator_init
{
const char *name; /* Name */
uint32 pwrId; /* id, unique identifier in a system */
uint32 init_voltage; /* Initial voltage value uV */
uint32 suspend_voltage; /* Voltage value in sleep mode uV */
uint32 suspend_enable; /* Whether to enable in sleep mode */
};

/* Set initial voltage for each regulator */
const struct regulator_init regulator_inits[] =
{
REGULATOR_INIT("buck1_out", PWR_ID_BUCK_1V8, 1800000, 0, 0),
REGULATOR_INIT("vcc_3v3", PWR_ID_VCCIO_3V3, 3300000, 0, 0),
REGULATOR_INIT("ldo2_out", PWR_ID_VDD_1V1, 1100000, 0, 0),
REGULATOR_INIT("vcc_1v8", PWR_ID_VCCIO_1V8, 1800000, 0, 0),
REGULATOR_INIT("vcc1v8_pmic", PWR_ID_VCCIO_1V8_PMU, 1800000, 0, 0),
{ 0 },
};

Taking the RK812 regulator module as an example, the following related information can be configured:

  • src/bsp/RK2206/board/rk2206_evb/board.c
#include "driver/drv_regulator.h"

#ifdef CONFIG_DRIVER_REGULATOR
/* Configure basic information for each regulator */
static struct regulator_desc regulators[] =
{
#if CONFIG_DRIVER_PMIC_REGULATOR
/****** buck1_out **********/
{
.flag = REGULATOR_FLG_I2C8 | REGULATOR_FLG_LOCK,
.desc.i2c_desc = RK812_BUCK(RK812_ID_DCDC1, I2C_DEV2, PWR_ID_BUCK_1V8),
},
/****** vcc_3v3 **********/
{
.flag = REGULATOR_FLG_I2C8 | REGULATOR_FLG_LOCK,
.desc.i2c_desc = RK812_LDO(RK812_ID_LDO1, I2C_DEV2, PWR_ID_VCCIO_3V3),
},
/****** ldo2_out **********/
{
.flag = REGULATOR_FLG_I2C8 | REGULATOR_FLG_LOCK,
.desc.i2c_desc = RK812_LDO2(RK812_ID_LDO2, I2C_DEV2, PWR_ID_VDD_1V1),
},
/****** vcc_1v8 **********/
{
.flag = REGULATOR_FLG_I2C8 | REGULATOR_FLG_LOCK,
.desc.i2c_desc = RK812_LDO(RK812_ID_LDO4, I2C_DEV2, PWR_ID_VCCIO_1V8),
},
/****** vcc1v8_pmic **********/
{
.flag = REGULATOR_FLG_I2C8 | REGULATOR_FLG_LOCK,
.desc.i2c_desc = RK812_LDO(RK812_ID_LDO5, I2C_DEV2, PWR_ID_VCCIO_1V8_PMU),
},
#endif
};

/* Set initial voltage for each regulator */
const struct regulator_init regulator_inits[] =
{
REGULATOR_INIT("buck1_out", PWR_ID_BUCK_1V8, 1800000, 0, 0),
REGULATOR_INIT("vcc_3v3", PWR_ID_VCCIO_3V3, 3300000, 0, 0),
REGULATOR_INIT("ldo2_out", PWR_ID_VDD_1V1, 1100000, 0, 0),
REGULATOR_INIT("vcc_1v8", PWR_ID_VCCIO_1V8, 1800000, 0, 0),
REGULATOR_INIT("vcc1v8_pmic", PWR_ID_VCCIO_1V8_PMU, 1800000, 0, 0),
{ 0 },
};
#endif

COMMON API void System_Power_Init(void)
{
...

/* Register the populated struct regulator_desc to the regulator driver */
#if CONFIG_DRIVER_REGULATOR
regulator_desc_init(regulators, HAL_ARRAY_SIZE(regulators));
#endif

...
}

Code and API​

  • src/driver/regulator/drv_regulator.c
  • include/driver/drv_regulator.h
/* Set specified regulator voltage */
rk_err_t regulator_set_voltage(struct regulator_desc *desc, int volt);
/* Get specified regulator voltage */
uint32 regulator_get_voltage(struct regulator_desc *desc);
/* Set specified regulator sleep mode voltage */
rk_err_t regulator_set_suspend_voltage(struct regulator_desc *desc, int volt);
/* Get specified regulator sleep mode voltage */
uint32 regulator_get_suspend_voltage(struct regulator_desc *desc);
/* Get specified regulator real voltage */
uint32 regulator_get_real_voltage(struct regulator_desc *desc);
/* Enable specified regulator */
rk_err_t regulator_enable(struct regulator_desc *desc);
/* Disable specified regulator */
rk_err_t regulator_disable(struct regulator_desc *desc);
/* Enable specified regulator in sleep mode */
rk_err_t regulator_suspend_enable(struct regulator_desc *descs);
/* Disable specified regulator in sleep mode */
rk_err_t regulator_suspend_disable(struct regulator_desc *descs);
/* Get regulator_desc by pwrid */
struct regulator_desc *regulator_get_desc_by_pwrid(ePWR_ID pwrId);
/* Get regulator_desc by name */
struct regulator_desc *regulator_get_desc_by_name(const char *name);
/* Initialize regulator_desc */
void regulator_desc_init(struct regulator_desc *descs, uint32 cnt);
/* Initialize regulator */
void regulator_setup(void);

Usage Example​

Regulator APIs are called by specific modules. Taking dvfs as an example:

  • src/driver/dvfs/drv_dvfs.c
#include "driver/drv_regulator.h"

rk_err_t regulator_req_set_voltage(struct req_pwr_desc *req_pwr, uint8_t req_id,
uint32_t volt)
{
...

volt_new = req_val_updata_val(req_ctrl, req_id, volt);

if (volt_new)
ret = regulator_set_voltage(req_pwr->desc, volt_new);

...
}

PMIC Regulator​

Overview​

Certain types of regulators have registers accessed via I2C. Regulators integrated inside PMICs are typically of this type. We uniformly abstract them as pmic regulators.

Configuration​

Configuration in menuconfig:

Enable pmic regulator driver (regulator driver must be enabled first):

BSP Driver --->
[*] Enable REGULATOR
[*] Enable PMIC REGULATOR

After the above configuration, the pmic regulator driver is ready for use.

Code and API​

  • src/driver/regulator/drv_pmic_regulator.c
  • include/driver/drv_pmic_regulator.h
/* Get specified pmic regulator voltage */
uint32 pmic_get_voltage(struct pwr_i2cbus_desc *desc);
/* Set specified pmic regulator voltage */
rk_err_t pmic_set_voltage(struct pwr_i2cbus_desc *desc,
uint32 voltUv);
/* Get sleep mode voltage of specified pmic regulator */
uint32 pmic_get_suspend_voltage(struct pwr_i2cbus_desc *desc);
/* Set sleep mode voltage of specified pmic regulator */
rk_err_t pmic_set_suspend_voltage(struct pwr_i2cbus_desc *desc,
uint32 voltUv);
/* Enable/disable specified pmic regulator */
rk_err_t pmic_set_enable(struct pwr_i2cbus_desc *desc, uint32 enable);
/* Set whether specified pmic regulator is enabled in sleep mode */
rk_err_t pmic_set_suspend_enable(struct pwr_i2cbus_desc *desc, uint32 enable);
/* Check if specified pmic regulator is enabled */
uint32 pmic_is_enabled(struct pwr_i2cbus_desc *desc);
/* Check if specified pmic regulator matches specified pwrid */
rk_err_t pmic_check_desc_by_pwrId(struct pwr_i2cbus_desc *pdesc, ePWR_ID pwrId);

Usage Example​

PMIC regulator APIs are typically called by the regulator driver, as shown below:

  • src/driver/regulator/drv_regulator.c
#include "driver/drv_pmic_regulator.h"

static rk_err_t __regulator_set_voltage(struct regulator_desc *descs, int volt)
{
...

#ifdef CONFIG_DRIVER_PMIC_REGULATOR
if (REGULATOR_CHK_I2C8(descs))
{
return pmic_set_voltage(&descs->desc.i2c_desc, volt);
}
#endif

...
}