diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 441e3efad94b3e6198beb659337392f4181ba97b..95c6d8db3068d3ab21f2dd3bef98c397c4585f9a 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -314,12 +314,11 @@ static int jlink_execute_queue(void)
 static int jlink_speed(int speed)
 {
 	int ret;
-	uint32_t freq;
-	uint16_t divider;
+	struct jaylink_speed tmp;
 	int max_speed;
 
 	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
-		ret = jaylink_get_speeds(devh, &freq, &divider);
+		ret = jaylink_get_speeds(devh, &tmp);
 
 		if (ret != JAYLINK_OK) {
 			LOG_ERROR("jaylink_get_speeds() failed: %s.",
@@ -327,8 +326,8 @@ static int jlink_speed(int speed)
 			return ERROR_JTAG_DEVICE_ERROR;
 		}
 
-		freq = freq / 1000;
-		max_speed = freq / divider;
+		tmp.freq /= 1000;
+		max_speed = tmp.freq / tmp.div;
 	} else {
 		max_speed = JLINK_MAX_SPEED;
 	}
@@ -433,15 +432,16 @@ static int select_interface(void)
 static int jlink_register(void)
 {
 	int ret;
-	int i;
+	size_t i;
 	bool handle_found;
+	size_t count;
 
 	if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER))
 		return ERROR_OK;
 
-	ret = jaylink_register(devh, &conn, connlist, NULL, NULL);
+	ret = jaylink_register(devh, &conn, connlist, &count);
 
-	if (ret < 0) {
+	if (ret != JAYLINK_OK) {
 		LOG_ERROR("jaylink_register() failed: %s.",
 			jaylink_strerror_name(ret));
 		return ERROR_FAIL;
@@ -449,7 +449,7 @@ static int jlink_register(void)
 
 	handle_found = false;
 
-	for (i = 0; i < ret; i++) {
+	for (i = 0; i < count; i++) {
 		if (connlist[i].handle == conn.handle) {
 			handle_found = true;
 			break;
@@ -502,8 +502,9 @@ static bool adjust_swd_buffer_size(void)
 	return true;
 }
 
-static int jaylink_log_handler(const struct jaylink_context *ctx, int level,
-		const char *format, va_list args, void *user_data)
+static int jaylink_log_handler(const struct jaylink_context *ctx,
+		enum jaylink_log_level level, const char *format, va_list args,
+		void *user_data)
 {
 	enum log_levels tmp;
 
@@ -561,10 +562,19 @@ static int jlink_init(void)
 		return ERROR_JTAG_INIT_FAILED;
 	}
 
-	ret = jaylink_get_device_list(jayctx, &devs);
+	ret = jaylink_discovery_scan(jayctx, 0);
 
-	if (ret < 0) {
-		LOG_ERROR("jaylink_get_device_list() failed: %s.",
+	if (ret != JAYLINK_OK) {
+		LOG_ERROR("jaylink_discovery_scan() failed: %s.",
+			jaylink_strerror_name(ret));
+		jaylink_exit(jayctx);
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	ret = jaylink_get_devices(jayctx, &devs, NULL);
+
+	if (ret != JAYLINK_OK) {
+		LOG_ERROR("jaylink_get_devices() failed: %s.",
 			jaylink_strerror_name(ret));
 		jaylink_exit(jayctx);
 		return ERROR_JTAG_INIT_FAILED;
@@ -614,7 +624,7 @@ static int jlink_init(void)
 		LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
 	}
 
-	jaylink_free_device_list(devs, 1);
+	jaylink_free_devices(devs, true);
 
 	if (!found_device) {
 		LOG_ERROR("No J-Link device found.");
@@ -723,7 +733,7 @@ static int jlink_init(void)
 
 	conn.handle = 0;
 	conn.pid = 0;
-	conn.hid = 0;
+	strcpy(conn.hid, "0.0.0.0");
 	conn.iid = 0;
 	conn.cid = 0;
 
@@ -767,6 +777,7 @@ static int jlink_init(void)
 static int jlink_quit(void)
 {
 	int ret;
+	size_t count;
 
 	if (trace_enabled) {
 		ret = jaylink_swo_stop(devh);
@@ -777,9 +788,9 @@ static int jlink_quit(void)
 	}
 
 	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) {
-		ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL);
+		ret = jaylink_unregister(devh, &conn, connlist, &count);
 
-		if (ret < 0)
+		if (ret != JAYLINK_OK)
 			LOG_ERROR("jaylink_unregister() failed: %s.",
 				jaylink_strerror_name(ret));
 	}
@@ -916,14 +927,22 @@ COMMAND_HANDLER(jlink_usb_command)
 
 COMMAND_HANDLER(jlink_serial_command)
 {
+	int ret;
+
 	if (CMD_ARGC != 1) {
 		command_print(CMD_CTX, "Need exactly one argument for jlink serial.");
 		return ERROR_COMMAND_SYNTAX_ERROR;
 	}
 
-	if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) {
+	ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number);
+
+	if (ret == JAYLINK_ERR) {
 		command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]);
 		return ERROR_FAIL;
+	} else if (ret != JAYLINK_OK) {
+		command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.",
+			jaylink_strerror_name(ret));
+		return ERROR_FAIL;
 	}
 
 	use_serial_number = true;
diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink
index d57dee67bc756291b7d8b51d350d1c6213e514f0..58a409dcbc83b63417d5dc2b4c3cb0bd3e0e53fd 160000
--- a/src/jtag/drivers/libjaylink
+++ b/src/jtag/drivers/libjaylink
@@ -1 +1 @@
-Subproject commit d57dee67bc756291b7d8b51d350d1c6213e514f0
+Subproject commit 58a409dcbc83b63417d5dc2b4c3cb0bd3e0e53fd