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
;
286 case ADIV5_MEM_AP_REG_CSW
:
290 case ADIV5_MEM_AP_REG_CFG
:
294 case ADIV5_MEM_AP_REG_BASE
:
295 *data
= RSH_CS_ROM_BASE
;
298 case ADIV5_AP_REG_IDR
:
305 case ADIV5_MEM_AP_REG_BD0
:
306 case ADIV5_MEM_AP_REG_BD1
:
307 case ADIV5_MEM_AP_REG_BD2
:
308 case ADIV5_MEM_AP_REG_BD3
:
309 addr
= (ap_tar
& ~0xf) + (reg
& 0x0C);
310 ap_addr_2_tile(&tile
, &addr
);
311 rc
= coresight_read(tile
, addr
, data
);
314 case ADIV5_MEM_AP_REG_DRW
:
315 addr
= (ap_tar
& ~0x3) + ap_tar_inc
;
316 ap_addr_2_tile(&tile
, &addr
);
317 rc
= coresight_read(tile
, addr
, data
);
318 if (!rc
&& (ap_csw
& CSW_ADDRINC_MASK
))
319 ap_tar_inc
+= (ap_csw
& 0x03) * 2;
323 LOG_INFO("Unknown command");
328 /* Track the last error code. */
330 rshim_dap_retval
= rc
;
335 static int rshim_ap_q_write(struct adiv5_ap
*ap
, unsigned int reg
,
338 int rc
= ERROR_OK
, tile
;
342 rshim_dap_retval
= ERROR_FAIL
;
347 case ADIV5_MEM_AP_REG_CSW
:
351 case ADIV5_MEM_AP_REG_TAR
:
356 case ADIV5_MEM_AP_REG_BD0
:
357 case ADIV5_MEM_AP_REG_BD1
:
358 case ADIV5_MEM_AP_REG_BD2
:
359 case ADIV5_MEM_AP_REG_BD3
:
360 addr
= (ap_tar
& ~0xf) + (reg
& 0x0C);
361 ap_addr_2_tile(&tile
, &addr
);
362 rc
= coresight_write(tile
, addr
, data
);
365 case ADIV5_MEM_AP_REG_DRW
:
367 addr
= (ap_tar
& ~0x3) + ap_tar_inc
;
368 ap_addr_2_tile(&tile
, &addr
);
369 rc
= coresight_write(tile
, addr
, data
);
370 if (!rc
&& (ap_csw
& CSW_ADDRINC_MASK
))
371 ap_tar_inc
+= (ap_csw
& 0x03) * 2;
379 /* Track the last error code. */
381 rshim_dap_retval
= rc
;
386 static int rshim_ap_q_abort(struct adiv5_dap
*dap
, uint8_t *ack
)
391 static int rshim_dp_run(struct adiv5_dap
*dap
)
393 int retval
= rshim_dap_retval
;
395 /* Clear the error code. */
396 rshim_dap_retval
= ERROR_OK
;
401 static int rshim_connect(struct adiv5_dap
*dap
)
403 char *path
= rshim_dev_path
? rshim_dev_path
: RSHIM_DEV_PATH_DEFAULT
;
405 rshim_fd
= open(path
, O_RDWR
| O_SYNC
);
406 if (rshim_fd
== -1) {
407 LOG_ERROR("Unable to open %s\n", path
);
412 * Set read/write operation via the device file. Function pointers
413 * are used here so more ways like remote accessing via socket could
416 rshim_read
= rshim_dev_read
;
417 rshim_write
= rshim_dev_write
;
422 static void rshim_disconnect(struct adiv5_dap
*dap
)
424 if (rshim_fd
!= -1) {
430 COMMAND_HANDLER(rshim_dap_device_command
)
433 command_print(CMD
, "Too many arguments");
434 return ERROR_COMMAND_SYNTAX_ERROR
;
437 free(rshim_dev_path
);
438 rshim_dev_path
= strdup(CMD_ARGV
[0]);
442 static const struct command_registration rshim_dap_subcommand_handlers
[] = {
445 .handler
= rshim_dap_device_command
,
446 .mode
= COMMAND_CONFIG
,
447 .help
= "set the rshim device",
448 .usage
= "</dev/rshim<N>/rshim>",
450 COMMAND_REGISTRATION_DONE
453 static const struct command_registration rshim_dap_command_handlers
[] = {
457 .help
= "perform rshim management",
458 .chain
= rshim_dap_subcommand_handlers
,
461 COMMAND_REGISTRATION_DONE
464 static int rshim_dap_init(void)
469 static int rshim_dap_quit(void)
474 static int rshim_dap_reset(int req_trst
, int req_srst
)
479 static int rshim_dap_speed(int speed
)
484 static int rshim_dap_khz(int khz
, int *jtag_speed
)
490 static int rshim_dap_speed_div(int speed
, int *khz
)
496 /* DAP operations. */
497 static const struct dap_ops rshim_dap_ops
= {
498 .connect
= rshim_connect
,
499 .queue_dp_read
= rshim_dp_q_read
,
500 .queue_dp_write
= rshim_dp_q_write
,
501 .queue_ap_read
= rshim_ap_q_read
,
502 .queue_ap_write
= rshim_ap_q_write
,
503 .queue_ap_abort
= rshim_ap_q_abort
,
505 .quit
= rshim_disconnect
,
508 static const char *const rshim_dap_transport
[] = { "dapdirect_swd", NULL
};
510 struct adapter_driver rshim_dap_adapter_driver
= {
512 .transports
= rshim_dap_transport
,
513 .commands
= rshim_dap_command_handlers
,
515 .init
= rshim_dap_init
,
516 .quit
= rshim_dap_quit
,
517 .reset
= rshim_dap_reset
,
518 .speed
= rshim_dap_speed
,
519 .khz
= rshim_dap_khz
,
520 .speed_div
= rshim_dap_speed_div
,
522 .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)