• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Regulator
2
3
4## Overview
5
6### Regulator
7
8The regulator module controls the voltage and current supplies of some devices in the system. In an embedded system (especially a mobile phone), it is important to control the power consumption, which directly affects the battery endurance. You can use a regulator to shut down the power supply to an idle module in the system or reduce the voltage and current for the module.
9
10### Working Principles
11
12In the Hardware Driver Foundation (HDF), the regulator module uses the unified service mode for API adaptation. In this mode, a device service is used as the regulator manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies when there are many device objects of the same type, for example, when the regulator has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and more memory resources will be consumed by services.
13
14The regulator module is divided into the following layers:
15- Interface layer: provides APIs for opening or closing a device and writing data.
16- Core layer: provides the capabilities of binding, initializing, and releasing devices.
17- Adaptation layer: implements other functions.
18
19![](../public_sys-resources/icon-note.gif) **NOTE**<br/>The core layer can call the APIs of the interface layer and uses hooks to call APIs of the adaptation layer. In this way, the adaptation layer can indirectly call the APIs of the interface layer, but the interface layer cannot call the APIs of the adaptation layer.
20
21**Figure 1** Unified service mode
22
23![image1](figures/unified-service-mode.png)
24
25
26
27### Constraints
28
29Currently, the regulator module supports only the kernels (LiteOS) of mini and small systems.
30
31## Development Guidelines
32
33### When to Use
34
35The regulator module controls the voltage and current supplies of some devices in the system.
36
37### Available APIs
38
39The functions in **RegulatorMethod** are used to call the corresponding regulator driver functions:
40
41**RegulatorMethod** structure:
42
43```
44struct RegulatorMethod {
45    int32_t (*open)(struct RegulatorNode *node);
46    int32_t (*close)(struct RegulatorNode *node);
47    int32_t (*release)(struct RegulatorNode *node);
48    int32_t (*enable)(struct RegulatorNode *node);
49    int32_t (*disable)(struct RegulatorNode *node);
50    int32_t (*forceDisable)(struct RegulatorNode *node);
51    int32_t (*setVoltage)(struct RegulatorNode *node, uint32_t minUv, uint32_t maxUv);
52    int32_t (*getVoltage)(struct RegulatorNode *node, uint32_t *voltage);
53    int32_t (*setCurrent)(struct RegulatorNode *node, uint32_t minUa, uint32_t maxUa);
54    int32_t (*getCurrent)(struct RegulatorNode *node, uint32_t *regCurrent);
55    int32_t (*getStatus)(struct RegulatorNode *node, uint32_t *status);
56};
57```
58
59**Table 1** Description of the RegulatorMethod structure
60
61
62| Method    | Input Parameter                                                        | Return Value            | Description            |
63| ------------ | ----------------------------------------------------------- | ----------------- | ---------------- |
64| open         | **node**: structure pointer to the regulator node at the core layer.                 | HDF_STATUS| Opens a device.        |
65| close        | **node**: structure pointer to the regulator node at the core layer.                 | HDF_STATUS| Closes a device.        |
66| release      | **node**: structure pointer to the regulator node at the core layer.                 | HDF_STATUS| Releases a device handle.    |
67| enable       | **node**: structure pointer to the regulator node at the core layer.                 | HDF_STATUS| Enables a regulator.            |
68| disable      | **node**: structure pointer to the regulator node at the core layer.                 | HDF_STATUS| Disables a regulator.            |
69| forceDisable | **node**: structure pointer to the regulator node at the core layer.                 | HDF_STATUS| Forcibly disables a regulator.        |
70| setVoltage   | **node**: structure pointer to the regulator node at the core layer.<br>**minUv**: minimum voltage to set. It is a uint32_t variable.<br>**maxUv**: maximum voltage to set. It is a uint32_t variable.| HDF_STATUS| Sets the output voltage range.|
71| getVoltage   | **node**: structure pointer to the regulator node at the core layer.<br>**voltage**: pointer to the output voltage.| HDF_STATUS| Obtains the voltage.        |
72| setCurrent   | **node**: structure pointer to the regulator node at the core layer.<br>**minUa**: minimum current to set. It is a uint32_t variable.<br>**maxUa**: maximum current to set. It is a uint32_t variable.| HDF_STATUS| Sets the output current range.|
73| getCurrent   | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current.        |
74| getStatus    | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status.    |
75
76### How to Develop
77
78The regulator module adaptation procedure is as follows:
79
801. Instantiate the driver entry.
812. Configure attribute files.
823. Instantiate the core layer APIs.
834. Debug the driver.
84
85## Development Example
86
871.  Instantiate the driver entry.
88
89    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**.
90
91    In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
92
93    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.
94
95    ```
96    struct HdfDriverEntry g_regulatorDriverEntry = {
97        .moduleVersion = 1,
98        .moduleName = "virtual_regulator_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
99        .Init = VirtualRegulatorInit,
100        .Release = VirtualRegulatorRelease,
101    };
102    // Call HDF_INIT to register the driver entry with the HDF.
103    HDF_INIT(g_regulatorDriverEntry);
104    ```
105
1062. Configure attribute files.
107
108   - Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
109
110     The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **RegulatorNode** members at the core layer.
111
112     In the unified service mode, the first device node in the **device_info.hcs** file must be the regulator manager. The parameters must be set as follows:
113
114     | Member         | Value                                                          |
115     | --------------- | ------------------------------------------------------------ |
116     | policy          | **0**, which indicates that no service is published.                                     |
117     | priority        | Driver startup priority, which ranges form 0 to 200. A larger value indicates a lower priority. If the priorities are the same, the device loading sequence is not ensured.|
118     | permission      | Driver permission.                                                    |
119     | moduleName      | **HDF_PLATFORM_REGULATOR_MANAGER**                       |
120     | serviceName     | **HDF_PLATFORM_REGULATOR_MANAGER**                        |
121     | deviceMatchAttr | Reserved.                                            |
122
123     Configure regulator controller information from the second node. This node specifies a type of regulator controllers rather than a specific regulator controller. In this example, there is only one regulator device. If there are multiple regulator devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **regulator\_config** file.
124
125    - **device_info.hcs** configuration example
126
127       ```
128       root {
129       device_info {
130         platform :: host {
131           hostName = "platform_host";
132           priority = 50;
133           device_regulator :: device {
134               device0:: deviceNode {   // Set an HDF device node for each regulator controller.
135                   policy = 1;	         // Policy for the driver to publish services.
136                   priority = 50;	     // Driver startup priority.
137                   permission = 0644;   // Permission to create device nodes for the driver.
138                   /* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
139                   moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
140                   serviceName = "HDF_PLATFORM_REGULATOR_MANAGER";		// (Mandatory) Unique name of the service published by the driver.
141                   /* (Mandatory) Set the controller private data, which must be same as that in regulator_config.hcs. */
142                   deviceMatchAttr = "hdf_platform_regulator_manager";
143               }
144               device1 :: deviceNode {
145                   policy = 0;
146                   priority = 55;
147                   permission = 0644;
148                   moduleName = "linux_regulator_adapter";
149                   deviceMatchAttr = "linux_regulator_adapter";
150               }
151           }
152         }
153       }
154       }
155       ```
156
157    - **regulator\_config.hcs** configuration example:
158
159      ```
160      root {
161          platform {
162              regulator_config {
163              match_attr = "linux_regulator_adapter";
164              template regulator_controller {    // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
165                  device_num = 1;
166                  name = "";
167                  devName = "regulator_adapter_consumer01";
168                  supplyName = "";
169                  mode = 1;
170                  minUv = 0;
171                  maxUv = 20000;
172                  minUa = 0;
173                  maxUa = 0;
174                  }
175              controller_0x130d0000 :: regulator_controller {
176                  device_num = 1;
177                  name = "regulator_adapter_1";
178                  devName = "regulator_adapter_consumer01";
179                  supplyName = "virtual-regulator-hdf-adapter";
180                  mode = 1;
181                  minUv = 1000;
182                  maxUv = 50000;
183                  minUa = 0;
184                  maxUa = 0;
185                  }
186              /* Each regulator controller corresponds to a controller node. If there are multiple regulator controllers, add the corresponding controller nodes one by one. */
187              controller_0x130d0001 :: regulator_controller {
188                  device_num = 1;
189                  name = "regulator_adapter_2";
190                  devName = "regulator_adapter_consumer01";
191                  supplyName = "virtual2-regulator-hdf-adapter";
192                  mode = 2;
193                  minUv = 0;
194                  maxUv = 0;
195                  minUa = 1000;
196                  maxUa = 50000;
197                  }
198              }
199          }
200      }
201      ```
202
2033. Instantiate the core layer APIs.
204
205   Initialize the **RegulatorNode** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) to instantiate **RegulatorMethod** in **RegulatorNode** (so that the underlying driver functions can be called).
206
207   - Defining a custom structure
208
209       The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator_config.hcs** using **DeviceResourceIface**.
210
211       ```
212       // RegulatorNode is the core layer controller structure. The Init function assigns values to the members of RegulatorNode.
213       struct RegulatorNode {
214           struct RegulatorDesc regulatorInfo;
215           struct DListHead node;
216           struct RegulatorMethod *ops;
217           void *priv;
218           struct OsalMutex lock;
219       };
220
221       struct RegulatorDesc {
222           const char *name;                           /* Regulator name. */
223           const char *parentName;                     /* Regulator parent node name. */
224           struct RegulatorConstraints constraints;    /* Regulator constraint information. */
225           uint32_t minUv;                             /* Minimum output voltage. */
226           uint32_t maxUv;                             /* Maximum output voltage. */
227           uint32_t minUa;                             /* Minimum output current. */
228           uint32_t maxUa;                             /* Maximum output current. */
229           uint32_t status;                            /* Regulator status, which can be on or off. */
230           int useCount;
231           int consumerRegNums;                        /* Number of the regulator consumers. */
232           RegulatorStatusChangecb cb;                 /* Variable used to notify the regulator status changes. */
233       };
234
235       struct RegulatorConstraints {
236           uint8_t alwaysOn;     /* Whether the regulator is always on. */
237           uint8_t mode;         /* Voltage or current. */
238           uint32_t minUv;       /* Minimum output voltage allowed. */
239           uint32_t maxUv;       /* Maximum output voltage allowed. */
240           uint32_t minUa;       /* Minimum output current allowed. */
241           uint32_t maxUa;       /* Maximum output current allowed. */
242       };
243       ```
244
245
246
247   - Instantiating **RegulatorMethod** (other members are initialized by **Init**)
248
249     ```c
250     // Example of regulator_virtual.c: Instantiate the hooks.
251     static struct RegulatorMethod g_method = {
252         .enable = VirtualRegulatorEnable,
253         .disable = VirtualRegulatorDisable,
254         .setVoltage = VirtualRegulatorSetVoltage,
255         .getVoltage = VirtualRegulatorGetVoltage,
256         .setCurrent = VirtualRegulatorSetCurrent,
257         .getCurrent = VirtualRegulatorGetCurrent,
258         .getStatus = VirtualRegulatorGetStatus,
259     };
260     ```
261
262
263
264   - **Init** function
265
266     **Input parameter**:
267
268     **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
269
270     **Return value**:
271
272     **HDF\_STATUS**
273
274     The table below describes some status. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.
275
276     **Table 2** Description of HDF_STATUS
277
278     | Status             | Description         |
279     | ---------------------- | -------------- |
280     | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
281     | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory.  |
282     | HDF_ERR_INVALID_PARAM  | Invalid parameter.      |
283     | HDF_ERR_IO             | I/O error.      |
284     | HDF_SUCCESS            | Initialization successful.    |
285     | HDF_FAILURE            | Initialization failed.    |
286
287     **Function description**:
288
289     Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer.
290
291
292     ```c
293       static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device)
294       {
295           int32_t ret;
296           const struct DeviceResourceNode *childNode = NULL;
297           ...
298           DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
299           ret = VirtualRegulatorParseAndInit(device, childNode);// (Mandatory) The implementation is as follows:
300           ...
301           }
302           ...
303       }
304
305       static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
306       {
307           int32_t ret;
308           struct RegulatorNode *regNode = NULL;
309           (void)device;
310
311           regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));// Load the .hcs file.
312           ...
313           ret = VirtualRegulatorReadHcs(regNode, node);                     // Read .hcs information.
314           ...
315           regNode->priv = (void *)node; ;                                   // Instantiate the node.
316           regNode->ops = &g_method;                                         // Instantiate OPS.
317
318           ret = RegulatorNodeAdd(regNode);                                  // Add the node.
319           ...
320       }
321     ```
322
323   -   **Release** function
324
325        **Input parameter**:
326
327        **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
328
329        **Return value**:
330
331         No value is returned.
332
333        **Function description**:
334
335        Releases the memory and deletes the controller. This function assigns values to the **Release** function 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.
336
337       ```c
338       static void VirtualRegulatorRelease(struct HdfDeviceObject *device)
339       {
340           ...
341           RegulatorNodeRemoveAll();// (Mandatory) Call the function at the core layer to release regulator controller devices and services.
342       }
343       ```
344
3454. Debug the driver.
346
347   (Optional) Verify the basic functions of the new driver, for example, check whether the test cases are successful after the driver is loaded.
348
349
350