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 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 386 – 387 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