| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Copyright (c) 2022, Linaro Ltd. |
| * |
| */ |
| |
| #ifndef _MHI_COMMON_H |
| #define _MHI_COMMON_H |
| |
| #include <linux/bitfield.h> |
| #include <linux/mhi.h> |
| |
| /* MHI registers */ |
| #define MHIREGLEN 0x00 |
| #define MHIVER 0x08 |
| #define MHICFG 0x10 |
| #define CHDBOFF 0x18 |
| #define ERDBOFF 0x20 |
| #define BHIOFF 0x28 |
| #define BHIEOFF 0x2c |
| #define DEBUGOFF 0x30 |
| #define MHICTRL 0x38 |
| #define MHISTATUS 0x48 |
| #define CCABAP_LOWER 0x58 |
| #define CCABAP_HIGHER 0x5c |
| #define ECABAP_LOWER 0x60 |
| #define ECABAP_HIGHER 0x64 |
| #define CRCBAP_LOWER 0x68 |
| #define CRCBAP_HIGHER 0x6c |
| #define CRDB_LOWER 0x70 |
| #define CRDB_HIGHER 0x74 |
| #define MHICTRLBASE_LOWER 0x80 |
| #define MHICTRLBASE_HIGHER 0x84 |
| #define MHICTRLLIMIT_LOWER 0x88 |
| #define MHICTRLLIMIT_HIGHER 0x8c |
| #define MHIDATABASE_LOWER 0x98 |
| #define MHIDATABASE_HIGHER 0x9c |
| #define MHIDATALIMIT_LOWER 0xa0 |
| #define MHIDATALIMIT_HIGHER 0xa4 |
| |
| /* MHI BHI registers */ |
| #define BHI_BHIVERSION_MINOR 0x00 |
| #define BHI_BHIVERSION_MAJOR 0x04 |
| #define BHI_IMGADDR_LOW 0x08 |
| #define BHI_IMGADDR_HIGH 0x0c |
| #define BHI_IMGSIZE 0x10 |
| #define BHI_RSVD1 0x14 |
| #define BHI_IMGTXDB 0x18 |
| #define BHI_RSVD2 0x1c |
| #define BHI_INTVEC 0x20 |
| #define BHI_RSVD3 0x24 |
| #define BHI_EXECENV 0x28 |
| #define BHI_STATUS 0x2c |
| #define BHI_ERRCODE 0x30 |
| #define BHI_ERRDBG1 0x34 |
| #define BHI_ERRDBG2 0x38 |
| #define BHI_ERRDBG3 0x3c |
| #define BHI_SERIALNU 0x40 |
| #define BHI_SBLANTIROLLVER 0x44 |
| #define BHI_NUMSEG 0x48 |
| #define BHI_MSMHWID(n) (0x4c + (0x4 * (n))) |
| #define BHI_OEMPKHASH(n) (0x64 + (0x4 * (n))) |
| #define BHI_RSVD5 0xc4 |
| |
| /* BHI register bits */ |
| #define BHI_TXDB_SEQNUM_BMSK GENMASK(29, 0) |
| #define BHI_TXDB_SEQNUM_SHFT 0 |
| #define BHI_STATUS_MASK GENMASK(31, 30) |
| #define BHI_STATUS_ERROR 0x03 |
| #define BHI_STATUS_SUCCESS 0x02 |
| #define BHI_STATUS_RESET 0x00 |
| |
| /* MHI BHIE registers */ |
| #define BHIE_MSMSOCID_OFFS 0x00 |
| #define BHIE_TXVECADDR_LOW_OFFS 0x2c |
| #define BHIE_TXVECADDR_HIGH_OFFS 0x30 |
| #define BHIE_TXVECSIZE_OFFS 0x34 |
| #define BHIE_TXVECDB_OFFS 0x3c |
| #define BHIE_TXVECSTATUS_OFFS 0x44 |
| #define BHIE_RXVECADDR_LOW_OFFS 0x60 |
| #define BHIE_RXVECADDR_HIGH_OFFS 0x64 |
| #define BHIE_RXVECSIZE_OFFS 0x68 |
| #define BHIE_RXVECDB_OFFS 0x70 |
| #define BHIE_RXVECSTATUS_OFFS 0x78 |
| |
| /* BHIE register bits */ |
| #define BHIE_TXVECDB_SEQNUM_BMSK GENMASK(29, 0) |
| #define BHIE_TXVECDB_SEQNUM_SHFT 0 |
| #define BHIE_TXVECSTATUS_SEQNUM_BMSK GENMASK(29, 0) |
| #define BHIE_TXVECSTATUS_SEQNUM_SHFT 0 |
| #define BHIE_TXVECSTATUS_STATUS_BMSK GENMASK(31, 30) |
| #define BHIE_TXVECSTATUS_STATUS_SHFT 30 |
| #define BHIE_TXVECSTATUS_STATUS_RESET 0x00 |
| #define BHIE_TXVECSTATUS_STATUS_XFER_COMPL 0x02 |
| #define BHIE_TXVECSTATUS_STATUS_ERROR 0x03 |
| #define BHIE_RXVECDB_SEQNUM_BMSK GENMASK(29, 0) |
| #define BHIE_RXVECDB_SEQNUM_SHFT 0 |
| #define BHIE_RXVECSTATUS_SEQNUM_BMSK GENMASK(29, 0) |
| #define BHIE_RXVECSTATUS_SEQNUM_SHFT 0 |
| #define BHIE_RXVECSTATUS_STATUS_BMSK GENMASK(31, 30) |
| #define BHIE_RXVECSTATUS_STATUS_SHFT 30 |
| #define BHIE_RXVECSTATUS_STATUS_RESET 0x00 |
| #define BHIE_RXVECSTATUS_STATUS_XFER_COMPL 0x02 |
| #define BHIE_RXVECSTATUS_STATUS_ERROR 0x03 |
| |
| /* MHI register bits */ |
| #define MHICFG_NHWER_MASK GENMASK(31, 24) |
| #define MHICFG_NER_MASK GENMASK(23, 16) |
| #define MHICFG_NHWCH_MASK GENMASK(15, 8) |
| #define MHICFG_NCH_MASK GENMASK(7, 0) |
| #define MHICTRL_MHISTATE_MASK GENMASK(15, 8) |
| #define MHICTRL_RESET_MASK BIT(1) |
| #define MHISTATUS_MHISTATE_MASK GENMASK(15, 8) |
| #define MHISTATUS_SYSERR_MASK BIT(2) |
| #define MHISTATUS_READY_MASK BIT(0) |
| |
| /* Command Ring Element macros */ |
| /* No operation command */ |
| #define MHI_TRE_CMD_NOOP_PTR 0 |
| #define MHI_TRE_CMD_NOOP_DWORD0 0 |
| #define MHI_TRE_CMD_NOOP_DWORD1 cpu_to_le32(FIELD_PREP(GENMASK(23, 16), MHI_CMD_NOP)) |
| |
| /* Channel reset command */ |
| #define MHI_TRE_CMD_RESET_PTR 0 |
| #define MHI_TRE_CMD_RESET_DWORD0 0 |
| #define MHI_TRE_CMD_RESET_DWORD1(chid) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), chid) | \ |
| FIELD_PREP(GENMASK(23, 16), \ |
| MHI_CMD_RESET_CHAN)) |
| |
| /* Channel stop command */ |
| #define MHI_TRE_CMD_STOP_PTR 0 |
| #define MHI_TRE_CMD_STOP_DWORD0 0 |
| #define MHI_TRE_CMD_STOP_DWORD1(chid) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), chid) | \ |
| FIELD_PREP(GENMASK(23, 16), \ |
| MHI_CMD_STOP_CHAN)) |
| |
| /* Channel start command */ |
| #define MHI_TRE_CMD_START_PTR 0 |
| #define MHI_TRE_CMD_START_DWORD0 0 |
| #define MHI_TRE_CMD_START_DWORD1(chid) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), chid) | \ |
| FIELD_PREP(GENMASK(23, 16), \ |
| MHI_CMD_START_CHAN)) |
| |
| #define MHI_TRE_GET_DWORD(tre, word) le32_to_cpu((tre)->dword[(word)]) |
| #define MHI_TRE_GET_CMD_CHID(tre) FIELD_GET(GENMASK(31, 24), MHI_TRE_GET_DWORD(tre, 1)) |
| #define MHI_TRE_GET_CMD_TYPE(tre) FIELD_GET(GENMASK(23, 16), MHI_TRE_GET_DWORD(tre, 1)) |
| |
| /* Event descriptor macros */ |
| #define MHI_TRE_EV_PTR(ptr) cpu_to_le64(ptr) |
| #define MHI_TRE_EV_DWORD0(code, len) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), code) | \ |
| FIELD_PREP(GENMASK(15, 0), len)) |
| #define MHI_TRE_EV_DWORD1(chid, type) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), chid) | \ |
| FIELD_PREP(GENMASK(23, 16), type)) |
| #define MHI_TRE_GET_EV_PTR(tre) le64_to_cpu((tre)->ptr) |
| #define MHI_TRE_GET_EV_CODE(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0))) |
| #define MHI_TRE_GET_EV_LEN(tre) FIELD_GET(GENMASK(15, 0), (MHI_TRE_GET_DWORD(tre, 0))) |
| #define MHI_TRE_GET_EV_CHID(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 1))) |
| #define MHI_TRE_GET_EV_TYPE(tre) FIELD_GET(GENMASK(23, 16), (MHI_TRE_GET_DWORD(tre, 1))) |
| #define MHI_TRE_GET_EV_STATE(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0))) |
| #define MHI_TRE_GET_EV_EXECENV(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0))) |
| #define MHI_TRE_GET_EV_SEQ(tre) MHI_TRE_GET_DWORD(tre, 0) |
| #define MHI_TRE_GET_EV_TIME(tre) MHI_TRE_GET_EV_PTR(tre) |
| #define MHI_TRE_GET_EV_COOKIE(tre) lower_32_bits(MHI_TRE_GET_EV_PTR(tre)) |
| #define MHI_TRE_GET_EV_VEID(tre) FIELD_GET(GENMASK(23, 16), (MHI_TRE_GET_DWORD(tre, 0))) |
| #define MHI_TRE_GET_EV_LINKSPEED(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 1))) |
| #define MHI_TRE_GET_EV_LINKWIDTH(tre) FIELD_GET(GENMASK(7, 0), (MHI_TRE_GET_DWORD(tre, 0))) |
| |
| /* State change event */ |
| #define MHI_SC_EV_PTR 0 |
| #define MHI_SC_EV_DWORD0(state) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), state)) |
| #define MHI_SC_EV_DWORD1(type) cpu_to_le32(FIELD_PREP(GENMASK(23, 16), type)) |
| |
| /* EE event */ |
| #define MHI_EE_EV_PTR 0 |
| #define MHI_EE_EV_DWORD0(ee) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), ee)) |
| #define MHI_EE_EV_DWORD1(type) cpu_to_le32(FIELD_PREP(GENMASK(23, 16), type)) |
| |
| |
| /* Command Completion event */ |
| #define MHI_CC_EV_PTR(ptr) cpu_to_le64(ptr) |
| #define MHI_CC_EV_DWORD0(code) cpu_to_le32(FIELD_PREP(GENMASK(31, 24), code)) |
| #define MHI_CC_EV_DWORD1(type) cpu_to_le32(FIELD_PREP(GENMASK(23, 16), type)) |
| |
| /* Transfer descriptor macros */ |
| #define MHI_TRE_DATA_PTR(ptr) cpu_to_le64(ptr) |
| #define MHI_TRE_DATA_DWORD0(len) cpu_to_le32(FIELD_PREP(GENMASK(15, 0), len)) |
| #define MHI_TRE_TYPE_TRANSFER 2 |
| #define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \ |
| MHI_TRE_TYPE_TRANSFER) | \ |
| FIELD_PREP(BIT(10), bei) | \ |
| FIELD_PREP(BIT(9), ieot) | \ |
| FIELD_PREP(BIT(8), ieob) | \ |
| FIELD_PREP(BIT(0), chain)) |
| #define MHI_TRE_DATA_GET_PTR(tre) le64_to_cpu((tre)->ptr) |
| #define MHI_TRE_DATA_GET_LEN(tre) FIELD_GET(GENMASK(15, 0), MHI_TRE_GET_DWORD(tre, 0)) |
| #define MHI_TRE_DATA_GET_CHAIN(tre) (!!(FIELD_GET(BIT(0), MHI_TRE_GET_DWORD(tre, 1)))) |
| #define MHI_TRE_DATA_GET_IEOB(tre) (!!(FIELD_GET(BIT(8), MHI_TRE_GET_DWORD(tre, 1)))) |
| #define MHI_TRE_DATA_GET_IEOT(tre) (!!(FIELD_GET(BIT(9), MHI_TRE_GET_DWORD(tre, 1)))) |
| #define MHI_TRE_DATA_GET_BEI(tre) (!!(FIELD_GET(BIT(10), MHI_TRE_GET_DWORD(tre, 1)))) |
| |
| /* RSC transfer descriptor macros */ |
| #define MHI_RSCTRE_DATA_PTR(ptr, len) cpu_to_le64(FIELD_PREP(GENMASK(64, 48), len) | ptr) |
| #define MHI_RSCTRE_DATA_DWORD0(cookie) cpu_to_le32(cookie) |
| #define MHI_RSCTRE_DATA_DWORD1 cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \ |
| MHI_PKT_TYPE_COALESCING)) |
| |
| enum mhi_pkt_type { |
| MHI_PKT_TYPE_INVALID = 0x0, |
| MHI_PKT_TYPE_NOOP_CMD = 0x1, |
| MHI_PKT_TYPE_TRANSFER = 0x2, |
| MHI_PKT_TYPE_COALESCING = 0x8, |
| MHI_PKT_TYPE_RESET_CHAN_CMD = 0x10, |
| MHI_PKT_TYPE_STOP_CHAN_CMD = 0x11, |
| MHI_PKT_TYPE_START_CHAN_CMD = 0x12, |
| MHI_PKT_TYPE_STATE_CHANGE_EVENT = 0x20, |
| MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21, |
| MHI_PKT_TYPE_TX_EVENT = 0x22, |
| MHI_PKT_TYPE_RSC_TX_EVENT = 0x28, |
| MHI_PKT_TYPE_EE_EVENT = 0x40, |
| MHI_PKT_TYPE_TSYNC_EVENT = 0x48, |
| MHI_PKT_TYPE_BW_REQ_EVENT = 0x50, |
| MHI_PKT_TYPE_STALE_EVENT, /* internal event */ |
| }; |
| |
| /* MHI transfer completion events */ |
| enum mhi_ev_ccs { |
| MHI_EV_CC_INVALID = 0x0, |
| MHI_EV_CC_SUCCESS = 0x1, |
| MHI_EV_CC_EOT = 0x2, /* End of transfer event */ |
| MHI_EV_CC_OVERFLOW = 0x3, |
| MHI_EV_CC_EOB = 0x4, /* End of block event */ |
| MHI_EV_CC_OOB = 0x5, /* Out of block event */ |
| MHI_EV_CC_DB_MODE = 0x6, |
| MHI_EV_CC_UNDEFINED_ERR = 0x10, |
| MHI_EV_CC_BAD_TRE = 0x11, |
| }; |
| |
| /* Channel state */ |
| enum mhi_ch_state { |
| MHI_CH_STATE_DISABLED, |
| MHI_CH_STATE_ENABLED, |
| MHI_CH_STATE_RUNNING, |
| MHI_CH_STATE_SUSPENDED, |
| MHI_CH_STATE_STOP, |
| MHI_CH_STATE_ERROR, |
| }; |
| |
| enum mhi_cmd_type { |
| MHI_CMD_NOP = 1, |
| MHI_CMD_RESET_CHAN = 16, |
| MHI_CMD_STOP_CHAN = 17, |
| MHI_CMD_START_CHAN = 18, |
| }; |
| |
| #define EV_CTX_RESERVED_MASK GENMASK(7, 0) |
| #define EV_CTX_INTMODC_MASK GENMASK(15, 8) |
| #define EV_CTX_INTMODT_MASK GENMASK(31, 16) |
| struct mhi_event_ctxt { |
| __le32 intmod; |
| __le32 ertype; |
| __le32 msivec; |
| |
| __le64 rbase __packed __aligned(4); |
| __le64 rlen __packed __aligned(4); |
| __le64 rp __packed __aligned(4); |
| __le64 wp __packed __aligned(4); |
| }; |
| |
| #define CHAN_CTX_CHSTATE_MASK GENMASK(7, 0) |
| #define CHAN_CTX_BRSTMODE_MASK GENMASK(9, 8) |
| #define CHAN_CTX_POLLCFG_MASK GENMASK(15, 10) |
| #define CHAN_CTX_RESERVED_MASK GENMASK(31, 16) |
| struct mhi_chan_ctxt { |
| __le32 chcfg; |
| __le32 chtype; |
| __le32 erindex; |
| |
| __le64 rbase __packed __aligned(4); |
| __le64 rlen __packed __aligned(4); |
| __le64 rp __packed __aligned(4); |
| __le64 wp __packed __aligned(4); |
| }; |
| |
| struct mhi_cmd_ctxt { |
| __le32 reserved0; |
| __le32 reserved1; |
| __le32 reserved2; |
| |
| __le64 rbase __packed __aligned(4); |
| __le64 rlen __packed __aligned(4); |
| __le64 rp __packed __aligned(4); |
| __le64 wp __packed __aligned(4); |
| }; |
| |
| struct mhi_ring_element { |
| __le64 ptr; |
| __le32 dword[2]; |
| }; |
| |
| #define MHI_STATE_LIST \ |
| mhi_state(RESET, "RESET") \ |
| mhi_state(READY, "READY") \ |
| mhi_state(M0, "M0") \ |
| mhi_state(M1, "M1") \ |
| mhi_state(M2, "M2") \ |
| mhi_state(M3, "M3") \ |
| mhi_state(M3_FAST, "M3_FAST") \ |
| mhi_state(BHI, "BHI") \ |
| mhi_state_end(SYS_ERR, "SYS ERROR") |
| |
| #undef mhi_state |
| #undef mhi_state_end |
| |
| #define mhi_state(a, b) case MHI_STATE_##a: return b; |
| #define mhi_state_end(a, b) case MHI_STATE_##a: return b; |
| |
| static inline const char *mhi_state_str(enum mhi_state state) |
| { |
| switch (state) { |
| MHI_STATE_LIST |
| default: |
| return "Unknown state"; |
| } |
| } |
| |
| #endif /* _MHI_COMMON_H */ |