summaryrefslogtreecommitdiff
path: root/gxp-debug-dump.h
blob: aeb822902e285bd2a9710180adb6f6dc1a3ee7f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/* 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 <linux/bitops.h>
#include <linux/types.h>
#include <linux/workqueue.h>

#include "gxp-dma.h"
#include "gxp-internal.h"

#define HAS_COREDUMP                                                           \
	(IS_ENABLED(CONFIG_GXP_TEST) || IS_ENABLED(CONFIG_SUBSYSTEM_COREDUMP))

#if HAS_COREDUMP
#include <linux/platform_data/sscoredump.h>
#endif

#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;
#if HAS_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.
 *
 * The caller must hold @crashed_vd->debug_dump_lock.
 *
 * 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__ */