diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c
index eeddad85009d..ccd1c9cb25be 100644
--- a/sys/dev/tpm/tpm20.c
+++ b/sys/dev/tpm/tpm20.c
@@ -1,357 +1,359 @@
 /*-
  * Copyright (c) 2018 Stormshield.
  * Copyright (c) 2018 Semihalf.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/random.h>
 
 #include "tpm20.h"
 
 #define TPM_HARVEST_SIZE     16
 /*
  * Perform a harvest every 10 seconds.
  * Since discrete TPMs are painfully slow
  * we don't want to execute this too often
  * as the chip is likely to be used by others too.
  */
-#define TPM_HARVEST_INTERVAL 10000000
+#define TPM_HARVEST_INTERVAL 10
 
 MALLOC_DECLARE(M_TPM20);
 MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver");
 
 static void tpm20_discard_buffer(void *arg);
 #ifdef TPM_HARVEST
-static void tpm20_harvest(void *arg);
+static void tpm20_harvest(void *arg, int unused);
 #endif
 static int  tpm20_save_state(device_t dev, bool suspend);
 
 static d_open_t		tpm20_open;
 static d_close_t	tpm20_close;
 static d_read_t		tpm20_read;
 static d_write_t	tpm20_write;
 static d_ioctl_t	tpm20_ioctl;
 
 static struct cdevsw tpm20_cdevsw = {
 	.d_version = D_VERSION,
 	.d_open = tpm20_open,
 	.d_close = tpm20_close,
 	.d_read = tpm20_read,
 	.d_write = tpm20_write,
 	.d_ioctl = tpm20_ioctl,
 	.d_name = "tpm20",
 };
 
 int
 tpm20_read(struct cdev *dev, struct uio *uio, int flags)
 {
 	struct tpm_sc *sc;
 	size_t bytes_to_transfer;
 	int result = 0;
 
 	sc = (struct tpm_sc *)dev->si_drv1;
 
 	callout_stop(&sc->discard_buffer_callout);
 	sx_xlock(&sc->dev_lock);
 	if (sc->owner_tid != uio->uio_td->td_tid) {
 		sx_xunlock(&sc->dev_lock);
 		return (EPERM);
 	}
 
 	bytes_to_transfer = MIN(sc->pending_data_length, uio->uio_resid);
 	if (bytes_to_transfer > 0) {
 		result = uiomove((caddr_t) sc->buf, bytes_to_transfer, uio);
 		memset(sc->buf, 0, TPM_BUFSIZE);
 		sc->pending_data_length = 0;
 		cv_signal(&sc->buf_cv);
 	} else {
 		result = ETIMEDOUT;
 	}
 
 	sx_xunlock(&sc->dev_lock);
 
 	return (result);
 }
 
 int
 tpm20_write(struct cdev *dev, struct uio *uio, int flags)
 {
 	struct tpm_sc *sc;
 	size_t byte_count;
 	int result = 0;
 
 	sc = (struct tpm_sc *)dev->si_drv1;
 
 	byte_count = uio->uio_resid;
 	if (byte_count < TPM_HEADER_SIZE) {
 		device_printf(sc->dev,
 		    "Requested transfer is too small\n");
 		return (EINVAL);
 	}
 
 	if (byte_count > TPM_BUFSIZE) {
 		device_printf(sc->dev,
 		    "Requested transfer is too large\n");
 		return (E2BIG);
 	}
 
 	sx_xlock(&sc->dev_lock);
 
 	while (sc->pending_data_length != 0)
 		cv_wait(&sc->buf_cv, &sc->dev_lock);
 
 	result = uiomove(sc->buf, byte_count, uio);
 	if (result != 0) {
 		sx_xunlock(&sc->dev_lock);
 		return (result);
 	}
 
 	result = sc->transmit(sc, byte_count);
 
 	if (result == 0) {
 		callout_reset(&sc->discard_buffer_callout,
 		    TPM_READ_TIMEOUT / tick, tpm20_discard_buffer, sc);
 		sc->owner_tid = uio->uio_td->td_tid;
 	}
 
 	sx_xunlock(&sc->dev_lock);
 	return (result);
 }
 
 static void
 tpm20_discard_buffer(void *arg)
 {
 	struct tpm_sc *sc;
 
 	sc = (struct tpm_sc *)arg;
 	if (callout_pending(&sc->discard_buffer_callout))
 		return;
 
 	sx_xlock(&sc->dev_lock);
 
 	memset(sc->buf, 0, TPM_BUFSIZE);
 	sc->pending_data_length = 0;
 
 	cv_signal(&sc->buf_cv);
 	sx_xunlock(&sc->dev_lock);
 
 	device_printf(sc->dev,
 	    "User failed to read buffer in time\n");
 }
 
 int
 tpm20_open(struct cdev *dev, int flag, int mode, struct thread *td)
 {
 
 	return (0);
 }
 
 int
 tpm20_close(struct cdev *dev, int flag, int mode, struct thread *td)
 {
 
 	return (0);
 }
 
 int
 tpm20_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
     int flags, struct thread *td)
 {
 
 	return (ENOTTY);
 }
 
 int
 tpm20_init(struct tpm_sc *sc)
 {
 	struct make_dev_args args;
 	int result;
 
 	sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK);
 	sx_init(&sc->dev_lock, "TPM driver lock");
 	cv_init(&sc->buf_cv, "TPM buffer cv");
 	callout_init(&sc->discard_buffer_callout, 1);
