• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Pin
2
3
4## Overview
5
6### Pin
7The pin, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function.
8
9### Basic Concepts
10
11Pin, as a software concept, provides APIs for uniformly managing the pins from different SoC vendors, providing the pin multiplexing function, and configuring the electrical features of pins.
12
13- SoC
14
15  An SOC is a chip that integrates microprocessors, analog IP cores, digital IP cores, and memory for specific purposes.
16
17- Pin multiplexing
18
19  When the number of pins of a chip cannot handle the increasing connection requests, you can set the software registers to make the pins to work in different states.
20
21### Working Principles
22
23In the HDF, the pin module does not support the user mode and therefore does not need to publish services. It uses the service-free mode in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
24
25The pin module is divided into the following layers:
26
27- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
28- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks.
29- Adaptation layer: instantiates hooks to implement specific functions.
30
31**Figure 1** Service-free mode
32
33![](figures/service-free-mode.png)
34
35### Constraints
36
37Currently, the pin module supports only the kernels (LiteOS) of mini and small systems.
38
39## Development Guidelines
40
41### When to Use
42
43The pin module is used to manage pin resources. When the devices from SoC vendors interconnect with the HDF, the pin driver needs to be adapted.
44
45### Available APIs
46
47The **PinCntlrMethod** APIs are used to call the functions of the pin driver.
48**PinCntlrMethod** definition:
49
50```c
51struct PinCntlrMethod {
52    int32_t (*SetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType pullType);
53    int32_t (*GetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType *pullType);
54    int32_t (*SetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t strength);
55    int32_t (*GetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t *strength);
56    int32_t (*SetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char *funcName);
57    int32_t (*GetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char **funcName);
58};
59```
60
61**Table 1** APIs for the members in the PinCntlrMethod structure
62
63| API    | Input Parameter                                       | Output Parameter                                  | Return Value| Description|
64| ------------ | ------------------------------------------- | ------ | ---- | ---- |
65| SetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pull type of the pin. It is an enum constant.| -|HDF_STATUS|Sets the pull type of a pin.|
66| GetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **pullType**: pointer to the pull type of the pin.| HDF_STATUS| Obtains the pull type of a pin.|
67| SetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pull strength of the pin. It is a uint32_t variable.| -| HDF_STATUS| Sets the pull strength of a pin.|
68| GetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **strength**: pointer to the pull strength of the pin.| HDF_STATUS| Obtains the pull strength of a pin.|
69| SetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char pointer to the pin function.| -| HDF_STATUS| Sets the pin function.|
70| GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **funcName**: char double pointer to the pin function.| HDF_STATUS| Obtains the pin function.|
71
72### How to Develop
73
74The pin module adaptation procedure is as follows:
75
76- Instantiate the driver entry.
77- Configure attribute files.
78- Instantiate the core layer APIs.
79- Debug the driver.
80
811. Instantiate the driver entry.
82
83   - Instantiate the **HdfDriverEntry** structure.
84     Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**.
85
86   - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
87     Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
88
89        ```c
90        static struct HdfDriverEntry g_hi35xxPinDriverEntry = {
91            .moduleVersion = 1,
92            .Bind = Hi35xxPinBind,
93            .Init = Hi35xxPinInit,
94            .Release = Hi35xxPinRelease,
95            .moduleName = "hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
96        };
97        HDF_INIT(g_hi35xxPinDriverEntry);// Call HDF_INIT to register the driver entry with the HDF.
98        ```
99
1002. Configure attribute files.
101   - Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
102        ```c
103        root {
104            device_info {
105                platform :: host {
106                    hostName = "platform_host";
107                    priority = 50;
108                    device_pin :: device {
109                        device0:: deviceNode {   // Set an HDF device node for each pin controller.
110                            policy = 0;			  // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
111                            priority = 10;        // Driver startup priority.
112                            permission = 0644;    // Permission to create device nodes for the driver.
113                            /* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
114                            moduleName = "hi35xx_pin_driver";
115                            /* (Mandatory) Set the controller private data, which must be same as that in pin_config.hcs. */
116                            deviceMatchAttr = "hisilicon_hi35xx_pin_0";
117                        }
118                        device1 :: deviceNode {
119                            policy = 0;
120                            priority = 10;
121                            permission = 0644;
122                            moduleName = "hi35xx_pin_driver";
123                            deviceMatchAttr = "hisilicon_hi35xx_pin_1";
124                        }
125                        ......
126                    }
127                }
128            }
129        }
130        ```
131   - Add the **pin_config.hcs** file.
132     Configure the device attributes in the **device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs** file. The parameters are set as follows:
133        ```c
134        root {
135            platform {
136                pin_config_hi35xx {
137                    template pin_controller {    // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
138                        number = 0;              // (Mandatory) Controller ID.
139                        regStartBasePhy = 0;     // (Mandatory) Start physical base address of the register.
140                        regSize = 0;           // (Mandatory) Register bit width.
141                        PinCount = 0;            // (Mandatory) Number of pins.
142                        match_attr = "";
143                        template pin_desc {
144                            pinName = "";        // (Mandatory) Name of the pin.
145                            init = 0;           // (Mandatory) Default value of the register.
146                            F0 = "";             // (Mandatory) Function 0.
147                            F1 = "";             // Function 1.
148                            F2 = "";             // Function 2.
149                            F3 = "";             // Function 3.
150                            F4 = "";             // Function 4.
151                            F5 = "";             // Function 5.
152                        }
153                    }
154                    controller_0 :: pin_controller {
155                        number = 0;
156                        regStartBasePhy = 0x10FF0000;
157                        regSize = 0x48;
158                        pinCount = 18;
159                        match_attr = "hisilicon_hi35xx_pin_0";
160                        T1 :: pin_desc {
161                            pinName = "T1";
162                            init = 0x0600;
163                            F0 = "EMMC_CLK";
164                            F1 = "SFC_CLK";
165                            F2 = "SFC_BOOT_MODE";
166                        }
167                        ...... // Correspond to the pins of the pin controller. Add pins according to actual situation.
168                    }
169                    ...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
170                }
171            }
172        }
173        ```
174
1753. Instantiate the pin controller object.
176   - Initialize the **PinCntlr** object.
177     Call **Hi35xxPinCntlrInit** to initialize the **PinCntlr** members.
178
179        ```c
180        struct Hi35xxPinDesc {
181            // Pin name.
182            const char *pinName;
183            // Initial value.
184            uint32_t init;
185            // Index of the pin.
186            uint32_t index;
187            // Pull type of the pin.
188            int32_t pullType;
189            // Pull strength of the pin.
190            int32_t strength;
191            // Array of pin function names.
192            const char *func[HI35XX_PIN_FUNC_MAX];
193        };
194
195        struct Hi35xxPinCntlr {
196            // Pin controller.
197            struct PinCntlr cntlr;
198            // Pointer to the pin description structure.
199            struct Hi35xxPinDesc *desc;
200            // Register mapping address.
201            volatile unsigned char *regBase;
202            // ID of the pin controller.
203            uint16_t number;
204            // Start address of the register physical base addresses.
205            uint32_t regStartBasePhy;
206            // Register bit width.
207            uint32_t regSize;
208            // Number of pins.
209            uint32_t pinCount;
210        };
211
212        // PinCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init() function.
213        struct PinCntlr {
214            struct IDeviceIoService service;
215            struct HdfDeviceObject *device;
216            struct PinCntlrMethod *method;
217            struct DListHead node; // Node in the linked list.
218            OsalSpinlock spin;      // Spinlock.
219            uint16_t number;       // ID of the pin controller.
220            uint16_t pinCount;      // Number of pins.
221            struct PinDesc *pins;
222            void *priv;             // Private data.
223        };
224
225        // Initialize PinCntlr.
226        static int32_t Hi35xxPinCntlrInit(struct HdfDeviceObject *device, struct Hi35xxPinCntlr *hi35xx)
227        {
228            struct DeviceResourceIface *drsOps = NULL;
229            int32_t ret;
230            // Read the pin controller attributes from the .hcs file.
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            // Assign the values read to the members of the pin controller to initialize the pin controller.
258            hi35xx->cntlr.pinCount = hi35xx->pinCount;
259            hi35xx->cntlr.number = hi35xx->number;
260            hi35xx->regBase = OsalIoRemap(hi35xx->regStartBasePhy, hi35xx->regSize); // Pin controller mapping.
261            if (hi35xx->regBase == NULL) {
262                HDF_LOGE("%s: remap Pin base failed", __func__);
263                return HDF_ERR_IO;
264            }
265            hi35xx->desc = (struct Hi35xxPinDesc *)OsalMemCalloc(sizeof(struct Hi35xxPinDesc) * hi35xx->pinCount);
266            hi35xx->cntlr.pins = (struct PinDesc *)OsalMemCalloc(sizeof(struct PinDesc) * hi35xx->pinCount);
267            return HDF_SUCCESS;
268        }
269        ```
270
271   - Instantiate the callback structure **PinCntlrMethod** in **PinCntlr**. Other members are initialized by using the **Init()** function.
272
273        ```c
274        // The members of the PinCntlrMethod structure are all callbacks. Vendors need to implement the corresponding functions according to Table 1.
275        static struct PinCntlrMethod g_method = {
276            .SetPinPull = Hi35xxPinSetPull,              // Set the pull type.
277            .GetPinPull = Hi35xxPinGetPull,             // Obtains the pull type.
278            .SetPinStrength = Hi35xxPinSetStrength,      // Set the pull strength.
279            .GetPinStrength = Hi35xxPinGetStrength,      // Obtains the pull strength.
280            .SetPinFunc = Hi35xxPinSetFunc,              // Set the pin functions.
281            .GetPinFunc = Hi35xxPinGetFunc,              // Obtain the pin functions.
282        };
283        ```
284
285   - **Init()** function
286
287        Input parameters:
288        **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
289
290        Return value:
291        **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
292
293        | **State**          | **Description**  |
294        | ---------------------- | -------------- |
295        | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
296        | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory.  |
297        | HDF_ERR_INVALID_PARAM  | Invalid parameter.      |
298        | HDF_ERR_IO             | I/O error.      |
299        | HDF_SUCCESS            | Initialization successful.    |
300        | HDF_FAILURE            | Initialization failed.    |
301
302        Function description:
303        Initializes the custom structure object and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd()** function.
304
305        ```c
306        static int32_t Hi35xxPinReadFunc(struct Hi35xxPinDesc *desc, const struct DeviceResourceNode *node, struct DeviceResourceIface *drsOps)
307        {
308            int32_t ret;
309            uint32_t funcNum = 0;
310            // Read the pin function names of the pin controller child nodes from the .hcs file.
311            ret = drsOps->GetString(node, "F0", &desc->func[funcNum], "NULL");
312            if (ret != HDF_SUCCESS) {
313                HDF_LOGE("%s: read F0 failed", __func__);
314                return ret;
315            }
316
317            funcNum++;
318            ret = drsOps->GetString(node, "F1", &desc->func[funcNum], "NULL");
319            if (ret != HDF_SUCCESS) {
320                HDF_LOGE("%s: read F1 failed", __func__);
321                return ret;
322            }
323
324            funcNum++;
325            ......
326            return HDF_SUCCESS;
327        }
328
329        static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node, struct Hi35xxPinCntlr *hi35xx, int32_t index)
330        {
331            int32_t ret;
332            struct DeviceResourceIface *drsOps = NULL;
333            // Read the pin attributes of the pin controller child nodes from the .hcs file.
334            drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
335            if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
336                HDF_LOGE("%s: invalid drs ops fail!", __func__);
337                return HDF_FAILURE;
338            }
339            ret = drsOps->GetString(node, "pinName", &hi35xx->desc[index].pinName, "NULL");
340            if (ret != HDF_SUCCESS) {
341                HDF_LOGE("%s: read pinName failed", __func__);
342                return ret;
343            }
344            ......
345            ret = Hi35xxPinReadFunc(&hi35xx->desc[index], node, drsOps);
346            if (ret != HDF_SUCCESS) {
347                HDF_LOGE("%s:Pin read Func failed", __func__);
348                return ret;
349            }
350            hi35xx->cntlr.pins[index].pinName = hi35xx->desc[index].pinName;
351            hi35xx->cntlr.pins[index].priv = (void *)node;
352            ......
353            return HDF_SUCCESS;
354        }
355
356        static int32_t Hi35xxPinInit(struct HdfDeviceObject *device)
357        {
358            ......
359            struct Hi35xxPinCntlr *hi35xx = NULL;
360            ......
361            ret = Hi35xxPinCntlrInit(device, hi35xx);    // Initialize the pin controller.
362            ......
363            DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { // Traverses each child node of the pin controller.
364                ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); // Parsing the child nodes.
365                ......
366            }
367
368            hi35xx->cntlr.method = &g_method;   // Instantiate method.
369            ret = PinCntlrAdd(&hi35xx->cntlr);   // Connect to the controller.
370            if (ret != HDF_SUCCESS) {
371                HDF_LOGE("%s: add Pin cntlr: failed", __func__);
372                ret = HDF_FAILURE;
373            }
374            return HDF_SUCCESS;
375        }
376        ```
377
378   - **Release()** function
379
380        Input parameters:
381
382        **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
383
384        Return value:
385
386387
388        Function description:
389
390        Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources.
391
392        ```c
393        static void Hi35xxPinRelease(struct HdfDeviceObject *device)
394        {
395            int32_t ret;
396            uint16_t number;
397            struct PinCntlr *cntlr = NULL;
398            struct Hi35xxPinCntlr *hi35xx = NULL;
399            struct DeviceResourceIface *drsOps = NULL;
400
401            if (device == NULL || device->property == NULL) {
402                HDF_LOGE("%s: device or property is null", __func__);
403                return;
404            }
405            // Read the pin controller ID from the .hcs file.
406            drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
407            if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
408                HDF_LOGE("%s: invalid drs ops", __func__);
409                return;
410            }
411            ret = drsOps->GetUint16(device->property, "number", &number, 0);
412            if (ret != HDF_SUCCESS) {
413                HDF_LOGE("%s: read cntlr number failed", __func__);
414                return;
415            }
416
417            cntlr = PinCntlrGetByNumber(number);   // Obtain the pin controller based on the controller ID.
418            PinCntlrRemove(cntlr);
419            hi35xx = (struct Hi35xxPinCntlr *)cntlr;
420            if (hi35xx != NULL) {
421                if (hi35xx->regBase != NULL) {
422                    OsalIoUnmap((void *)hi35xx->regBase);
423                }
424                OsalMemFree(hi35xx);
425            }
426        }
427        ```
4284. Debug the driver.
429   (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
430