Loading drivers/platform/msm/ipa/ipa_api.c +214 −98 Original line number Diff line number Diff line Loading @@ -73,6 +73,24 @@ } \ } while (0) #define IPA_API_DISPATCH_RETURN_BOOL(api, p...) \ do { \ if (!ipa_api_ctrl) { \ pr_err("IPA HW is not supported on this target\n"); \ ret = false; \ } \ else { \ if (ipa_api_ctrl->api) { \ ret = ipa_api_ctrl->api(p); \ } else { \ pr_err("%s not implemented for IPA ver %d\n", \ __func__, ipa_api_hw_type); \ WARN_ON(1); \ ret = false; \ } \ } \ } while (0) static enum ipa_hw_type ipa_api_hw_type; static struct ipa_api_controller *ipa_api_ctrl; Loading Loading @@ -1778,63 +1796,23 @@ void ipa_dma_destroy(void) } EXPORT_SYMBOL(ipa_dma_destroy); /** * ipa_mhi_init() - Initialize IPA MHI driver * @params: initialization params * * This function is called by MHI client driver on boot to initialize IPA MHI * Driver. When this function returns device can move to READY state. * This function is doing the following: * - Initialize MHI IPA internal data structures * - Create IPA RM resources * - Initialize debugfs * * Return codes: 0 : success * negative : error */ int ipa_mhi_init(struct ipa_mhi_init_params *params) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_init, params); return ret; } EXPORT_SYMBOL(ipa_mhi_init); /** * ipa_mhi_start() - Start IPA MHI engine * @params: pcie addresses for MHI * * This function is called by MHI client driver on MHI engine start for * handling MHI accelerated channels. This function is called after * ipa_mhi_init() was called and can be called after MHI reset to restart MHI * engine. When this function returns device can move to M0 state. * This function is doing the following: * - Send command to uC for initialization of MHI engine * - Add dependencies to IPA RM * - Request MHI_PROD in IPA RM * * Return codes: 0 : success * negative : error */ int ipa_mhi_start(struct ipa_mhi_start_params *params) int ipa_mhi_init_engine(struct ipa_mhi_init_engine *params) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_start, params); IPA_API_DISPATCH_RETURN(ipa_mhi_init_engine, params); return ret; } EXPORT_SYMBOL(ipa_mhi_start); EXPORT_SYMBOL(ipa_mhi_init_engine); /** * ipa_mhi_connect_pipe() - Connect pipe to IPA and start corresponding * ipa_connect_mhi_pipe() - Connect pipe to IPA and start corresponding * MHI channel * @in: connect parameters * @clnt_hdl: [out] client handle for this pipe * * This function is called by MHI client driver on MHI channel start. * This function is called by IPA MHI client driver on MHI channel start. * This function is called after MHI engine was started. * This function is doing the following: * - Send command to uC to start corresponding MHI channel Loading @@ -1843,23 +1821,24 @@ EXPORT_SYMBOL(ipa_mhi_start); * Return codes: 0 : success * negative : error */ int ipa_mhi_connect_pipe(struct ipa_mhi_connect_params *in, u32 *clnt_hdl) int ipa_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in, u32 *clnt_hdl) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_connect_pipe, in, clnt_hdl); IPA_API_DISPATCH_RETURN(ipa_connect_mhi_pipe, in, clnt_hdl); return ret; } EXPORT_SYMBOL(ipa_mhi_connect_pipe); EXPORT_SYMBOL(ipa_connect_mhi_pipe); /** * ipa_mhi_disconnect_pipe() - Disconnect pipe from IPA and reset corresponding * ipa_disconnect_mhi_pipe() - Disconnect pipe from IPA and reset corresponding * MHI channel * @in: connect parameters * @clnt_hdl: [out] client handle for this pipe * * This function is called by MHI client driver on MHI channel reset. * This function is called by IPA MHI client driver on MHI channel reset. * This function is called after MHI channel was started. * This function is doing the following: * - Send command to uC to reset corresponding MHI channel Loading @@ -1868,81 +1847,218 @@ EXPORT_SYMBOL(ipa_mhi_connect_pipe); * Return codes: 0 : success * negative : error */ int ipa_mhi_disconnect_pipe(u32 clnt_hdl) int ipa_disconnect_mhi_pipe(u32 clnt_hdl) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_disconnect_pipe, clnt_hdl); IPA_API_DISPATCH_RETURN(ipa_disconnect_mhi_pipe, clnt_hdl); return ret; } EXPORT_SYMBOL(ipa_mhi_disconnect_pipe); EXPORT_SYMBOL(ipa_disconnect_mhi_pipe); /** * ipa_mhi_suspend() - Suspend MHI accelerated channels * @force: * false: in case of data pending in IPA, MHI channels will not be * suspended and function will fail. * true: in case of data pending in IPA, make sure no further access from * IPA to PCIe is possible. In this case suspend cannot fail. * * This function is called by MHI client driver on MHI suspend. * This function is called after MHI channel was started. * When this function returns device can move to M1/M2/M3/D3cold state. * This function is doing the following: * - Send command to uC to suspend corresponding MHI channel * - Make sure no further access is possible from IPA to PCIe * - Release MHI_PROD in IPA RM * * Return codes: 0 : success * negative : error */ int ipa_mhi_suspend(bool force) bool ipa_mhi_stop_gsi_channel(enum ipa_client_type client) { bool ret; IPA_API_DISPATCH_RETURN_BOOL(ipa_mhi_stop_gsi_channel, client); return ret; } int ipa_uc_mhi_reset_channel(int channelHandle) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_suspend, force); IPA_API_DISPATCH_RETURN(ipa_uc_mhi_reset_channel, channelHandle); return ret; } EXPORT_SYMBOL(ipa_mhi_suspend); /** * ipa_mhi_resume() - Resume MHI accelerated channels * * This function is called by MHI client driver on MHI resume. * This function is called after MHI channel was suspended. * When this function returns device can move to M0 state. * This function is doing the following: * - Send command to uC to resume corresponding MHI channel * - Request MHI_PROD in IPA RM * - Resume data to IPA * * Return codes: 0 : success * negative : error */ int ipa_mhi_resume(void) bool ipa_mhi_sps_channel_empty(enum ipa_client_type client) { bool ret; IPA_API_DISPATCH_RETURN_BOOL(ipa_mhi_sps_channel_empty, client); return ret; } int ipa_qmi_enable_force_clear_datapath_send( struct ipa_enable_force_clear_datapath_req_msg_v01 *req) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_resume); IPA_API_DISPATCH_RETURN(ipa_qmi_enable_force_clear_datapath_send, req); return ret; } int ipa_qmi_disable_force_clear_datapath_send( struct ipa_disable_force_clear_datapath_req_msg_v01 *req) { int ret; IPA_API_DISPATCH_RETURN(ipa_qmi_disable_force_clear_datapath_send, req); return ret; } int ipa_generate_tag_process(void) { int ret; IPA_API_DISPATCH_RETURN(ipa_generate_tag_process); return ret; } int ipa_disable_sps_pipe(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_disable_sps_pipe, client); return ret; } int ipa_mhi_reset_channel_internal(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_reset_channel_internal, client); return ret; } int ipa_mhi_start_channel_internal(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_start_channel_internal, client); return ret; } void ipa_get_holb(int ep_idx, struct ipa_ep_cfg_holb *holb) { IPA_API_DISPATCH(ipa_get_holb, ep_idx, holb); } void ipa_set_tag_process_before_gating(bool val) { IPA_API_DISPATCH(ipa_set_tag_process_before_gating, val); } int ipa_mhi_query_ch_info(enum ipa_client_type client, struct gsi_chan_info *ch_info) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_query_ch_info, client, ch_info); return ret; } int ipa_uc_mhi_suspend_channel(int channelHandle) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_suspend_channel, channelHandle); return ret; } int ipa_uc_mhi_stop_event_update_channel(int channelHandle) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_stop_event_update_channel, channelHandle); return ret; } bool ipa_has_open_aggr_frame(enum ipa_client_type client) { bool ret; IPA_API_DISPATCH_RETURN_BOOL(ipa_has_open_aggr_frame, client); return ret; } int ipa_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, union __packed gsi_channel_scratch ch_scratch, u8 index) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_resume_channels_internal, client, LPTransitionRejected, brstmode_enabled, ch_scratch, index); return ret; } int ipa_uc_mhi_send_dl_ul_sync_info(union IpaHwMhiDlUlSyncCmdData_t *cmd) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_send_dl_ul_sync_info, cmd); return ret; } int ipa_mhi_destroy_channel(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_destroy_channel, client); return ret; } int ipa_uc_mhi_init(void (*ready_cb)(void), void (*wakeup_request_cb)(void)) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_init, ready_cb, wakeup_request_cb); return ret; } void ipa_uc_mhi_cleanup(void) { IPA_API_DISPATCH(ipa_uc_mhi_cleanup); } int ipa_uc_mhi_print_stats(char *dbg_buff, int size) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_print_stats, dbg_buff, size); return ret; } EXPORT_SYMBOL(ipa_mhi_resume); /** * ipa_mhi_destroy() - Destroy MHI IPA * ipa_uc_state_check() - Check the status of the uC interface * * This function is called by MHI client driver on MHI reset to destroy all IPA * MHI resources. * Return value: 0 if the uC is loaded, interface is initialized * and there was no recent failure in one of the commands. * A negative value is returned otherwise. */ void ipa_mhi_destroy(void) int ipa_uc_state_check(void) { IPA_API_DISPATCH(ipa_mhi_destroy); int ret; IPA_API_DISPATCH_RETURN(ipa_uc_state_check); return ret; } EXPORT_SYMBOL(ipa_mhi_destroy); int ipa_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) { Loading drivers/platform/msm/ipa/ipa_api.h +56 −7 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ * GNU General Public License for more details. */ #include <linux/ipa_mhi.h> #include "ipa_common_i.h" #ifndef _IPA_API_H_ Loading Loading @@ -214,20 +215,68 @@ struct ipa_api_controller { void (*ipa_dma_destroy)(void); int (*ipa_mhi_init)(struct ipa_mhi_init_params *params); bool (*ipa_has_open_aggr_frame)(enum ipa_client_type client); int (*ipa_mhi_start)(struct ipa_mhi_start_params *params); int (*ipa_generate_tag_process)(void); int (*ipa_mhi_connect_pipe)(struct ipa_mhi_connect_params *in, int (*ipa_disable_sps_pipe)(enum ipa_client_type client); void (*ipa_set_tag_process_before_gating)(bool val); int (*ipa_mhi_init_engine)(struct ipa_mhi_init_engine *params); int (*ipa_connect_mhi_pipe)(struct ipa_mhi_connect_params_internal *in, u32 *clnt_hdl); int (*ipa_mhi_disconnect_pipe)(u32 clnt_hdl); int (*ipa_disconnect_mhi_pipe)(u32 clnt_hdl); bool (*ipa_mhi_stop_gsi_channel)(enum ipa_client_type client); int (*ipa_qmi_disable_force_clear)(u32 request_id); int (*ipa_qmi_enable_force_clear_datapath_send)( struct ipa_enable_force_clear_datapath_req_msg_v01 *req); int (*ipa_qmi_disable_force_clear_datapath_send)( struct ipa_disable_force_clear_datapath_req_msg_v01 *req); bool (*ipa_mhi_sps_channel_empty)(enum ipa_client_type client); int (*ipa_mhi_reset_channel_internal)(enum ipa_client_type client); int (*ipa_mhi_start_channel_internal)(enum ipa_client_type client); void (*ipa_get_holb)(int ep_idx, struct ipa_ep_cfg_holb *holb); int (*ipa_mhi_query_ch_info)(enum ipa_client_type client, struct gsi_chan_info *ch_info); int (*ipa_mhi_resume_channels_internal)( enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, union __packed gsi_channel_scratch ch_scratch, u8 index); int (*ipa_mhi_destroy_channel)(enum ipa_client_type client); int (*ipa_uc_mhi_send_dl_ul_sync_info) (union IpaHwMhiDlUlSyncCmdData_t *cmd); int (*ipa_uc_mhi_init) (void (*ready_cb)(void), void (*wakeup_request_cb)(void)); void (*ipa_uc_mhi_cleanup)(void); int (*ipa_uc_mhi_print_stats)(char *dbg_buff, int size); int (*ipa_uc_mhi_reset_channel)(int channelHandle); int (*ipa_mhi_suspend)(bool force); int (*ipa_uc_mhi_suspend_channel)(int channelHandle); int (*ipa_mhi_resume)(void); int (*ipa_uc_mhi_stop_event_update_channel)(int channelHandle); void (*ipa_mhi_destroy)(void); int (*ipa_uc_state_check)(void); int (*ipa_write_qmap_id)(struct ipa_ioc_write_qmapid *param_in); Loading drivers/platform/msm/ipa/ipa_clients/Makefile +2 −2 Original line number Diff line number Diff line obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o obj-$(CONFIG_IPA) += odu_bridge.o No newline at end of file obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o ipa_mhi_client.o obj-$(CONFIG_IPA) += odu_bridge.o ipa_mhi_client.o No newline at end of file drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c 0 → 100644 +2589 −0 File added.Preview size limit exceeded, changes collapsed. Show changes drivers/platform/msm/ipa/ipa_common_i.h +189 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,9 @@ * GNU General Public License for more details. */ #include <linux/ipa_mhi.h> #include <linux/ipa_qmi_service_v01.h> #ifndef _IPA_COMMON_I_H_ #define _IPA_COMMON_I_H_ #include <linux/ipc_logging.h> Loading Loading @@ -103,6 +106,12 @@ do {\ ipa_assert();\ } while (0) #define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS) #define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX) #define IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC (1000) #define IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC (2000) enum ipa_active_client_log_type { EP, SIMPLE, Loading @@ -118,6 +127,146 @@ struct ipa_active_client_logging_info { enum ipa_active_client_log_type type; }; /** * struct ipa_mem_buffer - IPA memory buffer * @base: base * @phys_base: physical base address * @size: size of memory buffer */ struct ipa_mem_buffer { void *base; dma_addr_t phys_base; u32 size; }; /** * enum ipa_hw_mhi_channel_states - MHI channel state machine * * Values are according to MHI specification * @IPA_HW_MHI_CHANNEL_STATE_DISABLE: Channel is disabled and not processed by * the host or device. * @IPA_HW_MHI_CHANNEL_STATE_ENABLE: A channel is enabled after being * initialized and configured by host, including its channel context and * associated transfer ring. While this state, the channel is not active * and the device does not process transfer. * @IPA_HW_MHI_CHANNEL_STATE_RUN: The device processes transfers and doorbell * for channels. * @IPA_HW_MHI_CHANNEL_STATE_SUSPEND: Used to halt operations on the channel. * The device does not process transfers for the channel in this state. * This state is typically used to synchronize the transition to low power * modes. * @IPA_HW_MHI_CHANNEL_STATE_STOP: Used to halt operations on the channel. * The device does not process transfers for the channel in this state. * @IPA_HW_MHI_CHANNEL_STATE_ERROR: The device detected an error in an element * from the transfer ring associated with the channel. * @IPA_HW_MHI_CHANNEL_STATE_INVALID: Invalid state. Shall not be in use in * operational scenario. */ enum ipa_hw_mhi_channel_states { IPA_HW_MHI_CHANNEL_STATE_DISABLE = 0, IPA_HW_MHI_CHANNEL_STATE_ENABLE = 1, IPA_HW_MHI_CHANNEL_STATE_RUN = 2, IPA_HW_MHI_CHANNEL_STATE_SUSPEND = 3, IPA_HW_MHI_CHANNEL_STATE_STOP = 4, IPA_HW_MHI_CHANNEL_STATE_ERROR = 5, IPA_HW_MHI_CHANNEL_STATE_INVALID = 0xFF }; /** * Structure holding the parameters for IPA_CPU_2_HW_CMD_MHI_DL_UL_SYNC_INFO * command. Parameters are sent as 32b immediate parameters. * @isDlUlSyncEnabled: Flag to indicate if DL UL Syncronization is enabled * @UlAccmVal: UL Timer Accumulation value (Period after which device will poll * for UL data) * @ulMsiEventThreshold: Threshold at which HW fires MSI to host for UL events * @dlMsiEventThreshold: Threshold at which HW fires MSI to host for DL events */ union IpaHwMhiDlUlSyncCmdData_t { struct IpaHwMhiDlUlSyncCmdParams_t { u32 isDlUlSyncEnabled:8; u32 UlAccmVal:8; u32 ulMsiEventThreshold:8; u32 dlMsiEventThreshold:8; } params; u32 raw32b; }; struct ipa_mhi_ch_ctx { u8 chstate;/*0-7*/ u8 brstmode:2;/*8-9*/ u8 pollcfg:6;/*10-15*/ u16 rsvd;/*16-31*/ u32 chtype; u32 erindex; u64 rbase; u64 rlen; u64 rp; u64 wp; } __packed; struct ipa_mhi_ev_ctx { u32 intmodc:16; u32 intmodt:16; u32 ertype; u32 msivec; u64 rbase; u64 rlen; u64 rp; u64 wp; } __packed; struct ipa_mhi_init_uc_engine { struct ipa_mhi_msi_info *msi; u32 mmio_addr; u32 host_ctrl_addr; u32 host_data_addr; u32 first_ch_idx; u32 first_er_idx; union IpaHwMhiDlUlSyncCmdData_t *ipa_cached_dl_ul_sync_info; }; struct ipa_mhi_init_gsi_engine { u32 first_ch_idx; }; struct ipa_mhi_init_engine { struct ipa_mhi_init_uc_engine uC; struct ipa_mhi_init_gsi_engine gsi; }; struct start_gsi_channel { enum ipa_hw_mhi_channel_states state; struct ipa_mhi_msi_info *msi; struct ipa_mhi_ev_ctx *ev_ctx_host; u64 event_context_addr; struct ipa_mhi_ch_ctx *ch_ctx_host; u64 channel_context_addr; void (*ch_err_cb)(struct gsi_chan_err_notify *notify); void (*ev_err_cb)(struct gsi_evt_err_notify *notify); void *channel; bool assert_bit40; struct gsi_mhi_channel_scratch *mhi; unsigned long *cached_gsi_evt_ring_hdl; uint8_t evchid; }; struct start_uc_channel { enum ipa_hw_mhi_channel_states state; u8 index; u8 id; }; struct start_mhi_channel { struct start_uc_channel uC; struct start_gsi_channel gsi; }; struct ipa_mhi_connect_params_internal { struct ipa_sys_connect_params *sys; u8 channel_id; struct start_mhi_channel start; }; extern const char *ipa_clients_strings[]; #define IPA_IPC_LOGGING(buf, fmt, args...) \ Loading @@ -140,5 +289,45 @@ void *ipa_get_ipc_logbuf(void); void *ipa_get_ipc_logbuf_low(void); void ipa_assert(void); /* MHI */ int ipa_mhi_init_engine(struct ipa_mhi_init_engine *params); int ipa_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in, u32 *clnt_hdl); int ipa_disconnect_mhi_pipe(u32 clnt_hdl); bool ipa_mhi_stop_gsi_channel(enum ipa_client_type client); int ipa_qmi_enable_force_clear_datapath_send( struct ipa_enable_force_clear_datapath_req_msg_v01 *req); int ipa_qmi_disable_force_clear_datapath_send( struct ipa_disable_force_clear_datapath_req_msg_v01 *req); int ipa_generate_tag_process(void); int ipa_disable_sps_pipe(enum ipa_client_type client); int ipa_mhi_reset_channel_internal(enum ipa_client_type client); int ipa_mhi_start_channel_internal(enum ipa_client_type client); bool ipa_mhi_sps_channel_empty(enum ipa_client_type client); int ipa_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, union __packed gsi_channel_scratch ch_scratch, u8 index); int ipa_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req); int ipa_mhi_query_ch_info(enum ipa_client_type client, struct gsi_chan_info *ch_info); int ipa_mhi_destroy_channel(enum ipa_client_type client); /* MHI uC */ int ipa_uc_mhi_send_dl_ul_sync_info(union IpaHwMhiDlUlSyncCmdData_t *cmd); int ipa_uc_mhi_init (void (*ready_cb)(void), void (*wakeup_request_cb)(void)); void ipa_uc_mhi_cleanup(void); int ipa_uc_mhi_reset_channel(int channelHandle); int ipa_uc_mhi_suspend_channel(int channelHandle); int ipa_uc_mhi_stop_event_update_channel(int channelHandle); int ipa_uc_mhi_print_stats(char *dbg_buff, int size); /* uC */ int ipa_uc_state_check(void); /* general */ void ipa_get_holb(int ep_idx, struct ipa_ep_cfg_holb *holb); void ipa_set_tag_process_before_gating(bool val); bool ipa_has_open_aggr_frame(enum ipa_client_type client); #endif /* _IPA_COMMON_I_H_ */ Loading
drivers/platform/msm/ipa/ipa_api.c +214 −98 Original line number Diff line number Diff line Loading @@ -73,6 +73,24 @@ } \ } while (0) #define IPA_API_DISPATCH_RETURN_BOOL(api, p...) \ do { \ if (!ipa_api_ctrl) { \ pr_err("IPA HW is not supported on this target\n"); \ ret = false; \ } \ else { \ if (ipa_api_ctrl->api) { \ ret = ipa_api_ctrl->api(p); \ } else { \ pr_err("%s not implemented for IPA ver %d\n", \ __func__, ipa_api_hw_type); \ WARN_ON(1); \ ret = false; \ } \ } \ } while (0) static enum ipa_hw_type ipa_api_hw_type; static struct ipa_api_controller *ipa_api_ctrl; Loading Loading @@ -1778,63 +1796,23 @@ void ipa_dma_destroy(void) } EXPORT_SYMBOL(ipa_dma_destroy); /** * ipa_mhi_init() - Initialize IPA MHI driver * @params: initialization params * * This function is called by MHI client driver on boot to initialize IPA MHI * Driver. When this function returns device can move to READY state. * This function is doing the following: * - Initialize MHI IPA internal data structures * - Create IPA RM resources * - Initialize debugfs * * Return codes: 0 : success * negative : error */ int ipa_mhi_init(struct ipa_mhi_init_params *params) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_init, params); return ret; } EXPORT_SYMBOL(ipa_mhi_init); /** * ipa_mhi_start() - Start IPA MHI engine * @params: pcie addresses for MHI * * This function is called by MHI client driver on MHI engine start for * handling MHI accelerated channels. This function is called after * ipa_mhi_init() was called and can be called after MHI reset to restart MHI * engine. When this function returns device can move to M0 state. * This function is doing the following: * - Send command to uC for initialization of MHI engine * - Add dependencies to IPA RM * - Request MHI_PROD in IPA RM * * Return codes: 0 : success * negative : error */ int ipa_mhi_start(struct ipa_mhi_start_params *params) int ipa_mhi_init_engine(struct ipa_mhi_init_engine *params) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_start, params); IPA_API_DISPATCH_RETURN(ipa_mhi_init_engine, params); return ret; } EXPORT_SYMBOL(ipa_mhi_start); EXPORT_SYMBOL(ipa_mhi_init_engine); /** * ipa_mhi_connect_pipe() - Connect pipe to IPA and start corresponding * ipa_connect_mhi_pipe() - Connect pipe to IPA and start corresponding * MHI channel * @in: connect parameters * @clnt_hdl: [out] client handle for this pipe * * This function is called by MHI client driver on MHI channel start. * This function is called by IPA MHI client driver on MHI channel start. * This function is called after MHI engine was started. * This function is doing the following: * - Send command to uC to start corresponding MHI channel Loading @@ -1843,23 +1821,24 @@ EXPORT_SYMBOL(ipa_mhi_start); * Return codes: 0 : success * negative : error */ int ipa_mhi_connect_pipe(struct ipa_mhi_connect_params *in, u32 *clnt_hdl) int ipa_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in, u32 *clnt_hdl) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_connect_pipe, in, clnt_hdl); IPA_API_DISPATCH_RETURN(ipa_connect_mhi_pipe, in, clnt_hdl); return ret; } EXPORT_SYMBOL(ipa_mhi_connect_pipe); EXPORT_SYMBOL(ipa_connect_mhi_pipe); /** * ipa_mhi_disconnect_pipe() - Disconnect pipe from IPA and reset corresponding * ipa_disconnect_mhi_pipe() - Disconnect pipe from IPA and reset corresponding * MHI channel * @in: connect parameters * @clnt_hdl: [out] client handle for this pipe * * This function is called by MHI client driver on MHI channel reset. * This function is called by IPA MHI client driver on MHI channel reset. * This function is called after MHI channel was started. * This function is doing the following: * - Send command to uC to reset corresponding MHI channel Loading @@ -1868,81 +1847,218 @@ EXPORT_SYMBOL(ipa_mhi_connect_pipe); * Return codes: 0 : success * negative : error */ int ipa_mhi_disconnect_pipe(u32 clnt_hdl) int ipa_disconnect_mhi_pipe(u32 clnt_hdl) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_disconnect_pipe, clnt_hdl); IPA_API_DISPATCH_RETURN(ipa_disconnect_mhi_pipe, clnt_hdl); return ret; } EXPORT_SYMBOL(ipa_mhi_disconnect_pipe); EXPORT_SYMBOL(ipa_disconnect_mhi_pipe); /** * ipa_mhi_suspend() - Suspend MHI accelerated channels * @force: * false: in case of data pending in IPA, MHI channels will not be * suspended and function will fail. * true: in case of data pending in IPA, make sure no further access from * IPA to PCIe is possible. In this case suspend cannot fail. * * This function is called by MHI client driver on MHI suspend. * This function is called after MHI channel was started. * When this function returns device can move to M1/M2/M3/D3cold state. * This function is doing the following: * - Send command to uC to suspend corresponding MHI channel * - Make sure no further access is possible from IPA to PCIe * - Release MHI_PROD in IPA RM * * Return codes: 0 : success * negative : error */ int ipa_mhi_suspend(bool force) bool ipa_mhi_stop_gsi_channel(enum ipa_client_type client) { bool ret; IPA_API_DISPATCH_RETURN_BOOL(ipa_mhi_stop_gsi_channel, client); return ret; } int ipa_uc_mhi_reset_channel(int channelHandle) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_suspend, force); IPA_API_DISPATCH_RETURN(ipa_uc_mhi_reset_channel, channelHandle); return ret; } EXPORT_SYMBOL(ipa_mhi_suspend); /** * ipa_mhi_resume() - Resume MHI accelerated channels * * This function is called by MHI client driver on MHI resume. * This function is called after MHI channel was suspended. * When this function returns device can move to M0 state. * This function is doing the following: * - Send command to uC to resume corresponding MHI channel * - Request MHI_PROD in IPA RM * - Resume data to IPA * * Return codes: 0 : success * negative : error */ int ipa_mhi_resume(void) bool ipa_mhi_sps_channel_empty(enum ipa_client_type client) { bool ret; IPA_API_DISPATCH_RETURN_BOOL(ipa_mhi_sps_channel_empty, client); return ret; } int ipa_qmi_enable_force_clear_datapath_send( struct ipa_enable_force_clear_datapath_req_msg_v01 *req) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_resume); IPA_API_DISPATCH_RETURN(ipa_qmi_enable_force_clear_datapath_send, req); return ret; } int ipa_qmi_disable_force_clear_datapath_send( struct ipa_disable_force_clear_datapath_req_msg_v01 *req) { int ret; IPA_API_DISPATCH_RETURN(ipa_qmi_disable_force_clear_datapath_send, req); return ret; } int ipa_generate_tag_process(void) { int ret; IPA_API_DISPATCH_RETURN(ipa_generate_tag_process); return ret; } int ipa_disable_sps_pipe(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_disable_sps_pipe, client); return ret; } int ipa_mhi_reset_channel_internal(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_reset_channel_internal, client); return ret; } int ipa_mhi_start_channel_internal(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_start_channel_internal, client); return ret; } void ipa_get_holb(int ep_idx, struct ipa_ep_cfg_holb *holb) { IPA_API_DISPATCH(ipa_get_holb, ep_idx, holb); } void ipa_set_tag_process_before_gating(bool val) { IPA_API_DISPATCH(ipa_set_tag_process_before_gating, val); } int ipa_mhi_query_ch_info(enum ipa_client_type client, struct gsi_chan_info *ch_info) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_query_ch_info, client, ch_info); return ret; } int ipa_uc_mhi_suspend_channel(int channelHandle) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_suspend_channel, channelHandle); return ret; } int ipa_uc_mhi_stop_event_update_channel(int channelHandle) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_stop_event_update_channel, channelHandle); return ret; } bool ipa_has_open_aggr_frame(enum ipa_client_type client) { bool ret; IPA_API_DISPATCH_RETURN_BOOL(ipa_has_open_aggr_frame, client); return ret; } int ipa_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, union __packed gsi_channel_scratch ch_scratch, u8 index) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_resume_channels_internal, client, LPTransitionRejected, brstmode_enabled, ch_scratch, index); return ret; } int ipa_uc_mhi_send_dl_ul_sync_info(union IpaHwMhiDlUlSyncCmdData_t *cmd) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_send_dl_ul_sync_info, cmd); return ret; } int ipa_mhi_destroy_channel(enum ipa_client_type client) { int ret; IPA_API_DISPATCH_RETURN(ipa_mhi_destroy_channel, client); return ret; } int ipa_uc_mhi_init(void (*ready_cb)(void), void (*wakeup_request_cb)(void)) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_init, ready_cb, wakeup_request_cb); return ret; } void ipa_uc_mhi_cleanup(void) { IPA_API_DISPATCH(ipa_uc_mhi_cleanup); } int ipa_uc_mhi_print_stats(char *dbg_buff, int size) { int ret; IPA_API_DISPATCH_RETURN(ipa_uc_mhi_print_stats, dbg_buff, size); return ret; } EXPORT_SYMBOL(ipa_mhi_resume); /** * ipa_mhi_destroy() - Destroy MHI IPA * ipa_uc_state_check() - Check the status of the uC interface * * This function is called by MHI client driver on MHI reset to destroy all IPA * MHI resources. * Return value: 0 if the uC is loaded, interface is initialized * and there was no recent failure in one of the commands. * A negative value is returned otherwise. */ void ipa_mhi_destroy(void) int ipa_uc_state_check(void) { IPA_API_DISPATCH(ipa_mhi_destroy); int ret; IPA_API_DISPATCH_RETURN(ipa_uc_state_check); return ret; } EXPORT_SYMBOL(ipa_mhi_destroy); int ipa_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) { Loading
drivers/platform/msm/ipa/ipa_api.h +56 −7 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ * GNU General Public License for more details. */ #include <linux/ipa_mhi.h> #include "ipa_common_i.h" #ifndef _IPA_API_H_ Loading Loading @@ -214,20 +215,68 @@ struct ipa_api_controller { void (*ipa_dma_destroy)(void); int (*ipa_mhi_init)(struct ipa_mhi_init_params *params); bool (*ipa_has_open_aggr_frame)(enum ipa_client_type client); int (*ipa_mhi_start)(struct ipa_mhi_start_params *params); int (*ipa_generate_tag_process)(void); int (*ipa_mhi_connect_pipe)(struct ipa_mhi_connect_params *in, int (*ipa_disable_sps_pipe)(enum ipa_client_type client); void (*ipa_set_tag_process_before_gating)(bool val); int (*ipa_mhi_init_engine)(struct ipa_mhi_init_engine *params); int (*ipa_connect_mhi_pipe)(struct ipa_mhi_connect_params_internal *in, u32 *clnt_hdl); int (*ipa_mhi_disconnect_pipe)(u32 clnt_hdl); int (*ipa_disconnect_mhi_pipe)(u32 clnt_hdl); bool (*ipa_mhi_stop_gsi_channel)(enum ipa_client_type client); int (*ipa_qmi_disable_force_clear)(u32 request_id); int (*ipa_qmi_enable_force_clear_datapath_send)( struct ipa_enable_force_clear_datapath_req_msg_v01 *req); int (*ipa_qmi_disable_force_clear_datapath_send)( struct ipa_disable_force_clear_datapath_req_msg_v01 *req); bool (*ipa_mhi_sps_channel_empty)(enum ipa_client_type client); int (*ipa_mhi_reset_channel_internal)(enum ipa_client_type client); int (*ipa_mhi_start_channel_internal)(enum ipa_client_type client); void (*ipa_get_holb)(int ep_idx, struct ipa_ep_cfg_holb *holb); int (*ipa_mhi_query_ch_info)(enum ipa_client_type client, struct gsi_chan_info *ch_info); int (*ipa_mhi_resume_channels_internal)( enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, union __packed gsi_channel_scratch ch_scratch, u8 index); int (*ipa_mhi_destroy_channel)(enum ipa_client_type client); int (*ipa_uc_mhi_send_dl_ul_sync_info) (union IpaHwMhiDlUlSyncCmdData_t *cmd); int (*ipa_uc_mhi_init) (void (*ready_cb)(void), void (*wakeup_request_cb)(void)); void (*ipa_uc_mhi_cleanup)(void); int (*ipa_uc_mhi_print_stats)(char *dbg_buff, int size); int (*ipa_uc_mhi_reset_channel)(int channelHandle); int (*ipa_mhi_suspend)(bool force); int (*ipa_uc_mhi_suspend_channel)(int channelHandle); int (*ipa_mhi_resume)(void); int (*ipa_uc_mhi_stop_event_update_channel)(int channelHandle); void (*ipa_mhi_destroy)(void); int (*ipa_uc_state_check)(void); int (*ipa_write_qmap_id)(struct ipa_ioc_write_qmapid *param_in); Loading
drivers/platform/msm/ipa/ipa_clients/Makefile +2 −2 Original line number Diff line number Diff line obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o obj-$(CONFIG_IPA) += odu_bridge.o No newline at end of file obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o ipa_mhi_client.o obj-$(CONFIG_IPA) += odu_bridge.o ipa_mhi_client.o No newline at end of file
drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c 0 → 100644 +2589 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
drivers/platform/msm/ipa/ipa_common_i.h +189 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,9 @@ * GNU General Public License for more details. */ #include <linux/ipa_mhi.h> #include <linux/ipa_qmi_service_v01.h> #ifndef _IPA_COMMON_I_H_ #define _IPA_COMMON_I_H_ #include <linux/ipc_logging.h> Loading Loading @@ -103,6 +106,12 @@ do {\ ipa_assert();\ } while (0) #define IPA_CLIENT_IS_PROD(x) (x >= IPA_CLIENT_PROD && x < IPA_CLIENT_CONS) #define IPA_CLIENT_IS_CONS(x) (x >= IPA_CLIENT_CONS && x < IPA_CLIENT_MAX) #define IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC (1000) #define IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC (2000) enum ipa_active_client_log_type { EP, SIMPLE, Loading @@ -118,6 +127,146 @@ struct ipa_active_client_logging_info { enum ipa_active_client_log_type type; }; /** * struct ipa_mem_buffer - IPA memory buffer * @base: base * @phys_base: physical base address * @size: size of memory buffer */ struct ipa_mem_buffer { void *base; dma_addr_t phys_base; u32 size; }; /** * enum ipa_hw_mhi_channel_states - MHI channel state machine * * Values are according to MHI specification * @IPA_HW_MHI_CHANNEL_STATE_DISABLE: Channel is disabled and not processed by * the host or device. * @IPA_HW_MHI_CHANNEL_STATE_ENABLE: A channel is enabled after being * initialized and configured by host, including its channel context and * associated transfer ring. While this state, the channel is not active * and the device does not process transfer. * @IPA_HW_MHI_CHANNEL_STATE_RUN: The device processes transfers and doorbell * for channels. * @IPA_HW_MHI_CHANNEL_STATE_SUSPEND: Used to halt operations on the channel. * The device does not process transfers for the channel in this state. * This state is typically used to synchronize the transition to low power * modes. * @IPA_HW_MHI_CHANNEL_STATE_STOP: Used to halt operations on the channel. * The device does not process transfers for the channel in this state. * @IPA_HW_MHI_CHANNEL_STATE_ERROR: The device detected an error in an element * from the transfer ring associated with the channel. * @IPA_HW_MHI_CHANNEL_STATE_INVALID: Invalid state. Shall not be in use in * operational scenario. */ enum ipa_hw_mhi_channel_states { IPA_HW_MHI_CHANNEL_STATE_DISABLE = 0, IPA_HW_MHI_CHANNEL_STATE_ENABLE = 1, IPA_HW_MHI_CHANNEL_STATE_RUN = 2, IPA_HW_MHI_CHANNEL_STATE_SUSPEND = 3, IPA_HW_MHI_CHANNEL_STATE_STOP = 4, IPA_HW_MHI_CHANNEL_STATE_ERROR = 5, IPA_HW_MHI_CHANNEL_STATE_INVALID = 0xFF }; /** * Structure holding the parameters for IPA_CPU_2_HW_CMD_MHI_DL_UL_SYNC_INFO * command. Parameters are sent as 32b immediate parameters. * @isDlUlSyncEnabled: Flag to indicate if DL UL Syncronization is enabled * @UlAccmVal: UL Timer Accumulation value (Period after which device will poll * for UL data) * @ulMsiEventThreshold: Threshold at which HW fires MSI to host for UL events * @dlMsiEventThreshold: Threshold at which HW fires MSI to host for DL events */ union IpaHwMhiDlUlSyncCmdData_t { struct IpaHwMhiDlUlSyncCmdParams_t { u32 isDlUlSyncEnabled:8; u32 UlAccmVal:8; u32 ulMsiEventThreshold:8; u32 dlMsiEventThreshold:8; } params; u32 raw32b; }; struct ipa_mhi_ch_ctx { u8 chstate;/*0-7*/ u8 brstmode:2;/*8-9*/ u8 pollcfg:6;/*10-15*/ u16 rsvd;/*16-31*/ u32 chtype; u32 erindex; u64 rbase; u64 rlen; u64 rp; u64 wp; } __packed; struct ipa_mhi_ev_ctx { u32 intmodc:16; u32 intmodt:16; u32 ertype; u32 msivec; u64 rbase; u64 rlen; u64 rp; u64 wp; } __packed; struct ipa_mhi_init_uc_engine { struct ipa_mhi_msi_info *msi; u32 mmio_addr; u32 host_ctrl_addr; u32 host_data_addr; u32 first_ch_idx; u32 first_er_idx; union IpaHwMhiDlUlSyncCmdData_t *ipa_cached_dl_ul_sync_info; }; struct ipa_mhi_init_gsi_engine { u32 first_ch_idx; }; struct ipa_mhi_init_engine { struct ipa_mhi_init_uc_engine uC; struct ipa_mhi_init_gsi_engine gsi; }; struct start_gsi_channel { enum ipa_hw_mhi_channel_states state; struct ipa_mhi_msi_info *msi; struct ipa_mhi_ev_ctx *ev_ctx_host; u64 event_context_addr; struct ipa_mhi_ch_ctx *ch_ctx_host; u64 channel_context_addr; void (*ch_err_cb)(struct gsi_chan_err_notify *notify); void (*ev_err_cb)(struct gsi_evt_err_notify *notify); void *channel; bool assert_bit40; struct gsi_mhi_channel_scratch *mhi; unsigned long *cached_gsi_evt_ring_hdl; uint8_t evchid; }; struct start_uc_channel { enum ipa_hw_mhi_channel_states state; u8 index; u8 id; }; struct start_mhi_channel { struct start_uc_channel uC; struct start_gsi_channel gsi; }; struct ipa_mhi_connect_params_internal { struct ipa_sys_connect_params *sys; u8 channel_id; struct start_mhi_channel start; }; extern const char *ipa_clients_strings[]; #define IPA_IPC_LOGGING(buf, fmt, args...) \ Loading @@ -140,5 +289,45 @@ void *ipa_get_ipc_logbuf(void); void *ipa_get_ipc_logbuf_low(void); void ipa_assert(void); /* MHI */ int ipa_mhi_init_engine(struct ipa_mhi_init_engine *params); int ipa_connect_mhi_pipe(struct ipa_mhi_connect_params_internal *in, u32 *clnt_hdl); int ipa_disconnect_mhi_pipe(u32 clnt_hdl); bool ipa_mhi_stop_gsi_channel(enum ipa_client_type client); int ipa_qmi_enable_force_clear_datapath_send( struct ipa_enable_force_clear_datapath_req_msg_v01 *req); int ipa_qmi_disable_force_clear_datapath_send( struct ipa_disable_force_clear_datapath_req_msg_v01 *req); int ipa_generate_tag_process(void); int ipa_disable_sps_pipe(enum ipa_client_type client); int ipa_mhi_reset_channel_internal(enum ipa_client_type client); int ipa_mhi_start_channel_internal(enum ipa_client_type client); bool ipa_mhi_sps_channel_empty(enum ipa_client_type client); int ipa_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, union __packed gsi_channel_scratch ch_scratch, u8 index); int ipa_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req); int ipa_mhi_query_ch_info(enum ipa_client_type client, struct gsi_chan_info *ch_info); int ipa_mhi_destroy_channel(enum ipa_client_type client); /* MHI uC */ int ipa_uc_mhi_send_dl_ul_sync_info(union IpaHwMhiDlUlSyncCmdData_t *cmd); int ipa_uc_mhi_init (void (*ready_cb)(void), void (*wakeup_request_cb)(void)); void ipa_uc_mhi_cleanup(void); int ipa_uc_mhi_reset_channel(int channelHandle); int ipa_uc_mhi_suspend_channel(int channelHandle); int ipa_uc_mhi_stop_event_update_channel(int channelHandle); int ipa_uc_mhi_print_stats(char *dbg_buff, int size); /* uC */ int ipa_uc_state_check(void); /* general */ void ipa_get_holb(int ep_idx, struct ipa_ep_cfg_holb *holb); void ipa_set_tag_process_before_gating(bool val); bool ipa_has_open_aggr_frame(enum ipa_client_type client); #endif /* _IPA_COMMON_I_H_ */