/* SPDX-License-Identifier: GPL-2.0-only */


#ifndef __MSM_EP_PCIE_H
#define __MSM_EP_PCIE_H

#include <linux/types.h>

enum ep_pcie_link_status {
	EP_PCIE_LINK_DISABLED,
	EP_PCIE_LINK_UP,
	EP_PCIE_LINK_ENABLED,
	EP_PCIE_LINK_IN_L23READY,
};

enum ep_pcie_event {
	EP_PCIE_EVENT_INVALID = 0,
	EP_PCIE_EVENT_PM_D0 = 0x1,
	EP_PCIE_EVENT_PM_D3_HOT = 0x2,
	EP_PCIE_EVENT_PM_D3_COLD = 0x4,
	EP_PCIE_EVENT_PM_RST_DEAST = 0x8,
	EP_PCIE_EVENT_LINKDOWN = 0x10,
	EP_PCIE_EVENT_LINKUP = 0x20,
	EP_PCIE_EVENT_MHI_A7 = 0x40,
	EP_PCIE_EVENT_MMIO_WRITE = 0x80,
	EP_PCIE_EVENT_L1SUB_TIMEOUT = 0x100,
	EP_PCIE_EVENT_L1SUB_TIMEOUT_EXIT = 0x200,
	EP_PCIE_EVENT_LINKUP_VF = 0x400,
};

enum ep_pcie_irq_event {
	EP_PCIE_INT_EVT_LINK_DOWN = 1,
	EP_PCIE_INT_EVT_BME,
	EP_PCIE_INT_EVT_PM_TURNOFF,
	EP_PCIE_INT_EVT_DEBUG,
	EP_PCIE_INT_EVT_LTR,
	EP_PCIE_INT_EVT_MHI_Q6,
	EP_PCIE_INT_EVT_MHI_A7,
	EP_PCIE_INT_EVT_DSTATE_CHANGE,
	EP_PCIE_INT_EVT_L1SUB_TIMEOUT,
	EP_PCIE_INT_EVT_MMIO_WRITE,
	EP_PCIE_INT_EVT_CFG_WRITE,
	EP_PCIE_INT_EVT_BRIDGE_FLUSH_N,
	EP_PCIE_INT_EVT_LINK_UP,
	EP_PCIE_INT_EVT_EDMA = 22,
	EP_PCIE_INT_EVT_MAX = 13,
};

enum ep_pcie_trigger {
	EP_PCIE_TRIGGER_CALLBACK,
	EP_PCIE_TRIGGER_COMPLETION,
};

enum ep_pcie_options {
	EP_PCIE_OPT_NULL = 0,
	EP_PCIE_OPT_AST_WAKE = 0x1,
	EP_PCIE_OPT_POWER_ON = 0x2,
	EP_PCIE_OPT_ENUM = 0x4,
	EP_PCIE_OPT_ENUM_ASYNC = 0x8,
	EP_PCIE_OPT_ALL = 0xFFFFFFFF,
};

enum ep_pcie_msi_type {
	MSI = 0,
	MSIX = 0x1,
};

struct ep_pcie_notify {
	enum ep_pcie_event event;
	void *user;
	void *data;
	u32 options;
	u32 vf_id;
};

struct ep_pcie_register_event {
	u32 events;
	void *user;
	enum ep_pcie_trigger mode;
	void (*callback)(struct ep_pcie_notify *notify);
	struct ep_pcie_notify notify;
	struct completion *completion;
	u32 options;
};

struct ep_pcie_iatu {
	u64 start;
	u64 end;
	u64 tgt_lower;
	u64 tgt_upper;
};

struct ep_pcie_msi_config {
	u32 lower;
	u32 upper;
	u32 data;
	u32 msg_num;
	enum ep_pcie_msi_type msi_type;
};

struct ep_pcie_db_config {
	u8 base;
	u8 end;
	u32 tgt_addr;
};

struct ep_pcie_inactivity {
	bool enable;
	uint32_t timer_us;
};

struct ep_pcie_cap {
	bool sriov_enabled;
	bool msix_enabled;
	u32  num_vfs;
};

struct ep_pcie_hw {
	struct list_head node;
	u32 device_id;
	void **private_data;
	int (*register_event)(struct ep_pcie_register_event *reg);
	int (*deregister_event)(void);
	enum ep_pcie_link_status (*get_linkstatus)(void);
	int (*config_outbound_iatu)(struct ep_pcie_iatu entries[],
				u32 num_entries, u32 vf_id);
	int (*get_msi_config)(struct ep_pcie_msi_config *cfg, u32 vf_id);
	int (*trigger_msi)(u32 idx, u32 vf_id);
	int (*wakeup_host)(enum ep_pcie_event event);
	int (*enable_endpoint)(enum ep_pcie_options opt);
	int (*disable_endpoint)(void);
	int (*config_db_routing)(struct ep_pcie_db_config chdb_cfg,
				struct ep_pcie_db_config erdb_cfg,
				u32 vf_id);
	int (*mask_irq_event)(enum ep_pcie_irq_event event,
				bool enable);
	int (*configure_inactivity_timer)(struct ep_pcie_inactivity *param);
	int (*get_capability)(struct ep_pcie_cap *ep_cap);
};


int ep_pcie_register_drv(struct ep_pcie_hw *phandle);


int ep_pcie_deregister_drv(struct ep_pcie_hw *phandle);


struct ep_pcie_hw *ep_pcie_get_phandle(u32 id);


int ep_pcie_register_event(struct ep_pcie_hw *phandle,
	struct ep_pcie_register_event *reg);


int ep_pcie_deregister_event(struct ep_pcie_hw *phandle);


enum ep_pcie_link_status ep_pcie_get_linkstatus(struct ep_pcie_hw *phandle);


int ep_pcie_config_outbound_iatu(struct ep_pcie_hw *phandle,
				struct ep_pcie_iatu entries[],
				u32 num_entries,
				u32 vf_id);


int ep_pcie_get_msi_config(struct ep_pcie_hw *phandle,
				struct ep_pcie_msi_config *cfg, u32 vf_id);


int ep_pcie_trigger_msi(struct ep_pcie_hw *phandle, u32 idx, u32 vf_id);


int ep_pcie_wakeup_host(struct ep_pcie_hw *phandle, enum ep_pcie_event event);


int ep_pcie_enable_endpoint(struct ep_pcie_hw *phandle,
				enum ep_pcie_options opt);


int ep_pcie_disable_endpoint(struct ep_pcie_hw *phandle);


int ep_pcie_config_db_routing(struct ep_pcie_hw *phandle,
				struct ep_pcie_db_config chdb_cfg,
				struct ep_pcie_db_config erdb_cfg,
				u32 vf_id);


int ep_pcie_mask_irq_event(struct ep_pcie_hw *phandle,
				enum ep_pcie_irq_event event,
				bool enable);


int ep_pcie_configure_inactivity_timer(struct ep_pcie_hw *phandle,
					struct ep_pcie_inactivity *param);


int ep_pcie_core_l1ss_sleep_config_enable(void);


int ep_pcie_core_l1ss_sleep_config_disable(void);


int ep_pcie_core_get_capability(struct ep_pcie_hw *phandle,
		struct ep_pcie_cap *ep_cap);

#if IS_ENABLED(CONFIG_QCOM_PCI_EDMA)
int qcom_edma_init(struct device *dev);
void edma_dump(void);
#else
static inline int qcom_edma_init(struct device *dev)
{
	return 0;
}
static inline void edma_dump(void) {}
#endif

#endif
