aboutsummaryrefslogtreecommitdiff
path: root/src/target/xtensa/xtensa_chip.c
blob: 79aa3e48e8de4f8850a31a33a8833569d514bf86 (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
/* SPDX-License-Identifier: GPL-2.0-or-later */

/***************************************************************************
 *   Xtensa Chip-level Target Support for OpenOCD                          *
 *   Copyright (C) 2020-2022 Cadence Design Systems, Inc.                  *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "assert.h"
#include <target/target.h>
#include <target/target_type.h>
#include <target/arm_adi_v5.h>
#include <rtos/rtos.h>
#include "xtensa_chip.h"

int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
	struct xtensa_debug_module_config *dm_cfg)
{
	struct xtensa_chip_common *xtensa_chip = (struct xtensa_chip_common *)arch_info;
	int ret = xtensa_init_arch_info(target, &xtensa_chip->xtensa, dm_cfg);
	if (ret != ERROR_OK)
		return ret;
	/* All xtensa target structures point back to original xtensa_chip */
	xtensa_chip->xtensa.xtensa_chip = arch_info;
	return ERROR_OK;
}

int xtensa_chip_target_init(struct command_context *cmd_ctx, struct target *target)
{
	return xtensa_target_init(cmd_ctx, target);
}

int xtensa_chip_arch_state(struct target *target)
{
	return ERROR_OK;
}

static int xtensa_chip_poll(struct target *target)
{
	enum target_state old_state = target->state;
	int ret = xtensa_poll(target);

	if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
		/*Call any event callbacks that are applicable */
		if (old_state == TARGET_DEBUG_RUNNING)
			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
		else
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
	}

	return ret;
}

static int xtensa_chip_virt2phys(struct target *target,
	target_addr_t virtual, target_addr_t *physical)
{
	if (physical) {
		*physical = virtual;
		return ERROR_OK;
	}
	return ERROR_FAIL;
}

static const struct xtensa_debug_ops xtensa_chip_dm_dbg_ops = {
	.queue_enable = xtensa_dm_queue_enable,
	.queue_reg_read = xtensa_dm_queue_reg_read,
	.queue_reg_write = xtensa_dm_queue_reg_write
};

static const struct xtensa_power_ops xtensa_chip_dm_pwr_ops = {
	.queue_reg_read = xtensa_dm_queue_pwr_reg_read,
	.queue_reg_write = xtensa_dm_queue_pwr_reg_write
};

static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp)
{
	struct xtensa_debug_module_config xtensa_chip_dm_cfg = {
		.dbg_ops = &xtensa_chip_dm_dbg_ops,
		.pwr_ops = &xtensa_chip_dm_pwr_ops,
		.tap = NULL,
		.queue_tdi_idle = NULL,
		.queue_tdi_idle_arg = NULL,
	};

	xtensa_chip_dm_cfg.tap = target->tap;
	LOG_DEBUG("JTAG: %s:%s pos %d", target->tap->chip, target->tap->tapname, target->tap->abs_chain_position);

	struct xtensa_chip_common *xtensa_chip = calloc(1, sizeof(struct xtensa_chip_common));
	if (!xtensa_chip) {
		LOG_ERROR("Failed to alloc chip-level memory!");
		return ERROR_FAIL;
	}

	int ret = xtensa_chip_init_arch_info(target, xtensa_chip, &xtensa_chip_dm_cfg);
	if (ret != ERROR_OK) {
		LOG_ERROR("Failed to init arch info!");
		free(xtensa_chip);
		return ret;
	}

	/*Assume running target. If different, the first poll will fix this. */
	target->state = TARGET_RUNNING;
	target->debug_reason = DBG_REASON_NOTHALTED;
	return ERROR_OK;
}

void xtensa_chip_target_deinit(struct target *target)
{
	struct xtensa *xtensa = target_to_xtensa(target);
	xtensa_target_deinit(target);
	free(xtensa->xtensa_chip);
}

static int xtensa_chip_examine(struct target *target)
{
	return xtensa_examine(target);
}

int xtensa_chip_jim_configure(struct target *target, struct jim_getopt_info *goi)
{
	target->has_dap = false;
	return JIM_CONTINUE;
}

/** Methods for generic example of Xtensa-based chip-level targets. */
struct target_type xtensa_chip_target = {
	.name = "xtensa",

	.poll = xtensa_chip_poll,
	.arch_state = xtensa_chip_arch_state,

	.halt = xtensa_halt,
	.resume = xtensa_resume,
	.step = xtensa_step,

	.assert_reset = xtensa_assert_reset,
	.deassert_reset = xtensa_deassert_reset,
	.soft_reset_halt = xtensa_soft_reset_halt,

	.virt2phys = xtensa_chip_virt2phys,
	.mmu = xtensa_mmu_is_enabled,
	.read_memory = xtensa_read_memory,
	.write_memory = xtensa_write_memory,

	.read_buffer = xtensa_read_buffer,
	.write_buffer = xtensa_write_buffer,

	.checksum_memory = xtensa_checksum_memory,

	.get_gdb_reg_list = xtensa_get_gdb_reg_list,

	.add_breakpoint = xtensa_breakpoint_add,
	.remove_breakpoint = xtensa_breakpoint_remove,

	.add_watchpoint = xtensa_watchpoint_add,
	.remove_watchpoint = xtensa_watchpoint_remove,

	.target_create = xtensa_chip_target_create,
	.target_jim_configure = xtensa_chip_jim_configure,
	.init_target = xtensa_chip_target_init,
	.examine = xtensa_chip_examine,
	.deinit_target = xtensa_chip_target_deinit,

	.gdb_query_custom = xtensa_gdb_query_custom,

	.commands = xtensa_command_handlers,
};