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![](figures/unified-service-mode.png "CLOCK Unified Service Mode")
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