Driver for the Clock peripheral
The Clock driver manages and configures the various clock sources and their distribution across the system, including:
- Enabling/disabling clock gates for power management
- Configuring clock sources and frequencies (PLL, oscillator, etc.)
- Managing clock trees and dividers
- Note
- The following are SoC-specific enums, defined in the header file of the target platform:
- clk_ids_en: Clock IDs
- clk_pll_en: Clock PLLs
- clk_pll_config_en: Clock PLL configs
You can find them in: soc/<soc_name>/common/include/<soc_name>_clk.h where <soc_name> represents the target SoC (e.g., sr110).
Example: soc/SR110/common/include/sr110_clk.h
Configuration Considerations
Function
clk_init_tree
Initializes the clock tree by setting up both PLLs (Phase Locked Loops) with the specified configuration. Ensures that the voltage core settings are adjusted, both PLLs are initialized with the specified config, and the default clock tree is populated and synchronized. Sets up necessary clocks for system components.
{
LOG_INFO(LOG_MOD_CLOCK, "Clock tree initialized successfully with Config %d for both PLLs.\n", config);
}
{
LOG_ERROR(LOG_MOD_CLOCK, "Invalid PLL Config (%d).\n", config);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Clock tree initialization failed. Error: %d\n", ret);
}
clk_enable
Enables the specified clock by allowing the clock signal to propagate to the associated peripheral or subsystem. Ensures that the necessary clock gating control is cleared or configured to provide the required clock signal
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d enabled. \n", clk_id);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to enable clock %d. Error: %d \n", clk_id, ret);
}
clk_disable
Disables the specified clock by gating off its source. This function is used to reduce power consumption by stopping the clock signal to unused peripherals or subsystems. If any downstream clocks are enabled, this function will not disable the clock. Disable downstream clocks first or use clk_force_disable().
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d disabled successfully. \n", clk_id);
}
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d cannot be disabled its a system clock. \n", clk_id);
}
{
LOG_INFO(LOG_MOD_CLOCK, "No such Clock, Invalid Parameter given");
}
{
LOG_INFO(LOG_MOD_CLOCK, "Child clocks are still enabled so clock %d cannot be disabled");
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to disable clock %d. Error: %d \n", clk_id, ret);
}
clk_force_disable
Forcibly disables the specified clock regardless of downstream dependencies.
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d cannot be force-disabled. It is a system or reference clock.\n", clk_id);
}
{
LOG_INFO(LOG_MOD_CLOCK, "Force-disable failed. Invalid clock ID: %d\n", clk_id);
}
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d force-disabled successfully.\n", clk_id);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to force-disable clock %d. Error: %d\n", clk_id, ret);
}
clk_is_enabled
Checks whether the specified clock is currently enabled or disabled. The result is returned through the output status pointer.
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d is %s \n", clk_id,
(status == CLK_RC_CLK_ENABLE ? "ENABLED" : "DISABLED"));
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to get clock %d status. Error: %d \n", clk_id, ret);
}
clk_get_rate
Retrieves the current operating frequency of the specified clock. The rate is returned in Hz through the output pointer.
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d current rate: %u Hz \n", clk_id, out_rate);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to get clock %d rate. Error: %d \n", clk_id, ret);
}
clk_set_rate
Sets the operating frequency of the specified clock. The closest supported frequency not exceeding the requested rate will be set based on divider configuration computed internally.
uint32_t requested_rate = 100000000;
uint32_t achieved_rate = 0;
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d current rate: %u Hz\n", clk_id, achieved_rate);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to set clock %d rate. Error: %d\n", clk_id, ret);
}
clk_get_divider
Retrieves the current divider value applied to the specified clock. The divider is returned through the output pointer.
{
LOG_INFO(LOG_MOD_CLOCK, "Clock %d divider: %d \n", clk_id, out_divider);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to get divider for clock %d. Error: %d \n", clk_id, ret);
}
clk_set_pll_config
Applies the specified configuration to the given PLL. Used to set frequency, mode, and other PLL-specific configurations.
{
LOG_INFO(LOG_MOD_CLOCK, "PLL %d config set to HIGH \n", pll);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to set PLL %d config. Error: %d \n", pll, ret);
}
clk_get_pll_config
Retrieves the current configuration of the specified PLL. The configuration is returned via the output pointer.
{
LOG_INFO(LOG_MOD_CLOCK, "PLL %d current config: %d \n", pll, pll_config_out);
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "Failed to get PLL %d config. Error: %d \n", pll, ret);
}
clk_set_mux
Sets the mux output configuration for the specified clock. Configures the clock source selection (mux) for a given clock ID. It applies to clocks that support mux switching, such as PLL muxes or CGL clock muxes.
{
LOG_INFO(LOG_MOD_CLOCK, "Successfully set IPI_CLK mux to CLK_PLL1.\n");
}
{
LOG_ERROR(LOG_MOD_CLOCK, "Invalid parameter passed to clk_set_mux for IPI_CLK.\n");
}
{
LOG_ERROR(LOG_MOD_CLOCK, "IPI_CLK does not support mux configuration.\n");
}
else
{
LOG_ERROR(LOG_MOD_CLOCK, "clk_set_mux failed with error code: %d\n", ret);
}