• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * i2c_adapter.h
3  *
4  * i2c driver adapter of linux
5  *
6  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  */
18 
19 #include <linux/i2c.h>
20 #include "hdf_device_desc.h"
21 #include "hdf_log.h"
22 #include "i2c_core.h"
23 #include "osal_mem.h"
24 
25 #define HDF_LOG_TAG i2c_linux_adapter
26 
CreateLinuxI2cMsgs(struct I2cMsg * msgs,int16_t count)27 static struct i2c_msg *CreateLinuxI2cMsgs(struct I2cMsg *msgs, int16_t count)
28 {
29     int16_t i;
30     struct i2c_msg *linuxMsgs = NULL;
31 
32     linuxMsgs = (struct i2c_msg *)OsalMemCalloc(sizeof(*linuxMsgs) * count);
33     if (linuxMsgs == NULL) {
34         HDF_LOGE("%s: malloc linux msgs fail!", __func__);
35         return NULL;
36     }
37 
38     for (i = 0; i < count; i++) {
39         linuxMsgs[i].addr = msgs[i].addr;
40         linuxMsgs[i].buf = msgs[i].buf;
41         linuxMsgs[i].len = msgs[i].len;
42         linuxMsgs[i].flags = msgs[i].flags;
43     }
44     return linuxMsgs;
45 }
46 
FreeLinxI2cMsgs(struct i2c_msg * msgs,int16_t count)47 static inline void FreeLinxI2cMsgs(struct i2c_msg *msgs, int16_t count)
48 {
49     OsalMemFree(msgs);
50     (void)count;
51 }
52 
LinuxI2cTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)53 static int32_t LinuxI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
54 {
55     int32_t ret;
56     struct i2c_msg *linuxMsgs = NULL;
57 
58     if (cntlr == NULL || cntlr->priv == NULL) {
59         HDF_LOGE("%s: cntlr or priv is null!", __func__);
60         return HDF_ERR_INVALID_OBJECT;
61     }
62     if (msgs == NULL || count <= 0) {
63         HDF_LOGE("%s: err params! count:%d", __func__, count);
64         return HDF_ERR_INVALID_PARAM;
65     }
66 
67     linuxMsgs = CreateLinuxI2cMsgs(msgs, count);
68     if (linuxMsgs == NULL) {
69         return HDF_ERR_MALLOC_FAIL;
70     }
71 
72     ret = i2c_transfer((struct i2c_adapter *)cntlr->priv, linuxMsgs, count);
73     FreeLinxI2cMsgs(linuxMsgs, count);
74     return ret;
75 }
76 
77 static struct I2cMethod g_method = {
78     .transfer = LinuxI2cTransfer,
79 };
80 
LinuxI2cBind(struct HdfDeviceObject * device)81 static int32_t LinuxI2cBind(struct HdfDeviceObject *device)
82 {
83     (void)device;
84     return HDF_SUCCESS;
85 }
86 
LinuxI2cRemove(struct device * dev,void * data)87 static int LinuxI2cRemove(struct device *dev, void *data)
88 {
89     struct I2cCntlr *cntlr = NULL;
90     struct i2c_adapter *adapter = NULL;
91 
92     HDF_LOGI("%s: Enter", __func__);
93     (void)data;
94 
95     if (dev == NULL) {
96         HDF_LOGE("%s: dev is null", __func__);
97         return HDF_ERR_INVALID_OBJECT;
98     }
99 
100     if (dev->type != &i2c_adapter_type) {
101         return HDF_SUCCESS; // continue remove
102     }
103 
104     adapter = to_i2c_adapter(dev);
105     cntlr = I2cCntlrGet(adapter->nr);
106     if (cntlr != NULL) {
107         I2cCntlrPut(cntlr);
108         I2cCntlrRemove(cntlr);
109         i2c_put_adapter(adapter);
110         OsalMemFree(cntlr);
111     }
112     return HDF_SUCCESS;
113 }
114 
LinuxI2cProbe(struct device * dev,void * data)115 static int LinuxI2cProbe(struct device *dev, void *data)
116 {
117     int32_t ret;
118     struct I2cCntlr *cntlr = NULL;
119     struct i2c_adapter *adapter = NULL;
120 
121     (void)data;
122 
123     if (dev == NULL) {
124         HDF_LOGE("%s: dev is null", __func__);
125         return HDF_ERR_INVALID_OBJECT;
126     }
127 
128     if (dev->type != &i2c_adapter_type) {
129         return HDF_SUCCESS; // continue probe
130     }
131 
132     HDF_LOGI("%s: Enter", __func__);
133     adapter = to_i2c_adapter(dev);
134     cntlr = (struct I2cCntlr *)OsalMemCalloc(sizeof(*cntlr));
135     if (cntlr == NULL) {
136         HDF_LOGE("%s: malloc cntlr fail!", __func__);
137         i2c_put_adapter(adapter);
138         return HDF_ERR_MALLOC_FAIL;
139     }
140 
141     cntlr->busId = adapter->nr;
142     cntlr->priv = adapter;
143     cntlr->ops = &g_method;
144     ret = I2cCntlrAdd(cntlr);
145     if (ret != HDF_SUCCESS) {
146         i2c_put_adapter(adapter);
147         OsalMemFree(cntlr);
148         cntlr = NULL;
149         HDF_LOGE("%s: add controller fail:%d", __func__, ret);
150         return ret;
151     }
152     HDF_LOGI("%s: i2c adapter %d add success", __func__, cntlr->busId);
153     return HDF_SUCCESS;
154 }
155 
LinuxI2cInit(struct HdfDeviceObject * device)156 static int32_t LinuxI2cInit(struct HdfDeviceObject *device)
157 {
158     int32_t ret;
159 
160     HDF_LOGI("%s: Enter", __func__);
161     if (device == NULL) {
162         HDF_LOGE("%s: device is NULL", __func__);
163         return HDF_ERR_INVALID_OBJECT;
164     }
165 
166     ret = i2c_for_each_dev(NULL, LinuxI2cProbe);
167     HDF_LOGI("%s: done", __func__);
168     return ret;
169 }
170 
LinuxI2cRelease(struct HdfDeviceObject * device)171 static void LinuxI2cRelease(struct HdfDeviceObject *device)
172 {
173     HDF_LOGI("%s: enter", __func__);
174     if (device == NULL) {
175         HDF_LOGE("%s: device is NULL", __func__);
176         return;
177     }
178 
179     (void)i2c_for_each_dev(NULL, LinuxI2cRemove);
180 }
181 
182 struct HdfDriverEntry g_i2cLinuxDriverEntry = {
183     .moduleVersion = 1,
184     .Bind = LinuxI2cBind,
185     .Init = LinuxI2cInit,
186     .Release = LinuxI2cRelease,
187     .moduleName = "linux_i2c_adapter",
188 };
189 HDF_INIT(g_i2cLinuxDriverEntry);
190