• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Jiangsu Hoperun Software Co., Ltd.
3  *
4  * This file 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 #include <securec.h>
11 #include "i2c_core.h"
12 #include "i2c_if.h"
13 #include "wm_i2c.h"
14 #include "wm_gpio_afsel.h"
15 #include "device_resource_if.h"
16 #include "osal_mutex.h"
17 
18 #define DEC_NUM 10
19 #define GROUP_PIN_NUM 8
20 #define I2C_INVALID_ADDR 0xFFFF
21 #define HAL_I2C_ID_NUM 1
22 
23 struct I2cResource {
24     uint32_t port;
25     uint32_t sclPin;
26     uint32_t sdaPin;
27     uint32_t speed;
28 };
29 
30 struct I2cDevice {
31     uint16_t devAddr;      /**< device addr */
32     uint32_t addressWidth; /**< Addressing mode: 7 bit or 10 bit */
33     struct OsalMutex mutex;
34     uint32_t port;
35     struct I2cResource resource;
36 };
37 
38 /* HdfDriverEntry method definitions */
39 static int32_t i2cDriverBind(struct HdfDeviceObject *device);
40 static int32_t i2cDriverInit(struct HdfDeviceObject *device);
41 static void i2cDriverRelease(struct HdfDeviceObject *device);
42 
43 /* HdfDriverEntry definitions */
44 struct HdfDriverEntry g_i2cDriverEntry = {
45     .moduleVersion = 1,
46     .moduleName = "W800_I2C_MODULE_HDF",
47     .Bind = i2cDriverBind,
48     .Init = i2cDriverInit,
49     .Release = i2cDriverRelease,
50 };
51 
52 // Initialize HdfDriverEntry
53 HDF_INIT(g_i2cDriverEntry);
54 
55 /* I2cHostMethod method definitions */
56 static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
57 
58 struct I2cMethod g_i2cHostMethod = {
59     .transfer = i2cHostTransfer,
60 };
61 
InitI2cDevice(struct I2cDevice * device)62 static int32_t InitI2cDevice(struct I2cDevice *device)
63 {
64     uint32_t i2cPort;
65     struct I2cResource *resource = NULL;
66 
67     if (device == NULL) {
68         HDF_LOGE("device is NULL\r\n");
69         return HDF_ERR_INVALID_PARAM;
70     }
71 
72     resource = &device->resource;
73     device->port = resource->port;
74     i2cPort = device->port;
75     if (i2cPort >= HAL_I2C_ID_NUM) {
76         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
77         return HDF_ERR_NOT_SUPPORT;
78     }
79 
80     if (OsalMutexInit(&device->mutex) != HDF_SUCCESS) {
81         HDF_LOGE("%s %d OsalMutexInit fail\r\n", __func__, __LINE__);
82         return HDF_FAILURE;
83     }
84 
85     if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
86         HDF_LOGE("%s %d osMutexWait fail\r\n", __func__, __LINE__);
87         return HDF_ERR_TIMEOUT;
88     }
89 
90     if ((resource->sclPin == WM_IO_PA_01) && (resource->sdaPin == WM_IO_PA_04)) {
91         wm_i2c_scl_config(WM_IO_PA_01);
92         wm_i2c_sda_config(WM_IO_PA_04);
93     } else {
94         HDF_LOGE("%s %d scl sda pin fail\r\n", __func__, __LINE__);
95         OsalMutexUnlock(&device->mutex);
96         return HDF_ERR_INVALID_PARAM;
97     }
98 
99     tls_i2c_init(resource->speed);
100     OsalMutexUnlock(&device->mutex);
101     return HDF_SUCCESS;
102 }
103 
HostRestI2cDevice(struct I2cDevice * device)104 static int32_t HostRestI2cDevice(struct I2cDevice *device)
105 {
106     struct I2cResource *resource = NULL;
107     uint32_t i2cPort;
108 
109     if (device == NULL) {
110         HDF_LOGE("%s %d device is null\r\n", __func__, __LINE__);
111         return HDF_ERR_INVALID_PARAM;
112     }
113     resource = &device->resource;
114     if (resource == NULL) {
115         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
116         return HDF_ERR_INVALID_OBJECT;
117     }
118     device->port = resource->port;
119     i2cPort = device->port;
120     if (i2cPort > HAL_I2C_ID_NUM) {
121         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
122         return HDF_ERR_NOT_SUPPORT;
123     }
124 
125     return HDF_SUCCESS;
126 }
127 
GetI2cDeviceResource(struct I2cDevice * device,const struct DeviceResourceNode * resourceNode)128 static uint32_t GetI2cDeviceResource(struct I2cDevice *device,
129                                      const struct DeviceResourceNode *resourceNode)
130 {
131     uint32_t tempPin = 0;
132     struct I2cResource *resource = NULL;
133     struct DeviceResourceIface *dri = NULL;
134     if (device == NULL || resourceNode == NULL) {
135         HDF_LOGE("device or resourceNode is NULL\r\n");
136         return HDF_ERR_INVALID_PARAM;
137     }
138     resource = &device->resource;
139     if (resource == NULL) {
140         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
141         return HDF_ERR_INVALID_OBJECT;
142     }
143     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
144     if (dri == NULL || dri->GetUint32 == NULL) {
145         HDF_LOGE("DeviceResourceIface is invalid\r\n");
146         return HDF_ERR_INVALID_OBJECT;
147     }
148 
149     if (dri->GetUint32(resourceNode, "port", &resource->port, 0) != HDF_SUCCESS) {
150         HDF_LOGE("i2c config port fail\r\n");
151         return HDF_FAILURE;
152     }
153 
154     if (dri->GetUint32(resourceNode, "sclPin", &tempPin, 0) != HDF_SUCCESS) {
155         HDF_LOGE("i2c config sclPin fail\r\n");
156         return HDF_FAILURE;
157     }
158     resource->sclPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM);
159 
160     if (dri->GetUint32(resourceNode, "sdaPin", &tempPin, 0) != HDF_SUCCESS) {
161         HDF_LOGE("i2c config sdaPin fail\r\n");
162         return HDF_FAILURE;
163     }
164     resource->sdaPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM);
165 
166     if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) {
167         HDF_LOGE("i2c config speed fail\r\n");
168         return HDF_FAILURE;
169     }
170 
171     return HDF_SUCCESS;
172 }
173 
AttachI2cDevice(struct I2cCntlr * host,const struct HdfDeviceObject * device)174 static int32_t AttachI2cDevice(struct I2cCntlr *host, const struct HdfDeviceObject *device)
175 {
176     int32_t ret;
177     struct I2cDevice *i2cDevice = NULL;
178     struct I2cResource *resource = NULL;
179 
180     if (device == NULL || host == NULL) {
181         HDF_LOGE("%s: device or host is NULL\r\n", __func__);
182         return HDF_ERR_INVALID_PARAM;
183     }
184     i2cDevice = (struct I2cDevice *)OsalMemAlloc(sizeof(struct I2cDevice));
185     if (i2cDevice == NULL) {
186         HDF_LOGE("%s: OsalMemAlloc i2cDevice error\r\n", __func__);
187         return HDF_ERR_MALLOC_FAIL;
188     }
189     (void)memset_s(i2cDevice, sizeof(struct I2cDevice), 0, sizeof(struct I2cDevice));
190     ret = GetI2cDeviceResource(i2cDevice, device->property);
191     if (ret != HDF_SUCCESS) {
192         OsalMemFree(i2cDevice);
193         return HDF_FAILURE;
194     }
195     resource = &i2cDevice->resource;
196     if (resource == NULL) {
197         HDF_LOGE("%s %d: invalid parameter\r\n", __func__, __LINE__);
198         return HDF_ERR_INVALID_OBJECT;
199     }
200 
201     host->priv = i2cDevice;
202     host->busId = i2cDevice->port;
203 
204     return InitI2cDevice(i2cDevice);
205 }
206 
i2cDriverInit(struct HdfDeviceObject * device)207 static int32_t i2cDriverInit(struct HdfDeviceObject *device)
208 {
209     int32_t ret;
210     struct I2cCntlr *host = NULL;
211     if (device == NULL) {
212         HDF_LOGE("%s: device is NULL\r\n", __func__);
213         return HDF_ERR_INVALID_PARAM;
214     }
215 
216     host = (struct I2cCntlr *)OsalMemAlloc(sizeof(struct I2cCntlr));
217     if (host == NULL) {
218         HDF_LOGE("%s: host is NULL\r\n", __func__);
219         return HDF_ERR_MALLOC_FAIL;
220     }
221     (void)memset_s(host, sizeof(struct I2cCntlr), 0, sizeof(struct I2cCntlr));
222     host->ops = &g_i2cHostMethod;
223     device->priv = (void *)host;
224     ret = AttachI2cDevice(host, device);
225     if (ret != HDF_SUCCESS) {
226         HDF_LOGE("%s: attach error\r\n", __func__);
227         i2cDriverRelease(device);
228         return HDF_DEV_ERR_ATTACHDEV_FAIL;
229     }
230     ret = I2cCntlrAdd(host);
231     if (ret != HDF_SUCCESS) {
232         i2cDriverRelease(device);
233         return HDF_FAILURE;
234     }
235     return ret;
236 }
237 
i2cDriverBind(struct HdfDeviceObject * device)238 static int32_t i2cDriverBind(struct HdfDeviceObject *device)
239 {
240     if (device == NULL) {
241         HDF_LOGE("%s: I2c device object is NULL\r\n", __func__);
242         return HDF_FAILURE;
243     }
244     return HDF_SUCCESS;
245 }
246 
i2cDriverRelease(struct HdfDeviceObject * device)247 static void i2cDriverRelease(struct HdfDeviceObject *device)
248 {
249     struct I2cCntlr *i2cCntrl = NULL;
250     struct I2cDevice *i2cDevice = NULL;
251 
252     if (device == NULL) {
253         HDF_LOGE("%s: device is NULL\r\n", __func__);
254         return;
255     }
256     i2cCntrl = device->priv;
257     if (i2cCntrl == NULL || i2cCntrl->priv == NULL) {
258         HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__);
259         return;
260     }
261     i2cCntrl->ops = NULL;
262     i2cDevice = (struct I2cDevice *)i2cCntrl->priv;
263     OsalMemFree(i2cCntrl);
264 
265     if (i2cDevice != NULL) {
266         OsalMutexDestroy(&i2cDevice->mutex);
267         OsalMemFree(i2cDevice);
268     }
269 }
270 
i2c_send(struct I2cMsg * msg)271 static int32_t i2c_send(struct I2cMsg *msg)
272 {
273     uint16_t len;
274     uint8_t ifack;
275     uint8_t ifstop;
276     uint8_t ifstart;
277 
278     len = msg->len;
279     ifstop = 0;
280     if (msg->flags & I2C_FLAG_READ) {
281         ifack = (msg->flags & I2C_FLAG_READ_NO_ACK) ? 0 : 1;
282         for (int32_t j = 0; j < len; j++) {
283             if (((msg->flags & I2C_FLAG_STOP) && j) == (len - 1)) {
284                 ifstop = 1;
285             }
286             msg->buf[j] = tls_i2c_read_byte(ifack, ifstop);
287         }
288     } else {
289         ifack = (msg->flags & I2C_FLAG_IGNORE_NO_ACK) ? 0 : 1;
290         for (int32_t j = 0; j < len; j++) {
291             if (((msg->flags & I2C_FLAG_NO_START) == 0) && (j == 0)) {
292                 ifstart = 1;
293             }
294             tls_i2c_write_byte(msg->buf[j], ifstart);
295             if (ifack) {
296                 tls_i2c_wait_ack();
297             }
298         }
299     }
300 }
301 
i2c_transfer(struct I2cDevice * device,struct I2cMsg * msgs,int16_t count)302 static int32_t i2c_transfer(struct I2cDevice *device, struct I2cMsg *msgs, int16_t count)
303 {
304     struct I2cMsg *msg = NULL;
305 
306     uint32_t i2cPort;
307     if (device == NULL || msgs == NULL) {
308         HDF_LOGE("%s: device or  msgs is NULL\r\n", __func__);
309         return HDF_ERR_INVALID_PARAM;
310     }
311     i2cPort = (uint32_t)device->port;
312     if (i2cPort > HAL_I2C_ID_NUM) {
313         HDF_LOGE("i2c port %u not support\r\n", i2cPort);
314         return HDF_ERR_NOT_SUPPORT;
315     }
316     if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) {
317         HDF_LOGE("%s %d OsalMutexTimedLock fail\r\n", __func__, __LINE__);
318         return HDF_ERR_TIMEOUT;
319     }
320     for (int32_t i = 0; i < count; i++) {
321         msg = &msgs[i];
322         i2c_send(msg);
323     }
324     OsalMutexUnlock(&device->mutex);
325     return count;
326 }
327 
i2cHostTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)328 static int32_t i2cHostTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
329 {
330     struct I2cDevice *device = NULL;
331 
332     if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) {
333         HDF_LOGE("%s: I2cCntlr or msgs is NULL\r\n", __func__);
334         return HDF_ERR_INVALID_PARAM;
335     }
336     device = (struct I2cDevice *)cntlr->priv;
337     return i2c_transfer(device, msgs, count);
338 }
339