blob: 1b1fda0e41deb417594325834e0efd809b0de6da [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* GXP debug dump handler
*
* Copyright (C) 2020 Google LLC
*/
#ifndef __GXP_DEBUG_DUMP_H__
#define __GXP_DEBUG_DUMP_H__
#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#if IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP)
#include <linux/platform_data/sscoredump.h>
#endif
#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_buffer {
void *vaddr;
dma_addr_t daddr;
u32 size;
};
struct gxp_debug_dump_manager {
struct gxp_dev *gxp;
struct gxp_debug_dump_buffer buf;
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;
#if 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);
#endif /* __GXP_DEBUG_DUMP_H__ */