/* * Copyright (c) 2018 Samsung Electronics Co., Ltd. * http://www.samsung.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #ifndef __EXYNOS_BCM_DBG_H_ #define __EXYNOS_BCM_DBG_H_ #include #if defined(CONFIG_EXYNOS_BCM_DBG_GNR) || defined(CONFIG_EXYNOS_BCM_DBG_GNR_MODULE) #define BCM_BIN_SIZE (SZ_128K) #define BCM_BIN_NAME "/system/vendor/firmware/fimc_is_lib.bin" #endif #define ERRCODE_ITMON_SLVERR (0) #define ERRCODE_ITMON_TIMEOUT (6) #define EXYNOS_BCM_DBG_MODULE_NAME "exynos-bcm_dbg" #define BCM_DSS_NAME "log_bcm" #define EXYNOS_BCM_CMD_LOW_MASK (0x0000FFFF) #define EXYNOS_BCM_CMD_HIGH_MASK (0xFFFF0000) #define EXYNOS_BCM_U64_LOW_MASK (0x00000000FFFFFFFF) #define EXYNOS_BCM_U64_HIGH_MASK (0xFFFFFFFF00000000) #define EXYNOS_BCM_32BIT_SHIFT (32) #define EXYNOS_BCM_KTIME_SIZE (0x8) #define CMD_DATA_MAX (4) #define BCM_DEFAULT_TIMER_PERIOD (1) #define BCM_TIMER_PERIOD_MAX (500) #define BCM_TIMER_PERIOD_MIN (1) /* IPC common definition */ #define BCM_ONE_BIT_MASK (0x1) #define BCM_ERR_MASK (0x7) #define BCM_ERR_SHIFT (13) #define BCM_CMD_ID_MASK (0xF) #define BCM_CMD_ID_SHIFT (0) /* IPC_AP_BCM_PD definition */ #define BCM_PD_INFO_MAX (32) #define BCM_PD_INFO_MASK (0x1F) #define BCM_PD_INFO_SHIFT (0) #define BCM_PD_ON_SHIFT (6) /* IPC_AP_BCM_EVENT definition */ #define BCM_EVT_EVENT_MAX (8) #define BCM_EVT_ID_MASK BCM_PD_INFO_MASK #define BCM_EVT_ID_SHIFT BCM_PD_INFO_SHIFT #define BCM_EVT_DIR_SHIFT (5) #define BCM_EVT_PRE_DEFINE_MASK (0x7) #define BCM_EVT_PRE_DEFINE_SHIFT (6) #define BCM_IP_RANGE_SHIFT (9) #define BCM_IP_MASK (0x7F) #define BCM_IP_SHIFT (10) #define BCM_EVT_EVENT_MASK (0xFF) #define BCM_EVT_EVENT_SHIFT(x) (((x) >= 4) ? (((x) * 8) - 32) : ((x) * 8)) #define BCM_EVT_FLT_ACT_SHIFT(x) (x) #define BCM_EVT_FLT_OTHR_MAX (2) #define BCM_EVT_FLT_OTHR_TYPE_MASK (0x1F) #define BCM_EVT_FLT_OTHR_MASK_MASK (0x1F) #define BCM_EVT_FLT_OTHR_VALUE_MASK (0x1F) #define BCM_EVT_FLT_OTHR_TYPE_SHIFT(x) (((x) == 1) ? 26 : 10) #define BCM_EVT_FLT_OTHR_MASK_SHIFT(x) (((x) == 1) ? 21 : 5) #define BCM_EVT_FLT_OTHR_VALUE_SHIFT(x) (((x) == 1) ? 16 : 0) #define BCM_EVT_RUN_CONT_SHIFT (7) #define BCM_EVT_PERIOD_CONT_MASK (0xFFFFF) #define BCM_EVT_PERIOD_CONT_SHIFT (0) #define BCM_EVT_MODE_CONT_MASK (0x7) #define BCM_EVT_MODE_CONT_SHIFT (7) #define BCM_EVT_STR_STATE_SHIFT BCM_EVT_RUN_CONT_SHIFT #define BCM_EVT_IP_CONT_SHIFT BCM_EVT_RUN_CONT_SHIFT #define BCM_EVT_GLBAUTO_SHIFT BCM_EVT_RUN_CONT_SHIFT /* 2.7c, 2.7d */ #define BCM_IP_D0_INDEX 7 #define BCM_IP_D1_INDEX 8 #define BCM_IP_D2_INDEX 9 #define BCM_IP_D3_INDEX 10 #define BCM_IP_DPUF0D0_INDEX 13 #define BCM_IP_DPUF0D1_INDEX 14 #define BCM_IP_DPUF1D0_INDEX 15 #define BCM_IP_DPUF1D1_INDEX 16 #define BCM_CMD_GET(cmd_data, mask, shift) ((cmd_data & (mask << shift)) >> shift) #define BCM_CMD_CLEAR(mask, shift) (~(mask << shift)) #define BCM_CMD_SET(data, mask, shift) ((data & mask) << shift) #undef BCM_DBGGEN #ifdef BCM_DBGGEN #define BCM_DBG(x...) pr_info("bcm_dbg: " x) #else #define BCM_DBG(x...) do {} while (0) #endif #define BCM_INFO(x...) pr_info("bcm_info: " x) #define BCM_ERR(x...) pr_err("bcm_err: " x) enum exynos_bcm_dbg_ipc_type { IPC_BCM_DBG_EVENT = 0, IPC_BCM_DBG_PD, IPC_BCM_DBG_MAX }; enum exynos_bcm_err_code { E_OK = 0, E_INVAL, E_BUSY, }; enum exynos_bcm_event_dir { BCM_EVT_GET = 0, BCM_EVT_SET, }; enum exynos_bcm_event_id { BCM_EVT_PRE_DEFINE = 0, BCM_EVT_EVENT, BCM_EVT_RUN_CONT, BCM_EVT_IP_CONT, BCM_EVT_PERIOD_CONT, BCM_EVT_MODE_CONT, BCM_EVT_EVENT_FLT_ID, BCM_EVT_EVENT_FLT_OTHERS, BCM_EVT_EVENT_SAMPLE_ID, BCM_EVT_STR_STATE, BCM_EVT_DUMP_ADDR, BCM_EVT_GLBAUTO_CONT, BCM_EVT_HISTOGRAM_ID, BCM_EVT_HISTOGRAM_CONFIG, BCM_EVT_MAX, }; enum exynos_bcm_ip_range { BCM_EACH = 0, BCM_ALL, BCM_RANGE_MAX, }; struct exynos_bcm_dump_addr { u32 p_addr; u32 p_size; u32 buff_size; void __iomem *v_addr; }; struct exynos_bcm_ipc_base_info { enum exynos_bcm_event_dir direction; enum exynos_bcm_event_id event_id; enum exynos_bcm_ip_range ip_range; }; struct exynos_bcm_pd_info { char *pd_name; unsigned int cal_pdid; unsigned int pd_index; bool on; }; struct exynos_bcm_filter_id { unsigned int sm_id_mask; unsigned int sm_id_value; unsigned int sm_id_active[BCM_EVT_EVENT_MAX]; }; struct exynos_bcm_filter_others { unsigned int sm_other_type[BCM_EVT_FLT_OTHR_MAX]; unsigned int sm_other_mask[BCM_EVT_FLT_OTHR_MAX]; unsigned int sm_other_value[BCM_EVT_FLT_OTHR_MAX]; unsigned int sm_other_active[BCM_EVT_EVENT_MAX]; }; struct exynos_bcm_sample_id { unsigned int peak_mask; unsigned int peak_id; unsigned int peak_enable[BCM_EVT_EVENT_MAX]; }; struct exynos_bcm_event { unsigned int index; unsigned int event[BCM_EVT_EVENT_MAX]; }; struct exynos_bcm_dbg_data { struct device *dev; spinlock_t lock; struct exynos_bcm_dump_addr dump_addr; bool dump_klog; bool rmem_acquired; struct device_node *ipc_node; unsigned int ipc_ch_num; unsigned int ipc_size; struct exynos_bcm_pd_info *pd_info[BCM_PD_INFO_MAX]; unsigned int pd_size; struct exynos_bcm_event define_event[PRE_DEFINE_EVT_MAX]; unsigned int default_define_event; unsigned int define_event_max; struct exynos_bcm_filter_id define_filter_id[PRE_DEFINE_EVT_MAX]; struct exynos_bcm_filter_others define_filter_others[PRE_DEFINE_EVT_MAX]; struct exynos_bcm_sample_id define_sample_id[PRE_DEFINE_EVT_MAX]; unsigned int bcm_ip_nr; unsigned int bcm_ip_print_nr; unsigned int initial_bcm_run; unsigned int initial_period; unsigned int initial_bcm_mode; unsigned int *initial_run_ip; unsigned int glb_auto_en; unsigned int bcm_run_state; bool available_stop_owner[STOP_OWNER_MAX]; #if defined(CONFIG_EXYNOS_BCM_DBG_GNR) || defined(CONFIG_EXYNOS_BCM_DBG_GNR_MODULE) bool bcm_load_bin; struct hrtimer bcm_hrtimer; unsigned int period; unsigned int bcm_mode; #endif unsigned int bcm_cnt_nr; struct notifier_block itmon_notifier; struct exynos_bcm_calc *bcm_calc; struct exynos_bcm_show_bw *bcm_show_bw; #if defined(CONFIG_CPU_IDLE) unsigned int idle_ip_index; #endif }; struct exynos_bcm_calc_data { u64 dump_time; u64 ccnt; u64 pmcnt[BCM_EVT_EVENT_MAX]; }; struct exynos_bcm_calc { struct exynos_bcm_dbg_data *data; struct exynos_bcm_calc_data *acc_data; unsigned int sample_time; struct mutex lock; unsigned int num_ip; char **ip_name; int *bus_width; int *ip_cnt; unsigned int *ip_idx; struct delayed_work work; bool enable; unsigned int perf_define_event; unsigned int usage_cnt; }; struct exynos_bcm_show_bw { struct mutex lock; struct delayed_work bw_work; unsigned int num_sample; int enable_ctrl; u64 old_bw; u64 old_time; u64 new_bw; u64 new_time; u64 *mem_bw; u64 *dump_time; /* unit: msec */ }; struct exynos_bcm_bw_data { u64 seq_no; u64 dump_time; u64 ccnt; u64 pmcnt[BCM_EVT_EVENT_MAX]; }; struct exynos_bcm_bw { int measure_time; unsigned int num_ip; unsigned int *ip_idx; struct exynos_bcm_bw_data *bw_data; }; #if defined(CONFIG_EXYNOS_BCM_DBG_GNR) || defined(CONFIG_EXYNOS_BCM_DBG_GNR_MODULE) struct cmd_data { unsigned int raw_cmd; unsigned int cmd[CMD_DATA_MAX]; }; struct bin_system_func { int (*send_data)(struct cmd_data *); int (*timer_event)(void); }; struct os_system_func { void *(*ioremap)(u64 phys_addr, size_t size); void (*iounmap)(volatile void *addr); int (*snprint)(char *buf, size_t size, const char *fmt, ...); int (*print)(const char *, ...); u64 (*sched_clock)(void); }; #endif #if defined(CONFIG_EXYNOS_BCM_DBG) || defined(CONFIG_EXYNOS_BCM_DBG_MODULE) int exynos_bcm_dbg_ipc_send_data(enum exynos_bcm_dbg_ipc_type ipc_type, struct exynos_bcm_dbg_data *data, unsigned int *cmd); int exynos_bcm_dbg_pd_sync(unsigned int cal_pdid, bool on); void exynos_bcm_dbg_start(void); void exynos_bcm_dbg_stop(unsigned int bcm_stop_owner); void exynos_bcm_dbg_get_data(void *bcm); /* For MIF profiler */ void exynos_bcm_get_data(u64 *rwdata_transfer, u64 *rdata_transfer_cnt, u64 *rdata_latency_sum, u64 *output_bw); bool exynos_bcm_calc_enable(int enable); u64 exynos_bcm_get_ccnt(unsigned int idx); #else #define exynos_bcm_dbg_pd(a, b) do {} while (0) #define exynos_bcm_dbg_ipc_send_data(a, b, c) do {} while (0) #define exynos_bcm_dbg_start() do {} while (0) #define exynos_bcm_dbg_stop(a) do {} while (0) #define exynos_bcm_get_data(a, b, c, d) do {} while (0) #define exynos_bcm_calc_enable(a) do {} while (0) #endif #if defined(CONFIG_EXYNOS_BCM_DBG_GNR) || defined(CONFIG_EXYNOS_BCM_DBG_GNR_MODULE) int __nocfi exynos_bcm_dbg_load_bin(void); #else #define exynos_bcm_dbg_load_bin() do {} while (0) #endif #endif /* __EXYNOS_BCM_DBG_H_ */