blob: 3b40b41e059d5f540a88133b177b8a46714b70ba [file] [log] [blame]
Ashok Vuyyuru27ede172019-01-28 15:35:55 +05301/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
Amir Levy9659e592016-10-27 18:08:27 +03002 *
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
13#include <linux/ipa_mhi.h>
14#include <linux/ipa_qmi_service_v01.h>
15
16#ifndef _IPA_COMMON_I_H_
17#define _IPA_COMMON_I_H_
Jennifer L. Zennerdf159af2018-04-25 16:44:38 -040018#include <linux/errno.h>
Amir Levy9659e592016-10-27 18:08:27 +030019#include <linux/ipc_logging.h>
20#include <linux/ipa.h>
21#include <linux/ipa_uc_offload.h>
Skylar Chang852379b2016-12-13 14:00:19 -080022#include <linux/ipa_wdi3.h>
Mohammed Javida4252d82017-10-13 13:51:21 +053023#include <linux/ratelimit.h>
24
25#define WARNON_RATELIMIT_BURST 1
26#define IPA_RATELIMIT_BURST 1
Amir Levy9659e592016-10-27 18:08:27 +030027
28#define __FILENAME__ \
29 (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
30
31#define IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client) \
32 log_info.file = __FILENAME__; \
33 log_info.line = __LINE__; \
34 log_info.type = EP; \
Ghanim Fodia4bf8472017-07-12 14:44:15 +030035 log_info.id_string = (client < 0 || client >= IPA_CLIENT_MAX) \
36 ? "Invalid Client" : ipa_clients_strings[client]
Amir Levy9659e592016-10-27 18:08:27 +030037
38#define IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info) \
39 log_info.file = __FILENAME__; \
40 log_info.line = __LINE__; \
41 log_info.type = SIMPLE; \
42 log_info.id_string = __func__
43
44#define IPA_ACTIVE_CLIENTS_PREP_RESOURCE(log_info, resource_name) \
45 log_info.file = __FILENAME__; \
46 log_info.line = __LINE__; \
47 log_info.type = RESOURCE; \
48 log_info.id_string = resource_name
49
50#define IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, id_str) \
51 log_info.file = __FILENAME__; \
52 log_info.line = __LINE__; \
53 log_info.type = SPECIAL; \
54 log_info.id_string = id_str
55
56#define IPA_ACTIVE_CLIENTS_INC_EP(client) \
57 do { \
58 struct ipa_active_client_logging_info log_info; \
59 IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client); \
60 ipa_inc_client_enable_clks(&log_info); \
61 } while (0)
62
63#define IPA_ACTIVE_CLIENTS_DEC_EP(client) \
64 do { \
65 struct ipa_active_client_logging_info log_info; \
66 IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client); \
67 ipa_dec_client_disable_clks(&log_info); \
68 } while (0)
69
70#define IPA_ACTIVE_CLIENTS_INC_SIMPLE() \
71 do { \
72 struct ipa_active_client_logging_info log_info; \
73 IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); \
74 ipa_inc_client_enable_clks(&log_info); \
75 } while (0)
76
77#define IPA_ACTIVE_CLIENTS_DEC_SIMPLE() \
78 do { \
79 struct ipa_active_client_logging_info log_info; \
80 IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info); \
81 ipa_dec_client_disable_clks(&log_info); \
82 } while (0)
83
84#define IPA_ACTIVE_CLIENTS_INC_RESOURCE(resource_name) \
85 do { \
86 struct ipa_active_client_logging_info log_info; \
87 IPA_ACTIVE_CLIENTS_PREP_RESOURCE(log_info, resource_name); \
88 ipa_inc_client_enable_clks(&log_info); \
89 } while (0)
90
91#define IPA_ACTIVE_CLIENTS_DEC_RESOURCE(resource_name) \
92 do { \
93 struct ipa_active_client_logging_info log_info; \
94 IPA_ACTIVE_CLIENTS_PREP_RESOURCE(log_info, resource_name); \
95 ipa_dec_client_disable_clks(&log_info); \
96 } while (0)
97
98#define IPA_ACTIVE_CLIENTS_INC_SPECIAL(id_str) \
99 do { \
100 struct ipa_active_client_logging_info log_info; \
101 IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, id_str); \
102 ipa_inc_client_enable_clks(&log_info); \
103 } while (0)
104
105#define IPA_ACTIVE_CLIENTS_DEC_SPECIAL(id_str) \
106 do { \
107 struct ipa_active_client_logging_info log_info; \
108 IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, id_str); \
109 ipa_dec_client_disable_clks(&log_info); \
110 } while (0)
111
Mohammed Javida4252d82017-10-13 13:51:21 +0530112/*
113 * Printing one warning message in 5 seconds if multiple warning messages
114 * are coming back to back.
115 */
116
117#define WARN_ON_RATELIMIT_IPA(condition) \
118({ \
119 static DEFINE_RATELIMIT_STATE(_rs, \
120 DEFAULT_RATELIMIT_INTERVAL, \
121 WARNON_RATELIMIT_BURST); \
122 int rtn = !!(condition); \
123 \
124 if (unlikely(rtn && __ratelimit(&_rs))) \
125 WARN_ON(rtn); \
126})
127
128/*
129 * Printing one error message in 5 seconds if multiple error messages
130 * are coming back to back.
131 */
132
133#define pr_err_ratelimited_ipa(fmt, ...) \
134 printk_ratelimited_ipa(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
135#define printk_ratelimited_ipa(fmt, ...) \
136({ \
137 static DEFINE_RATELIMIT_STATE(_rs, \
138 DEFAULT_RATELIMIT_INTERVAL, \
139 IPA_RATELIMIT_BURST); \
140 \
141 if (__ratelimit(&_rs)) \
142 printk(fmt, ##__VA_ARGS__); \
143})
144
Amir Levy9659e592016-10-27 18:08:27 +0300145#define ipa_assert_on(condition)\
146do {\
147 if (unlikely(condition))\
148 ipa_assert();\
149} while (0)
150
Skylar Changa9516582017-05-09 11:36:47 -0700151#define IPA_CLIENT_IS_PROD(x) \
152 (x < IPA_CLIENT_MAX && (x & 0x1) == 0)
153#define IPA_CLIENT_IS_CONS(x) \
154 (x < IPA_CLIENT_MAX && (x & 0x1) == 1)
Amir Levy9659e592016-10-27 18:08:27 +0300155
156#define IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC (1000)
157#define IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC (2000)
158
159enum ipa_active_client_log_type {
160 EP,
161 SIMPLE,
162 RESOURCE,
163 SPECIAL,
164 INVALID
165};
166
167struct ipa_active_client_logging_info {
168 const char *id_string;
169 char *file;
170 int line;
171 enum ipa_active_client_log_type type;
172};
173
174/**
175 * struct ipa_mem_buffer - IPA memory buffer
176 * @base: base
177 * @phys_base: physical base address
178 * @size: size of memory buffer
179 */
180struct ipa_mem_buffer {
181 void *base;
182 dma_addr_t phys_base;
183 u32 size;
184};
185
Amir Levy9659e592016-10-27 18:08:27 +0300186/**
187 * enum ipa3_mhi_burst_mode - MHI channel burst mode state
188 *
189 * Values are according to MHI specification
190 * @IPA_MHI_BURST_MODE_DEFAULT: burst mode enabled for HW channels,
191 * disabled for SW channels
192 * @IPA_MHI_BURST_MODE_RESERVED:
193 * @IPA_MHI_BURST_MODE_DISABLE: Burst mode is disabled for this channel
194 * @IPA_MHI_BURST_MODE_ENABLE: Burst mode is enabled for this channel
195 *
196 */
197enum ipa3_mhi_burst_mode {
198 IPA_MHI_BURST_MODE_DEFAULT,
199 IPA_MHI_BURST_MODE_RESERVED,
200 IPA_MHI_BURST_MODE_DISABLE,
201 IPA_MHI_BURST_MODE_ENABLE,
202};
203
204/**
205 * enum ipa_hw_mhi_channel_states - MHI channel state machine
206 *
207 * Values are according to MHI specification
208 * @IPA_HW_MHI_CHANNEL_STATE_DISABLE: Channel is disabled and not processed by
209 * the host or device.
210 * @IPA_HW_MHI_CHANNEL_STATE_ENABLE: A channel is enabled after being
211 * initialized and configured by host, including its channel context and
212 * associated transfer ring. While this state, the channel is not active
213 * and the device does not process transfer.
214 * @IPA_HW_MHI_CHANNEL_STATE_RUN: The device processes transfers and doorbell
215 * for channels.
216 * @IPA_HW_MHI_CHANNEL_STATE_SUSPEND: Used to halt operations on the channel.
217 * The device does not process transfers for the channel in this state.
218 * This state is typically used to synchronize the transition to low power
219 * modes.
220 * @IPA_HW_MHI_CHANNEL_STATE_STOP: Used to halt operations on the channel.
221 * The device does not process transfers for the channel in this state.
222 * @IPA_HW_MHI_CHANNEL_STATE_ERROR: The device detected an error in an element
223 * from the transfer ring associated with the channel.
224 * @IPA_HW_MHI_CHANNEL_STATE_INVALID: Invalid state. Shall not be in use in
225 * operational scenario.
226 */
227enum ipa_hw_mhi_channel_states {
228 IPA_HW_MHI_CHANNEL_STATE_DISABLE = 0,
229 IPA_HW_MHI_CHANNEL_STATE_ENABLE = 1,
230 IPA_HW_MHI_CHANNEL_STATE_RUN = 2,
231 IPA_HW_MHI_CHANNEL_STATE_SUSPEND = 3,
232 IPA_HW_MHI_CHANNEL_STATE_STOP = 4,
233 IPA_HW_MHI_CHANNEL_STATE_ERROR = 5,
234 IPA_HW_MHI_CHANNEL_STATE_INVALID = 0xFF
235};
236
237/**
238 * Structure holding the parameters for IPA_CPU_2_HW_CMD_MHI_DL_UL_SYNC_INFO
239 * command. Parameters are sent as 32b immediate parameters.
240 * @isDlUlSyncEnabled: Flag to indicate if DL UL Syncronization is enabled
241 * @UlAccmVal: UL Timer Accumulation value (Period after which device will poll
242 * for UL data)
243 * @ulMsiEventThreshold: Threshold at which HW fires MSI to host for UL events
244 * @dlMsiEventThreshold: Threshold at which HW fires MSI to host for DL events
245 */
246union IpaHwMhiDlUlSyncCmdData_t {
247 struct IpaHwMhiDlUlSyncCmdParams_t {
248 u32 isDlUlSyncEnabled:8;
249 u32 UlAccmVal:8;
250 u32 ulMsiEventThreshold:8;
251 u32 dlMsiEventThreshold:8;
252 } params;
253 u32 raw32b;
254};
255
256struct ipa_mhi_ch_ctx {
257 u8 chstate;/*0-7*/
258 u8 brstmode:2;/*8-9*/
259 u8 pollcfg:6;/*10-15*/
260 u16 rsvd;/*16-31*/
261 u32 chtype;
262 u32 erindex;
263 u64 rbase;
264 u64 rlen;
265 u64 rp;
266 u64 wp;
267} __packed;
268
269struct ipa_mhi_ev_ctx {
270 u32 intmodc:16;
271 u32 intmodt:16;
272 u32 ertype;
273 u32 msivec;
274 u64 rbase;
275 u64 rlen;
276 u64 rp;
277 u64 wp;
278} __packed;
279
280struct ipa_mhi_init_uc_engine {
281 struct ipa_mhi_msi_info *msi;
282 u32 mmio_addr;
283 u32 host_ctrl_addr;
284 u32 host_data_addr;
285 u32 first_ch_idx;
286 u32 first_er_idx;
287 union IpaHwMhiDlUlSyncCmdData_t *ipa_cached_dl_ul_sync_info;
288};
289
290struct ipa_mhi_init_gsi_engine {
291 u32 first_ch_idx;
292};
293
294struct ipa_mhi_init_engine {
295 struct ipa_mhi_init_uc_engine uC;
296 struct ipa_mhi_init_gsi_engine gsi;
297};
298
299struct start_gsi_channel {
300 enum ipa_hw_mhi_channel_states state;
301 struct ipa_mhi_msi_info *msi;
302 struct ipa_mhi_ev_ctx *ev_ctx_host;
303 u64 event_context_addr;
304 struct ipa_mhi_ch_ctx *ch_ctx_host;
305 u64 channel_context_addr;
306 void (*ch_err_cb)(struct gsi_chan_err_notify *notify);
307 void (*ev_err_cb)(struct gsi_evt_err_notify *notify);
308 void *channel;
309 bool assert_bit40;
310 struct gsi_mhi_channel_scratch *mhi;
311 unsigned long *cached_gsi_evt_ring_hdl;
312 uint8_t evchid;
313};
314
315struct start_uc_channel {
316 enum ipa_hw_mhi_channel_states state;
317 u8 index;
318 u8 id;
319};
320
321struct start_mhi_channel {
322 struct start_uc_channel uC;
323 struct start_gsi_channel gsi;
324};
325
326struct ipa_mhi_connect_params_internal {
327 struct ipa_sys_connect_params *sys;
328 u8 channel_id;
329 struct start_mhi_channel start;
330};
331
332/**
333 * struct ipa_hdr_offset_entry - IPA header offset entry
334 * @link: entry's link in global header offset entries list
335 * @offset: the offset
336 * @bin: bin
Skylar Chang68c37d82018-04-07 16:42:36 -0700337 * @ipacm_installed: indicate if installed by ipacm
Amir Levy9659e592016-10-27 18:08:27 +0300338 */
339struct ipa_hdr_offset_entry {
340 struct list_head link;
341 u32 offset;
342 u32 bin;
Skylar Chang68c37d82018-04-07 16:42:36 -0700343 bool ipacm_installed;
Amir Levy9659e592016-10-27 18:08:27 +0300344};
345
346extern const char *ipa_clients_strings[];
347
348#define IPA_IPC_LOGGING(buf, fmt, args...) \
349 do { \
350 if (buf) \
351 ipc_log_string((buf), fmt, __func__, __LINE__, \
352 ## args); \
353 } while (0)
354
355void ipa_inc_client_enable_clks(struct ipa_active_client_logging_info *id);
356void ipa_dec_client_disable_clks(struct ipa_active_client_logging_info *id);
357int ipa_inc_client_enable_clks_no_block(
358 struct ipa_active_client_logging_info *id);
359int ipa_suspend_resource_no_block(enum ipa_rm_resource_name resource);
360int ipa_resume_resource(enum ipa_rm_resource_name name);
361int ipa_suspend_resource_sync(enum ipa_rm_resource_name resource);
362int ipa_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
363 u32 bandwidth_mbps);
364void *ipa_get_ipc_logbuf(void);
365void *ipa_get_ipc_logbuf_low(void);
366void ipa_assert(void);
367
368/* MHI */
369int ipa_mhi_init_engine(struct ipa_mhi_init_engine *params);
370int ipa_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in,
371 u32 *clnt_hdl);
372int ipa_disconnect_mhi_pipe(u32 clnt_hdl);
373bool ipa_mhi_stop_gsi_channel(enum ipa_client_type client);
374int ipa_qmi_enable_force_clear_datapath_send(
375 struct ipa_enable_force_clear_datapath_req_msg_v01 *req);
376int ipa_qmi_disable_force_clear_datapath_send(
377 struct ipa_disable_force_clear_datapath_req_msg_v01 *req);
378int ipa_generate_tag_process(void);
379int ipa_disable_sps_pipe(enum ipa_client_type client);
380int ipa_mhi_reset_channel_internal(enum ipa_client_type client);
381int ipa_mhi_start_channel_internal(enum ipa_client_type client);
382bool ipa_mhi_sps_channel_empty(enum ipa_client_type client);
383int ipa_mhi_resume_channels_internal(enum ipa_client_type client,
384 bool LPTransitionRejected, bool brstmode_enabled,
385 union __packed gsi_channel_scratch ch_scratch, u8 index);
386int ipa_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req);
387int ipa_mhi_query_ch_info(enum ipa_client_type client,
388 struct gsi_chan_info *ch_info);
389int ipa_mhi_destroy_channel(enum ipa_client_type client);
390int ipa_mhi_is_using_dma(bool *flag);
391const char *ipa_mhi_get_state_str(int state);
392
393/* MHI uC */
394int ipa_uc_mhi_send_dl_ul_sync_info(union IpaHwMhiDlUlSyncCmdData_t *cmd);
395int ipa_uc_mhi_init
396 (void (*ready_cb)(void), void (*wakeup_request_cb)(void));
397void ipa_uc_mhi_cleanup(void);
398int ipa_uc_mhi_reset_channel(int channelHandle);
399int ipa_uc_mhi_suspend_channel(int channelHandle);
400int ipa_uc_mhi_stop_event_update_channel(int channelHandle);
401int ipa_uc_mhi_print_stats(char *dbg_buff, int size);
402
403/* uC */
404int ipa_uc_state_check(void);
405
406/* general */
407void ipa_get_holb(int ep_idx, struct ipa_ep_cfg_holb *holb);
408void ipa_set_tag_process_before_gating(bool val);
409bool ipa_has_open_aggr_frame(enum ipa_client_type client);
410int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
411 ipa_notify_cb notify, void *priv, u8 hdr_len,
412 struct ipa_ntn_conn_out_params *outp);
413
Michael Adisumartab1bafa42018-04-16 16:48:10 -0700414int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl,
415 struct ipa_ntn_conn_in_params *params);
Amir Levy9659e592016-10-27 18:08:27 +0300416u8 *ipa_write_64(u64 w, u8 *dest);
417u8 *ipa_write_32(u32 w, u8 *dest);
418u8 *ipa_write_16(u16 hw, u8 *dest);
419u8 *ipa_write_8(u8 b, u8 *dest);
420u8 *ipa_pad_to_64(u8 *dest);
421u8 *ipa_pad_to_32(u8 *dest);
Sunil Paidimarrifbbcd072017-04-04 17:43:50 -0700422int ipa_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *user_data),
423 void *user_data);
424void ipa_ntn_uc_dereg_rdyCB(void);
Skylar Chang852379b2016-12-13 14:00:19 -0800425
Shihuan Liu105b31f2017-11-21 11:43:58 -0800426int ipa_conn_wdi_pipes(struct ipa_wdi_conn_in_params *in,
427 struct ipa_wdi_conn_out_params *out,
428 ipa_wdi_meter_notifier_cb wdi_notify);
Skylar Chang852379b2016-12-13 14:00:19 -0800429
Shihuan Liu105b31f2017-11-21 11:43:58 -0800430int ipa_disconn_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
Skylar Chang852379b2016-12-13 14:00:19 -0800431
Shihuan Liu105b31f2017-11-21 11:43:58 -0800432int ipa_enable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
Skylar Chang852379b2016-12-13 14:00:19 -0800433
Shihuan Liu105b31f2017-11-21 11:43:58 -0800434int ipa_disable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
Skylar Chang852379b2016-12-13 14:00:19 -0800435
Amir Levy9659e592016-10-27 18:08:27 +0300436const char *ipa_get_version_string(enum ipa_hw_type ver);
Skylar Chang9fbce062017-07-25 16:20:42 -0700437int ipa_start_gsi_channel(u32 clnt_hdl);
Amir Levy9659e592016-10-27 18:08:27 +0300438
Michael Adisumarta3e350812017-09-18 14:54:36 -0700439bool ipa_pm_is_used(void);
440
Michael Adisumartab1bafa42018-04-16 16:48:10 -0700441int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr,
442 struct sg_table *in_sgt_ptr);
443int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr);
444
Jennifer L. Zennerdf159af2018-04-25 16:44:38 -0400445int ipa_ut_module_init(void);
446void ipa_ut_module_exit(void);
447
Ashok Vuyyuru27ede172019-01-28 15:35:55 +0530448void ipa_register_client_callback(int (*client_cb)(bool is_lock),
449 bool (*teth_port_state)(void), u32 ipa_ep_idx);
450
451void ipa_deregister_client_callback(u32 ipa_ep_idx);
452
Amir Levy9659e592016-10-27 18:08:27 +0300453#endif /* _IPA_COMMON_I_H_ */