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