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 return ERROR_COMMAND_SYNTAX_ERROR
;
440 free(rshim_dev_path
);
441 rshim_dev_path
= strdup(CMD_ARGV
[0]);
445 static const struct command_registration rshim_dap_subcommand_handlers
[] = {
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
[] = {
460 .help
= "perform rshim management",
461 .chain
= rshim_dap_subcommand_handlers
,
464 COMMAND_REGISTRATION_DONE
467 static int rshim_dap_init(void)
472 static int rshim_dap_quit(void)
477 static int rshim_dap_reset(int req_trst
, int req_srst
)
482 static int rshim_dap_speed(int speed
)
487 static int rshim_dap_khz(int khz
, int *jtag_speed
)
493 static int rshim_dap_speed_div(int speed
, int *khz
)
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
,
508 .quit
= rshim_disconnect
,
511 static const char *const rshim_dap_transport
[] = { "dapdirect_swd", NULL
};
513 struct adapter_driver rshim_dap_adapter_driver
= {
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
,