-#ifdef TPM_HARVEST
-	sc->harvest_ticks = TPM_HARVEST_INTERVAL / tick;
-	callout_init(&sc->harvest_callout, 1);
-	callout_reset(&sc->harvest_callout, 0, tpm20_harvest, sc);
-#endif
 	sc->pending_data_length = 0;
 
 	make_dev_args_init(&args);
 	args.mda_devsw = &tpm20_cdevsw;
 	args.mda_uid = UID_ROOT;
 	args.mda_gid = GID_WHEEL;
 	args.mda_mode = TPM_CDEV_PERM_FLAG;
 	args.mda_si_drv1 = sc;
 	result = make_dev_s(&args, &sc->sc_cdev, TPM_CDEV_NAME);
 	if (result != 0)
 		tpm20_release(sc);
 
+#ifdef TPM_HARVEST
+	TIMEOUT_TASK_INIT(taskqueue_thread, &sc->harvest_task, 0,
+	    tpm20_harvest, sc);
+	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 0);
+#endif
+
 	return (result);
 
 }
 
 void
 tpm20_release(struct tpm_sc *sc)
 {
 
 #ifdef TPM_HARVEST
-	callout_drain(&sc->harvest_callout);
+	if (device_is_attached(sc->dev))
+		taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
 #endif
 
 	if (sc->buf != NULL)
 		free(sc->buf, M_TPM20);
 
 	sx_destroy(&sc->dev_lock);
 	cv_destroy(&sc->buf_cv);
 	if (sc->sc_cdev != NULL)
 		destroy_dev(sc->sc_cdev);
 }
 
 int
 tpm20_suspend(device_t dev)
 {
 	return (tpm20_save_state(dev, true));
 }
 
 int
 tpm20_shutdown(device_t dev)
 {
 	return (tpm20_save_state(dev, false));
 }
 
 #ifdef TPM_HARVEST
-
 /*
  * Get TPM_HARVEST_SIZE random bytes and add them
  * into system entropy pool.
  */
 static void
-tpm20_harvest(void *arg)
+tpm20_harvest(void *arg, int unused)
 {
 	struct tpm_sc *sc;
 	unsigned char entropy[TPM_HARVEST_SIZE];
 	uint16_t entropy_size;
 	int result;
 	uint8_t cmd[] = {
 		0x80, 0x01,		/* TPM_ST_NO_SESSIONS tag*/
 		0x00, 0x00, 0x00, 0x0c,	/* cmd length */
 		0x00, 0x00, 0x01, 0x7b,	/* cmd TPM_CC_GetRandom */
 		0x00, TPM_HARVEST_SIZE 	/* number of bytes requested */
 	};
 
 	sc = arg;
 	sx_xlock(&sc->dev_lock);
 	while (sc->pending_data_length != 0)
 		cv_wait(&sc->buf_cv, &sc->dev_lock);
 
 	memcpy(sc->buf, cmd, sizeof(cmd));
 	result = sc->transmit(sc, sizeof(cmd));
 	if (result != 0) {
 		sx_xunlock(&sc->dev_lock);
 		return;
 	}
 
 	/* Ignore response size */
 	sc->pending_data_length = 0;
 
 	/* The number of random bytes we got is placed right after the header */
 	entropy_size = (uint16_t) sc->buf[TPM_HEADER_SIZE + 1];
 	if (entropy_size > 0) {
 		entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE);
 		memcpy(entropy,
 			sc->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
 			entropy_size);
 	}
 
 	sx_xunlock(&sc->dev_lock);
 	if (entropy_size > 0)
 		random_harvest_queue(entropy, entropy_size, RANDOM_PURE_TPM);
 
