1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (c) 2020, Mellanox Technologies Ltd. - All Rights Reserved
5 * Liming Sun <lsun@mellanox.com>
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>
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(). */
66 } __attribute__((packed
)) rshim_ioctl_msg
;
69 RSH_IOC_READ
= _IOWR('R', 0, rshim_ioctl_msg
),
70 RSH_IOC_WRITE
= _IOWR('R', 1, rshim_ioctl_msg
),
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;
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
)
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
) {
111 rc
= ioctl(rshim_fd
, RSH_IOC_READ
, &msg
);
120 static int rshim_dev_write(int chan
, int addr
, uint64_t value
)
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
) {
133 rc
= ioctl(rshim_fd
, RSH_IOC_WRITE
, &msg
);
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
) {
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
)
164 if (!rshim_read
|| !rshim_write
)
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);
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
);
182 rc
= rshim_read(RSH_MMIO_CHANNEL_RSHIM
,
183 RSH_CORESIGHT_CTL
, &ctl
);
185 LOG_ERROR("Failed to read rshim.\n");
188 } while (RSH_CS_GET_FIELD(ctl
, GO
));
193 static int coresight_read(uint32_t tile
, uint32_t addr
, uint32_t *value
)
198 if (!rshim_read
|| !rshim_write
)
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);
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
);
215 rc
= rshim_read(RSH_MMIO_CHANNEL_RSHIM
,
216 RSH_CORESIGHT_CTL
, &ctl
);
218 LOG_ERROR("Failed to write rshim.\n");
221 } while (RSH_CS_GET_FIELD(ctl
, GO
));
223 *value
= RSH_CS_GET_FIELD(ctl
, DATA
);
227 static int rshim_dp_q_read(struct adiv5_dap
*dap
, unsigned int reg
,
239 *data
= CDBGPWRUPACK
| CSYSPWRUPACK
;
249 static int rshim_dp_q_write(struct adiv5_dap
*dap
, unsigned int reg
,
257 ap_sel
= (data
& ADIV5_DP_SELECT_APSEL
) >> 24;
258 ap_bank
= (data
& ADIV5_DP_SELECT_APBANK
) >> 4;
261 LOG_INFO("Unknown command");
268 static int rshim_ap_q_read(struct adiv5_ap
*ap
, unsigned int reg
,
272 int rc
= ERROR_OK
, tile
;
274 if (is_adiv6(ap
->dap
)) {
275 static bool error_flagged
;
277 LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode");
278 error_flagged
= true;
283 case ADIV5_MEM_AP_REG_CSW
:
287 case ADIV5_MEM_AP_REG_CFG
:
291 case ADIV5_MEM_AP_REG_BASE
:
292 *data
= RSH_CS_ROM_BASE
;
295 case ADIV5_AP_REG_IDR
:
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
);
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;
320 LOG_INFO("Unknown command");
325 /* Track the last error code. */
327 rshim_dap_retval
= rc
;
332 static int rshim_ap_q_write(struct adiv5_ap
*ap
, unsigned int reg
,
335 int rc
= ERROR_OK
, tile
;
338 if (is_adiv6(ap
->dap
)) {
339 static bool error_flagged
;
341 LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode");
342 error_flagged
= true;
347 rshim_dap_retval
= ERROR_FAIL
;
352 case ADIV5_MEM_AP_REG_CSW
:
356 case ADIV5_MEM_AP_REG_TAR
:
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
);
370 case ADIV5_MEM_AP_REG_DRW
:
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;
384 /* Track the last error code. */
386 rshim_dap_retval
= rc
;
391 static int rshim_ap_q_abort(struct adiv5_dap
*dap
, uint8_t *ack
)
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
;
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
);
417 * Set read/write operation via the device file. Function pointers
418 * are used here so more ways like remote accessing via socket could
421 rshim_read
= rshim_dev_read
;
422 rshim_write
= rshim_dev_write
;
427 static void rshim_disconnect(struct adiv5_dap
*dap
)
429 if (rshim_fd
!= -1) {
435 COMMAND_HANDLER(rshim_dap_device_command
)
438 command_print(CMD
, "Too many arguments");
439 return ERROR_COMMAND_SYNTAX_ERROR
;
442 free(rshim_dev_path
);
443 rshim_dev_path
= strdup(CMD_ARGV
[0]);
447 static const struct command_registration rshim_dap_subcommand_handlers
[] = {
450 .handler
= rshim_dap_device_command
,
451 .mode
= COMMAND_CONFIG
,
452 .help
= "set the rshim device",
453 .usage
= "</dev/rshim<N>/rshim>",
455 COMMAND_REGISTRATION_DONE
458 static const struct command_registration rshim_dap_command_handlers
[] = {
462 .help
= "perform rshim management",
463 .chain
= rshim_dap_subcommand_handlers
,
466 COMMAND_REGISTRATION_DONE
469 static int rshim_dap_init(void)
474 static int rshim_dap_quit(void)
479 static int rshim_dap_reset(int req_trst
, int req_srst
)
484 static int rshim_dap_speed(int speed
)
489 static int rshim_dap_khz(int khz
, int *jtag_speed
)
495 static int rshim_dap_speed_div(int speed
, int *khz
)
501 /* DAP operations. */
502 static const struct dap_ops rshim_dap_ops
= {
503 .connect
= rshim_connect
,
504 .queue_dp_read
= rshim_dp_q_read
,
505 .queue_dp_write
= rshim_dp_q_write
,
506 .queue_ap_read
= rshim_ap_q_read
,
507 .queue_ap_write
= rshim_ap_q_write
,
508 .queue_ap_abort
= rshim_ap_q_abort
,
510 .quit
= rshim_disconnect
,
513 static const char *const rshim_dap_transport
[] = { "dapdirect_swd", NULL
};
515 struct adapter_driver rshim_dap_adapter_driver
= {
517 .transports
= rshim_dap_transport
,
518 .commands
= rshim_dap_command_handlers
,
520 .init
= rshim_dap_init
,
521 .quit
= rshim_dap_quit
,
522 .reset
= rshim_dap_reset
,
523 .speed
= rshim_dap_speed
,
524 .khz
= rshim_dap_khz
,
525 .speed_div
= rshim_dap_speed_div
,
527 .dap_swd_ops
= &rshim_dap_ops
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)