unplugged-kernel/drivers/misc/mediatek/eccci/fsm/ccci_fsm_internal.h

304 lines
7.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2016 MediaTek Inc.
*/
#ifndef __CCCI_FSM_INTERNAL_H__
#define __CCCI_FSM_INTERNAL_H__
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/sched/clock.h> /* local_clock() */
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <linux/poll.h>
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#endif
#include "ccci_core.h"
#include "ccci_fsm.h"
#include "ccci_modem.h"
#include "ccci_hif.h"
#include "ccci_port.h"
#include "port_t.h"
/************ enumerations ************/
enum {
CCCI_FSM_INVALID = 0,
CCCI_FSM_GATED,
CCCI_FSM_STARTING,
CCCI_FSM_READY,
CCCI_FSM_STOPPING,
CCCI_FSM_EXCEPTION,
};
enum CCCI_FSM_EVENT {
CCCI_EVENT_INVALID = 0,
CCCI_EVENT_HS1,
CCCI_EVENT_FS_IN,
CCCI_EVENT_FS_OUT,
CCCI_EVENT_HS2,
CCCI_EVENT_CCIF_EX_HS_DONE,
CCCI_EVENT_MD_EX,
CCCI_EVENT_MD_EX_REC_OK,
CCCI_EVENT_MD_EX_PASS,
CCCI_EVENT_MAX,
};
enum CCCI_FSM_COMMAND {
CCCI_COMMAND_INVALID = 0,
CCCI_COMMAND_START, /* from md_init */
CCCI_COMMAND_STOP, /* from md_init */
CCCI_COMMAND_WDT, /* from MD */
CCCI_COMMAND_EE, /* from MD */
CCCI_COMMAND_MD_HANG, /* from status polling thread */
CCCI_COMMAND_MAX,
};
enum CCCI_EE_REASON {
EXCEPTION_NONE = 0,
EXCEPTION_HS1_TIMEOUT,
EXCEPTION_HS2_TIMEOUT,
EXCEPTION_WDT,
EXCEPTION_EE,
EXCEPTION_MD_NO_RESPONSE,
};
enum CCCI_FSM_POLLER_STATE {
FSM_POLLER_INVALID = 0,
FSM_POLLER_WAITING_RESPONSE,
FSM_POLLER_RECEIVED_RESPONSE,
};
enum {
SCP_CCCI_STATE_INVALID = 0,
SCP_CCCI_STATE_BOOTING = 1,
SCP_CCCI_STATE_RBREADY = 2,
SCP_CCCI_STATE_STOP = 3,
};
enum CCCI_MD_MSG {
CCCI_MD_MSG_FORCE_STOP_REQUEST = 0xFAF50001,
CCCI_MD_MSG_FLIGHT_STOP_REQUEST,
CCCI_MD_MSG_FORCE_START_REQUEST,
CCCI_MD_MSG_FLIGHT_START_REQUEST,
CCCI_MD_MSG_RESET_REQUEST,
CCCI_MD_MSG_EXCEPTION,
CCCI_MD_MSG_SEND_BATTERY_INFO,
CCCI_MD_MSG_STORE_NVRAM_MD_TYPE,
CCCI_MD_MSG_CFG_UPDATE,
CCCI_MD_MSG_RANDOM_PATTERN,
};
enum {
/* also used to check EE flow done */
MD_EE_FLOW_START = (1 << 0),
MD_EE_MSG_GET = (1 << 1),
MD_EE_OK_MSG_GET = (1 << 2),
MD_EE_PASS_MSG_GET = (1 << 3),
MD_EE_PENDING_TOO_LONG = (1 << 4),
MD_EE_WDT_GET = (1 << 5),
MD_EE_DUMP_IN_GPD = (1 << 6),
MD_EE_SWINT_GET = (1 << 7),
};
enum {
/*
* we assume every valid EE is started with CCIF EX interrupt,
* and ignore EX messages without one.
* if we get EX_OK, then we can parse out valid EE info anyway,
* so no need to distinguish EX_OK only case.
* and we never encountered EX_PASS only case~
*/
MD_EE_CASE_NORMAL = 0,
MD_EE_CASE_ONLY_SWINT,
MD_EE_CASE_ONLY_EX,
MD_EE_CASE_NO_RESPONSE,
MD_EE_CASE_WDT,
};
enum MDEE_DUMP_LEVEL {
MDEE_DUMP_LEVEL_BOOT_FAIL,
MDEE_DUMP_LEVEL_STAGE1,
MDEE_DUMP_LEVEL_STAGE2,
};
enum ccci_ipi_op_id {
CCCI_OP_SCP_STATE,
CCCI_OP_MD_STATE,
CCCI_OP_SHM_INIT,
CCCI_OP_SHM_RESET,
CCCI_OP_LOG_LEVEL,
CCCI_OP_GPIO_TEST,
CCCI_OP_EINT_TEST,
CCCI_OP_MSGSND_TEST,
CCCI_OP_ASSERT_TEST,
};
/************ definetions ************/
#define FSM_NAME "ccci_fsm"
#define FSM_CMD_FLAG_WAIT_FOR_COMPLETE (1 << 0)
#define FSM_CMD_FLAG_FLIGHT_MODE (1 << 1)
#define EVENT_POLL_INTEVAL 20 /* ms */
#define BOOT_TIMEOUT (30*1000)
#define MD_EX_CCIF_TIMEOUT 10000
#define MD_EX_REC_OK_TIMEOUT 10000
#define MD_EX_PASS_TIMEOUT 10000
#define EE_DONE_TIMEOUT 30 /* s */
#define SCP_BOOT_TIMEOUT (30*1000)
#define GET_OTHER_MD_ID(a) (a == MD_SYS1 ? MD_SYS3 : MD_SYS1)
#define MD_IMG_DUMP_SIZE (1<<8)
#define DSP_IMG_DUMP_SIZE (1<<9)
#define CCCI_AED_DUMP_EX_MEM (1<<0)
#define CCCI_AED_DUMP_MD_IMG_MEM (1<<1)
#define CCCI_AED_DUMP_CCIF_REG (1<<2)
#define CCCI_AED_DUMP_EX_PKT (1<<3)
#define MD_EX_MPU_STR_LEN (128)
#define MD_EX_START_TIME_LEN (128)
/************ structures ************/
struct ccci_ipi_msg {
u16 md_id;
u16 op_id;
u32 data[1];
} __packed;
struct ccci_fsm_scp {
int md_id;
struct work_struct scp_md_state_sync_work;
};
struct ccci_fsm_poller {
int md_id;
enum CCCI_FSM_POLLER_STATE poller_state;
struct task_struct *poll_thread;
wait_queue_head_t status_rx_wq;
unsigned long long latest_poll_start_time;
};
struct ccci_fsm_ee;
struct md_ee_ops {
void (*set_ee_pkg)(struct ccci_fsm_ee *ee_ctl, char *data, int len);
void (*dump_ee_info)(struct ccci_fsm_ee *ee_ctl,
enum MDEE_DUMP_LEVEL level, int more_info);
};
struct ccci_fsm_ee {
int md_id;
unsigned int ee_info_flag;
spinlock_t ctrl_lock;
unsigned int ee_case;
unsigned int ex_type;
void *dumper_obj;
struct md_ee_ops *ops;
char ex_mpu_string[MD_EX_MPU_STR_LEN];
char ex_start_time[MD_EX_START_TIME_LEN];
unsigned int mdlog_dump_done;
};
struct ccci_fsm_monitor {
int md_id;
dev_t dev_n;
struct cdev *char_dev;
atomic_t usage_cnt;
wait_queue_head_t rx_wq;
struct ccci_skb_queue rx_skb_list;
};
struct ccci_fsm_ctl {
int md_id;
enum MD_STATE md_state;
unsigned int curr_state;
unsigned int last_state;
struct list_head command_queue;
struct list_head event_queue;
wait_queue_head_t command_wq;
spinlock_t event_lock;
spinlock_t command_lock;
spinlock_t cmd_complete_lock;
struct task_struct *fsm_thread;
atomic_t fs_ongoing;
char wakelock_name[32];
struct wakeup_source *wakelock;
unsigned long boot_count; /* for throttling feature */
struct ccci_fsm_scp scp_ctl;
struct ccci_fsm_poller poller_ctl;
struct ccci_fsm_ee ee_ctl;
struct ccci_fsm_monitor monitor_ctl;
};
struct ccci_fsm_event {
struct list_head entry;
enum CCCI_FSM_EVENT event_id;
unsigned int length;
unsigned char data[0];
};
struct ccci_fsm_command {
struct list_head entry;
enum CCCI_FSM_COMMAND cmd_id;
unsigned int flag;
int complete; /* -1: fail; 0: on-going; 1: success */
wait_queue_head_t complete_wq;
};
/************ APIs ************/
int fsm_append_command(struct ccci_fsm_ctl *ctl,
enum CCCI_FSM_COMMAND cmd_id, unsigned int flag);
int fsm_append_event(struct ccci_fsm_ctl *ctl, enum CCCI_FSM_EVENT event_id,
unsigned char *data, unsigned int length);
int fsm_scp_init(struct ccci_fsm_scp *scp_ctl);
int fsm_poller_init(struct ccci_fsm_poller *poller_ctl);
int fsm_ee_init(struct ccci_fsm_ee *ee_ctl);
int fsm_monitor_init(struct ccci_fsm_monitor *monitor_ctl);
int fsm_sys_init(void);
struct ccci_fsm_ctl *fsm_get_entity_by_device_number(dev_t dev_n);
struct ccci_fsm_ctl *fsm_get_entity_by_md_id(int md_id);
int fsm_monitor_send_message(int md_id, enum CCCI_MD_MSG msg, u32 resv);
int fsm_ccism_init_ack_handler(int md_id, int data);
void fsm_md_bootup_timeout_handler(struct ccci_fsm_ee *ee_ctl);
void fsm_md_wdt_handler(struct ccci_fsm_ee *ee_ctl);
void fsm_md_no_response_handler(struct ccci_fsm_ee *ee_ctl);
void fsm_md_exception_stage(struct ccci_fsm_ee *ee_ctl, int stage);
void fsm_ee_message_handler(struct ccci_fsm_ee *ee_ctl, struct sk_buff *skb);
int fsm_check_ee_done(struct ccci_fsm_ee *ee_ctl, int timeout);
int force_md_stop(struct ccci_fsm_monitor *monitor_ctl);
extern int mdee_dumper_v1_alloc(struct ccci_fsm_ee *mdee);
extern int mdee_dumper_v2_alloc(struct ccci_fsm_ee *mdee);
extern int mdee_dumper_v3_alloc(struct ccci_fsm_ee *mdee);
extern int mdee_dumper_v5_alloc(struct ccci_fsm_ee *mdee);
extern void inject_md_status_event(int md_id, int event_type, char reason[]);
#ifdef SET_EMI_STEP_BY_STAGE
extern void ccci_set_mem_access_protection_second_stage(int md_id);
#endif
extern void mdee_set_ex_start_str(struct ccci_fsm_ee *ee_ctl,
unsigned int type, char *str);
#endif /* __CCCI_FSM_INTERNAL_H__ */