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