/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
 *
 * (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 */

/*
 * Virtual interface for CSF hardware counter backend.
 */

#ifndef _KBASE_HWCNT_BACKEND_CSF_IF_H_
#define _KBASE_HWCNT_BACKEND_CSF_IF_H_

#include <linux/types.h>

struct kbase_hwcnt_backend_csf_if_ctx;

struct kbase_hwcnt_backend_csf_if_ring_buf;

/**
 * struct kbase_hwcnt_backend_csf_if_enable - enable hardware counter collection
 *                                            structure.
 * @fe_bm:          Front End counters selection bitmask.
 * @shader_bm:      Shader counters selection bitmask.
 * @tiler_bm:       Tiler counters selection bitmask.
 * @mmu_l2_bm:      MMU_L2 counters selection bitmask.
 * @fw_bm:          FW counters selection bitmask
 * @csg_bm:         FW CSG counters selection bitmask.
 * @counter_set:    The performance counter set to enable.
 * @clk_enable_map: An array of u64 bitfields, each bit of which enables cycle
 *                  counter for a given clock domain.
 */
struct kbase_hwcnt_backend_csf_if_enable {
	u32 fe_bm;
	u32 shader_bm;
	u32 tiler_bm;
	u32 mmu_l2_bm;
	u32 fw_bm;
	u32 csg_bm;
	u8 counter_set;
	u64 clk_enable_map;
};

/**
 * struct kbase_hwcnt_backend_csf_if_prfcnt_info - Performance counter
 *                                                 information.
 * @prfcnt_hw_size:    Total length in bytes of all the hardware counters data. The hardware
 *                     counters are sub-divided into 4 classes: front-end, shader, tiler, and
 *                     memory system (l2 cache + MMU).
 * @prfcnt_fw_size:    Total length in bytes of all the firmware counters data.
 * @dump_bytes:        Bytes of GPU memory required to perform a performance
 *                     counter dump. dump_bytes = prfcnt_hw_size + prfcnt_fw_size.
 * @prfcnt_block_size: Bytes of each performance counter block.
 * @l2_count:          The MMU L2 cache count.
 * @csg_count:         The total number of CSGs in the system
 * @sc_core_mask:         Shader core mask.
 * @clk_cnt:           Clock domain count in the system.
 * @clearing_samples:  Indicates whether counters are cleared after each sample
 *                     is taken.
 */
struct kbase_hwcnt_backend_csf_if_prfcnt_info {
	size_t prfcnt_hw_size;
	size_t prfcnt_fw_size;
	size_t dump_bytes;
	size_t prfcnt_block_size;
	size_t l2_count;
	u32 csg_count;
	u64 sc_core_mask;
	u8 clk_cnt;
	bool clearing_samples;
};

/**
 * typedef kbase_hwcnt_backend_csf_if_assert_lock_held_fn - Assert that the
 *                                                          backend spinlock is
 *                                                          held.
 * @ctx: Non-NULL pointer to a CSF context.
 */
typedef void (*kbase_hwcnt_backend_csf_if_assert_lock_held_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx);

/**
 * typedef kbase_hwcnt_backend_csf_if_lock_fn - Acquire backend spinlock.
 *
 * @ctx:   Non-NULL pointer to a CSF context.
 * @flags: Pointer to the memory location that would store the previous
 *         interrupt state.
 */
typedef void (*kbase_hwcnt_backend_csf_if_lock_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx,
						   unsigned long *flags);

/**
 * typedef kbase_hwcnt_backend_csf_if_unlock_fn - Release backend spinlock.
 *
 * @ctx:   Non-NULL pointer to a CSF context.
 * @flags: Previously stored interrupt state when Scheduler interrupt
 *         spinlock was acquired.
 */
typedef void (*kbase_hwcnt_backend_csf_if_unlock_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx,
						     unsigned long flags);

/**
 * typedef kbase_hwcnt_backend_csf_if_acquire_fn - Enable counter collection.
 *
 * @ctx:   Non-NULL pointer to a CSF context.
 */
typedef void (*kbase_hwcnt_backend_csf_if_acquire_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx);

/**
 * typedef kbase_hwcnt_backend_csf_if_release_fn - Disable counter collection.
 *
 * @ctx:   Non-NULL pointer to a CSF context.
 */
typedef void (*kbase_hwcnt_backend_csf_if_release_fn)(struct kbase_hwcnt_backend_csf_if_ctx *ctx);

/**
 * typedef kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn - Get performance
 *                                                         counter information.
 * @ctx:          Non-NULL pointer to a CSF context.
 * @prfcnt_info:  Non-NULL pointer to struct where performance counter
 *                information should be stored.
 */
typedef void (*kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx,
	struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info);

/**
 * typedef kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn - Allocate a ring buffer
 *                                                        for CSF interface.
 * @ctx:           Non-NULL pointer to a CSF context.
 * @buf_count:     The buffer count in the ring buffer to be allocated,
 *                 MUST be power of 2.
 * @cpu_dump_base: Non-NULL pointer to where ring buffer CPU base address is
 *                 stored when success.
 * @ring_buf:      Non-NULL pointer to where ring buffer is stored when success.
 *
 * A ring buffer is needed by the CSF interface to do manual HWC sample and
 * automatic HWC samples, the buffer count in the ring buffer MUST be power
 * of 2 to meet the hardware requirement.
 *
 * Return: 0 on success, else error code.
 */
typedef int (*kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 buf_count, void **cpu_dump_base,
	struct kbase_hwcnt_backend_csf_if_ring_buf **ring_buf);

/**
 * typedef kbase_hwcnt_backend_csf_if_ring_buf_sync_fn - Sync HWC dump buffers
 *                                                       memory.
 * @ctx:             Non-NULL pointer to a CSF context.
 * @ring_buf:        Non-NULL pointer to the ring buffer.
 * @buf_index_first: The first buffer index in the ring buffer to be synced,
 *                   inclusive.
 * @buf_index_last:  The last buffer index in the ring buffer to be synced,
 *                   exclusive.
 * @for_cpu:         The direction of sync to be applied, set to true when CPU
 *                   cache needs invalidating before reading the buffer, and set
 *                   to false after CPU writes to flush these before this memory
 *                   is overwritten by the GPU.
 *
 * Flush cached HWC dump buffer data to ensure that all writes from GPU and CPU
 * are correctly observed.
 */
typedef void (*kbase_hwcnt_backend_csf_if_ring_buf_sync_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx,
	struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, u32 buf_index_first,
	u32 buf_index_last, bool for_cpu);

/**
 * typedef kbase_hwcnt_backend_csf_if_ring_buf_free_fn - Free a ring buffer for
 *                                                       the CSF interface.
 *
 * @ctx:      Non-NULL pointer to a CSF interface context.
 * @ring_buf: Non-NULL pointer to the ring buffer which to be freed.
 */
typedef void (*kbase_hwcnt_backend_csf_if_ring_buf_free_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx,
	struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf);

/**
 * typedef kbase_hwcnt_backend_csf_if_timestamp_ns_fn - Get the current
 *                                                      timestamp of the CSF
 *                                                      interface.
 * @ctx: Non-NULL pointer to a CSF interface context.
 *
 * Return: CSF interface timestamp in nanoseconds.
 */
typedef u64 (*kbase_hwcnt_backend_csf_if_timestamp_ns_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx);

/**
 * typedef kbase_hwcnt_backend_csf_if_dump_enable_fn - Setup and enable hardware
 *                                                     counter in CSF interface.
 * @ctx:      Non-NULL pointer to a CSF interface context.
 * @ring_buf: Non-NULL pointer to the ring buffer which used to setup the HWC.
 * @enable:   Non-NULL pointer to the enable map of HWC.
 *
 * Requires lock to be taken before calling.
 */
typedef void (*kbase_hwcnt_backend_csf_if_dump_enable_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx,
	struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf,
	struct kbase_hwcnt_backend_csf_if_enable *enable);

/**
 * typedef kbase_hwcnt_backend_csf_if_dump_disable_fn - Disable hardware counter
 *                                                      in CSF interface.
 * @ctx: Non-NULL pointer to a CSF interface context.
 *
 * Requires lock to be taken before calling.
 */
typedef void (*kbase_hwcnt_backend_csf_if_dump_disable_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx);

/**
 * typedef kbase_hwcnt_backend_csf_if_dump_request_fn - Request a HWC dump.
 *
 * @ctx: Non-NULL pointer to the interface context.
 *
 * Requires lock to be taken before calling.
 */
typedef void (*kbase_hwcnt_backend_csf_if_dump_request_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx);

/**
 * typedef kbase_hwcnt_backend_csf_if_get_indexes_fn - Get current extract and
 *                                                     insert indexes of the
 *                                                     ring buffer.
 *
 * @ctx:           Non-NULL pointer to a CSF interface context.
 * @extract_index: Non-NULL pointer where current extract index to be saved.
 * @insert_index:  Non-NULL pointer where current insert index to be saved.
 *
 * Requires lock to be taken before calling.
 */
typedef void (*kbase_hwcnt_backend_csf_if_get_indexes_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 *extract_index, u32 *insert_index);

/**
 * typedef kbase_hwcnt_backend_csf_if_set_extract_index_fn - Update the extract
 *                                                           index of the ring
 *                                                           buffer.
 *
 * @ctx:            Non-NULL pointer to a CSF interface context.
 * @extract_index:  New extract index to be set.
 *
 * Requires lock to be taken before calling.
 */
typedef void (*kbase_hwcnt_backend_csf_if_set_extract_index_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 extract_index);

/**
 * typedef kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn - Get the current
 *                                                             GPU cycle count.
 * @ctx:            Non-NULL pointer to a CSF interface context.
 * @cycle_counts:   Non-NULL pointer to an array where cycle counts to be saved,
 *                  the array size should be at least as big as the number of
 *                  clock domains returned by get_prfcnt_info interface.
 * @clk_enable_map: An array of bitfields, each bit specifies an enabled clock
 *                  domain.
 *
 * Requires lock to be taken before calling.
 */
typedef void (*kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx, u64 *cycle_counts, u64 clk_enable_map);

/**
 * typedef kbase_hwcnt_backend_csf_if_time_convert_gpu_to_cpu_fn - Convert GPU timestamp
 *                                                                    to CPU MONOTONIC time.
 * @ctx:            Non-NULL pointer to a CSF interface context.
 * @gpu_ts:         GPU timestamp.
 *
 * Return: The CPU timestamp.
 */
typedef u64 (*kbase_hwcnt_backend_csf_if_time_convert_gpu_to_cpu_fn)(
	struct kbase_hwcnt_backend_csf_if_ctx *ctx, u64 gpu_ts);

/**
 * struct kbase_hwcnt_backend_csf_if - Hardware counter backend CSF virtual
 *                                     interface.
 * @ctx:                 CSF interface context.
 * @assert_lock_held:    Function ptr to assert backend spinlock is held.
 * @lock:                Function ptr to acquire backend spinlock.
 * @unlock:              Function ptr to release backend spinlock.
 * @acquire:             Callback to indicate that counter collection has
 *                       been enabled.
 * @release:             Callback to indicate that counter collection has
 *                       been disabled.
 * @get_prfcnt_info:     Function ptr to get performance counter related
 *                       information.
 * @ring_buf_alloc:      Function ptr to allocate ring buffer for CSF HWC.
 * @ring_buf_sync:       Function ptr to sync ring buffer to CPU.
 * @ring_buf_free:       Function ptr to free ring buffer for CSF HWC.
 * @timestamp_ns:        Function ptr to get the current CSF interface
 *                       timestamp.
 * @dump_enable:         Function ptr to enable dumping.
 * @dump_disable:        Function ptr to disable dumping.
 * @dump_request:        Function ptr to request a dump.
 * @get_indexes:         Function ptr to get extract and insert indexes of the
 *                       ring buffer.
 * @set_extract_index:   Function ptr to set extract index of ring buffer.
 * @get_gpu_cycle_count: Function ptr to get the GPU cycle count.
 * @time_convert_gpu_to_cpu: Function ptr to convert GPU to CPU timestamp.
 */
struct kbase_hwcnt_backend_csf_if {
	struct kbase_hwcnt_backend_csf_if_ctx *ctx;
	kbase_hwcnt_backend_csf_if_assert_lock_held_fn assert_lock_held;
	kbase_hwcnt_backend_csf_if_lock_fn lock;
	kbase_hwcnt_backend_csf_if_unlock_fn unlock;
	kbase_hwcnt_backend_csf_if_acquire_fn acquire;
	kbase_hwcnt_backend_csf_if_release_fn release;
	kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn get_prfcnt_info;
	kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn ring_buf_alloc;
	kbase_hwcnt_backend_csf_if_ring_buf_sync_fn ring_buf_sync;
	kbase_hwcnt_backend_csf_if_ring_buf_free_fn ring_buf_free;
	kbase_hwcnt_backend_csf_if_timestamp_ns_fn timestamp_ns;
	kbase_hwcnt_backend_csf_if_dump_enable_fn dump_enable;
	kbase_hwcnt_backend_csf_if_dump_disable_fn dump_disable;
	kbase_hwcnt_backend_csf_if_dump_request_fn dump_request;
	kbase_hwcnt_backend_csf_if_get_indexes_fn get_indexes;
	kbase_hwcnt_backend_csf_if_set_extract_index_fn set_extract_index;
	kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn get_gpu_cycle_count;
	kbase_hwcnt_backend_csf_if_time_convert_gpu_to_cpu_fn time_convert_gpu_to_cpu;
};

#endif /* #define _KBASE_HWCNT_BACKEND_CSF_IF_H_ */
