1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright (c) 2022, Linaro Ltd. |
4 | * |
5 | */ |
6 | |
7 | #ifndef _MHI_EP_INTERNAL_ |
8 | #define _MHI_EP_INTERNAL_ |
9 | |
10 | #include <linux/bitfield.h> |
11 | |
12 | #include "../common.h" |
13 | |
14 | extern struct bus_type mhi_ep_bus_type; |
15 | |
16 | #define MHI_REG_OFFSET 0x100 |
17 | #define BHI_REG_OFFSET 0x200 |
18 | |
19 | /* MHI registers */ |
20 | #define EP_MHIREGLEN (MHI_REG_OFFSET + MHIREGLEN) |
21 | #define EP_MHIVER (MHI_REG_OFFSET + MHIVER) |
22 | #define EP_MHICFG (MHI_REG_OFFSET + MHICFG) |
23 | #define EP_CHDBOFF (MHI_REG_OFFSET + CHDBOFF) |
24 | #define EP_ERDBOFF (MHI_REG_OFFSET + ERDBOFF) |
25 | #define EP_BHIOFF (MHI_REG_OFFSET + BHIOFF) |
26 | #define EP_BHIEOFF (MHI_REG_OFFSET + BHIEOFF) |
27 | #define EP_DEBUGOFF (MHI_REG_OFFSET + DEBUGOFF) |
28 | #define EP_MHICTRL (MHI_REG_OFFSET + MHICTRL) |
29 | #define EP_MHISTATUS (MHI_REG_OFFSET + MHISTATUS) |
30 | #define EP_CCABAP_LOWER (MHI_REG_OFFSET + CCABAP_LOWER) |
31 | #define EP_CCABAP_HIGHER (MHI_REG_OFFSET + CCABAP_HIGHER) |
32 | #define EP_ECABAP_LOWER (MHI_REG_OFFSET + ECABAP_LOWER) |
33 | #define EP_ECABAP_HIGHER (MHI_REG_OFFSET + ECABAP_HIGHER) |
34 | #define EP_CRCBAP_LOWER (MHI_REG_OFFSET + CRCBAP_LOWER) |
35 | #define EP_CRCBAP_HIGHER (MHI_REG_OFFSET + CRCBAP_HIGHER) |
36 | #define EP_CRDB_LOWER (MHI_REG_OFFSET + CRDB_LOWER) |
37 | #define EP_CRDB_HIGHER (MHI_REG_OFFSET + CRDB_HIGHER) |
38 | #define EP_MHICTRLBASE_LOWER (MHI_REG_OFFSET + MHICTRLBASE_LOWER) |
39 | #define EP_MHICTRLBASE_HIGHER (MHI_REG_OFFSET + MHICTRLBASE_HIGHER) |
40 | #define EP_MHICTRLLIMIT_LOWER (MHI_REG_OFFSET + MHICTRLLIMIT_LOWER) |
41 | #define EP_MHICTRLLIMIT_HIGHER (MHI_REG_OFFSET + MHICTRLLIMIT_HIGHER) |
42 | #define EP_MHIDATABASE_LOWER (MHI_REG_OFFSET + MHIDATABASE_LOWER) |
43 | #define EP_MHIDATABASE_HIGHER (MHI_REG_OFFSET + MHIDATABASE_HIGHER) |
44 | #define EP_MHIDATALIMIT_LOWER (MHI_REG_OFFSET + MHIDATALIMIT_LOWER) |
45 | #define EP_MHIDATALIMIT_HIGHER (MHI_REG_OFFSET + MHIDATALIMIT_HIGHER) |
46 | |
47 | /* MHI BHI registers */ |
48 | #define EP_BHI_INTVEC (BHI_REG_OFFSET + BHI_INTVEC) |
49 | #define EP_BHI_EXECENV (BHI_REG_OFFSET + BHI_EXECENV) |
50 | |
51 | /* MHI Doorbell registers */ |
52 | #define CHDB_LOWER_n(n) (0x400 + 0x8 * (n)) |
53 | #define CHDB_HIGHER_n(n) (0x404 + 0x8 * (n)) |
54 | #define ERDB_LOWER_n(n) (0x800 + 0x8 * (n)) |
55 | #define ERDB_HIGHER_n(n) (0x804 + 0x8 * (n)) |
56 | |
57 | #define MHI_CTRL_INT_STATUS 0x4 |
58 | #define MHI_CTRL_INT_STATUS_MSK BIT(0) |
59 | #define MHI_CTRL_INT_STATUS_CRDB_MSK BIT(1) |
60 | #define MHI_CHDB_INT_STATUS_n(n) (0x28 + 0x4 * (n)) |
61 | #define MHI_ERDB_INT_STATUS_n(n) (0x38 + 0x4 * (n)) |
62 | |
63 | #define MHI_CTRL_INT_CLEAR 0x4c |
64 | #define MHI_CTRL_INT_MMIO_WR_CLEAR BIT(2) |
65 | #define MHI_CTRL_INT_CRDB_CLEAR BIT(1) |
66 | #define MHI_CTRL_INT_CRDB_MHICTRL_CLEAR BIT(0) |
67 | |
68 | #define MHI_CHDB_INT_CLEAR_n(n) (0x70 + 0x4 * (n)) |
69 | #define MHI_CHDB_INT_CLEAR_n_CLEAR_ALL GENMASK(31, 0) |
70 | #define MHI_ERDB_INT_CLEAR_n(n) (0x80 + 0x4 * (n)) |
71 | #define MHI_ERDB_INT_CLEAR_n_CLEAR_ALL GENMASK(31, 0) |
72 | |
73 | /* |
74 | * Unlike the usual "masking" convention, writing "1" to a bit in this register |
75 | * enables the interrupt and writing "0" will disable it.. |
76 | */ |
77 | #define MHI_CTRL_INT_MASK 0x94 |
78 | #define MHI_CTRL_INT_MASK_MASK GENMASK(1, 0) |
79 | #define MHI_CTRL_MHICTRL_MASK BIT(0) |
80 | #define MHI_CTRL_CRDB_MASK BIT(1) |
81 | |
82 | #define MHI_CHDB_INT_MASK_n(n) (0xb8 + 0x4 * (n)) |
83 | #define MHI_CHDB_INT_MASK_n_EN_ALL GENMASK(31, 0) |
84 | #define MHI_ERDB_INT_MASK_n(n) (0xc8 + 0x4 * (n)) |
85 | #define MHI_ERDB_INT_MASK_n_EN_ALL GENMASK(31, 0) |
86 | |
87 | #define NR_OF_CMD_RINGS 1 |
88 | #define MHI_MASK_ROWS_CH_DB 4 |
89 | #define MHI_MASK_ROWS_EV_DB 4 |
90 | #define MHI_MASK_CH_LEN 32 |
91 | #define MHI_MASK_EV_LEN 32 |
92 | |
93 | /* Generic context */ |
94 | struct mhi_generic_ctx { |
95 | __le32 reserved0; |
96 | __le32 reserved1; |
97 | __le32 reserved2; |
98 | |
99 | __le64 rbase __packed __aligned(4); |
100 | __le64 rlen __packed __aligned(4); |
101 | __le64 rp __packed __aligned(4); |
102 | __le64 wp __packed __aligned(4); |
103 | }; |
104 | |
105 | enum mhi_ep_ring_type { |
106 | RING_TYPE_CMD, |
107 | RING_TYPE_ER, |
108 | RING_TYPE_CH, |
109 | }; |
110 | |
111 | /* Ring element */ |
112 | union mhi_ep_ring_ctx { |
113 | struct mhi_cmd_ctxt cmd; |
114 | struct mhi_event_ctxt ev; |
115 | struct mhi_chan_ctxt ch; |
116 | struct mhi_generic_ctx generic; |
117 | }; |
118 | |
119 | struct mhi_ep_ring_item { |
120 | struct list_head node; |
121 | struct mhi_ep_ring *ring; |
122 | }; |
123 | |
124 | struct mhi_ep_ring { |
125 | struct mhi_ep_cntrl *mhi_cntrl; |
126 | union mhi_ep_ring_ctx *ring_ctx; |
127 | struct mhi_ring_element *ring_cache; |
128 | enum mhi_ep_ring_type type; |
129 | struct delayed_work intmodt_work; |
130 | u64 rbase; |
131 | size_t rd_offset; |
132 | size_t wr_offset; |
133 | size_t ring_size; |
134 | u32 db_offset_h; |
135 | u32 db_offset_l; |
136 | u32 ch_id; |
137 | u32 er_index; |
138 | u32 irq_vector; |
139 | u32 intmodt; |
140 | bool started; |
141 | bool irq_pending; |
142 | }; |
143 | |
144 | struct mhi_ep_cmd { |
145 | struct mhi_ep_ring ring; |
146 | }; |
147 | |
148 | struct mhi_ep_event { |
149 | struct mhi_ep_ring ring; |
150 | }; |
151 | |
152 | struct mhi_ep_state_transition { |
153 | struct list_head node; |
154 | enum mhi_state state; |
155 | }; |
156 | |
157 | struct mhi_ep_chan { |
158 | char *name; |
159 | struct mhi_ep_device *mhi_dev; |
160 | struct mhi_ep_ring ring; |
161 | struct mutex lock; |
162 | void (*xfer_cb)(struct mhi_ep_device *mhi_dev, struct mhi_result *result); |
163 | enum mhi_ch_state state; |
164 | enum dma_data_direction dir; |
165 | size_t rd_offset; |
166 | u64 tre_loc; |
167 | u32 tre_size; |
168 | u32 tre_bytes_left; |
169 | u32 chan; |
170 | bool skip_td; |
171 | }; |
172 | |
173 | /* MHI Ring related functions */ |
174 | void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id); |
175 | void mhi_ep_ring_reset(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring); |
176 | int mhi_ep_ring_start(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring, |
177 | union mhi_ep_ring_ctx *ctx); |
178 | size_t mhi_ep_ring_addr2offset(struct mhi_ep_ring *ring, u64 ptr); |
179 | int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *element); |
180 | void mhi_ep_ring_inc_index(struct mhi_ep_ring *ring); |
181 | int mhi_ep_update_wr_offset(struct mhi_ep_ring *ring); |
182 | |
183 | /* MMIO related functions */ |
184 | u32 mhi_ep_mmio_read(struct mhi_ep_cntrl *mhi_cntrl, u32 offset); |
185 | void mhi_ep_mmio_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 val); |
186 | void mhi_ep_mmio_masked_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 mask, u32 val); |
187 | u32 mhi_ep_mmio_masked_read(struct mhi_ep_cntrl *dev, u32 offset, u32 mask); |
188 | void mhi_ep_mmio_enable_ctrl_interrupt(struct mhi_ep_cntrl *mhi_cntrl); |
189 | void mhi_ep_mmio_disable_ctrl_interrupt(struct mhi_ep_cntrl *mhi_cntrl); |
190 | void mhi_ep_mmio_enable_cmdb_interrupt(struct mhi_ep_cntrl *mhi_cntrl); |
191 | void mhi_ep_mmio_disable_cmdb_interrupt(struct mhi_ep_cntrl *mhi_cntrl); |
192 | void mhi_ep_mmio_enable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id); |
193 | void mhi_ep_mmio_disable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id); |
194 | void mhi_ep_mmio_enable_chdb_interrupts(struct mhi_ep_cntrl *mhi_cntrl); |
195 | bool mhi_ep_mmio_read_chdb_status_interrupts(struct mhi_ep_cntrl *mhi_cntrl); |
196 | void mhi_ep_mmio_mask_interrupts(struct mhi_ep_cntrl *mhi_cntrl); |
197 | void mhi_ep_mmio_get_chc_base(struct mhi_ep_cntrl *mhi_cntrl); |
198 | void mhi_ep_mmio_get_erc_base(struct mhi_ep_cntrl *mhi_cntrl); |
199 | void mhi_ep_mmio_get_crc_base(struct mhi_ep_cntrl *mhi_cntrl); |
200 | u64 mhi_ep_mmio_get_db(struct mhi_ep_ring *ring); |
201 | void mhi_ep_mmio_set_env(struct mhi_ep_cntrl *mhi_cntrl, u32 value); |
202 | void mhi_ep_mmio_clear_reset(struct mhi_ep_cntrl *mhi_cntrl); |
203 | void mhi_ep_mmio_reset(struct mhi_ep_cntrl *mhi_cntrl); |
204 | void mhi_ep_mmio_get_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state *state, |
205 | bool *mhi_reset); |
206 | void mhi_ep_mmio_init(struct mhi_ep_cntrl *mhi_cntrl); |
207 | void mhi_ep_mmio_update_ner(struct mhi_ep_cntrl *mhi_cntrl); |
208 | |
209 | /* MHI EP core functions */ |
210 | int mhi_ep_send_state_change_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state state); |
211 | int mhi_ep_send_ee_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_ee_type exec_env); |
212 | bool mhi_ep_check_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state cur_mhi_state, |
213 | enum mhi_state mhi_state); |
214 | int mhi_ep_set_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state mhi_state); |
215 | int mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl); |
216 | int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl); |
217 | int mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl); |
218 | void mhi_ep_handle_syserr(struct mhi_ep_cntrl *mhi_cntrl); |
219 | void mhi_ep_resume_channels(struct mhi_ep_cntrl *mhi_cntrl); |
220 | void mhi_ep_suspend_channels(struct mhi_ep_cntrl *mhi_cntrl); |
221 | |
222 | #endif |
223 | |