On 23. 7. 4. 18:32, Sascha Hauer wrote: > The DDR_MON counters are free running counters. These are resetted to 0 > when starting them over like currently done when reading the current > counter values. > > Resetting the counters becomes a problem with perf support we want to > add later, because perf needs counters that are not modified elsewhere. > > This patch removes resetting the counters and keeps them running > instead. That means we no longer use the absolute counter values but > instead compare them with the counter values we read last time. Not > stopping the counters also has the impact that they are running while > we are reading them. We cannot read multiple timers atomically, so > the values do not exactly fit together. The effect should be negligible > though as the time between two measurements is some orders of magnitude > bigger than the time we need to read multiple registers. > > Reviewed-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> > Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> > --- > > Notes: > Changes since v4: > - rephrase commit message > - Drop unused variable > > drivers/devfreq/event/rockchip-dfi.c | 52 ++++++++++++++++------------ > 1 file changed, 30 insertions(+), 22 deletions(-) > > diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c > index 680f629da64fc..126bb744645b6 100644 > --- a/drivers/devfreq/event/rockchip-dfi.c > +++ b/drivers/devfreq/event/rockchip-dfi.c > @@ -38,11 +38,15 @@ > #define DDRMON_CH1_COUNT_NUM 0x3c > #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 > > -struct dmc_usage { > +struct dmc_count_channel { > u32 access; > u32 total; > }; > > +struct dmc_count { > + struct dmc_count_channel c[RK3399_DMC_NUM_CH]; > +}; > + > /* > * The dfi controller can monitor DDR load. It has an upper and lower threshold > * for the operating points. Whenever the usage leaves these bounds an event is > @@ -51,7 +55,7 @@ struct dmc_usage { > struct rockchip_dfi { > struct devfreq_event_dev *edev; > struct devfreq_event_desc desc; > - struct dmc_usage ch_usage[RK3399_DMC_NUM_CH]; > + struct dmc_count last_event_count; > struct device *dev; > void __iomem *regs; > struct regmap *regmap_pmu; > @@ -85,30 +89,18 @@ static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) > writel_relaxed(SOFTWARE_DIS, dfi_regs + DDRMON_CTRL); > } > > -static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev) > +static void rockchip_dfi_read_counters(struct devfreq_event_dev *edev, struct dmc_count *count) > { > struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev); > - u32 tmp, max = 0; > - u32 i, busier_ch = 0; > + u32 i; > void __iomem *dfi_regs = dfi->regs; > > - rockchip_dfi_stop_hardware_counter(edev); > - > - /* Find out which channel is busier */ > for (i = 0; i < RK3399_DMC_NUM_CH; i++) { > - dfi->ch_usage[i].access = readl_relaxed(dfi_regs + > + count->c[i].access = readl_relaxed(dfi_regs + > DDRMON_CH0_DFI_ACCESS_NUM + i * 20); > - dfi->ch_usage[i].total = readl_relaxed(dfi_regs + > + count->c[i].total = readl_relaxed(dfi_regs + > DDRMON_CH0_COUNT_NUM + i * 20); > - tmp = dfi->ch_usage[i].access; > - if (tmp > max) { > - busier_ch = i; > - max = tmp; > - } > } > - rockchip_dfi_start_hardware_counter(edev); > - > - return busier_ch; > } > > static int rockchip_dfi_disable(struct devfreq_event_dev *edev) > @@ -145,12 +137,28 @@ static int rockchip_dfi_get_event(struct devfreq_event_dev *edev, > struct devfreq_event_data *edata) > { > struct rockchip_dfi *dfi = devfreq_event_get_drvdata(edev); > - int busier_ch; > + struct dmc_count count; > + struct dmc_count *last = &dfi->last_event_count; > + u32 access = 0, total = 0; > + int i; > + > + rockchip_dfi_read_counters(edev, &count); > + > + /* We can only report one channel, so find the busiest one */ > + for (i = 0; i < RK3399_DMC_NUM_CH; i++) { > + u32 a = count.c[i].access - last->c[i].access; > + u32 t = count.c[i].total - last->c[i].total; > + > + if (a > access) { > + access = a; > + total = t; > + } > + } > > - busier_ch = rockchip_dfi_get_busier_ch(edev); > + edata->load_count = access * 4; > + edata->total_count = total; > > - edata->load_count = dfi->ch_usage[busier_ch].access * 4; > - edata->total_count = dfi->ch_usage[busier_ch].total; > + dfi->last_event_count = count; > > return 0; > } Acked-by: Chanwoo Choi <cw00.choi@xxxxxxxxxxx> -- Best Regards, Samsung Electronics Chanwoo Choi