1e41f4b71Sopenharmony_ci# Clock 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Function 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThe clock regulates the timing and speed of all functions in a device. For example, the CPU clock is an internal time generator of the CPU. It operates in frequency and used to synchronize and control the operations within the CPU. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci### Basic Concepts 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciThe clock signal is used to synchronize and control the operations of the modules or components of an electronic device. It serves as a fundamental signal reference source to ensure proper functioning and accurate data transmission. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci### Working Principles 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ciIn the Hardware Driver Foundation (HDF), the **Clock** module uses the unified service mode for API adaptation. In this mode, a service is used as the clock manager to handle external access requests in a unified manner. The unified service mode applies when the system has multiple device objects of the same type. If the independent service mode is used in this case, more device nodes need to be configured and more memory resources will be consumed. The **Clock** module uses the unified service mode (see **Figure 1**). 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ciThe **Clock** module is divided into the following layers: 18e41f4b71Sopenharmony_ci- Interface layer: provides the APIs for opening a device, writing data, and closing a device. 19e41f4b71Sopenharmony_ci- Core layer: binds services, initializes and releases the PlatformManager, and provides the capabilities of adding, deleting, and obtaining controllers. 20e41f4b71Sopenharmony_ci- Adaptation layer: implements hardware-related functions, such as controller initialization. 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ciIn the unified service mode, the core layer manages all controllers in a unified manner and publishes a service for the interface layer. That is, the driver does not need to publish a service for each controller. 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci**Figure 1** Unified service mode 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci## Usage Guidelines 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci### When to Use 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ciThe **Clock** module provides chip-level clock management, including frequency division, frequency multiplication, clock source selection, and clock gating within the chip. Proper clock management can enhance chip efficiency while streamlining coordination and synergy among all functional components. 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci### Available APIs 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ciTo enable applications to successfully operate the hardware by calling the **Clock** APIs, the system provides the following hook APIs in **//drivers/hdf_core/framework/support/platform/include/clock/clock_core.h** for the core layer. You need to implement these hook APIs at the adaptation layer and hook them to implement the interaction between the interface layer and the core layer. 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ciDefinitions of **ClockMethod** and **ClockLockMethod**: 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ci```c 42e41f4b71Sopenharmony_cistruct ClockMethod { 43e41f4b71Sopenharmony_ci int32_t (*start)(struct ClockDevice *device); 44e41f4b71Sopenharmony_ci int32_t (*stop)(struct ClockDevice *device); 45e41f4b71Sopenharmony_ci int32_t (*setRate)(struct ClockDevice *device, uint32_t rate); 46e41f4b71Sopenharmony_ci int32_t (*getRate)(struct ClockDevice *device, uint32_t *rate); 47e41f4b71Sopenharmony_ci int32_t (*disable)(struct ClockDevice *device); 48e41f4b71Sopenharmony_ci int32_t (*enable)(struct ClockDevice *device); 49e41f4b71Sopenharmony_ci struct ClockDevice *(*getParent)(struct ClockDevice *device); 50e41f4b71Sopenharmony_ci int32_t (*setParent)(struct ClockDevice *device, struct ClockDevice *parent); 51e41f4b71Sopenharmony_ci}; 52e41f4b71Sopenharmony_ci 53e41f4b71Sopenharmony_cistruct ClockLockMethod { 54e41f4b71Sopenharmony_ci int32_t (*lock)(struct ClockDevice *device); 55e41f4b71Sopenharmony_ci void (*unlock)(struct ClockDevice *device); 56e41f4b71Sopenharmony_ci}; 57e41f4b71Sopenharmony_ci 58e41f4b71Sopenharmony_ci``` 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ciThe **ClockMethod** method must be implemented at the adaptation layer, and **ClockLockMethod** can be implemented based on service requirements. The core layer provides the default **ClockLockMethod** method, in which a spinlock is used to protect the critical section. 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci```c 63e41f4b71Sopenharmony_cistatic int32_t ClockDeviceLockDefault(struct ClockDevice *device) 64e41f4b71Sopenharmony_ci{ 65e41f4b71Sopenharmony_ci if (device == NULL) { 66e41f4b71Sopenharmony_ci HDF_LOGE("ClockDeviceLockDefault: device is null!"); 67e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 68e41f4b71Sopenharmony_ci } 69e41f4b71Sopenharmony_ci return OsalSpinLock(&device->spin); 70e41f4b71Sopenharmony_ci} 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_cistatic void ClockDeviceUnlockDefault(struct ClockDevice *device) 73e41f4b71Sopenharmony_ci{ 74e41f4b71Sopenharmony_ci if (device == NULL) { 75e41f4b71Sopenharmony_ci HDF_LOGE("ClockDeviceUnlockDefault: device is null!"); 76e41f4b71Sopenharmony_ci return; 77e41f4b71Sopenharmony_ci } 78e41f4b71Sopenharmony_ci (void)OsalSpinUnlock(&device->spin); 79e41f4b71Sopenharmony_ci} 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_cistatic const struct ClockLockMethod g_clockLockOpsDefault = { 82e41f4b71Sopenharmony_ci .lock = ClockDeviceLockDefault, 83e41f4b71Sopenharmony_ci .unlock = ClockDeviceUnlockDefault, 84e41f4b71Sopenharmony_ci}; 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ci``` 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ciIf spinlock cannot be used, you can use another type of lock to implement **ClockLockMethod**. The customized **ClockLockMethod** method will replace the default **ClockLockMethod** method. 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci **Table 1** Hook APIs in **ClockMethod** 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci| API | Input Parameter| Output Parameter| Return Value| Description| 93e41f4b71Sopenharmony_ci| -------- | -------- | -------- | -------- | -------- | 94e41f4b71Sopenharmony_ci| start | **device**: structure pointer to the clock controller at the core layer.| –| HDF_STATUS | Starts a clock device. | 95e41f4b71Sopenharmony_ci| stop | **device**: structure pointer to the clock controller at the core layer.| –| HDF_STATUS | Stops a clock device. | 96e41f4b71Sopenharmony_ci| setRate | **device**: structure pointer to the clock controller at the core layer.| –| HDF_STATUS | Sets the clock rate. | 97e41f4b71Sopenharmony_ci| getRate | **device**: structure pointer to the clock controller at the core layer.| Clock rate obtained. | HDF_STATUS | Obtains the clock rate. | 98e41f4b71Sopenharmony_ci| disable | **device**: structure pointer to the clock controller at the core layer.| –| HDF_STATUS | Enables clock. | 99e41f4b71Sopenharmony_ci| enable | **device**: structure pointer to the clock controller at the core layer.| –| HDF_STATUS | Disables clock. | 100e41f4b71Sopenharmony_ci| getParent | **device**: structure pointer to the clock controller at the core layer.| Structure pointer to the clock controller obtained. | HDF_STATUS | Obtains the parent clock. | 101e41f4b71Sopenharmony_ci| setParent | **device**: structure pointer to the clock controller at the core layer.| –| HDF_STATUS | Sets the parent clock. | 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ci**Table 2** APIs in **ClockLockMethod** 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci| Function| Input Parameter| Output Parameter| Return Value| Description| 106e41f4b71Sopenharmony_ci| -------- | -------- | -------- | -------- | -------- | 107e41f4b71Sopenharmony_ci| lock | **device**: structure pointer to the clock device object at the core layer.| –| HDF_STATUS| Acquires the critical section lock. | 108e41f4b71Sopenharmony_ci| unlock | **device**: structure pointer to the clock device object at the core layer.| –| HDF_STATUS| Releases the critical section lock.| 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci### How to Develop 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ciThe **Clock** module adaptation involves the following steps: 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ci1. Instantiate the driver entry. 115e41f4b71Sopenharmony_ci - Instantiate the **HdfDriverEntry** structure. 116e41f4b71Sopenharmony_ci - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF. 117e41f4b71Sopenharmony_ci 118e41f4b71Sopenharmony_ci2. Configure attribute files. 119e41f4b71Sopenharmony_ci - Add the **deviceNode** information to the **device_info.hcs** file. 120e41f4b71Sopenharmony_ci - (Optional) Add the **clock_config.hcs** file. 121e41f4b71Sopenharmony_ci 122e41f4b71Sopenharmony_ci3. Instantiate the core layer APIs. 123e41f4b71Sopenharmony_ci - Initialize **ClockDevice**. 124e41f4b71Sopenharmony_ci - Instantiate **ClockMethod** in the **ClockDevice** object. 125e41f4b71Sopenharmony_ci > **NOTE** 126e41f4b71Sopenharmony_ci > 127e41f4b71Sopenharmony_ci > For details about the functions in **ClockMethod**, see [Available APIs](#available-apis). 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci4. (Optional) Debug the driver. 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci Verify the basic driver functionalities. 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ci### Example 135e41f4b71Sopenharmony_ci 136e41f4b71Sopenharmony_ciThe following uses the RK3568 driver **//drivers/hdf_core/adapter/khdf/linux/platform/clock/clock_adapter.c** as an example to describe how to perform the clock driver adaptation. 137e41f4b71Sopenharmony_ci 138e41f4b71Sopenharmony_ci1. Instantiate the driver entry. 139e41f4b71Sopenharmony_ci 140e41f4b71Sopenharmony_ci The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **//drivers/hdf_core/interfaces/inner_api/host/shared/hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. 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. 141e41f4b71Sopenharmony_ci 142e41f4b71Sopenharmony_ci Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. 143e41f4b71Sopenharmony_ci 144e41f4b71Sopenharmony_ci Clock driver entry example: 145e41f4b71Sopenharmony_ci 146e41f4b71Sopenharmony_ci Multiple devices may connect to the clock controller. In the HDF, a manager object needs to be created for this type of devices. When a device needs to be started, the manager object locates the target device based on the specified parameters. 147e41f4b71Sopenharmony_ci 148e41f4b71Sopenharmony_ci You do not need to implement the driver of the clock manager, which is implemented by the core layer. However, the **ClockDeviceAdd** method of the core layer must be invoked in the **Init** method to implement the related features. 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci ```c 151e41f4b71Sopenharmony_ci struct HdfDriverEntry g_clockLinuxDriverEntry = { 152e41f4b71Sopenharmony_ci .moduleVersion = 1, 153e41f4b71Sopenharmony_ci .Bind = NULL, 154e41f4b71Sopenharmony_ci .Init = LinuxClockInit, 155e41f4b71Sopenharmony_ci .Release = LinuxClockRelease, 156e41f4b71Sopenharmony_ci .moduleName = "linux_clock_adapter", // (Mandatory) The value must be the same as the module name in the device_info.hcs file. 157e41f4b71Sopenharmony_ci }; 158e41f4b71Sopenharmony_ci HDF_INIT(g_clockLinuxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. 159e41f4b71Sopenharmony_ci 160e41f4b71Sopenharmony_ci /* Driver entry of the clock_core.c manager service at the core layer */ 161e41f4b71Sopenharmony_ci struct HdfDriverEntry g_clockManagerEntry = { 162e41f4b71Sopenharmony_ci .moduleVersion = 1, 163e41f4b71Sopenharmony_ci .Bind = ClockManagerBind, 164e41f4b71Sopenharmony_ci .Init = ClockManagerInit, 165e41f4b71Sopenharmony_ci .Release = ClockManagerRelease, 166e41f4b71Sopenharmony_ci .moduleName = "HDF_PLATFORM_CLOCK_MANAGER", // The value must be that of device0 in the device_info.hcs file. 167e41f4b71Sopenharmony_ci }; 168e41f4b71Sopenharmony_ci HDF_INIT(g_clockManagerEntry); 169e41f4b71Sopenharmony_ci ``` 170e41f4b71Sopenharmony_ci 171e41f4b71Sopenharmony_ci2. Add the **deviceNode** information to the **//vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs** file and configure the device attributes in **clock_config.hcs**. 172e41f4b71Sopenharmony_ci 173e41f4b71Sopenharmony_ci The **deviceNode** information is related to the driver entry registration. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **ClockDevice** members at the core layer. 174e41f4b71Sopenharmony_ci 175e41f4b71Sopenharmony_ci In the unified service mode, the first device node in the **device_info.hcs** file must be the clock manager. The parameters must be set as follows: 176e41f4b71Sopenharmony_ci 177e41f4b71Sopenharmony_ci | Parameter| Value| 178e41f4b71Sopenharmony_ci | -------- | -------- | 179e41f4b71Sopenharmony_ci | policy | Service publishing policy. For the clock controller, it is **2**, which means to publish services for both kernel- and user-mode processes. | 180e41f4b71Sopenharmony_ci | priority | Loading priority of the cloud driver. The value range is 0 to 200. A larger value indicates a lower priority.<br/>It is set to **59** for the clock controller. | 181e41f4b71Sopenharmony_ci | permission | Permission for the device node created. It is **0664** for the clock controller. | 182e41f4b71Sopenharmony_ci | moduleName | **HDF_PLATFORM_CLOCK_MANAGER**. | 183e41f4b71Sopenharmony_ci | serviceName | **HDF_PLATFORM_CLOCK_MANAGER**. | 184e41f4b71Sopenharmony_ci | deviceMatchAttr | Reserved.| 185e41f4b71Sopenharmony_ci 186e41f4b71Sopenharmony_ci Configure clock controller information from the second node. This node specifies a type of clock controllers rather than a clock controller. In this example, there is only one clock device. If there are multiple clock devices, add the **deviceNode** information to the **device_info.hcs** file and add the corresponding device attributes to the **clock_config** file for each device. 187e41f4b71Sopenharmony_ci 188e41f4b71Sopenharmony_ci - **device_info.hcs** example 189e41f4b71Sopenharmony_ci 190e41f4b71Sopenharmony_ci ``` 191e41f4b71Sopenharmony_ci root { 192e41f4b71Sopenharmony_ci device_info { 193e41f4b71Sopenharmony_ci platform :: host { 194e41f4b71Sopenharmony_ci device_clock :: device { 195e41f4b71Sopenharmony_ci device0 :: deviceNode { 196e41f4b71Sopenharmony_ci policy = 2; 197e41f4b71Sopenharmony_ci priority = 59; 198e41f4b71Sopenharmony_ci permission = 0644; 199e41f4b71Sopenharmony_ci moduleName = "HDF_PLATFORM_CLOCK_MANAGER"; 200e41f4b71Sopenharmony_ci serviceName = "HDF_PLATFORM_CLOCK_MANAGER"; 201e41f4b71Sopenharmony_ci } 202e41f4b71Sopenharmony_ci device1 :: deviceNode { 203e41f4b71Sopenharmony_ci policy = 0; // The value 0 indicates that no service is published. 204e41f4b71Sopenharmony_ci priority = 65; // Driver startup priority. 205e41f4b71Sopenharmony_ci permission = 0644; // Permission for the device node created. 206e41f4b71Sopenharmony_ci moduleName = "linux_clock_adapter"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry. 207e41f4b71Sopenharmony_ci deviceMatchAttr = "linux_clock_adapter_0"; // (Mandatory) Private data of the controller. The value must be the same as that of the controller 208e41f4b71Sopenharmony_ci } 209e41f4b71Sopenharmony_ci } 210e41f4b71Sopenharmony_ci } 211e41f4b71Sopenharmony_ci } 212e41f4b71Sopenharmony_ci } 213e41f4b71Sopenharmony_ci ``` 214e41f4b71Sopenharmony_ci 215e41f4b71Sopenharmony_ci - **clock_config.hcs** example 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ci The following uses RK3568 as an example. 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci ``` 220e41f4b71Sopenharmony_ci root { 221e41f4b71Sopenharmony_ci platform { 222e41f4b71Sopenharmony_ci clock_config { 223e41f4b71Sopenharmony_ci match_attr = "linux_clock_adapter_0"; 224e41f4b71Sopenharmony_ci template clock_device { 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci device_clock_0x0000 :: clock_device { 227e41f4b71Sopenharmony_ci deviceName = "/cpus/cpu@0"; 228e41f4b71Sopenharmony_ci deviceIndex = 1; 229e41f4b71Sopenharmony_ci } 230e41f4b71Sopenharmony_ci } 231e41f4b71Sopenharmony_ci } 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci ``` 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci After the **clock_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect. 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ci For example, if the **clock_config.hcs** file is in **//vendor/hihope/rk3568/hdf_config/hdf_config/khdf/hdf.hcs**, add the following statement to **hdf.hcs** of the product: 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci ``` 240e41f4b71Sopenharmony_ci #include "platform/clock_config_linux.hcs" // Relative path of the configuration file 241e41f4b71Sopenharmony_ci ``` 242e41f4b71Sopenharmony_ci 243e41f4b71Sopenharmony_ci This example is based on RK3568 development board that runs the Standard system. The **hdf.hcs** file is in **//vendor/hihope/rk3568/hdf_config/ hdf_config/khdf/**. You can modify the file as required. 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci3. Initialize the **ClockDevice** 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 **ClocMethod** in **ClocDevice** (so that the underlying driver functions can be called). 246e41f4b71Sopenharmony_ci 247e41f4b71Sopenharmony_ci - Define a custom structure. 248e41f4b71Sopenharmony_ci 249e41f4b71Sopenharmony_ci To the driver, the custom structure holds parameters and data. The DeviceResourceIface() function provided by the HDF reads **clock_config.hcs** to initialize the custom structure and passes some important parameters, such as the device number and bus number, to the **ClockDevice** object at the core layer. 250e41f4b71Sopenharmony_ci ```c 251e41f4b71Sopenharmony_ci /* ClockDevice is the core layer controller structure. The **Init()** function assigns values to the members of ClockDevice. */ 252e41f4b71Sopenharmony_ci struct ClockDevice { 253e41f4b71Sopenharmony_ci const struct ClockMethod *ops; 254e41f4b71Sopenharmony_ci OsalSpinlock spin; 255e41f4b71Sopenharmony_ci const char *deviceName; 256e41f4b71Sopenharmony_ci const char *clockName; 257e41f4b71Sopenharmony_ci uint32_t deviceIndex; 258e41f4b71Sopenharmony_ci const struct ClockLockMethod *lockOps; 259e41f4b71Sopenharmony_ci void *clk; 260e41f4b71Sopenharmony_ci void *priv; 261e41f4b71Sopenharmony_ci struct ClockDevice *parent; 262e41f4b71Sopenharmony_ci }; 263e41f4b71Sopenharmony_ci ``` 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci- Instantiate the hook function structure **ClockMethod** of **ClockDevice**. 266e41f4b71Sopenharmony_ci 267e41f4b71Sopenharmony_ci The **ClockLockMethod** is not implemented in this example. To instantiate the structure, refer to the I2C driver development. Other members are initialized in the **Init** function. 268e41f4b71Sopenharmony_ci 269e41f4b71Sopenharmony_ci ```c 270e41f4b71Sopenharmony_ci struct ClockMethod { 271e41f4b71Sopenharmony_ci int32_t (*start)(struct ClockDevice *device); 272e41f4b71Sopenharmony_ci int32_t (*stop)(struct ClockDevice *device); 273e41f4b71Sopenharmony_ci int32_t (*setRate)(struct ClockDevice *device, uint32_t rate); 274e41f4b71Sopenharmony_ci int32_t (*getRate)(struct ClockDevice *device, uint32_t *rate); 275e41f4b71Sopenharmony_ci int32_t (*disable)(struct ClockDevice *device); 276e41f4b71Sopenharmony_ci int32_t (*enable)(struct ClockDevice *device); 277e41f4b71Sopenharmony_ci struct ClockDevice *(*getParent)(struct ClockDevice *device); 278e41f4b71Sopenharmony_ci int32_t (*setParent)(struct ClockDevice *device, struct ClockDevice *parent); 279e41f4b71Sopenharmony_ci }; 280e41f4b71Sopenharmony_ci ``` 281e41f4b71Sopenharmony_ci 282e41f4b71Sopenharmony_ci - Implement the **Init** function. 283e41f4b71Sopenharmony_ci 284e41f4b71Sopenharmony_ci Input parameter: 285e41f4b71Sopenharmony_ci 286e41f4b71Sopenharmony_ci **HdfDeviceObject**, an interface parameter provided by the driver, contains the .hcs information. 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci Return value: 289e41f4b71Sopenharmony_ci 290e41f4b71Sopenharmony_ci **HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h** file. 291e41f4b71Sopenharmony_ci 292e41f4b71Sopenharmony_ci **Table 4** HDF_STATUS 293e41f4b71Sopenharmony_ci 294e41f4b71Sopenharmony_ci | Value | Description | 295e41f4b71Sopenharmony_ci | -------- | -------- | 296e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_OBJECT | Invalid controller object.| 297e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_PARAM | Invalid parameter.| 298e41f4b71Sopenharmony_ci | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.| 299e41f4b71Sopenharmony_ci | HDF_ERR_IO | I/O error.| 300e41f4b71Sopenharmony_ci | HDF_SUCCESS | Transmission successful.| 301e41f4b71Sopenharmony_ci | HDF_FAILURE | Transmission failed.| 302e41f4b71Sopenharmony_ci 303e41f4b71Sopenharmony_ci Function description: 304e41f4b71Sopenharmony_ci 305e41f4b71Sopenharmony_ci Initializes the custom structure object and **ClockDevice**, and calls the **ClockDeviceAdd** function at the core layer. 306e41f4b71Sopenharmony_ci 307e41f4b71Sopenharmony_ci ```c 308e41f4b71Sopenharmony_ci static int32_t LinuxClockInit(struct HdfDeviceObject *device) 309e41f4b71Sopenharmony_ci { 310e41f4b71Sopenharmony_ci int32_t ret = HDF_SUCCESS; 311e41f4b71Sopenharmony_ci struct DeviceResourceNode *childNode = NULL; 312e41f4b71Sopenharmony_ci 313e41f4b71Sopenharmony_ci if (device == NULL || device->property == NULL) { 314e41f4b71Sopenharmony_ci HDF_LOGE("LinuxClockInit: device or property is null"); 315e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 316e41f4b71Sopenharmony_ci } 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ci DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { 319e41f4b71Sopenharmony_ci ret = ClockParseAndDeviceAdd(device, childNode); 320e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 321e41f4b71Sopenharmony_ci HDF_LOGE("LinuxClockInit: clock init fail!"); 322e41f4b71Sopenharmony_ci return ret; 323e41f4b71Sopenharmony_ci } 324e41f4b71Sopenharmony_ci } 325e41f4b71Sopenharmony_ci HDF_LOGE("LinuxClockInit: clock init success!"); 326e41f4b71Sopenharmony_ci 327e41f4b71Sopenharmony_ci return HDF_SUCCESS; 328e41f4b71Sopenharmony_ci } 329e41f4b71Sopenharmony_ci 330e41f4b71Sopenharmony_ci static int32_t ClockParseAndDeviceAdd(struct HdfDeviceObject *device, struct DeviceResourceNode *node) 331e41f4b71Sopenharmony_ci { 332e41f4b71Sopenharmony_ci int32_t ret; 333e41f4b71Sopenharmony_ci struct ClockDevice *clockDevice = NULL; 334e41f4b71Sopenharmony_ci 335e41f4b71Sopenharmony_ci (void)device; 336e41f4b71Sopenharmony_ci clockDevice = (struct ClockDevice *)OsalMemCalloc(sizeof(*clockDevice)); 337e41f4b71Sopenharmony_ci if (clockDevice == NULL) { 338e41f4b71Sopenharmony_ci HDF_LOGE("ClockParseAndDeviceAdd: alloc clockDevice fail!"); 339e41f4b71Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 340e41f4b71Sopenharmony_ci } 341e41f4b71Sopenharmony_ci ret = ClockReadDrs(clockDevice, node); 342e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 343e41f4b71Sopenharmony_ci HDF_LOGE("ClockParseAndDeviceAdd: read drs fail, ret: %d!", ret); 344e41f4b71Sopenharmony_ci OsalMemFree(clockDevice); 345e41f4b71Sopenharmony_ci return ret; 346e41f4b71Sopenharmony_ci } 347e41f4b71Sopenharmony_ci 348e41f4b71Sopenharmony_ci clockDevice->priv = (void *)node; 349e41f4b71Sopenharmony_ci clockDevice->ops = &g_method; 350e41f4b71Sopenharmony_ci 351e41f4b71Sopenharmony_ci ret = ClockDeviceAdd(clockDevice); 352e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 353e41f4b71Sopenharmony_ci HDF_LOGE("ClockParseAndDeviceAdd: add clock device:%u fail!", clockDevice->deviceIndex); 354e41f4b71Sopenharmony_ci OsalMemFree(clockDevice); 355e41f4b71Sopenharmony_ci return ret; 356e41f4b71Sopenharmony_ci } 357e41f4b71Sopenharmony_ci 358e41f4b71Sopenharmony_ci return HDF_SUCCESS; 359e41f4b71Sopenharmony_ci } 360e41f4b71Sopenharmony_ci 361e41f4b71Sopenharmony_ci static int32_t ClockReadDrs(struct ClockDevice *clockDevice, const struct DeviceResourceNode *node) 362e41f4b71Sopenharmony_ci { 363e41f4b71Sopenharmony_ci int32_t ret; 364e41f4b71Sopenharmony_ci struct DeviceResourceIface *drsOps = NULL; 365e41f4b71Sopenharmony_ci 366e41f4b71Sopenharmony_ci drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 367e41f4b71Sopenharmony_ci if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) { 368e41f4b71Sopenharmony_ci HDF_LOGE("ClockReadDrs: invalid drs ops!"); 369e41f4b71Sopenharmony_ci return HDF_ERR_NOT_SUPPORT; 370e41f4b71Sopenharmony_ci } 371e41f4b71Sopenharmony_ci ret = drsOps->GetUint32(node, "deviceIndex", &clockDevice->deviceIndex, 0); 372e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 373e41f4b71Sopenharmony_ci HDF_LOGE("ClockReadDrs: read deviceIndex fail, ret: %d!", ret); 374e41f4b71Sopenharmony_ci return ret; 375e41f4b71Sopenharmony_ci } 376e41f4b71Sopenharmony_ci 377e41f4b71Sopenharmony_ci drsOps->GetString(node, "clockName", &clockDevice->clockName, 0); 378e41f4b71Sopenharmony_ci 379e41f4b71Sopenharmony_ci ret = drsOps->GetString(node, "deviceName", &clockDevice->deviceName, 0); 380e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 381e41f4b71Sopenharmony_ci HDF_LOGE("ClockReadDrs: read deviceName fail, ret: %d!", ret); 382e41f4b71Sopenharmony_ci return ret; 383e41f4b71Sopenharmony_ci } 384e41f4b71Sopenharmony_ci return HDF_SUCCESS; 385e41f4b71Sopenharmony_ci } 386e41f4b71Sopenharmony_ci ``` 387e41f4b71Sopenharmony_ci 388e41f4b71Sopenharmony_ci 389e41f4b71Sopenharmony_ci 390e41f4b71Sopenharmony_ci - Implement the **Release** function. 391e41f4b71Sopenharmony_ci 392e41f4b71Sopenharmony_ci Input parameter: 393e41f4b71Sopenharmony_ci 394e41f4b71Sopenharmony_ci **HdfDeviceObject**, an interface parameter provided by the driver, contains the .hcs information. 395e41f4b71Sopenharmony_ci 396e41f4b71Sopenharmony_ci Return value: 397e41f4b71Sopenharmony_ci 398e41f4b71Sopenharmony_ci No value is returned. 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci Function description: 401e41f4b71Sopenharmony_ci 402e41f4b71Sopenharmony_ci 403e41f4b71Sopenharmony_ci 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. 404e41f4b71Sopenharmony_ci 405e41f4b71Sopenharmony_ci ```c 406e41f4b71Sopenharmony_ci static void LinuxClockRelease(struct HdfDeviceObject *device) 407e41f4b71Sopenharmony_ci { 408e41f4b71Sopenharmony_ci const struct DeviceResourceNode *childNode = NULL; 409e41f4b71Sopenharmony_ci if (device == NULL || device->property == NULL) { 410e41f4b71Sopenharmony_ci HDF_LOGE("LinuxClockRelease: device or property is null!"); 411e41f4b71Sopenharmony_ci return; 412e41f4b71Sopenharmony_ci } 413e41f4b71Sopenharmony_ci DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { 414e41f4b71Sopenharmony_ci ClockRemoveByNode(childNode); 415e41f4b71Sopenharmony_ci } 416e41f4b71Sopenharmony_ci } 417e41f4b71Sopenharmony_ci 418e41f4b71Sopenharmony_ci static void ClockRemoveByNode(const struct DeviceResourceNode *node) 419e41f4b71Sopenharmony_ci { 420e41f4b71Sopenharmony_ci int32_t ret; 421e41f4b71Sopenharmony_ci int32_t deviceIndex; 422e41f4b71Sopenharmony_ci struct ClockDevice *device = NULL; 423e41f4b71Sopenharmony_ci struct DeviceResourceIface *drsOps = NULL; 424e41f4b71Sopenharmony_ci 425e41f4b71Sopenharmony_ci drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 426e41f4b71Sopenharmony_ci if (drsOps == NULL || drsOps->GetUint32 == NULL) { 427e41f4b71Sopenharmony_ci HDF_LOGE("ClockRemoveByNode: invalid drs ops!"); 428e41f4b71Sopenharmony_ci return; 429e41f4b71Sopenharmony_ci } 430e41f4b71Sopenharmony_ci 431e41f4b71Sopenharmony_ci ret = drsOps->GetUint32(node, "deviceIndex", (uint32_t *)&deviceIndex, 0); 432e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 433e41f4b71Sopenharmony_ci HDF_LOGE("ClockRemoveByNode: read deviceIndex fail, ret: %d!", ret); 434e41f4b71Sopenharmony_ci return; 435e41f4b71Sopenharmony_ci } 436e41f4b71Sopenharmony_ci 437e41f4b71Sopenharmony_ci device = ClockDeviceGet(deviceIndex); 438e41f4b71Sopenharmony_ci if (device != NULL && device->priv == node) { 439e41f4b71Sopenharmony_ci ret = ClockStop(device); 440e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 441e41f4b71Sopenharmony_ci HDF_LOGE("ClockRemoveByNode: close fail, ret: %d!", ret); 442e41f4b71Sopenharmony_ci } 443e41f4b71Sopenharmony_ci if (device->parent && device->parent->deviceName == NULL) { 444e41f4b71Sopenharmony_ci ClockDeviceRemove(device->parent); 445e41f4b71Sopenharmony_ci OsalMemFree(device->parent); 446e41f4b71Sopenharmony_ci } 447e41f4b71Sopenharmony_ci ClockDeviceRemove(device); 448e41f4b71Sopenharmony_ci OsalMemFree(device); 449e41f4b71Sopenharmony_ci } 450e41f4b71Sopenharmony_ci } 451e41f4b71Sopenharmony_ci ``` 452e41f4b71Sopenharmony_ci4. (Optional) Debug the driver. 453e41f4b71Sopenharmony_ci Verify the basic driver functionalities. 454