target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / jtag / drivers / rshim.c
blob21fc7fd378509c329a19017447c8c78b777fc357
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /*
4 * Copyright (c) 2020, Mellanox Technologies Ltd. - All Rights Reserved
5 * Liming Sun <lsun@mellanox.com>
6 */
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include <helper/types.h>
13 #include <helper/system.h>
14 #include <helper/time_support.h>
15 #include <helper/list.h>
16 #include <jtag/interface.h>
17 #ifdef HAVE_SYS_IOCTL_H
18 #include <sys/ioctl.h>
19 #endif
20 #include <target/arm_adi_v5.h>
21 #include <transport/transport.h>
23 /* Rshim channel where the CoreSight register resides. */
24 #define RSH_MMIO_CHANNEL_RSHIM 0x1
26 /* APB and tile address translation. */
27 #define RSH_CS_ROM_BASE 0x80000000
28 #define RSH_CS_TILE_BASE 0x44000000
29 #define RSH_CS_TILE_SIZE 0x04000000
32 * APB-AP Identification Register
33 * The default value is defined in "CoreSight on-chip trace and debug
34 * (Revision: r1p0)", Section 3.16.5 APB-AP register summary.
36 #define APB_AP_IDR 0x44770002
38 /* CoreSight register definition. */
39 #define RSH_CORESIGHT_CTL 0x0e00
40 #define RSH_CORESIGHT_CTL_GO_SHIFT 0
41 #define RSH_CORESIGHT_CTL_GO_MASK 0x1ULL
42 #define RSH_CORESIGHT_CTL_ACTION_SHIFT 1
43 #define RSH_CORESIGHT_CTL_ACTION_MASK 0x2ULL
44 #define RSH_CORESIGHT_CTL_ADDR_SHIFT 2
45 #define RSH_CORESIGHT_CTL_ADDR_MASK 0x7ffffffcULL
46 #define RSH_CORESIGHT_CTL_ERR_SHIFT 31
47 #define RSH_CORESIGHT_CTL_ERR_MASK 0x80000000ULL
48 #define RSH_CORESIGHT_CTL_DATA_SHIFT 32
49 #define RSH_CORESIGHT_CTL_DATA_MASK 0xffffffff00000000ULL
51 /* Util macros to access the CoreSight register. */
52 #define RSH_CS_GET_FIELD(reg, field) \
53 (((uint64_t)(reg) & RSH_CORESIGHT_CTL_##field##_MASK) >> \
54 RSH_CORESIGHT_CTL_##field##_SHIFT)
56 #define RSH_CS_SET_FIELD(reg, field, value) \
57 (reg) = (((reg) & ~RSH_CORESIGHT_CTL_##field##_MASK) | \
58 (((uint64_t)(value) << RSH_CORESIGHT_CTL_##field##_SHIFT) & \
59 RSH_CORESIGHT_CTL_##field##_MASK))
61 #ifdef HAVE_SYS_IOCTL_H
62 /* Message used to program rshim via ioctl(). */
63 typedef struct {
64 uint32_t addr;
65 uint64_t data;
66 } __attribute__((packed)) rshim_ioctl_msg;
68 enum {
69 RSH_IOC_READ = _IOWR('R', 0, rshim_ioctl_msg),
70 RSH_IOC_WRITE = _IOWR('R', 1, rshim_ioctl_msg),
72 #endif
74 /* Use local variable stub for DP/AP registers. */
75 static uint32_t dp_ctrl_stat;
76 static uint32_t dp_id_code;
77 static uint32_t ap_sel, ap_bank;
78 static uint32_t ap_csw;
79 static uint32_t ap_drw;
80 static uint32_t ap_tar, ap_tar_inc;
82 /* Static functions to read/write via rshim/coresight. */
83 static int (*rshim_read)(int chan, int addr, uint64_t *value);
84 static int (*rshim_write)(int chan, int addr, uint64_t value);
85 static int coresight_write(uint32_t tile, uint32_t addr, uint32_t wdata);
86 static int coresight_read(uint32_t tile, uint32_t addr, uint32_t *value);
88 /* RShim file handler. */
89 static int rshim_fd = -1;
91 /* DAP error code. */
92 static int rshim_dap_retval = ERROR_OK;
94 /* Default rshim device. */
95 #define RSHIM_DEV_PATH_DEFAULT "/dev/rshim0/rshim"
96 static char *rshim_dev_path;
98 static int rshim_dev_read(int chan, int addr, uint64_t *value)
100 int rc;
102 addr = (addr & 0xFFFF) | (1 << 16);
103 rc = pread(rshim_fd, value, sizeof(*value), addr);
105 #ifdef HAVE_SYS_IOCTL_H
106 if (rc < 0 && errno == ENOSYS) {
107 rshim_ioctl_msg msg;
109 msg.addr = addr;
110 msg.data = 0;
111 rc = ioctl(rshim_fd, RSH_IOC_READ, &msg);
112 if (!rc)
113 *value = msg.data;
115 #endif
117 return rc;
120 static int rshim_dev_write(int chan, int addr, uint64_t value)
122 int rc;
124 addr = (addr & 0xFFFF) | (1 << 16);
125 rc = pwrite(rshim_fd, &value, sizeof(value), addr);
127 #ifdef HAVE_SYS_IOCTL_H
128 if (rc < 0 && errno == ENOSYS) {
129 rshim_ioctl_msg msg;
131 msg.addr = addr;
132 msg.data = value;
133 rc = ioctl(rshim_fd, RSH_IOC_WRITE, &msg);
135 #endif
137 return rc;
140 /* Convert AP address to tile local address. */
141 static void ap_addr_2_tile(int *tile, uint32_t *addr)
143 *addr -= RSH_CS_ROM_BASE;
145 if (*addr < RSH_CS_TILE_BASE) {
146 *tile = 0;
147 } else {
148 *addr -= RSH_CS_TILE_BASE;
149 *tile = *addr / RSH_CS_TILE_SIZE + 1;
150 *addr = *addr % RSH_CS_TILE_SIZE;
155 * Write 4 bytes on the APB bus.
156 * tile = 0: access the root CS_ROM table
157 * > 0: access the ROM table of cluster (tile - 1)
159 static int coresight_write(uint32_t tile, uint32_t addr, uint32_t wdata)
161 uint64_t ctl = 0;
162 int rc;
164 if (!rshim_read || !rshim_write)
165 return ERROR_FAIL;
168 * ADDR[28] - must be set to 1 due to coresight ip.
169 * ADDR[27:24] - linear tile id
171 addr = (addr >> 2) | (tile << 24);
172 if (tile)
173 addr |= (1 << 28);
174 RSH_CS_SET_FIELD(ctl, ADDR, addr);
175 RSH_CS_SET_FIELD(ctl, ACTION, 0); /* write */
176 RSH_CS_SET_FIELD(ctl, DATA, wdata);
177 RSH_CS_SET_FIELD(ctl, GO, 1); /* start */
179 rshim_write(RSH_MMIO_CHANNEL_RSHIM, RSH_CORESIGHT_CTL, ctl);
181 do {
182 rc = rshim_read(RSH_MMIO_CHANNEL_RSHIM,
183 RSH_CORESIGHT_CTL, &ctl);
184 if (rc < 0) {
185 LOG_ERROR("Failed to read rshim.\n");
186 return rc;
188 } while (RSH_CS_GET_FIELD(ctl, GO));
190 return ERROR_OK;
193 static int coresight_read(uint32_t tile, uint32_t addr, uint32_t *value)
195 uint64_t ctl = 0;
196 int rc;
198 if (!rshim_read || !rshim_write)
199 return ERROR_FAIL;
202 * ADDR[28] - must be set to 1 due to coresight ip.
203 * ADDR[27:24] - linear tile id
205 addr = (addr >> 2) | (tile << 24);
206 if (tile)
207 addr |= (1 << 28);
208 RSH_CS_SET_FIELD(ctl, ADDR, addr);
209 RSH_CS_SET_FIELD(ctl, ACTION, 1); /* read */
210 RSH_CS_SET_FIELD(ctl, GO, 1); /* start */
212 rshim_write(RSH_MMIO_CHANNEL_RSHIM, RSH_CORESIGHT_CTL, ctl);
214 do {
215 rc = rshim_read(RSH_MMIO_CHANNEL_RSHIM,
216 RSH_CORESIGHT_CTL, &ctl);
217 if (rc < 0) {
218 LOG_ERROR("Failed to write rshim.\n");
219 return rc;
221 } while (RSH_CS_GET_FIELD(ctl, GO));
223 *value = RSH_CS_GET_FIELD(ctl, DATA);
224 return ERROR_OK;
227 static int rshim_dp_q_read(struct adiv5_dap *dap, unsigned int reg,
228 uint32_t *data)
230 if (!data)
231 return ERROR_OK;
233 switch (reg) {
234 case DP_DPIDR:
235 *data = dp_id_code;
236 break;
238 case DP_CTRL_STAT:
239 *data = CDBGPWRUPACK | CSYSPWRUPACK;
240 break;
242 default:
243 break;
246 return ERROR_OK;
249 static int rshim_dp_q_write(struct adiv5_dap *dap, unsigned int reg,
250 uint32_t data)
252 switch (reg) {
253 case DP_CTRL_STAT:
254 dp_ctrl_stat = data;
255 break;
256 case DP_SELECT:
257 ap_sel = (data & ADIV5_DP_SELECT_APSEL) >> 24;
258 ap_bank = (data & ADIV5_DP_SELECT_APBANK) >> 4;
259 break;
260 default:
261 LOG_INFO("Unknown command");
262 break;
265 return ERROR_OK;
268 static int rshim_ap_q_read(struct adiv5_ap *ap, unsigned int reg,
269 uint32_t *data)
271 uint32_t addr;
272 int rc = ERROR_OK, tile;
274 if (is_adiv6(ap->dap)) {
275 static bool error_flagged;
276 if (!error_flagged)
277 LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode");
278 error_flagged = true;
279 return ERROR_FAIL;
282 switch (reg) {
283 case ADIV5_MEM_AP_REG_CSW:
284 *data = ap_csw;
285 break;
287 case ADIV5_MEM_AP_REG_CFG:
288 *data = 0;
289 break;
291 case ADIV5_MEM_AP_REG_BASE:
292 *data = RSH_CS_ROM_BASE;
293 break;
295 case ADIV5_AP_REG_IDR:
296 if (ap->ap_num == 0)
297 *data = APB_AP_IDR;
298 else
299 *data = 0;
300 break;
302 case ADIV5_MEM_AP_REG_BD0:
303 case ADIV5_MEM_AP_REG_BD1:
304 case ADIV5_MEM_AP_REG_BD2:
305 case ADIV5_MEM_AP_REG_BD3:
306 addr = (ap_tar & ~0xf) + (reg & 0x0C);
307 ap_addr_2_tile(&tile, &addr);
308 rc = coresight_read(tile, addr, data);
309 break;
311 case ADIV5_MEM_AP_REG_DRW:
312 addr = (ap_tar & ~0x3) + ap_tar_inc;
313 ap_addr_2_tile(&tile, &addr);
314 rc = coresight_read(tile, addr, data);
315 if (!rc && (ap_csw & CSW_ADDRINC_MASK))
316 ap_tar_inc += (ap_csw & 0x03) * 2;
317 break;
319 default:
320 LOG_INFO("Unknown command");
321 rc = ERROR_FAIL;
322 break;
325 /* Track the last error code. */
326 if (rc != ERROR_OK)
327 rshim_dap_retval = rc;
329 return rc;
332 static int rshim_ap_q_write(struct adiv5_ap *ap, unsigned int reg,
333 uint32_t data)
335 int rc = ERROR_OK, tile;
336 uint32_t addr;
338 if (is_adiv6(ap->dap)) {
339 static bool error_flagged;
340 if (!error_flagged)
341 LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode");
342 error_flagged = true;
343 return ERROR_FAIL;
346 if (ap_bank != 0) {
347 rshim_dap_retval = ERROR_FAIL;
348 return ERROR_FAIL;
351 switch (reg) {
352 case ADIV5_MEM_AP_REG_CSW:
353 ap_csw = data;
354 break;
356 case ADIV5_MEM_AP_REG_TAR:
357 ap_tar = data;
358 ap_tar_inc = 0;
359 break;
361 case ADIV5_MEM_AP_REG_BD0:
362 case ADIV5_MEM_AP_REG_BD1:
363 case ADIV5_MEM_AP_REG_BD2:
364 case ADIV5_MEM_AP_REG_BD3:
365 addr = (ap_tar & ~0xf) + (reg & 0x0C);
366 ap_addr_2_tile(&tile, &addr);
367 rc = coresight_write(tile, addr, data);
368 break;
370 case ADIV5_MEM_AP_REG_DRW:
371 ap_drw = data;
372 addr = (ap_tar & ~0x3) + ap_tar_inc;
373 ap_addr_2_tile(&tile, &addr);
374 rc = coresight_write(tile, addr, data);
375 if (!rc && (ap_csw & CSW_ADDRINC_MASK))
376 ap_tar_inc += (ap_csw & 0x03) * 2;
377 break;
379 default:
380 rc = EINVAL;
381 break;
384 /* Track the last error code. */
385 if (rc != ERROR_OK)
386 rshim_dap_retval = rc;
388 return rc;
391 static int rshim_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack)
393 return ERROR_OK;
396 static int rshim_dp_run(struct adiv5_dap *dap)
398 int retval = rshim_dap_retval;
400 /* Clear the error code. */
401 rshim_dap_retval = ERROR_OK;
403 return retval;
406 static int rshim_connect(struct adiv5_dap *dap)
408 char *path = rshim_dev_path ? rshim_dev_path : RSHIM_DEV_PATH_DEFAULT;
410 rshim_fd = open(path, O_RDWR | O_SYNC);
411 if (rshim_fd == -1) {
412 LOG_ERROR("Unable to open %s\n", path);
413 return ERROR_FAIL;
417 * Set read/write operation via the device file. Function pointers
418 * are used here so more ways like remote accessing via socket could
419 * be added later.
421 rshim_read = rshim_dev_read;
422 rshim_write = rshim_dev_write;
424 return ERROR_OK;
427 static void rshim_disconnect(struct adiv5_dap *dap)
429 if (rshim_fd != -1) {
430 close(rshim_fd);
431 rshim_fd = -1;
435 COMMAND_HANDLER(rshim_dap_device_command)
437 if (CMD_ARGC != 1)
438 return ERROR_COMMAND_SYNTAX_ERROR;
440 free(rshim_dev_path);
441 rshim_dev_path = strdup(CMD_ARGV[0]);
442 return ERROR_OK;
445 static const struct command_registration rshim_dap_subcommand_handlers[] = {
447 .name = "device",
448 .handler = rshim_dap_device_command,
449 .mode = COMMAND_CONFIG,
450 .help = "set the rshim device",
451 .usage = "</dev/rshim<N>/rshim>",
453 COMMAND_REGISTRATION_DONE
456 static const struct command_registration rshim_dap_command_handlers[] = {
458 .name = "rshim",
459 .mode = COMMAND_ANY,
460 .help = "perform rshim management",
461 .chain = rshim_dap_subcommand_handlers,
462 .usage = "",
464 COMMAND_REGISTRATION_DONE
467 static int rshim_dap_init(void)
469 return ERROR_OK;
472 static int rshim_dap_quit(void)
474 return ERROR_OK;
477 static int rshim_dap_reset(int req_trst, int req_srst)
479 return ERROR_OK;
482 static int rshim_dap_speed(int speed)
484 return ERROR_OK;
487 static int rshim_dap_khz(int khz, int *jtag_speed)
489 *jtag_speed = khz;
490 return ERROR_OK;
493 static int rshim_dap_speed_div(int speed, int *khz)
495 *khz = speed;
496 return ERROR_OK;
499 /* DAP operations. */
500 static const struct dap_ops rshim_dap_ops = {
501 .connect = rshim_connect,
502 .queue_dp_read = rshim_dp_q_read,
503 .queue_dp_write = rshim_dp_q_write,
504 .queue_ap_read = rshim_ap_q_read,
505 .queue_ap_write = rshim_ap_q_write,
506 .queue_ap_abort = rshim_ap_q_abort,
507 .run = rshim_dp_run,
508 .quit = rshim_disconnect,
511 static const char *const rshim_dap_transport[] = { "dapdirect_swd", NULL };
513 struct adapter_driver rshim_dap_adapter_driver = {
514 .name = "rshim",
515 .transports = rshim_dap_transport,
516 .commands = rshim_dap_command_handlers,
518 .init = rshim_dap_init,
519 .quit = rshim_dap_quit,
520 .reset = rshim_dap_reset,
521 .speed = rshim_dap_speed,
522 .khz = rshim_dap_khz,
523 .speed_div = rshim_dap_speed_div,
525 .dap_swd_ops = &rshim_dap_ops,