[bsp][rockchip] support DVFS for Rockchip

The I2C will timeout in fan53555, fixed it.

Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
GuEe-GUI
2026-06-23 08:02:09 +08:00
committed by Rbb666
parent 741d82c42b
commit b2e1f13a05
20 changed files with 3478 additions and 156 deletions
+3
View File
@@ -1,6 +1,9 @@
SOC_DM_ADC_DIR = $(SOC_DM_DIR)/adc
SOC_DM_CAN_DIR = $(SOC_DM_DIR)/can
SOC_DM_CLK_DIR = $(SOC_DM_DIR)/clk
SOC_DM_DVFS_EVENT_DIR = $(SOC_DM_DIR)/dvfs/event
SOC_DM_DVFS_CPUFREQ_DIR = $(SOC_DM_DIR)/dvfs/cpufreq
SOC_DM_DVFS_DEVFREQ_DIR = $(SOC_DM_DIR)/dvfs/devfreq
SOC_DM_HWCRYPTO_DIR = $(SOC_DM_DIR)/hwcrypto
SOC_DM_HWSPINLOCK_DIR = $(SOC_DM_DIR)/hwspinlock
SOC_DM_CLOCK_TIME_DIR = $(SOC_DM_DIR)/hwtimer
+21
View File
@@ -0,0 +1,21 @@
from building import *
group = []
if not GetDepend(['RT_USING_DVFS']):
Return('group')
cwd = GetCurrentDir()
list = os.listdir(cwd)
CPPPATH = [cwd + '/../include']
src = []
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')
+10
View File
@@ -0,0 +1,10 @@
config RT_DVFS_ROCKCHIP_CPUFREQ
bool "Rockchip CPUfreq driver"
depends on RT_USING_DVFS
depends on RT_USING_OFW
default y
help
Rockchip CPUfreq with OPP table parsing and optional nvmem
bin/leakage voltage selection. Uses SCMI clock and DT cpu-supply
regulator (e.g. FAN53555). Thermal throttling uses
thermal-cool-dvfs on the cpufreq device.
+13
View File
@@ -0,0 +1,13 @@
from building import *
group = []
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../include']
if GetDepend(['RT_DVFS_ROCKCHIP_CPUFREQ']):
src += ['dvfs-rockchip-cpufreq.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
config RT_DVFS_ROCKCHIP_DMC
bool "Rockchip DMC devfreq (DFI event test stub)"
depends on RT_USING_DVFS
depends on RT_USING_DVFS_EVENT
select RT_DVFS_EVENT_ROCKCHIP_DFI
default n
help
Minimal devfreq on the DMC node to bind DFI event and verify
devfreq_load_from_event. Does not perform ATF/SIP DDR scaling.
+13
View File
@@ -0,0 +1,13 @@
from building import *
group = []
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../include']
if GetDepend(['RT_DVFS_ROCKCHIP_DMC']):
src += ['dvfs-rockchip-dmc.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
+182
View File
@@ -0,0 +1,182 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-21 GuEe-GUI first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "dvfs.rockchip.dmc"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
struct rockchip_dmcfreq
{
struct rt_dvfs_devfreq devfreq;
struct rt_platform_device *pdev;
};
static const struct rt_ofw_node_id dfi_compat_ids[] =
{
{ .compatible = "rockchip,rk3568-dfi" },
{ .compatible = "rockchip,rk3562-dfi" },
{ .compatible = "rockchip,px30-dfi" },
{ /* sentinel */ }
};
static rt_err_t rockchip_dmc_bind_dfi_event(struct rockchip_dmcfreq *dmc,
struct rt_device *dev)
{
struct rt_ofw_node *np = dev->ofw_node, *ev_np;
for (int i = 0; ; ++i)
{
if (!(ev_np = rt_ofw_parse_phandle(np, "devfreq-events", i)))
{
break;
}
if (rt_ofw_node_match(ev_np, dfi_compat_ids))
{
dmc->devfreq.ev = rt_ofw_data(ev_np);
}
rt_ofw_node_put(ev_np);
if (dmc->devfreq.ev)
{
break;
}
}
if (!dmc->devfreq.ev)
{
LOG_W("%s: no DFI devfreq-event", rt_dm_dev_get_name(dev));
return -RT_ENOENT;
}
return RT_EOK;
}
static rt_err_t rockchip_dmc_probe(struct rt_platform_device *pdev)
{
rt_err_t err;
struct rt_device *dev = &pdev->parent;
struct rockchip_dmcfreq *dmc;
struct rt_dvfs_scaling *scaling;
if (!(dmc = rt_calloc(1, sizeof(*dmc))))
{
return -RT_ENOMEM;
}
dmc->pdev = pdev;
scaling = rt_dvfs_devfreq_to_scaling(&dmc->devfreq);
rt_dm_dev_set_name_auto(dev, "dmc");
if ((err = rt_device_register(dev, rt_dm_dev_get_name(dev), RT_DEVICE_FLAG_DEACTIVATE)))
{
rt_free(dmc);
return err;
}
scaling->dev = dev;
scaling->ops = &rt_dvfs_devfreq_ops;
scaling->clk = rt_clk_get_by_index(dev, 0);
if (rt_is_err(scaling->clk))
{
LOG_W("%s: no dmc clk, event test only", rt_dm_dev_get_name(dev));
scaling->clk = RT_NULL;
}
scaling->supply = rt_regulator_get(dev, "center");
if (rt_is_err(scaling->supply))
{
scaling->supply = RT_NULL;
}
if ((err = rockchip_dmc_bind_dfi_event(dmc, dev)))
{
goto _fail;
}
if ((err = rt_dvfs_devfreq_register(&dmc->devfreq)))
{
goto _fail;
}
if ((err = rt_dvfs_scaling_set_governor(scaling, RT_DVFS_GOVERNOR_TYPE_ONDEMAND)))
{
LOG_W("%s: ondemand failed: %s", rt_dm_dev_get_name(dev), rt_strerror(err));
}
pdev->priv = dmc;
LOG_I("%s: event-only devfreq ready, freq %lu-%lu Hz",
rt_dm_dev_get_name(dev), scaling->min_freq, scaling->max_freq);
return RT_EOK;
_fail:
if (scaling->clk)
{
rt_clk_put(scaling->clk);
}
if (scaling->supply)
{
rt_regulator_put(scaling->supply);
}
rt_device_unregister(dev);
rt_free(dmc);
return err;
}
static rt_err_t rockchip_dmc_remove(struct rt_platform_device *pdev)
{
struct rockchip_dmcfreq *dmc = pdev->priv;
if (!dmc)
{
return RT_EOK;
}
rt_dvfs_devfreq_unregister(&dmc->devfreq);
struct rt_dvfs_scaling *scaling = rt_dvfs_devfreq_to_scaling(&dmc->devfreq);
if (scaling->clk)
{
rt_clk_put(scaling->clk);
}
if (scaling->supply)
{
rt_regulator_put(scaling->supply);
}
rt_device_unregister(&pdev->parent);
rt_free(dmc);
pdev->priv = RT_NULL;
return RT_EOK;
}
static const struct rt_ofw_node_id rockchip_dmc_ofw_ids[] =
{
{ .compatible = "rockchip,rk3568-dmc" },
{ .compatible = "rockchip,rk3562-dmc" },
{ /* sentinel */ }
};
static struct rt_platform_driver rockchip_dmc_driver =
{
.name = "rockchip-dmc",
.ids = rockchip_dmc_ofw_ids,
.probe = rockchip_dmc_probe,
.remove = rockchip_dmc_remove,
};
RT_PLATFORM_DRIVER_EXPORT(rockchip_dmc_driver);
+4
View File
@@ -0,0 +1,4 @@
config RT_DVFS_EVENT_ROCKCHIP_DFI
bool "Rockchip DFI Devfreq event driver"
depends on RT_USING_DVFS_EVENT
default n
+13
View File
@@ -0,0 +1,13 @@
from building import *
group = []
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../include']
if GetDepend(['RT_DVFS_EVENT_ROCKCHIP_DFI']):
src += ['event-rockchip-dfi.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+107
View File
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-11-21 GuEe-GUI first version
*/
#ifndef __OPP_SELECT_H__
#define __OPP_SELECT_H__
#include <rtthread.h>
#include <rtdevice.h>
struct opp_info;
struct volt_rm_table
{
int volt;
int rm;
};
struct opp_data
{
rt_err_t (*get_soc_info)(struct rt_device *dev, struct rt_ofw_node *np,
int *bin, int *process);
rt_err_t (*set_soc_info)(struct rt_device *dev, struct rt_ofw_node *np,
struct opp_info *info);
rt_err_t (*set_read_margin)(struct rt_device *dev,
struct opp_info *opp_info, rt_uint32_t rm);
rt_err_t (*config_regulators)(struct rt_device *dev,
struct rt_dvfs_opp *old_opp, struct rt_dvfs_opp *new_opp,
struct opp_info *info);
};
struct opp_info
{
struct rt_device *dev;
struct rt_ofw_node *opp_np;
const struct opp_data *data;
struct rt_clk *clk;
struct rt_regulator *supply;
struct rt_regulator *mem_supply;
int bin;
int process;
int volt_sel;
int scale;
int leakage;
rt_bool_t is_runtime_active;
struct rt_spinlock dvfs_lock;
};
#if defined(RT_DVFS_ROCKCHIP_CPUFREQ)
void get_opp_data(const struct rt_ofw_node_id *matches, struct opp_info *info);
rt_err_t nvmem_cell_read_u8(struct rt_ofw_node *np, const char *cell_id,
rt_uint8_t *val);
const char *regulator_name(struct rt_ofw_node *cpu_np);
rt_err_t opp_table_init(struct rt_device *dev, struct opp_info *info,
const char *reg_name);
void opp_table_uninit(struct rt_device *dev, struct opp_info *info);
rt_err_t opp_table_adjust(struct rt_device *dev, struct opp_info *info,
struct rt_dvfs_scaling *scaling);
rt_err_t opp_parse(struct rt_dvfs_scaling *dvfs, struct rt_dvfs_opp *opp,
struct rt_ofw_node *opp_np, struct opp_info *info);
rt_err_t cpufreq_set_opp(struct rt_dvfs_scaling *scaling, struct rt_dvfs_opp *opp,
struct opp_info *info);
rt_err_t cpufreq_sync_hw_state(struct rt_dvfs_scaling *scaling);
void opp_dvfs_lock(struct opp_info *info);
void opp_dvfs_unlock(struct opp_info *info);
#else
static inline void get_opp_data(const struct rt_ofw_node_id *matches,
struct opp_info *info)
{
RT_UNUSED(matches);
RT_UNUSED(info);
}
static inline rt_err_t opp_table_init(struct rt_device *dev,
struct opp_info *info, const char *reg_name)
{
RT_UNUSED(dev);
RT_UNUSED(info);
RT_UNUSED(reg_name);
return -RT_ENOSYS;
}
#endif /* RT_DVFS_ROCKCHIP_CPUFREQ */
#endif /* __OPP_SELECT_H__ */
+3
View File
@@ -17,6 +17,9 @@ if GetDepend(['RT_SOC_ROCKCHIP_HW_DECOMPRESS']):
if GetDepend(['RT_SOC_ROCKCHIP_IODOMAIN']):
src += ['io-domain.c']
if GetDepend(['RT_DVFS_ROCKCHIP_CPUFREQ']):
src += ['opp-select.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+29 -16
View File
@@ -305,7 +305,23 @@
#define RT_FIRMWARE_ARM_SCMI
#define RT_FIRMWARE_ARM_SCMI_TRANSPORT_MAILBOX
#define RT_FIRMWARE_ARM_SCMI_TRANSPORT_SMC
#define RT_USING_DVFS
#define RT_USING_DVFS_EVENT
#define RT_USING_DVFS_OPP_RETRY_MAX 10
/* DVFS Event Drivers */
#define RT_DVFS_EVENT_ROCKCHIP_DFI
/* DVFS CPUfreq Drivers */
#define RT_DVFS_ROCKCHIP_CPUFREQ
/* DVFS Devfreq Drivers */
#define RT_DVFS_ROCKCHIP_DMC
#define RT_USING_REGULATOR
#define RT_REGULATOR_FAN53555
#define RT_REGULATOR_FIXED
#define RT_REGULATOR_GPIO
#define RT_REGULATOR_SCMI
@@ -326,6 +342,7 @@
/* Thermal Cool Drivers */
#define RT_THERMAL_COOL_DVFS
#define RT_THERMAL_COOL_PWM_FAN
#define RT_USING_NVMEM
#define RT_NVMEM_ROCKCHIP_OTP
@@ -576,10 +593,22 @@
/* end of File System */
/* Tmpfs Testcase */
/* end of Tmpfs Testcase */
/* CPP11 */
/* end of CPP11 */
/* LWP Testcase */
/* end of LWP Testcase */
/* Memory Management Subsytem Testcase */
/* end of Memory Management Subsytem Testcase */
/* Network */
/* end of Network */
@@ -588,14 +617,6 @@
/* end of Utest Framework */
/* end of Kernel Components */
/* Memory Management Subsytem Testcase */
/* end of Memory Management Subsytem Testcase */
/* Tmpfs Testcase */
/* end of Tmpfs Testcase */
/* end of RT-Thread Utestcases */
/* RT-Thread online packages */
@@ -719,14 +740,6 @@
/* GD32 Drivers */
/* end of GD32 Drivers */
/* HPMicro SDK */
/* end of HPMicro SDK */
/* FT32 HAL & SDK Drivers */
/* end of FT32 HAL & SDK Drivers */
/* end of HAL & SDK Drivers */
/* sensors drivers */
+6
View File
@@ -4,6 +4,12 @@ menuconfig RT_USING_REGULATOR
select RT_USING_ADT_REF
default n
config RT_REGULATOR_FAN53555
bool "Fairchild FAN53555 / TCS4525 Regulator"
depends on RT_USING_REGULATOR
depends on RT_USING_I2C
default n
config RT_REGULATOR_FIXED
bool "Fixed regulator support"
depends on RT_USING_REGULATOR
+3
View File
@@ -10,6 +10,9 @@ CPPPATH = [cwd + '/../include']
src = ['regulator.c', 'regulator_dm.c', 'regulator_cmd.c']
if GetDepend(['RT_REGULATOR_FAN53555']):
src += ['regulator-fan53555.c']
if GetDepend(['RT_REGULATOR_FIXED']):
src += ['regulator-fixed.c']
File diff suppressed because it is too large Load Diff