blob: f53a4bd8fa6bc7a4fdc4649a282cd74f87b7c9d8 [file] [log] [blame]
Skylar Changc9939cf2017-02-21 09:46:46 -08001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Amir Levycdccd632016-10-30 09:36:41 +02002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#ifndef GSI_H
13#define GSI_H
14
15#include <linux/device.h>
16#include <linux/types.h>
17#include <linux/completion.h>
18#include <linux/mutex.h>
19#include <linux/spinlock.h>
20#include <linux/msm_gsi.h>
Skylar Chang4d6a8fe2017-03-16 16:55:57 -070021#include <linux/ipc_logging.h>
Amir Levycdccd632016-10-30 09:36:41 +020022
Amir Levy41644242016-11-03 15:38:09 +020023#define GSI_CHAN_MAX 31
24#define GSI_EVT_RING_MAX 23
Amir Levycdccd632016-10-30 09:36:41 +020025#define GSI_NO_EVT_ERINDEX 31
26
27#define gsi_readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
28#define gsi_writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); })
29
Skylar Chang4d6a8fe2017-03-16 16:55:57 -070030#define GSI_IPC_LOGGING(buf, fmt, args...) \
31 do { \
32 if (buf) \
33 ipc_log_string((buf), fmt, __func__, __LINE__, \
34 ## args); \
35 } while (0)
36
Amir Levycdccd632016-10-30 09:36:41 +020037#define GSIDBG(fmt, args...) \
Skylar Chang4d6a8fe2017-03-16 16:55:57 -070038 do { \
39 dev_dbg(gsi_ctx->dev, "%s:%d " fmt, __func__, __LINE__, \
40 ## args);\
41 if (gsi_ctx) { \
42 GSI_IPC_LOGGING(gsi_ctx->ipc_logbuf, \
43 "%s:%d " fmt, ## args); \
44 GSI_IPC_LOGGING(gsi_ctx->ipc_logbuf_low, \
45 "%s:%d " fmt, ## args); \
46 } \
47 } while (0)
48
49#define GSIDBG_LOW(fmt, args...) \
50 do { \
51 dev_dbg(gsi_ctx->dev, "%s:%d " fmt, __func__, __LINE__, \
52 ## args);\
53 if (gsi_ctx) { \
54 GSI_IPC_LOGGING(gsi_ctx->ipc_logbuf_low, \
55 "%s:%d " fmt, ## args); \
56 } \
57 } while (0)
58
59#define GSIERR(fmt, args...) \
60 do { \
61 dev_err(gsi_ctx->dev, "%s:%d " fmt, __func__, __LINE__, \
62 ## args);\
63 if (gsi_ctx) { \
64 GSI_IPC_LOGGING(gsi_ctx->ipc_logbuf, \
65 "%s:%d " fmt, ## args); \
66 GSI_IPC_LOGGING(gsi_ctx->ipc_logbuf_low, \
67 "%s:%d " fmt, ## args); \
68 } \
69 } while (0)
70
71#define GSI_IPC_LOG_PAGES 50
Amir Levycdccd632016-10-30 09:36:41 +020072
73enum gsi_evt_ring_state {
74 GSI_EVT_RING_STATE_NOT_ALLOCATED = 0x0,
75 GSI_EVT_RING_STATE_ALLOCATED = 0x1,
76 GSI_EVT_RING_STATE_ERROR = 0xf
77};
78
79enum gsi_chan_state {
80 GSI_CHAN_STATE_NOT_ALLOCATED = 0x0,
81 GSI_CHAN_STATE_ALLOCATED = 0x1,
82 GSI_CHAN_STATE_STARTED = 0x2,
83 GSI_CHAN_STATE_STOPPED = 0x3,
84 GSI_CHAN_STATE_STOP_IN_PROC = 0x4,
85 GSI_CHAN_STATE_ERROR = 0xf
86};
87
88struct gsi_ring_ctx {
89 spinlock_t slock;
90 unsigned long base_va;
91 uint64_t base;
92 uint64_t wp;
93 uint64_t rp;
94 uint64_t wp_local;
95 uint64_t rp_local;
96 uint16_t len;
97 uint8_t elem_sz;
98 uint16_t max_num_elem;
99 uint64_t end;
100};
101
102struct gsi_chan_dp_stats {
103 unsigned long ch_below_lo;
104 unsigned long ch_below_hi;
105 unsigned long ch_above_hi;
106 unsigned long empty_time;
107 unsigned long last_timestamp;
108};
109
110struct gsi_chan_stats {
111 unsigned long queued;
112 unsigned long completed;
113 unsigned long callback_to_poll;
114 unsigned long poll_to_callback;
115 unsigned long invalid_tre_error;
116 unsigned long poll_ok;
117 unsigned long poll_empty;
118 struct gsi_chan_dp_stats dp;
119};
120
121struct gsi_chan_ctx {
122 struct gsi_chan_props props;
123 enum gsi_chan_state state;
124 struct gsi_ring_ctx ring;
125 void **user_data;
126 struct gsi_evt_ctx *evtr;
127 struct mutex mlock;
128 struct completion compl;
129 bool allocated;
130 atomic_t poll_mode;
131 union __packed gsi_channel_scratch scratch;
132 struct gsi_chan_stats stats;
133 bool enable_dp_stats;
134 bool print_dp_stats;
135};
136
137struct gsi_evt_stats {
138 unsigned long completed;
139};
140
141struct gsi_evt_ctx {
142 struct gsi_evt_ring_props props;
143 enum gsi_evt_ring_state state;
144 uint8_t id;
145 struct gsi_ring_ctx ring;
146 struct mutex mlock;
147 struct completion compl;
148 struct gsi_chan_ctx *chan;
149 atomic_t chan_ref_cnt;
150 union __packed gsi_evt_scratch scratch;
151 struct gsi_evt_stats stats;
152};
153
154struct gsi_ee_scratch {
155 union __packed {
156 struct {
Skylar Changc9939cf2017-02-21 09:46:46 -0800157 uint32_t inter_ee_cmd_return_code:3;
158 uint32_t resvd1:2;
159 uint32_t generic_ee_cmd_return_code:3;
160 uint32_t resvd2:7;
Amir Levycdccd632016-10-30 09:36:41 +0200161 uint32_t max_usb_pkt_size:1;
Skylar Changc9939cf2017-02-21 09:46:46 -0800162 uint32_t resvd3:8;
Amir Levycdccd632016-10-30 09:36:41 +0200163 uint32_t mhi_base_chan_idx:8;
164 } s;
165 uint32_t val;
166 } word0;
167 uint32_t word1;
168};
169
Skylar Chang22ecb822016-10-21 10:15:04 -0700170struct ch_debug_stats {
171 unsigned long ch_allocate;
172 unsigned long ch_start;
173 unsigned long ch_stop;
174 unsigned long ch_reset;
175 unsigned long ch_de_alloc;
176 unsigned long ch_db_stop;
177 unsigned long cmd_completed;
178};
179
Skylar Changc9939cf2017-02-21 09:46:46 -0800180struct gsi_generic_ee_cmd_debug_stats {
181 unsigned long halt_channel;
182};
183
Amir Levycdccd632016-10-30 09:36:41 +0200184struct gsi_ctx {
185 void __iomem *base;
186 struct device *dev;
187 struct gsi_per_props per;
188 bool per_registered;
Amir Levy41644242016-11-03 15:38:09 +0200189 struct gsi_chan_ctx chan[GSI_CHAN_MAX];
Skylar Chang22ecb822016-10-21 10:15:04 -0700190 struct ch_debug_stats ch_dbg[GSI_CHAN_MAX];
Amir Levy41644242016-11-03 15:38:09 +0200191 struct gsi_evt_ctx evtr[GSI_EVT_RING_MAX];
Skylar Changc9939cf2017-02-21 09:46:46 -0800192 struct gsi_generic_ee_cmd_debug_stats gen_ee_cmd_dbg;
Amir Levycdccd632016-10-30 09:36:41 +0200193 struct mutex mlock;
194 spinlock_t slock;
195 unsigned long evt_bmap;
196 bool enabled;
197 atomic_t num_chan;
198 atomic_t num_evt_ring;
199 struct gsi_ee_scratch scratch;
200 int num_ch_dp_stats;
201 struct workqueue_struct *dp_stat_wq;
Amir Levy41644242016-11-03 15:38:09 +0200202 u32 max_ch;
203 u32 max_ev;
Skylar Changc9939cf2017-02-21 09:46:46 -0800204 struct completion gen_ee_cmd_compl;
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700205 void *ipc_logbuf;
206 void *ipc_logbuf_low;
Amir Levycdccd632016-10-30 09:36:41 +0200207};
208
209enum gsi_re_type {
210 GSI_RE_XFER = 0x2,
211 GSI_RE_IMMD_CMD = 0x3,
212};
213
214struct __packed gsi_tre {
215 uint64_t buffer_ptr;
216 uint16_t buf_len;
217 uint16_t resvd1;
218 uint16_t chain:1;
219 uint16_t resvd4:7;
220 uint16_t ieob:1;
221 uint16_t ieot:1;
222 uint16_t bei:1;
223 uint16_t resvd3:5;
224 uint8_t re_type;
225 uint8_t resvd2;
226};
227
228struct __packed gsi_xfer_compl_evt {
229 uint64_t xfer_ptr;
230 uint16_t len;
231 uint8_t resvd1;
232 uint8_t code; /* see gsi_chan_evt */
233 uint16_t resvd;
234 uint8_t type;
235 uint8_t chid;
236};
237
238enum gsi_err_type {
239 GSI_ERR_TYPE_GLOB = 0x1,
240 GSI_ERR_TYPE_CHAN = 0x2,
241 GSI_ERR_TYPE_EVT = 0x3,
242};
243
244enum gsi_err_code {
245 GSI_INVALID_TRE_ERR = 0x1,
246 GSI_OUT_OF_BUFFERS_ERR = 0x2,
247 GSI_OUT_OF_RESOURCES_ERR = 0x3,
248 GSI_UNSUPPORTED_INTER_EE_OP_ERR = 0x4,
249 GSI_EVT_RING_EMPTY_ERR = 0x5,
250 GSI_NON_ALLOCATED_EVT_ACCESS_ERR = 0x6,
251 GSI_HWO_1_ERR = 0x8
252};
253
254struct __packed gsi_log_err {
255 uint32_t arg3:4;
256 uint32_t arg2:4;
257 uint32_t arg1:4;
258 uint32_t code:4;
259 uint32_t resvd:3;
260 uint32_t virt_idx:5;
261 uint32_t err_type:4;
262 uint32_t ee:4;
263};
264
265enum gsi_ch_cmd_opcode {
266 GSI_CH_ALLOCATE = 0x0,
267 GSI_CH_START = 0x1,
268 GSI_CH_STOP = 0x2,
269 GSI_CH_RESET = 0x9,
270 GSI_CH_DE_ALLOC = 0xa,
271 GSI_CH_DB_STOP = 0xb,
272};
273
274enum gsi_evt_ch_cmd_opcode {
275 GSI_EVT_ALLOCATE = 0x0,
276 GSI_EVT_RESET = 0x9, /* TODO: is this valid? */
277 GSI_EVT_DE_ALLOC = 0xa,
278};
279
Skylar Changc9939cf2017-02-21 09:46:46 -0800280enum gsi_generic_ee_cmd_opcode {
281 GSI_GEN_EE_CMD_HALT_CHANNEL = 0x1,
282};
283
284enum gsi_generic_ee_cmd_return_code {
285 GSI_GEN_EE_CMD_RETURN_CODE_SUCCESS = 0x1,
286 GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING = 0x2,
287 GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_DIRECTION = 0x3,
288 GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE = 0x4,
289 GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX = 0x5,
290};
291
Amir Levycdccd632016-10-30 09:36:41 +0200292extern struct gsi_ctx *gsi_ctx;
293void gsi_debugfs_init(void);
294uint16_t gsi_find_idx_from_addr(struct gsi_ring_ctx *ctx, uint64_t addr);
295void gsi_update_ch_dp_stats(struct gsi_chan_ctx *ctx, uint16_t used);
296
297#endif