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;