1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "device_resource_if.h"
17 #include "mmc_corex.h"
18 #include "mmc_sdio.h"
19 #include "gpio_core.h"
20
21 #define HDF_LOG_TAG sdio_adapter_c
22
FakeSdioSetBlockSize(struct SdioDevice * dev,uint32_t blockSize)23 static int32_t FakeSdioSetBlockSize(struct SdioDevice *dev, uint32_t blockSize)
24 {
25 (void)dev;
26 (void)blockSize;
27 return HDF_SUCCESS;
28 }
29
FakeSdioGetCommonInfo(struct SdioDevice * dev,SdioCommonInfo * info,uint32_t infoType)30 static int32_t FakeSdioGetCommonInfo(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType)
31 {
32 if (info == NULL) {
33 HDF_LOGE("[%s]info is null", __func__);
34 return HDF_ERR_INVALID_PARAM;
35 }
36 if (infoType != SDIO_FUNC_INFO) {
37 HDF_LOGE("[%s]info type %u is not supported", __func__, infoType);
38 return HDF_ERR_NOT_SUPPORT;
39 }
40
41 info->funcInfo.enTimeout = 0;
42 info->funcInfo.funcNum = 1;
43 info->funcInfo.irqCap = 0;
44 info->funcInfo.data = NULL;
45 return HDF_SUCCESS;
46 }
47
FakeSdioSetCommonInfo(struct SdioDevice * dev,SdioCommonInfo * info,uint32_t infoType)48 static int32_t FakeSdioSetCommonInfo(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType)
49 {
50 (void)dev;
51 if (info == NULL) {
52 HDF_LOGE("[%s]info is null", __func__);
53 return HDF_ERR_INVALID_PARAM;
54 }
55 if (infoType != SDIO_FUNC_INFO) {
56 HDF_LOGE("[%s]info type %u is not supported", __func__, infoType);
57 return HDF_ERR_NOT_SUPPORT;
58 }
59 return HDF_SUCCESS;
60 }
61
FakeSdioEnableFunc(struct SdioDevice * dev)62 static int32_t FakeSdioEnableFunc(struct SdioDevice *dev)
63 {
64 (void)dev;
65 return HDF_SUCCESS;
66 }
67
FakeSdioFindFunc(struct SdioDevice * dev,struct SdioFunctionConfig * configData)68 static int32_t FakeSdioFindFunc(struct SdioDevice *dev, struct SdioFunctionConfig *configData)
69 {
70 if (dev == NULL || configData == NULL) {
71 HDF_LOGE("[%s]dev or configData is NULL", __func__);
72 return HDF_ERR_INVALID_OBJECT;
73 }
74 return HDF_SUCCESS;
75 }
76
77 static struct SdioDeviceOps g_fakeSdioDeviceOps = {
78 .setBlockSize = FakeSdioSetBlockSize,
79 .getCommonInfo = FakeSdioGetCommonInfo,
80 .setCommonInfo = FakeSdioSetCommonInfo,
81 .enableFunc = FakeSdioEnableFunc,
82 .findFunc = FakeSdioFindFunc,
83 };
84
FakeSdioDeleteCntlr(struct MmcCntlr * cntlr)85 static void FakeSdioDeleteCntlr(struct MmcCntlr *cntlr)
86 {
87 if (cntlr == NULL) {
88 return;
89 }
90 if (cntlr->curDev != NULL) {
91 MmcDeviceRemove(cntlr->curDev);
92 OsalMemFree(cntlr->curDev);
93 }
94 MmcCntlrRemove(cntlr);
95 OsalMemFree(cntlr);
96 }
97
FakeSdioCntlrParse(struct MmcCntlr * cntlr,struct HdfDeviceObject * obj)98 static int32_t FakeSdioCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj)
99 {
100 const struct DeviceResourceNode *node = NULL;
101 struct DeviceResourceIface *drsOps = NULL;
102 int32_t ret;
103
104 if (obj == NULL || cntlr == NULL) {
105 HDF_LOGE("[%s]input para is NULL", __func__);
106 return HDF_FAILURE;
107 }
108
109 node = obj->property;
110 if (node == NULL) {
111 HDF_LOGE("[%s]HdfDeviceObject property is NULL", __func__);
112 return HDF_FAILURE;
113 }
114 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
115 if (drsOps == NULL || drsOps->GetUint16 == NULL || drsOps->GetUint32 == NULL) {
116 HDF_LOGE("[%s]get HDF_CONFIG_SOURCE failed", __func__);
117 return HDF_FAILURE;
118 }
119
120 ret = drsOps->GetUint16(node, "hostId", &(cntlr->index), 0);
121 if (ret != HDF_SUCCESS) {
122 HDF_LOGE("[%s]read hostIndex failed: %d", __func__, ret);
123 return ret;
124 }
125 ret = drsOps->GetUint32(node, "devType", &(cntlr->devType), 0);
126 if (ret != HDF_SUCCESS) {
127 HDF_LOGE("[%s]read devType failed: %d", __func__, ret);
128 return ret;
129 }
130
131 return HDF_SUCCESS;
132 }
133
FakeSdioRescan(struct MmcCntlr * cntlr)134 static int32_t FakeSdioRescan(struct MmcCntlr *cntlr)
135 {
136 if (cntlr == NULL) {
137 HDF_LOGE("[%s]cntlr is NULL", __func__);
138 return HDF_ERR_INVALID_OBJECT;
139 }
140 return HDF_SUCCESS;
141 }
142
143 static struct MmcCntlrOps g_fakeSdioCntlrOps = {
144 .rescanSdioDev = FakeSdioRescan,
145 };
146
FakeSdioBind(struct HdfDeviceObject * obj)147 static int32_t FakeSdioBind(struct HdfDeviceObject *obj)
148 {
149 struct MmcCntlr *cntlr = NULL;
150 int32_t ret;
151
152 if (obj == NULL) {
153 HDF_LOGE("[%s]HdfDeviceObject is NULL", __func__);
154 return HDF_ERR_INVALID_OBJECT;
155 }
156
157 cntlr = OsalMemCalloc(sizeof(struct MmcCntlr));
158 if (cntlr == NULL) {
159 HDF_LOGE("[%s]alloc MmcCntlr failed", __func__);
160 return HDF_ERR_MALLOC_FAIL;
161 }
162
163 cntlr->ops = &g_fakeSdioCntlrOps;
164 cntlr->hdfDevObj = obj;
165 obj->service = &cntlr->service;
166 if ((ret = FakeSdioCntlrParse(cntlr, obj)) != HDF_SUCCESS) {
167 goto ERR_OUT;
168 }
169
170 if ((ret = MmcCntlrAdd(cntlr, false)) != HDF_SUCCESS) {
171 HDF_LOGE("[%s]add MmcCntlr failed: %d", __func__, ret);
172 goto ERR_OUT;
173 }
174
175 if ((ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType)) != HDF_SUCCESS) {
176 HDF_LOGE("[%s]alloc dev failed: %d", __func__, ret);
177 goto ERR_OUT;
178 }
179 MmcDeviceAddOps(cntlr->curDev, &g_fakeSdioDeviceOps);
180
181 return HDF_SUCCESS;
182
183 ERR_OUT:
184 FakeSdioDeleteCntlr(cntlr);
185 return ret;
186 }
187
FakeSdioInit(struct HdfDeviceObject * obj)188 static int32_t FakeSdioInit(struct HdfDeviceObject *obj)
189 {
190 (void)obj;
191 return HDF_SUCCESS;
192 }
193
FakeSdioRelease(struct HdfDeviceObject * obj)194 static void FakeSdioRelease(struct HdfDeviceObject *obj)
195 {
196 if (obj == NULL) {
197 return;
198 }
199 FakeSdioDeleteCntlr((struct MmcCntlr *)obj->service);
200 }
201
202 struct HdfDriverEntry g_fakeSdioEntry = {
203 .moduleVersion = 1,
204 .Bind = FakeSdioBind,
205 .Init = FakeSdioInit,
206 .Release = FakeSdioRelease,
207 .moduleName = "HDF_PLATFORM_SDIO",
208 };
209 HDF_INIT(g_fakeSdioEntry);
210
211
212 /*
213 * WIFI depends on SDIO & GPIO. HDF defined HdfWlanConfigSDIO interface,
214 * but user must implement it. Also, we add a dummy GPIO controller here.
215 */
216
FakeGiopDummyOps0(struct GpioCntlr * cntlr,uint16_t local,uint16_t dir)217 static int32_t FakeGiopDummyOps0(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir)
218 {
219 (void)cntlr;
220 (void)local;
221 (void)dir;
222 return HDF_SUCCESS;
223 }
224
225 static struct GpioMethod g_fakeGpioOps = {
226 .write = FakeGiopDummyOps0,
227 .setDir = FakeGiopDummyOps0,
228 };
229
HdfWlanConfigSDIO(uint8_t busId)230 int32_t HdfWlanConfigSDIO(uint8_t busId)
231 {
232 (void)busId;
233 int32_t ret;
234 struct GpioCntlr *cntlr = OsalMemCalloc(sizeof(struct GpioCntlr));
235
236 if (cntlr == NULL) {
237 HDF_LOGE("[%s]alloc memory failed", __func__);
238 return HDF_ERR_MALLOC_FAIL;
239 }
240
241 cntlr->count = 1;
242 cntlr->ops = &g_fakeGpioOps;
243 if ((ret = GpioCntlrAdd(cntlr)) != HDF_SUCCESS) {
244 OsalMemFree(cntlr);
245 }
246
247 return ret;
248 }
249
250