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