| /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 and |
| * only version 2 as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| #ifndef MSM_MHI_H |
| #define MSM_MHI_H |
| #include <linux/types.h> |
| #include <linux/device.h> |
| #include <linux/scatterlist.h> |
| |
| #define MHI_DMA_MASK 0xFFFFFFFFFFULL |
| #define MHI_MAX_MTU 0xFFFF |
| |
| struct mhi_client_config; |
| struct mhi_device_ctxt; |
| |
| enum MHI_CLIENT_CHANNEL { |
| MHI_CLIENT_LOOPBACK_OUT = 0, |
| MHI_CLIENT_LOOPBACK_IN = 1, |
| MHI_CLIENT_SAHARA_OUT = 2, |
| MHI_CLIENT_SAHARA_IN = 3, |
| MHI_CLIENT_DIAG_OUT = 4, |
| MHI_CLIENT_DIAG_IN = 5, |
| MHI_CLIENT_SSR_OUT = 6, |
| MHI_CLIENT_SSR_IN = 7, |
| MHI_CLIENT_QDSS_OUT = 8, |
| MHI_CLIENT_QDSS_IN = 9, |
| MHI_CLIENT_EFS_OUT = 10, |
| MHI_CLIENT_EFS_IN = 11, |
| MHI_CLIENT_MBIM_OUT = 12, |
| MHI_CLIENT_MBIM_IN = 13, |
| MHI_CLIENT_QMI_OUT = 14, |
| MHI_CLIENT_QMI_IN = 15, |
| MHI_CLIENT_IP_CTRL_0_OUT = 16, |
| MHI_CLIENT_IP_CTRL_0_IN = 17, |
| MHI_CLIENT_IP_CTRL_1_OUT = 18, |
| MHI_CLIENT_IP_CTRL_1_IN = 19, |
| MHI_CLIENT_DCI_OUT = 20, |
| MHI_CLIENT_DCI_IN = 21, |
| MHI_CLIENT_TF_OUT = 22, |
| MHI_CLIENT_TF_IN = 23, |
| MHI_CLIENT_BL_OUT = 24, |
| MHI_CLIENT_BL_IN = 25, |
| MHI_CLIENT_DUN_OUT = 32, |
| MHI_CLIENT_DUN_IN = 33, |
| MHI_CLIENT_IPC_ROUTER_OUT = 34, |
| MHI_CLIENT_IPC_ROUTER_IN = 35, |
| MHI_CLIENT_IP_SW_1_OUT = 36, |
| MHI_CLIENT_IP_SW_1_IN = 37, |
| MHI_CLIENT_IP_SW_2_OUT = 38, |
| MHI_CLIENT_IP_SW_2_IN = 39, |
| MHI_CLIENT_IP_SW_3_OUT = 40, |
| MHI_CLIENT_IP_SW_3_IN = 41, |
| MHI_CLIENT_CSVT_OUT = 42, |
| MHI_CLIENT_CSVT_IN = 43, |
| MHI_CLIENT_SMCT_OUT = 44, |
| MHI_CLIENT_SMCT_IN = 45, |
| MHI_CLIENT_IP_SW_4_OUT = 46, |
| MHI_CLIENT_IP_SW_4_IN = 47, |
| MHI_CLIENT_RESERVED_1_LOWER = 48, |
| MHI_CLIENT_RESERVED_1_UPPER = 99, |
| MHI_CLIENT_IP_HW_0_OUT = 100, |
| MHI_CLIENT_IP_HW_0_IN = 101, |
| MHI_CLIENT_IP_HW_ADPL_IN = 102, |
| MHI_CLIENT_RESERVED_2_LOWER = 103, |
| MHI_CLIENT_RESERVED_2_UPPER = 127, |
| MHI_MAX_CHANNELS = 103 |
| }; |
| |
| enum MHI_CB_REASON { |
| MHI_CB_XFER, |
| MHI_CB_MHI_DISABLED, |
| MHI_CB_MHI_ENABLED, |
| MHI_CB_MHI_SHUTDOWN, |
| MHI_CB_SYS_ERROR, |
| MHI_CB_RDDM, |
| MHI_CB_MHI_PROBED, |
| }; |
| |
| enum MHI_FLAGS { |
| MHI_EOB = 0x100, |
| MHI_EOT = 0x200, |
| MHI_CHAIN = 0x1, |
| MHI_FLAGS_reserved = 0x80000000, |
| }; |
| |
| struct mhi_result { |
| void *user_data; |
| void *buf_addr; |
| size_t bytes_xferd; |
| int transaction_status; |
| enum MHI_FLAGS flags; |
| }; |
| |
| struct mhi_cb_info { |
| struct mhi_result *result; |
| enum MHI_CB_REASON cb_reason; |
| u32 chan; |
| }; |
| |
| struct mhi_client_info_t { |
| enum MHI_CLIENT_CHANNEL chan; |
| const struct device const *dev; |
| const char *node_name; |
| void (*mhi_client_cb)(struct mhi_cb_info *); |
| bool pre_allocate; |
| size_t max_payload; |
| void *user_data; |
| }; |
| |
| struct mhi_client_handle { |
| u32 dev_id; |
| u32 domain; |
| u32 bus; |
| u32 slot; |
| bool enabled; |
| struct mhi_client_config *client_config; |
| }; |
| |
| struct __packed bhi_vec_entry { |
| u64 phys_addr; |
| u64 size; |
| }; |
| |
| /** |
| * struct mhi_device - IO resources for MHI |
| * @dev: device node points to of_node |
| * @pdev: pci device node |
| * @resource: bar memory space and IRQ resources |
| * @support_rddm: this device support ramdump collection |
| * @rddm_size: size of ramdump buffer in bytes to allocate |
| * @pm_runtime_get: fp for bus masters rpm pm_runtime_get |
| * @pm_runtime_noidle: fp for bus masters rpm pm_runtime_noidle |
| * @status_cb: fp for MHI status change notifications |
| * @mhi_dev_ctxt: private data for host |
| */ |
| struct mhi_device { |
| struct device *dev; |
| struct pci_dev *pci_dev; |
| struct resource resources[2]; |
| bool support_rddm; |
| size_t rddm_size; |
| int (*pm_runtime_get)(struct pci_dev *pci_dev); |
| void (*pm_runtime_put_noidle)(struct pci_dev *pci_dev); |
| void (*status_cb)(enum MHI_CB_REASON, void *priv); |
| struct mhi_device_ctxt *mhi_dev_ctxt; |
| }; |
| |
| enum mhi_dev_ctrl { |
| MHI_DEV_CTRL_INIT, |
| MHI_DEV_CTRL_DE_INIT, |
| MHI_DEV_CTRL_SUSPEND, |
| MHI_DEV_CTRL_RESUME, |
| MHI_DEV_CTRL_POWER_OFF, |
| MHI_DEV_CTRL_POWER_ON, |
| MHI_DEV_CTRL_TRIGGER_RDDM, |
| MHI_DEV_CTRL_RDDM, |
| MHI_DEV_CTRL_RDDM_KERNEL_PANIC, |
| MHI_DEV_CTRL_NOTIFY_LINK_ERROR, |
| MHI_DEV_CTRL_MAXCMD, |
| }; |
| |
| enum mhi_rddm_segment { |
| MHI_RDDM_FW_SEGMENT, |
| MHI_RDDM_RD_SEGMENT, |
| }; |
| |
| #if defined(CONFIG_MSM_MHI) |
| /** |
| * mhi_is_device_ready - Check if MHI is ready to register clients |
| * |
| * @dev: device node that points to DT node |
| * @node_name: device tree node that links MHI node |
| * |
| * @Return true if ready |
| */ |
| bool mhi_is_device_ready(const struct device const *dev, |
| const char *node_name); |
| |
| /** |
| * mhi_resgister_device - register hardware resources with MHI |
| * |
| * @mhi_device: resources to be used |
| * @node_name: DT node name |
| * @userdata: cb data for client |
| * @Return 0 on success |
| */ |
| int mhi_register_device(struct mhi_device *mhi_device, const char *node_name, |
| void *user_data); |
| |
| /** |
| * mhi_register_channel - Client must call this function to obtain a handle for |
| * any MHI operations |
| * |
| * @client_handle: Handle populated by MHI, opaque to client |
| * @client_info: Channel\device information provided by client to |
| * which the handle maps to. |
| * |
| * @Return errno |
| */ |
| int mhi_register_channel(struct mhi_client_handle **client_handle, |
| struct mhi_client_info_t *client_info); |
| |
| /** |
| * mhi_pm_control_device - power management control api |
| * @mhi_device: registered device structure |
| * @ctrl: specific command |
| * @Return 0 on success |
| */ |
| int mhi_pm_control_device(struct mhi_device *mhi_device, |
| enum mhi_dev_ctrl ctrl); |
| |
| /** |
| * mhi_xfer_rddm - transfer rddm segment to bus master |
| * @mhi_device: registered device structure |
| * @seg: scatterlist pointing to segments |
| * @Return: # of segments, 0 if no segment available |
| */ |
| int mhi_xfer_rddm(struct mhi_device *mhi_device, enum mhi_rddm_segment seg, |
| struct scatterlist **sg_list); |
| |
| /** |
| * mhi_deregister_channel - de-register callbacks from MHI |
| * |
| * @client_handle: Handle populated by MHI, opaque to client |
| * |
| * @Return errno |
| */ |
| int mhi_deregister_channel(struct mhi_client_handle *client_handle); |
| |
| /** |
| * mhi_open_channel - Client must call this function to open a channel |
| * |
| * @client_handle: Handle populated by MHI, opaque to client |
| * |
| * Not thread safe, caller must ensure concurrency protection. |
| * |
| * @Return errno |
| */ |
| int mhi_open_channel(struct mhi_client_handle *client_handle); |
| |
| /** |
| * mhi_queue_xfer - Client called function to add a buffer to MHI channel |
| * |
| * @client_handle Pointer to client handle previously obtained from |
| * mhi_open_channel |
| * @buf Pointer to client buffer |
| * @buf_len Length of the client buffer |
| * @chain Specify whether to set the chain bit on this buffer |
| * @eob Specify whether this buffer should trigger EOB interrupt |
| * |
| * NOTE: |
| * Not thread safe, caller must ensure concurrency protection. |
| * User buffer must be physically contiguous. |
| * |
| * @Return errno |
| */ |
| int mhi_queue_xfer(struct mhi_client_handle *client_handle, void *buf, |
| size_t buf_len, enum MHI_FLAGS mhi_flags); |
| |
| /** |
| * mhi_close_channel - Client can request channel to be closed and handle freed |
| * |
| * @client_handle Pointer to client handle previously obtained from |
| * mhi_open_channel |
| * Not thread safe, caller must ensure concurrency protection. |
| * |
| * @client_handle Pointer to handle to be released |
| */ |
| void mhi_close_channel(struct mhi_client_handle *client_handle); |
| |
| /** |
| * mhi_get_free_desc - Get the number of free descriptors on channel. |
| * client_handle Pointer to client handle previously obtained from |
| * mhi_open_channel. |
| * |
| * This API returns a snapshot of available descriptors on the given |
| * channel |
| * |
| * @Return non negative on success |
| */ |
| int mhi_get_free_desc(struct mhi_client_handle *client_handle); |
| |
| /* |
| * mhi_poll_inbound - Poll a buffer from MHI channel |
| * @client_handle Pointer to client handle previously obtained from |
| * mhi_open_channel. |
| * @result Result structure to be populated with buffer info |
| * if available; |
| * |
| * Client may asynchronously poll on an inbound channel for descriptors |
| * which have been populated. This API is used by client to receive data |
| * from device after a callback notification has been received. |
| * |
| * Not thread safe, caller must ensure concurrency protection. |
| * |
| * @Return non negative on success |
| */ |
| int mhi_poll_inbound(struct mhi_client_handle *client_handle, |
| struct mhi_result *result); |
| |
| /** |
| * mhi_get_max_desc - Get the maximum number of descriptors |
| * supported on the channel. |
| * @client_handle Pointer to client handle previously obtained from |
| * mhi_open_channel. |
| * @Return non negative on success |
| */ |
| int mhi_get_max_desc(struct mhi_client_handle *client_handle); |
| |
| /* following APIs meant to be used by rmnet interface only */ |
| int mhi_set_lpm(struct mhi_client_handle *client_handle, bool enable_lpm); |
| int mhi_get_epid(struct mhi_client_handle *mhi_handle); |
| struct mhi_result *mhi_poll(struct mhi_client_handle *client_handle); |
| void mhi_mask_irq(struct mhi_client_handle *client_handle); |
| void mhi_unmask_irq(struct mhi_client_handle *client_handle); |
| |
| #else |
| static inline bool mhi_is_device_ready(const struct device * const dev, |
| const char *node_name) |
| { |
| return false; |
| }; |
| |
| static inline int mhi_register_device(struct mhi_device *mhi_device, |
| const char *node_name, void *user_data) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_register_channel(struct mhi_client_handle **client_handle, |
| struct mhi_client_info_t *client_info) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_pm_control_device(struct mhi_device *mhi_device, |
| enum mhi_dev_ctrl ctrl) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_xfer_rddm(struct mhi_device *mhi_device, |
| enum mhi_rddm_segment seg, |
| struct scatterlist **sg_list) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_deregister_channel(struct mhi_client_handle |
| *client_handle) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_open_channel(struct mhi_client_handle *client_handle) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_queue_xfer(struct mhi_client_handle *client_handle, |
| void *buf, size_t buf_len, |
| enum MHI_FLAGS mhi_flags) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline void mhi_close_channel(struct mhi_client_handle *client_handle) |
| { |
| }; |
| |
| static inline int mhi_get_free_desc(struct mhi_client_handle *client_handle) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_poll_inbound(struct mhi_client_handle *client_handle, |
| struct mhi_result *result) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_get_max_desc(struct mhi_client_handle *client_handle) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_set_lpm(struct mhi_client_handle *client_handle, |
| bool enable_lpm) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline int mhi_get_epid(struct mhi_client_handle *mhi_handle) |
| { |
| return -EINVAL; |
| }; |
| |
| static inline struct mhi_result *mhi_poll(struct mhi_client_handle |
| *client_handle) |
| { |
| return NULL; |
| }; |
| |
| static inline void mhi_mask_irq(struct mhi_client_handle *client_handle) |
| { |
| }; |
| |
| static inline void mhi_unmask_irq(struct mhi_client_handle *client_handle) |
| { |
| }; |
| |
| #endif |
| #endif |