-	callout_reset(&sc->harvest_callout, sc->harvest_ticks, tpm20_harvest, sc);
+	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
+	    hz * TPM_HARVEST_INTERVAL);
 }
 #endif	/* TPM_HARVEST */
 
 static int
 tpm20_save_state(device_t dev, bool suspend)
 {
 	struct tpm_sc *sc;
 	uint8_t save_cmd[] = {
 		0x80, 0x01,             /* TPM_ST_NO_SESSIONS tag*/
 		0x00, 0x00, 0x00, 0x0C, /* cmd length */
 		0x00, 0x00, 0x01, 0x45, /* cmd TPM_CC_Shutdown */
 		0x00, 0x00              /* TPM_SU_STATE */
 	};
 
 	sc = device_get_softc(dev);
 
 	/*
 	 * Inform the TPM whether we are going to suspend or reboot/shutdown.
 	 */
 	if (suspend)
 		save_cmd[11] = 1; /* TPM_SU_STATE */
 
 	if (sc == NULL || sc->buf == NULL)
 		return (0);
 
 	sx_xlock(&sc->dev_lock);
 
 	memcpy(sc->buf, save_cmd, sizeof(save_cmd));
 	sc->transmit(sc, sizeof(save_cmd));
 
 	sx_xunlock(&sc->dev_lock);
 
 	return (0);
 }
 
 int32_t
 tpm20_get_timeout(uint32_t command)
 {
 	int32_t timeout;
 
 	switch (command) {
 		case TPM_CC_CreatePrimary:
 		case TPM_CC_Create:
 		case TPM_CC_CreateLoaded:
 			timeout = TPM_TIMEOUT_LONG;
 			break;
 		case TPM_CC_SequenceComplete:
 		case TPM_CC_Startup:
 		case TPM_CC_SequenceUpdate:
 		case TPM_CC_GetCapability:
 		case TPM_CC_PCR_Extend:
 		case TPM_CC_EventSequenceComplete:
 		case TPM_CC_HashSequenceStart:
 			timeout = TPM_TIMEOUT_C;
 			break;
 		default:
 			timeout = TPM_TIMEOUT_B;
 			break;
 	}
 	return timeout;
 }
diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h
index bafbd93dc136..fd1ab55a65e3 100644
--- a/sys/dev/tpm/tpm20.h
+++ b/sys/dev/tpm/tpm20.h
@@ -1,190 +1,190 @@
 /*-
  * Copyright (c) 2018 Stormshield.
  * Copyright (c) 2018 Semihalf.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _TPM20_H_
 #define	_TPM20_H_
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/endian.h>
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
 
 #include <sys/bus.h>
 #include <sys/callout.h>
 #include <sys/conf.h>
 #include <sys/module.h>
 #include <sys/rman.h>
 #include <sys/sx.h>
+#include <sys/taskqueue.h>
 #include <sys/uio.h>
 
 #include <machine/bus.h>
 #include <machine/md_var.h>
 #include <machine/resource.h>
 
 #include <contrib/dev/acpica/include/acpi.h>
 #include <contrib/dev/acpica/include/accommon.h>
 #include <dev/acpica/acpivar.h>
 #include "opt_acpi.h"
 
 #include "opt_tpm.h"
 
 #define	BIT(x) (1 << (x))
 
 /* Timeouts in us */
 #define	TPM_TIMEOUT_A			750000
 #define	TPM_TIMEOUT_B			2000000
 #define	TPM_TIMEOUT_C			200000
 #define	TPM_TIMEOUT_D			30000
 
 /*
  * Generating RSA key pair takes ~(10-20s), which is significantly longer than
  * any timeout defined in spec. Because of that we need a new one.
  */
 #define	TPM_TIMEOUT_LONG		40000000
 
 /* List of commands that require TPM_TIMEOUT_LONG time to complete */
 #define	TPM_CC_CreatePrimary		0x00000131
 #define	TPM_CC_Create			0x00000153
 #define	TPM_CC_CreateLoaded		0x00000191
 
 /* List of commands that require only TPM_TIMEOUT_C time to complete */
 #define	TPM_CC_SequenceComplete		0x0000013e
 #define	TPM_CC_Startup			0x00000144
 #define	TPM_CC_SequenceUpdate		0x0000015c
 #define	TPM_CC_GetCapability		0x0000017a
 #define	TPM_CC_PCR_Extend		0x00000182
 #define	TPM_CC_EventSequenceComplete	0x00000185
 #define	TPM_CC_HashSequenceStart	0x00000186
 
 /* Timeout before data in read buffer is discarded */
 #define	TPM_READ_TIMEOUT		500000
 
 #define	TPM_BUFSIZE			0x1000
 
 #define	TPM_HEADER_SIZE			10
 
 #define	TPM_CDEV_NAME			"tpm0"
 #define	TPM_CDEV_PERM_FLAG		0600
 
 #define	TPM2_START_METHOD_ACPI		2
 #define	TPM2_START_METHOD_TIS		6
 #define	TPM2_START_METHOD_CRB		7
 #define	TPM2_START_METHOD_CRB_ACPI	8
 
 struct tpm_sc {
 	device_t	dev;
 
 	struct resource	*mem_res;
 	struct resource	*irq_res;
 	int		mem_rid;
 	int		irq_rid;
 
 	struct cdev	*sc_cdev;
 
 	struct sx 	dev_lock;
 	struct cv	buf_cv;
 
 	void 		*intr_cookie;
 	int 		intr_type;	/* Current event type */
 	bool 		interrupts;
 
 	uint8_t 	*buf;
 	size_t		pending_data_length;
 	lwpid_t		owner_tid;
 
 	struct callout 	discard_buffer_callout;
 #ifdef TPM_HARVEST
-	struct callout 	harvest_callout;
-	int		harvest_ticks;
+	struct timeout_task 	harvest_task;
 #endif
 
 	int		(*transmit)(struct tpm_sc *, size_t);
 };
 
 int tpm20_suspend(device_t dev);
 int tpm20_shutdown(device_t dev);
 int32_t tpm20_get_timeout(uint32_t command);
 int tpm20_init(struct tpm_sc *sc);
 void tpm20_release(struct tpm_sc *sc);
 
 /* Small helper routines for io ops */
 static inline uint8_t
 RD1(struct tpm_sc *sc, bus_size_t off)
 {
 
 	return (bus_read_1(sc->mem_res, off));
 }
 static inline uint32_t
 RD4(struct tpm_sc *sc, bus_size_t off)
 {
 
 	return (bus_read_4(sc->mem_res, off));
 }
 #ifdef __amd64__
 static inline uint64_t
 RD8(struct tpm_sc *sc, bus_size_t off)
 {
 
 	return (bus_read_8(sc->mem_res, off));
 }
 #endif
 static inline void
 WR1(struct tpm_sc *sc, bus_size_t off, uint8_t val)
 {
 
 	bus_write_1(sc->mem_res, off, val);
 }
 static inline void
 WR4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
 {
 
 	bus_write_4(sc->mem_res, off, val);
 }
 static inline void
 AND4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
 {
 
 	WR4(sc, off, RD4(sc, off) & val);
 }
 static inline void
 OR1(struct tpm_sc *sc, bus_size_t off, uint8_t val)
 {
 
 	WR1(sc, off, RD1(sc, off) | val);
 }
 static inline void
 OR4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
 {
 
 	WR4(sc, off, RD4(sc, off) | val);
 }
 #endif	/* _TPM20_H_ */