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