Merge "bus: mhi: host: Add snapshot of MHI bus misc driver"

This commit is contained in:
qctecmdr 2022-09-18 20:39:11 -07:00 committed by Gerrit - the friendly Code Review server
commit a5b6faf118
6 changed files with 2932 additions and 0 deletions

View File

@ -29,3 +29,11 @@ config MHI_BUS_PCI_GENERIC
This driver provides MHI PCI controller driver for devices such as
Qualcomm SDX55 based PCIe modems.
config MHI_BUS_MISC
bool "Support for miscellaneous MHI features"
depends on MHI_BUS
help
Miscellaneous features support for MHI Bus driver includes IPC logs,
introduction of a list of controllers for debug using ramdumps and
other features not present upstream such as Dynamic Resource Vote,
SFR parsing using RDDM dumps, scanning for the RDDM cookie and more.

View File

@ -1,5 +1,6 @@
obj-$(CONFIG_MHI_BUS) += mhi.o
mhi-y := init.o main.o pm.o boot.o
mhi-$(CONFIG_MHI_BUS_MISC) += misc.o
mhi-$(CONFIG_MHI_BUS_DEBUG) += debugfs.o
obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o

View File

@ -8,6 +8,7 @@
#define _MHI_INT_H
#include "../common.h"
#include "misc.h"
extern struct bus_type mhi_bus_type;

1913
drivers/bus/mhi/host/misc.c Normal file

File diff suppressed because it is too large Load Diff

340
drivers/bus/mhi/host/misc.h Normal file
View File

