diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c
index 9ea98075b3..4aade565e2 100644
--- a/drivers/tpm/tpm_tis_sandbox.c
+++ b/drivers/tpm/tpm_tis_sandbox.c
@@ -217,7 +217,7 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
 			rsk.struct_version = 2;
 			rsk.uid = ROLLBACK_SPACE_KERNEL_UID;
 			rsk.kernel_versions = 0;
-			rsk.crc8 = crc8((unsigned char *)&rsk,
+			rsk.crc8 = crc8(0, (unsigned char *)&rsk,
 					offsetof(struct rollback_space_kernel,
 						 crc8));
 			memcpy(data, &rsk, sizeof(rsk));
diff --git a/include/linux/crc8.h b/include/linux/crc8.h
index b5fd2ac9d6..f7c300a9b1 100644
--- a/include/linux/crc8.h
+++ b/include/linux/crc8.h
@@ -14,10 +14,11 @@
  * This uses an x^8 + x^2 + x + 1 polynomial.  A table-based algorithm would
  * be faster, but for only a few bytes it isn't worth the code size
  *
+ * @crc_start: CRC8 start value
  * @vptr: Buffer to checksum
  * @len: Length of buffer in bytes
  * @return CRC8 checksum
  */
-unsigned int crc8(const unsigned char *vptr, int len);
+unsigned int crc8(unsigned int crc_start, const unsigned char *vptr, int len);
 
 #endif
diff --git a/lib/crc8.c b/lib/crc8.c
index 8b68a29e40..51d540fbcb 100644
--- a/lib/crc8.c
+++ b/lib/crc8.c
@@ -6,20 +6,27 @@
 
 #include "linux/crc8.h"
 
-unsigned int crc8(const unsigned char *vptr, int len)
-{
-	const unsigned char *data = vptr;
-	unsigned int crc = 0;
-	int i, j;
+#define POLY	(0x1070U << 3)
 
-	for (j = len; j; j--, data++) {
-		crc ^= (*data << 8);
-		for (i = 8; i; i--) {
-			if (crc & 0x8000)
-				crc ^= (0x1070 << 3);
-			crc <<= 1;
-		}
+static unsigned char _crc8(unsigned short data)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		if (data & 0x8000)
+			data = data ^ POLY;
+		data = data << 1;
 	}
 
-	return (crc >> 8) & 0xff;
+	return (unsigned char)(data >> 8);
+}
+
+unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		crc = _crc8((crc ^ vptr[i]) << 8);
+
+	return crc;
 }