From dfb8a71ba393cb99291bb5a5c1836b121649b5c2 Mon Sep 17 00:00:00 2001 From: Zhihuan He Date: Fri, 25 Oct 2024 11:16:39 +0800 Subject: [PATCH] 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 --- drivers/devfreq/event/rockchip-dfi.c | 90 +++++++++++++++++++++------- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index d4ab6bc50d13..1b7741c56861 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -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;