1 /*
2 * Copyright 2018-2021, NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #include <string.h>
9 #include <assert.h>
10 #include <string.h>
11
12 #include "fsl_common.h"
13
14 #include "srtm_heap.h"
15 #include "srtm_list.h"
16 #include "srtm_dispatcher.h"
17 #include "srtm_service.h"
18 #include "srtm_service_struct.h"
19 #include "srtm_i2c_service.h"
20 #include "srtm_message.h"
21 #include "srtm_message_struct.h"
22 #include "srtm_channel.h"
23 #include "srtm_channel_struct.h"
24
25 /*******************************************************************************
26 * Definitions
27 ******************************************************************************/
28 /* Protocol definition */
29 #define SRTM_I2C_CATEGORY (0x9U)
30 #define SRTM_I2C_VERSION (0x0100U)
31
32 #define SRTM_I2C_RETURN_CODE_SUCEESS (0x0U)
33 #define SRTM_I2C_RETURN_CODE_FAIL (0x1U)
34 #define SRTM_I2C_RETURN_CODE_UNSUPPORTED (0x2U)
35
36 typedef struct _srtm_i2c_service
37 {
38 struct _srtm_service service;
39 srtm_i2c_adapter_t adapter;
40 } *srtm_i2c_service_t;
41
42 static srtm_status_t SRTM_I2CService_Request(srtm_service_t service, srtm_request_t request);
43 static srtm_status_t SRTM_I2CService_Notify(srtm_service_t service, srtm_notification_t notif);
44
SRTM_I2C_SearchBus(srtm_i2c_adapter_t adapter,uint8_t busID)45 static i2c_bus_t SRTM_I2C_SearchBus(srtm_i2c_adapter_t adapter, uint8_t busID)
46 {
47 uint8_t bus_num = adapter->bus_structure.bus_num;
48 i2c_bus_t busArray = adapter->bus_structure.buses;
49 uint8_t i;
50
51 for (i = 0U; i != bus_num; i++)
52 {
53 if (busArray[i].bus_id == busID)
54 {
55 break;
56 }
57 }
58
59 return (i == bus_num) ? NULL : (busArray + i);
60 }
61
SRTM_I2CService_ReadBus(srtm_service_t service,uint8_t busID,uint16_t slaveAddr,uint8_t * buf,uint16_t len,uint16_t flags)62 static srtm_status_t SRTM_I2CService_ReadBus(
63 srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len, uint16_t flags)
64 {
65 srtm_i2c_service_t handle = (srtm_i2c_service_t)(void *)service;
66 srtm_i2c_adapter_t adapter = handle->adapter;
67 i2c_bus_t targetBus;
68 uint32_t base_addr;
69 uint8_t switch_index;
70 uint16_t switch_addr;
71 srtm_i2c_switch_channel switch_channel;
72 srtm_status_t status;
73 srtm_i2c_type_t type;
74 i2c_switch_t switch_inst;
75
76 targetBus = SRTM_I2C_SearchBus(adapter, busID);
77 base_addr = targetBus->base_addr;
78 switch_index = targetBus->switch_idx;
79 type = targetBus->type;
80 /*
81 * Switch Channel
82 */
83 if (switch_index < adapter->bus_structure.switch_num)
84 {
85 switch_inst = &adapter->bus_structure.switches[switch_index];
86 switch_addr = switch_inst->slaveAddr;
87 switch_channel = targetBus->switch_channel;
88 if (switch_inst->cur_channel != switch_channel)
89 {
90 (void)adapter->switchchannel(adapter, base_addr, type, switch_addr, switch_channel);
91 switch_inst->cur_channel = switch_channel;
92 }
93 }
94 /*
95 * Read
96 */
97 status = adapter->read(adapter, base_addr, type, slaveAddr, buf, len, flags); // APP_SRTM_I2C_Read
98 return status;
99 }
100
SRTM_I2CService_WriteBus(srtm_service_t service,uint8_t busID,uint16_t slaveAddr,uint8_t * buf,uint16_t len,uint16_t flags)101 static srtm_status_t SRTM_I2CService_WriteBus(
102 srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len, uint16_t flags)
103 {
104 srtm_i2c_service_t handle = (srtm_i2c_service_t)(void *)service;
105 srtm_i2c_adapter_t adapter = handle->adapter;
106 i2c_bus_t targetBus;
107 uint32_t base_addr;
108 uint8_t switch_index;
109 uint16_t switch_addr;
110 srtm_i2c_switch_channel switch_channel;
111 srtm_status_t status;
112 srtm_i2c_type_t type;
113 i2c_switch_t switch_inst;
114
115 targetBus = SRTM_I2C_SearchBus(adapter, busID);
116 base_addr = targetBus->base_addr;
117 switch_index = targetBus->switch_idx;
118 type = targetBus->type;
119 /*
120 * Switch Channel
121 */
122 if (switch_index < adapter->bus_structure.switch_num)
123 {
124 switch_inst = &adapter->bus_structure.switches[switch_index];
125 switch_addr = switch_inst->slaveAddr;
126 switch_channel = targetBus->switch_channel;
127 if (switch_inst->cur_channel != switch_channel)
128 {
129 (void)adapter->switchchannel(adapter, base_addr, type, switch_addr, switch_channel);
130 switch_inst->cur_channel = switch_channel;
131 }
132 }
133 /*
134 * Write
135 */
136 status = adapter->write(adapter, base_addr, type, slaveAddr, buf, len, flags); // APP_SRTM_I2C_Write
137 return status;
138 }
139
SRTM_I2CService_Create(srtm_i2c_adapter_t adapter)140 srtm_service_t SRTM_I2CService_Create(srtm_i2c_adapter_t adapter)
141 {
142 srtm_i2c_service_t handle;
143
144 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
145 handle = (srtm_i2c_service_t)SRTM_Heap_Malloc(sizeof(struct _srtm_i2c_service));
146 assert(handle);
147
148 adapter->service = &handle->service;
149 handle->adapter = adapter;
150
151 SRTM_List_Init(&handle->service.node);
152 handle->service.dispatcher = NULL;
153 handle->service.category = SRTM_I2C_CATEGORY;
154 handle->service.destroy = SRTM_I2CService_Destroy;
155 handle->service.request = SRTM_I2CService_Request;
156 handle->service.notify = SRTM_I2CService_Notify;
157
158 return &handle->service;
159 }
160
SRTM_I2CService_Destroy(srtm_service_t service)161 void SRTM_I2CService_Destroy(srtm_service_t service)
162 {
163 srtm_i2c_service_t handle = (srtm_i2c_service_t)(void *)service;
164
165 assert(service);
166
167 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
168
169 /* Service must be unregistered from dispatcher before destroy */
170 assert(SRTM_List_IsEmpty(&service->node));
171
172 SRTM_Heap_Free(handle);
173 }
174
SRTM_I2CService_Reset(srtm_service_t service,srtm_peercore_t core)175 void SRTM_I2CService_Reset(srtm_service_t service, srtm_peercore_t core)
176 {
177 assert(service);
178
179 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
180 }
181
SRTM_I2CService_Request(srtm_service_t service,srtm_request_t request)182 static srtm_status_t SRTM_I2CService_Request(srtm_service_t service, srtm_request_t request)
183 {
184 srtm_status_t status;
185 srtm_channel_t channel;
186 uint8_t command;
187 uint32_t payloadLen;
188 srtm_response_t response;
189 struct _srtm_i2c_payload *i2cReq;
190 struct _srtm_i2c_payload *i2cResp;
191
192 assert(service->dispatcher);
193
194 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
195
196 channel = SRTM_CommMessage_GetChannel(request);
197 command = SRTM_CommMessage_GetCommand(request);
198 i2cReq = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(request);
199 payloadLen = SRTM_CommMessage_GetPayloadLen(request);
200 (void)payloadLen; /* try to fix warning: variable 'payloadLen' set but not used */
201 assert(i2cReq);
202 assert((uint32_t)(i2cReq->len + sizeof(struct _srtm_i2c_payload) - sizeof(i2cReq->data[0])) <= payloadLen);
203
204 response =
205 SRTM_Response_Create(channel, SRTM_I2C_CATEGORY, SRTM_I2C_VERSION, command,
206 (uint16_t)((sizeof(struct _srtm_i2c_payload) - sizeof(i2cReq->data[0])) + i2cReq->len));
207 if (response == NULL)
208 {
209 return SRTM_Status_OutOfMemory;
210 }
211
212 i2cResp = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(response);
213
214 status = SRTM_Service_CheckVersion(service, request, SRTM_I2C_VERSION);
215 if (status != SRTM_Status_Success)
216 {
217 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: format error!\r\n", __func__);
218 i2cResp->retCode = SRTM_I2C_RETURN_CODE_UNSUPPORTED;
219 }
220 else
221 {
222 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO,
223 "SRTM receive I2C request:cmd=%x, busID %d, slaveAddr 0x%x!, data %d bytes\r\n", command,
224 i2cReq->busID, i2cReq->slaveAddr, i2cReq->len);
225 (void)memcpy(i2cResp, i2cReq,
226 (sizeof(struct _srtm_i2c_payload) - sizeof(i2cReq->data[0]) + (size_t)i2cReq->len));
227
228 switch (command)
229 {
230 case (uint8_t)SRTM_I2C_CMD_READ:
231 status = SRTM_I2CService_ReadBus(service, i2cResp->busID, i2cResp->slaveAddr, i2cResp->data,
232 i2cReq->len, i2cReq->flags);
233 i2cResp->retCode =
234 status == SRTM_Status_Success ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
235 break;
236 case (uint8_t)SRTM_I2C_CMD_WRITE:
237 status = SRTM_I2CService_WriteBus(service, i2cResp->busID, i2cResp->slaveAddr, i2cResp->data,
238 i2cReq->len, i2cReq->flags);
239 i2cResp->retCode =
240 status == SRTM_Status_Success ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
241 break;
242 default:
243 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__, command);
244 assert(false);
245 break;
246 }
247 }
248
249 return SRTM_Dispatcher_DeliverResponse(service->dispatcher, response);
250 }
251
SRTM_I2CService_Notify(srtm_service_t service,srtm_notification_t notif)252 static srtm_status_t SRTM_I2CService_Notify(srtm_service_t service, srtm_notification_t notif)
253 {
254 SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__,
255 SRTM_CommMessage_GetCommand(notif));
256
257 return SRTM_Status_ServiceNotFound;
258 }
259
SRTM_I2C_HandleBusRead(srtm_dispatcher_t dispatcher,void * param1,void * param2)260 static void SRTM_I2C_HandleBusRead(srtm_dispatcher_t dispatcher, void *param1, void *param2)
261 {
262 srtm_status_t status;
263 srtm_i2c_payload_t i2c_payload = (srtm_i2c_payload_t)param1;
264 srtm_service_t service = (srtm_service_t)param2;
265 status = SRTM_I2CService_ReadBus(service, i2c_payload->busID, i2c_payload->slaveAddr, i2c_payload->data,
266 (uint8_t)i2c_payload->len, i2c_payload->flags);
267 i2c_payload->retCode = (status == SRTM_Status_Success) ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
268 }
269
SRTM_I2C_HandleBusWrite(srtm_dispatcher_t dispatcher,void * param1,void * param2)270 static void SRTM_I2C_HandleBusWrite(srtm_dispatcher_t dispatcher, void *param1, void *param2)
271 {
272 srtm_status_t status;
273 srtm_i2c_payload_t i2c_payload = (srtm_i2c_payload_t)param1;
274 srtm_service_t service = (srtm_service_t)param2;
275 status = SRTM_I2CService_WriteBus(service, i2c_payload->busID, i2c_payload->slaveAddr, i2c_payload->data,
276 (uint8_t)i2c_payload->len, i2c_payload->flags);
277 i2c_payload->retCode = (status == SRTM_Status_Success) ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
278 }
279
SRTM_I2C_RequestBusRead(srtm_service_t service,uint8_t busID,uint16_t slaveAddr,uint8_t * buf,uint16_t len)280 srtm_status_t SRTM_I2C_RequestBusRead(
281 srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len)
282 {
283 srtm_request_t request;
284 srtm_status_t status;
285 srtm_i2c_payload_t i2cReq;
286 srtm_procedure_t proc;
287 /*
288 * Allocate an SRTM message and copy necessary information
289 */
290 request = SRTM_Request_Create(NULL, SRTM_I2C_CATEGORY, SRTM_I2C_VERSION, (uint8_t)SRTM_I2C_CMD_READ,
291 (uint16_t)((sizeof(struct _srtm_i2c_payload) - sizeof(uint8_t)) + len));
292 i2cReq = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(request);
293 i2cReq->busID = busID;
294 i2cReq->slaveAddr = slaveAddr;
295 i2cReq->len = len;
296 (void)memset(i2cReq->data, 0, len);
297 /*
298 * Call proc in sync manner
299 */
300 proc = SRTM_Procedure_Create(SRTM_I2C_HandleBusRead, i2cReq, service);
301 (void)SRTM_Dispatcher_CallProc(service->dispatcher, proc, SRTM_WAIT_FOR_EVER); /*synchronized call*/
302 /*
303 * Save proc exec result
304 */
305 (void)memcpy(buf, i2cReq->data, len);
306 status = (srtm_status_t)i2cReq->retCode;
307 /*
308 * Clean the allocated SRTM object
309 */
310 SRTM_Procedure_Destroy(proc);
311 SRTM_Response_Destroy(request);
312
313 return status;
314 }
315
SRTM_I2C_RequestBusWrite(srtm_service_t service,uint8_t busID,uint16_t slaveAddr,uint8_t * buf,uint16_t len,uint8_t needStop)316 srtm_status_t SRTM_I2C_RequestBusWrite(
317 srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len, uint8_t needStop)
318 {
319 srtm_request_t request;
320 srtm_status_t status;
321 srtm_i2c_payload_t i2cReq;
322 srtm_procedure_t proc;
323 /*
324 * Allocate an SRTM message and copy necessary information
325 */
326 request = SRTM_Request_Create(NULL, SRTM_I2C_CATEGORY, SRTM_I2C_VERSION, (uint8_t)SRTM_I2C_CMD_WRITE,
327 (uint16_t)((sizeof(struct _srtm_i2c_payload) - sizeof(uint8_t)) + len));
328 i2cReq = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(request);
329 i2cReq->busID = busID;
330 i2cReq->slaveAddr = slaveAddr;
331 i2cReq->len = len;
332 i2cReq->flags = needStop > 0U ? (SRTM_I2C_FLAG_NEED_STOP) : 0U;
333
334 (void)memcpy(i2cReq->data, buf, len);
335 /*
336 * Call proc in sync manner
337 */
338 proc = SRTM_Procedure_Create(SRTM_I2C_HandleBusWrite, i2cReq, service);
339 (void)SRTM_Dispatcher_CallProc(service->dispatcher, proc, SRTM_WAIT_FOR_EVER); /*synchronized call*/
340 /*
341 * Save proc exec result
342 */
343 status = (srtm_status_t)i2cReq->retCode;
344 /*
345 * Clean the allocated SRTM object
346 */
347 SRTM_Procedure_Destroy(proc);
348 SRTM_Response_Destroy(request);
349
350 return status;
351 }
352