1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <stdlib.h>
32
33 #include "hcs_macro.h"
34 #include "hdf_config_macro.h"
35 #include "hdf_device_desc.h"
36 #include "hdf_log.h"
37 #include "i2c_core.h"
38 #include "i2c_if.h"
39 #include "osal_mutex.h"
40 #include "stm32f4xx_i2c.h"
41
42 #define HDF_LOG_TAG "hdf_i2c"
43
44 typedef enum {
45 I2C_HANDLE_NULL = 0,
46 I2C_HANDLE_1 = 1,
47 I2C_HANDLE_2 = 2,
48 I2C_HANDLE_3 = 3,
49 I2C_HANDLE_MAX = I2C_HANDLE_3
50 } I2C_HANDLE;
51
52 struct RealI2cResource {
53 uint8_t port;
54 uint8_t devMode;
55 uint32_t devAddr;
56 uint32_t speed;
57 struct OsalMutex mutex;
58 };
59
60 #define I2CT_FLAG_TIMEOUT ((uint32_t)0x1000)
61 #define I2CT_LONG_TIMEOUT ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))
62 static uint32_t I2CTimeout = I2CT_LONG_TIMEOUT;
63
64 static int32_t I2C_TIMEOUT_UserCallback(void);
65
66 static bool g_I2cEnableFlg[I2C_HANDLE_MAX] = {0};
67
68 static void HdfI2cInit(I2C_HANDLE i2cx, unsigned int i2cRate, unsigned int addr);
69 static int32_t HdfI2cWrite(I2C_HANDLE i2cx, unsigned char devAddr, const unsigned char *buf, unsigned int len);
70 static int32_t HdfI2cRead(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len);
71
72 static int32_t I2cDriverBind(struct HdfDeviceObject *device);
73 static int32_t I2cDriverInit(struct HdfDeviceObject *device);
74 static void I2cDriverRelease(struct HdfDeviceObject *device);
75 static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
76
77 struct HdfDriverEntry gI2cHdfDriverEntry = {
78 .moduleVersion = 1,
79 .moduleName = "ST_I2C_MODULE_HDF",
80 .Bind = I2cDriverBind,
81 .Init = I2cDriverInit,
82 .Release = I2cDriverRelease,
83 };
84 HDF_INIT(gI2cHdfDriverEntry);
85
86 struct I2cMethod gI2cHostMethod = {
87 .transfer = I2cDataTransfer,
88 };
89
90 #define I2C_FIND_CONFIG(node, name, resource) \
91 do { \
92 if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
93 (resource)->port = HCS_PROP(node, port); \
94 (resource)->devMode = HCS_PROP(node, devMode); \
95 (resource)->devAddr = HCS_PROP(node, devAddr); \
96 (resource)->speed = HCS_PROP(node, speed); \
97 result = HDF_SUCCESS; \
98 } \
99 } while (0)
100
101 #define PLATFORM_I2C_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), i2c_config)
GetI2cDeviceResource(struct RealI2cResource * i2cResource,const char * deviceMatchAttr)102 static uint32_t GetI2cDeviceResource(struct RealI2cResource *i2cResource, const char *deviceMatchAttr)
103 {
104 int32_t result = HDF_FAILURE;
105 struct RealI2cResource *resource = NULL;
106 if (i2cResource == NULL || deviceMatchAttr == NULL) {
107 HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
108 return HDF_ERR_INVALID_PARAM;
109 }
110 resource = i2cResource;
111 #if HCS_NODE_HAS_PROP(HCS_NODE(HCS_ROOT, platform), i2c_config)
112 HCS_FOREACH_CHILD_VARGS(PLATFORM_I2C_CONFIG, I2C_FIND_CONFIG, deviceMatchAttr, resource);
113 #endif
114 if (result != HDF_SUCCESS) {
115 HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
116 } else {
117 HdfI2cInit(i2cResource->port, i2cResource->speed, i2cResource->devAddr);
118 }
119 return result;
120 }
121
AttachI2cDevice(struct I2cCntlr * host,const struct HdfDeviceObject * device)122 static int32_t AttachI2cDevice(struct I2cCntlr *host, const struct HdfDeviceObject *device)
123 {
124 int32_t ret = HDF_FAILURE;
125
126 if (host == NULL || device == NULL) {
127 HDF_LOGE("[%s]: param is NULL\r\n", __func__);
128 return HDF_ERR_INVALID_PARAM;
129 }
130
131 struct RealI2cResource *i2cResource = (struct RealI2cResource *)OsalMemAlloc(sizeof(struct RealI2cResource));
132 if (i2cResource == NULL) {
133 HDF_LOGE("[%s]: OsalMemAlloc RealI2cResource fail\r\n", __func__);
134 return HDF_ERR_MALLOC_FAIL;
135 }
136 (void)memset_s(i2cResource, sizeof(struct RealI2cResource), 0, sizeof(struct RealI2cResource));
137
138 ret = GetI2cDeviceResource(i2cResource, device->deviceMatchAttr);
139 if (ret != HDF_SUCCESS) {
140 OsalMemFree(i2cResource);
141 return HDF_FAILURE;
142 }
143
144 host->busId = i2cResource->port;
145 host->priv = i2cResource;
146
147 return HDF_SUCCESS;
148 }
149
I2cDataTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)150 static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
151 {
152 int ret;
153
154 if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) {
155 HDF_LOGE("[%s]: I2cDataTransfer param is NULL\r\n", __func__);
156 return HDF_ERR_INVALID_PARAM;
157 }
158
159 if (count <= 0) {
160 HDF_LOGE("[%s]: I2cDataTransfer count err\r\n", __func__);
161 return HDF_ERR_INVALID_PARAM;
162 }
163
164 struct RealI2cResource *device = (struct I2cDevice *)cntlr->priv;
165 struct I2cMsg *msg = NULL;
166 if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
167 HDF_LOGE("[%s]: OsalMutexLock fail\r\n", __func__);
168 return HDF_ERR_TIMEOUT;
169 }
170
171 for (int32_t i = 0; i < count; i++) {
172 msg = &msgs[i];
173 if (msg->flags == I2C_FLAG_READ) {
174 ret = HdfI2cRead(device->port, msg->addr, msg->buf, msg->len);
175 } else {
176 ret = HdfI2cWrite(device->port, msg->addr, msg->buf, msg->len);
177 }
178
179 if (ret != HDF_SUCCESS) {
180 OsalMutexUnlock(&device->mutex);
181 return i;
182 }
183 }
184
185 OsalMutexUnlock(&device->mutex);
186
187 return count;
188 }
189
I2cDriverBind(struct HdfDeviceObject * device)190 static int32_t I2cDriverBind(struct HdfDeviceObject *device)
191 {
192 if (device == NULL) {
193 HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__);
194 return HDF_FAILURE;
195 }
196 return HDF_SUCCESS;
197 }
198
I2cDriverInit(struct HdfDeviceObject * device)199 static int32_t I2cDriverInit(struct HdfDeviceObject *device)
200 {
201 int32_t ret = HDF_FAILURE;
202 struct I2cCntlr *host = NULL;
203 if (device == NULL) {
204 HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__);
205 return HDF_ERR_INVALID_PARAM;
206 }
207
208 host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr));
209 if (host == NULL) {
210 HDF_LOGE("[%s]: malloc host is NULL\r\n", __func__);
211 return HDF_ERR_MALLOC_FAIL;
212 }
213
214 (void)memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr));
215 host->ops = &gI2cHostMethod;
216 device->priv = (void *)host;
217
218 ret = AttachI2cDevice(host, device);
219 if (ret != HDF_SUCCESS) {
220 HDF_LOGE("[%s]: AttachI2cDevice error, ret = %d\r\n", __func__, ret);
221 I2cDriverRelease(device);
222 return HDF_DEV_ERR_ATTACHDEV_FAIL;
223 }
224
225 ret = I2cCntlrAdd(host);
226 if (ret != HDF_SUCCESS) {
227 I2cDriverRelease(device);
228 return HDF_FAILURE;
229 }
230
231 return HDF_SUCCESS;
232 }
233
I2cDriverRelease(struct HdfDeviceObject * device)234 static void I2cDriverRelease(struct HdfDeviceObject *device)
235 {
236 if (device == NULL) {
237 HDF_LOGE("%s: device is NULL\r\n", __func__);
238 return;
239 }
240
241 struct I2cCntlr *i2cCntrl = device->priv;
242 if (i2cCntrl == NULL || i2cCntrl->priv == NULL) {
243 HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__);
244 return;
245 }
246 i2cCntrl->ops = NULL;
247 struct RealI2cResource *i2cDevice = (struct I2cDevice *)i2cCntrl->priv;
248 OsalMemFree(i2cCntrl);
249
250 if (i2cDevice != NULL) {
251 OsalMutexDestroy(&i2cDevice->mutex);
252 OsalMemFree(i2cDevice);
253 }
254 }
255
GetI2cHandlerMatch(I2C_HANDLE i2cx)256 static I2C_TypeDef *GetI2cHandlerMatch(I2C_HANDLE i2cx)
257 {
258 if (i2cx > I2C_HANDLE_MAX) {
259 printf("ERR: GetLLI2cClkMatch fail, param match fail\r\n");
260 return NULL;
261 }
262
263 switch (i2cx) {
264 case I2C_HANDLE_1:
265 return (I2C_TypeDef *)I2C1;
266 case I2C_HANDLE_2:
267 return (I2C_TypeDef *)I2C2;
268 case I2C_HANDLE_3:
269 return (I2C_TypeDef *)I2C3;
270 default:
271 printf("ERR: GetI2cClkMatch fail, handler match fail\r\n");
272 return NULL;
273 }
274 }
275
EnableI2cClock(const I2C_TypeDef * i2cx)276 static bool EnableI2cClock(const I2C_TypeDef *i2cx)
277 {
278 if (i2cx == I2C1) {
279 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
280 return true;
281 } else if (i2cx == I2C2) {
282 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
283 return true;
284 } else if (i2cx == I2C3) {
285 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C3, ENABLE);
286 return true;
287 } else {
288 printf("EnableI2cClock fail, i2cx match fail\r\n");
289 return false;
290 }
291 }
292
HdfI2cInit(I2C_HANDLE i2cx,unsigned int i2cRate,unsigned int addr)293 static void HdfI2cInit(I2C_HANDLE i2cx, unsigned int i2cRate, unsigned int addr)
294 {
295 I2C_InitTypeDef I2C_InitStructure = {0};
296 I2C_TypeDef *myI2c = GetI2cHandlerMatch(i2cx);
297 if (myI2c == NULL) {
298 return;
299 }
300
301 EnableI2cClock(myI2c);
302 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
303 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
304 I2C_InitStructure.I2C_OwnAddress1 = addr;
305 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
306 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
307 I2C_InitStructure.I2C_ClockSpeed = i2cRate;
308 I2C_Init(myI2c, &I2C_InitStructure);
309 I2C_Cmd(myI2c, ENABLE);
310 I2C_AcknowledgeConfig(myI2c, ENABLE);
311
312 g_I2cEnableFlg[i2cx] = true;
313 }
314
I2C_TIMEOUT_UserCallback(void)315 static int32_t I2C_TIMEOUT_UserCallback(void)
316 {
317 /* Block communication and all processes */
318 printf("I2C timeout!\r\n");
319 return HDF_FAILURE;
320 }
321
HdfI2cWrite(I2C_HANDLE i2cx,unsigned char devAddr,const unsigned char * buf,unsigned int len)322 static int32_t HdfI2cWrite(I2C_HANDLE i2cx, unsigned char devAddr, const unsigned char *buf, unsigned int len)
323 {
324 if (g_I2cEnableFlg[i2cx] != true) {
325 printf("I2C_WriteByte err, Please initialize first!");
326 return HDF_FAILURE;
327 }
328
329 I2C_TypeDef *myI2c = GetI2cHandlerMatch(i2cx);
330 if (myI2c == NULL) {
331 return HDF_FAILURE;
332 }
333
334 I2CTimeout = I2CT_LONG_TIMEOUT;
335 while (I2C_GetFlagStatus(myI2c, I2C_FLAG_BUSY) == SET) {
336 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
337 }
338
339 I2C_GenerateSTART(myI2c, ENABLE);
340
341 I2CTimeout = I2CT_FLAG_TIMEOUT;
342 while (I2C_CheckEvent(myI2c, I2C_EVENT_MASTER_MODE_SELECT) == 0) {
343 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
344 }
345
346 I2C_Send7bitAddress(myI2c, devAddr, I2C_Direction_Transmitter);
347
348 I2CTimeout = I2CT_FLAG_TIMEOUT;
349 while (I2C_CheckEvent(myI2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == 0) {
350 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
351 }
352
353 I2C_GetLastEvent(myI2c);
354
355 for (unsigned int i = 0; i < len; i++) {
356 I2C_SendData(myI2c, buf[i]);
357
358 I2CTimeout = I2CT_FLAG_TIMEOUT;
359 while (I2C_CheckEvent(myI2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == 0) {
360 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
361 }
362 }
363
364 I2C_GenerateSTOP(myI2c, ENABLE);
365 return HDF_SUCCESS;
366 }
367
HdfI2cRead(I2C_HANDLE i2cx,unsigned char devAddr,unsigned char * buf,unsigned int len)368 static int32_t HdfI2cRead(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len)
369 {
370 if (g_I2cEnableFlg[i2cx] != true) {
371 printf("I2C_ReadByte err, Please initialize first!");
372 return HDF_FAILURE;
373 }
374
375 I2C_TypeDef *myI2c = GetI2cHandlerMatch(i2cx);
376 if (myI2c == NULL) {
377 return HDF_FAILURE;
378 }
379
380 I2CTimeout = I2CT_LONG_TIMEOUT;
381
382 while (I2C_GetFlagStatus(myI2c, I2C_FLAG_BUSY) == SET) {
383 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
384 }
385
386 I2C_GenerateSTART(myI2c, ENABLE);
387
388 I2CTimeout = I2CT_FLAG_TIMEOUT;
389 while (I2C_CheckEvent(myI2c, I2C_EVENT_MASTER_MODE_SELECT) == 0) {
390 if ((I2CTimeout--) ==0) return I2C_TIMEOUT_UserCallback();
391 }
392
393 I2C_Send7bitAddress(myI2c, devAddr, I2C_Direction_Receiver);
394
395 I2CTimeout = I2CT_FLAG_TIMEOUT;
396 while (I2C_CheckEvent(myI2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == 0) {
397 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
398 }
399
400 for (unsigned int i = 0; i < len; i++) {
401 if (i == len - 1) {
402 I2C_AcknowledgeConfig(myI2c, DISABLE);
403 I2C_GenerateSTOP(myI2c, ENABLE);
404 }
405
406 I2CTimeout = I2CT_LONG_TIMEOUT;
407 while (I2C_CheckEvent(myI2c, I2C_EVENT_MASTER_BYTE_RECEIVED) == 0) {
408 if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback();
409 }
410
411 buf[i] = I2C_ReceiveData(myI2c);
412 }
413
414 I2C_AcknowledgeConfig(myI2c, ENABLE);
415 return HDF_SUCCESS;
416 }
417