• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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