TISCI PM Clock API Documentation¶
Introduction¶
This document describes the TISCI API set for configuring and controlling the clocks within the system.
Clock configuration and control APIs¶
TISCI Message ID | Message Name |
---|---|
0x0100 | TISCI_MSG_SET_CLOCK |
0x0101 | TISCI_MSG_GET_CLOCK |
0x0102 | TISCI_MSG_SET_CLOCK_PARENT |
0x0103 | TISCI_MSG_GET_CLOCK_PARENT |
0x0104 | TISCI_MSG_GET_NUM_CLOCK_PARENTS |
0x010c | TISCI_MSG_SET_FREQ |
0x010d | TISCI_MSG_QUERY_FREQ |
0x010e | TISCI_MSG_GET_FREQ |
Note
Reference Chapter 5: SoC Family Specific Documentation to see clock IDs and device IDs for your SoC.
Note
The SSC controls are not yet available in the system firmware.
Macros Used in this Document¶
TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ 0
The IP does not require this clock, it can be disabled, regardless of the state of the device
TISCI_MSG_VALUE_CLOCK_SW_STATE_AUTO 1
Allow the system controller to automatically manage the state of this clock. If the device is enabled, then the clock is enabled. If the device is set to off or retention, then the clock is internally set as not being required by the device. This is the default state.
TISCI_MSG_VALUE_CLOCK_SW_STATE_REQ 2
Configure the clock to be enabled, regardless of the state of the device.
TISCI_MSG_VALUE_CLOCK_HW_STATE_NOT_READY 0
Indicate hardware state of the clock is that it is not running.
TISCI_MSG_VALUE_CLOCK_HW_STATE_READY 1
Indicate hardware state of the clock is that it is running.
TISCI_MSG_FLAG_CLOCK_ALLOW_SSC BIT(8)
Allow this clock to be modified via spread spectrum clocking. note: The SSC feature is currently not supported in System Firmware.
TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE BIT(9)
Allow this clock’s frequency to be changed while it is running so long as it is within the min/max limits.
TISCI_MSG_FLAG_CLOCK_INPUT_TERM BIT(10)
Enable input termination, this is only applicable to clock inputs on the SoC pseudo-device, BOARD0.
TISCI_MSG_FLAG_CLOCK_SSC_ACTIVE BIT(11)
Indicate that SSC is active for this clock. note: The SSC feature is currently not supported in System Firmware.
Large Clock Index Compatibility¶
Clock indexes identify clocks connected to devices. There are typically a small number of clocks connected to each device. The original API was designed with an 8-bit field to represent clock indexes allowing a maximum clock index of 254, which 255 being reserved to indicate an invalid clock index.
The number of clocks connected to devices on newer SoCs has multiplied rapidly and has exceeded the 254 limit, largely due to very wide input muxes. The API has been extended to support these larger clock indexes while still remaining forward and reverse compatible. This change requires some action by users of the API when indexes larger than 254 are present.
For each clock index within a message a 32-bit field has been appended to the end of the message. If a clock index is less than or equal to 254, the extra field is unused and the clock index is stored in the original 8-bit field. If the clock index is 255 or larger, the value 255 is stored is the original 8-bit field and the actual value is stored in the extra 32-bit field. This applies to both requests and responses from the firmware.
Note that if a host with large clock index support attempts to send a clock index 255 or greater to a firmware without large clock index support, the firmware will interpret the 255 value in the 8-bit clock index field as invalid and NAK the request. Similarly, if a request is made that requires the firmware to respond with a value 255 or greater (such as the number of clock parents) the firmware will return a NAK. If a host without large clock index support makes a request that requires a firmware with large clock index support to respond with a value of 255 or greater it will return an ACK but place 255 in the 8-bit field. This should be interpreted by the host as an invalid clock index.
The host can also request the ABI version. ABI versions prior to 2.6 lack large clock index support.
TISCI_MSG_SET_CLOCK¶
Objective¶
Setup a hardware device’s clock state
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This requests for finer control of hardware device’s clocks. This allows for configuration for hardware blocks that require customization of the specific input clocks. NOTE: each of the clock IDs are relative to the hardware block.
TISCI Message ID¶
TISCI_MSG_SET_CLOCK (0x0100U)
Message Data Structures¶
struct tisci_msg_set_clock_req
Mark a clock as required/not required.
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to modify. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
state | u8 | The desired state of the clock, TISCI_MSG_VALUE_CLOCK_SW_STATE_REQ if the clock is currently required by the IP and TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ if it is not. TISCI_MSG_VALUE_CLOCK_SW_STATE_AUTO enables the clock when the IP is set to enabled and disables it when the IP is set to disabled. This is the default state. |
Indicate that the selected clock is currently required/not required by the IP. Certain flags can be set in the message header for device clocks: TISCI_MSG_FLAG_CLOCK_ALLOW_SSC, TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, TISCI_MSG_FLAG_CLOCK_INPUT_TERM. If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_set_clock_resp
Empty response for TISCI_MSG_SET_CLOCK
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header to provide ACK/NAK flags to the host. |
Although this message is essentially empty and contains only a header a full data structure is created for consistency in implementation.
TISCI_MSG_GET_CLOCK¶
Objective¶
Get the state of a clock to or from a hardware block.
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This requests for additional information about the state of a clock within the system including the state it is programmed to and the actual state of the clock.
TISCI Message ID¶
TISCI_MSG_GET_CLOCK (0x0101U)
Message Data Structures¶
struct tisci_msg_get_clock_req
Get the current state of a clock
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to get. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_get_clock_resp
Clock state response.
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
programmed_state | u8 | The programmed state as set by the set message. |
current_state | u8 | The actual state of the clock. If it is desired that a clock be on, it is usually better to send a set message with a flag indicating that an ack be sent when the message is processed rather than attempting to poll this state. |
TISCI_MSG_SET_CLOCK_PARENT¶
Objective¶
SoC specific customization for setting up a specific clock parent ID for the various clock input options for a hardware block’s clock.
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This is rarely used customization that may be required based on the usecase of the system where the reset input clock option may not suffice for the usecase attempted.
Message ID¶
TISCI_MSG_SET_CLOCK_PARENT (0x0102U)
Message Data Structures¶
struct tisci_msg_set_clock_parent_req
Set the clock parent
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to modify. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
parent | u8 | The new clock parent is selectable by an index via this parameter. |
parent32 | u32 | Stores the actual parent clock index if parent field is set to 255. This field is ignored otherwise. This field can hold the full range of possible parent clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
Many IPs have a mux external to the IP that can select among different clock sources. The clock must be disabled (TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ) for this message to succeed. If a set frequency command is not issued before the clock is enabled again, then the execution of the enable command will attempt to set the new parent to the old parent’s frequency. If this fails, then the enable will fail. Muxes that provide clocks to multiple devices are not currently configurable via this API. If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares. If the parent clock index is 255 or greater, this field should be set to 255 and the full value placed in the parent32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_set_clock_parent_resp
Empty response for TISCI_MSG_SET_CLOCK_PARENT
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header to provide ACK/NAK flags to the host. |
Although this message is essentially empty and contains only a header a full data structure is created for consistency in implementation.
TISCI_MSG_GET_CLOCK_PARENT¶
Objective¶
Query the clock parent currently configured for a specific clock source of a hardware block
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This is typically used to confirm the current clock parent to ensure that the requisite usecase for the hardware block can be satisfied. Note that if the programmed value in the underlying hardware is invalid, a NAK is returned for this message. Once a valid parent is programmed via a successful TISCI_MSG_SET_CLOCK_PARENT call, calls to TISCI_MSG_GET_CLOCK_PARENT will succeed.
Message ID¶
TISCI_MSG_GET_CLOCK_PARENT (0x0103U)
Message Data Structures¶
struct tisci_msg_get_clock_parent_req
Return the current clock parent
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to get. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
If the hardware value indicating the current clock parent contains a reserved value, a NAK is returned for this message. Once a valid parent is programmed via a successful SET_CLOCK_PARENT call, calls to GET_CLOCK_PARENT will succeed. If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_get_clock_parent_resp
Clock parent response
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
parent | u8 | The current clock parent. |
parent32 | u32 | Parent Clock index if 255 or greater and parent field is set to 255. This field will contain 0xFFFFFFFF otherwise. |
If the parent clock index is 255 or greater, this field will be set to 255 and the full value placed in the parent32 field. This is for backwards compatibility with older firmwares.
TISCI_MSG_GET_NUM_CLOCK_PARENTS¶
Objective¶
Query for the number of parent clock paths available for a specific hardware block’s clock.
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This is typically used to get the max number of clock parent options available for a specific hardware block’s clock.
Message ID¶
TISCI_MSG_GET_NUM_CLOCK_PARENTS (0x0104U)
Message Data Structures¶
struct tisci_msg_get_num_clock_parents_req
Return the number of possible parents for a clock
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to query. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_get_num_clock_parents_resp
Num clock parents response
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
num_parents | u8 | The number of clock parents. |
num_parents32 | u32 | Number of clock parents if 255 or greater and num_parents field is set to 255. This field will contain 0xFFFFFFFF otherwise. |
If the number of clock parents is 255 or greater, this field will be set to 255 and the full value placed in the num_parents32 field. This is for backwards compatibility with older firmwares.
TISCI_MSG_SET_FREQ¶
Objective¶
Setup a clock frequency for a hardware block’s clock.
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This is typically desired when the default frequency of the hardware block’s clock is not appropriate for the usecase desired.
NOTE: Normally clock frequency management is automatically done by TISCI entity. In case of specific requests, TISCI evaluates capability to achieve requested range and responds with success/failure message.
This sets the desired frequency for a clock within an allowable range. This message will fail on an enabled clock unless MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, if other clocks have their frequency modified due to this message, they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled.
Calling set frequency on a clock input to the SoC pseudo-device will inform the PMMC of that clock’s frequency. Setting a frequency of zero will indicate the clock is disabled.
Calling set frequency on clock outputs from the SoC pseudo-device will function similarly to setting the clock frequency on a device.
Message ID¶
TISCI_MSG_SET_FREQ (0x010cU)
Message Data Structures¶
struct tisci_msg_set_freq_req
Set the desired frequency for a clock.
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
min_freq_hz | u64 | The minimum allowable frequency in Hz. This is the minimum allowable programmed frequency and does not account for clock tolerances and jitter. |
target_freq_hz | u64 | The target clock frequency. The clock will be programmed at a rate as close to this target frequency as possible. |
max_freq_hz | u64 | The maximum allowable frequency in Hz. This is the maximum allowable programmed frequency and does not account for clock tolerances and jitter. The firmware will actually accept any frequency up to but not including max + 1. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to modify. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
This set the desired frequency for a clock within an allowable range. This message will fail on an enabled clock unless TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, if other clocks have their frequency modified due to this message, they also must have the TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled. Calling set frequency on a clock input to the SoC psuedo-device will inform the PMMC of that clock’s frequency. Setting a frequency of zero will indicate the clock is disabled. Calling set frequency on clock outputs from the SoC pseudo-device will function similarly to setting the clock frequency on a device. If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_set_freq_resp
Empty response for TISCI_MSG_SET_FREQ
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header to provide ACK/NAK flags to the host. |
Although this message is essentially empty and contains only a header a full data structure is created for consistency in implementation.
TISCI_MSG_QUERY_FREQ¶
Objective¶
Query to find closest match possible for a target frequency.
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This message does no real operation, instead, it requests the system control entity to respond with the best frequency that can match a frequency range provided.
NOTE: This is a snapshot view. In a multi processing system, it is very well possible that another processing entity might change the configuration after one entity has queried for best match capability. Only a SET_CLOCK_FREQ will guarantee the frequency is configured.
Message ID¶
TISCI_MSG_QUERY_FREQ (0x010dU)
Message Data Structures¶
struct tisci_msg_query_freq_req
Determine the result of a hypothetical set frequency operation.
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
min_freq_hz | u64 | The minimum allowable frequency in Hz. This is the minimum allowable programmed frequency and does not account for clock tolerances and jitter. |
target_freq_hz | u64 | The target clock frequency. A frequency will be found as close to the target frequency as possible. |
max_freq_hz | u64 | The maximum allowable frequency in Hz. This is the maximum allowable programmed frequency and does not account for clock tolerances and jitter. The firmware will actually accept any frequency up to but not including max + 1. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to query. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
This allows the OS to determine what rate would be set given a set of parameters. A nack will be received if a frequency is not available in the given range. If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_query_freq_resp
Result of a query operation
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
freq_hz | u64 | The frequency in Hz that the hardware would set for the given parameters. |
TISCI_MSG_GET_FREQ¶
Objective¶
Get the clock frequency of a specific clock which belongs to a hardware block.
Usage¶
Message Type | Normal |
Secure Queue Only? | No |
This is most used functionality and is meant for usage when the driver controlling the hardware block requires to know the input clock frequency for configuring internal dividers / multipliers as required.
Message ID¶
TISCI_MSG_GET_FREQ (0x010eU)
Message Data Structures¶
struct tisci_msg_get_freq_req
Get the current frequency of a device’s clock
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
device | u32 | The device ID that the clock is connected to. |
clk | u8 | Each device has its own set of clock inputs. This indexes which clock input to query. |
clk32 | u32 | Stores the actual clock index if clk field is set to 255. This field is ignored otherwise. This field can hold the full range of possible clock indexes, but for compatibility with older firmwares should only be used when the index is 255 or greater. |
This message will only succeed if the clock is currently enabled, otherwise it returns nack. If the clock index is 255 or greater, this field should be set to 255 and the full value placed in the clk32 field. This is kept for backwards compatibility with older firmwares.
struct tisci_msg_get_freq_resp
Result of get frequency request
Parameter | Type | Description |
---|---|---|
hdr | struct tisci_header | TISCI header |
freq_hz | u64 | The current frequency in Hz. |
Power Management Clock Frequency Configuration Example¶
Power Management Clock Frequency Configuration without Multiplexers¶
An example sequence for setting the clock frequency for a given module is as given below. The input to this code snippet is as below:
device_id
: Refer to the AM6 Devices Descriptionsclk_id
: Refer to the AM6 Clock Identifiers. Choose the Ids which are marked “Input Clock”.min_hz
: Minimum Frequency which should be set for this clock.freq_hz
: Target Frequency which should be set for this clock.max_hz
: Maximum Frequency which should be set for this clock.
The simplified sequence of operations is as below:
/* Allocate space for the messages */
u32 tisci_msg_data[13];
/* Pointer to the header */
struct tisci_header *hdr = (struct tisci_header *) tisci_msg_data;
struct tisci_msg_get_freq_req *get_freq_req;
struct tisci_msg_get_freq_resp *get_freq_resp;
struct tisci_msg_set_freq_req *set_freq_req;
struct tisci_msg_query_freq_resp *query_freq_resp;
int ret = 0;
/* Initialize the message data with 0s */
memset(tisci_msg_data, 0, sizeof(tisci_msg_data));
/* Get the current frequency of the device and corresponding clock */
hdr->host = 0x01;
hdr->flags = TISCI_MSG_FLAG_AOP;
/* Message for Getting the frequency for the clock of the device of interest */
hdr->type = TISCI_MSG_GET_FREQ;
get_freq_req = (struct tisci_msg_get_freq_req *) (hdr + 1);
/* Give the device ID from the devices list in the SoC Documentation */
get_freq_req->device = device_id;
/* The clock IDs can be less than 255 or greater than 255. If the clock
* ID is greater than 255, then set 2 fields in the message.
*/
if (clk_id >= 255) {
get_freq_req->clk = 255;
get_freq_req->clk32 = clk_id;
} else {
get_freq_req->clk = clk_id;
}
/* Send a message to the System firmware on a specific Secure Proxy Queue.
* The same structure for the message data. The same can be used as the
* message data is copied to the secure proxy registers.
*/
ret = send_receive_with_timeout(TISCI_MSG_QUEUE_NONSEC_HIGH_TX,
(void *)tisci_msg_data,
sizeof(tisci_msg_data),
(void *)tisci_msg_data, sizeof(tisci_msg_data));
if (ret < 0)
return ret;
get_freq_resp = (struct tisci_msg_get_freq_resp *) (hdr + 1);
printf("Current: ");
print_freq(get_freq_resp->freq_hz);
printf("\n");
printf("Sending query: ");
print_freq(min_hz);
printf(", ");
print_freq(freq_hz);
printf(", ");
print_freq(max_hz);
printf("\n");
/* Initialize the message data with 0s */
memset(tisci_msg_data, 0, sizeof(tisci_msg_data));
hdr->host = 0x01;
hdr->flags = TISCI_MSG_FLAG_AOP;
/* Message for querying if the frequency is possible for the clock of the device of interest */
hdr->type = TISCI_MSG_QUERY_FREQ;
set_freq_req = (struct tisci_msg_set_freq_req *) (hdr + 1);
/* Give the device ID from the devices list in the SoC Documentation */
set_freq_req->device = device_id;
/* The clock IDs can be less than 255 or greater than 255. If the clock
* ID is greater than 255, then set 2 fields in the message.
*/
if (clk_id >= 255) {
set_freq_req->clk = 255;
set_freq_req->clk32 = clk_id;
} else {
set_freq_req->clk = clk_id;
}
set_freq_req->min_freq_hz = min_hz;
set_freq_req->target_freq_hz = freq_hz;
set_freq_req->max_freq_hz = max_hz;
/* Send a message to the System firmware on a specific Secure Proxy Queue.
* The same structure for the message data. The same can be used as the
* message data is copied to the secure proxy registers.
*/
ret = send_receive_with_timeout(TISCI_MSG_QUEUE_NONSEC_HIGH_TX,
(void *)tisci_msg_data,
sizeof(tisci_msg_data),
(void *)tisci_msg_data, sizeof(tisci_msg_data));
if (ret == 0 && !(hdr->flags & TISCI_MSG_FLAG_ACK))
ret = -ENODEV;
if (ret == 0) {
query_freq_resp = (struct tisci_msg_query_freq_resp *) (hdr + 1);
printf("Query response: ");
print_freq(query_freq_resp->freq_hz);
printf("\n");
if (query_freq_resp->freq_hz < min_hz || query_freq_resp->freq_hz > max_hz)
ret = -EINVAL;
}
if (ret < 0)
return ret;
freq_hz = query_freq_resp->freq_hz;
printf("Sending set: ");
print_freq(freq_hz);
printf(", ");
print_freq(freq_hz);
printf(", ");
print_freq(freq_hz);
printf("\n");
/* Initialize the message data with 0s */
memset(tisci_msg_data, 0, sizeof(tisci_msg_data));
hdr->host = 0x01;
hdr->flags = TISCI_MSG_FLAG_AOP;
/* Message for setting the frequency for the clock of the device of interest. Actually changes the frequency */
hdr->type = TISCI_MSG_SET_FREQ;
set_freq_req = (struct tisci_msg_set_freq_req *) (hdr + 1);
/* Give the device ID from the devices list in the SoC Documentation */
set_freq_req->device = device_id;
/* The clock IDs can be less than 255 or greater than 255. If the clock
* ID is greater than 255, then set 2 fields in the message.
*/
if (clk_id >= 255) {
set_freq_req->clk = 255;
set_freq_req->clk32 = clk_id;
} else {
set_freq_req->clk = clk_id;
}
set_freq_req->min_freq_hz = freq_hz;
set_freq_req->target_freq_hz = freq_hz;
set_freq_req->max_freq_hz = freq_hz;
/* Send a message to the System firmware on a specific Secure Proxy Queue.
* The same structure for the message data. The same can be used as the
* message data is copied to the secure proxy registers.
*/
ret = send_receive_with_timeout(TISCI_MSG_QUEUE_NONSEC_HIGH_TX,
(void *)tisci_msg_data,
sizeof(tisci_msg_data),
(void *)tisci_msg_data, sizeof(tisci_msg_data));
if (ret == 0 && !(hdr->flags & TISCI_MSG_FLAG_ACK))
ret = -ENODEV;
if (ret < 0)
return ret;
/* Initialize the message data with 0s */
memset(tisci_msg_data, 0, sizeof(tisci_msg_data));
hdr->host = 0x01;
hdr->flags = TISCI_MSG_FLAG_AOP;
/* Message for Getting the frequency for the clock of the device of interest */
hdr->type = TISCI_MSG_GET_FREQ;
get_freq_req = (struct tisci_msg_get_freq_req *) (hdr + 1);
/* Give the device ID from the devices list in the SoC Documentation */
get_freq_req->device = device_id;
/* The clock IDs can be less than 255 or greater than 255. If the clock
* ID is greater than 255, then set 2 fields in the message.
*/
if (clk_id >= 255) {
get_freq_req->clk = 255;
get_freq_req->clk32 = clk_id;
} else {
get_freq_req->clk = clk_id;
}
/* Send a message to the System firmware on a specific Secure Proxy Queue.
* The same structure for the message data. The same can be used as the
* message data is copied to the secure proxy registers.
*/
ret = send_receive_with_timeout(TISCI_MSG_QUEUE_NONSEC_HIGH_TX,
(void *)tisci_msg_data,
sizeof(tisci_msg_data),
(void *)tisci_msg_data, sizeof(tisci_msg_data));
if (ret == 0) {
get_freq_resp = (struct tisci_msg_get_freq_resp *) (hdr + 1);
printf("New: ");
print_freq(get_freq_resp->freq_hz);
printf("\n");
if (freq_hz != get_freq_resp->freq_hz)
ret = -EINVAL;
}
if (ret < 0)
return ret;
Power Management Clock Frequency Configuration Example with Mux programming¶
An example pseudo sequence for setting the clock frequency while searching for the right multiplexer parent is as below:
device_id
: Refer to the AM6 Devices Descriptionsclk_id
: Refer to the AM6 Clock Identifiers. Choose the Ids which are marked “Input Clock”.min_hz
: Minimum Frequency which should be set for this clock.freq_hz
: Target Frequency which should be set for this clock.max_hz
: Maximum Frequency which should be set for this clock.
The flow chart for the same is as below:
/* Check if the clock is enabled or not */
status = TISCI_MSG_GET_CLOCK(device_id,
clk_id,
&clockStatus);
if (status == PASS)
{
/* Get the number of parents for the clock */
status = TISCI_MSG_GET_NUM_CLOCK_PARENTS(device_id,
clk_id,
&numParents);
if ((status == PASS) && (numParents > 1U))
{
status = TISCI_MSG_GET_CLOCK_PARENT(device_id, clk_id, &origParent);
}
}
if (status == PASS)
{
/* Disabling the clock */
status = TISCI_MSG_SET_CLOCK(device_id,
clk_id,
TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ);
}
if (status == PASS)
{
foundParent = 0U;
/* Try to loop and change parents of the clock */
for(i=0U;i<numParents;i++)
{
if (numParents > 1U)
{
/* Setting the new parent */
status = TISCI_MSG_SET_CLOCK_PARENT(
device_id,
clk_id,
clk_id+i+1U);
/* Check if the clock can be set to desirable freq. */
if (status == PASS)
{
moduleClockParentChanged = 1U;
}
}
if (status == PASS)
{
status = TISCI_MSG_QUERY_FREQ(device_id,
clk_id,
freq_hz,
&respfreq_hz);
}
if ((status == PASS) && (respfreq_hz == freq_hz))
{
foundParent = 1U;
break;
}
}
}
if ((status == PASS) && (numParents == 0U))
{
status = TISCI_MSG_QUERY_FREQ(device_id,
clk_id,
freq_hz,
&respfreq_hz);
if ((status == PASS) && (respfreq_hz == freq_hz))
{
foundParent = 1U;
}
}
if (foundParent == 1U)
{
/* Set the clock at the desirable frequency*/
status = TISCI_MSG_SET_FREQ(
device_id,
clk_id,
freq_hz,
TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE);
}
else
{
status = CSL_EFAIL;
}
if ((status == PASS) &&
(clockStatus == (uint32_t) TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ))
{
/* Restore the clock again to original state */
status = TISCI_MSG_SET_CLOCK(
device_id,
clk_id,
clockStatus);
}
finalStatus = status;
if ((status != PASS) && (moduleClockParentChanged == 1U))
{
/* Setting the original parent if failure */
(void) TISCI_MSG_SET_CLOCK_PARENT(
device_id,
clk_id,
origParent);
}