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