162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2020-2023 Intel Corporation
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef __IVPU_DRV_H__
762306a36Sopenharmony_ci#define __IVPU_DRV_H__
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <drm/drm_device.h>
1062306a36Sopenharmony_ci#include <drm/drm_drv.h>
1162306a36Sopenharmony_ci#include <drm/drm_managed.h>
1262306a36Sopenharmony_ci#include <drm/drm_mm.h>
1362306a36Sopenharmony_ci#include <drm/drm_print.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/pci.h>
1662306a36Sopenharmony_ci#include <linux/xarray.h>
1762306a36Sopenharmony_ci#include <uapi/drm/ivpu_accel.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "ivpu_mmu_context.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define DRIVER_NAME "intel_vpu"
2262306a36Sopenharmony_ci#define DRIVER_DESC "Driver for Intel Versatile Processing Unit (VPU)"
2362306a36Sopenharmony_ci#define DRIVER_DATE "20230117"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define PCI_DEVICE_ID_MTL   0x7d1d
2662306a36Sopenharmony_ci#define PCI_DEVICE_ID_ARL   0xad1d
2762306a36Sopenharmony_ci#define PCI_DEVICE_ID_LNL   0x643e
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define IVPU_HW_37XX	37
3062306a36Sopenharmony_ci#define IVPU_HW_40XX	40
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0
3362306a36Sopenharmony_ci/* SSID 1 is used by the VPU to represent invalid context */
3462306a36Sopenharmony_ci#define IVPU_USER_CONTEXT_MIN_SSID   2
3562306a36Sopenharmony_ci#define IVPU_USER_CONTEXT_MAX_SSID   (IVPU_USER_CONTEXT_MIN_SSID + 63)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define IVPU_NUM_ENGINES	     2
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define IVPU_PLATFORM_SILICON 0
4062306a36Sopenharmony_ci#define IVPU_PLATFORM_SIMICS  2
4162306a36Sopenharmony_ci#define IVPU_PLATFORM_FPGA    3
4262306a36Sopenharmony_ci#define IVPU_PLATFORM_INVALID 8
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define IVPU_DBG_REG	 BIT(0)
4562306a36Sopenharmony_ci#define IVPU_DBG_IRQ	 BIT(1)
4662306a36Sopenharmony_ci#define IVPU_DBG_MMU	 BIT(2)
4762306a36Sopenharmony_ci#define IVPU_DBG_FILE	 BIT(3)
4862306a36Sopenharmony_ci#define IVPU_DBG_MISC	 BIT(4)
4962306a36Sopenharmony_ci#define IVPU_DBG_FW_BOOT BIT(5)
5062306a36Sopenharmony_ci#define IVPU_DBG_PM	 BIT(6)
5162306a36Sopenharmony_ci#define IVPU_DBG_IPC	 BIT(7)
5262306a36Sopenharmony_ci#define IVPU_DBG_BO	 BIT(8)
5362306a36Sopenharmony_ci#define IVPU_DBG_JOB	 BIT(9)
5462306a36Sopenharmony_ci#define IVPU_DBG_JSM	 BIT(10)
5562306a36Sopenharmony_ci#define IVPU_DBG_KREF	 BIT(11)
5662306a36Sopenharmony_ci#define IVPU_DBG_RPM	 BIT(12)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define ivpu_err(vdev, fmt, ...) \
5962306a36Sopenharmony_ci	drm_err(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__)
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define ivpu_err_ratelimited(vdev, fmt, ...) \
6262306a36Sopenharmony_ci	drm_err_ratelimited(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#define ivpu_warn(vdev, fmt, ...) \
6562306a36Sopenharmony_ci	drm_warn(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__)
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define ivpu_warn_ratelimited(vdev, fmt, ...) \
6862306a36Sopenharmony_ci	drm_err_ratelimited(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__)
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define ivpu_info(vdev, fmt, ...) drm_info(&(vdev)->drm, fmt, ##__VA_ARGS__)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define ivpu_dbg(vdev, type, fmt, args...) do {                                \
7362306a36Sopenharmony_ci	if (unlikely(IVPU_DBG_##type & ivpu_dbg_mask))                         \
7462306a36Sopenharmony_ci		dev_dbg((vdev)->drm.dev, "[%s] " fmt, #type, ##args);          \
7562306a36Sopenharmony_ci} while (0)
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci#define IVPU_WA(wa_name) (vdev->wa.wa_name)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define IVPU_PRINT_WA(wa_name) do {					\
8062306a36Sopenharmony_ci	if (IVPU_WA(wa_name))						\
8162306a36Sopenharmony_ci		ivpu_dbg(vdev, MISC, "Using WA: " #wa_name "\n");	\
8262306a36Sopenharmony_ci} while (0)
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistruct ivpu_wa_table {
8562306a36Sopenharmony_ci	bool punit_disabled;
8662306a36Sopenharmony_ci	bool clear_runtime_mem;
8762306a36Sopenharmony_ci	bool d3hot_after_power_off;
8862306a36Sopenharmony_ci	bool interrupt_clear_with_0;
8962306a36Sopenharmony_ci	bool disable_clock_relinquish;
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistruct ivpu_hw_info;
9362306a36Sopenharmony_cistruct ivpu_mmu_info;
9462306a36Sopenharmony_cistruct ivpu_fw_info;
9562306a36Sopenharmony_cistruct ivpu_ipc_info;
9662306a36Sopenharmony_cistruct ivpu_pm_info;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct ivpu_device {
9962306a36Sopenharmony_ci	struct drm_device drm;
10062306a36Sopenharmony_ci	void __iomem *regb;
10162306a36Sopenharmony_ci	void __iomem *regv;
10262306a36Sopenharmony_ci	u32 platform;
10362306a36Sopenharmony_ci	u32 irq;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	struct ivpu_wa_table wa;
10662306a36Sopenharmony_ci	struct ivpu_hw_info *hw;
10762306a36Sopenharmony_ci	struct ivpu_mmu_info *mmu;
10862306a36Sopenharmony_ci	struct ivpu_fw_info *fw;
10962306a36Sopenharmony_ci	struct ivpu_ipc_info *ipc;
11062306a36Sopenharmony_ci	struct ivpu_pm_info *pm;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	struct ivpu_mmu_context gctx;
11362306a36Sopenharmony_ci	struct xarray context_xa;
11462306a36Sopenharmony_ci	struct xa_limit context_xa_limit;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	struct xarray submitted_jobs_xa;
11762306a36Sopenharmony_ci	struct task_struct *job_done_thread;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	atomic64_t unique_id_counter;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	struct {
12262306a36Sopenharmony_ci		int boot;
12362306a36Sopenharmony_ci		int jsm;
12462306a36Sopenharmony_ci		int tdr;
12562306a36Sopenharmony_ci		int reschedule_suspend;
12662306a36Sopenharmony_ci	} timeout;
12762306a36Sopenharmony_ci};
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/*
13062306a36Sopenharmony_ci * file_priv has its own refcount (ref) that allows user space to close the fd
13162306a36Sopenharmony_ci * without blocking even if VPU is still processing some jobs.
13262306a36Sopenharmony_ci */
13362306a36Sopenharmony_cistruct ivpu_file_priv {
13462306a36Sopenharmony_ci	struct kref ref;
13562306a36Sopenharmony_ci	struct ivpu_device *vdev;
13662306a36Sopenharmony_ci	struct mutex lock; /* Protects cmdq */
13762306a36Sopenharmony_ci	struct ivpu_cmdq *cmdq[IVPU_NUM_ENGINES];
13862306a36Sopenharmony_ci	struct ivpu_mmu_context ctx;
13962306a36Sopenharmony_ci	u32 priority;
14062306a36Sopenharmony_ci	bool has_mmu_faults;
14162306a36Sopenharmony_ci};
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ciextern int ivpu_dbg_mask;
14462306a36Sopenharmony_ciextern u8 ivpu_pll_min_ratio;
14562306a36Sopenharmony_ciextern u8 ivpu_pll_max_ratio;
14662306a36Sopenharmony_ciextern bool ivpu_disable_mmu_cont_pages;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci#define IVPU_TEST_MODE_DISABLED  0
14962306a36Sopenharmony_ci#define IVPU_TEST_MODE_FW_TEST   1
15062306a36Sopenharmony_ci#define IVPU_TEST_MODE_NULL_HW   2
15162306a36Sopenharmony_ciextern int ivpu_test_mode;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistruct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv);
15462306a36Sopenharmony_cistruct ivpu_file_priv *ivpu_file_priv_get_by_ctx_id(struct ivpu_device *vdev, unsigned long id);
15562306a36Sopenharmony_civoid ivpu_file_priv_put(struct ivpu_file_priv **link);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciint ivpu_boot(struct ivpu_device *vdev);
15862306a36Sopenharmony_ciint ivpu_shutdown(struct ivpu_device *vdev);
15962306a36Sopenharmony_civoid ivpu_prepare_for_reset(struct ivpu_device *vdev);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic inline u8 ivpu_revision(struct ivpu_device *vdev)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	return to_pci_dev(vdev->drm.dev)->revision;
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic inline u16 ivpu_device_id(struct ivpu_device *vdev)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	return to_pci_dev(vdev->drm.dev)->device;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic inline int ivpu_hw_gen(struct ivpu_device *vdev)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	switch (ivpu_device_id(vdev)) {
17462306a36Sopenharmony_ci	case PCI_DEVICE_ID_MTL:
17562306a36Sopenharmony_ci	case PCI_DEVICE_ID_ARL:
17662306a36Sopenharmony_ci		return IVPU_HW_37XX;
17762306a36Sopenharmony_ci	case PCI_DEVICE_ID_LNL:
17862306a36Sopenharmony_ci		return IVPU_HW_40XX;
17962306a36Sopenharmony_ci	default:
18062306a36Sopenharmony_ci		ivpu_err(vdev, "Unknown VPU device\n");
18162306a36Sopenharmony_ci		return 0;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic inline struct ivpu_device *to_ivpu_device(struct drm_device *dev)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	return container_of(dev, struct ivpu_device, drm);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic inline u32 ivpu_get_context_count(struct ivpu_device *vdev)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	struct xa_limit ctx_limit = vdev->context_xa_limit;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	return (ctx_limit.max - ctx_limit.min + 1);
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic inline u32 ivpu_get_platform(struct ivpu_device *vdev)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	WARN_ON_ONCE(vdev->platform == IVPU_PLATFORM_INVALID);
20062306a36Sopenharmony_ci	return vdev->platform;
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic inline bool ivpu_is_silicon(struct ivpu_device *vdev)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	return ivpu_get_platform(vdev) == IVPU_PLATFORM_SILICON;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic inline bool ivpu_is_simics(struct ivpu_device *vdev)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	return ivpu_get_platform(vdev) == IVPU_PLATFORM_SIMICS;
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic inline bool ivpu_is_fpga(struct ivpu_device *vdev)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	return ivpu_get_platform(vdev) == IVPU_PLATFORM_FPGA;
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci#endif /* __IVPU_DRV_H__ */
219