armv7m_trace: get rid of the old tpiu code
[fw/openocd] / src / target / armv7m_trace.c
1 /***************************************************************************
2  *   Copyright (C) 2015  Paul Fertser <fercerpav@gmail.com>                *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
16  ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <target/target.h>
23 #include <target/armv7m.h>
24 #include <target/cortex_m.h>
25 #include <target/armv7m_trace.h>
26 #include <jtag/interface.h>
27 #include <helper/time_support.h>
28
29 int armv7m_trace_itm_config(struct target *target)
30 {
31         struct armv7m_common *armv7m = target_to_armv7m(target);
32         struct armv7m_trace_config *trace_config = &armv7m->trace_config;
33         int retval;
34
35         retval = target_write_u32(target, ITM_LAR, ITM_LAR_KEY);
36         if (retval != ERROR_OK)
37                 return retval;
38
39         /* pg315 of CoreSight Components
40          * It is recommended that the ITMEn bit is cleared and waits for the
41          * ITMBusy bit to be cleared, before changing any fields in the
42          * Control Register, otherwise the behavior can be unpredictable.
43          */
44         uint32_t itm_tcr;
45         retval = target_read_u32(target, ITM_TCR, &itm_tcr);
46         if (retval != ERROR_OK)
47                 return retval;
48         retval = target_write_u32(target,
49                         ITM_TCR,
50                         itm_tcr & ~ITM_TCR_ITMENA_BIT
51                         );
52         if (retval != ERROR_OK)
53                 return retval;
54
55         int64_t then = timeval_ms() + 1000;
56         do {
57                 retval = target_read_u32(target, ITM_TCR, &itm_tcr);
58                 if (retval != ERROR_OK)
59                         return retval;
60                 if (timeval_ms() > then) {
61                         LOG_ERROR("timeout waiting for ITM_TCR_BUSY_BIT");
62                         return ERROR_FAIL;
63                 }
64         } while (itm_tcr & ITM_TCR_BUSY_BIT);
65
66         /* Enable ITM, TXENA, set TraceBusID and other parameters */
67         retval = target_write_u32(target, ITM_TCR, (1 << 0) | (1 << 3) |
68                                   (trace_config->itm_diff_timestamps << 1) |
69                                   (trace_config->itm_synchro_packets << 2) |
70                                   (trace_config->itm_async_timestamps << 4) |
71                                   (trace_config->itm_ts_prescale << 8) |
72                                   (trace_config->trace_bus_id << 16));
73         if (retval != ERROR_OK)
74                 return retval;
75
76         for (unsigned int i = 0; i < 8; i++) {
77                 retval = target_write_u32(target, ITM_TER0 + i * 4,
78                                           trace_config->itm_ter[i]);
79                 if (retval != ERROR_OK)
80                         return retval;
81         }
82
83         return ERROR_OK;
84 }
85
86 COMMAND_HANDLER(handle_itm_port_command)
87 {
88         struct target *target = get_current_target(CMD_CTX);
89         struct armv7m_common *armv7m = target_to_armv7m(target);
90         unsigned int reg_idx;
91         uint8_t port;
92         bool enable;
93
94         if (CMD_ARGC != 2)
95                 return ERROR_COMMAND_SYNTAX_ERROR;
96
97         COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], port);
98         COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
99         reg_idx = port / 32;
100         port = port % 32;
101         if (enable)
102                 armv7m->trace_config.itm_ter[reg_idx] |= (1 << port);
103         else
104                 armv7m->trace_config.itm_ter[reg_idx] &= ~(1 << port);
105
106         if (CMD_CTX->mode == COMMAND_EXEC)
107                 return armv7m_trace_itm_config(target);
108
109         armv7m->trace_config.itm_deferred_config = true;
110         return ERROR_OK;
111 }
112
113 COMMAND_HANDLER(handle_itm_ports_command)
114 {
115         struct target *target = get_current_target(CMD_CTX);
116         struct armv7m_common *armv7m = target_to_armv7m(target);
117         bool enable;
118
119         if (CMD_ARGC != 1)
120                 return ERROR_COMMAND_SYNTAX_ERROR;
121
122         COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
123         memset(armv7m->trace_config.itm_ter, enable ? 0xff : 0,
124                sizeof(armv7m->trace_config.itm_ter));
125
126         if (CMD_CTX->mode == COMMAND_EXEC)
127                 return armv7m_trace_itm_config(target);
128
129         armv7m->trace_config.itm_deferred_config = true;
130         return ERROR_OK;
131 }
132
133 static const struct command_registration itm_command_handlers[] = {
134         {
135                 .name = "port",
136                 .handler = handle_itm_port_command,
137                 .mode = COMMAND_ANY,
138                 .help = "Enable or disable ITM stimulus port",
139                 .usage = "<port> (0|1|on|off)",
140         },
141         {
142                 .name = "ports",
143                 .handler = handle_itm_ports_command,
144                 .mode = COMMAND_ANY,
145                 .help = "Enable or disable all ITM stimulus ports",
146                 .usage = "(0|1|on|off)",
147         },
148         COMMAND_REGISTRATION_DONE
149 };
150
151 const struct command_registration armv7m_trace_command_handlers[] = {
152         {
153                 .name = "itm",
154                 .mode = COMMAND_ANY,
155                 .help = "itm command group",
156                 .usage = "",
157                 .chain = itm_command_handlers,
158         },
159         COMMAND_REGISTRATION_DONE
160 };