xref: /rk3399_ARM-atf/plat/intel/soc/common/socfpga_sip_svc.c (revision 108514ff7160a86efb791449a4635ffe0f9fdf2c)
1c76d4239SHadi Asyrafi /*
212d71ac6SAbdul Halim, Muhammad Hadi Asyrafi  * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
3c76d4239SHadi Asyrafi  *
4c76d4239SHadi Asyrafi  * SPDX-License-Identifier: BSD-3-Clause
5c76d4239SHadi Asyrafi  */
6c76d4239SHadi Asyrafi 
7c76d4239SHadi Asyrafi #include <assert.h>
8c76d4239SHadi Asyrafi #include <common/debug.h>
9c76d4239SHadi Asyrafi #include <common/runtime_svc.h>
1013d33d52SHadi Asyrafi #include <lib/mmio.h>
11c76d4239SHadi Asyrafi #include <tools_share/uuid.h>
12c76d4239SHadi Asyrafi 
13c76d4239SHadi Asyrafi #include "socfpga_mailbox.h"
149c8f3af5SHadi Asyrafi #include "socfpga_reset_manager.h"
15d25041bfSHadi Asyrafi #include "socfpga_sip_svc.h"
16c76d4239SHadi Asyrafi 
17c76d4239SHadi Asyrafi 
18c76d4239SHadi Asyrafi /* Total buffer the driver can hold */
19c76d4239SHadi Asyrafi #define FPGA_CONFIG_BUFFER_SIZE 4
20c76d4239SHadi Asyrafi 
21aad868b4SAbdul Halim, Muhammad Hadi Asyrafi static int current_block, current_buffer;
22aad868b4SAbdul Halim, Muhammad Hadi Asyrafi static int read_block, max_blocks, is_partial_reconfig;
23aad868b4SAbdul Halim, Muhammad Hadi Asyrafi static uint32_t send_id, rcv_id;
24aad868b4SAbdul Halim, Muhammad Hadi Asyrafi static uint32_t bytes_per_block, blocks_submitted;
25c76d4239SHadi Asyrafi 
26c76d4239SHadi Asyrafi 
27c76d4239SHadi Asyrafi /*  SiP Service UUID */
28c76d4239SHadi Asyrafi DEFINE_SVC_UUID2(intl_svc_uid,
29c76d4239SHadi Asyrafi 		0xa85273b0, 0xe85a, 0x4862, 0xa6, 0x2a,
30c76d4239SHadi Asyrafi 		0xfa, 0x88, 0x88, 0x17, 0x68, 0x81);
31c76d4239SHadi Asyrafi 
32e5ebe87bSHadi Asyrafi static uint64_t socfpga_sip_handler(uint32_t smc_fid,
33c76d4239SHadi Asyrafi 				   uint64_t x1,
34c76d4239SHadi Asyrafi 				   uint64_t x2,
35c76d4239SHadi Asyrafi 				   uint64_t x3,
36c76d4239SHadi Asyrafi 				   uint64_t x4,
37c76d4239SHadi Asyrafi 				   void *cookie,
38c76d4239SHadi Asyrafi 				   void *handle,
39c76d4239SHadi Asyrafi 				   uint64_t flags)
40c76d4239SHadi Asyrafi {
41c76d4239SHadi Asyrafi 	ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
42c76d4239SHadi Asyrafi 	SMC_RET1(handle, SMC_UNK);
43c76d4239SHadi Asyrafi }
44c76d4239SHadi Asyrafi 
45c76d4239SHadi Asyrafi struct fpga_config_info fpga_config_buffers[FPGA_CONFIG_BUFFER_SIZE];
46c76d4239SHadi Asyrafi 
477c58fd4eSHadi Asyrafi static int intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer)
48c76d4239SHadi Asyrafi {
49ea9b9627SAbdul Halim, Muhammad Hadi Asyrafi 	uint32_t args[3];
50c76d4239SHadi Asyrafi 
51c76d4239SHadi Asyrafi 	while (max_blocks > 0 && buffer->size > buffer->size_written) {
52c76d4239SHadi Asyrafi 		args[0] = (1<<8);
53c76d4239SHadi Asyrafi 		args[1] = buffer->addr + buffer->size_written;
547c58fd4eSHadi Asyrafi 		if (buffer->size - buffer->size_written <= bytes_per_block) {
55c76d4239SHadi Asyrafi 			args[2] = buffer->size - buffer->size_written;
56c76d4239SHadi Asyrafi 			current_buffer++;
57c76d4239SHadi Asyrafi 			current_buffer %= FPGA_CONFIG_BUFFER_SIZE;
587c58fd4eSHadi Asyrafi 		} else
59c76d4239SHadi Asyrafi 			args[2] = bytes_per_block;
607c58fd4eSHadi Asyrafi 
617c58fd4eSHadi Asyrafi 		buffer->size_written += args[2];
62aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		mailbox_send_cmd_async(&send_id, MBOX_RECONFIG_DATA, args,
63d57318b7SAbdul Halim, Muhammad Hadi Asyrafi 					3U, CMD_INDIRECT);
647c58fd4eSHadi Asyrafi 
65c76d4239SHadi Asyrafi 		buffer->subblocks_sent++;
66c76d4239SHadi Asyrafi 		max_blocks--;
67c76d4239SHadi Asyrafi 	}
687c58fd4eSHadi Asyrafi 
697c58fd4eSHadi Asyrafi 	return !max_blocks;
70c76d4239SHadi Asyrafi }
71c76d4239SHadi Asyrafi 
72c76d4239SHadi Asyrafi static int intel_fpga_sdm_write_all(void)
73c76d4239SHadi Asyrafi {
747c58fd4eSHadi Asyrafi 	for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++)
757c58fd4eSHadi Asyrafi 		if (intel_fpga_sdm_write_buffer(
767c58fd4eSHadi Asyrafi 			&fpga_config_buffers[current_buffer]))
777c58fd4eSHadi Asyrafi 			break;
78c76d4239SHadi Asyrafi 	return 0;
79c76d4239SHadi Asyrafi }
80c76d4239SHadi Asyrafi 
81dfdd38c2SHadi Asyrafi static uint32_t intel_mailbox_fpga_config_isdone(uint32_t query_type)
82c76d4239SHadi Asyrafi {
83dfdd38c2SHadi Asyrafi 	uint32_t ret;
84dfdd38c2SHadi Asyrafi 
85dfdd38c2SHadi Asyrafi 	if (query_type == 1)
86dfdd38c2SHadi Asyrafi 		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS);
87dfdd38c2SHadi Asyrafi 	else
88dfdd38c2SHadi Asyrafi 		ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS);
897c58fd4eSHadi Asyrafi 
907c58fd4eSHadi Asyrafi 	if (ret) {
917c58fd4eSHadi Asyrafi 		if (ret == MBOX_CFGSTAT_STATE_CONFIG)
927c58fd4eSHadi Asyrafi 			return INTEL_SIP_SMC_STATUS_BUSY;
937c58fd4eSHadi Asyrafi 		else
947c58fd4eSHadi Asyrafi 			return INTEL_SIP_SMC_STATUS_ERROR;
957c58fd4eSHadi Asyrafi 	}
967c58fd4eSHadi Asyrafi 
979c8f3af5SHadi Asyrafi 	if (query_type != 1) {
989c8f3af5SHadi Asyrafi 		/* full reconfiguration */
999c8f3af5SHadi Asyrafi 		if (!is_partial_reconfig)
1009c8f3af5SHadi Asyrafi 			socfpga_bridges_enable();	/* Enable bridge */
1019c8f3af5SHadi Asyrafi 	}
1029c8f3af5SHadi Asyrafi 
1037c58fd4eSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
104c76d4239SHadi Asyrafi }
105c76d4239SHadi Asyrafi 
106c76d4239SHadi Asyrafi static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed)
107c76d4239SHadi Asyrafi {
108c76d4239SHadi Asyrafi 	int i;
109c76d4239SHadi Asyrafi 
110c76d4239SHadi Asyrafi 	for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
111c76d4239SHadi Asyrafi 		if (fpga_config_buffers[i].block_number == current_block) {
112c76d4239SHadi Asyrafi 			fpga_config_buffers[i].subblocks_sent--;
113c76d4239SHadi Asyrafi 			if (fpga_config_buffers[i].subblocks_sent == 0
114c76d4239SHadi Asyrafi 			&& fpga_config_buffers[i].size <=
115c76d4239SHadi Asyrafi 			fpga_config_buffers[i].size_written) {
116c76d4239SHadi Asyrafi 				fpga_config_buffers[i].write_requested = 0;
117c76d4239SHadi Asyrafi 				current_block++;
118c76d4239SHadi Asyrafi 				*buffer_addr_completed =
119c76d4239SHadi Asyrafi 					fpga_config_buffers[i].addr;
120c76d4239SHadi Asyrafi 				return 0;
121c76d4239SHadi Asyrafi 			}
122c76d4239SHadi Asyrafi 		}
123c76d4239SHadi Asyrafi 	}
124c76d4239SHadi Asyrafi 
125c76d4239SHadi Asyrafi 	return -1;
126c76d4239SHadi Asyrafi }
127c76d4239SHadi Asyrafi 
128e5ebe87bSHadi Asyrafi static int intel_fpga_config_completed_write(uint32_t *completed_addr,
129aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 					uint32_t *count, uint32_t *job_id)
130c76d4239SHadi Asyrafi {
131c76d4239SHadi Asyrafi 	uint32_t status = INTEL_SIP_SMC_STATUS_OK;
132c76d4239SHadi Asyrafi 	*count = 0;
133c76d4239SHadi Asyrafi 	int resp_len = 0;
134c76d4239SHadi Asyrafi 	uint32_t resp[5];
135c76d4239SHadi Asyrafi 	int all_completed = 1;
136c76d4239SHadi Asyrafi 
137cefb37ebSTien Hock, Loh 	while (*count < 3) {
138c76d4239SHadi Asyrafi 
139aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		resp_len = mailbox_read_response(job_id,
140f8e6a09cSAbdul Halim, Muhammad Hadi Asyrafi 				resp, ARRAY_SIZE(resp));
141c76d4239SHadi Asyrafi 
142cefb37ebSTien Hock, Loh 		if (resp_len < 0)
143cefb37ebSTien Hock, Loh 			break;
144c76d4239SHadi Asyrafi 
145c76d4239SHadi Asyrafi 		max_blocks++;
146cefb37ebSTien Hock, Loh 
147c76d4239SHadi Asyrafi 		if (mark_last_buffer_xfer_completed(
148c76d4239SHadi Asyrafi 			&completed_addr[*count]) == 0)
149c76d4239SHadi Asyrafi 			*count = *count + 1;
150c76d4239SHadi Asyrafi 		else
151c76d4239SHadi Asyrafi 			break;
152c76d4239SHadi Asyrafi 	}
153c76d4239SHadi Asyrafi 
154c76d4239SHadi Asyrafi 	if (*count <= 0) {
155c76d4239SHadi Asyrafi 		if (resp_len != MBOX_NO_RESPONSE &&
156c76d4239SHadi Asyrafi 			resp_len != MBOX_TIMEOUT && resp_len != 0) {
157cefb37ebSTien Hock, Loh 			mailbox_clear_response();
158c76d4239SHadi Asyrafi 			return INTEL_SIP_SMC_STATUS_ERROR;
159c76d4239SHadi Asyrafi 		}
160c76d4239SHadi Asyrafi 
161c76d4239SHadi Asyrafi 		*count = 0;
162c76d4239SHadi Asyrafi 	}
163c76d4239SHadi Asyrafi 
164c76d4239SHadi Asyrafi 	intel_fpga_sdm_write_all();
165c76d4239SHadi Asyrafi 
166c76d4239SHadi Asyrafi 	if (*count > 0)
167c76d4239SHadi Asyrafi 		status = INTEL_SIP_SMC_STATUS_OK;
168c76d4239SHadi Asyrafi 	else if (*count == 0)
169c76d4239SHadi Asyrafi 		status = INTEL_SIP_SMC_STATUS_BUSY;
170c76d4239SHadi Asyrafi 
171c76d4239SHadi Asyrafi 	for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
172c76d4239SHadi Asyrafi 		if (fpga_config_buffers[i].write_requested != 0) {
173c76d4239SHadi Asyrafi 			all_completed = 0;
174c76d4239SHadi Asyrafi 			break;
175c76d4239SHadi Asyrafi 		}
176c76d4239SHadi Asyrafi 	}
177c76d4239SHadi Asyrafi 
178c76d4239SHadi Asyrafi 	if (all_completed == 1)
179c76d4239SHadi Asyrafi 		return INTEL_SIP_SMC_STATUS_OK;
180c76d4239SHadi Asyrafi 
181c76d4239SHadi Asyrafi 	return status;
182c76d4239SHadi Asyrafi }
183c76d4239SHadi Asyrafi 
184e5ebe87bSHadi Asyrafi static int intel_fpga_config_start(uint32_t config_type)
185c76d4239SHadi Asyrafi {
186c76d4239SHadi Asyrafi 	uint32_t response[3];
187c76d4239SHadi Asyrafi 	int status = 0;
188c76d4239SHadi Asyrafi 
1899c8f3af5SHadi Asyrafi 	is_partial_reconfig = config_type;
1909c8f3af5SHadi Asyrafi 
191cefb37ebSTien Hock, Loh 	mailbox_clear_response();
192cefb37ebSTien Hock, Loh 
193d57318b7SAbdul Halim, Muhammad Hadi Asyrafi 	mailbox_send_cmd(1U, MBOX_CMD_CANCEL, NULL, 0U, CMD_CASUAL, NULL, 0U);
194cefb37ebSTien Hock, Loh 
195d57318b7SAbdul Halim, Muhammad Hadi Asyrafi 	status = mailbox_send_cmd(1U, MBOX_RECONFIG, NULL, 0U, CMD_CASUAL,
196f8e6a09cSAbdul Halim, Muhammad Hadi Asyrafi 			response, ARRAY_SIZE(response));
197c76d4239SHadi Asyrafi 
198c76d4239SHadi Asyrafi 	if (status < 0)
199c76d4239SHadi Asyrafi 		return status;
200c76d4239SHadi Asyrafi 
201c76d4239SHadi Asyrafi 	max_blocks = response[0];
202c76d4239SHadi Asyrafi 	bytes_per_block = response[1];
203c76d4239SHadi Asyrafi 
204c76d4239SHadi Asyrafi 	for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
205c76d4239SHadi Asyrafi 		fpga_config_buffers[i].size = 0;
206c76d4239SHadi Asyrafi 		fpga_config_buffers[i].size_written = 0;
207c76d4239SHadi Asyrafi 		fpga_config_buffers[i].addr = 0;
208c76d4239SHadi Asyrafi 		fpga_config_buffers[i].write_requested = 0;
209c76d4239SHadi Asyrafi 		fpga_config_buffers[i].block_number = 0;
210c76d4239SHadi Asyrafi 		fpga_config_buffers[i].subblocks_sent = 0;
211c76d4239SHadi Asyrafi 	}
212c76d4239SHadi Asyrafi 
213c76d4239SHadi Asyrafi 	blocks_submitted = 0;
214c76d4239SHadi Asyrafi 	current_block = 0;
215cefb37ebSTien Hock, Loh 	read_block = 0;
216c76d4239SHadi Asyrafi 	current_buffer = 0;
217c76d4239SHadi Asyrafi 
2189c8f3af5SHadi Asyrafi 	/* full reconfiguration */
2199c8f3af5SHadi Asyrafi 	if (!is_partial_reconfig) {
2209c8f3af5SHadi Asyrafi 		/* Disable bridge */
2219c8f3af5SHadi Asyrafi 		socfpga_bridges_disable();
2229c8f3af5SHadi Asyrafi 	}
2239c8f3af5SHadi Asyrafi 
224c76d4239SHadi Asyrafi 	return 0;
225c76d4239SHadi Asyrafi }
226c76d4239SHadi Asyrafi 
2277c58fd4eSHadi Asyrafi static bool is_fpga_config_buffer_full(void)
2287c58fd4eSHadi Asyrafi {
2297c58fd4eSHadi Asyrafi 	for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++)
2307c58fd4eSHadi Asyrafi 		if (!fpga_config_buffers[i].write_requested)
2317c58fd4eSHadi Asyrafi 			return false;
2327c58fd4eSHadi Asyrafi 	return true;
2337c58fd4eSHadi Asyrafi }
2347c58fd4eSHadi Asyrafi 
235aad868b4SAbdul Halim, Muhammad Hadi Asyrafi bool is_address_in_ddr_range(uint64_t addr, uint64_t size)
2367c58fd4eSHadi Asyrafi {
23712d71ac6SAbdul Halim, Muhammad Hadi Asyrafi 	if (!addr && !size) {
23812d71ac6SAbdul Halim, Muhammad Hadi Asyrafi 		return true;
23912d71ac6SAbdul Halim, Muhammad Hadi Asyrafi 	}
2401a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	if (size > (UINT64_MAX - addr))
2417c58fd4eSHadi Asyrafi 		return false;
242a62b47b8SAbdul Halim, Muhammad Hadi Asyrafi 	if (addr < BL31_LIMIT)
2431a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 		return false;
2441a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	if (addr + size > DRAM_BASE + DRAM_SIZE)
2451a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 		return false;
2461a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 
2471a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	return true;
2487c58fd4eSHadi Asyrafi }
249c76d4239SHadi Asyrafi 
250e5ebe87bSHadi Asyrafi static uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size)
251c76d4239SHadi Asyrafi {
2527c58fd4eSHadi Asyrafi 	int i;
253c76d4239SHadi Asyrafi 
2547c58fd4eSHadi Asyrafi 	intel_fpga_sdm_write_all();
255c76d4239SHadi Asyrafi 
2561a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	if (!is_address_in_ddr_range(mem, size) ||
2577c58fd4eSHadi Asyrafi 		is_fpga_config_buffer_full())
2587c58fd4eSHadi Asyrafi 		return INTEL_SIP_SMC_STATUS_REJECTED;
259c76d4239SHadi Asyrafi 
260c76d4239SHadi Asyrafi 	for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
2617c58fd4eSHadi Asyrafi 		int j = (i + current_buffer) % FPGA_CONFIG_BUFFER_SIZE;
2627c58fd4eSHadi Asyrafi 
2637c58fd4eSHadi Asyrafi 		if (!fpga_config_buffers[j].write_requested) {
2647c58fd4eSHadi Asyrafi 			fpga_config_buffers[j].addr = mem;
2657c58fd4eSHadi Asyrafi 			fpga_config_buffers[j].size = size;
2667c58fd4eSHadi Asyrafi 			fpga_config_buffers[j].size_written = 0;
2677c58fd4eSHadi Asyrafi 			fpga_config_buffers[j].write_requested = 1;
2687c58fd4eSHadi Asyrafi 			fpga_config_buffers[j].block_number =
269c76d4239SHadi Asyrafi 				blocks_submitted++;
2707c58fd4eSHadi Asyrafi 			fpga_config_buffers[j].subblocks_sent = 0;
271c76d4239SHadi Asyrafi 			break;
272c76d4239SHadi Asyrafi 		}
273c76d4239SHadi Asyrafi 	}
274c76d4239SHadi Asyrafi 
2757c58fd4eSHadi Asyrafi 	if (is_fpga_config_buffer_full())
2767c58fd4eSHadi Asyrafi 		return INTEL_SIP_SMC_STATUS_BUSY;
277c76d4239SHadi Asyrafi 
2787c58fd4eSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
279c76d4239SHadi Asyrafi }
280c76d4239SHadi Asyrafi 
28113d33d52SHadi Asyrafi static int is_out_of_sec_range(uint64_t reg_addr)
28213d33d52SHadi Asyrafi {
28313d33d52SHadi Asyrafi 	switch (reg_addr) {
28413d33d52SHadi Asyrafi 	case(0xF8011100):	/* ECCCTRL1 */
28513d33d52SHadi Asyrafi 	case(0xF8011104):	/* ECCCTRL2 */
28613d33d52SHadi Asyrafi 	case(0xF8011110):	/* ERRINTEN */
28713d33d52SHadi Asyrafi 	case(0xF8011114):	/* ERRINTENS */
28813d33d52SHadi Asyrafi 	case(0xF8011118):	/* ERRINTENR */
28913d33d52SHadi Asyrafi 	case(0xF801111C):	/* INTMODE */
29013d33d52SHadi Asyrafi 	case(0xF8011120):	/* INTSTAT */
29113d33d52SHadi Asyrafi 	case(0xF8011124):	/* DIAGINTTEST */
29213d33d52SHadi Asyrafi 	case(0xF801112C):	/* DERRADDRA */
29313d33d52SHadi Asyrafi 	case(0xFFD12028):	/* SDMMCGRP_CTRL */
29413d33d52SHadi Asyrafi 	case(0xFFD12044):	/* EMAC0 */
29513d33d52SHadi Asyrafi 	case(0xFFD12048):	/* EMAC1 */
29613d33d52SHadi Asyrafi 	case(0xFFD1204C):	/* EMAC2 */
29713d33d52SHadi Asyrafi 	case(0xFFD12090):	/* ECC_INT_MASK_VALUE */
29813d33d52SHadi Asyrafi 	case(0xFFD12094):	/* ECC_INT_MASK_SET */
29913d33d52SHadi Asyrafi 	case(0xFFD12098):	/* ECC_INT_MASK_CLEAR */
30013d33d52SHadi Asyrafi 	case(0xFFD1209C):	/* ECC_INTSTATUS_SERR */
30113d33d52SHadi Asyrafi 	case(0xFFD120A0):	/* ECC_INTSTATUS_DERR */
30213d33d52SHadi Asyrafi 	case(0xFFD120C0):	/* NOC_TIMEOUT */
30313d33d52SHadi Asyrafi 	case(0xFFD120C4):	/* NOC_IDLEREQ_SET */
30413d33d52SHadi Asyrafi 	case(0xFFD120C8):	/* NOC_IDLEREQ_CLR */
30513d33d52SHadi Asyrafi 	case(0xFFD120D0):	/* NOC_IDLEACK */
30613d33d52SHadi Asyrafi 	case(0xFFD120D4):	/* NOC_IDLESTATUS */
30713d33d52SHadi Asyrafi 	case(0xFFD12200):	/* BOOT_SCRATCH_COLD0 */
30813d33d52SHadi Asyrafi 	case(0xFFD12204):	/* BOOT_SCRATCH_COLD1 */
30913d33d52SHadi Asyrafi 	case(0xFFD12220):	/* BOOT_SCRATCH_COLD8 */
31013d33d52SHadi Asyrafi 	case(0xFFD12224):	/* BOOT_SCRATCH_COLD9 */
31113d33d52SHadi Asyrafi 		return 0;
31213d33d52SHadi Asyrafi 
31313d33d52SHadi Asyrafi 	default:
31413d33d52SHadi Asyrafi 		break;
31513d33d52SHadi Asyrafi 	}
31613d33d52SHadi Asyrafi 
31713d33d52SHadi Asyrafi 	return -1;
31813d33d52SHadi Asyrafi }
31913d33d52SHadi Asyrafi 
32013d33d52SHadi Asyrafi /* Secure register access */
32113d33d52SHadi Asyrafi uint32_t intel_secure_reg_read(uint64_t reg_addr, uint32_t *retval)
32213d33d52SHadi Asyrafi {
32313d33d52SHadi Asyrafi 	if (is_out_of_sec_range(reg_addr))
32413d33d52SHadi Asyrafi 		return INTEL_SIP_SMC_STATUS_ERROR;
32513d33d52SHadi Asyrafi 
32613d33d52SHadi Asyrafi 	*retval = mmio_read_32(reg_addr);
32713d33d52SHadi Asyrafi 
32813d33d52SHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
32913d33d52SHadi Asyrafi }
33013d33d52SHadi Asyrafi 
33113d33d52SHadi Asyrafi uint32_t intel_secure_reg_write(uint64_t reg_addr, uint32_t val,
33213d33d52SHadi Asyrafi 				uint32_t *retval)
33313d33d52SHadi Asyrafi {
33413d33d52SHadi Asyrafi 	if (is_out_of_sec_range(reg_addr))
33513d33d52SHadi Asyrafi 		return INTEL_SIP_SMC_STATUS_ERROR;
33613d33d52SHadi Asyrafi 
33713d33d52SHadi Asyrafi 	mmio_write_32(reg_addr, val);
33813d33d52SHadi Asyrafi 
33913d33d52SHadi Asyrafi 	return intel_secure_reg_read(reg_addr, retval);
34013d33d52SHadi Asyrafi }
34113d33d52SHadi Asyrafi 
34213d33d52SHadi Asyrafi uint32_t intel_secure_reg_update(uint64_t reg_addr, uint32_t mask,
34313d33d52SHadi Asyrafi 				 uint32_t val, uint32_t *retval)
34413d33d52SHadi Asyrafi {
34513d33d52SHadi Asyrafi 	if (!intel_secure_reg_read(reg_addr, retval)) {
34613d33d52SHadi Asyrafi 		*retval &= ~mask;
347c9c07099SSiew Chin Lim 		*retval |= val & mask;
34813d33d52SHadi Asyrafi 		return intel_secure_reg_write(reg_addr, *retval, retval);
34913d33d52SHadi Asyrafi 	}
35013d33d52SHadi Asyrafi 
35113d33d52SHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_ERROR;
35213d33d52SHadi Asyrafi }
35313d33d52SHadi Asyrafi 
354e1f97d9cSHadi Asyrafi /* Intel Remote System Update (RSU) services */
355e1f97d9cSHadi Asyrafi uint64_t intel_rsu_update_address;
356e1f97d9cSHadi Asyrafi 
357d57318b7SAbdul Halim, Muhammad Hadi Asyrafi static uint32_t intel_rsu_status(uint64_t *respbuf, unsigned int respbuf_sz)
358e1f97d9cSHadi Asyrafi {
359e1f97d9cSHadi Asyrafi 	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
360960896ebSAbdul Halim, Muhammad Hadi Asyrafi 		return INTEL_SIP_SMC_RSU_ERROR;
361e1f97d9cSHadi Asyrafi 
362e1f97d9cSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
363e1f97d9cSHadi Asyrafi }
364e1f97d9cSHadi Asyrafi 
365e1f97d9cSHadi Asyrafi static uint32_t intel_rsu_update(uint64_t update_address)
366e1f97d9cSHadi Asyrafi {
367e1f97d9cSHadi Asyrafi 	intel_rsu_update_address = update_address;
368e1f97d9cSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
369e1f97d9cSHadi Asyrafi }
370e1f97d9cSHadi Asyrafi 
371ea9b9627SAbdul Halim, Muhammad Hadi Asyrafi static uint32_t intel_rsu_notify(uint32_t execution_stage)
372e1f97d9cSHadi Asyrafi {
373a62b47b8SAbdul Halim, Muhammad Hadi Asyrafi 	if (mailbox_hps_stage_notify(execution_stage) < 0)
374960896ebSAbdul Halim, Muhammad Hadi Asyrafi 		return INTEL_SIP_SMC_RSU_ERROR;
375e1f97d9cSHadi Asyrafi 
376e1f97d9cSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
377e1f97d9cSHadi Asyrafi }
378e1f97d9cSHadi Asyrafi 
379e1f97d9cSHadi Asyrafi static uint32_t intel_rsu_retry_counter(uint32_t *respbuf, uint32_t respbuf_sz,
380e1f97d9cSHadi Asyrafi 					uint32_t *ret_stat)
381e1f97d9cSHadi Asyrafi {
382e1f97d9cSHadi Asyrafi 	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
383960896ebSAbdul Halim, Muhammad Hadi Asyrafi 		return INTEL_SIP_SMC_RSU_ERROR;
384e1f97d9cSHadi Asyrafi 
385e1f97d9cSHadi Asyrafi 	*ret_stat = respbuf[8];
386e1f97d9cSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
387e1f97d9cSHadi Asyrafi }
388e1f97d9cSHadi Asyrafi 
3890c5d62adSHadi Asyrafi /* Mailbox services */
390d57318b7SAbdul Halim, Muhammad Hadi Asyrafi static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, uint32_t len,
391d57318b7SAbdul Halim, Muhammad Hadi Asyrafi 				    uint32_t urgent, uint32_t *response,
392d57318b7SAbdul Halim, Muhammad Hadi Asyrafi 				    uint32_t resp_len, int *mbox_status,
3930c5d62adSHadi Asyrafi 				    int *len_in_resp)
3940c5d62adSHadi Asyrafi {
3951a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	*len_in_resp = 0;
3961a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	*mbox_status = 0;
3971a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 
3981a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 	if (!is_address_in_ddr_range((uint64_t)args, sizeof(uint32_t) * len))
3991a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 		return INTEL_SIP_SMC_STATUS_REJECTED;
4001a87db5dSAbdul Halim, Muhammad Hadi Asyrafi 
4010c5d62adSHadi Asyrafi 	int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent,
4020c5d62adSHadi Asyrafi 				      response, resp_len);
4030c5d62adSHadi Asyrafi 
4040c5d62adSHadi Asyrafi 	if (status < 0) {
4050c5d62adSHadi Asyrafi 		*mbox_status = -status;
4060c5d62adSHadi Asyrafi 		return INTEL_SIP_SMC_STATUS_ERROR;
4070c5d62adSHadi Asyrafi 	}
4080c5d62adSHadi Asyrafi 
4090c5d62adSHadi Asyrafi 	*mbox_status = 0;
4100c5d62adSHadi Asyrafi 	*len_in_resp = status;
4110c5d62adSHadi Asyrafi 	return INTEL_SIP_SMC_STATUS_OK;
4120c5d62adSHadi Asyrafi }
4130c5d62adSHadi Asyrafi 
414c76d4239SHadi Asyrafi /*
415c76d4239SHadi Asyrafi  * This function is responsible for handling all SiP calls from the NS world
416c76d4239SHadi Asyrafi  */
417c76d4239SHadi Asyrafi 
418c76d4239SHadi Asyrafi uintptr_t sip_smc_handler(uint32_t smc_fid,
419c76d4239SHadi Asyrafi 			 u_register_t x1,
420c76d4239SHadi Asyrafi 			 u_register_t x2,
421c76d4239SHadi Asyrafi 			 u_register_t x3,
422c76d4239SHadi Asyrafi 			 u_register_t x4,
423c76d4239SHadi Asyrafi 			 void *cookie,
424c76d4239SHadi Asyrafi 			 void *handle,
425c76d4239SHadi Asyrafi 			 u_register_t flags)
426c76d4239SHadi Asyrafi {
427aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 	uint32_t retval = 0;
428c76d4239SHadi Asyrafi 	uint32_t status = INTEL_SIP_SMC_STATUS_OK;
429c76d4239SHadi Asyrafi 	uint32_t completed_addr[3];
430e1f97d9cSHadi Asyrafi 	uint64_t rsu_respbuf[9];
4310c5d62adSHadi Asyrafi 	u_register_t x5, x6;
4320c5d62adSHadi Asyrafi 	int mbox_status, len_in_resp;
433c76d4239SHadi Asyrafi 
434f8e6a09cSAbdul Halim, Muhammad Hadi Asyrafi 
435c76d4239SHadi Asyrafi 	switch (smc_fid) {
436c76d4239SHadi Asyrafi 	case SIP_SVC_UID:
437c76d4239SHadi Asyrafi 		/* Return UID to the caller */
438c76d4239SHadi Asyrafi 		SMC_UUID_RET(handle, intl_svc_uid);
43913d33d52SHadi Asyrafi 
440c76d4239SHadi Asyrafi 	case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE:
441dfdd38c2SHadi Asyrafi 		status = intel_mailbox_fpga_config_isdone(x1);
442c76d4239SHadi Asyrafi 		SMC_RET4(handle, status, 0, 0, 0);
44313d33d52SHadi Asyrafi 
444c76d4239SHadi Asyrafi 	case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM:
445c76d4239SHadi Asyrafi 		SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
446c76d4239SHadi Asyrafi 			INTEL_SIP_SMC_FPGA_CONFIG_ADDR,
447c76d4239SHadi Asyrafi 			INTEL_SIP_SMC_FPGA_CONFIG_SIZE -
448c76d4239SHadi Asyrafi 				INTEL_SIP_SMC_FPGA_CONFIG_ADDR);
44913d33d52SHadi Asyrafi 
450c76d4239SHadi Asyrafi 	case INTEL_SIP_SMC_FPGA_CONFIG_START:
451c76d4239SHadi Asyrafi 		status = intel_fpga_config_start(x1);
452c76d4239SHadi Asyrafi 		SMC_RET4(handle, status, 0, 0, 0);
45313d33d52SHadi Asyrafi 
454c76d4239SHadi Asyrafi 	case INTEL_SIP_SMC_FPGA_CONFIG_WRITE:
455c76d4239SHadi Asyrafi 		status = intel_fpga_config_write(x1, x2);
456c76d4239SHadi Asyrafi 		SMC_RET4(handle, status, 0, 0, 0);
45713d33d52SHadi Asyrafi 
458c76d4239SHadi Asyrafi 	case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE:
459c76d4239SHadi Asyrafi 		status = intel_fpga_config_completed_write(completed_addr,
460aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 							&retval, &rcv_id);
461aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		switch (retval) {
462c76d4239SHadi Asyrafi 		case 1:
463c76d4239SHadi Asyrafi 			SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
464c76d4239SHadi Asyrafi 				completed_addr[0], 0, 0);
46513d33d52SHadi Asyrafi 
466c76d4239SHadi Asyrafi 		case 2:
467c76d4239SHadi Asyrafi 			SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
468c76d4239SHadi Asyrafi 				completed_addr[0],
469c76d4239SHadi Asyrafi 				completed_addr[1], 0);
47013d33d52SHadi Asyrafi 
471c76d4239SHadi Asyrafi 		case 3:
472c76d4239SHadi Asyrafi 			SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
473c76d4239SHadi Asyrafi 				completed_addr[0],
474c76d4239SHadi Asyrafi 				completed_addr[1],
475c76d4239SHadi Asyrafi 				completed_addr[2]);
47613d33d52SHadi Asyrafi 
477c76d4239SHadi Asyrafi 		case 0:
478c76d4239SHadi Asyrafi 			SMC_RET4(handle, status, 0, 0, 0);
47913d33d52SHadi Asyrafi 
480c76d4239SHadi Asyrafi 		default:
481cefb37ebSTien Hock, Loh 			mailbox_clear_response();
482c76d4239SHadi Asyrafi 			SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR);
483c76d4239SHadi Asyrafi 		}
48413d33d52SHadi Asyrafi 
48513d33d52SHadi Asyrafi 	case INTEL_SIP_SMC_REG_READ:
486aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		status = intel_secure_reg_read(x1, &retval);
487aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		SMC_RET3(handle, status, retval, x1);
48813d33d52SHadi Asyrafi 
48913d33d52SHadi Asyrafi 	case INTEL_SIP_SMC_REG_WRITE:
490aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		status = intel_secure_reg_write(x1, (uint32_t)x2, &retval);
491aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		SMC_RET3(handle, status, retval, x1);
49213d33d52SHadi Asyrafi 
49313d33d52SHadi Asyrafi 	case INTEL_SIP_SMC_REG_UPDATE:
49413d33d52SHadi Asyrafi 		status = intel_secure_reg_update(x1, (uint32_t)x2,
495aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 						 (uint32_t)x3, &retval);
496aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 		SMC_RET3(handle, status, retval, x1);
497c76d4239SHadi Asyrafi 
498e1f97d9cSHadi Asyrafi 	case INTEL_SIP_SMC_RSU_STATUS:
499e1f97d9cSHadi Asyrafi 		status = intel_rsu_status(rsu_respbuf,
500e1f97d9cSHadi Asyrafi 					ARRAY_SIZE(rsu_respbuf));
501e1f97d9cSHadi Asyrafi 		if (status) {
502e1f97d9cSHadi Asyrafi 			SMC_RET1(handle, status);
503e1f97d9cSHadi Asyrafi 		} else {
504e1f97d9cSHadi Asyrafi 			SMC_RET4(handle, rsu_respbuf[0], rsu_respbuf[1],
505e1f97d9cSHadi Asyrafi 					rsu_respbuf[2], rsu_respbuf[3]);
506e1f97d9cSHadi Asyrafi 		}
507e1f97d9cSHadi Asyrafi 
508e1f97d9cSHadi Asyrafi 	case INTEL_SIP_SMC_RSU_UPDATE:
509e1f97d9cSHadi Asyrafi 		status = intel_rsu_update(x1);
510e1f97d9cSHadi Asyrafi 		SMC_RET1(handle, status);
511e1f97d9cSHadi Asyrafi 
512e1f97d9cSHadi Asyrafi 	case INTEL_SIP_SMC_RSU_NOTIFY:
513e1f97d9cSHadi Asyrafi 		status = intel_rsu_notify(x1);
514e1f97d9cSHadi Asyrafi 		SMC_RET1(handle, status);
515e1f97d9cSHadi Asyrafi 
516e1f97d9cSHadi Asyrafi 	case INTEL_SIP_SMC_RSU_RETRY_COUNTER:
517e1f97d9cSHadi Asyrafi 		status = intel_rsu_retry_counter((uint32_t *)rsu_respbuf,
518aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 						ARRAY_SIZE(rsu_respbuf), &retval);
519e1f97d9cSHadi Asyrafi 		if (status) {
520e1f97d9cSHadi Asyrafi 			SMC_RET1(handle, status);
521e1f97d9cSHadi Asyrafi 		} else {
522aad868b4SAbdul Halim, Muhammad Hadi Asyrafi 			SMC_RET2(handle, status, retval);
523e1f97d9cSHadi Asyrafi 		}
524e1f97d9cSHadi Asyrafi 
5250c5d62adSHadi Asyrafi 	case INTEL_SIP_SMC_MBOX_SEND_CMD:
5260c5d62adSHadi Asyrafi 		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
5270c5d62adSHadi Asyrafi 		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
528ea9b9627SAbdul Halim, Muhammad Hadi Asyrafi 		status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4,
5290c5d62adSHadi Asyrafi 					     (uint32_t *)x5, x6, &mbox_status,
5300c5d62adSHadi Asyrafi 					     &len_in_resp);
531*108514ffSSieu Mun Tang 		SMC_RET3(handle, status, mbox_status, len_in_resp);
5320c5d62adSHadi Asyrafi 
533c76d4239SHadi Asyrafi 	default:
534c76d4239SHadi Asyrafi 		return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
535c76d4239SHadi Asyrafi 			cookie, handle, flags);
536c76d4239SHadi Asyrafi 	}
537c76d4239SHadi Asyrafi }
538c76d4239SHadi Asyrafi 
539c76d4239SHadi Asyrafi DECLARE_RT_SVC(
540c76d4239SHadi Asyrafi 	socfpga_sip_svc,
541c76d4239SHadi Asyrafi 	OEN_SIP_START,
542c76d4239SHadi Asyrafi 	OEN_SIP_END,
543c76d4239SHadi Asyrafi 	SMC_TYPE_FAST,
544c76d4239SHadi Asyrafi 	NULL,
545c76d4239SHadi Asyrafi 	sip_smc_handler
546c76d4239SHadi Asyrafi );
547c76d4239SHadi Asyrafi 
548c76d4239SHadi Asyrafi DECLARE_RT_SVC(
549c76d4239SHadi Asyrafi 	socfpga_sip_svc_std,
550c76d4239SHadi Asyrafi 	OEN_SIP_START,
551c76d4239SHadi Asyrafi 	OEN_SIP_END,
552c76d4239SHadi Asyrafi 	SMC_TYPE_YIELD,
553c76d4239SHadi Asyrafi 	NULL,
554c76d4239SHadi Asyrafi 	sip_smc_handler
555c76d4239SHadi Asyrafi );
556