blob: 08dc3a23abfa4ef6402d94b99e9159c56bfa6642 [file] [log] [blame]
/* 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