• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device 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 "spi_core.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "spi_if.h"
13 
14 #define HDF_LOG_TAG spi_core
15 
SpiCntlrOpen(struct SpiCntlr * cntlr,uint32_t csNum)16 int32_t SpiCntlrOpen(struct SpiCntlr *cntlr, uint32_t csNum)
17 {
18     int32_t ret;
19 
20     if (cntlr == NULL) {
21         HDF_LOGE("%s: invalid parameter", __func__);
22         return HDF_ERR_INVALID_PARAM;
23     }
24     if (cntlr->method == NULL || cntlr->method->Open == NULL) {
25         HDF_LOGE("%s: Open not support", __func__);
26         return HDF_ERR_NOT_SUPPORT;
27     }
28     (void)OsalMutexLock(&(cntlr->lock));
29     cntlr->curCs = csNum;
30     ret = cntlr->method->Open(cntlr);
31     (void)OsalMutexUnlock(&(cntlr->lock));
32     return ret;
33 }
34 
SpiCntlrClose(struct SpiCntlr * cntlr,uint32_t csNum)35 int32_t SpiCntlrClose(struct SpiCntlr *cntlr, uint32_t csNum)
36 {
37     int32_t ret;
38 
39     if (cntlr == NULL) {
40         HDF_LOGE("%s: invalid parameter", __func__);
41         return HDF_ERR_INVALID_PARAM;
42     }
43     if (cntlr->method == NULL || cntlr->method->Close == NULL) {
44         HDF_LOGE("%s: Close not support", __func__);
45         return HDF_ERR_NOT_SUPPORT;
46     }
47     (void)OsalMutexLock(&(cntlr->lock));
48     cntlr->curCs = csNum;
49     ret = cntlr->method->Close(cntlr);
50     (void)OsalMutexUnlock(&(cntlr->lock));
51     return ret;
52 }
53 
SpiCntlrTransfer(struct SpiCntlr * cntlr,uint32_t csNum,struct SpiMsg * msg,uint32_t count)54 int32_t SpiCntlrTransfer(struct SpiCntlr *cntlr, uint32_t csNum, struct SpiMsg *msg, uint32_t count)
55 {
56     int32_t ret;
57 
58     if (cntlr == NULL) {
59         HDF_LOGE("%s: invalid parameter", __func__);
60         return HDF_ERR_INVALID_PARAM;
61     }
62     if (cntlr->method == NULL || cntlr->method->Transfer == NULL) {
63         HDF_LOGE("%s: transfer not support", __func__);
64         return HDF_ERR_NOT_SUPPORT;
65     }
66 
67     (void)OsalMutexLock(&(cntlr->lock));
68     cntlr->curCs = csNum;
69     ret = cntlr->method->Transfer(cntlr, msg, count);
70     (void)OsalMutexUnlock(&(cntlr->lock));
71     return ret;
72 }
73 
SpiCntlrSetCfg(struct SpiCntlr * cntlr,uint32_t csNum,struct SpiCfg * cfg)74 int32_t SpiCntlrSetCfg(struct SpiCntlr *cntlr, uint32_t csNum, struct SpiCfg *cfg)
75 {
76     int32_t ret;
77 
78     if (cntlr == NULL) {
79         HDF_LOGE("%s: invalid parameter", __func__);
80         return HDF_ERR_INVALID_PARAM;
81     }
82 
83     if (cntlr->method == NULL || cntlr->method->SetCfg == NULL) {
84         HDF_LOGE("%s: not support", __func__);
85         return HDF_ERR_NOT_SUPPORT;
86     }
87 
88     (void)OsalMutexLock(&(cntlr->lock));
89     cntlr->curCs = csNum;
90     ret = cntlr->method->SetCfg(cntlr, cfg);
91     (void)OsalMutexUnlock(&(cntlr->lock));
92     return ret;
93 }
94 
SpiCntlrGetCfg(struct SpiCntlr * cntlr,uint32_t csNum,struct SpiCfg * cfg)95 int32_t SpiCntlrGetCfg(struct SpiCntlr *cntlr, uint32_t csNum, struct SpiCfg *cfg)
96 {
97     int32_t ret;
98 
99     if (cntlr == NULL) {
100         HDF_LOGE("%s: invalid parameter", __func__);
101         return HDF_ERR_INVALID_PARAM;
102     }
103 
104     if (cntlr->method == NULL || cntlr->method->GetCfg == NULL) {
105         HDF_LOGE("%s: not support", __func__);
106         return HDF_ERR_NOT_SUPPORT;
107     }
108 
109     (void)OsalMutexLock(&(cntlr->lock));
110     cntlr->curCs = csNum;
111     ret = cntlr->method->GetCfg(cntlr, cfg);
112     (void)OsalMutexUnlock(&(cntlr->lock));
113     return ret;
114 }
115 
SpiTransferRebuildMsgs(struct HdfSBuf * data,struct SpiMsg ** ppmsgs,uint32_t * pcount,uint8_t ** ppbuf)116 static int32_t SpiTransferRebuildMsgs(struct HdfSBuf *data, struct SpiMsg **ppmsgs, uint32_t *pcount, uint8_t **ppbuf)
117 {
118     uint32_t count;
119     int32_t i;
120     uint32_t len;
121     uint32_t lenReply = 0;
122     uint8_t *buf = NULL;
123     uint8_t *bufReply = NULL;
124     struct SpiMsg *msgs = NULL;
125 
126     if (!HdfSbufReadBuffer(data, (const void **)&msgs, &len) || msgs == NULL || len == 0) {
127         HDF_LOGE("%s: read msgs fail!", __func__);
128         return HDF_ERR_IO;
129     }
130 
131     count = (uint32_t)len / (uint32_t)sizeof(struct SpiMsg);
132     for (i = 0; i < count; i++) {
133         if (msgs[i].rbuf != NULL) {
134             lenReply += msgs[i].len;
135         }
136         if (msgs[i].wbuf == NULL) {
137             continue;
138         }
139         if (!HdfSbufReadBuffer(data, (const void **)&buf, &len)) {
140             HDF_LOGE("%s: read msg[%d] buf fail!", __func__, i);
141         } else {
142             msgs[i].wbuf = buf;
143         }
144     }
145 
146     if (lenReply > 0) {
147         bufReply = OsalMemCalloc(lenReply);
148         if (bufReply == NULL) {
149             return HDF_ERR_MALLOC_FAIL;
150         }
151         for (i = 0, buf = bufReply; i < count && buf < (bufReply + lenReply); i++) {
152             if (msgs[i].rbuf != NULL) {
153                 msgs[i].rbuf = buf;
154                 buf += msgs[i].len;
155             }
156         }
157     }
158 
159     *ppmsgs = msgs;
160     *pcount = count;
161     *ppbuf = bufReply;
162 
163     return HDF_SUCCESS;
164 }
165 
SpiTransferWriteBackMsgs(struct HdfSBuf * reply,struct SpiMsg * msgs,uint32_t count)166 static int32_t SpiTransferWriteBackMsgs(struct HdfSBuf *reply, struct SpiMsg *msgs, uint32_t count)
167 {
168     uint32_t i;
169 
170     for (i = 0; i < count; i++) {
171         if (msgs[i].rbuf == NULL) {
172             continue;
173         }
174 
175         if (!HdfSbufWriteBuffer(reply, msgs[i].rbuf, msgs[i].len)) {
176             HDF_LOGE("%s: write msg[%d] reply failed!", __func__, i);
177             return HDF_ERR_IO;
178         }
179     }
180 
181     return HDF_SUCCESS;
182 }
183 
SpiIoTransfer(struct SpiCntlr * cntlr,uint32_t csNum,struct HdfSBuf * data,struct HdfSBuf * reply)184 static int32_t SpiIoTransfer(struct SpiCntlr *cntlr, uint32_t csNum, struct HdfSBuf *data, struct HdfSBuf *reply)
185 {
186     int32_t ret;
187     uint32_t count;
188     struct SpiMsg *msgs = NULL;
189     uint8_t *bufReply = NULL;
190 
191     if (data == NULL || reply == NULL) {
192         return HDF_ERR_INVALID_PARAM;
193     }
194 
195     ret = SpiTransferRebuildMsgs(data, &msgs, &count, &bufReply);
196     if (ret != HDF_SUCCESS) {
197         HDF_LOGE("%s: rebuild msgs fail:%d", __func__, ret);
198         goto EXIT;
199     }
200 
201     ret = SpiCntlrTransfer(cntlr, csNum, msgs, count);
202     if (ret != HDF_SUCCESS) {
203         HDF_LOGE("%s: do transfer failed:%d", __func__, ret);
204         goto EXIT;
205     }
206 
207     ret =  SpiTransferWriteBackMsgs(reply, msgs, count);
208 
209 EXIT:
210     if (bufReply != NULL) {
211         OsalMemFree(bufReply);
212     }
213     return ret;
214 }
215 
SpiIoOpen(struct SpiCntlr * cntlr,uint32_t csNum)216 static int32_t SpiIoOpen(struct SpiCntlr *cntlr, uint32_t csNum)
217 {
218     return SpiCntlrOpen(cntlr, csNum);
219 }
220 
SpiIoClose(struct SpiCntlr * cntlr,uint32_t csNum)221 static int32_t SpiIoClose(struct SpiCntlr *cntlr, uint32_t csNum)
222 {
223     return SpiCntlrClose(cntlr, csNum);
224 }
225 
SpiIoSetConfig(struct SpiCntlr * cntlr,uint32_t csNum,struct HdfSBuf * data)226 static int32_t SpiIoSetConfig(struct SpiCntlr *cntlr, uint32_t csNum, struct HdfSBuf *data)
227 {
228     uint32_t len;
229     struct SpiCfg *cfg = NULL;
230 
231     if (!HdfSbufReadBuffer(data, (const void **)&cfg, &len) || sizeof(*cfg) != len) {
232         HDF_LOGE("%s: read buffer failed!", __func__);
233         return HDF_ERR_IO;
234     }
235     return SpiCntlrSetCfg(cntlr, csNum, cfg);
236 }
237 
SpiIoGetConfig(struct SpiCntlr * cntlr,uint32_t csNum,struct HdfSBuf * reply)238 static int32_t SpiIoGetConfig(struct SpiCntlr *cntlr, uint32_t csNum, struct HdfSBuf *reply)
239 {
240     int32_t ret;
241     struct SpiCfg cfg;
242 
243     ret = SpiCntlrGetCfg(cntlr, csNum, &cfg);
244     if (ret != HDF_SUCCESS) {
245         HDF_LOGE("%s: get cfg failed!", __func__);
246         return ret;
247     }
248 
249     if (!HdfSbufWriteBuffer(reply, &cfg, sizeof(cfg))) {
250         HDF_LOGE("%s: write buffer failed!", __func__);
251         return ret;
252     }
253     return HDF_SUCCESS;
254 }
255 
SpiIoDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)256 static int32_t SpiIoDispatch(struct HdfDeviceIoClient *client, int cmd,
257     struct HdfSBuf *data, struct HdfSBuf *reply)
258 {
259     int32_t ret;
260     uint32_t csNum;
261     struct SpiCntlr *cntlr = NULL;
262 
263     if (client == NULL || client->device == NULL || client->device->service == NULL) {
264         HDF_LOGE("%s: invalid client", __func__);
265         return HDF_ERR_INVALID_OBJECT;
266     }
267 
268     cntlr = (struct SpiCntlr *)client->device->service;
269     if (data == NULL) {
270         HDF_LOGE("%s: data is NULL", __func__);
271         return HDF_ERR_INVALID_PARAM;
272     }
273 
274     if (!HdfSbufReadUint32(data, &csNum)) {
275         HDF_LOGE("%s: read csNum failed!", __func__);
276         return HDF_ERR_IO;
277     }
278 
279     switch (cmd) {
280         case SPI_IO_OPEN:
281             return SpiIoOpen(cntlr, csNum);
282         case SPI_IO_CLOSE:
283             return SpiIoClose(cntlr, csNum);
284         case SPI_IO_SET_CONFIG:
285             return SpiIoSetConfig(cntlr, csNum, data);
286         case SPI_IO_GET_CONFIG:
287             return SpiIoGetConfig(cntlr, csNum, reply);
288         case SPI_IO_TRANSFER:
289             return SpiIoTransfer(cntlr, csNum, data, reply);
290         default:
291             ret = HDF_ERR_NOT_SUPPORT;
292             break;
293     }
294     return ret;
295 }
296 
SpiCntlrDestroy(struct SpiCntlr * cntlr)297 void SpiCntlrDestroy(struct SpiCntlr *cntlr)
298 {
299     if (cntlr == NULL) {
300         return;
301     }
302     (void)OsalMutexDestroy(&(cntlr->lock));
303     OsalMemFree(cntlr);
304 }
305 
SpiCntlrCreate(struct HdfDeviceObject * device)306 struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device)
307 {
308     struct SpiCntlr *cntlr = NULL;
309 
310     if (device == NULL) {
311         HDF_LOGE("%s: invalid parameter", __func__);
312         return NULL;
313     }
314 
315     cntlr = (struct SpiCntlr *)OsalMemCalloc(sizeof(*cntlr));
316     if (cntlr == NULL) {
317         HDF_LOGE("%s: OsalMemCalloc error", __func__);
318         return NULL;
319     }
320     cntlr->device = device;
321     device->service = &(cntlr->service);
322     device->service->Dispatch = SpiIoDispatch;
323     (void)OsalMutexInit(&cntlr->lock);
324     DListHeadInit(&cntlr->list);
325     cntlr->priv = NULL;
326     return cntlr;
327 }
328