crypto/fsl: Fix HW accelerated hash commands

The hash command function were not flushing the dcache before passing data
to CAAM/DMA and not invalidating the dcache when getting data back.

Due the data cache incoherency, HW accelerated hash commands used to fail
with CAAM errors like "Invalid KEY Command".

Check if pbuf and pout buffers are properly aligned to the cache line size
and flush/invalidate the memory regions to address this issue.

This solution is based in a previous work from Clemens Gruber in
commit 598e9dccc75d ("crypto/fsl: fix BLOB encapsulation and
decapsulation")

Reported-by: Anatolij Gustschin <agust@denx.de>
Signed-off-by: Breno Lima <breno.lima@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index a63eba3..9373a39 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <memalign.h>
 #include "jobdesc.h"
 #include "desc.h"
 #include "jr.h"
@@ -163,20 +164,37 @@
 {
 	int ret = 0;
 	uint32_t *desc;
+	unsigned int size;
 
-	desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
+	desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
 	if (!desc) {
 		debug("Not enough memory for descriptor allocation\n");
 		return -ENOMEM;
 	}
 
+	if (!IS_ALIGNED((uintptr_t)pbuf, ARCH_DMA_MINALIGN) ||
+	    !IS_ALIGNED((uintptr_t)pout, ARCH_DMA_MINALIGN)) {
+		puts("Error: Address arguments are not aligned\n");
+		return -EINVAL;
+	}
+
+	size = ALIGN(buf_len, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size);
+
 	inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout,
 				  driver_hash[algo].alg_type,
 				  driver_hash[algo].digestsize,
 				  0);
 
+	size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)desc, (unsigned long)desc + size);
+
 	ret = run_descriptor_jr(desc);
 
+	size = ALIGN(driver_hash[algo].digestsize, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)pout,
+				(unsigned long)pout + size);
+
 	free(desc);
 	return ret;
 }