/* SPDX-License-Identifier: GPL-2.0 */ /* * GXP debug dump handler * * Copyright (C) 2020-2022 Google LLC */ #ifndef __GXP_DEBUG_DUMP_H__ #define __GXP_DEBUG_DUMP_H__ #include #include #include #if IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP) #include #endif #include "gxp-dma.h" #include "gxp-internal.h" #define GXP_NUM_COMMON_SEGMENTS 2 #define GXP_NUM_CORE_SEGMENTS 8 #define GXP_NUM_BUFFER_MAPPINGS 32 #define GXP_SEG_HEADER_NAME_LENGTH 32 #define GXP_NUM_SEGMENTS_PER_CORE \ (GXP_NUM_COMMON_SEGMENTS + GXP_NUM_CORE_SEGMENTS + \ GXP_NUM_BUFFER_MAPPINGS + 1) #define GXP_Q7_ICACHE_SIZE 131072 /* I-cache size in bytes */ #define GXP_Q7_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ #define GXP_Q7_ICACHE_WAYS 4 #define GXP_Q7_ICACHE_SETS \ ((GXP_Q7_ICACHE_SIZE / GXP_Q7_ICACHE_WAYS) / GXP_Q7_ICACHE_LINESIZE) #define GXP_Q7_ICACHE_WORDS_PER_LINE (GXP_Q7_ICACHE_LINESIZE / sizeof(u32)) #define GXP_Q7_DCACHE_SIZE 65536 /* D-cache size in bytes */ #define GXP_Q7_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ #define GXP_Q7_DCACHE_WAYS 4 #define GXP_Q7_DCACHE_SETS \ ((GXP_Q7_DCACHE_SIZE / GXP_Q7_DCACHE_WAYS) / GXP_Q7_DCACHE_LINESIZE) #define GXP_Q7_DCACHE_WORDS_PER_LINE (GXP_Q7_DCACHE_LINESIZE / sizeof(u32)) #define GXP_Q7_NUM_AREGS 64 #define GXP_Q7_DCACHE_TAG_RAMS 2 #define GXP_DEBUG_DUMP_INT 0x1 #define GXP_DEBUG_DUMP_INT_MASK BIT(GXP_DEBUG_DUMP_INT) #define GXP_DEBUG_DUMP_RETRY_NUM 5 /* * For debug dump, the kernel driver header file version must be the same as * the firmware header file version. In other words, * GXP_DEBUG_DUMP_HEADER_VERSION must be the same value as the value of * kGxpDebugDumpHeaderVersion in firmware. * Note: This needs to be updated when there are updates to gxp_core_dump and * gxp_core_dump_header (or anything within the struct that may cause a mismatch * with the firmware version of the debug dump header file). */ #define GXP_DEBUG_DUMP_HEADER_VERSION 0 struct gxp_timer_registers { u32 comparator; u32 control; u32 value; }; struct gxp_lpm_transition_registers { u32 next_state; u32 seq_addr; u32 timer_val; u32 timer_en; u32 trigger_num; u32 trigger_en; }; struct gxp_lpm_state_table_registers { struct gxp_lpm_transition_registers trans[PSM_TRANS_COUNT]; u32 enable_state; }; struct gxp_lpm_psm_registers { struct gxp_lpm_state_table_registers state_table[PSM_STATE_TABLE_COUNT]; u32 data[PSM_DATA_COUNT]; u32 cfg; u32 status; u32 debug_cfg; u32 break_addr; u32 gpin_lo_rd; u32 gpin_hi_rd; u32 gpout_lo_rd; u32 gpout_hi_rd; u32 debug_status; }; struct gxp_common_registers { u32 aurora_revision; u32 common_int_pol_0; u32 common_int_pol_1; u32 dedicated_int_pol; u32 raw_ext_int; u32 core_pd[CORE_PD_COUNT]; u32 global_counter_low; u32 global_counter_high; u32 wdog_control; u32 wdog_value; struct gxp_timer_registers timer[TIMER_COUNT]; u32 doorbell[DOORBELL_COUNT]; u32 sync_barrier[SYNC_BARRIER_COUNT]; }; struct gxp_lpm_registers { u32 lpm_version; u32 trigger_csr_start; u32 imem_start; u32 lpm_config; u32 psm_descriptor[PSM_DESCRIPTOR_COUNT]; u32 events_en[EVENTS_EN_COUNT]; u32 events_inv[EVENTS_INV_COUNT]; u32 function_select; u32 trigger_status; u32 event_status; u32 ops[OPS_COUNT]; struct gxp_lpm_psm_registers psm_regs[PSM_COUNT]; }; struct gxp_user_buffer { u64 device_addr; /* Device address of user buffer */ u32 size; /* Size of user buffer */ }; struct gxp_core_header { u32 core_id; /* Aurora core ID */ u32 dump_available; /* Dump data is available for core*/ u32 dump_req_reason; /* Code indicating reason for debug dump request */ u32 header_version; /* Header file version */ u32 fw_version; /* Firmware version */ u32 core_dump_size; /* Size of core dump */ struct gxp_user_buffer user_bufs[GXP_NUM_BUFFER_MAPPINGS]; }; struct gxp_seg_header { char name[GXP_SEG_HEADER_NAME_LENGTH]; /* Name of data type */ u32 size; /* Size of segment data */ u32 valid; /* Validity of segment data */ }; struct gxp_core_dump_header { struct gxp_core_header core_header; struct gxp_seg_header seg_header[GXP_NUM_CORE_SEGMENTS]; }; struct gxp_common_dump_data { struct gxp_common_registers common_regs; /* Seg 0 */ struct gxp_lpm_registers lpm_regs; /* Seg 1 */ }; struct gxp_common_dump { struct gxp_seg_header seg_header[GXP_NUM_COMMON_SEGMENTS]; struct gxp_common_dump_data common_dump_data; }; struct gxp_core_dump { struct gxp_core_dump_header core_dump_header[GXP_NUM_CORES]; /* * A collection of 'GXP_NUM_CORES' core dumps; * Each is core_dump_header[i].core_dump_size bytes long. */ uint32_t dump_data[]; }; struct gxp_debug_dump_work { struct work_struct work; struct gxp_dev *gxp; uint core_id; }; struct gxp_debug_dump_manager { struct gxp_dev *gxp; struct gxp_coherent_buf buf; /* Buffer holding debug dump data */ struct gxp_debug_dump_work debug_dump_works[GXP_NUM_CORES]; struct gxp_core_dump *core_dump; /* start of the core dump */ struct gxp_common_dump *common_dump; void *sscd_dev; void *sscd_pdata; dma_addr_t debug_dump_dma_handle; /* dma handle for debug dump */ /* * Debug dump lock to ensure only one debug dump is being processed at a * time */ struct mutex debug_dump_lock; /* * Array index maps to dsp cores. Array stores the pointer to the * crashed VD that was running on the respective core. This is used * only in mcu mode. */ struct gxp_virtual_device *crashed_core_to_vd[GXP_NUM_CORES]; #if IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP) struct sscd_segment segs[GXP_NUM_CORES][GXP_NUM_SEGMENTS_PER_CORE]; #endif }; int gxp_debug_dump_init(struct gxp_dev *gxp, void *sscd_dev, void *sscd_pdata); void gxp_debug_dump_exit(struct gxp_dev *gxp); struct work_struct *gxp_debug_dump_get_notification_handler(struct gxp_dev *gxp, uint core); bool gxp_debug_dump_is_enabled(void); /** * gxp_debug_dump_invalidate_segments() - Invalidate debug dump segments to enable * firmware to populate them on next debug * dump trigger. * * This function is not thread safe. Caller should take the necessary precautions. * * @gxp: The GXP device to obtain the handler for * @core_id: physical id of core whose dump segments need to be invalidated. */ void gxp_debug_dump_invalidate_segments(struct gxp_dev *gxp, uint32_t core_id); /** * gxp_debug_dump_process_dump_mcu_mode() - Checks and process the debug dump * for cores from core_list. * @gxp: The GXP device to obtain the handler for * @core_list: A bitfield enumerating the physical cores on which crash is * reported from firmware. * @crashed_vd: vd that has crashed. * * Return: * * 0 - Success. * * -EINVAL - If vd state is not GXP_VD_UNAVAILABLE. */ int gxp_debug_dump_process_dump_mcu_mode(struct gxp_dev *gxp, uint core_list, struct gxp_virtual_device *crashed_vd); #endif /* __GXP_DEBUG_DUMP_H__ */