@ -0,0 +1,340 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */
#ifndef _MHI_CORE_MISC_H_
#define _MHI_CORE_MISC_H_
#include <linux/mhi_misc.h>
#include <linux/msm_pcie.h>
#define MHI_FORCE_WAKE_DELAY_US (100)
#define MHI_IPC_LOG_PAGES (100)
#define MAX_RDDM_TABLE_SIZE (8)
#define MHI_REG_SIZE (SZ_4K)
#define REG_WRITE_QUEUE_LEN 512
/* MHI misc capability registers */
#define MISC_OFFSET (0x24)
#define MISC_CAP_MASK (0xFFFFFFFF)
#define MISC_CAP_SHIFT (0)
#define CAP_CAPID_MASK (0xFF000000)
#define CAP_CAPID_SHIFT (24)
#define CAP_NEXT_CAP_MASK (0x00FFF000)
#define CAP_NEXT_CAP_SHIFT (12)
/* MHI Bandwidth scaling offsets */
#define BW_SCALE_CFG_OFFSET (0x04)
#define BW_SCALE_CFG_CHAN_DB_ID_MASK (0xFE000000)
#define BW_SCALE_CFG_CHAN_DB_ID_SHIFT (25)
#define BW_SCALE_CFG_ENABLED_MASK (0x01000000)
#define BW_SCALE_CFG_ENABLED_SHIFT (24)
#define BW_SCALE_CFG_ER_ID_MASK (0x00F80000)
#define BW_SCALE_CFG_ER_ID_SHIFT (19)
#define BW_SCALE_CAP_ID (3)
#define MHI_TRE_GET_EV_BW_REQ_SEQ(tre) (((tre)->dword[0] >> 8) & 0xFF)
#define MHI_BW_SCALE_CHAN_DB 126
#define MHI_BW_SCALE_SETUP(er_index) (((MHI_BW_SCALE_CHAN_DB << \
BW_SCALE_CFG_CHAN_DB_ID_SHIFT) & BW_SCALE_CFG_CHAN_DB_ID_MASK) | \
((1 << BW_SCALE_CFG_ENABLED_SHIFT) & BW_SCALE_CFG_ENABLED_MASK) | \
(((er_index) << BW_SCALE_CFG_ER_ID_SHIFT) & BW_SCALE_CFG_ER_ID_MASK))
#define MHI_BW_SCALE_RESULT(status, seq) (((status) & 0xF) << 8 | \
((seq) & 0xFF))
#define MHI_BW_SCALE_NACK 0xF
/* subsystem failure reason cfg command */
#define MHI_TRE_CMD_SFR_CFG_PTR(ptr) (ptr)
#define MHI_TRE_CMD_SFR_CFG_DWORD0(len) (len)
#define MHI_TRE_CMD_SFR_CFG_DWORD1 (MHI_CMD_SFR_CFG << 16)
/* MHI Timesync offsets */
#define TIMESYNC_CFG_OFFSET (0x04)
#define TIMESYNC_CFG_ENABLED_MASK (0x80000000)
#define TIMESYNC_CFG_ENABLED_SHIFT (31)
#define TIMESYNC_CFG_CHAN_DB_ID_MASK (0x0000FF00)
#define TIMESYNC_CFG_CHAN_DB_ID_SHIFT (8)
#define TIMESYNC_CFG_ER_ID_MASK (0x000000FF)
#define TIMESYNC_CFG_ER_ID_SHIFT (0)
#define TIMESYNC_TIME_LOW_OFFSET (0x8)
#define TIMESYNC_TIME_HIGH_OFFSET (0xC)
#define MHI_TIMESYNC_CHAN_DB (125)
#define TIMESYNC_CAP_ID (2)
#define MHI_TIMESYNC_DB_SETUP(er_index) ((MHI_TIMESYNC_CHAN_DB << \
TIMESYNC_CFG_CHAN_DB_ID_SHIFT) & TIMESYNC_CFG_CHAN_DB_ID_MASK | \
(1 << TIMESYNC_CFG_ENABLED_SHIFT) & TIMESYNC_CFG_ENABLED_MASK | \
((er_index) << TIMESYNC_CFG_ER_ID_SHIFT) & TIMESYNC_CFG_ER_ID_MASK)
#define MHI_VERB(dev, fmt, ...) do { \
struct mhi_private *mhi_priv = \
dev_get_drvdata(&mhi_cntrl->mhi_dev->dev); \
dev_dbg(dev, "[D][%s] " fmt, __func__, ##__VA_ARGS__); \
if (mhi_priv && mhi_priv->log_lvl <= MHI_MSG_LVL_VERBOSE) \
ipc_log_string(mhi_priv->log_buf, "[D][%s] " fmt, __func__, \
##__VA_ARGS__); \
} while (0)
#define MHI_LOG(dev, fmt, ...) do { \
struct mhi_private *mhi_priv = \
dev_get_drvdata(&mhi_cntrl->mhi_dev->dev); \
dev_dbg(dev, "[I][%s] " fmt, __func__, ##__VA_ARGS__); \
if (mhi_priv && mhi_priv->log_lvl <= MHI_MSG_LVL_INFO) \
ipc_log_string(mhi_priv->log_buf, "[I][%s] " fmt, __func__, \
##__VA_ARGS__); \
} while (0)
#define MHI_ERR(dev, fmt, ...) do { \
struct mhi_private *mhi_priv = \
dev_get_drvdata(&mhi_cntrl->mhi_dev->dev); \
dev_err(dev, "[E][%s] " fmt, __func__, ##__VA_ARGS__); \
if (mhi_priv && mhi_priv->log_lvl <= MHI_MSG_LVL_ERROR) \
ipc_log_string(mhi_priv->log_buf, "[E][%s] " fmt, __func__, \
##__VA_ARGS__); \
} while (0)
#define MHI_CRITICAL(dev, fmt, ...) do { \
struct mhi_private *mhi_priv = \
dev_get_drvdata(&mhi_cntrl->mhi_dev->dev); \
dev_crit(dev, "[C][%s] " fmt, __func__, ##__VA_ARGS__); \
if (mhi_priv && mhi_priv->log_lvl <= MHI_MSG_LVL_CRITICAL) \
ipc_log_string(mhi_priv->log_buf, "[C][%s] " fmt, __func__, \
##__VA_ARGS__); \
} while (0)
/**
* struct rddm_table_info - rddm table info
* @base_address - Start offset of the file
* @actual_phys_address - phys addr offset of file
* @size - size of file
* @description - file description
* @file_name - name of file
*/
struct rddm_table_info {
u64 base_address;
u64 actual_phys_address;
u64 size;
char description[20];
char file_name[20];
};
/**
* struct rddm_header - rddm header
* @version - header ver
* @header_size - size of header
* @rddm_table_info - array of rddm table info
*/
struct rddm_header {
u32 version;
u32 header_size;
struct rddm_table_info table_info[MAX_RDDM_TABLE_SIZE];
};
/**
* struct file_info - keeping track of file info while traversing the rddm
* table header
* @file_offset - current file offset
* @seg_idx - mhi buf seg array index
* @rem_seg_len - remaining length of the segment containing current file
*/
struct file_info {
u8 *file_offset;
u32 file_size;
u32 seg_idx;
u32 rem_seg_len;
};
/**
* struct reg_write_info - offload reg write info
* @reg_addr - register address
* @val - value to be written to register
* @chan - channel number
* @valid - entry is valid or not
*/
struct reg_write_info {
void __iomem *reg_addr;
u32 val;
bool valid;
};
/**
* struct mhi_private - For private variables of an MHI controller
*/
struct mhi_private {
struct list_head node;
struct mhi_controller *mhi_cntrl;
enum MHI_DEBUG_LEVEL log_lvl;
void *log_buf;
u32 saved_pm_state;
enum mhi_state saved_dev_state;
u32 m2_timeout_ms;
void *priv_data;
void __iomem *bw_scale_db;
int (*bw_scale)(struct mhi_controller *mhi_cntrl,
struct mhi_link_info *link_info);
phys_addr_t base_addr;
u32 numeric_id;
u32 bw_response;
struct mhi_sfr_info *sfr_info;
struct mhi_timesync *timesync;
/* reg write offload */
struct workqueue_struct *offload_wq;
struct work_struct reg_write_work;
struct reg_write_info *reg_write_q;
atomic_t write_idx;
u32 read_idx;
};
/**
* struct mhi_bus - For MHI controller debug
*/
struct mhi_bus {
struct list_head controller_list;
struct mutex lock;
};
/**
* struct mhi_sfr_info - For receiving MHI subsystem failure reason
*/
struct mhi_sfr_info {
void *buf_addr;
dma_addr_t dma_addr;
size_t len;
char *str;
unsigned int ccs;
struct completion completion;
};
/**
* struct mhi_timesync - For enabling use of MHI time synchronization feature
*/
struct mhi_timesync {
u64 (*time_get)(struct mhi_controller *mhi_cntrl);
int (*lpm_disable)(struct mhi_controller *mhi_cntrl);
int (*lpm_enable)(struct mhi_controller *mhi_cntrl);
void __iomem *time_reg;
void __iomem *time_db;
u32 int_sequence;
u64 local_time;
u64 remote_time;
bool db_pending;
struct completion completion;
spinlock_t lock; /* list protection */
struct list_head head;
struct mutex mutex;
};
/**
* struct tsync_node - Stores requests when using the timesync doorbell method
*/
struct tsync_node {
struct list_head node;
u32 sequence;
u64 remote_time;
struct mhi_device *mhi_dev;
void (*cb_func)(struct mhi_device *mhi_dev, u32 sequence,
u64 local_time, u64 remote_time);
};
#ifdef CONFIG_MHI_BUS_MISC
void mhi_misc_init(void);
void mhi_misc_exit(void);
int mhi_misc_init_mmio(struct mhi_controller *mhi_cntrl);
int mhi_misc_register_controller(struct mhi_controller *mhi_cntrl);
void mhi_misc_unregister_controller(struct mhi_controller *mhi_cntrl);
int mhi_process_misc_bw_ev_ring(struct mhi_controller *mhi_cntrl,
struct mhi_event *mhi_event, u32 event_quota);
int mhi_process_misc_tsync_ev_ring(struct mhi_controller *mhi_cntrl,
struct mhi_event *mhi_event, u32 event_quota);
void mhi_misc_mission_mode(struct mhi_controller *mhi_cntrl);
void mhi_misc_dbs_pending(struct mhi_controller *mhi_cntrl);
void mhi_misc_disable(struct mhi_controller *mhi_cntrl);
void mhi_misc_cmd_configure(struct mhi_controller *mhi_cntrl,
unsigned int type, u64 *ptr, u32 *dword0,
u32 *dword1);
void mhi_misc_cmd_completion(struct mhi_controller *mhi_cntrl,
unsigned int type, unsigned int ccs);
void mhi_write_offload_wakedb(struct mhi_controller *mhi_cntrl, int db_val);
void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl);
void mhi_force_reg_write(struct mhi_controller *mhi_cntrl);
#else
static inline void mhi_misc_init(void)
{
}
static inline void mhi_misc_exit(void)
{
}
static inline int mhi_misc_init_mmio(struct mhi_controller *mhi_cntrl)
{
return 0;
}
static inline int mhi_misc_register_controller(struct mhi_controller *mhi_cntrl)
{
return 0;
}
static inline void mhi_misc_unregister_controller(struct mhi_controller
*mhi_cntrl)
{
}
static inline int mhi_process_misc_bw_ev_ring(struct mhi_controller *mhi_cntrl,
struct mhi_event *mhi_event, u32 event_quota)
{
return 0;
}
static inline int mhi_process_misc_tsync_ev_ring
(struct mhi_controller *mhi_cntrl,
struct mhi_event *mhi_event, u32 event_quota)
{
return 0;
}
static inline void mhi_misc_mission_mode(struct mhi_controller *mhi_cntrl)
{
}
static inline void mhi_special_dbs_pending(struct mhi_controller *mhi_cntrl)
{
}
static inline void mhi_misc_disable(struct mhi_controller *mhi_cntrl)
{
}
static inline void mhi_misc_cmd_configure(struct mhi_controller *mhi_cntrl,
unsigned int type, u64 *ptr,
u32 *dword0, u32 *dword1)
{
}
static inline void mhi_misc_cmd_completion(struct mhi_controller *mhi_cntrl,
unsigned int type, unsigned int ccs)
{
}
static inline void mhi_write_offload_wakedb(struct mhi_controller *mhi_cntrl,
int db_val)
{
}
void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl)
{
}
void mhi_force_reg_write(struct mhi_controller *mhi_cntrl)
{
}
#endif
#endif /* _MHI_CORE_MISC_H_ */

669
include/linux/mhi_misc.h Normal file
View File

@ -0,0 +1,669 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */
#ifndef _MHI_MISC_H_
#define _MHI_MISC_H_
#include <linux/mhi.h>
#include <linux/ipc_logging.h>
/**
* enum MHI_DEBUG_LEVEL - various debugging levels
*/
enum MHI_DEBUG_LEVEL {
MHI_MSG_LVL_VERBOSE,
MHI_MSG_LVL_INFO,
MHI_MSG_LVL_ERROR,
MHI_MSG_LVL_CRITICAL,
MHI_MSG_LVL_MASK_ALL,
MHI_MSG_LVL_MAX,
};
/**
* struct mhi_buf - MHI Buffer description
* @node: list entry point
* @buf: Virtual address of the buffer
* @name: Buffer label. For offload channel, configurations name must be:
* ECA - Event context array data
* CCA - Channel context array data
* @dma_addr: IOMMU address of the buffer
* @phys_addr: physical address of the buffer
* @len: # of bytes
* @is_io: buffer is of IO/registesr type (resource) rather than of DDR/RAM type
*/
struct mhi_buf_extended {
struct list_head node;
void *buf;
const char *name;
dma_addr_t dma_addr;
phys_addr_t phys_addr;
size_t len;
bool is_io;
};
#ifdef CONFIG_MHI_BUS_MISC
/**
* mhi_report_error - Can be used by controller to signal error condition to the
* MHI core driver in case of any need to halt processing or incoming sideband
* signal detects an error on endpoint
* @mhi_cntrl: MHI controller
*
* Returns:
* 0 if success in reporting the error condition to MHI core
* error code on failure
*/
int mhi_report_error(struct mhi_controller *mhi_cntrl);
/**
* mhi_controller_set_privdata - Set private data for MHI controller
* @mhi_cntrl: MHI controller
* @priv: pointer to data
*/
void mhi_controller_set_privdata(struct mhi_controller *mhi_cntrl, void *priv);
/**
* mhi_controller_get_privdata - Get private data from MHI controller
* @mhi_cntrl: MHI controller
*/
void *mhi_controller_get_privdata(struct mhi_controller *mhi_cntrl);
/**
* mhi_bdf_to_controller - Get controller associated with given BDF values
* @domain: Domain or root complex of PCIe port
* @bus: Bus number
* @slot: PCI slot or function number
* @dev_id: Device ID of the endpoint
*
* Returns:
* MHI controller structure pointer if BDF match is found
* NULL if cookie is not found
*/
struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot, u32 dev_id);
/**
* mhi_set_m2_timeout_ms - Set M2 timeout in milliseconds to wait before a
* fast/silent suspend
* @mhi_cntrl: MHI controller
* @timeout: timeout in ms
*/
void mhi_set_m2_timeout_ms(struct mhi_controller *mhi_cntrl, u32 timeout);
/**
* mhi_pm_fast_resume - Resume MHI from a fast/silent suspended state
* @mhi_cntrl: MHI controller
* @notify_clients: if true, clients will be notified of the resume transition
*/
int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_clients);
/**
* mhi_pm_fast_suspend - Move MHI into a fast/silent suspended state
* @mhi_cntrl: MHI controller
* @notify_clients: if true, clients will be notified of the suspend transition
*/
int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_clients);
/**
* mhi_debug_reg_dump - dump MHI registers for debug purpose
* @mhi_cntrl: MHI controller
*/
void mhi_debug_reg_dump(struct mhi_controller *mhi_cntrl);
/**
* mhi_dump_sfr - Print SFR string from RDDM table.
* @mhi_cntrl: MHI controller
*/
void mhi_dump_sfr(struct mhi_controller *mhi_cntrl);
/**
* mhi_device_configure - Allow devices with offload channels to setup their own
* channel and event ring context.
* @mhi_dev: MHI device
* @dir: direction associated with the channel needed to configure
* @cfg_tbl: Buffer with ECA/CCA information and data needed to setup context
* @elements: Number of items to iterate over from the configuration table
*/
int mhi_device_configure(struct mhi_device *mhi_dev,
enum dma_data_direction dir,
struct mhi_buf *cfg_tbl,
int elements);
/**
* mhi_scan_rddm_cookie - Look for supplied cookie value in the BHI debug
* registers set by device to indicate rddm readiness for debugging purposes.
* @mhi_cntrl: MHI controller
* @cookie: cookie/pattern value to match
*
* Returns:
* true if cookie is found
* false if cookie is not found
*/
bool mhi_scan_rddm_cookie(struct mhi_controller *mhi_cntrl, u32 cookie);
/**
* mhi_device_get_sync_atomic - Asserts device_wait and moves device to M0
* @mhi_dev: Device associated with the channels
* @timeout_us: timeout, in micro-seconds
* @in_panic: If requested while kernel is in panic state and no ISRs expected
*
* The device_wake is asserted to keep device in M0 or bring it to M0.
* If device is not in M0 state, then this function will wait for device to
* move to M0, until @timeout_us elapses.
* However, if device's M1 state-change event races with this function
* then there is a possiblity of device moving from M0 to M2 and back
* to M0. That can't be avoided as host must transition device from M1 to M2
* as per the spec.
* Clients can ignore that transition after this function returns as the device
* is expected to immediately move from M2 to M0 as wake is asserted and
* wouldn't enter low power state.
* If in_panic boolean is set, no ISRs are expected, hence this API will have to
* resort to reading the MHI status register and poll on M0 state change.
*
* Returns:
* 0 if operation was successful (however, M0 -> M2 -> M0 is possible later) as
* mentioned above.
* -ETIMEDOUT is device faled to move to M0 before @timeout_us elapsed
* -EIO if the MHI state is one of the ERROR states.
*/
int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev, int timeout_us,
bool in_panic);
/**
* mhi_controller_set_bw_scale_cb - Set the BW scale callback for MHI controller
* @mhi_cntrl: MHI controller
* @cb_func: Callback to set for the MHI controller to receive BW scale requests
*/
void mhi_controller_set_bw_scale_cb(struct mhi_controller *mhi_cntrl,
int (*cb_func)(struct mhi_controller *mhi_cntrl,
struct mhi_link_info *link_info));
/**
* mhi_controller_set_base - Set the controller base / resource start address
* @mhi_cntrl: MHI controller
* @base: Physical address to be set for future reference
*/
void mhi_controller_set_base(struct mhi_controller *mhi_cntrl,
phys_addr_t base);
/**
* mhi_controller_get_base - Get the controller base / resource start address
* @mhi_cntrl: MHI controller
* @base: Pointer to physical address to be populated
*/
int mhi_controller_get_base(struct mhi_controller *mhi_cntrl,
phys_addr_t *base);
/**
* mhi_controller_get_numeric_id - set numeric ID for controller
* @mhi_cntrl: MHI controller
* returns value set as ID or 0 if no value was set
*/
u32 mhi_controller_get_numeric_id(struct mhi_controller *mhi_cntrl);
/**
* mhi_get_channel_db_base - retrieve the channel doorbell base address
* @mhi_dev: Device associated with the channels
* @value: Pointer to an address value which will be populated
*/
int mhi_get_channel_db_base(struct mhi_device *mhi_dev, phys_addr_t *value);
/**
* mhi_get_event_ring_db_base - retrieve the event ring doorbell base address
* @mhi_dev: Device associated with the channels
* @value: Pointer to an address value which will be populated
*/
int mhi_get_event_ring_db_base(struct mhi_device *mhi_dev, phys_addr_t *value);
/**
* mhi_get_device_for_channel - get the MHI device for a specific channel number
* @mhi_cntrl: MHI controller
* @channel - channel number
*
* Returns:
* Pointer to the MHI device associated with the channel
*/
struct mhi_device *mhi_get_device_for_channel(struct mhi_controller *mhi_cntrl,
u32 channel);
/**
* mhi_device_ioctl - user space IOCTL support for MHI channels
* Native support for setting TIOCM
* @mhi_dev: Device associated with the channels
* @cmd: IOCTL cmd
* @arg: Optional parameter, iotcl cmd specific
*/
long mhi_device_ioctl(struct mhi_device *mhi_dev, unsigned int cmd,
unsigned long arg);
/**
* mhi_controller_set_sfr_support - Set support for subsystem failure reason
* @mhi_cntrl: MHI controller
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_controller_set_sfr_support(struct mhi_controller *mhi_cntrl,
size_t len);
/**
* mhi_controller_setup_timesync - Set support for time synchronization feature
* @mhi_cntrl: MHI controller
* @time_get: Callback to set for the MHI controller to receive host time
* @lpm_disable: Callback to set for the MHI controller to disable link LPM
* @lpm_enable: Callback to set for the MHI controller to enable link LPM
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_controller_setup_timesync(struct mhi_controller *mhi_cntrl,
u64 (*time_get)(struct mhi_controller *c),
int (*lpm_disable)(struct mhi_controller *c),
int (*lpm_enable)(struct mhi_controller *c));
/**
* mhi_get_remote_time_sync - Get external soc time relative to local soc time
* using MMIO method.
* @mhi_dev: Device associated with the channels
* @t_host: Pointer to output local soc time
* @t_dev: Pointer to output remote soc time
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_get_remote_time_sync(struct mhi_device *mhi_dev,
u64 *t_host,
u64 *t_dev);
/**
* mhi_get_remote_time - Get external modem time relative to host time
* Trigger event to capture modem time, also capture host time so client
* can do a relative drift comparision.
* Recommended only tsync device calls this method and do not call this
* from atomic context
* @mhi_dev: Device associated with the channels
* @sequence:unique sequence id track event
* @cb_func: callback function to call back
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_get_remote_time(struct mhi_device *mhi_dev,
u32 sequence,
void (*cb_func)(struct mhi_device *mhi_dev,
u32 sequence,
u64 local_time,
u64 remote_time));
/**
* mhi_force_reset - does host reset request to collect device side dumps
* for debugging purpose
* @mhi_cntrl: MHI controller
*/
int mhi_force_reset(struct mhi_controller *mhi_cntrl);
/**
* mhi_controller_set_loglevel - API for controller to set a desired log level
* which will be set to VERBOSE or 0 by default
* @mhi_cntrl: MHI controller
* @lvl: Log level from MHI_DEBUG_LEVEL enumerator
*/
void mhi_controller_set_loglevel(struct mhi_controller *mhi_cntrl,
enum MHI_DEBUG_LEVEL lvl);
/**
* mhi_get_soc_info - Get SoC info before registering mhi controller
* @mhi_cntrl: MHI controller
*/
int mhi_get_soc_info(struct mhi_controller *mhi_cntrl);
#else
/**
* mhi_report_error - Can be used by controller to signal error condition to the
* MHI core driver in case of any need to halt processing or incoming sideband
* signal detects an error on endpoint
* @mhi_cntrl: MHI controller
*
* Returns:
* 0 if success in reporting the error condition to MHI core
* error code on failure
*/
static inline int mhi_report_error(struct mhi_controller *mhi_cntrl)
{
return -EPERM;
}
/**
* mhi_controller_set_privdata - Set private data for MHI controller
* @mhi_cntrl: MHI controller
* @priv: pointer to data
*/
void mhi_controller_set_privdata(struct mhi_controller *mhi_cntrl, void *priv)
{
}
/**
* mhi_controller_get_privdata - Get private data from MHI controller
* @mhi_cntrl: MHI controller
*/
void *mhi_controller_get_privdata(struct mhi_controller *mhi_cntrl)
{
return ERR_PTR(-EINVAL);
}
/**
* mhi_bdf_to_controller - Get controller associated with given BDF values
* @domain: Domain or root complex of PCIe port
* @bus: Bus number
* @slot: PCI slot or function number
* @dev_id: Device ID of the endpoint
*
* Returns:
* MHI controller structure pointer if BDF match is found
* NULL if cookie is not found
*/
struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot, u32 dev_id)
{
return ERR_PTR(-EINVAL);
}
/**
* mhi_set_m2_timeout_ms - Set M2 timeout in milliseconds to wait before a
* fast/silent suspend
* @mhi_cntrl: MHI controller
* @timeout: timeout in ms
*/
void mhi_set_m2_timeout_ms(struct mhi_controller *mhi_cntrl, u32 timeout)
{
}
/**
* mhi_pm_fast_resume - Resume MHI from a fast/silent suspended state
* @mhi_cntrl: MHI controller
* @notify_clients: if true, clients will be notified of the resume transition
*/
int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_clients)
{
return -EPERM;
}
/**
* mhi_pm_fast_suspend - Move MHI into a fast/silent suspended state
* @mhi_cntrl: MHI controller
* @notify_clients: if true, clients will be notified of the suspend transition
*/
int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_clients)
{
return -EPERM;
}
/**
* mhi_debug_reg_dump - dump MHI registers for debug purpose
* @mhi_cntrl: MHI controller
*/
void mhi_debug_reg_dump(struct mhi_controller *mhi_cntrl)
{
}
/**
* mhi_dump_sfr - Print SFR string from RDDM table.
* @mhi_cntrl: MHI controller
*/
void mhi_dump_sfr(struct mhi_controller *mhi_cntrl)
{
}
/**
* mhi_device_configure - Allow devices with offload channels to setup their own
* channel and event ring context.
* @mhi_dev: MHI device
* @dir: direction associated with the channel needed to configure
* @cfg_tbl: Buffer with ECA/CCA information and data needed to setup context
* @elements: Number of items to iterate over from the configuration table
*/
int mhi_device_configure(struct mhi_device *mhi_dev,
enum dma_data_direction dir,
struct mhi_buf *cfg_tbl,
int elements)
{
return -EPERM;
}
/**
* mhi_scan_rddm_cookie - Look for supplied cookie value in the BHI debug
* registers set by device to indicate rddm readiness for debugging purposes.
* @mhi_cntrl: MHI controller
* @cookie: cookie/pattern value to match
*
* Returns:
* true if cookie is found
* false if cookie is not found
*/
bool mhi_scan_rddm_cookie(struct mhi_controller *mhi_cntrl, u32 cookie)
{
return false;
}
/**
* mhi_device_get_sync_atomic - Asserts device_wait and moves device to M0
* @mhi_dev: Device associated with the channels
* @timeout_us: timeout, in micro-seconds
* @in_panic: If requested while kernel is in panic state and no ISRs expected
*
* The device_wake is asserted to keep device in M0 or bring it to M0.
* If device is not in M0 state, then this function will wait for device to
* move to M0, until @timeout_us elapses.
* However, if device's M1 state-change event races with this function
* then there is a possiblity of device moving from M0 to M2 and back
* to M0. That can't be avoided as host must transition device from M1 to M2
* as per the spec.
* Clients can ignore that transition after this function returns as the device
* is expected to immediately move from M2 to M0 as wake is asserted and
* wouldn't enter low power state.
* If in_panic boolean is set, no ISRs are expected, hence this API will have to
* resort to reading the MHI status register and poll on M0 state change.
*
* Returns:
* 0 if operation was successful (however, M0 -> M2 -> M0 is possible later) as
* mentioned above.
* -ETIMEDOUT is device faled to move to M0 before @timeout_us elapsed
* -EIO if the MHI state is one of the ERROR states.
*/
int mhi_device_get_sync_atomic(struct mhi_device *mhi_dev, int timeout_us,
bool in_panic)
{
return -EPERM;
}
/**
* mhi_controller_set_bw_scale_cb - Set the BW scale callback for MHI controller
* @mhi_cntrl: MHI controller
* @cb_func: Callback to set for the MHI controller to receive BW scale requests
*/
void mhi_controller_set_bw_scale_cb(struct mhi_controller *mhi_cntrl,
int (*cb_func)(struct mhi_controller *mhi_cntrl,
struct mhi_link_info *link_info))
{
}
/**
* mhi_controller_set_base - Set the controller base / resource start address
* @mhi_cntrl: MHI controller
* @base: Physical address to be set for future reference
*/
void mhi_controller_set_base(struct mhi_controller *mhi_cntrl,
phys_addr_t base)
{
}
/**
* mhi_controller_get_base - Get the controller base / resource start address
* @mhi_cntrl: MHI controller
* @base: Pointer to physical address to be populated
*/
int mhi_controller_get_base(struct mhi_controller *mhi_cntrl,
phys_addr_t *base)
{
return -EINVAL;
}
/**
* mhi_controller_get_numeric_id - set numeric ID for controller
* @mhi_cntrl: MHI controller
* returns value set as ID or 0 if no value was set
*/
u32 mhi_controller_get_numeric_id(struct mhi_controller *mhi_cntrl)
{
return 0;
}
/**
* mhi_get_channel_db_base - retrieve the channel doorbell base address
* @mhi_dev: Device associated with the channels
* @value: Pointer to an address value which will be populated
*/
int mhi_get_channel_db_base(struct mhi_device *mhi_dev, phys_addr_t *value)
{
return -EPERM;
}
/**
* mhi_get_event_ring_db_base - retrieve the event ring doorbell base address
* @mhi_dev: Device associated with the channels
* @value: Pointer to an address value which will be populated
*/
int mhi_get_event_ring_db_base(struct mhi_device *mhi_dev, phys_addr_t *value)
{
return -EPERM;
}
/**
* mhi_get_device_for_channel - get the MHI device for a specific channel number
* @mhi_cntrl: MHI controller
* @channel - channel number
*
* Returns:
* Pointer to the MHI device associated with the channel
*/
struct mhi_device *mhi_get_device_for_channel(struct mhi_controller *mhi_cntrl,
u32 channel)
{
return ERR_PTR(-EINVAL);
}
/**
* mhi_device_ioctl - user space IOCTL support for MHI channels
* Native support for setting TIOCM
* @mhi_dev: Device associated with the channels
* @cmd: IOCTL cmd
* @arg: Optional parameter, iotcl cmd specific
*/
long mhi_device_ioctl(struct mhi_device *mhi_dev, unsigned int cmd,
unsigned long arg)
{
return -EPERM;
}
/**
* mhi_controller_set_sfr_support - Set support for subsystem failure reason
* @mhi_cntrl: MHI controller
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_controller_set_sfr_support(struct mhi_controller *mhi_cntrl,
size_t len)
{
return -EPERM;
}
/**
* mhi_controller_setup_timesync - Set support for time synchronization feature
* @mhi_cntrl: MHI controller
* @time_get: Callback to set for the MHI controller to receive host time
* @lpm_disable: Callback to set for the MHI controller to disable link LPM
* @lpm_enable: Callback to set for the MHI controller to enable link LPM
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_controller_setup_timesync(struct mhi_controller *mhi_cntrl,
u64 (*time_get)(struct mhi_controller *c),
int (*lpm_disable)(struct mhi_controller *c),
int (*lpm_enable)(struct mhi_controller *c))
{
return -EPERM;
}
/**
* mhi_get_remote_time_sync - Get external soc time relative to local soc time
* using MMIO method.
* @mhi_dev: Device associated with the channels
* @t_host: Pointer to output local soc time
* @t_dev: Pointer to output remote soc time
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_get_remote_time_sync(struct mhi_device *mhi_dev,
u64 *t_host,
u64 *t_dev)
{
return -EPERM;
}
/**
* mhi_get_remote_time - Get external modem time relative to host time
* Trigger event to capture modem time, also capture host time so client
* can do a relative drift comparision.
* Recommended only tsync device calls this method and do not call this
* from atomic context
* @mhi_dev: Device associated with the channels
* @sequence:unique sequence id track event
* @cb_func: callback function to call back
*
* Returns:
* 0 for success, error code for failure
*/
int mhi_get_remote_time(struct mhi_device *mhi_dev,
u32 sequence,
void (*cb_func)(struct mhi_device *mhi_dev,
u32 sequence,
u64 local_time,
u64 remote_time))
{
return -EPERM;
}
/**
* mhi_force_reset - does host reset request to collect device side dumps
* for debugging purpose
* @mhi_cntrl: MHI controller
*/
int mhi_force_reset(struct mhi_controller *mhi_cntrl)
{
return -EINVAL;
}
/**
* mhi_controller_set_loglevel - API for controller to set a desired log level
* which will be set to VERBOSE or 0 by default
* @mhi_cntrl: MHI controller
* @lvl: Log level from MHI_DEBUG_LEVEL enumerator
*/
void mhi_controller_set_loglevel(struct mhi_controller *mhi_cntrl,
enum MHI_DEBUG_LEVEL lvl)
{
}
/**
* mhi_get_soc_info - Get SoC info before registering mhi controller
* @mhi_cntrl: MHI controller
*/
int mhi_get_soc_info(struct mhi_controller *mhi_cntrl)
{
return -EINVAL;
}
#endif /* CONFIG_MHI_BUS_MISC */
#endif /* _MHI_MISC_H_ */