xref: /optee_os/core/drivers/imx/dcp/dcp.c (revision 04e46975d8f02e25209af552aaea4acb4d70c7f9)
193e678edSClement Faure // SPDX-License-Identifier: BSD-2-Clause
293e678edSClement Faure /*
393e678edSClement Faure  * Copyright 2020 NXP
493e678edSClement Faure  */
593e678edSClement Faure 
693e678edSClement Faure #include <config.h>
793e678edSClement Faure #include <dcp_utils.h>
893e678edSClement Faure #include <drivers/imx/dcp.h>
993e678edSClement Faure #include <imx-regs.h>
1093e678edSClement Faure #include <io.h>
1193e678edSClement Faure #include <kernel/boot.h>
1293e678edSClement Faure #include <kernel/dt.h>
1393e678edSClement Faure #include <kernel/mutex.h>
1493e678edSClement Faure #include <kernel/spinlock.h>
1593e678edSClement Faure #include <libfdt.h>
1693e678edSClement Faure #include <local.h>
1793e678edSClement Faure #include <mm/core_memprot.h>
1893e678edSClement Faure #include <tee/cache.h>
1993e678edSClement Faure #include <utee_defines.h>
2093e678edSClement Faure 
2193e678edSClement Faure static const uint8_t sha1_null_msg[] = {
2293e678edSClement Faure 	0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
2393e678edSClement Faure 	0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09,
2493e678edSClement Faure };
2593e678edSClement Faure 
2693e678edSClement Faure static const uint8_t sha256_null_msg[] = {
2793e678edSClement Faure 	0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4,
2893e678edSClement Faure 	0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
2993e678edSClement Faure 	0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
3093e678edSClement Faure };
3193e678edSClement Faure 
3293e678edSClement Faure static vaddr_t dcp_base;
3393e678edSClement Faure static bool driver_initialized;
3493e678edSClement Faure static unsigned int clk_refcount;
3593e678edSClement Faure static unsigned int key_store_spinlock = SPINLOCK_UNLOCK;
3693e678edSClement Faure static unsigned int clock_spinlock = SPINLOCK_UNLOCK;
3793e678edSClement Faure static struct dcp_align_buf hw_context_buffer;
3893e678edSClement Faure 
3993e678edSClement Faure static struct mutex lock_channel[DCP_NB_CHANNELS] = {
4093e678edSClement Faure 	[DCP_CHANN0] = MUTEX_INITIALIZER,
4193e678edSClement Faure 	[DCP_CHANN1] = MUTEX_INITIALIZER,
4293e678edSClement Faure 	[DCP_CHANN2] = MUTEX_INITIALIZER,
4393e678edSClement Faure 	[DCP_CHANN3] = MUTEX_INITIALIZER,
4493e678edSClement Faure };
4593e678edSClement Faure 
4693e678edSClement Faure static const struct dcp_hashalg hash_alg[2] = {
4793e678edSClement Faure 	[DCP_SHA1] = {
4893e678edSClement Faure 		.type = DCP_CONTROL1_HASH_SELECT_SHA1,
4993e678edSClement Faure 		.size = TEE_SHA1_HASH_SIZE,
5093e678edSClement Faure 	},
5193e678edSClement Faure 	[DCP_SHA256] = {
5293e678edSClement Faure 		.type = DCP_CONTROL1_HASH_SELECT_SHA256,
5393e678edSClement Faure 		.size = TEE_SHA256_HASH_SIZE,
5493e678edSClement Faure 	},
5593e678edSClement Faure };
5693e678edSClement Faure 
5793e678edSClement Faure /*
5893e678edSClement Faure  * Enable/disable DCP clock.
5993e678edSClement Faure  *
6093e678edSClement Faure  * @enable   Enable the clock if true, disable if false.
6193e678edSClement Faure  */
dcp_clk_enable(bool enable)6293e678edSClement Faure static void dcp_clk_enable(bool enable)
6393e678edSClement Faure {
64c2e4eb43SAnton Rybakov 	vaddr_t ccm_base = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC,
65c2e4eb43SAnton Rybakov 					   CCM_CCGR0 + sizeof(uint32_t));
6693e678edSClement Faure 	uint32_t clock_except = cpu_spin_lock_xsave(&clock_spinlock);
6793e678edSClement Faure 
6893e678edSClement Faure 	if (enable) {
6993e678edSClement Faure 		if (clk_refcount > 0) {
7093e678edSClement Faure 			clk_refcount++;
7193e678edSClement Faure 			goto out;
7293e678edSClement Faure 		} else {
7393e678edSClement Faure 			clk_refcount++;
7493e678edSClement Faure 			io_setbits32(ccm_base + CCM_CCGR0, DCP_CLK_ENABLE_MASK);
7593e678edSClement Faure 		}
7693e678edSClement Faure 	} else {
7793e678edSClement Faure 		assert(clk_refcount != 0);
7893e678edSClement Faure 
7993e678edSClement Faure 		clk_refcount--;
8093e678edSClement Faure 		if (clk_refcount > 0)
8193e678edSClement Faure 			goto out;
8293e678edSClement Faure 		else
8393e678edSClement Faure 			io_clrbits32(ccm_base + CCM_CCGR0, DCP_CLK_ENABLE_MASK);
8493e678edSClement Faure 	}
8593e678edSClement Faure out:
8693e678edSClement Faure 	cpu_spin_unlock_xrestore(&clock_spinlock, clock_except);
8793e678edSClement Faure }
8893e678edSClement Faure 
8993e678edSClement Faure /*
9093e678edSClement Faure  * Lock the given channel with a mutex.
9193e678edSClement Faure  *
9293e678edSClement Faure  * @chan   DCP channel to lock
9393e678edSClement Faure  */
dcp_lock_known_channel(enum dcp_channel chan)9493e678edSClement Faure static TEE_Result dcp_lock_known_channel(enum dcp_channel chan)
9593e678edSClement Faure {
9693e678edSClement Faure 	if (mutex_trylock(&lock_channel[chan]))
9793e678edSClement Faure 		return TEE_SUCCESS;
9893e678edSClement Faure 	else
9993e678edSClement Faure 		return TEE_ERROR_BUSY;
10093e678edSClement Faure }
10193e678edSClement Faure 
10293e678edSClement Faure /*
10393e678edSClement Faure  * Lock a DCP channel
10493e678edSClement Faure  *
10593e678edSClement Faure  * @channel    Pointer on operation channel parameter
10693e678edSClement Faure  */
dcp_lock_channel(enum dcp_channel * channel)10793e678edSClement Faure static TEE_Result dcp_lock_channel(enum dcp_channel *channel)
10893e678edSClement Faure {
10993e678edSClement Faure 	TEE_Result ret = TEE_ERROR_BUSY;
11093e678edSClement Faure 	enum dcp_channel chan = DCP_CHANN0;
11193e678edSClement Faure 
11293e678edSClement Faure 	for (chan = DCP_CHANN0; chan < DCP_NB_CHANNELS; chan++) {
11393e678edSClement Faure 		ret = dcp_lock_known_channel(chan);
11493e678edSClement Faure 		if (ret == TEE_SUCCESS) {
11593e678edSClement Faure 			*channel = chan;
11693e678edSClement Faure 			return ret;
11793e678edSClement Faure 		}
11893e678edSClement Faure 	}
11993e678edSClement Faure 
12093e678edSClement Faure 	EMSG("All channels are busy");
12193e678edSClement Faure 
12293e678edSClement Faure 	return ret;
12393e678edSClement Faure }
12493e678edSClement Faure 
12593e678edSClement Faure /*
12693e678edSClement Faure  * Unlock the given channel.
12793e678edSClement Faure  *
12893e678edSClement Faure  * @chan   DCP channel to unlock
12993e678edSClement Faure  */
dcp_unlock_channel(enum dcp_channel chan)13093e678edSClement Faure static void dcp_unlock_channel(enum dcp_channel chan)
13193e678edSClement Faure {
13293e678edSClement Faure 	mutex_unlock(&lock_channel[chan]);
13393e678edSClement Faure }
13493e678edSClement Faure 
13593e678edSClement Faure /*
13693e678edSClement Faure  * Start the DCP operation.
13793e678edSClement Faure  *
13893e678edSClement Faure  * @dcp_data   Structure containing dcp_descriptor configuration and channel to
13993e678edSClement Faure  *	       use.
14093e678edSClement Faure  */
dcp_run(struct dcp_data * dcp_data)14193e678edSClement Faure static TEE_Result dcp_run(struct dcp_data *dcp_data)
14293e678edSClement Faure {
14393e678edSClement Faure 	TEE_Result ret = TEE_SUCCESS;
14493e678edSClement Faure 	unsigned int timeout = 0;
14593e678edSClement Faure 	uint32_t val = 0;
14693e678edSClement Faure 
14793e678edSClement Faure 	dcp_data->desc.next = 0;
14893e678edSClement Faure 	cache_operation(TEE_CACHEFLUSH, &dcp_data->desc,
14993e678edSClement Faure 			sizeof(dcp_data->desc));
15093e678edSClement Faure 
15193e678edSClement Faure 	/* Enable clock if it's not done */
15293e678edSClement Faure 	dcp_clk_enable(true);
15393e678edSClement Faure 
15493e678edSClement Faure 	/* Clear DCP_STAT IRQ field for the channel used by the operation */
15593e678edSClement Faure 	io_clrbits32(dcp_base + DCP_STAT, BIT32(dcp_data->channel));
15693e678edSClement Faure 
15793e678edSClement Faure 	/* Clear CH_N_STAT to clear IRQ and error codes */
15893e678edSClement Faure 	io_write32(dcp_base + DCP_CH_N_STAT(dcp_data->channel), 0x0);
15993e678edSClement Faure 
16093e678edSClement Faure 	/* Update descriptor structure to be processed for the channel */
16193e678edSClement Faure 	io_write32(dcp_base + DCP_CH_N_CMDPTR(dcp_data->channel),
16293e678edSClement Faure 		   virt_to_phys(&dcp_data->desc));
16393e678edSClement Faure 
16493e678edSClement Faure 	/* Increment the semaphore to start the transfer */
16593e678edSClement Faure 	io_write32(dcp_base + DCP_CH_N_SEMA(dcp_data->channel), 0x1);
16693e678edSClement Faure 
16793e678edSClement Faure 	for (timeout = 0; timeout < DCP_MAX_TIMEOUT; timeout++) {
16893e678edSClement Faure 		dcp_udelay(10);
16993e678edSClement Faure 		val = io_read32(dcp_base + DCP_STAT);
17093e678edSClement Faure 		if (val & BIT(dcp_data->channel))
17193e678edSClement Faure 			break;
17293e678edSClement Faure 	}
17393e678edSClement Faure 
17493e678edSClement Faure 	if (timeout == DCP_MAX_TIMEOUT) {
17593e678edSClement Faure 		EMSG("Timeout elapsed before operation");
17693e678edSClement Faure 		ret = TEE_ERROR_GENERIC;
17793e678edSClement Faure 		goto out;
17893e678edSClement Faure 	}
17993e678edSClement Faure 
18093e678edSClement Faure 	val = io_read32(dcp_base + DCP_CH_N_STAT(dcp_data->channel));
18193e678edSClement Faure 	if (val & DCP_CH_STAT_ERROR_MASK) {
18293e678edSClement Faure 		EMSG("Error operation, 0x%" PRIx32, val);
18393e678edSClement Faure 		ret = TEE_ERROR_GENERIC;
18493e678edSClement Faure 	}
18593e678edSClement Faure 
18693e678edSClement Faure out:
18793e678edSClement Faure 	dcp_clk_enable(false);
18893e678edSClement Faure 
18993e678edSClement Faure 	return ret;
19093e678edSClement Faure }
19193e678edSClement Faure 
dcp_cmac_subkey_generation(struct dcp_cipher_init * init,uint8_t * k1,uint8_t * k2)19293e678edSClement Faure static TEE_Result dcp_cmac_subkey_generation(struct dcp_cipher_init *init,
19393e678edSClement Faure 					     uint8_t *k1, uint8_t *k2)
19493e678edSClement Faure {
19593e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
19693e678edSClement Faure 	struct dcp_cipher_data data = { };
19793e678edSClement Faure 	uint8_t l[16] = { };
19893e678edSClement Faure 	uint8_t tmp[16] = { };
19993e678edSClement Faure 	uint8_t const_zero[16] = { };
20093e678edSClement Faure 	uint8_t const_rb[16] = { [15] = 0x87 };
20193e678edSClement Faure 
20293e678edSClement Faure 	ret = dcp_cipher_do_init(&data, init);
20393e678edSClement Faure 	if (ret != TEE_SUCCESS)
20493e678edSClement Faure 		return ret;
20593e678edSClement Faure 
20693e678edSClement Faure 	ret = dcp_cipher_do_update(&data, const_zero, l, sizeof(l));
20793e678edSClement Faure 	if (ret != TEE_SUCCESS)
20893e678edSClement Faure 		goto out;
20993e678edSClement Faure 
21093e678edSClement Faure 	if ((l[0] & BIT(7)) == 0) {
21193e678edSClement Faure 		dcp_left_shift_buffer(l, k1, 16);
21293e678edSClement Faure 	} else {
21393e678edSClement Faure 		dcp_left_shift_buffer(l, tmp, 16);
21493e678edSClement Faure 		dcp_xor(tmp, const_rb, k1, 16);
21593e678edSClement Faure 	}
21693e678edSClement Faure 
21793e678edSClement Faure 	if ((k1[0] & BIT(7)) == 0) {
21893e678edSClement Faure 		dcp_left_shift_buffer(k1, k2, 16);
21993e678edSClement Faure 	} else {
22093e678edSClement Faure 		dcp_left_shift_buffer(k1, tmp, 16);
22193e678edSClement Faure 		dcp_xor(tmp, const_rb, k2, 16);
22293e678edSClement Faure 	}
22393e678edSClement Faure 
22493e678edSClement Faure 	ret = TEE_SUCCESS;
22593e678edSClement Faure out:
22693e678edSClement Faure 	dcp_cipher_do_final(&data);
22793e678edSClement Faure 
22893e678edSClement Faure 	return ret;
22993e678edSClement Faure }
23093e678edSClement Faure 
dcp_store_key(uint32_t * key,unsigned int index)23193e678edSClement Faure TEE_Result dcp_store_key(uint32_t *key, unsigned int index)
23293e678edSClement Faure {
23393e678edSClement Faure 	uint32_t val = 0;
23493e678edSClement Faure 	unsigned int i = 0;
23593e678edSClement Faure 	uint32_t key_store_except = 0;
23693e678edSClement Faure 
23793e678edSClement Faure 	if (!key)
23893e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
23993e678edSClement Faure 
24093e678edSClement Faure 	if (index > DCP_SRAM_KEY_NB_SUBWORD - 1) {
24193e678edSClement Faure 		EMSG("Bad parameters, index must be < %u",
24293e678edSClement Faure 		     DCP_SRAM_KEY_NB_SUBWORD);
24393e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
24493e678edSClement Faure 	}
24593e678edSClement Faure 
24693e678edSClement Faure 	key_store_except = cpu_spin_lock_xsave(&key_store_spinlock);
24793e678edSClement Faure 
24893e678edSClement Faure 	dcp_clk_enable(true);
24993e678edSClement Faure 
25093e678edSClement Faure 	val = DCP_SRAM_KEY_INDEX(index);
25193e678edSClement Faure 	io_write32(dcp_base + DCP_KEY, val);
25293e678edSClement Faure 
25393e678edSClement Faure 	/*
25493e678edSClement Faure 	 * Key is stored as four uint32 values, starting with subword0
25593e678edSClement Faure 	 * (least-significant word)
25693e678edSClement Faure 	 */
25793e678edSClement Faure 	for (i = 0; i < DCP_SRAM_KEY_NB_SUBWORD; i++) {
25893e678edSClement Faure 		val = TEE_U32_TO_BIG_ENDIAN(key[i]);
25993e678edSClement Faure 		io_write32(dcp_base + DCP_KEYDATA, val);
26093e678edSClement Faure 	}
26193e678edSClement Faure 
26293e678edSClement Faure 	dcp_clk_enable(false);
26393e678edSClement Faure 
26493e678edSClement Faure 	cpu_spin_unlock_xrestore(&key_store_spinlock, key_store_except);
26593e678edSClement Faure 
26693e678edSClement Faure 	return TEE_SUCCESS;
26793e678edSClement Faure }
26893e678edSClement Faure 
dcp_cmac(struct dcp_cipher_init * init,uint8_t * input,size_t input_size,uint8_t * output)26993e678edSClement Faure TEE_Result dcp_cmac(struct dcp_cipher_init *init, uint8_t *input,
27093e678edSClement Faure 		    size_t input_size, uint8_t *output)
27193e678edSClement Faure {
27293e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
27393e678edSClement Faure 	uint8_t key1[DCP_AES128_KEY_SIZE] = { };
27493e678edSClement Faure 	uint8_t key2[DCP_AES128_KEY_SIZE] = { };
27593e678edSClement Faure 	unsigned int nb_blocks = 0;
27693e678edSClement Faure 	bool block_complete = false;
27793e678edSClement Faure 	struct dcp_cipher_data data = { };
27893e678edSClement Faure 	uint8_t y[DCP_AES128_BLOCK_SIZE] = { };
27993e678edSClement Faure 	uint8_t x[DCP_AES128_BLOCK_SIZE] = { };
28093e678edSClement Faure 	uint8_t last[DCP_AES128_BLOCK_SIZE] = { };
28193e678edSClement Faure 	unsigned int i = 0;
28293e678edSClement Faure 	uint8_t offset = 0;
28393e678edSClement Faure 
28493e678edSClement Faure 	if (!output || !init)
28593e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
28693e678edSClement Faure 
28793e678edSClement Faure 	if (!input && input_size)
28893e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
28993e678edSClement Faure 
29093e678edSClement Faure 	ret = dcp_cipher_do_init(&data, init);
29193e678edSClement Faure 	if (ret != TEE_SUCCESS) {
29293e678edSClement Faure 		ret = TEE_ERROR_OUT_OF_MEMORY;
29393e678edSClement Faure 		goto out;
29493e678edSClement Faure 	}
29593e678edSClement Faure 
29693e678edSClement Faure 	/* Generate CMAC subkeys */
29793e678edSClement Faure 	ret = dcp_cmac_subkey_generation(init, key1, key2);
29893e678edSClement Faure 	if (ret != TEE_SUCCESS)
29993e678edSClement Faure 		goto out;
30093e678edSClement Faure 
30193e678edSClement Faure 	/* Get number of block */
302*04e46975SEtienne Carriere 	nb_blocks = ROUNDUP_DIV(input_size, DCP_AES128_BLOCK_SIZE);
30393e678edSClement Faure 
30493e678edSClement Faure 	block_complete = nb_blocks && !(input_size % DCP_AES128_BLOCK_SIZE);
30593e678edSClement Faure 	if (nb_blocks == 0)
30693e678edSClement Faure 		nb_blocks = 1;
30793e678edSClement Faure 
30893e678edSClement Faure 	for (i = 0; i < nb_blocks - 1; i++) {
30993e678edSClement Faure 		dcp_xor(x, input + offset, y, DCP_AES128_BLOCK_SIZE);
31093e678edSClement Faure 		ret = dcp_cipher_do_update(&data, y, x,
31193e678edSClement Faure 					   DCP_AES128_BLOCK_SIZE);
31293e678edSClement Faure 		if (ret)
31393e678edSClement Faure 			goto out;
31493e678edSClement Faure 		offset += DCP_AES128_BLOCK_SIZE;
31593e678edSClement Faure 	}
31693e678edSClement Faure 
31793e678edSClement Faure 	/* Process the last block */
31893e678edSClement Faure 	memcpy(last, input + offset, input_size - offset);
31993e678edSClement Faure 
32093e678edSClement Faure 	if (block_complete) {
32193e678edSClement Faure 		dcp_xor(last, key1, last, DCP_AES128_BLOCK_SIZE);
32293e678edSClement Faure 	} else {
32393e678edSClement Faure 		dcp_cmac_padding(last, input_size % DCP_AES128_BLOCK_SIZE);
32493e678edSClement Faure 		dcp_xor(last, key2, last, DCP_AES128_BLOCK_SIZE);
32593e678edSClement Faure 	}
32693e678edSClement Faure 
32793e678edSClement Faure 	dcp_xor(x, last, y, DCP_AES128_BLOCK_SIZE);
32893e678edSClement Faure 	ret = dcp_cipher_do_update(&data, y, x,
32993e678edSClement Faure 				   DCP_AES128_BLOCK_SIZE);
33093e678edSClement Faure 	if (ret)
33193e678edSClement Faure 		goto out;
33293e678edSClement Faure 
33393e678edSClement Faure 	memcpy(output, x, DCP_AES128_BLOCK_SIZE);
33493e678edSClement Faure 
33593e678edSClement Faure out:
33693e678edSClement Faure 	dcp_cipher_do_final(&data);
33793e678edSClement Faure 
33893e678edSClement Faure 	return ret;
33993e678edSClement Faure }
34093e678edSClement Faure 
dcp_cipher_do_init(struct dcp_cipher_data * data,struct dcp_cipher_init * init)34193e678edSClement Faure TEE_Result dcp_cipher_do_init(struct dcp_cipher_data *data,
34293e678edSClement Faure 			      struct dcp_cipher_init *init)
34393e678edSClement Faure {
34493e678edSClement Faure 	struct dcp_descriptor *desc = NULL;
34593e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
34693e678edSClement Faure 
34793e678edSClement Faure 	if (!init || !data)
34893e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
34993e678edSClement Faure 
35093e678edSClement Faure 	ret = dcp_lock_channel(&data->dcp_data.channel);
35193e678edSClement Faure 	if (ret != TEE_SUCCESS)
35293e678edSClement Faure 		return ret;
35393e678edSClement Faure 
35493e678edSClement Faure 	desc = &data->dcp_data.desc;
35593e678edSClement Faure 
35693e678edSClement Faure 	desc->ctrl0 = DCP_CONTROL0_DECR_SEMAPHORE | DCP_CONTROL0_ENABLE_CIPHER |
35793e678edSClement Faure 		      DCP_CONTROL0_INTERRUPT_ENABLE;
35893e678edSClement Faure 	desc->ctrl1 = DCP_CONTROL1_CIPHER_SELECT_AES128;
35993e678edSClement Faure 
36093e678edSClement Faure 	if (init->op == DCP_ENCRYPT)
36193e678edSClement Faure 		desc->ctrl0 |= DCP_CONTROL0_CIPHER_ENCRYPT;
36293e678edSClement Faure 
36393e678edSClement Faure 	if (init->key_mode == DCP_OTP) {
364ebc90499SClement Faure 		desc->ctrl0 &= ~DCP_CONTROL0_OTP_KEY;
36593e678edSClement Faure 		desc->ctrl1 |= DCP_CONTROL1_KEY_SELECT_OTP_CRYPTO;
36693e678edSClement Faure 	} else if (init->key_mode == DCP_PAYLOAD) {
36793e678edSClement Faure 		desc->ctrl0 |= DCP_CONTROL0_PAYLOAD_KEY;
36893e678edSClement Faure 		if (!init->key)
36993e678edSClement Faure 			return TEE_ERROR_BAD_PARAMETERS;
37093e678edSClement Faure 		memcpy(data->key, init->key, DCP_AES128_KEY_SIZE);
37193e678edSClement Faure 	} else {
37293e678edSClement Faure 		desc->ctrl1 |= SHIFT_U32(init->key_mode, 8);
37393e678edSClement Faure 	}
37493e678edSClement Faure 
37593e678edSClement Faure 	if (init->mode == DCP_CBC) {
37693e678edSClement Faure 		desc->ctrl0 |= DCP_CONTROL0_CIPHER_INIT;
37793e678edSClement Faure 		desc->ctrl1 |= DCP_CONTROL1_CIPHER_MODE_CBC;
37893e678edSClement Faure 		if (!init->iv)
37993e678edSClement Faure 			return TEE_ERROR_BAD_PARAMETERS;
38093e678edSClement Faure 		memcpy(data->iv, init->iv, DCP_AES128_IV_SIZE);
38193e678edSClement Faure 	}
38293e678edSClement Faure 
38393e678edSClement Faure 	/* Allocate aligned buffer for dcp iv and key */
38493e678edSClement Faure 	ret = dcp_calloc_align_buf(&data->payload,
38593e678edSClement Faure 				   DCP_AES128_IV_SIZE + DCP_AES128_KEY_SIZE);
38693e678edSClement Faure 	if (ret != TEE_SUCCESS)
38793e678edSClement Faure 		return ret;
38893e678edSClement Faure 
38993e678edSClement Faure 	desc->src_buffer = 0;
39093e678edSClement Faure 	desc->dest_buffer = 0;
39193e678edSClement Faure 	desc->status = 0;
39293e678edSClement Faure 	desc->buff_size = 0;
39393e678edSClement Faure 	desc->next = virt_to_phys(desc);
39493e678edSClement Faure 
39593e678edSClement Faure 	data->initialized = true;
39693e678edSClement Faure 
39793e678edSClement Faure 	return ret;
39893e678edSClement Faure }
39993e678edSClement Faure 
dcp_cipher_do_update(struct dcp_cipher_data * data,const uint8_t * src,uint8_t * dst,size_t size)40093e678edSClement Faure TEE_Result dcp_cipher_do_update(struct dcp_cipher_data *data,
40193e678edSClement Faure 				const uint8_t *src, uint8_t *dst, size_t size)
40293e678edSClement Faure {
40393e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
40493e678edSClement Faure 	struct dcp_align_buf output = { };
40593e678edSClement Faure 	struct dcp_align_buf input = { };
40693e678edSClement Faure 	struct dcp_descriptor *desc = NULL;
40793e678edSClement Faure 
40893e678edSClement Faure 	if (!data || !src || !dst)
40993e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
41093e678edSClement Faure 
41193e678edSClement Faure 	if (!data->initialized) {
41293e678edSClement Faure 		EMSG("Error, please call dcp_aes_do_init() before");
41393e678edSClement Faure 		return TEE_ERROR_BAD_STATE;
41493e678edSClement Faure 	}
41593e678edSClement Faure 
41693e678edSClement Faure 	if (size % DCP_AES128_BLOCK_SIZE) {
41793e678edSClement Faure 		EMSG("Input size has to be a multiple of %zu bytes",
41893e678edSClement Faure 		     DCP_AES128_BLOCK_SIZE);
41993e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
42093e678edSClement Faure 	}
42193e678edSClement Faure 
42293e678edSClement Faure 	ret = dcp_calloc_align_buf(&output, size);
42393e678edSClement Faure 	if (ret != TEE_SUCCESS)
42493e678edSClement Faure 		goto out;
42593e678edSClement Faure 
42693e678edSClement Faure 	ret = dcp_calloc_align_buf(&input, size);
42793e678edSClement Faure 	if (ret != TEE_SUCCESS)
42893e678edSClement Faure 		goto out;
42993e678edSClement Faure 
43093e678edSClement Faure 	desc = &data->dcp_data.desc;
43193e678edSClement Faure 
43293e678edSClement Faure 	/* Copy input data */
43393e678edSClement Faure 	memcpy(input.data, src, size);
43493e678edSClement Faure 
43593e678edSClement Faure 	/* Copy key and IV */
43693e678edSClement Faure 	memcpy(data->payload.data, data->key, DCP_AES128_KEY_SIZE);
43793e678edSClement Faure 	data->payload_size = DCP_AES128_KEY_SIZE;
43893e678edSClement Faure 	if (desc->ctrl0 & DCP_CONTROL0_CIPHER_INIT) {
43993e678edSClement Faure 		memcpy(data->payload.data + DCP_AES128_KEY_SIZE, data->iv,
44093e678edSClement Faure 		       DCP_AES128_IV_SIZE);
44193e678edSClement Faure 		data->payload_size += DCP_AES128_IV_SIZE;
44293e678edSClement Faure 	}
44393e678edSClement Faure 
44493e678edSClement Faure 	desc->src_buffer = input.paddr;
44593e678edSClement Faure 	desc->dest_buffer = output.paddr;
44693e678edSClement Faure 	desc->payload = data->payload.paddr;
44793e678edSClement Faure 	desc->buff_size = size;
44893e678edSClement Faure 
44993e678edSClement Faure 	cache_operation(TEE_CACHECLEAN, data->payload.data,
45093e678edSClement Faure 			data->payload_size);
45193e678edSClement Faure 	cache_operation(TEE_CACHECLEAN, input.data, size);
45293e678edSClement Faure 	cache_operation(TEE_CACHEINVALIDATE, output.data, size);
45393e678edSClement Faure 
45493e678edSClement Faure 	ret = dcp_run(&data->dcp_data);
45593e678edSClement Faure 	if (ret)
45693e678edSClement Faure 		goto out;
45793e678edSClement Faure 
45893e678edSClement Faure 	cache_operation(TEE_CACHEINVALIDATE, output.data, size);
45993e678edSClement Faure 
46093e678edSClement Faure 	desc->ctrl0 &= ~DCP_CONTROL0_CIPHER_INIT;
46193e678edSClement Faure 
46293e678edSClement Faure 	memcpy(dst, output.data, size);
46393e678edSClement Faure out:
46493e678edSClement Faure 	dcp_free(&output);
46593e678edSClement Faure 	dcp_free(&input);
46693e678edSClement Faure 
46793e678edSClement Faure 	return ret;
46893e678edSClement Faure }
46993e678edSClement Faure 
dcp_cipher_do_final(struct dcp_cipher_data * data)47093e678edSClement Faure void dcp_cipher_do_final(struct dcp_cipher_data *data)
47193e678edSClement Faure {
47293e678edSClement Faure 	if (data)
47393e678edSClement Faure 		data->initialized = false;
47493e678edSClement Faure 
47593e678edSClement Faure 	dcp_free(&data->payload);
47693e678edSClement Faure 	dcp_unlock_channel(data->dcp_data.channel);
47793e678edSClement Faure }
47893e678edSClement Faure 
dcp_sha_do_init(struct dcp_hash_data * hashdata)47993e678edSClement Faure TEE_Result dcp_sha_do_init(struct dcp_hash_data *hashdata)
48093e678edSClement Faure {
48193e678edSClement Faure 	struct dcp_descriptor *desc = NULL;
48293e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
48393e678edSClement Faure 
48493e678edSClement Faure 	if (!hashdata) {
48593e678edSClement Faure 		EMSG("Bad parameters, hashdata is NULL");
48693e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
48793e678edSClement Faure 	}
48893e678edSClement Faure 
48993e678edSClement Faure 	desc = &hashdata->dcp_data.desc;
49093e678edSClement Faure 
49193e678edSClement Faure 	/* DCP descriptor init */
49293e678edSClement Faure 	desc->status = 0;
49393e678edSClement Faure 	desc->payload = 0;
49493e678edSClement Faure 	desc->dest_buffer = 0;
49593e678edSClement Faure 	desc->ctrl0 = DCP_CONTROL0_ENABLE_HASH | DCP_CONTROL0_INTERRUPT_ENABLE |
49693e678edSClement Faure 		      DCP_CONTROL0_DECR_SEMAPHORE | DCP_CONTROL0_HASH_INIT;
49793e678edSClement Faure 	desc->ctrl1 = hash_alg[hashdata->alg].type;
49893e678edSClement Faure 	desc->buff_size = 0;
49993e678edSClement Faure 	desc->next = 0;
50093e678edSClement Faure 	desc->src_buffer = 0;
50193e678edSClement Faure 
50293e678edSClement Faure 	ret = dcp_lock_channel(&hashdata->dcp_data.channel);
50393e678edSClement Faure 	if (ret != TEE_SUCCESS) {
50493e678edSClement Faure 		EMSG("Channel is busy, can't start operation now");
50593e678edSClement Faure 		return ret;
50693e678edSClement Faure 	}
50793e678edSClement Faure 
50893e678edSClement Faure 	/* Allocate context data */
50993e678edSClement Faure 	ret = dcp_calloc_align_buf(&hashdata->ctx, DCP_SHA_BLOCK_SIZE);
51093e678edSClement Faure 	if (ret != TEE_SUCCESS)
51193e678edSClement Faure 		return ret;
51293e678edSClement Faure 
51393e678edSClement Faure 	hashdata->initialized = true;
51493e678edSClement Faure 	hashdata->ctx_size = 0;
51593e678edSClement Faure 
51693e678edSClement Faure 	return ret;
51793e678edSClement Faure }
51893e678edSClement Faure 
dcp_sha_do_update(struct dcp_hash_data * hashdata,const uint8_t * data,size_t len)51993e678edSClement Faure TEE_Result dcp_sha_do_update(struct dcp_hash_data *hashdata,
52093e678edSClement Faure 			     const uint8_t *data, size_t len)
52193e678edSClement Faure {
52293e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
52393e678edSClement Faure 	struct dcp_descriptor *desc = NULL;
52493e678edSClement Faure 	struct dcp_align_buf input = { };
52593e678edSClement Faure 	uint32_t offset = 0;
52693e678edSClement Faure 	uint32_t nb_blocks = 0;
52793e678edSClement Faure 	size_t size_todo = 0;
52893e678edSClement Faure 	size_t size_left = 0;
52993e678edSClement Faure 	size_t size_total = 0;
53093e678edSClement Faure 
53193e678edSClement Faure 	if (!hashdata || !data || !len)
53293e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
53393e678edSClement Faure 
53493e678edSClement Faure 	if (!hashdata->initialized) {
53593e678edSClement Faure 		EMSG("hashdata is uninitialized");
53693e678edSClement Faure 		return TEE_ERROR_BAD_STATE;
53793e678edSClement Faure 	}
53893e678edSClement Faure 
53993e678edSClement Faure 	/* Get number of blocks */
54093e678edSClement Faure 	if (ADD_OVERFLOW(hashdata->ctx_size, len, &size_total))
54193e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
54293e678edSClement Faure 
54393e678edSClement Faure 	nb_blocks = size_total / DCP_SHA_BLOCK_SIZE;
54493e678edSClement Faure 	size_todo = nb_blocks * DCP_SHA_BLOCK_SIZE;
54593e678edSClement Faure 	size_left = len - size_todo + hashdata->ctx_size;
54693e678edSClement Faure 	desc = &hashdata->dcp_data.desc;
54793e678edSClement Faure 
54893e678edSClement Faure 	if (size_todo) {
54993e678edSClement Faure 		/* Allocate buffer as input */
55093e678edSClement Faure 		ret = dcp_calloc_align_buf(&input, size_todo);
55193e678edSClement Faure 		if (ret != TEE_SUCCESS)
55293e678edSClement Faure 			return ret;
55393e678edSClement Faure 
55493e678edSClement Faure 		/* Copy previous data if any */
55593e678edSClement Faure 		offset = size_todo - hashdata->ctx_size;
55693e678edSClement Faure 		memcpy(input.data, hashdata->ctx.data, hashdata->ctx_size);
55793e678edSClement Faure 		memcpy(input.data + hashdata->ctx_size, data, offset);
55893e678edSClement Faure 		hashdata->ctx_size = 0;
55993e678edSClement Faure 
56093e678edSClement Faure 		desc->src_buffer = input.paddr;
56193e678edSClement Faure 		desc->buff_size = size_todo;
56293e678edSClement Faure 
56393e678edSClement Faure 		cache_operation(TEE_CACHECLEAN, input.data, size_todo);
56493e678edSClement Faure 
56593e678edSClement Faure 		ret = dcp_run(&hashdata->dcp_data);
56693e678edSClement Faure 		desc->ctrl0 &= ~DCP_CONTROL0_HASH_INIT;
56793e678edSClement Faure 
56893e678edSClement Faure 		dcp_free(&input);
56993e678edSClement Faure 	} else {
57093e678edSClement Faure 		size_left = len;
57193e678edSClement Faure 		offset = 0;
57293e678edSClement Faure 		ret = TEE_SUCCESS;
57393e678edSClement Faure 	}
57493e678edSClement Faure 
57593e678edSClement Faure 	/* Save any data left */
57693e678edSClement Faure 	memcpy(hashdata->ctx.data + hashdata->ctx_size, data + offset,
57793e678edSClement Faure 	       size_left);
57893e678edSClement Faure 	hashdata->ctx_size += size_left;
57993e678edSClement Faure 
58093e678edSClement Faure 	return ret;
58193e678edSClement Faure }
58293e678edSClement Faure 
dcp_sha_do_final(struct dcp_hash_data * hashdata,uint8_t * digest,size_t digest_size)58393e678edSClement Faure TEE_Result dcp_sha_do_final(struct dcp_hash_data *hashdata, uint8_t *digest,
58493e678edSClement Faure 			    size_t digest_size)
58593e678edSClement Faure {
58693e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
58793e678edSClement Faure 	size_t payload_size = 0;
58893e678edSClement Faure 	struct dcp_descriptor *desc = NULL;
58993e678edSClement Faure 	struct dcp_align_buf payload = { };
59093e678edSClement Faure 
59193e678edSClement Faure 	if (!hashdata || !digest)
59293e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
59393e678edSClement Faure 
59493e678edSClement Faure 	if (!hashdata->initialized) {
59593e678edSClement Faure 		EMSG("hashdata is uninitialized");
59693e678edSClement Faure 		return TEE_ERROR_BAD_STATE;
59793e678edSClement Faure 	}
59893e678edSClement Faure 
59993e678edSClement Faure 	if (digest_size < hash_alg[hashdata->alg].size) {
60093e678edSClement Faure 		EMSG("Digest buffer size is to small, should be %" PRId32,
60193e678edSClement Faure 		     hash_alg[hashdata->alg].size);
60293e678edSClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
60393e678edSClement Faure 	}
60493e678edSClement Faure 
60593e678edSClement Faure 	desc = &hashdata->dcp_data.desc;
60693e678edSClement Faure 	payload_size = hash_alg[hashdata->alg].size;
60793e678edSClement Faure 
60893e678edSClement Faure 	/* Handle the case where the input message is NULL */
60993e678edSClement Faure 	if ((desc->ctrl0 & DCP_CONTROL0_HASH_INIT) && hashdata->ctx_size == 0) {
61093e678edSClement Faure 		if (hashdata->alg == DCP_SHA1)
61193e678edSClement Faure 			memcpy(digest, sha1_null_msg, payload_size);
61293e678edSClement Faure 		if (hashdata->alg == DCP_SHA256)
61393e678edSClement Faure 			memcpy(digest, sha256_null_msg, payload_size);
61493e678edSClement Faure 		ret = TEE_SUCCESS;
61593e678edSClement Faure 	} else {
61693e678edSClement Faure 		/* Allocate buffer for the digest */
61793e678edSClement Faure 		ret = dcp_calloc_align_buf(&payload, payload_size);
61893e678edSClement Faure 		if (ret != TEE_SUCCESS)
61993e678edSClement Faure 			return ret;
62093e678edSClement Faure 
62193e678edSClement Faure 		/* Set work packet for last iteration */
62293e678edSClement Faure 		desc->ctrl0 |= DCP_CONTROL0_HASH_TERM;
62393e678edSClement Faure 		desc->src_buffer = hashdata->ctx.paddr;
62493e678edSClement Faure 		desc->buff_size = hashdata->ctx_size;
62593e678edSClement Faure 		desc->payload = payload.paddr;
62693e678edSClement Faure 
62793e678edSClement Faure 		cache_operation(TEE_CACHECLEAN, hashdata->ctx.data,
62893e678edSClement Faure 				hashdata->ctx_size);
62993e678edSClement Faure 		cache_operation(TEE_CACHEINVALIDATE, payload.data,
63093e678edSClement Faure 				payload_size);
63193e678edSClement Faure 
63293e678edSClement Faure 		ret = dcp_run(&hashdata->dcp_data);
63393e678edSClement Faure 
63493e678edSClement Faure 		/* Copy the result */
63593e678edSClement Faure 		cache_operation(TEE_CACHEINVALIDATE, payload.data,
63693e678edSClement Faure 				payload_size);
63793e678edSClement Faure 		/* DCP payload result is flipped */
63893e678edSClement Faure 		dcp_reverse(payload.data, digest, payload_size);
63993e678edSClement Faure 
64093e678edSClement Faure 		dcp_free(&payload);
64193e678edSClement Faure 	}
64293e678edSClement Faure 
64393e678edSClement Faure 	dcp_free(&hashdata->ctx);
64493e678edSClement Faure 
64593e678edSClement Faure 	/* Reset hashdata strcuture */
64693e678edSClement Faure 	hashdata->initialized = false;
64793e678edSClement Faure 
64893e678edSClement Faure 	dcp_unlock_channel(hashdata->dcp_data.channel);
64993e678edSClement Faure 
65093e678edSClement Faure 	return ret;
65193e678edSClement Faure }
65293e678edSClement Faure 
dcp_disable_unique_key(void)6533fc5c287SClement Faure void dcp_disable_unique_key(void)
6543fc5c287SClement Faure {
6553fc5c287SClement Faure 	dcp_clk_enable(true);
6563fc5c287SClement Faure 	io_setbits32(dcp_base + DCP_CAPABILITY0,
6573fc5c287SClement Faure 		     DCP_CAPABILITY0_DISABLE_UNIQUE_KEY);
6583fc5c287SClement Faure 	dcp_clk_enable(false);
6593fc5c287SClement Faure }
6603fc5c287SClement Faure 
66193e678edSClement Faure #ifdef CFG_DT
66293e678edSClement Faure static const char *const dt_ctrl_match_table[] = {
66393e678edSClement Faure 	"fsl,imx28-dcp",
66493e678edSClement Faure 	"fsl,imx6sl-dcp",
66593e678edSClement Faure };
66693e678edSClement Faure 
66793e678edSClement Faure /*
66893e678edSClement Faure  * Fetch DCP base address from DT
66993e678edSClement Faure  *
67093e678edSClement Faure  * @base        [out] DCP base address
67193e678edSClement Faure  */
dcp_pbase(paddr_t * base)67293e678edSClement Faure static TEE_Result dcp_pbase(paddr_t *base)
67393e678edSClement Faure {
67493e678edSClement Faure 	void *fdt = NULL;
67593e678edSClement Faure 	int node = -1;
67693e678edSClement Faure 	unsigned int i = 0;
67793e678edSClement Faure 
67893e678edSClement Faure 	fdt = get_dt();
67993e678edSClement Faure 	if (!fdt) {
68093e678edSClement Faure 		EMSG("DTB no present");
68193e678edSClement Faure 		return TEE_ERROR_ITEM_NOT_FOUND;
68293e678edSClement Faure 	}
68393e678edSClement Faure 
68493e678edSClement Faure 	for (i = 0; i < ARRAY_SIZE(dt_ctrl_match_table); i++) {
68593e678edSClement Faure 		node = fdt_node_offset_by_compatible(fdt, 0,
68693e678edSClement Faure 						     dt_ctrl_match_table[i]);
68793e678edSClement Faure 		if (node >= 0)
68893e678edSClement Faure 			break;
68993e678edSClement Faure 	}
69093e678edSClement Faure 
69193e678edSClement Faure 	if (node < 0) {
69293e678edSClement Faure 		EMSG("DCP node not found err = %d", node);
69393e678edSClement Faure 		return TEE_ERROR_ITEM_NOT_FOUND;
69493e678edSClement Faure 	}
69593e678edSClement Faure 
696f354a5d8SGatien Chevallier 	if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED)
69793e678edSClement Faure 		return TEE_ERROR_ITEM_NOT_FOUND;
69893e678edSClement Faure 
69993e678edSClement Faure 	/* Force secure-status = "okay" and status="disabled" */
70093e678edSClement Faure 	if (dt_enable_secure_status(fdt, node)) {
70193e678edSClement Faure 		EMSG("Not able to set DCP Control DTB entry secure");
70293e678edSClement Faure 		return TEE_ERROR_NOT_SUPPORTED;
70393e678edSClement Faure 	}
70493e678edSClement Faure 
705f354a5d8SGatien Chevallier 	*base = fdt_reg_base_address(fdt, node);
70693e678edSClement Faure 	if (*base == DT_INFO_INVALID_REG) {
70793e678edSClement Faure 		EMSG("Unable to get the DCP Base address");
70893e678edSClement Faure 		return TEE_ERROR_ITEM_NOT_FOUND;
70993e678edSClement Faure 	}
71093e678edSClement Faure 
71193e678edSClement Faure 	return TEE_SUCCESS;
71293e678edSClement Faure }
71393e678edSClement Faure #endif /* CFG_DT */
71493e678edSClement Faure 
dcp_init(void)71593e678edSClement Faure TEE_Result dcp_init(void)
71693e678edSClement Faure {
71793e678edSClement Faure 	TEE_Result ret = TEE_ERROR_GENERIC;
71893e678edSClement Faure 	paddr_t pbase = 0;
71993e678edSClement Faure 
72093e678edSClement Faure 	if (driver_initialized)
72193e678edSClement Faure 		return TEE_SUCCESS;
72293e678edSClement Faure 
72393e678edSClement Faure 	dcp_clk_enable(true);
72493e678edSClement Faure 
72593e678edSClement Faure 	ret = dcp_pbase(&pbase);
72693e678edSClement Faure 	if (ret != TEE_SUCCESS)
72793e678edSClement Faure 		pbase = DCP_BASE;
72893e678edSClement Faure 
729c2e4eb43SAnton Rybakov 	dcp_base = core_mmu_get_va(pbase, MEM_AREA_IO_SEC, DCP_CONTEXT +
730c2e4eb43SAnton Rybakov 				   sizeof(uint32_t));
73193e678edSClement Faure 	if (!dcp_base) {
73293e678edSClement Faure 		EMSG("Unable to get DCP physical address");
73393e678edSClement Faure 		return TEE_ERROR_ITEM_NOT_FOUND;
73493e678edSClement Faure 	}
73593e678edSClement Faure 
73693e678edSClement Faure 	/* Context switching buffer memory allocation */
73793e678edSClement Faure 	ret = dcp_calloc_align_buf(&hw_context_buffer, DCP_CONTEXT_BUFFER_SIZE);
73893e678edSClement Faure 	if (ret != TEE_SUCCESS) {
73993e678edSClement Faure 		EMSG("hw_context_buffer allocation failed");
74093e678edSClement Faure 		return ret;
74193e678edSClement Faure 	}
74293e678edSClement Faure 
74393e678edSClement Faure 	/*
744b6760712SClement Faure 	 * Reset the DCP before initialization. Depending on the SoC lifecycle
745b6760712SClement Faure 	 * state, the DCP needs to be reset to reload the OTP master key from
746b6760712SClement Faure 	 * the SNVS.
747b6760712SClement Faure 	 */
748b6760712SClement Faure 	io_write32(dcp_base + DCP_CTRL_SET, DCP_CTRL_SFTRST | DCP_CTRL_CLKGATE);
749b6760712SClement Faure 
750b6760712SClement Faure 	/*
75193e678edSClement Faure 	 * Initialize control register.
75293e678edSClement Faure 	 * Enable normal DCP operation (SFTRST & CLKGATE bits set to 0)
75393e678edSClement Faure 	 */
75493e678edSClement Faure 	io_write32(dcp_base + DCP_CTRL_CLR, DCP_CTRL_SFTRST | DCP_CTRL_CLKGATE);
75593e678edSClement Faure 
75693e678edSClement Faure 	io_write32(dcp_base + DCP_CTRL_SET,
75793e678edSClement Faure 		   DCP_CTRL_GATHER_RESIDUAL_WRITES |
75893e678edSClement Faure 			   DCP_CTRL_ENABLE_CONTEXT_SWITCHING);
75993e678edSClement Faure 
76093e678edSClement Faure 	/* Enable all DCP channels */
76193e678edSClement Faure 	io_write32(dcp_base + DCP_CHANNELCTRL,
76293e678edSClement Faure 		   DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK);
76393e678edSClement Faure 
76493e678edSClement Faure 	/* Clear DCP_STAT register */
76593e678edSClement Faure 	io_write32(dcp_base + DCP_STAT_CLR, DCP_STAT_CLEAR);
76693e678edSClement Faure 
76793e678edSClement Faure 	/* Copy context switching buffer address in DCP_CONTEXT register */
76893e678edSClement Faure 	io_write32(dcp_base + DCP_CONTEXT, (uint32_t)hw_context_buffer.paddr);
76993e678edSClement Faure 
77093e678edSClement Faure 	driver_initialized = true;
77193e678edSClement Faure 
77293e678edSClement Faure 	dcp_clk_enable(false);
77393e678edSClement Faure 
77493e678edSClement Faure 	return ret;
77593e678edSClement Faure }
776