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;
294 case MEM_AP_REG_BASE:
295 *data = RSH_CS_ROM_BASE;
309 addr = (ap_tar & ~0xf) + (reg & 0x0C);
310 ap_addr_2_tile(&tile, &addr);
311 rc = coresight_read(tile, addr, data);
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;
360 addr = (ap_tar & ~0xf) + (reg & 0x0C);
361 ap_addr_2_tile(&tile, &addr);
362 rc = coresight_write(tile, addr, data);
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. Funtion 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,