mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-22 17:30:40 +03:00
Enum tegra_soc_hwpm_ip is defined to query IP information. To untangle its use from HWPM related functionality, enum tegra_soc_hwpm_resource should be used by IP drivers to register with HWPM. An IP can have multiple instances with multiple IP core elements in each instance. Currently, the IP <-> HWPM register access API passes register offset only. However, it is not possible to figure out requested specific register access only with register offset. For example, MC device has one instance with 16 duplicate channels. To access channel x perfmux register, HWPM driver should pass perfmux register offset alongwith channel number (index). Add instance element index as an argument to the register access API, tegra_soc_hwpm_ip_ops.hwpm_ip_reg_op(). -Update internal copy of tegra_soc_hwpm_ip_ops. -Update hwpm_ip_reg_op() implemented in flcn driver. -Update hwpm_ip_reg_op() implemented in pva driver. Update hwpm_ip_pm() in flcn driver to use nvhost power management APIs. Bug 3573882 Jira THWPM-8 Change-Id: I0138927f383e9a67085816132ce33538bd609560 Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2713274 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> Reviewed-by: Vasuki Shankar <vasukis@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Seema Khowala <seemaj@nvidia.com> GVS: Gerrit_Virtual_Submit
403 lines
11 KiB
C
403 lines
11 KiB
C
/*
|
|
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope 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.
|
|
*/
|
|
|
|
#ifndef TEGRA_HWPM_H
|
|
#define TEGRA_HWPM_H
|
|
|
|
#include <linux/platform_device.h>
|
|
#include <linux/device.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/delay.h>
|
|
#include <soc/tegra/fuse.h>
|
|
|
|
#include <uapi/linux/tegra-soc-hwpm-uapi.h>
|
|
|
|
#undef BIT
|
|
#define BIT(x) (0x1U << (u32)(x))
|
|
|
|
#undef ARRAY_SIZE
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
|
|
#define TEGRA_SOC_HWPM_IP_INACTIVE ~(0U)
|
|
|
|
struct hwpm_ip_register_list {
|
|
struct tegra_soc_hwpm_ip_ops ip_ops;
|
|
struct hwpm_ip_register_list *next;
|
|
};
|
|
extern struct hwpm_ip_register_list *ip_register_list_head;
|
|
|
|
/*
|
|
* This structure is copy of struct tegra_soc_hwpm_ip_ops uapi structure.
|
|
* This is not a hard requirement as tegra_hwpm_validate_ip_ops conversion
|
|
* function.
|
|
*/
|
|
struct tegra_hwpm_ip_ops {
|
|
/*
|
|
* Opaque ip device handle used for callback from
|
|
* SOC HWPM driver to IP drivers. This handle can be used
|
|
* to access IP driver functionality with the callbacks.
|
|
*/
|
|
void *ip_dev;
|
|
/*
|
|
* hwpm_ip_pm is callback function to disable/enable
|
|
* IP driver power management. Before SOC HWPM doing
|
|
* perf measuremnts, this callback is called with
|
|
* "disable = true ", so that IP driver will disable IP specific
|
|
* power management to keep IP driver responsive. Once SOC HWPM is
|
|
* done with perf measurement, this callaback is called
|
|
* with "disable = false", so that IP driver can restore back
|
|
* it's orignal power management.
|
|
*/
|
|
int (*hwpm_ip_pm)(void *dev, bool disable);
|
|
/*
|
|
* hwpm_ip_reg_op is callback function to do IP
|
|
* register 32 bit read or write.
|
|
* For read:
|
|
* input : dev - IP device handle
|
|
* input : reg_op - TEGRA_SOC_HWPM_IP_REG_OP_READ
|
|
* input : inst_element_index - element index within IP instance
|
|
* input : reg_offset - register offset
|
|
* output: reg_data - u32 read value
|
|
* For write:
|
|
* input : dev - IP device handle
|
|
* input : reg_op - TEGRA_SOC_HWPM_IP_REG_OP_WRITE
|
|
* input : inst_element_index - element index within IP instance
|
|
* input : reg_offset - register offset
|
|
* output: reg_data - u32 write value
|
|
* Return:
|
|
* reg_op success / failure
|
|
*/
|
|
int (*hwpm_ip_reg_op)(void *dev,
|
|
enum tegra_soc_hwpm_ip_reg_op reg_op,
|
|
u32 inst_element_index, u64 reg_offset,
|
|
u32 *reg_data);
|
|
};
|
|
|
|
/* There are 3 types of HWPM components/apertures */
|
|
#define TEGRA_HWPM_APERTURE_TYPE_PERFMUX 0U
|
|
#define TEGRA_HWPM_APERTURE_TYPE_BROADCAST 1U
|
|
#define TEGRA_HWPM_APERTURE_TYPE_PERFMON 2U
|
|
#define TEGRA_HWPM_APERTURE_TYPE_MAX 3U
|
|
|
|
/*
|
|
* Devices handled by HWPM driver can be divided into 2 categories
|
|
* - HWPM : Components in HWPM device address space
|
|
* All perfmons, PMA and RTR perfmuxes
|
|
* - IP : Components in IP address space
|
|
* IP perfmuxes
|
|
*
|
|
* This enum defines MACROS to specify an element to be HWPM or IP
|
|
* and the specific aperture.
|
|
*/
|
|
enum tegra_hwpm_element_type {
|
|
HWPM_ELEMENT_INVALID,
|
|
HWPM_ELEMENT_PERFMON,
|
|
HWPM_ELEMENT_PERFMUX,
|
|
IP_ELEMENT_PERFMUX,
|
|
IP_ELEMENT_BROADCAST,
|
|
};
|
|
|
|
enum tegra_hwpm_funcs {
|
|
TEGRA_HWPM_INIT_IP_STRUCTURES,
|
|
TEGRA_HWPM_MATCH_BASE_ADDRESS,
|
|
TEGRA_HWPM_GET_ALIST_SIZE,
|
|
TEGRA_HWPM_COMBINE_ALIST,
|
|
TEGRA_HWPM_RESERVE_GIVEN_RESOURCE,
|
|
TEGRA_HWPM_BIND_RESOURCES,
|
|
TEGRA_HWPM_FIND_GIVEN_ADDRESS,
|
|
TEGRA_HWPM_RELEASE_RESOURCES,
|
|
TEGRA_HWPM_RELEASE_ROUTER,
|
|
TEGRA_HWPM_RELEASE_IP_STRUCTURES
|
|
};
|
|
|
|
struct tegra_hwpm_func_args {
|
|
u64 *alist;
|
|
u64 full_alist_idx;
|
|
};
|
|
|
|
struct allowlist {
|
|
u64 reg_offset;
|
|
bool zero_at_init;
|
|
};
|
|
|
|
struct hwpm_ip_aperture {
|
|
/*
|
|
* Indicates which domain (HWPM or IP) aperture belongs to,
|
|
* used for reverse mapping
|
|
*/
|
|
enum tegra_hwpm_element_type element_type;
|
|
|
|
/*
|
|
* Element index : Index of this aperture within the instance
|
|
* This will be used to update element_fs_mask to indicate availability.
|
|
*/
|
|
u32 element_index_mask;
|
|
|
|
/*
|
|
* Element index in device tree entry
|
|
* For perfmux entries, this index is passed to hwpm_ip_reg_op()
|
|
*/
|
|
u32 dt_index;
|
|
|
|
/* MMIO device tree aperture - only populated for perfmon */
|
|
void __iomem *dt_mmio;
|
|
|
|
/* DT tree name */
|
|
char name[64];
|
|
|
|
/* Allowlist */
|
|
struct allowlist *alist;
|
|
u64 alist_size;
|
|
|
|
/* Physical aperture */
|
|
u64 start_abs_pa;
|
|
u64 end_abs_pa;
|
|
|
|
/* MMIO aperture */
|
|
u64 start_pa;
|
|
u64 end_pa;
|
|
|
|
/* Base address: used to calculate register offset */
|
|
u64 base_pa;
|
|
|
|
/* Fake registers for VDK which doesn't have a SOC HWPM fmodel */
|
|
u32 *fake_registers;
|
|
};
|
|
|
|
struct hwpm_ip_element_info {
|
|
/* Number of elements per instance */
|
|
u32 num_element_per_inst;
|
|
|
|
/*
|
|
* Static elements in this instance corresponding to aperture
|
|
* Array size: num_element_per_inst
|
|
*/
|
|
struct hwpm_ip_aperture *element_static_array;
|
|
|
|
/*
|
|
* Ascending instance address range corresponding to elements
|
|
* NOTE: It is possible that address range of elements in the instance
|
|
* are not in same sequential order as their indexes.
|
|
* For example, 0th element of an instance can have start address higher
|
|
* than element 1. In this case, range_start and range_end should be
|
|
* initialized in increasing order.
|
|
*/
|
|
u64 range_start;
|
|
u64 range_end;
|
|
|
|
/* Element physical address stride for each element of IP instance */
|
|
u64 element_stride;
|
|
|
|
/*
|
|
* Elements that can fit into instance address range.
|
|
* This gives number of indices in element_arr
|
|
*/
|
|
u32 element_slots;
|
|
|
|
/*
|
|
* Dynamic elements array corresponding to this element
|
|
* Array size: element_slots pointers
|
|
*/
|
|
struct hwpm_ip_aperture **element_arr;
|
|
};
|
|
|
|
struct hwpm_ip_inst {
|
|
/*
|
|
* HW inst index : HW instance index of this instance
|
|
* This mask builds hwpm_ip.inst_fs_mask indicating availability.
|
|
*/
|
|
u32 hw_inst_mask;
|
|
|
|
/* Element details specific to this instance */
|
|
struct hwpm_ip_element_info element_info[TEGRA_HWPM_APERTURE_TYPE_MAX];
|
|
|
|
/*
|
|
* IP ops are specific for an instance, used for perfmux and broadcast
|
|
* register accesses.
|
|
*/
|
|
struct tegra_hwpm_ip_ops ip_ops;
|
|
|
|
/*
|
|
* An IP contains perfmux-perfmon groups that correspond to each other.
|
|
* If a perfmux is present, it indicates that the corresponding
|
|
* perfmon is present.
|
|
* This mask is usually updated based on available perfmuxes.
|
|
* (except for SCF).
|
|
*/
|
|
u32 element_fs_mask;
|
|
};
|
|
|
|
struct hwpm_ip_inst_per_aperture_info {
|
|
/*
|
|
* Ascending IP address range corresponding to instances
|
|
* NOTE: It is possible that address range of IP instances
|
|
* are not in same sequential order as their indexes.
|
|
* For example, 0th instance of an IP can have start address higher
|
|
* than instance 1. In this case, range_start and range_end should be
|
|
* initialized in increasing order.
|
|
*/
|
|
u64 range_start;
|
|
u64 range_end;
|
|
|
|
/* Aperture address range for each IP instance */
|
|
u64 inst_stride;
|
|
|
|
/*
|
|
* Aperture instances that can fit into IP aperture address range.
|
|
* This gives number of entries in inst_arr
|
|
*/
|
|
u32 inst_slots;
|
|
|
|
/* IP inst aperture array */
|
|
struct hwpm_ip_inst **inst_arr;
|
|
};
|
|
|
|
struct hwpm_ip {
|
|
/* Number of instances */
|
|
u32 num_instances;
|
|
|
|
/* Static array of IP instances */
|
|
struct hwpm_ip_inst *ip_inst_static_array;
|
|
|
|
/* Instance info corresponding to apertures in this IP */
|
|
struct hwpm_ip_inst_per_aperture_info inst_aperture_info[
|
|
TEGRA_HWPM_APERTURE_TYPE_MAX];
|
|
|
|
/* Override IP config based on fuse value */
|
|
bool override_enable;
|
|
|
|
/*
|
|
* IP floorsweep info based on hw index of aperture
|
|
* NOTE: This mask needs to based on hw instance index because
|
|
* hwpm driver clients use hw instance index to find aperture
|
|
* info (start/end address) from hw manual.
|
|
*/
|
|
u32 inst_fs_mask;
|
|
|
|
bool reserved;
|
|
};
|
|
|
|
struct tegra_soc_hwpm;
|
|
|
|
struct tegra_soc_hwpm_chip {
|
|
/* Array of pointers to active IP structures */
|
|
struct hwpm_ip **chip_ips;
|
|
|
|
/* Chip HALs */
|
|
bool (*is_ip_active)(struct tegra_soc_hwpm *hwpm,
|
|
u32 ip_index, u32 *config_ip_index);
|
|
bool (*is_resource_active)(struct tegra_soc_hwpm *hwpm,
|
|
u32 res_index, u32 *config_ip_index);
|
|
|
|
u32 (*get_rtr_int_idx)(struct tegra_soc_hwpm *hwpm);
|
|
u32 (*get_ip_max_idx)(struct tegra_soc_hwpm *hwpm);
|
|
|
|
int (*extract_ip_ops)(struct tegra_soc_hwpm *hwpm,
|
|
struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops, bool available);
|
|
int (*force_enable_ips)(struct tegra_soc_hwpm *hwpm);
|
|
int (*get_fs_info)(struct tegra_soc_hwpm *hwpm,
|
|
u32 ip_enum, u64 *fs_mask, u8 *ip_status);
|
|
|
|
int (*init_prod_values)(struct tegra_soc_hwpm *hwpm);
|
|
int (*disable_slcg)(struct tegra_soc_hwpm *hwpm);
|
|
int (*enable_slcg)(struct tegra_soc_hwpm *hwpm);
|
|
|
|
int (*reserve_rtr)(struct tegra_soc_hwpm *hwpm);
|
|
int (*release_rtr)(struct tegra_soc_hwpm *hwpm);
|
|
|
|
int (*disable_triggers)(struct tegra_soc_hwpm *hwpm);
|
|
int (*perfmon_enable)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_aperture *perfmon);
|
|
int (*perfmon_disable)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_aperture *perfmon);
|
|
int (*perfmux_disable)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_aperture *perfmux);
|
|
|
|
int (*disable_mem_mgmt)(struct tegra_soc_hwpm *hwpm);
|
|
int (*enable_mem_mgmt)(struct tegra_soc_hwpm *hwpm,
|
|
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream);
|
|
int (*invalidate_mem_config)(struct tegra_soc_hwpm *hwpm);
|
|
int (*stream_mem_bytes)(struct tegra_soc_hwpm *hwpm);
|
|
int (*disable_pma_streaming)(struct tegra_soc_hwpm *hwpm);
|
|
int (*update_mem_bytes_get_ptr)(struct tegra_soc_hwpm *hwpm,
|
|
u64 mem_bump);
|
|
u64 (*get_mem_bytes_put_ptr)(struct tegra_soc_hwpm *hwpm);
|
|
bool (*membuf_overflow_status)(struct tegra_soc_hwpm *hwpm);
|
|
|
|
size_t (*get_alist_buf_size)(struct tegra_soc_hwpm *hwpm);
|
|
int (*zero_alist_regs)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_inst *ip_inst,
|
|
struct hwpm_ip_aperture *aperture);
|
|
int (*copy_alist)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_aperture *aperture,
|
|
u64 *full_alist,
|
|
u64 *full_alist_idx);
|
|
bool (*check_alist)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_aperture *aperture, u64 phys_addr);
|
|
|
|
void (*release_sw_setup)(struct tegra_soc_hwpm *hwpm);
|
|
};
|
|
|
|
struct allowlist;
|
|
extern struct platform_device *tegra_soc_hwpm_pdev;
|
|
extern const struct file_operations tegra_soc_hwpm_ops;
|
|
|
|
/* Driver struct */
|
|
struct tegra_soc_hwpm {
|
|
/* Device */
|
|
struct platform_device *pdev;
|
|
struct device *dev;
|
|
struct device_node *np;
|
|
struct class class;
|
|
dev_t dev_t;
|
|
struct cdev cdev;
|
|
|
|
/* Device info */
|
|
struct tegra_soc_hwpm_device_info device_info;
|
|
|
|
/* Active chip info */
|
|
struct tegra_soc_hwpm_chip *active_chip;
|
|
|
|
/* Clocks and resets */
|
|
struct clk *la_clk;
|
|
struct clk *la_parent_clk;
|
|
struct reset_control *la_rst;
|
|
struct reset_control *hwpm_rst;
|
|
|
|
/* Memory Management */
|
|
struct dma_buf *stream_dma_buf;
|
|
struct dma_buf_attachment *stream_attach;
|
|
struct sg_table *stream_sgt;
|
|
struct dma_buf *mem_bytes_dma_buf;
|
|
struct dma_buf_attachment *mem_bytes_attach;
|
|
struct sg_table *mem_bytes_sgt;
|
|
void *mem_bytes_kernel;
|
|
|
|
/* SW State */
|
|
bool bind_completed;
|
|
bool device_opened;
|
|
u64 full_alist_size;
|
|
|
|
atomic_t hwpm_in_use;
|
|
|
|
u32 dbg_mask;
|
|
|
|
/* Debugging */
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct dentry *debugfs_root;
|
|
#endif
|
|
bool fake_registers_enabled;
|
|
};
|
|
|
|
#endif /* TEGRA_HWPM_H */
|