mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-22 17:30:40 +03:00
Set the floorsweeping information for IPs only if the configuration is non Hypervisor. Force enable IPs are only valid for native-Linux config. On hypervisor config, a driver is allowed to only remap addresses owned by the device node. Thus, ioremap of perfmux addresses is not allowed in hypervisor configuration. Add check to prevent force enable IPs and ioremap in hypervisor configuration. JIRA THWPM-45 Change-Id: I8fe6d3c4984c66be5a117e0cc2164ea20a5374cb Signed-off-by: vasukis <vasukis@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2674003 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> Reviewed-by: Seema Khowala <seemaj@nvidia.com> GVS: Gerrit_Virtual_Submit
263 lines
7.0 KiB
C
263 lines
7.0 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)
|
|
|
|
/* FIXME: Default timeout is 1 sec. Is this sufficient for pre-si? */
|
|
#define HWPM_TIMEOUT(timeout_check, expiry_msg) ({ \
|
|
bool timeout_expired = false; \
|
|
s32 timeout_msecs = 1000; \
|
|
u32 sleep_msecs = 100; \
|
|
while (!(timeout_check)) { \
|
|
msleep(sleep_msecs); \
|
|
timeout_msecs -= sleep_msecs; \
|
|
if (timeout_msecs <= 0) { \
|
|
tegra_hwpm_err(NULL, "Timeout expired for %s!", \
|
|
expiry_msg); \
|
|
timeout_expired = true; \
|
|
break; \
|
|
} \
|
|
} \
|
|
timeout_expired; \
|
|
})
|
|
|
|
struct hwpm_ip_aperture {
|
|
/*
|
|
* Indicates which domain (HWPM or IP) aperture belongs to,
|
|
* used for reverse mapping
|
|
*/
|
|
bool is_hwpm_element;
|
|
|
|
/* HW index : This is used to update IP fs_mask */
|
|
u32 hw_inst_mask;
|
|
|
|
/* MMIO device tree aperture - only populated for perfmon */
|
|
void __iomem *dt_mmio;
|
|
|
|
/* DT tree name */
|
|
char name[64];
|
|
|
|
/* IP ops - only populated for perfmux */
|
|
struct tegra_soc_hwpm_ip_ops ip_ops;
|
|
|
|
/* 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;
|
|
};
|
|
|
|
typedef struct hwpm_ip_aperture hwpm_ip_perfmon;
|
|
typedef struct hwpm_ip_aperture hwpm_ip_perfmux;
|
|
|
|
struct hwpm_ip {
|
|
/* Number of instances */
|
|
u32 num_instances;
|
|
|
|
/* Number of perfmons per instance */
|
|
u32 num_perfmon_per_inst;
|
|
|
|
/* Number of perfmuxes per instance */
|
|
u32 num_perfmux_per_inst;
|
|
|
|
/* IP perfmon address range */
|
|
u64 perfmon_range_start;
|
|
u64 perfmon_range_end;
|
|
|
|
/* Perfmon physical address stride for each IP instance */
|
|
u64 inst_perfmon_stride;
|
|
|
|
/*
|
|
* Perfmon slots that can fit into perfmon address range.
|
|
* This gives number of indices in ip_perfmon
|
|
*/
|
|
u32 num_perfmon_slots;
|
|
|
|
/* IP perfmon array */
|
|
hwpm_ip_perfmon **ip_perfmon;
|
|
|
|
/* IP perfmux address range */
|
|
u64 perfmux_range_start;
|
|
u64 perfmux_range_end;
|
|
|
|
/* Perfmux physical address stride for each IP instance */
|
|
u64 inst_perfmux_stride;
|
|
|
|
/*
|
|
* Perfmux slots that can fit into perfmux address range.
|
|
* This gives number of indices in ip_perfmux
|
|
*/
|
|
u32 num_perfmux_slots;
|
|
|
|
/* IP perfmux array */
|
|
hwpm_ip_perfmux **ip_perfmux;
|
|
|
|
/* 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 fs_mask;
|
|
|
|
/* IP perfmon array */
|
|
hwpm_ip_perfmon *perfmon_static_array;
|
|
|
|
/* IP perfmux array */
|
|
hwpm_ip_perfmux *perfmux_static_array;
|
|
|
|
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);
|
|
|
|
int (*extract_ip_ops)(struct tegra_soc_hwpm *hwpm,
|
|
struct tegra_soc_hwpm_ip_ops *hwpm_ip_ops, bool available);
|
|
int (*init_fs_info)(struct tegra_soc_hwpm *hwpm);
|
|
int (*get_fs_info)(struct tegra_soc_hwpm *hwpm,
|
|
u32 ip_index, 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_pma)(struct tegra_soc_hwpm *hwpm);
|
|
int (*reserve_rtr)(struct tegra_soc_hwpm *hwpm);
|
|
int (*release_pma)(struct tegra_soc_hwpm *hwpm);
|
|
int (*release_rtr)(struct tegra_soc_hwpm *hwpm);
|
|
|
|
int (*reserve_given_resource)(struct tegra_soc_hwpm *hwpm, u32 ip_idx);
|
|
int (*bind_reserved_resources)(struct tegra_soc_hwpm *hwpm);
|
|
int (*disable_triggers)(struct tegra_soc_hwpm *hwpm);
|
|
int (*release_all_resources)(struct tegra_soc_hwpm *hwpm);
|
|
|
|
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_aperture *aperture);
|
|
int (*get_alist_size)(struct tegra_soc_hwpm *hwpm);
|
|
int (*combine_alist)(struct tegra_soc_hwpm *hwpm, u64 *alist);
|
|
bool (*check_alist)(struct tegra_soc_hwpm *hwpm,
|
|
struct hwpm_ip_aperture *aperture, u64 phys_addr);
|
|
|
|
int (*exec_reg_ops)(struct tegra_soc_hwpm *hwpm,
|
|
struct tegra_soc_hwpm_reg_op *reg_op);
|
|
|
|
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 */
|