1 /*
2 * Copyright (c) 2022 Talkweb Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <stdlib.h>
10 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
11 #include "hcs_macro.h"
12 #include "hdf_config_macro.h"
13 #else
14 #include "device_resource_if.h"
15 #endif
16 #include "hdf_device_desc.h"
17 #include "hdf_log.h"
18 #include "i2c_core.h"
19 #include "i2c_if.h"
20 #include "osal_mutex.h"
21 #include "hdf_base_hal.h"
22 #include "stm32f4xx_ll_i2c.h"
23
24 #define HDF_LOG_TAG "hdf_i2c"
25
26 typedef enum {
27 I2C_HANDLE_NULL = 0,
28 I2C_HANDLE_1 = 1,
29 I2C_HANDLE_2 = 2,
30 I2C_HANDLE_3 = 3,
31 I2C_HANDLE_MAX = I2C_HANDLE_3
32 } I2C_HANDLE;
33
34 struct RealI2cResource {
35 uint8_t port;
36 uint8_t devMode;
37 uint32_t devAddr;
38 uint32_t speed;
39 struct OsalMutex mutex;
40 };
41
42 static bool g_I2cEnableFlg[I2C_HANDLE_MAX] = {0};
43
44 static void HdfI2cInit(I2C_HANDLE i2cx, unsigned int i2cRate, unsigned int addr);
45 static void HdfI2cWrite(I2C_HANDLE i2cx, unsigned char devAddr, const unsigned char *buf, unsigned int len);
46 static void HdfI2cRead(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len);
47
48 static int32_t I2cDriverBind(struct HdfDeviceObject *device);
49 static int32_t I2cDriverInit(struct HdfDeviceObject *device);
50 static void I2cDriverRelease(struct HdfDeviceObject *device);
51 static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
52
53 struct HdfDriverEntry gI2cHdfDriverEntry = {
54 .moduleVersion = 1,
55 .moduleName = "HDF_I2C",
56 .Bind = I2cDriverBind,
57 .Init = I2cDriverInit,
58 .Release = I2cDriverRelease,
59 };
60 HDF_INIT(gI2cHdfDriverEntry);
61
62 struct I2cMethod gI2cHostMethod = {
63 .transfer = I2cDataTransfer,
64 };
65
66 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
67 #define I2C_FIND_CONFIG(node, name, resource) \
68 do { \
69 if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
70 resource->port = HCS_PROP(node, port); \
71 resource->devMode = HCS_PROP(node, devMode); \
72 resource->devAddr = HCS_PROP(node, devAddr); \
73 resource->speed = HCS_PROP(node, speed); \
74 result = HDF_SUCCESS; \
75 } \
76 } while (0)
77 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
78 #define PLATFORM_I2C_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), i2c_config)
GetI2cDeviceResource(struct RealI2cResource * i2cResource,const char * deviceMatchAttr)79 static uint32_t GetI2cDeviceResource(struct RealI2cResource *i2cResource, const char *deviceMatchAttr)
80 {
81 int32_t result = HDF_FAILURE;
82 struct RealI2cResource *resource = NULL;
83 if (i2cResource == NULL || deviceMatchAttr == NULL) {
84 HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
85 return HDF_ERR_INVALID_PARAM;
86 }
87 resource = i2cResource;
88 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, i2c_config)
89 HCS_FOREACH_CHILD_VARGS(PLATFORM_I2C_CONFIG, I2C_FIND_CONFIG, deviceMatchAttr, resource);
90 #endif
91 if (result != HDF_SUCCESS) {
92 HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
93 } else {
94 HdfI2cInit(i2cResource->port, i2cResource->speed, i2cResource->devAddr);
95 }
96 return result;
97 }
98 #else
GetI2cDeviceResource(struct RealI2cResource * i2cResource,const struct DeviceResourceNode * resourceNode)99 static int32_t GetI2cDeviceResource(struct RealI2cResource *i2cResource, const struct DeviceResourceNode *resourceNode)
100 {
101 if (i2cResource == NULL || resourceNode == NULL) {
102 HDF_LOGE("[%s]: param is NULL\r\n", __func__);
103 return HDF_ERR_INVALID_PARAM;
104 }
105
106 struct DeviceResourceIface *dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
107 if (dri == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL || dri->GetUint32Array == NULL) {
108 HDF_LOGE("DeviceResourceIface is invalid\r\n");
109 return HDF_ERR_INVALID_OBJECT;
110 }
111
112 if (dri->GetUint8(resourceNode, "port", &i2cResource->port, 0) != HDF_SUCCESS) {
113 HDF_LOGE("i2c config port fail\r\n");
114 return HDF_FAILURE;
115 }
116
117 if (dri->GetUint8(resourceNode, "devMode", &i2cResource->devMode, 0) != HDF_SUCCESS) {
118 HDF_LOGE("i2c config devMode fail\r\n");
119 return HDF_FAILURE;
120 }
121
122 if (dri->GetUint32(resourceNode, "devAddr", &i2cResource->devAddr, 0) != HDF_SUCCESS) {
123 HDF_LOGE("i2c config devAddr fail\r\n");
124 return HDF_FAILURE;
125 }
126
127 if (dri->GetUint32(resourceNode, "speed", &i2cResource->speed, 0) != HDF_SUCCESS) {
128 HDF_LOGE("i2c config speed fail\r\n");
129 return HDF_FAILURE;
130 }
131
132 HdfI2cInit(i2cResource->port, i2cResource->speed, i2cResource->devAddr);
133
134 return HDF_SUCCESS;
135 }
136 #endif
137
AttachI2cDevice(struct I2cCntlr * host,const struct HdfDeviceObject * device)138 static int32_t AttachI2cDevice(struct I2cCntlr *host, const struct HdfDeviceObject *device)
139 {
140 int32_t ret = HDF_FAILURE;
141
142 if (host == NULL || device == NULL) {
143 HDF_LOGE("[%s]: param is NULL\r\n", __func__);
144 return HDF_ERR_INVALID_PARAM;
145 }
146
147 struct RealI2cResource *i2cResource = (struct RealI2cResource *)OsalMemAlloc(sizeof(struct RealI2cResource));
148 if (i2cResource == NULL) {
149 HDF_LOGE("[%s]: OsalMemAlloc RealI2cResource fail\r\n", __func__);
150 return HDF_ERR_MALLOC_FAIL;
151 }
152 (void)memset_s(i2cResource, sizeof(struct RealI2cResource), 0, sizeof(struct RealI2cResource));
153 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
154 ret = GetI2cDeviceResource(i2cResource, device->deviceMatchAttr);
155 #else
156 ret = GetI2cDeviceResource(i2cResource, device->property);
157 #endif
158 if (ret != HDF_SUCCESS) {
159 OsalMemFree(i2cResource);
160 return HDF_FAILURE;
161 }
162
163 host->busId = i2cResource->port;
164 host->priv = i2cResource;
165
166 return HDF_SUCCESS;
167 }
168
I2cDataTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)169 static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
170 {
171 if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) {
172 HDF_LOGE("[%s]: I2cDataTransfer param is NULL\r\n", __func__);
173 return HDF_ERR_INVALID_PARAM;
174 }
175
176 if (count <= 0) {
177 HDF_LOGE("[%s]: I2cDataTransfer count err\r\n", __func__);
178 return HDF_ERR_INVALID_PARAM;
179 }
180
181 struct RealI2cResource *device = (struct I2cDevice *)cntlr->priv;
182 struct I2cMsg *msg = NULL;
183 if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
184 HDF_LOGE("[%s]: OsalMutexLock fail\r\n", __func__);
185 return HDF_ERR_TIMEOUT;
186 }
187
188 for (int32_t i = 0; i < count; i++) {
189 msg = &msgs[i];
190 if (msg->flags == I2C_FLAG_READ) {
191 HdfI2cRead(device->port, msg->addr, msg->buf, msg->len);
192 } else {
193 HdfI2cWrite(device->port, msg->addr, msg->buf, msg->len);
194 }
195 }
196 OsalMutexUnlock(&device->mutex);
197
198 return count;
199 }
200
I2cDriverBind(struct HdfDeviceObject * device)201 static int32_t I2cDriverBind(struct HdfDeviceObject *device)
202 {
203 if (device == NULL) {
204 HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__);
205 return HDF_FAILURE;
206 }
207 return HDF_SUCCESS;
208 }
209
I2cDriverInit(struct HdfDeviceObject * device)210 static int32_t I2cDriverInit(struct HdfDeviceObject *device)
211 {
212 int32_t ret = HDF_FAILURE;
213 struct I2cCntlr *host = NULL;
214 if (device == NULL) {
215 HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__);
216 return HDF_ERR_INVALID_PARAM;
217 }
218
219 host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr));
220 if (host == NULL) {
221 HDF_LOGE("[%s]: malloc host is NULL\r\n", __func__);
222 return HDF_ERR_MALLOC_FAIL;
223 }
224
225 (void)memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr));
226 host->ops = &gI2cHostMethod;
227 device->priv = (void *)host;
228
229 ret = AttachI2cDevice(host, device);
230 if (ret != HDF_SUCCESS) {
231 HDF_LOGE("[%s]: AttachI2cDevice error, ret = %d\r\n", __func__, ret);
232 I2cDriverRelease(device);
233 return HDF_DEV_ERR_ATTACHDEV_FAIL;
234 }
235
236 ret = I2cCntlrAdd(host);
237 if (ret != HDF_SUCCESS) {
238 I2cDriverRelease(device);
239 return HDF_FAILURE;
240 }
241
242 return HDF_SUCCESS;
243 }
244
I2cDriverRelease(struct HdfDeviceObject * device)245 static void I2cDriverRelease(struct HdfDeviceObject *device)
246 {
247 if (device == NULL) {
248 HDF_LOGE("%s: device is NULL\r\n", __func__);
249 return;
250 }
251
252 struct I2cCntlr *i2cCntrl = device->priv;
253 if (i2cCntrl == NULL || i2cCntrl->priv == NULL) {
254 HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__);
255 return;
256 }
257 i2cCntrl->ops = NULL;
258 struct RealI2cResource *i2cDevice = (struct I2cDevice *)i2cCntrl->priv;
259 OsalMemFree(i2cCntrl);
260
261 if (i2cDevice != NULL) {
262 OsalMutexDestroy(&i2cDevice->mutex);
263 OsalMemFree(i2cDevice);
264 }
265 }
266
GetLLI2cHandlerMatch(I2C_HANDLE i2cx)267 static I2C_TypeDef *GetLLI2cHandlerMatch(I2C_HANDLE i2cx)
268 {
269 if (i2cx > I2C_HANDLE_MAX) {
270 printf("ERR: GetLLI2cClkMatch fail, param match fail\r\n");
271 return NULL;
272 }
273
274 switch (i2cx) {
275 case I2C_HANDLE_1:
276 return (I2C_TypeDef *)I2C1;
277 case I2C_HANDLE_2:
278 return (I2C_TypeDef *)I2C2;
279 case I2C_HANDLE_3:
280 return (I2C_TypeDef *)I2C3;
281 default:
282 printf("ERR: GetLLI2cClkMatch fail, handler match fail\r\n");
283 return NULL;
284 }
285 }
286
EnableLLI2cClock(const I2C_TypeDef * i2cx)287 static bool EnableLLI2cClock(const I2C_TypeDef *i2cx)
288 {
289 if (i2cx == I2C1) {
290 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
291 return true;
292 } else if (i2cx == I2C2) {
293 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C2);
294 return true;
295 } else if (i2cx == I2C3) {
296 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
297 return true;
298 } else {
299 printf("EnableI2cClock fail, i2cx match fail\r\n");
300 return false;
301 }
302 }
303
HdfI2cInit(I2C_HANDLE i2cx,unsigned int i2cRate,unsigned int addr)304 static void HdfI2cInit(I2C_HANDLE i2cx, unsigned int i2cRate, unsigned int addr)
305 {
306 LL_I2C_InitTypeDef I2C_InitStruct = {0};
307 I2C_TypeDef *myI2c = GetLLI2cHandlerMatch(i2cx);
308 if (myI2c == NULL) {
309 return;
310 }
311
312 EnableLLI2cClock(myI2c);
313 LL_I2C_DisableOwnAddress2(myI2c);
314 LL_I2C_DisableGeneralCall(myI2c);
315 LL_I2C_EnableClockStretching(myI2c);
316 I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
317 I2C_InitStruct.ClockSpeed = i2cRate;
318 I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
319 I2C_InitStruct.OwnAddress1 = addr;
320 I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
321 I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
322 LL_I2C_Init(myI2c, &I2C_InitStruct);
323 LL_I2C_SetOwnAddress2(myI2c, 0);
324
325 g_I2cEnableFlg[i2cx] = true;
326 }
327
HdfI2cWrite(I2C_HANDLE i2cx,unsigned char devAddr,const unsigned char * buf,unsigned int len)328 static void HdfI2cWrite(I2C_HANDLE i2cx, unsigned char devAddr, const unsigned char *buf, unsigned int len)
329 {
330 if (g_I2cEnableFlg[i2cx] != true) {
331 printf("I2C_WriteByte err, Please initialize first!");
332 return;
333 }
334
335 I2C_TypeDef *myI2c = GetLLI2cHandlerMatch(i2cx);
336 if (myI2c == NULL) {
337 return;
338 }
339
340 while (LL_I2C_IsActiveFlag_BUSY(myI2c)) { }
341
342 LL_I2C_GenerateStartCondition(myI2c);
343 while (LL_I2C_IsActiveFlag_SB(myI2c) == RESET) { }
344
345 LL_I2C_TransmitData8(myI2c, (devAddr << 1));
346 while (LL_I2C_IsActiveFlag_TXE(myI2c) == RESET) { }
347
348 LL_I2C_ClearFlag_ADDR(myI2c);
349 while (LL_I2C_IsActiveFlag_TXE(myI2c) == RESET) { }
350
351 for (unsigned int i = 0; i < len; i++) {
352 LL_I2C_TransmitData8(myI2c, buf[i]);
353 while (LL_I2C_IsActiveFlag_TXE(myI2c) == RESET) { }
354 }
355
356 LL_I2C_GenerateStopCondition(myI2c);
357 }
358
HdfI2cRead(I2C_HANDLE i2cx,unsigned char devAddr,unsigned char * buf,unsigned int len)359 static void HdfI2cRead(I2C_HANDLE i2cx, unsigned char devAddr, unsigned char *buf, unsigned int len)
360 {
361 if (g_I2cEnableFlg[i2cx] != true) {
362 printf("I2C_ReadByte err, Please initialize first!");
363 return;
364 }
365
366 I2C_TypeDef *myI2c = GetLLI2cHandlerMatch(i2cx);
367 if (myI2c == NULL) {
368 return;
369 }
370
371 while (LL_I2C_IsActiveFlag_BUSY(myI2c)) { }
372
373 LL_I2C_GenerateStartCondition(myI2c);
374 while (LL_I2C_IsActiveFlag_SB(myI2c) == RESET) { }
375
376 LL_I2C_TransmitData8(myI2c, ((devAddr << 1) | 1));
377 while ((LL_I2C_IsActiveFlag_ADDR(myI2c) == RESET) || (LL_I2C_IsActiveFlag_MSL(myI2c) == RESET) ||
378 (LL_I2C_IsActiveFlag_BUSY(myI2c) == RESET)) { }
379
380 for (unsigned int i = 0; i < len; i++) {
381 if (i < len - 1) {
382 LL_I2C_AcknowledgeNextData(myI2c, LL_I2C_ACK);
383 } else {
384 LL_I2C_AcknowledgeNextData(myI2c, LL_I2C_NACK);
385 }
386 while (LL_I2C_IsActiveFlag_RXNE(myI2c) == RESET) { }
387 buf[i] = LL_I2C_ReceiveData8(myI2c);
388 }
389 LL_I2C_GenerateStopCondition(myI2c);
390 }
391