1 /*
2 * Copyright (c) 2021-2023 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 "pcie_core.h"
10 #include "device_resource_if.h"
11 #include "hdf_log.h"
12 #include "osal_mem.h"
13 #include "pcie_dispatch.h"
14 #include "securec.h"
15
16 #define HDF_LOG_TAG pcie_core_c
17
PcieCntlrInit(struct PcieCntlr * cntlr)18 static int32_t PcieCntlrInit(struct PcieCntlr *cntlr)
19 {
20 int32_t ret;
21
22 if (cntlr == NULL || cntlr->hdfDevObj == NULL) {
23 HDF_LOGE("PcieCntlrInit: cntlr or hdfDevObj is null!");
24 return HDF_ERR_INVALID_OBJECT;
25 }
26
27 ret = OsalSpinInit(&cntlr->spin);
28 if (ret != HDF_SUCCESS) {
29 HDF_LOGE("PcieCntlrInit: spin init fail!");
30 return ret;
31 }
32
33 cntlr->service.Dispatch = PcieIoDispatch;
34 cntlr->hdfDevObj->service = &(cntlr->service);
35 cntlr->device.number = (int32_t)cntlr->devInfo.busNum;
36 cntlr->device.hdfDev = cntlr->hdfDevObj;
37 return HDF_SUCCESS;
38 }
39
PcieCntlrUninit(struct PcieCntlr * cntlr)40 static inline void PcieCntlrUninit(struct PcieCntlr *cntlr)
41 {
42 if (cntlr != NULL) {
43 (void)OsalSpinDestroy(&cntlr->spin);
44 }
45 }
46
PcieCntlrAdd(struct PcieCntlr * cntlr)47 int32_t PcieCntlrAdd(struct PcieCntlr *cntlr)
48 {
49 int32_t ret;
50
51 if (cntlr == NULL) {
52 HDF_LOGE("PcieCntlrAdd: invalid param!");
53 return HDF_ERR_INVALID_OBJECT;
54 }
55
56 ret = PcieCntlrInit(cntlr);
57 if (ret != HDF_SUCCESS) {
58 HDF_LOGE("PcieCntlrAdd: pcie cntlr init fail!");
59 return ret;
60 }
61
62 cntlr->device.manager = PlatformManagerGet(PLATFORM_MODULE_PCIE);
63 ret = PlatformDeviceAdd(&cntlr->device);
64 if (ret != HDF_SUCCESS) {
65 HDF_LOGE("PcieCntlrAdd: device add fail!");
66 PcieCntlrUninit(cntlr);
67 return ret;
68 }
69 return HDF_SUCCESS;
70 }
71
PcieCntlrRemove(struct PcieCntlr * cntlr)72 void PcieCntlrRemove(struct PcieCntlr *cntlr)
73 {
74 if (cntlr != NULL) {
75 PlatformDeviceDel(&cntlr->device);
76 PcieCntlrUninit(cntlr);
77 }
78 }
79
PcieCntlrParse(struct PcieCntlr * cntlr,struct HdfDeviceObject * obj)80 int32_t PcieCntlrParse(struct PcieCntlr *cntlr, struct HdfDeviceObject *obj)
81 {
82 const struct DeviceResourceNode *node = NULL;
83 struct DeviceResourceIface *drsOps = NULL;
84 int32_t ret;
85
86 if (obj == NULL || cntlr == NULL) {
87 HDF_LOGE("PcieCntlrParse: input param is null!");
88 return HDF_FAILURE;
89 }
90
91 node = obj->property;
92 if (node == NULL) {
93 HDF_LOGE("PcieCntlrParse: drs node is null!");
94 return HDF_FAILURE;
95 }
96 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
97 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
98 HDF_LOGE("PcieCntlrParse: invalid drs ops fail.");
99 return HDF_FAILURE;
100 }
101
102 ret = drsOps->GetUint16(node, "busNum", &(cntlr->devInfo.busNum), 0);
103 if (ret != HDF_SUCCESS) {
104 HDF_LOGE("PcieCntlrParse: read busNum fail!");
105 return ret;
106 }
107
108 ret = drsOps->GetUint32(node, "vendorId", &(cntlr->devInfo.vendorId), 0);
109 if (ret != HDF_SUCCESS) {
110 HDF_LOGE("PcieCntlrParse: read vendorId fail!");
111 return HDF_FAILURE;
112 }
113
114 ret = drsOps->GetUint32(node, "devId", &(cntlr->devInfo.devId), 0);
115 if (ret != HDF_SUCCESS) {
116 HDF_LOGE("PcieCntlrParse: read devId fail!");
117 return HDF_FAILURE;
118 }
119 return HDF_SUCCESS;
120 }
121
PcieCntlrRead(struct PcieCntlr * cntlr,uint32_t mode,uint32_t pos,uint8_t * data,uint32_t len)122 int32_t PcieCntlrRead(struct PcieCntlr *cntlr, uint32_t mode, uint32_t pos, uint8_t *data, uint32_t len)
123 {
124 int32_t ret;
125
126 if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->read == NULL) {
127 HDF_LOGE("PcieCntlrRead: invalid cntlr");
128 return HDF_ERR_INVALID_OBJECT;
129 }
130 if (data == NULL || len == 0 || mode > PCIE_IO) {
131 HDF_LOGE("PcieCntlrRead: invalid param");
132 return HDF_ERR_INVALID_PARAM;
133 }
134
135 PcieCntlrLock(cntlr);
136 ret = cntlr->ops->read(cntlr, mode, pos, data, len);
137 PcieCntlrUnlock(cntlr);
138 return ret;
139 }
140
PcieCntlrWrite(struct PcieCntlr * cntlr,uint32_t mode,uint32_t pos,uint8_t * data,uint32_t len)141 int32_t PcieCntlrWrite(struct PcieCntlr *cntlr, uint32_t mode, uint32_t pos, uint8_t *data, uint32_t len)
142 {
143 int32_t ret;
144 if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->write == NULL) {
145 HDF_LOGE("PcieCntlrWrite: invalid cntlr");
146 return HDF_ERR_INVALID_OBJECT;
147 }
148 if (data == NULL || len == 0 || mode > PCIE_IO) {
149 HDF_LOGE("PcieCntlrWrite: invalid cb");
150 return HDF_ERR_INVALID_PARAM;
151 }
152
153 PcieCntlrLock(cntlr);
154 ret = cntlr->ops->write(cntlr, mode, pos, data, len);
155 PcieCntlrUnlock(cntlr);
156 return ret;
157 }
158
PcieCntlrDmaMap(struct PcieCntlr * cntlr,PcieCallbackFunc cb,uintptr_t addr,uint32_t len,uint8_t dir)159 int32_t PcieCntlrDmaMap(struct PcieCntlr *cntlr, PcieCallbackFunc cb, uintptr_t addr, uint32_t len, uint8_t dir)
160 {
161 int32_t ret;
162
163 if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->write == NULL) {
164 HDF_LOGE("PcieCntlrDmaMap: invalid param");
165 return HDF_ERR_INVALID_OBJECT;
166 }
167 if (addr == 0 || cb == NULL || len == 0) {
168 HDF_LOGE("PcieCntlrDmaMap: invalid param");
169 return HDF_ERR_INVALID_PARAM;
170 }
171
172 PcieCntlrLock(cntlr);
173 if (cntlr->dmaCb != NULL) {
174 HDF_LOGE("PcieCntlrDmaMap: irq has been registered");
175 PcieCntlrUnlock(cntlr);
176 return HDF_FAILURE;
177 }
178 cntlr->dmaCb = cb;
179 ret = cntlr->ops->dmaMap(cntlr, addr, len, dir);
180 PcieCntlrUnlock(cntlr);
181 return ret;
182 }
183
PcieCntlrDmaUnmap(struct PcieCntlr * cntlr,uintptr_t addr,uint32_t len,uint8_t dir)184 void PcieCntlrDmaUnmap(struct PcieCntlr *cntlr, uintptr_t addr, uint32_t len, uint8_t dir)
185 {
186 if (cntlr == NULL) {
187 HDF_LOGE("PcieCntlrDmaUnmap: invalid param");
188 return;
189 }
190 PcieCntlrLock(cntlr);
191 cntlr->ops->dmaUnmap(cntlr, addr, len, dir);
192 cntlr->dmaCb = NULL;
193 PcieCntlrUnlock(cntlr);
194 }
195
PcieCntlrRegisterIrq(struct PcieCntlr * cntlr,PcieCallbackFunc cb)196 int32_t PcieCntlrRegisterIrq(struct PcieCntlr *cntlr, PcieCallbackFunc cb)
197 {
198 if (cntlr == NULL || cntlr->ops == NULL || cb == NULL) {
199 HDF_LOGE("PcieCntlrRegisterIrq: invalid param");
200 return HDF_ERR_INVALID_OBJECT;
201 }
202
203 PcieCntlrLock(cntlr);
204 if (cntlr->cb != NULL) {
205 HDF_LOGE("PcieCntlrRegisterIrq: irq has been registered");
206 PcieCntlrUnlock(cntlr);
207 return HDF_FAILURE;
208 }
209 cntlr->cb = cb;
210 if (cntlr->ops->registerIrq != NULL) {
211 cntlr->ops->registerIrq(cntlr);
212 }
213 PcieCntlrUnlock(cntlr);
214 return HDF_SUCCESS;
215 }
216
PcieCntlrUnregisterIrq(struct PcieCntlr * cntlr)217 void PcieCntlrUnregisterIrq(struct PcieCntlr *cntlr)
218 {
219 if (cntlr == NULL || cntlr->ops == NULL) {
220 HDF_LOGE("PcieCntlrUnregisterIrq: invalid param");
221 return;
222 }
223 PcieCntlrLock(cntlr);
224 if (cntlr->ops->unregisterIrq != NULL) {
225 cntlr->ops->unregisterIrq(cntlr);
226 }
227
228 cntlr->cb = NULL;
229 PcieCntlrUnlock(cntlr);
230 }
231
PcieCntlrCallback(struct PcieCntlr * cntlr)232 int32_t PcieCntlrCallback(struct PcieCntlr *cntlr)
233 {
234 if (cntlr == NULL) {
235 HDF_LOGE("PcieCntlrCallback: cntlr is null!");
236 return HDF_ERR_INVALID_OBJECT;
237 }
238 if (cntlr->cb != NULL) {
239 return cntlr->cb((DevHandle)cntlr);
240 }
241 return HDF_SUCCESS;
242 }
243
PcieCntlrDmaCallback(struct PcieCntlr * cntlr)244 int32_t PcieCntlrDmaCallback(struct PcieCntlr *cntlr)
245 {
246 if (cntlr == NULL) {
247 HDF_LOGE("PcieCntlrDmaCallback: cntlr is null!");
248 return HDF_ERR_INVALID_OBJECT;
249 }
250 if (cntlr->dmaCb != NULL) {
251 return cntlr->dmaCb((DevHandle)cntlr);
252 }
253 return HDF_SUCCESS;
254 }
255