[RESEND PATCH v4 1/3] perf/marvell: Refactor to extract platform data

Gowthami Thiagarajan gthiagarajan at marvell.com
Fri Apr 19 03:43:33 PDT 2024


Hi,

The patches are updated as per the comments received. Do you have any feedback on this version?

Thanks,
Gowthami

> -----Original Message-----
> From: Gowthami Thiagarajan <gthiagarajan at marvell.com>
> Sent: Wednesday, March 27, 2024 12:49 PM
> To: will at kernel.org; mark.rutland at arm.com; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org
> Cc: Sunil Kovvuri Goutham <sgoutham at marvell.com>; Bharat Bhushan <bbhushan2 at marvell.com>; George
> Cherian <gcherian at marvell.com>; Gowthami Thiagarajan <gthiagarajan at marvell.com>
> Subject: [RESEND PATCH v4 1/3] perf/marvell: Refactor to extract platform data
> 
> This commit introduces a refactor to the Marvell driver
> code, specifically targeting the extraction of platform data
> (referred to as "pdata") from the existing driver. The purpose of
> this refactor is to prepare for the upcoming support of the next
> version of the Performance Monitoring Unit (PMU) in this
> driver.
> 
> No functional changes are introduced in this refactor. Its sole
> purpose is to improve code organization and pave the way for
> future enhancements to the driver.
> 
> Signed-off-by: Gowthami Thiagarajan <gthiagarajan at marvell.com>
> ---
>  drivers/perf/marvell_cn10k_ddr_pmu.c | 282 ++++++++++++++++++++-------
>  1 file changed, 210 insertions(+), 72 deletions(-)
> 
> diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c
> index 524ba82bfce2..d6485c4cf30f 100644
> --- a/drivers/perf/marvell_cn10k_ddr_pmu.c
> +++ b/drivers/perf/marvell_cn10k_ddr_pmu.c
> @@ -1,7 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0
> -/* Marvell CN10K DRAM Subsystem (DSS) Performance Monitor Driver
> +/*
> + * Marvell CN10K DRAM Subsystem (DSS) Performance Monitor Driver
>   *
> - * Copyright (C) 2021 Marvell.
> + * Copyright (C) 2024 Marvell.
>   */
> 
>  #include <linux/init.h>
> @@ -14,24 +15,24 @@
>  #include <linux/platform_device.h>
> 
>  /* Performance Counters Operating Mode Control Registers */
> -#define DDRC_PERF_CNT_OP_MODE_CTRL	0x8020
> -#define OP_MODE_CTRL_VAL_MANNUAL	0x1
> +#define CN10K_DDRC_PERF_CNT_OP_MODE_CTRL	0x8020
> +#define OP_MODE_CTRL_VAL_MANUAL	0x1
> 
>  /* Performance Counters Start Operation Control Registers */
> -#define DDRC_PERF_CNT_START_OP_CTRL	0x8028
> +#define CN10K_DDRC_PERF_CNT_START_OP_CTRL	0x8028
>  #define START_OP_CTRL_VAL_START		0x1ULL
>  #define START_OP_CTRL_VAL_ACTIVE	0x2
> 
>  /* Performance Counters End Operation Control Registers */
> -#define DDRC_PERF_CNT_END_OP_CTRL	0x8030
> +#define CN10K_DDRC_PERF_CNT_END_OP_CTRL	0x8030
>  #define END_OP_CTRL_VAL_END		0x1ULL
> 
>  /* Performance Counters End Status Registers */
> -#define DDRC_PERF_CNT_END_STATUS		0x8038
> +#define CN10K_DDRC_PERF_CNT_END_STATUS		0x8038
>  #define END_STATUS_VAL_END_TIMER_MODE_END	0x1
> 
>  /* Performance Counters Configuration Registers */
> -#define DDRC_PERF_CFG_BASE		0x8040
> +#define CN10K_DDRC_PERF_CFG_BASE		0x8040
> 
>  /* 8 Generic event counter + 2 fixed event counters */
>  #define DDRC_PERF_NUM_GEN_COUNTERS	8
> @@ -42,17 +43,19 @@
>  					 DDRC_PERF_NUM_FIX_COUNTERS)
> 
>  /* Generic event counter registers */
> -#define DDRC_PERF_CFG(n)		(DDRC_PERF_CFG_BASE + 8 * (n))
> +#define DDRC_PERF_CFG(base, n)		((base) + 8 * (n))
>  #define EVENT_ENABLE			BIT_ULL(63)
> 
>  /* Two dedicated event counters for DDR reads and writes */
>  #define EVENT_DDR_READS			101
>  #define EVENT_DDR_WRITES		100
> 
> +#define DDRC_PERF_REG(base, n)		((base) + 8 * (n))
>  /*
>   * programmable events IDs in programmable event counters.
>   * DO NOT change these event-id numbers, they are used to
>   * program event bitmap in h/w.
> + *
>   */
>  #define EVENT_OP_IS_ZQLATCH			55
>  #define EVENT_OP_IS_ZQSTART			54
> @@ -63,8 +66,8 @@
>  #define EVENT_VISIBLE_WIN_LIMIT_REACHED_RD	49
>  #define EVENT_BSM_STARVATION			48
>  #define EVENT_BSM_ALLOC				47
> -#define EVENT_LPR_REQ_WITH_NOCREDIT		46
> -#define EVENT_HPR_REQ_WITH_NOCREDIT		45
> +#define EVENT_RETRY_FIFO_FULL_OR_LPR_REQ_NOCRED	46
> +#define EVENT_DFI_OR_HPR_REQ_NOCRED		45
>  #define EVENT_OP_IS_ZQCS			44
>  #define EVENT_OP_IS_ZQCL			43
>  #define EVENT_OP_IS_LOAD_MODE			42
> @@ -102,28 +105,38 @@
>  #define EVENT_HIF_RD_OR_WR			1
> 
>  /* Event counter value registers */
> -#define DDRC_PERF_CNT_VALUE_BASE		0x8080
> -#define DDRC_PERF_CNT_VALUE(n)	(DDRC_PERF_CNT_VALUE_BASE + 8 * (n))
> +#define CN10K_DDRC_PERF_CNT_VALUE_BASE	0x8080
> 
>  /* Fixed event counter enable/disable register */
> -#define DDRC_PERF_CNT_FREERUN_EN	0x80C0
> +#define CN10K_DDRC_PERF_CNT_FREERUN_EN		0x80C0
>  #define DDRC_PERF_FREERUN_WRITE_EN	0x1
>  #define DDRC_PERF_FREERUN_READ_EN	0x2
> 
>  /* Fixed event counter control register */
> -#define DDRC_PERF_CNT_FREERUN_CTRL	0x80C8
> +#define CN10K_DDRC_PERF_CNT_FREERUN_CTRL	0x80C8
>  #define DDRC_FREERUN_WRITE_CNT_CLR	0x1
>  #define DDRC_FREERUN_READ_CNT_CLR	0x2
> 
> -/* Fixed event counter value register */
> -#define DDRC_PERF_CNT_VALUE_WR_OP	0x80D0
> -#define DDRC_PERF_CNT_VALUE_RD_OP	0x80D8
>  #define DDRC_PERF_CNT_VALUE_OVERFLOW	BIT_ULL(48)
>  #define DDRC_PERF_CNT_MAX_VALUE		GENMASK_ULL(48, 0)
> 
> +/* Fixed event counter value register */
> +#define CN10K_DDRC_PERF_CNT_VALUE_WR_OP		0x80D0
> +#define CN10K_DDRC_PERF_CNT_VALUE_RD_OP		0x80D8
> +
> +enum mrvl_ddr_pmu_version {
> +	DDR_PMU_V1 = 1,
> +};
> +
> +struct ddr_pmu_data {
> +	int id;
> +};
> +
>  struct cn10k_ddr_pmu {
>  	struct pmu pmu;
>  	void __iomem *base;
> +	const struct ddr_pmu_platform_data *p_data;
> +	int version;
>  	unsigned int cpu;
>  	struct	device *dev;
>  	int active_events;
> @@ -132,8 +145,35 @@ struct cn10k_ddr_pmu {
>  	struct hlist_node node;
>  };
> 
> +struct ddr_pmu_ops {
> +	void (*enable_read_freerun_counter)(struct cn10k_ddr_pmu *pmu,
> +					    bool enable);
> +	void (*enable_write_freerun_counter)(struct cn10k_ddr_pmu *pmu,
> +					     bool enable);
> +	void (*clear_read_freerun_counter)(struct cn10k_ddr_pmu *pmu);
> +	void (*clear_write_freerun_counter)(struct cn10k_ddr_pmu *pmu);
> +	void (*pmu_overflow_handler)(struct cn10k_ddr_pmu *pmu, int evt_idx);
> +};
> +
>  #define to_cn10k_ddr_pmu(p)	container_of(p, struct cn10k_ddr_pmu, pmu)
> 
> +struct ddr_pmu_platform_data {
> +	u64 counter_overflow_val;
> +	u64 counter_max_val;
> +	u64 ddrc_perf_cnt_base;
> +	u64 ddrc_perf_cfg_base;
> +	u64 ddrc_perf_cnt_op_mode_ctrl;
> +	u64 ddrc_perf_cnt_start_op_ctrl;
> +	u64 ddrc_perf_cnt_end_op_ctrl;
> +	u64 ddrc_perf_cnt_end_status;
> +	u64 ddrc_perf_cnt_freerun_en;
> +	u64 ddrc_perf_cnt_freerun_ctrl;
> +	u64 ddrc_perf_cnt_freerun_clr;
> +	u64 ddrc_perf_cnt_value_wr_op;
> +	u64 ddrc_perf_cnt_value_rd_op;
> +	const struct ddr_pmu_ops *ops;
> +};
> +
>  static ssize_t cn10k_ddr_pmu_event_show(struct device *dev,
>  					struct device_attribute *attr,
>  					char *page)
> @@ -189,9 +229,9 @@ static struct attribute *cn10k_ddr_perf_events_attrs[] = {
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_zqcl, EVENT_OP_IS_ZQCL),
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_wr_access, EVENT_OP_IS_ZQCS),
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_hpr_req_with_nocredit,
> -					EVENT_HPR_REQ_WITH_NOCREDIT),
> +				 EVENT_DFI_OR_HPR_REQ_NOCRED),
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_lpr_req_with_nocredit,
> -					EVENT_LPR_REQ_WITH_NOCREDIT),
> +				 EVENT_RETRY_FIFO_FULL_OR_LPR_REQ_NOCRED),
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_alloc, EVENT_BSM_ALLOC),
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_starvation, EVENT_BSM_STARVATION),
>  	CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_rd,
> @@ -266,7 +306,8 @@ static ktime_t cn10k_ddr_pmu_timer_period(void)
>  	return ms_to_ktime((u64)cn10k_ddr_pmu_poll_period_sec * USEC_PER_SEC);
>  }
> 
> -static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap)
> +static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap,
> +				     struct cn10k_ddr_pmu *ddr_pmu)
>  {
>  	switch (eventid) {
>  	case EVENT_HIF_RD_OR_WR ... EVENT_WAW_HAZARD:
> @@ -354,6 +395,8 @@ static int cn10k_ddr_perf_event_init(struct perf_event *event)
>  static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
>  					  int counter, bool enable)
>  {
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	const struct ddr_pmu_ops *ops = p_data->ops;
>  	u32 reg;
>  	u64 val;
> 
> @@ -363,7 +406,7 @@ static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
>  	}
> 
>  	if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
> -		reg = DDRC_PERF_CFG(counter);
> +		reg = DDRC_PERF_CFG(p_data->ddrc_perf_cfg_base, counter);
>  		val = readq_relaxed(pmu->base + reg);
> 
>  		if (enable)
> @@ -373,19 +416,10 @@ static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
> 
>  		writeq_relaxed(val, pmu->base + reg);
>  	} else {
> -		val = readq_relaxed(pmu->base + DDRC_PERF_CNT_FREERUN_EN);
> -		if (enable) {
> -			if (counter == DDRC_PERF_READ_COUNTER_IDX)
> -				val |= DDRC_PERF_FREERUN_READ_EN;
> -			else
> -				val |= DDRC_PERF_FREERUN_WRITE_EN;
> -		} else {
> -			if (counter == DDRC_PERF_READ_COUNTER_IDX)
> -				val &= ~DDRC_PERF_FREERUN_READ_EN;
> -			else
> -				val &= ~DDRC_PERF_FREERUN_WRITE_EN;
> -		}
> -		writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_EN);
> +		if (counter == DDRC_PERF_READ_COUNTER_IDX)
> +			ops->enable_read_freerun_counter(pmu, enable);
> +		else
> +			ops->enable_write_freerun_counter(pmu, enable);
>  	}
>  }
> 
> @@ -393,13 +427,18 @@ static u64 cn10k_ddr_perf_read_counter(struct cn10k_ddr_pmu *pmu, int counter)
>  {
>  	u64 val;
> 
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +
>  	if (counter == DDRC_PERF_READ_COUNTER_IDX)
> -		return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_RD_OP);
> +		return readq_relaxed(pmu->base +
> +				     p_data->ddrc_perf_cnt_value_rd_op);
> 
>  	if (counter == DDRC_PERF_WRITE_COUNTER_IDX)
> -		return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_WR_OP);
> +		return readq_relaxed(pmu->base +
> +				     p_data->ddrc_perf_cnt_value_wr_op);
> 
> -	val = readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE(counter));
> +	val = readq_relaxed(pmu->base +
> +			    DDRC_PERF_REG(p_data->ddrc_perf_cnt_base, counter));
>  	return val;
>  }
> 
> @@ -407,6 +446,7 @@ static void cn10k_ddr_perf_event_update(struct perf_event *event)
>  {
>  	struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
>  	struct hw_perf_event *hwc = &event->hw;
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
>  	u64 prev_count, new_count, mask;
> 
>  	do {
> @@ -414,7 +454,7 @@ static void cn10k_ddr_perf_event_update(struct perf_event *event)
>  		new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
>  	} while (local64_xchg(&hwc->prev_count, new_count) != prev_count);
> 
> -	mask = DDRC_PERF_CNT_MAX_VALUE;
> +	mask = p_data->counter_max_val;
> 
>  	local64_add((new_count - prev_count) & mask, &event->count);
>  }
> @@ -435,6 +475,8 @@ static void cn10k_ddr_perf_event_start(struct perf_event *event, int flags)
>  static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
>  {
>  	struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	const struct ddr_pmu_ops *ops = p_data->ops;
>  	struct hw_perf_event *hwc = &event->hw;
>  	u8 config = event->attr.config;
>  	int counter, ret;
> @@ -454,8 +496,8 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
> 
>  	if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
>  		/* Generic counters, configure event id */
> -		reg_offset = DDRC_PERF_CFG(counter);
> -		ret = ddr_perf_get_event_bitmap(config, &val);
> +		reg_offset = DDRC_PERF_CFG(p_data->ddrc_perf_cfg_base, counter);
> +		ret = ddr_perf_get_event_bitmap(config, &val, pmu);
>  		if (ret)
>  			return ret;
> 
> @@ -463,11 +505,9 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
>  	} else {
>  		/* fixed event counter, clear counter value */
>  		if (counter == DDRC_PERF_READ_COUNTER_IDX)
> -			val = DDRC_FREERUN_READ_CNT_CLR;
> +			ops->clear_read_freerun_counter(pmu);
>  		else
> -			val = DDRC_FREERUN_WRITE_CNT_CLR;
> -
> -		writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_CTRL);
> +			ops->clear_write_freerun_counter(pmu);
>  	}
> 
>  	hwc->state |= PERF_HES_STOPPED;
> @@ -512,17 +552,19 @@ static void cn10k_ddr_perf_event_del(struct perf_event *event, int flags)
>  static void cn10k_ddr_perf_pmu_enable(struct pmu *pmu)
>  {
>  	struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
> +	const struct ddr_pmu_platform_data *p_data = ddr_pmu->p_data;
> 
>  	writeq_relaxed(START_OP_CTRL_VAL_START, ddr_pmu->base +
> -		       DDRC_PERF_CNT_START_OP_CTRL);
> +		       p_data->ddrc_perf_cnt_start_op_ctrl);
>  }
> 
>  static void cn10k_ddr_perf_pmu_disable(struct pmu *pmu)
>  {
>  	struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
> +	const struct ddr_pmu_platform_data *p_data = ddr_pmu->p_data;
> 
>  	writeq_relaxed(END_OP_CTRL_VAL_END, ddr_pmu->base +
> -		       DDRC_PERF_CNT_END_OP_CTRL);
> +		       p_data->ddrc_perf_cnt_end_op_ctrl);
>  }
> 
>  static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu)
> @@ -547,8 +589,63 @@ static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu)
>  	}
>  }
> 
> +static void ddr_pmu_enable_read_freerun(struct cn10k_ddr_pmu *pmu, bool enable)
> +{
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	u64 val;
> +
> +	val = readq_relaxed(pmu->base + p_data->ddrc_perf_cnt_freerun_en);
> +	if (enable)
> +		val |= DDRC_PERF_FREERUN_READ_EN;
> +	else
> +		val &= ~DDRC_PERF_FREERUN_READ_EN;
> +
> +	writeq_relaxed(val, pmu->base +	p_data->ddrc_perf_cnt_freerun_en);
> +}
> +
> +static void ddr_pmu_enable_write_freerun(struct cn10k_ddr_pmu *pmu, bool enable)
> +{
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	u64 val;
> +
> +	val = readq_relaxed(pmu->base + p_data->ddrc_perf_cnt_freerun_en);
> +	if (enable)
> +		val |= DDRC_PERF_FREERUN_WRITE_EN;
> +	else
> +		val &= ~DDRC_PERF_FREERUN_WRITE_EN;
> +
> +	writeq_relaxed(val, pmu->base +	p_data->ddrc_perf_cnt_freerun_en);
> +}
> +
> +static void ddr_pmu_read_clear_freerun(struct cn10k_ddr_pmu *pmu)
> +{
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	u64 val;
> +
> +	val = DDRC_FREERUN_READ_CNT_CLR;
> +	writeq_relaxed(val, pmu->base + p_data->ddrc_perf_cnt_freerun_ctrl);
> +}
> +
> +static void ddr_pmu_write_clear_freerun(struct cn10k_ddr_pmu *pmu)
> +{
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	u64 val;
> +
> +	val = DDRC_FREERUN_WRITE_CNT_CLR;
> +	writeq_relaxed(val, pmu->base + p_data->ddrc_perf_cnt_freerun_ctrl);
> +}
> +
> +static void ddr_pmu_overflow_hander(struct cn10k_ddr_pmu *pmu, int evt_idx)
> +{
> +	cn10k_ddr_perf_event_update_all(pmu);
> +	cn10k_ddr_perf_pmu_disable(&pmu->pmu);
> +	cn10k_ddr_perf_pmu_enable(&pmu->pmu);
> +}
> +
>  static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
>  {
> +	const struct ddr_pmu_platform_data *p_data = pmu->p_data;
> +	const struct ddr_pmu_ops *ops = p_data->ops;
>  	struct perf_event *event;
>  	struct hw_perf_event *hwc;
>  	u64 prev_count, new_count;
> @@ -586,11 +683,9 @@ static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
>  			continue;
> 
>  		value = cn10k_ddr_perf_read_counter(pmu, i);
> -		if (value == DDRC_PERF_CNT_MAX_VALUE) {
> +		if (value == p_data->counter_max_val) {
>  			pr_info("Counter-(%d) reached max value\n", i);
> -			cn10k_ddr_perf_event_update_all(pmu);
> -			cn10k_ddr_perf_pmu_disable(&pmu->pmu);
> -			cn10k_ddr_perf_pmu_enable(&pmu->pmu);
> +			ops->pmu_overflow_handler(pmu, i);
>  		}
>  	}
> 
> @@ -629,13 +724,44 @@ static int cn10k_ddr_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
>  	return 0;
>  }
> 
> +static const struct ddr_pmu_ops ddr_pmu_ops = {
> +	.enable_read_freerun_counter = ddr_pmu_enable_read_freerun,
> +	.enable_write_freerun_counter = ddr_pmu_enable_write_freerun,
> +	.clear_read_freerun_counter = ddr_pmu_read_clear_freerun,
> +	.clear_write_freerun_counter = ddr_pmu_write_clear_freerun,
> +	.pmu_overflow_handler = ddr_pmu_overflow_hander,
> +};
> +
> +static const struct ddr_pmu_platform_data cn10k_ddr_pmu_pdata = {
> +	.counter_overflow_val =  BIT_ULL(48),
> +	.counter_max_val = GENMASK_ULL(48, 0),
> +	.ddrc_perf_cnt_base = CN10K_DDRC_PERF_CNT_VALUE_BASE,
> +	.ddrc_perf_cfg_base = CN10K_DDRC_PERF_CFG_BASE,
> +	.ddrc_perf_cnt_op_mode_ctrl = CN10K_DDRC_PERF_CNT_OP_MODE_CTRL,
> +	.ddrc_perf_cnt_start_op_ctrl = CN10K_DDRC_PERF_CNT_START_OP_CTRL,
> +	.ddrc_perf_cnt_end_op_ctrl = CN10K_DDRC_PERF_CNT_END_OP_CTRL,
> +	.ddrc_perf_cnt_end_status = CN10K_DDRC_PERF_CNT_END_STATUS,
> +	.ddrc_perf_cnt_freerun_en = CN10K_DDRC_PERF_CNT_FREERUN_EN,
> +	.ddrc_perf_cnt_freerun_ctrl = CN10K_DDRC_PERF_CNT_FREERUN_CTRL,
> +	.ddrc_perf_cnt_freerun_clr = 0,
> +	.ddrc_perf_cnt_value_wr_op = CN10K_DDRC_PERF_CNT_VALUE_WR_OP,
> +	.ddrc_perf_cnt_value_rd_op = CN10K_DDRC_PERF_CNT_VALUE_RD_OP,
> +	.ops = &ddr_pmu_ops,
> +};
> +
> +static const struct ddr_pmu_data ddr_pmu_data = {
> +	.id   = DDR_PMU_V1,
> +};
> +
>  static int cn10k_ddr_perf_probe(struct platform_device *pdev)
>  {
> +	const struct ddr_pmu_data *dev_data;
>  	struct cn10k_ddr_pmu *ddr_pmu;
>  	struct resource *res;
>  	void __iomem *base;
>  	char *name;
>  	int ret;
> +	int version;
> 
>  	ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(*ddr_pmu), GFP_KERNEL);
>  	if (!ddr_pmu)
> @@ -644,30 +770,42 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
>  	ddr_pmu->dev = &pdev->dev;
>  	platform_set_drvdata(pdev, ddr_pmu);
> 
> +	dev_data = device_get_match_data(&pdev->dev);
> +	if (!dev_data) {
> +		dev_err(&pdev->dev, "Error: No device match data found\n");
> +		return -ENODEV;
> +	}
> +	version = dev_data->id;
> +	ddr_pmu->version = version;
> +
>  	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
>  	if (IS_ERR(base))
>  		return PTR_ERR(base);
> 
>  	ddr_pmu->base = base;
> 
> -	/* Setup the PMU counter to work in manual mode */
> -	writeq_relaxed(OP_MODE_CTRL_VAL_MANNUAL, ddr_pmu->base +
> -		       DDRC_PERF_CNT_OP_MODE_CTRL);
> -
> -	ddr_pmu->pmu = (struct pmu) {
> -		.module	      = THIS_MODULE,
> -		.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
> -		.task_ctx_nr = perf_invalid_context,
> -		.attr_groups = cn10k_attr_groups,
> -		.event_init  = cn10k_ddr_perf_event_init,
> -		.add	     = cn10k_ddr_perf_event_add,
> -		.del	     = cn10k_ddr_perf_event_del,
> -		.start	     = cn10k_ddr_perf_event_start,
> -		.stop	     = cn10k_ddr_perf_event_stop,
> -		.read	     = cn10k_ddr_perf_event_update,
> -		.pmu_enable  = cn10k_ddr_perf_pmu_enable,
> -		.pmu_disable = cn10k_ddr_perf_pmu_disable,
> -	};
> +	if (version == DDR_PMU_V1) {
> +		/* Setup the PMU counter to work in manual mode */
> +		writeq_relaxed(OP_MODE_CTRL_VAL_MANUAL, ddr_pmu->base +
> +			       (ddr_pmu->p_data->ddrc_perf_cnt_op_mode_ctrl));
> +
> +		ddr_pmu->pmu = (struct pmu) {
> +			.module       = THIS_MODULE,
> +			.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
> +			.task_ctx_nr = perf_invalid_context,
> +			.attr_groups = cn10k_attr_groups,
> +			.event_init  = cn10k_ddr_perf_event_init,
> +			.add         = cn10k_ddr_perf_event_add,
> +			.del         = cn10k_ddr_perf_event_del,
> +			.start       = cn10k_ddr_perf_event_start,
> +			.stop        = cn10k_ddr_perf_event_stop,
> +			.read        = cn10k_ddr_perf_event_update,
> +			.pmu_enable  = cn10k_ddr_perf_pmu_enable,
> +			.pmu_disable = cn10k_ddr_perf_pmu_disable,
> +		};
> +
> +		ddr_pmu->p_data = &cn10k_ddr_pmu_pdata;
> +	}
> 
>  	/* Choose this cpu to collect perf data */
>  	ddr_pmu->cpu = raw_smp_processor_id();
> @@ -688,7 +826,7 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto error;
> 
> -	pr_info("CN10K DDR PMU Driver for ddrc@%llx\n", res->start);
> +	pr_info("DDR PMU Driver for ddrc@%llx\n", res->start);
>  	return 0;
>  error:
>  	cpuhp_state_remove_instance_nocalls(
> @@ -711,7 +849,7 @@ static int cn10k_ddr_perf_remove(struct platform_device *pdev)
> 
>  #ifdef CONFIG_OF
>  static const struct of_device_id cn10k_ddr_pmu_of_match[] = {
> -	{ .compatible = "marvell,cn10k-ddr-pmu", },
> +	{ .compatible = "marvell,cn10k-ddr-pmu", .data = &ddr_pmu_data},
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
> @@ -719,7 +857,7 @@ MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
> 
>  #ifdef CONFIG_ACPI
>  static const struct acpi_device_id cn10k_ddr_pmu_acpi_match[] = {
> -	{"MRVL000A", 0},
> +	{"MRVL000A", (kernel_ulong_t)&ddr_pmu_data},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(acpi, cn10k_ddr_pmu_acpi_match);
> --
> 2.25.1




More information about the linux-arm-kernel mailing list