1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Texas Instruments System Control Interface Driver
4  *
5  * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
6  *	Manorit Chawdhry <m-chawdhry@ti.com>
7  */
8 
9 #include <drivers/ti_sci.h>
10 #include <inttypes.h>
11 #include <k3/otp_keywriting_ta.h>
12 #include <kernel/pseudo_ta.h>
13 
write_otp_row(uint32_t param_types,TEE_Param params[4])14 static TEE_Result write_otp_row(uint32_t param_types, TEE_Param params[4])
15 {
16 	TEE_Result ret = TEE_SUCCESS;
17 	const uint32_t exp_param_types =
18 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
19 				TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE,
20 				TEE_PARAM_TYPE_NONE);
21 
22 	/*
23 	 * Safely get the invocation parameters
24 	 */
25 	if (param_types != exp_param_types)
26 		return TEE_ERROR_BAD_PARAMETERS;
27 
28 	ret = ti_sci_write_otp_row(params[0].value.a, params[1].value.a,
29 				   params[1].value.b);
30 	if (ret)
31 		return ret;
32 
33 	DMSG("Written the value: 0x%08"PRIx32, params[1].value.a);
34 
35 	return TEE_SUCCESS;
36 }
37 
read_otp_mmr(uint32_t param_types,TEE_Param params[4])38 static TEE_Result read_otp_mmr(uint32_t param_types, TEE_Param params[4])
39 {
40 	TEE_Result ret = TEE_SUCCESS;
41 	const uint32_t exp_param_types =
42 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
43 				TEE_PARAM_TYPE_VALUE_OUTPUT,
44 				TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE);
45 
46 	/*
47 	 * Safely get the invocation parameters
48 	 */
49 	if (param_types != exp_param_types)
50 		return TEE_ERROR_BAD_PARAMETERS;
51 
52 	ret = ti_sci_read_otp_mmr(params[0].value.a, &params[1].value.a);
53 	if (ret)
54 		return ret;
55 
56 	DMSG("Got the value: 0x%08"PRIx32, params[1].value.a);
57 
58 	return TEE_SUCCESS;
59 }
60 
lock_otp_row(uint32_t param_types,TEE_Param params[4])61 static TEE_Result lock_otp_row(uint32_t param_types, TEE_Param params[4])
62 {
63 	TEE_Result ret = TEE_SUCCESS;
64 	int hw_write_lock = 0;
65 	int hw_read_lock = 0;
66 	int soft_lock = 0;
67 	const uint32_t exp_param_types =
68 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE,
69 				TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE);
70 
71 	/*
72 	 * Safely get the invocation parameters
73 	 */
74 	if (param_types != exp_param_types)
75 		return TEE_ERROR_BAD_PARAMETERS;
76 
77 	if (params[0].value.b & K3_OTP_KEYWRITING_SOFT_LOCK)
78 		soft_lock = 0x5A;
79 	if (params[0].value.b & K3_OTP_KEYWRITING_HW_READ_LOCK)
80 		hw_read_lock = 0x5A;
81 	if (params[0].value.b & K3_OTP_KEYWRITING_HW_WRITE_LOCK)
82 		hw_write_lock = 0x5A;
83 
84 	DMSG("hw_write_lock: 0x%#x", hw_write_lock);
85 	DMSG("hw_read_lock: 0x%#x", hw_read_lock);
86 	DMSG("soft_lock: 0x%#x", soft_lock);
87 
88 	ret = ti_sci_lock_otp_row(params[0].value.a, hw_write_lock,
89 				  hw_read_lock, soft_lock);
90 
91 	if (ret)
92 		return ret;
93 
94 	DMSG("Locked the row: 0x%08"PRIx32, params[1].value.a);
95 
96 	return TEE_SUCCESS;
97 }
98 
invoke_command(void * session __unused,uint32_t command,uint32_t param_types,TEE_Param params[4])99 static TEE_Result invoke_command(void *session __unused,
100 				 uint32_t command, uint32_t param_types,
101 				 TEE_Param params[4])
102 {
103 	switch (command) {
104 	case TA_OTP_KEYWRITING_CMD_READ_MMR:
105 		return read_otp_mmr(param_types, params);
106 	case TA_OTP_KEYWRITING_CMD_WRITE_ROW:
107 		return write_otp_row(param_types, params);
108 	case TA_OTP_KEYWRITING_CMD_LOCK_ROW:
109 		return lock_otp_row(param_types, params);
110 	default:
111 		EMSG("Command ID 0x%"PRIx32" is not supported", command);
112 		return TEE_ERROR_NOT_SUPPORTED;
113 	}
114 }
115 
116 pseudo_ta_register(.uuid = PTA_K3_OTP_KEYWRITING_UUID,
117 		   .name = PTA_K3_OTP_KEYWRITING_NAME,
118 		   .flags = PTA_DEFAULT_FLAGS,
119 		   .invoke_command_entry_point = invoke_command);
120