mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
PM / devfreq: rockchip-dfi: add dfi pclk management
In the most of the time, the pclk of dfi is turned off. The pclk is only enabled when the result is retrieved for power saving. Change-Id: I040a87e0b146694874b15dce3b23e4ddc5e86c1e Signed-off-by: Zhihuan He <huan.he@rock-chips.com>
This commit is contained in:
@@ -121,7 +121,7 @@ struct rockchip_dfi {
|
||||
struct regmap *regmap_pmu;
|
||||
struct regmap *regmap_grf;
|
||||
struct regmap *regmap_pmugrf;
|
||||
struct clk *clk;
|
||||
struct clk *clk[MAX_DMC_NUM_CH];
|
||||
u32 dram_type;
|
||||
u32 mon_version;
|
||||
u32 mon_idx;
|
||||
@@ -506,34 +506,69 @@ static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
|
||||
return busier_ch;
|
||||
}
|
||||
|
||||
static int rockchip_dfi_clk_enable(struct rockchip_dfi *info)
|
||||
{
|
||||
u32 i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < MAX_DMC_NUM_CH; i++) {
|
||||
if (!(info->ch_msk & BIT(i)))
|
||||
continue;
|
||||
if (info->clk[i]) {
|
||||
ret = clk_prepare_enable(info->clk[i]);
|
||||
if (ret) {
|
||||
dev_err(info->dev, "failed to enable ch%d dfi clk: %d\n",
|
||||
i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dfi_clk_disable(struct rockchip_dfi *info)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < MAX_DMC_NUM_CH; i++) {
|
||||
if (!(info->ch_msk & BIT(i)))
|
||||
continue;
|
||||
if (info->clk[i])
|
||||
clk_disable_unprepare(info->clk[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
|
||||
{
|
||||
int ret;
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
|
||||
ret = rockchip_dfi_clk_enable(info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rockchip_dfi_stop_hardware_counter(edev);
|
||||
if (info->clk)
|
||||
clk_disable_unprepare(info->clk);
|
||||
rockchip_dfi_clk_disable(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
|
||||
{
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
int ret;
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
|
||||
if (info->clk) {
|
||||
ret = clk_prepare_enable(info->clk);
|
||||
if (ret) {
|
||||
dev_err(&edev->dev, "failed to enable dfi clk: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = rockchip_dfi_clk_enable(info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rockchip_dfi_get_mon_version(edev);
|
||||
|
||||
rockchip_dfi_start_hardware_counter(edev);
|
||||
rockchip_dfi_clk_disable(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -548,11 +583,18 @@ static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
|
||||
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
||||
int busier_ch;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = rockchip_dfi_clk_enable(info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
local_irq_save(flags);
|
||||
busier_ch = rockchip_dfi_get_busier_ch(edev);
|
||||
local_irq_restore(flags);
|
||||
|
||||
rockchip_dfi_clk_disable(info);
|
||||
|
||||
edata->load_count = info->ch_usage[busier_ch].access;
|
||||
edata->total_count = info->ch_usage[busier_ch].total;
|
||||
|
||||
@@ -572,7 +614,8 @@ static __maybe_unused __init int rk3588_dfi_init(struct platform_device *pdev,
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
u32 val_2, val_3, val_4;
|
||||
u32 val_2, val_3, val_4, i;
|
||||
char clk_name[20];
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
@@ -598,7 +641,17 @@ static __maybe_unused __init int rk3588_dfi_init(struct platform_device *pdev,
|
||||
data->count_rate = 2;
|
||||
data->dram_dynamic_info_reg = RK3588_PMUGRF_OS_REG(6);
|
||||
data->ch_msk = READ_CH_INFO(val_2) | READ_CH_INFO(val_4) << 2;
|
||||
data->clk = NULL;
|
||||
|
||||
for (i = 0; i < MAX_DMC_NUM_CH; i++) {
|
||||
if (data->ch_msk & BIT(i)) {
|
||||
snprintf(clk_name, sizeof(clk_name), "pclk_ddr_mon_ch%d", i);
|
||||
data->clk[i] = devm_clk_get(&pdev->dev, clk_name);
|
||||
if (IS_ERR(data->clk[i])) {
|
||||
dev_err(&pdev->dev, "Failed to get %s\n", clk_name);
|
||||
return PTR_ERR(data->clk[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desc->ops = &rockchip_dfi_ops;
|
||||
|
||||
@@ -647,7 +700,6 @@ static __maybe_unused __init int px30_dfi_init(struct platform_device *pdev,
|
||||
else
|
||||
data->dram_type = READ_DRAMTYPE_INFO(val_2);
|
||||
data->ch_msk = 1;
|
||||
data->clk = NULL;
|
||||
|
||||
desc->ops = &rockchip_dfi_ops;
|
||||
|
||||
@@ -739,9 +791,9 @@ static __maybe_unused __init int rockchip_dfi_init(struct platform_device *pdev,
|
||||
if (IS_ERR(data->regs))
|
||||
return PTR_ERR(data->regs);
|
||||
|
||||
data->clk = devm_clk_get(dev, "pclk_ddr_mon");
|
||||
if (IS_ERR(data->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(data->clk),
|
||||
data->clk[0] = devm_clk_get(dev, "pclk_ddr_mon");
|
||||
if (IS_ERR(data->clk[0]))
|
||||
return dev_err_probe(dev, PTR_ERR(data->clk[0]),
|
||||
"Cannot get the clk pclk_ddr_mon\n");
|
||||
|
||||
node = of_parse_phandle(np, "rockchip,pmu", 0);
|
||||
@@ -785,7 +837,6 @@ static __maybe_unused __init int rk3328_dfi_init(struct platform_device *pdev,
|
||||
regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val);
|
||||
data->dram_type = READ_DRAMTYPE_INFO(val);
|
||||
data->ch_msk = 1;
|
||||
data->clk = NULL;
|
||||
|
||||
desc->ops = &rockchip_dfi_ops;
|
||||
|
||||
@@ -820,7 +871,6 @@ static __maybe_unused __init int rk3528_dfi_init(struct platform_device *pdev,
|
||||
data->dram_type = READ_DRAMTYPE_INFO(val_18);
|
||||
data->count_rate = 2;
|
||||
data->ch_msk = 1;
|
||||
data->clk = NULL;
|
||||
|
||||
desc->ops = &rockchip_dfi_ops;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user