1 /*
2 * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 "pin_hi35xx.h"
17 #include "device_resource_if.h"
18 #include "hdf_log.h"
19 #include "osal_io.h"
20 #include "osal_mem.h"
21 #include "pin_core.h"
22
23 #define HDF_LOG_TAG pin_hi35xx
24
25 #define HI35XX_PIN_FUNC_MAX 6
26 #define HI35XX_PIN_REG_SIZE 4
27
28 struct Hi35xxPinDesc {
29 const char *pinName;
30 uint32_t init;
31 uint32_t index;
32 int32_t pullType;
33 int32_t strength;
34 const char *func[HI35XX_PIN_FUNC_MAX];
35 };
36
37 struct Hi35xxPinCntlr {
38 struct PinCntlr cntlr;
39 struct Hi35xxPinDesc *desc;
40 volatile unsigned char *regBase;
41 uint16_t number;
42 uint32_t regStartBasePhy;
43 uint32_t regSize;
44 uint32_t pinCount;
45 };
46
Hi35xxPinSetPull(struct PinCntlr * cntlr,uint32_t index,enum PinPullType pullType)47 static int32_t Hi35xxPinSetPull(struct PinCntlr *cntlr, uint32_t index, enum PinPullType pullType)
48 {
49 uint32_t value;
50 struct Hi35xxPinCntlr *hi35xx = NULL;
51
52 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
53 value = OSAL_READL(hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
54 value = (value & ~PIN_PULL_TYPE_MASK) | ((uint32_t)pullType << PIN_PULL_TYPE_OFFSET);
55 OSAL_WRITEL(value, hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
56 HDF_LOGD("%s: set pin Pull success.", __func__);
57 return HDF_SUCCESS;
58 }
59
Hi35xxPinGetPull(struct PinCntlr * cntlr,uint32_t index,enum PinPullType * pullType)60 static int32_t Hi35xxPinGetPull(struct PinCntlr *cntlr, uint32_t index, enum PinPullType *pullType)
61 {
62 uint32_t value;
63 struct Hi35xxPinCntlr *hi35xx = NULL;
64 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
65
66 value = OSAL_READL(hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
67 *pullType = (enum PinPullType)((value & PIN_PULL_TYPE_MASK) >> PIN_PULL_TYPE_OFFSET);
68 HDF_LOGD("%s: get pin Pull success.", __func__);
69 return HDF_SUCCESS;
70 }
71
Hi35xxPinSetStrength(struct PinCntlr * cntlr,uint32_t index,uint32_t strength)72 static int32_t Hi35xxPinSetStrength(struct PinCntlr *cntlr, uint32_t index, uint32_t strength)
73 {
74 uint32_t value;
75 struct Hi35xxPinCntlr *hi35xx = NULL;
76
77 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
78 value = OSAL_READL(hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
79 value = (value & ~PIN_STRENGTH_MASK) | (strength << PIN_STRENGTH_OFFSET);
80 OSAL_WRITEL(value, hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
81 HDF_LOGD("%s: set pin Strength success.", __func__);
82 return HDF_SUCCESS;
83 }
84
Hi35xxPinGetStrength(struct PinCntlr * cntlr,uint32_t index,uint32_t * strength)85 static int32_t Hi35xxPinGetStrength(struct PinCntlr *cntlr, uint32_t index, uint32_t *strength)
86 {
87 uint32_t value;
88 struct Hi35xxPinCntlr *hi35xx = NULL;
89 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
90
91 value = OSAL_READL(hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
92 *strength = (value & PIN_STRENGTH_MASK) >> PIN_STRENGTH_OFFSET;
93 HDF_LOGD("%s: get pin Strength success.", __func__);
94 return HDF_SUCCESS;
95 }
96
Hi35xxPinSetFunc(struct PinCntlr * cntlr,uint32_t index,const char * funcName)97 static int32_t Hi35xxPinSetFunc(struct PinCntlr *cntlr, uint32_t index, const char *funcName)
98 {
99 uint32_t value;
100 int ret;
101 uint32_t funcNum;
102 struct Hi35xxPinCntlr *hi35xx = NULL;
103
104 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
105
106 for (funcNum = 0; funcNum < HI35XX_PIN_FUNC_MAX; funcNum++) {
107 ret = strcmp(funcName, hi35xx->desc[index].func[funcNum]);
108 if (ret == 0) {
109 value = OSAL_READL(hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
110 value = (value & ~PIN_FUNC_MASK) | funcNum;
111 OSAL_WRITEL(value, hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
112 HDF_LOGD("%s: set pin function success.", __func__);
113 return HDF_SUCCESS;
114 }
115 }
116 HDF_LOGE("%s: set pin Function failed.", __func__);
117 return HDF_ERR_IO;
118 }
119
Hi35xxPinGetFunc(struct PinCntlr * cntlr,uint32_t index,const char ** funcName)120 static int32_t Hi35xxPinGetFunc(struct PinCntlr *cntlr, uint32_t index, const char **funcName)
121 {
122 uint32_t value;
123 uint32_t funcNum;
124 struct Hi35xxPinCntlr *hi35xx = NULL;
125
126 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
127
128 value = OSAL_READL(hi35xx->regBase + index * HI35XX_PIN_REG_SIZE);
129 funcNum = value & PIN_FUNC_MASK;
130 *funcName = hi35xx->desc[index].func[funcNum];
131 HDF_LOGD("%s: get pin function success.", __func__);
132 return HDF_SUCCESS;
133 }
134
135 static struct PinCntlrMethod g_method = {
136 .SetPinPull = Hi35xxPinSetPull,
137 .GetPinPull = Hi35xxPinGetPull,
138 .SetPinStrength = Hi35xxPinSetStrength,
139 .GetPinStrength = Hi35xxPinGetStrength,
140 .SetPinFunc = Hi35xxPinSetFunc,
141 .GetPinFunc = Hi35xxPinGetFunc,
142 };
143
Hi35xxPinReadFunc(struct Hi35xxPinDesc * desc,const struct DeviceResourceNode * node,struct DeviceResourceIface * drsOps)144 static int32_t Hi35xxPinReadFunc(struct Hi35xxPinDesc *desc,
145 const struct DeviceResourceNode *node, struct DeviceResourceIface *drsOps)
146 {
147 int32_t ret;
148 uint32_t funcNum = 0;
149
150 ret = drsOps->GetString(node, "F0", &desc->func[funcNum], "NULL");
151 if (ret != HDF_SUCCESS) {
152 HDF_LOGE("%s: read F0 failed", __func__);
153 return ret;
154 }
155
156 funcNum++;
157 ret = drsOps->GetString(node, "F1", &desc->func[funcNum], "NULL");
158 if (ret != HDF_SUCCESS) {
159 HDF_LOGE("%s: read F1 failed", __func__);
160 return ret;
161 }
162
163 funcNum++;
164 ret = drsOps->GetString(node, "F2", &desc->func[funcNum], "NULL");
165 if (ret != HDF_SUCCESS) {
166 HDF_LOGE("%s: read F2 failed", __func__);
167 return ret;
168 }
169
170 funcNum++;
171 ret = drsOps->GetString(node, "F3", &desc->func[funcNum], "NULL");
172 if (ret != HDF_SUCCESS) {
173 HDF_LOGE("%s: read F3 failed", __func__);
174 return ret;
175 }
176
177 funcNum++;
178 ret = drsOps->GetString(node, "F4", &desc->func[funcNum], "NULL");
179 if (ret != HDF_SUCCESS) {
180 HDF_LOGE("%s: read F4 failed", __func__);
181 return ret;
182 }
183
184 funcNum++;
185 ret = drsOps->GetString(node, "F5", &desc->func[funcNum], "NULL");
186 if (ret != HDF_SUCCESS) {
187 HDF_LOGE("%s: read F5 failed", __func__);
188 return ret;
189 }
190 return HDF_SUCCESS;
191 }
192
Hi35xxPinParsePinNode(const struct DeviceResourceNode * node,struct Hi35xxPinCntlr * hi35xx,int32_t index)193 static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node,
194 struct Hi35xxPinCntlr *hi35xx, int32_t index)
195 {
196 int32_t ret;
197 struct DeviceResourceIface *drsOps = NULL;
198
199 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
200 if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
201 HDF_LOGE("%s: invalid drs ops fail!", __func__);
202 return HDF_FAILURE;
203 }
204 ret = drsOps->GetString(node, "pinName", &hi35xx->desc[index].pinName, "NULL");
205 if (ret != HDF_SUCCESS) {
206 HDF_LOGE("%s: read pinName failed", __func__);
207 return ret;
208 }
209
210 ret = drsOps->GetUint32(node, "init", &hi35xx->desc[index].init, 0);
211 if (ret != HDF_SUCCESS) {
212 HDF_LOGE("%s: read init failed", __func__);
213 return ret;
214 }
215
216 ret = Hi35xxPinReadFunc(&hi35xx->desc[index], node, drsOps);
217 if (ret != HDF_SUCCESS) {
218 HDF_LOGE("%s:Pin read Func failed", __func__);
219 return ret;
220 }
221 hi35xx->cntlr.pins[index].pinName = hi35xx->desc[index].pinName;
222 hi35xx->cntlr.pins[index].priv = (void *)node;
223 return HDF_SUCCESS;
224 }
225
Hi35xxPinCntlrInit(struct HdfDeviceObject * device,struct Hi35xxPinCntlr * hi35xx)226 static int32_t Hi35xxPinCntlrInit(struct HdfDeviceObject *device, struct Hi35xxPinCntlr *hi35xx)
227 {
228 struct DeviceResourceIface *drsOps = NULL;
229 int32_t ret;
230
231 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
232 if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
233 HDF_LOGE("%s: invalid drs ops fail!", __func__);
234 return HDF_FAILURE;
235 }
236 ret = drsOps->GetUint16(device->property, "number", &hi35xx->number, 0);
237 if (ret != HDF_SUCCESS) {
238 HDF_LOGE("%s: read number failed", __func__);
239 return ret;
240 }
241
242 ret = drsOps->GetUint32(device->property, "regStartBasePhy", &hi35xx->regStartBasePhy, 0);
243 if (ret != HDF_SUCCESS) {
244 HDF_LOGE("%s: read regStartBasePhy failed", __func__);
245 return ret;
246 }
247 ret = drsOps->GetUint32(device->property, "regSize", &hi35xx->regSize, 0);
248 if (ret != HDF_SUCCESS) {
249 HDF_LOGE("%s: read regSize failed", __func__);
250 return ret;
251 }
252 ret = drsOps->GetUint32(device->property, "pinCount", &hi35xx->pinCount, 0);
253 if (ret != HDF_SUCCESS) {
254 HDF_LOGE("%s: read pinCount failed", __func__);
255 return ret;
256 }
257 hi35xx->cntlr.pinCount = hi35xx->pinCount;
258 hi35xx->cntlr.number = hi35xx->number;
259 hi35xx->regBase = OsalIoRemap(hi35xx->regStartBasePhy, hi35xx->regSize);
260 if (hi35xx->regBase == NULL) {
261 HDF_LOGE("%s: remap Pin base failed", __func__);
262 return HDF_ERR_IO;
263 }
264 hi35xx->desc = (struct Hi35xxPinDesc *)OsalMemCalloc(sizeof(struct Hi35xxPinDesc) * hi35xx->pinCount);
265 hi35xx->cntlr.pins = (struct PinDesc *)OsalMemCalloc(sizeof(struct PinDesc) * hi35xx->pinCount);
266 return HDF_SUCCESS;
267 }
268
Hi35xxPinBind(struct HdfDeviceObject * device)269 static int32_t Hi35xxPinBind(struct HdfDeviceObject *device)
270 {
271 (void)device;
272 return HDF_SUCCESS;
273 }
274
Hi35xxPinInit(struct HdfDeviceObject * device)275 static int32_t Hi35xxPinInit(struct HdfDeviceObject *device)
276 {
277 int32_t ret;
278 int32_t index;
279 const struct DeviceResourceNode *childNode = NULL;
280 struct Hi35xxPinCntlr *hi35xx = NULL;
281
282 hi35xx = (struct Hi35xxPinCntlr *)OsalMemCalloc(sizeof(*hi35xx));
283 if (hi35xx == NULL) {
284 HDF_LOGE("%s: alloc hi35xx failed", __func__);
285 return HDF_ERR_MALLOC_FAIL;
286 }
287
288 ret = Hi35xxPinCntlrInit(device, hi35xx);
289 index = 0;
290
291 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
292 ret = Hi35xxPinParsePinNode(childNode, hi35xx, index);
293 if (ret != HDF_SUCCESS) {
294 return ret;
295 }
296 index++;
297 }
298
299 hi35xx->cntlr.method = &g_method;
300 ret = PinCntlrAdd(&hi35xx->cntlr);
301 if (ret != HDF_SUCCESS) {
302 HDF_LOGE("%s: add Pin cntlr: failed", __func__);
303 ret = HDF_FAILURE;
304 }
305 HDF_LOGI("%s: Pin Init success", __func__);
306 return HDF_SUCCESS;
307 }
308
Hi35xxPinRelease(struct HdfDeviceObject * device)309 static void Hi35xxPinRelease(struct HdfDeviceObject *device)
310 {
311 int32_t ret;
312 uint16_t number;
313 struct PinCntlr *cntlr = NULL;
314 struct Hi35xxPinCntlr *hi35xx = NULL;
315 struct DeviceResourceIface *drsOps = NULL;
316
317 HDF_LOGI("%s: enter", __func__);
318 if (device == NULL || device->property == NULL) {
319 HDF_LOGE("%s: device or property is null", __func__);
320 return;
321 }
322 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
323 if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
324 HDF_LOGE("%s: invalid drs ops", __func__);
325 return;
326 }
327
328 ret = drsOps->GetUint16(device->property, "number", &number, 0);
329 if (ret != HDF_SUCCESS) {
330 HDF_LOGE("%s: read cntlr number failed", __func__);
331 return;
332 }
333
334 cntlr = PinCntlrGetByNumber(number);
335 PinCntlrRemove(cntlr);
336 hi35xx = (struct Hi35xxPinCntlr *)cntlr;
337 if (hi35xx != NULL) {
338 if (hi35xx->regBase != NULL) {
339 OsalIoUnmap((void *)hi35xx->regBase);
340 }
341 OsalMemFree(hi35xx);
342 }
343 }
344
345 static struct HdfDriverEntry g_hi35xxPinDriverEntry = {
346 .moduleVersion = 1,
347 .Bind = Hi35xxPinBind,
348 .Init = Hi35xxPinInit,
349 .Release = Hi35xxPinRelease,
350 .moduleName = "hi35xx_pin_driver",
351 };
352 HDF_INIT(g_hi35xxPinDriverEntry);