936268b25a81113928b38e80dc5497a3a93d3353
[fw/openocd] / src / jtag / swim.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /*
4  * Copyright (C) 2020 by Antonio Borneo <borneo.antonio@gmail.com
5  *
6  * SWIM (Single Wire Interface Module) is a low-pin-count debug protocol
7  * used by STMicroelectronics MCU family STM8 and documented in UM470
8  * https://www.st.com/resource/en/user_manual/cd00173911.pdf
9  */
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include "interface.h"
16 #include "swim.h"
17 #include <helper/command.h>
18 #include <transport/transport.h>
19
20 extern struct adapter_driver *adapter_driver;
21
22 int swim_system_reset(void)
23 {
24         assert(adapter_driver->swim_ops);
25
26         return adapter_driver->swim_ops->srst();
27 }
28
29 int swim_read_mem(uint32_t addr, uint32_t size, uint32_t count,
30                                   uint8_t *buffer)
31 {
32         assert(adapter_driver->swim_ops);
33
34         return adapter_driver->swim_ops->read_mem(addr, size, count, buffer);
35 }
36
37 int swim_write_mem(uint32_t addr, uint32_t size, uint32_t count,
38                                    const uint8_t *buffer)
39 {
40         assert(adapter_driver->swim_ops);
41
42         return adapter_driver->swim_ops->write_mem(addr, size, count, buffer);
43 }
44
45 int swim_reconnect(void)
46 {
47         assert(adapter_driver->swim_ops);
48
49         return adapter_driver->swim_ops->reconnect();
50 }
51
52 COMMAND_HANDLER(handle_swim_newtap_command)
53 {
54         struct jtag_tap *tap;
55
56         /*
57          * only need "basename" and "tap_type", but for backward compatibility
58          * ignore extra parameters
59          */
60         if (CMD_ARGC < 2)
61                 return ERROR_COMMAND_SYNTAX_ERROR;
62
63         tap = calloc(1, sizeof(*tap));
64         if (!tap) {
65                 LOG_ERROR("Out of memory");
66                 return ERROR_FAIL;
67         }
68
69         tap->chip = strdup(CMD_ARGV[0]);
70         tap->tapname = strdup(CMD_ARGV[1]);
71         tap->dotted_name = alloc_printf("%s.%s", CMD_ARGV[0], CMD_ARGV[1]);
72         if (!tap->chip || !tap->tapname || !tap->dotted_name) {
73                 LOG_ERROR("Out of memory");
74                 free(tap->dotted_name);
75                 free(tap->tapname);
76                 free(tap->chip);
77                 free(tap);
78                 return ERROR_FAIL;
79         }
80
81         LOG_DEBUG("Creating new SWIM \"tap\", Chip: %s, Tap: %s, Dotted: %s",
82                           tap->chip, tap->tapname, tap->dotted_name);
83
84         /* default is enabled-after-reset */
85         tap->enabled = true;
86
87         jtag_tap_init(tap);
88         return ERROR_OK;
89 }
90
91 static const struct command_registration swim_transport_subcommand_handlers[] = {
92         {
93                 .name = "newtap",
94                 .handler = handle_swim_newtap_command,
95                 .mode = COMMAND_CONFIG,
96                 .help = "Create a new TAP instance named basename.tap_type, "
97                                 "and appends it to the scan chain.",
98                 .usage = "basename tap_type",
99         },
100         COMMAND_REGISTRATION_DONE
101 };
102
103 static const struct command_registration swim_transport_command_handlers[] = {
104         {
105                 .name = "swim",
106                 .mode = COMMAND_ANY,
107                 .help = "perform swim adapter actions",
108                 .usage = "",
109                 .chain = swim_transport_subcommand_handlers,
110         },
111         COMMAND_REGISTRATION_DONE
112 };
113
114 static int swim_transport_select(struct command_context *cmd_ctx)
115 {
116         LOG_DEBUG(__func__);
117
118         return register_commands(cmd_ctx, NULL, swim_transport_command_handlers);
119 }
120
121 static int swim_transport_init(struct command_context *cmd_ctx)
122 {
123         enum reset_types jtag_reset_config = jtag_get_reset_config();
124
125         LOG_DEBUG(__func__);
126
127         if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
128                 if (jtag_reset_config & RESET_SRST_NO_GATING)
129                         adapter_assert_reset();
130                 else
131                         LOG_WARNING("\'srst_nogate\' reset_config option is required");
132         } else
133                 adapter_deassert_reset();
134
135         return ERROR_OK;
136 }
137
138 static struct transport swim_transport = {
139         .name = "swim",
140         .select = swim_transport_select,
141         .init = swim_transport_init,
142 };
143
144 static void swim_constructor(void) __attribute__ ((constructor));
145 static void swim_constructor(void)
146 {
147         transport_register(&swim_transport);
148 }
149
150 bool transport_is_swim(void)
151 {
152         return get_current_transport() == &swim_transport;
153 }