162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2022, Linaro Ltd.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef _MHI_EP_INTERNAL_
862306a36Sopenharmony_ci#define _MHI_EP_INTERNAL_
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/bitfield.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "../common.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciextern struct bus_type mhi_ep_bus_type;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define MHI_REG_OFFSET				0x100
1762306a36Sopenharmony_ci#define BHI_REG_OFFSET				0x200
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* MHI registers */
2062306a36Sopenharmony_ci#define EP_MHIREGLEN				(MHI_REG_OFFSET + MHIREGLEN)
2162306a36Sopenharmony_ci#define EP_MHIVER				(MHI_REG_OFFSET + MHIVER)
2262306a36Sopenharmony_ci#define EP_MHICFG				(MHI_REG_OFFSET + MHICFG)
2362306a36Sopenharmony_ci#define EP_CHDBOFF				(MHI_REG_OFFSET + CHDBOFF)
2462306a36Sopenharmony_ci#define EP_ERDBOFF				(MHI_REG_OFFSET + ERDBOFF)
2562306a36Sopenharmony_ci#define EP_BHIOFF				(MHI_REG_OFFSET + BHIOFF)
2662306a36Sopenharmony_ci#define EP_BHIEOFF				(MHI_REG_OFFSET + BHIEOFF)
2762306a36Sopenharmony_ci#define EP_DEBUGOFF				(MHI_REG_OFFSET + DEBUGOFF)
2862306a36Sopenharmony_ci#define EP_MHICTRL				(MHI_REG_OFFSET + MHICTRL)
2962306a36Sopenharmony_ci#define EP_MHISTATUS				(MHI_REG_OFFSET + MHISTATUS)
3062306a36Sopenharmony_ci#define EP_CCABAP_LOWER				(MHI_REG_OFFSET + CCABAP_LOWER)
3162306a36Sopenharmony_ci#define EP_CCABAP_HIGHER			(MHI_REG_OFFSET + CCABAP_HIGHER)
3262306a36Sopenharmony_ci#define EP_ECABAP_LOWER				(MHI_REG_OFFSET + ECABAP_LOWER)
3362306a36Sopenharmony_ci#define EP_ECABAP_HIGHER			(MHI_REG_OFFSET + ECABAP_HIGHER)
3462306a36Sopenharmony_ci#define EP_CRCBAP_LOWER				(MHI_REG_OFFSET + CRCBAP_LOWER)
3562306a36Sopenharmony_ci#define EP_CRCBAP_HIGHER			(MHI_REG_OFFSET + CRCBAP_HIGHER)
3662306a36Sopenharmony_ci#define EP_CRDB_LOWER				(MHI_REG_OFFSET + CRDB_LOWER)
3762306a36Sopenharmony_ci#define EP_CRDB_HIGHER				(MHI_REG_OFFSET + CRDB_HIGHER)
3862306a36Sopenharmony_ci#define EP_MHICTRLBASE_LOWER			(MHI_REG_OFFSET + MHICTRLBASE_LOWER)
3962306a36Sopenharmony_ci#define EP_MHICTRLBASE_HIGHER			(MHI_REG_OFFSET + MHICTRLBASE_HIGHER)
4062306a36Sopenharmony_ci#define EP_MHICTRLLIMIT_LOWER			(MHI_REG_OFFSET + MHICTRLLIMIT_LOWER)
4162306a36Sopenharmony_ci#define EP_MHICTRLLIMIT_HIGHER			(MHI_REG_OFFSET + MHICTRLLIMIT_HIGHER)
4262306a36Sopenharmony_ci#define EP_MHIDATABASE_LOWER			(MHI_REG_OFFSET + MHIDATABASE_LOWER)
4362306a36Sopenharmony_ci#define EP_MHIDATABASE_HIGHER			(MHI_REG_OFFSET + MHIDATABASE_HIGHER)
4462306a36Sopenharmony_ci#define EP_MHIDATALIMIT_LOWER			(MHI_REG_OFFSET + MHIDATALIMIT_LOWER)
4562306a36Sopenharmony_ci#define EP_MHIDATALIMIT_HIGHER			(MHI_REG_OFFSET + MHIDATALIMIT_HIGHER)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* MHI BHI registers */
4862306a36Sopenharmony_ci#define EP_BHI_INTVEC				(BHI_REG_OFFSET + BHI_INTVEC)
4962306a36Sopenharmony_ci#define EP_BHI_EXECENV				(BHI_REG_OFFSET + BHI_EXECENV)
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* MHI Doorbell registers */
5262306a36Sopenharmony_ci#define CHDB_LOWER_n(n)				(0x400 + 0x8 * (n))
5362306a36Sopenharmony_ci#define CHDB_HIGHER_n(n)			(0x404 + 0x8 * (n))
5462306a36Sopenharmony_ci#define ERDB_LOWER_n(n)				(0x800 + 0x8 * (n))
5562306a36Sopenharmony_ci#define ERDB_HIGHER_n(n)			(0x804 + 0x8 * (n))
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define MHI_CTRL_INT_STATUS			0x4
5862306a36Sopenharmony_ci#define MHI_CTRL_INT_STATUS_MSK			BIT(0)
5962306a36Sopenharmony_ci#define MHI_CTRL_INT_STATUS_CRDB_MSK		BIT(1)
6062306a36Sopenharmony_ci#define MHI_CHDB_INT_STATUS_n(n)		(0x28 + 0x4 * (n))
6162306a36Sopenharmony_ci#define MHI_ERDB_INT_STATUS_n(n)		(0x38 + 0x4 * (n))
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define MHI_CTRL_INT_CLEAR			0x4c
6462306a36Sopenharmony_ci#define MHI_CTRL_INT_MMIO_WR_CLEAR		BIT(2)
6562306a36Sopenharmony_ci#define MHI_CTRL_INT_CRDB_CLEAR			BIT(1)
6662306a36Sopenharmony_ci#define MHI_CTRL_INT_CRDB_MHICTRL_CLEAR		BIT(0)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define MHI_CHDB_INT_CLEAR_n(n)			(0x70 + 0x4 * (n))
6962306a36Sopenharmony_ci#define MHI_CHDB_INT_CLEAR_n_CLEAR_ALL		GENMASK(31, 0)
7062306a36Sopenharmony_ci#define MHI_ERDB_INT_CLEAR_n(n)			(0x80 + 0x4 * (n))
7162306a36Sopenharmony_ci#define MHI_ERDB_INT_CLEAR_n_CLEAR_ALL		GENMASK(31, 0)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/*
7462306a36Sopenharmony_ci * Unlike the usual "masking" convention, writing "1" to a bit in this register
7562306a36Sopenharmony_ci * enables the interrupt and writing "0" will disable it..
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_ci#define MHI_CTRL_INT_MASK			0x94
7862306a36Sopenharmony_ci#define MHI_CTRL_INT_MASK_MASK			GENMASK(1, 0)
7962306a36Sopenharmony_ci#define MHI_CTRL_MHICTRL_MASK			BIT(0)
8062306a36Sopenharmony_ci#define MHI_CTRL_CRDB_MASK			BIT(1)
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define MHI_CHDB_INT_MASK_n(n)			(0xb8 + 0x4 * (n))
8362306a36Sopenharmony_ci#define MHI_CHDB_INT_MASK_n_EN_ALL		GENMASK(31, 0)
8462306a36Sopenharmony_ci#define MHI_ERDB_INT_MASK_n(n)			(0xc8 + 0x4 * (n))
8562306a36Sopenharmony_ci#define MHI_ERDB_INT_MASK_n_EN_ALL		GENMASK(31, 0)
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define NR_OF_CMD_RINGS				1
8862306a36Sopenharmony_ci#define MHI_MASK_ROWS_CH_DB			4
8962306a36Sopenharmony_ci#define MHI_MASK_ROWS_EV_DB			4
9062306a36Sopenharmony_ci#define MHI_MASK_CH_LEN				32
9162306a36Sopenharmony_ci#define MHI_MASK_EV_LEN				32
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/* Generic context */
9462306a36Sopenharmony_cistruct mhi_generic_ctx {
9562306a36Sopenharmony_ci	__le32 reserved0;
9662306a36Sopenharmony_ci	__le32 reserved1;
9762306a36Sopenharmony_ci	__le32 reserved2;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	__le64 rbase __packed __aligned(4);
10062306a36Sopenharmony_ci	__le64 rlen __packed __aligned(4);
10162306a36Sopenharmony_ci	__le64 rp __packed __aligned(4);
10262306a36Sopenharmony_ci	__le64 wp __packed __aligned(4);
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cienum mhi_ep_ring_type {
10662306a36Sopenharmony_ci	RING_TYPE_CMD,
10762306a36Sopenharmony_ci	RING_TYPE_ER,
10862306a36Sopenharmony_ci	RING_TYPE_CH,
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/* Ring element */
11262306a36Sopenharmony_ciunion mhi_ep_ring_ctx {
11362306a36Sopenharmony_ci	struct mhi_cmd_ctxt cmd;
11462306a36Sopenharmony_ci	struct mhi_event_ctxt ev;
11562306a36Sopenharmony_ci	struct mhi_chan_ctxt ch;
11662306a36Sopenharmony_ci	struct mhi_generic_ctx generic;
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistruct mhi_ep_ring_item {
12062306a36Sopenharmony_ci	struct list_head node;
12162306a36Sopenharmony_ci	struct mhi_ep_ring *ring;
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct mhi_ep_ring {
12562306a36Sopenharmony_ci	struct mhi_ep_cntrl *mhi_cntrl;
12662306a36Sopenharmony_ci	union mhi_ep_ring_ctx *ring_ctx;
12762306a36Sopenharmony_ci	struct mhi_ring_element *ring_cache;
12862306a36Sopenharmony_ci	enum mhi_ep_ring_type type;
12962306a36Sopenharmony_ci	u64 rbase;
13062306a36Sopenharmony_ci	size_t rd_offset;
13162306a36Sopenharmony_ci	size_t wr_offset;
13262306a36Sopenharmony_ci	size_t ring_size;
13362306a36Sopenharmony_ci	u32 db_offset_h;
13462306a36Sopenharmony_ci	u32 db_offset_l;
13562306a36Sopenharmony_ci	u32 ch_id;
13662306a36Sopenharmony_ci	u32 er_index;
13762306a36Sopenharmony_ci	u32 irq_vector;
13862306a36Sopenharmony_ci	bool started;
13962306a36Sopenharmony_ci};
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistruct mhi_ep_cmd {
14262306a36Sopenharmony_ci	struct mhi_ep_ring ring;
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistruct mhi_ep_event {
14662306a36Sopenharmony_ci	struct mhi_ep_ring ring;
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistruct mhi_ep_state_transition {
15062306a36Sopenharmony_ci	struct list_head node;
15162306a36Sopenharmony_ci	enum mhi_state state;
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistruct mhi_ep_chan {
15562306a36Sopenharmony_ci	char *name;
15662306a36Sopenharmony_ci	struct mhi_ep_device *mhi_dev;
15762306a36Sopenharmony_ci	struct mhi_ep_ring ring;
15862306a36Sopenharmony_ci	struct mutex lock;
15962306a36Sopenharmony_ci	void (*xfer_cb)(struct mhi_ep_device *mhi_dev, struct mhi_result *result);
16062306a36Sopenharmony_ci	enum mhi_ch_state state;
16162306a36Sopenharmony_ci	enum dma_data_direction dir;
16262306a36Sopenharmony_ci	u64 tre_loc;
16362306a36Sopenharmony_ci	u32 tre_size;
16462306a36Sopenharmony_ci	u32 tre_bytes_left;
16562306a36Sopenharmony_ci	u32 chan;
16662306a36Sopenharmony_ci	bool skip_td;
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci/* MHI Ring related functions */
17062306a36Sopenharmony_civoid mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id);
17162306a36Sopenharmony_civoid mhi_ep_ring_reset(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring);
17262306a36Sopenharmony_ciint mhi_ep_ring_start(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring,
17362306a36Sopenharmony_ci		      union mhi_ep_ring_ctx *ctx);
17462306a36Sopenharmony_cisize_t mhi_ep_ring_addr2offset(struct mhi_ep_ring *ring, u64 ptr);
17562306a36Sopenharmony_ciint mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *element);
17662306a36Sopenharmony_civoid mhi_ep_ring_inc_index(struct mhi_ep_ring *ring);
17762306a36Sopenharmony_ciint mhi_ep_update_wr_offset(struct mhi_ep_ring *ring);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/* MMIO related functions */
18062306a36Sopenharmony_ciu32 mhi_ep_mmio_read(struct mhi_ep_cntrl *mhi_cntrl, u32 offset);
18162306a36Sopenharmony_civoid mhi_ep_mmio_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 val);
18262306a36Sopenharmony_civoid mhi_ep_mmio_masked_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 mask, u32 val);
18362306a36Sopenharmony_ciu32 mhi_ep_mmio_masked_read(struct mhi_ep_cntrl *dev, u32 offset, u32 mask);
18462306a36Sopenharmony_civoid mhi_ep_mmio_enable_ctrl_interrupt(struct mhi_ep_cntrl *mhi_cntrl);
18562306a36Sopenharmony_civoid mhi_ep_mmio_disable_ctrl_interrupt(struct mhi_ep_cntrl *mhi_cntrl);
18662306a36Sopenharmony_civoid mhi_ep_mmio_enable_cmdb_interrupt(struct mhi_ep_cntrl *mhi_cntrl);
18762306a36Sopenharmony_civoid mhi_ep_mmio_disable_cmdb_interrupt(struct mhi_ep_cntrl *mhi_cntrl);
18862306a36Sopenharmony_civoid mhi_ep_mmio_enable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id);
18962306a36Sopenharmony_civoid mhi_ep_mmio_disable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id);
19062306a36Sopenharmony_civoid mhi_ep_mmio_enable_chdb_interrupts(struct mhi_ep_cntrl *mhi_cntrl);
19162306a36Sopenharmony_cibool mhi_ep_mmio_read_chdb_status_interrupts(struct mhi_ep_cntrl *mhi_cntrl);
19262306a36Sopenharmony_civoid mhi_ep_mmio_mask_interrupts(struct mhi_ep_cntrl *mhi_cntrl);
19362306a36Sopenharmony_civoid mhi_ep_mmio_get_chc_base(struct mhi_ep_cntrl *mhi_cntrl);
19462306a36Sopenharmony_civoid mhi_ep_mmio_get_erc_base(struct mhi_ep_cntrl *mhi_cntrl);
19562306a36Sopenharmony_civoid mhi_ep_mmio_get_crc_base(struct mhi_ep_cntrl *mhi_cntrl);
19662306a36Sopenharmony_ciu64 mhi_ep_mmio_get_db(struct mhi_ep_ring *ring);
19762306a36Sopenharmony_civoid mhi_ep_mmio_set_env(struct mhi_ep_cntrl *mhi_cntrl, u32 value);
19862306a36Sopenharmony_civoid mhi_ep_mmio_clear_reset(struct mhi_ep_cntrl *mhi_cntrl);
19962306a36Sopenharmony_civoid mhi_ep_mmio_reset(struct mhi_ep_cntrl *mhi_cntrl);
20062306a36Sopenharmony_civoid mhi_ep_mmio_get_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state *state,
20162306a36Sopenharmony_ci			       bool *mhi_reset);
20262306a36Sopenharmony_civoid mhi_ep_mmio_init(struct mhi_ep_cntrl *mhi_cntrl);
20362306a36Sopenharmony_civoid mhi_ep_mmio_update_ner(struct mhi_ep_cntrl *mhi_cntrl);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/* MHI EP core functions */
20662306a36Sopenharmony_ciint mhi_ep_send_state_change_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state state);
20762306a36Sopenharmony_ciint mhi_ep_send_ee_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_ee_type exec_env);
20862306a36Sopenharmony_cibool mhi_ep_check_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state cur_mhi_state,
20962306a36Sopenharmony_ci			    enum mhi_state mhi_state);
21062306a36Sopenharmony_ciint mhi_ep_set_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state mhi_state);
21162306a36Sopenharmony_ciint mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl);
21262306a36Sopenharmony_ciint mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl);
21362306a36Sopenharmony_ciint mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl);
21462306a36Sopenharmony_civoid mhi_ep_handle_syserr(struct mhi_ep_cntrl *mhi_cntrl);
21562306a36Sopenharmony_civoid mhi_ep_resume_channels(struct mhi_ep_cntrl *mhi_cntrl);
21662306a36Sopenharmony_civoid mhi_ep_suspend_channels(struct mhi_ep_cntrl *mhi_cntrl);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci#endif
219