2 * Copyright (c) 2020, Mellanox Technologies Ltd. - All Rights Reserved
3 * Liming Sun <lsun@mellanox.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <helper/types.h>
24 #include <helper/system.h>
25 #include <helper/time_support.h>
26 #include <helper/list.h>
27 #include <jtag/interface.h>
28 #ifdef HAVE_SYS_IOCTL_H
29 #include <sys/ioctl.h>
31 #include <target/arm_adi_v5.h>
32 #include <transport/transport.h>
34 /* Rshim channel where the CoreSight register resides. */
35 #define RSH_MMIO_CHANNEL_RSHIM 0x1
37 /* APB and tile address translation. */
38 #define RSH_CS_ROM_BASE 0x80000000
39 #define RSH_CS_TILE_BASE 0x44000000
40 #define RSH_CS_TILE_SIZE 0x04000000
43 * APB-AP Identification Register
44 * The default value is defined in "CoreSight on-chip trace and debug
45 * (Revision: r1p0)", Section 3.16.5 APB-AP register summary.
47 #define APB_AP_IDR 0x44770002
49 /* CoreSight register definition. */
50 #define RSH_CORESIGHT_CTL 0x0e00
51 #define RSH_CORESIGHT_CTL_GO_SHIFT 0
52 #define RSH_CORESIGHT_CTL_GO_MASK 0x1ULL
53 #define RSH_CORESIGHT_CTL_ACTION_SHIFT 1
54 #define RSH_CORESIGHT_CTL_ACTION_MASK 0x2ULL
55 #define RSH_CORESIGHT_CTL_ADDR_SHIFT 2
56 #define RSH_CORESIGHT_CTL_ADDR_MASK 0x7ffffffcULL
57 #define RSH_CORESIGHT_CTL_ERR_SHIFT 31
58 #define RSH_CORESIGHT_CTL_ERR_MASK 0x80000000ULL
59 #define RSH_CORESIGHT_CTL_DATA_SHIFT 32
60 #define RSH_CORESIGHT_CTL_DATA_MASK 0xffffffff00000000ULL
62 /* Util macros to access the CoreSight register. */
63 #define RSH_CS_GET_FIELD(reg, field) \
64 (((uint64_t)(reg) & RSH_CORESIGHT_CTL_##field##_MASK) >> \
65 RSH_CORESIGHT_CTL_##field##_SHIFT)
67 #define RSH_CS_SET_FIELD(reg, field, value) \
68 (reg) = (((reg) & ~RSH_CORESIGHT_CTL_##field##_MASK) | \
69 (((uint64_t)(value) << RSH_CORESIGHT_CTL_##field##_SHIFT) & \
70 RSH_CORESIGHT_CTL_##field##_MASK))
72 #ifdef HAVE_SYS_IOCTL_H
73 /* Message used to program rshim via ioctl(). */
77 } __attribute__((packed
)) rshim_ioctl_msg
;
80 RSH_IOC_READ
= _IOWR('R', 0, rshim_ioctl_msg
),
81 RSH_IOC_WRITE
= _IOWR('R', 1, rshim_ioctl_msg
),
85 /* Use local variable stub for DP/AP registers. */
86 static uint32_t dp_ctrl_stat
;
87 static uint32_t dp_id_code
;
88 static uint32_t ap_sel
, ap_bank
;
89 static uint32_t ap_csw
;
90 static uint32_t ap_drw
;
91 static uint32_t ap_tar
, ap_tar_inc
;
93 /* Static functions to read/write via rshim/coresight. */
94 static int (*rshim_read
)(int chan
, int addr
, uint64_t *value
);
95 static int (*rshim_write
)(int chan
, int addr
, uint64_t value
);
96 static int coresight_write(uint32_t tile
, uint32_t addr
, uint32_t wdata
);
97 static int coresight_read(uint32_t tile
, uint32_t addr
, uint32_t *value
);
99 /* RShim file handler. */
100 static int rshim_fd
= -1;
102 /* DAP error code. */
103 static int rshim_dap_retval
= ERROR_OK
;
105 /* Default rshim device. */
106 #define RSHIM_DEV_PATH_DEFAULT "/dev/rshim0/rshim"
107 static char *rshim_dev_path
;
109 static int rshim_dev_read(int chan
, int addr
, uint64_t *value
)
113 addr
= (addr
& 0xFFFF) | (1 << 16);
114 rc
= pread(rshim_fd
, value
, sizeof(*value
), addr
);
116 #ifdef HAVE_SYS_IOCTL_H
117 if (rc
< 0 && errno
== ENOSYS
) {
122 rc
= ioctl(rshim_fd
, RSH_IOC_READ
, &msg
);
131 static int rshim_dev_write(int chan
, int addr
, uint64_t value
)
135 addr
= (addr
& 0xFFFF) | (1 << 16);
136 rc
= pwrite(rshim_fd
, &value
, sizeof(value
), addr
);
138 #ifdef HAVE_SYS_IOCTL_H
139 if (rc
< 0 && errno
== ENOSYS
) {
144 rc
= ioctl(rshim_fd
, RSH_IOC_WRITE
, &msg
);
151 /* Convert AP address to tile local address. */
152 static void ap_addr_2_tile(int *tile
, uint32_t *addr
)
154 *addr
-= RSH_CS_ROM_BASE
;
156 if (*addr
< RSH_CS_TILE_BASE
) {
159 *addr
-= RSH_CS_TILE_BASE
;
160 *tile
= *addr
/ RSH_CS_TILE_SIZE
+ 1;
161 *addr
= *addr
% RSH_CS_TILE_SIZE
;
166 * Write 4 bytes on the APB bus.
167 * tile = 0: access the root CS_ROM table
168 * > 0: access the ROM table of cluster (tile - 1)
170 static int coresight_write(uint32_t tile
, uint32_t addr
, uint32_t wdata
)
175 if (!rshim_read
|| !rshim_write
)
179 * ADDR[28] - must be set to 1 due to coresight ip.
180 * ADDR[27:24] - linear tile id
182 addr
= (addr
>> 2) | (tile
<< 24);
185 RSH_CS_SET_FIELD(ctl
, ADDR
, addr
);
186 RSH_CS_SET_FIELD(ctl
, ACTION
, 0); /* write */
187 RSH_CS_SET_FIELD(ctl
, DATA
, wdata
);
188 RSH_CS_SET_FIELD(ctl
, GO
, 1); /* start */
190 rshim_write(RSH_MMIO_CHANNEL_RSHIM
, RSH_CORESIGHT_CTL
, ctl
);
193 rc
= rshim_read(RSH_MMIO_CHANNEL_RSHIM
,
194 RSH_CORESIGHT_CTL
, &ctl
);
196 LOG_ERROR("Failed to read rshim.\n");
199 } while (RSH_CS_GET_FIELD(ctl
, GO
));
204 static int coresight_read(uint32_t tile
, uint32_t addr
, uint32_t *value
)
209 if (!rshim_read
|| !rshim_write
)
213 * ADDR[28] - must be set to 1 due to coresight ip.
214 * ADDR[27:24] - linear tile id
216 addr
= (addr
>> 2) | (tile
<< 24);
219 RSH_CS_SET_FIELD(ctl
, ADDR
, addr
);
220 RSH_CS_SET_FIELD(ctl
, ACTION
, 1); /* read */
221 RSH_CS_SET_FIELD(ctl
, GO
, 1); /* start */
223 rshim_write(RSH_MMIO_CHANNEL_RSHIM
, RSH_CORESIGHT_CTL
, ctl
);
226 rc
= rshim_read(RSH_MMIO_CHANNEL_RSHIM
,
227 RSH_CORESIGHT_CTL
, &ctl
);
229 LOG_ERROR("Failed to write rshim.\n");
232 } while (RSH_CS_GET_FIELD(ctl
, GO
));
234 *value
= RSH_CS_GET_FIELD(ctl
, DATA
);
238 static int rshim_dp_q_read(struct adiv5_dap
*dap
, unsigned int reg
,
250 *data
= CDBGPWRUPACK
| CSYSPWRUPACK
;
260 static int rshim_dp_q_write(struct adiv5_dap
*dap
, unsigned int reg
,
268 ap_sel
= (data
& DP_SELECT_APSEL
) >> 24;
269 ap_bank
= (data
& DP_SELECT_APBANK
) >> 4;
272 LOG_INFO("Unknown command");
279 static int rshim_ap_q_read(struct adiv5_ap
*ap
, unsigned int reg
,
283 int rc
= ERROR_OK
, tile
;
285 if (is_adiv6(ap
->dap
)) {
286 static bool error_flagged
;
288 LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode");
289 error_flagged
= true;
294 case ADIV5_MEM_AP_REG_CSW
:
298 case ADIV5_MEM_AP_REG_CFG
:
302 case ADIV5_MEM_AP_REG_BASE
:
303 *data
= RSH_CS_ROM_BASE
;
306 case ADIV5_AP_REG_IDR
:
313 case ADIV5_MEM_AP_REG_BD0
:
314 case ADIV5_MEM_AP_REG_BD1
:
315 case ADIV5_MEM_AP_REG_BD2
:
316 case ADIV5_MEM_AP_REG_BD3
:
317 addr
= (ap_tar
& ~0xf) + (reg
& 0x0C);
318 ap_addr_2_tile(&tile
, &addr
);
319 rc
= coresight_read(tile
, addr
, data
);
322 case ADIV5_MEM_AP_REG_DRW
:
323 addr
= (ap_tar
& ~0x3) + ap_tar_inc
;
324 ap_addr_2_tile(&tile
, &addr
);
325 rc
= coresight_read(tile
, addr
, data
);
326 if (!rc
&& (ap_csw
& CSW_ADDRINC_MASK
))
327 ap_tar_inc
+= (ap_csw
& 0x03) * 2;
331 LOG_INFO("Unknown command");
336 /* Track the last error code. */
338 rshim_dap_retval
= rc
;
343 static int rshim_ap_q_write(struct adiv5_ap
*ap
, unsigned int reg
,
346 int rc
= ERROR_OK
, tile
;
349 if (is_adiv6(ap
->dap
)) {
350 static bool error_flagged
;
352 LOG_ERROR("ADIv6 dap not supported by rshim dap-direct mode");
353 error_flagged
= true;
358 rshim_dap_retval
= ERROR_FAIL
;
363 case ADIV5_MEM_AP_REG_CSW
:
367 case ADIV5_MEM_AP_REG_TAR
:
372 case ADIV5_MEM_AP_REG_BD0
:
373 case ADIV5_MEM_AP_REG_BD1
:
374 case ADIV5_MEM_AP_REG_BD2
:
375 case ADIV5_MEM_AP_REG_BD3
:
376 addr
= (ap_tar
& ~0xf) + (reg
& 0x0C);
377 ap_addr_2_tile(&tile
, &addr
);
378 rc
= coresight_write(tile
, addr
, data
);
381 case ADIV5_MEM_AP_REG_DRW
:
383 addr
= (ap_tar
& ~0x3) + ap_tar_inc
;
384 ap_addr_2_tile(&tile
, &addr
);
385 rc
= coresight_write(tile
, addr
, data
);
386 if (!rc
&& (ap_csw
& CSW_ADDRINC_MASK
))
387 ap_tar_inc
+= (ap_csw
& 0x03) * 2;
395 /* Track the last error code. */
397 rshim_dap_retval
= rc
;
402 static int rshim_ap_q_abort(struct adiv5_dap
*dap
, uint8_t *ack
)
407 static int rshim_dp_run(struct adiv5_dap
*dap
)
409 int retval
= rshim_dap_retval
;
411 /* Clear the error code. */
412 rshim_dap_retval
= ERROR_OK
;
417 static int rshim_connect(struct adiv5_dap
*dap
)
419 char *path
= rshim_dev_path
? rshim_dev_path
: RSHIM_DEV_PATH_DEFAULT
;
421 rshim_fd
= open(path
, O_RDWR
| O_SYNC
);
422 if (rshim_fd
== -1) {
423 LOG_ERROR("Unable to open %s\n", path
);
428 * Set read/write operation via the device file. Function pointers
429 * are used here so more ways like remote accessing via socket could
432 rshim_read
= rshim_dev_read
;
433 rshim_write
= rshim_dev_write
;
438 static void rshim_disconnect(struct adiv5_dap
*dap
)
440 if (rshim_fd
!= -1) {
446 COMMAND_HANDLER(rshim_dap_device_command
)
449 command_print(CMD
, "Too many arguments");
450 return ERROR_COMMAND_SYNTAX_ERROR
;
453 free(rshim_dev_path
);
454 rshim_dev_path
= strdup(CMD_ARGV
[0]);
458 static const struct command_registration rshim_dap_subcommand_handlers
[] = {
461 .handler
= rshim_dap_device_command
,
462 .mode
= COMMAND_CONFIG
,
463 .help
= "set the rshim device",
464 .usage
= "</dev/rshim<N>/rshim>",
466 COMMAND_REGISTRATION_DONE
469 static const struct command_registration rshim_dap_command_handlers
[] = {
473 .help
= "perform rshim management",
474 .chain
= rshim_dap_subcommand_handlers
,
477 COMMAND_REGISTRATION_DONE
480 static int rshim_dap_init(void)
485 static int rshim_dap_quit(void)
490 static int rshim_dap_reset(int req_trst
, int req_srst
)
495 static int rshim_dap_speed(int speed
)
500 static int rshim_dap_khz(int khz
, int *jtag_speed
)
506 static int rshim_dap_speed_div(int speed
, int *khz
)
512 /* DAP operations. */
513 static const struct dap_ops rshim_dap_ops
= {
514 .connect
= rshim_connect
,
515 .queue_dp_read
= rshim_dp_q_read
,
516 .queue_dp_write
= rshim_dp_q_write
,
517 .queue_ap_read
= rshim_ap_q_read
,
518 .queue_ap_write
= rshim_ap_q_write
,
519 .queue_ap_abort
= rshim_ap_q_abort
,
521 .quit
= rshim_disconnect
,
524 static const char *const rshim_dap_transport
[] = { "dapdirect_swd", NULL
};
526 struct adapter_driver rshim_dap_adapter_driver
= {
528 .transports
= rshim_dap_transport
,
529 .commands
= rshim_dap_command_handlers
,
531 .init
= rshim_dap_init
,
532 .quit
= rshim_dap_quit
,
533 .reset
= rshim_dap_reset
,
534 .speed
= rshim_dap_speed
,
535 .khz
= rshim_dap_khz
,
536 .speed_div
= rshim_dap_speed_div
,
538 .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)